aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ntfs/ChangeLog11
-rw-r--r--fs/ntfs/lcnalloc.c41
-rw-r--r--fs/ntfs/lcnalloc.h40
-rw-r--r--fs/ntfs/mft.c13
4 files changed, 86 insertions, 19 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 0a361ddb3b45..6e4f44eed6fa 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -24,10 +24,13 @@ ToDo/Notes:
24 24
252.1.25-WIP 252.1.25-WIP
26 26
27 - Change ntfs_map_runlist_nolock() and ntfs_attr_find_vcn_nolock() to 27 - Change ntfs_map_runlist_nolock(), ntfs_attr_find_vcn_nolock() and
28 also take an optional attribute search context as argument. This 28 {__,}ntfs_cluster_free() to also take an optional attribute search
29 allows calling these functions with the mft record mapped. Update 29 context as argument. This allows calling these functions with the
30 all callers. 30 mft record mapped. Update all callers.
31 - Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock()
32 error handling by passing in the active search context when calling
33 ntfs_cluster_free().
31 34
322.1.24 - Lots of bug fixes and support more clean journal states. 352.1.24 - Lots of bug fixes and support more clean journal states.
33 36
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
index 8e60c47fafac..75313f4307e3 100644
--- a/fs/ntfs/lcnalloc.c
+++ b/fs/ntfs/lcnalloc.c
@@ -782,6 +782,7 @@ out:
782 * @ni: ntfs inode whose runlist describes the clusters to free 782 * @ni: ntfs inode whose runlist describes the clusters to free
783 * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters 783 * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
784 * @count: number of clusters to free or -1 for all clusters 784 * @count: number of clusters to free or -1 for all clusters
785 * @ctx: active attribute search context if present or NULL if not
785 * @is_rollback: true if this is a rollback operation 786 * @is_rollback: true if this is a rollback operation
786 * 787 *
787 * Free @count clusters starting at the cluster @start_vcn in the runlist 788 * Free @count clusters starting at the cluster @start_vcn in the runlist
@@ -791,15 +792,39 @@ out:
791 * deallocated. Thus, to completely free all clusters in a runlist, use 792 * deallocated. Thus, to completely free all clusters in a runlist, use
792 * @start_vcn = 0 and @count = -1. 793 * @start_vcn = 0 and @count = -1.
793 * 794 *
795 * If @ctx is specified, it is an active search context of @ni and its base mft
796 * record. This is needed when __ntfs_cluster_free() encounters unmapped
797 * runlist fragments and allows their mapping. If you do not have the mft
798 * record mapped, you can specify @ctx as NULL and __ntfs_cluster_free() will
799 * perform the necessary mapping and unmapping.
800 *
801 * Note, __ntfs_cluster_free() saves the state of @ctx on entry and restores it
802 * before returning. Thus, @ctx will be left pointing to the same attribute on
803 * return as on entry. However, the actual pointers in @ctx may point to
804 * different memory locations on return, so you must remember to reset any
805 * cached pointers from the @ctx, i.e. after the call to __ntfs_cluster_free(),
806 * you will probably want to do:
807 * m = ctx->mrec;
808 * a = ctx->attr;
809 * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
810 * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
811 *
794 * @is_rollback should always be FALSE, it is for internal use to rollback 812 * @is_rollback should always be FALSE, it is for internal use to rollback
795 * errors. You probably want to use ntfs_cluster_free() instead. 813 * errors. You probably want to use ntfs_cluster_free() instead.
796 * 814 *
797 * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller 815 * Note, __ntfs_cluster_free() does not modify the runlist, so you have to
798 * has to deal with it later. 816 * remove from the runlist or mark sparse the freed runs later.
799 * 817 *
800 * Return the number of deallocated clusters (not counting sparse ones) on 818 * Return the number of deallocated clusters (not counting sparse ones) on
801 * success and -errno on error. 819 * success and -errno on error.
802 * 820 *
821 * WARNING: If @ctx is supplied, regardless of whether success or failure is
822 * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
823 * is no longer valid, i.e. you need to either call
824 * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
825 * In that case PTR_ERR(@ctx->mrec) will give you the error code for
826 * why the mapping of the old inode failed.
827 *
803 * Locking: - The runlist described by @ni must be locked for writing on entry 828 * Locking: - The runlist described by @ni must be locked for writing on entry
804 * and is locked on return. Note the runlist may be modified when 829 * and is locked on return. Note the runlist may be modified when
805 * needed runlist fragments need to be mapped. 830 * needed runlist fragments need to be mapped.
@@ -807,9 +832,13 @@ out:
807 * on return. 832 * on return.
808 * - This function takes the volume lcn bitmap lock for writing and 833 * - This function takes the volume lcn bitmap lock for writing and
809 * modifies the bitmap contents. 834 * modifies the bitmap contents.
835 * - If @ctx is NULL, the base mft record of @ni must not be mapped on
836 * entry and it will be left unmapped on return.
837 * - If @ctx is not NULL, the base mft record must be mapped on entry
838 * and it will be left mapped on return.
810 */ 839 */
811s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count, 840s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
812 const BOOL is_rollback) 841 ntfs_attr_search_ctx *ctx, const BOOL is_rollback)
813{ 842{
814 s64 delta, to_free, total_freed, real_freed; 843 s64 delta, to_free, total_freed, real_freed;
815 ntfs_volume *vol; 844 ntfs_volume *vol;
@@ -839,7 +868,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
839 868
840 total_freed = real_freed = 0; 869 total_freed = real_freed = 0;
841 870
842 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, NULL); 871 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, ctx);
843 if (IS_ERR(rl)) { 872 if (IS_ERR(rl)) {
844 if (!is_rollback) 873 if (!is_rollback)
845 ntfs_error(vol->sb, "Failed to find first runlist " 874 ntfs_error(vol->sb, "Failed to find first runlist "
@@ -893,7 +922,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
893 922
894 /* Attempt to map runlist. */ 923 /* Attempt to map runlist. */
895 vcn = rl->vcn; 924 vcn = rl->vcn;
896 rl = ntfs_attr_find_vcn_nolock(ni, vcn, NULL); 925 rl = ntfs_attr_find_vcn_nolock(ni, vcn, ctx);
897 if (IS_ERR(rl)) { 926 if (IS_ERR(rl)) {
898 err = PTR_ERR(rl); 927 err = PTR_ERR(rl);
899 if (!is_rollback) 928 if (!is_rollback)
@@ -961,7 +990,7 @@ err_out:
961 * If rollback fails, set the volume errors flag, emit an error 990 * If rollback fails, set the volume errors flag, emit an error
962 * message, and return the error code. 991 * message, and return the error code.
963 */ 992 */
964 delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE); 993 delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, TRUE);
965 if (delta < 0) { 994 if (delta < 0) {
966 ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " 995 ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
967 "inconsistent metadata! Unmount and run " 996 "inconsistent metadata! Unmount and run "
diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h
index a6a8827882e7..aa0518509cd3 100644
--- a/fs/ntfs/lcnalloc.h
+++ b/fs/ntfs/lcnalloc.h
@@ -27,6 +27,7 @@
27 27
28#include <linux/fs.h> 28#include <linux/fs.h>
29 29
30#include "attrib.h"
30#include "types.h" 31#include "types.h"
31#include "inode.h" 32#include "inode.h"
32#include "runlist.h" 33#include "runlist.h"
@@ -44,13 +45,14 @@ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
44 const NTFS_CLUSTER_ALLOCATION_ZONES zone); 45 const NTFS_CLUSTER_ALLOCATION_ZONES zone);
45 46
46extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, 47extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
47 s64 count, const BOOL is_rollback); 48 s64 count, ntfs_attr_search_ctx *ctx, const BOOL is_rollback);
48 49
49/** 50/**
50 * ntfs_cluster_free - free clusters on an ntfs volume 51 * ntfs_cluster_free - free clusters on an ntfs volume
51 * @ni: ntfs inode whose runlist describes the clusters to free 52 * @ni: ntfs inode whose runlist describes the clusters to free
52 * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters 53 * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
53 * @count: number of clusters to free or -1 for all clusters 54 * @count: number of clusters to free or -1 for all clusters
55 * @ctx: active attribute search context if present or NULL if not
54 * 56 *
55 * Free @count clusters starting at the cluster @start_vcn in the runlist 57 * Free @count clusters starting at the cluster @start_vcn in the runlist
56 * described by the ntfs inode @ni. 58 * described by the ntfs inode @ni.
@@ -59,12 +61,36 @@ extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
59 * deallocated. Thus, to completely free all clusters in a runlist, use 61 * deallocated. Thus, to completely free all clusters in a runlist, use
60 * @start_vcn = 0 and @count = -1. 62 * @start_vcn = 0 and @count = -1.
61 * 63 *
62 * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller 64 * If @ctx is specified, it is an active search context of @ni and its base mft
63 * has to deal with it later. 65 * record. This is needed when ntfs_cluster_free() encounters unmapped runlist
66 * fragments and allows their mapping. If you do not have the mft record
67 * mapped, you can specify @ctx as NULL and ntfs_cluster_free() will perform
68 * the necessary mapping and unmapping.
69 *
70 * Note, ntfs_cluster_free() saves the state of @ctx on entry and restores it
71 * before returning. Thus, @ctx will be left pointing to the same attribute on
72 * return as on entry. However, the actual pointers in @ctx may point to
73 * different memory locations on return, so you must remember to reset any
74 * cached pointers from the @ctx, i.e. after the call to ntfs_cluster_free(),
75 * you will probably want to do:
76 * m = ctx->mrec;
77 * a = ctx->attr;
78 * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
79 * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
80 *
81 * Note, ntfs_cluster_free() does not modify the runlist, so you have to remove
82 * from the runlist or mark sparse the freed runs later.
64 * 83 *
65 * Return the number of deallocated clusters (not counting sparse ones) on 84 * Return the number of deallocated clusters (not counting sparse ones) on
66 * success and -errno on error. 85 * success and -errno on error.
67 * 86 *
87 * WARNING: If @ctx is supplied, regardless of whether success or failure is
88 * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
89 * is no longer valid, i.e. you need to either call
90 * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
91 * In that case PTR_ERR(@ctx->mrec) will give you the error code for
92 * why the mapping of the old inode failed.
93 *
68 * Locking: - The runlist described by @ni must be locked for writing on entry 94 * Locking: - The runlist described by @ni must be locked for writing on entry
69 * and is locked on return. Note the runlist may be modified when 95 * and is locked on return. Note the runlist may be modified when
70 * needed runlist fragments need to be mapped. 96 * needed runlist fragments need to be mapped.
@@ -72,11 +98,15 @@ extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
72 * on return. 98 * on return.
73 * - This function takes the volume lcn bitmap lock for writing and 99 * - This function takes the volume lcn bitmap lock for writing and
74 * modifies the bitmap contents. 100 * modifies the bitmap contents.
101 * - If @ctx is NULL, the base mft record of @ni must not be mapped on
102 * entry and it will be left unmapped on return.
103 * - If @ctx is not NULL, the base mft record must be mapped on entry
104 * and it will be left mapped on return.
75 */ 105 */
76static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, 106static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
77 s64 count) 107 s64 count, ntfs_attr_search_ctx *ctx)
78{ 108{
79 return __ntfs_cluster_free(ni, start_vcn, count, FALSE); 109 return __ntfs_cluster_free(ni, start_vcn, count, ctx, FALSE);
80} 110}
81 111
82extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, 112extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 15df34f62038..5577fc6e190f 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -1952,20 +1952,21 @@ restore_undo_alloc:
1952 NVolSetErrors(vol); 1952 NVolSetErrors(vol);
1953 return ret; 1953 return ret;
1954 } 1954 }
1955 a = ctx->attr; 1955 ctx->attr->data.non_resident.highest_vcn =
1956 a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1); 1956 cpu_to_sle64(old_last_vcn - 1);
1957undo_alloc: 1957undo_alloc:
1958 if (ntfs_cluster_free(mft_ni, old_last_vcn, -1) < 0) { 1958 if (ntfs_cluster_free(mft_ni, old_last_vcn, -1, ctx) < 0) {
1959 ntfs_error(vol->sb, "Failed to free clusters from mft data " 1959 ntfs_error(vol->sb, "Failed to free clusters from mft data "
1960 "attribute.%s", es); 1960 "attribute.%s", es);
1961 NVolSetErrors(vol); 1961 NVolSetErrors(vol);
1962 } 1962 }
1963 a = ctx->attr;
1963 if (ntfs_rl_truncate_nolock(vol, &mft_ni->runlist, old_last_vcn)) { 1964 if (ntfs_rl_truncate_nolock(vol, &mft_ni->runlist, old_last_vcn)) {
1964 ntfs_error(vol->sb, "Failed to truncate mft data attribute " 1965 ntfs_error(vol->sb, "Failed to truncate mft data attribute "
1965 "runlist.%s", es); 1966 "runlist.%s", es);
1966 NVolSetErrors(vol); 1967 NVolSetErrors(vol);
1967 } 1968 }
1968 if (mp_rebuilt) { 1969 if (mp_rebuilt && !IS_ERR(ctx->mrec)) {
1969 if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( 1970 if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
1970 a->data.non_resident.mapping_pairs_offset), 1971 a->data.non_resident.mapping_pairs_offset),
1971 old_alen - le16_to_cpu( 1972 old_alen - le16_to_cpu(
@@ -1982,6 +1983,10 @@ undo_alloc:
1982 } 1983 }
1983 flush_dcache_mft_record_page(ctx->ntfs_ino); 1984 flush_dcache_mft_record_page(ctx->ntfs_ino);
1984 mark_mft_record_dirty(ctx->ntfs_ino); 1985 mark_mft_record_dirty(ctx->ntfs_ino);
1986 } else if (IS_ERR(ctx->mrec)) {
1987 ntfs_error(vol->sb, "Failed to restore attribute search "
1988 "context.%s", es);
1989 NVolSetErrors(vol);
1985 } 1990 }
1986 if (ctx) 1991 if (ctx)
1987 ntfs_attr_put_search_ctx(ctx); 1992 ntfs_attr_put_search_ctx(ctx);