aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ntfs/ChangeLog6
-rw-r--r--fs/ntfs/attrib.c61
2 files changed, 48 insertions, 19 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 67994c9c248f..a6d2b943a148 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -139,6 +139,12 @@ ToDo/Notes:
139 and ntfs_mapping_pairs_build() to allow the runlist encoding to be 139 and ntfs_mapping_pairs_build() to allow the runlist encoding to be
140 partial which is desirable when filling holes in sparse attributes. 140 partial which is desirable when filling holes in sparse attributes.
141 Update all callers. 141 Update all callers.
142 - Change ntfs_map_runlist_nolock() to only decompress the mapping pairs
143 if the requested vcn is inside it. Otherwise we get into problems
144 when we try to map an out of bounds vcn because we then try to map
145 the already mapped runlist fragment which causes
146 ntfs_mapping_pairs_decompress() to fail and return error. Update
147 ntfs_attr_find_vcn_nolock() accordingly.
142 148
1432.1.22 - Many bug and race fixes and error handling improvements. 1492.1.22 - Many bug and race fixes and error handling improvements.
144 150
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index c6b2bb64d651..543d47fa5fc9 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -39,15 +39,19 @@
39 * 39 *
40 * Map the part of a runlist containing the @vcn of the ntfs inode @ni. 40 * Map the part of a runlist containing the @vcn of the ntfs inode @ni.
41 * 41 *
42 * Return 0 on success and -errno on error. 42 * Return 0 on success and -errno on error. There is one special error code
43 * which is not an error as such. This is -ENOENT. It means that @vcn is out
44 * of bounds of the runlist.
43 * 45 *
44 * Locking: - The runlist must be locked for writing. 46 * Locking: - The runlist must be locked for writing.
45 * - This function modifies the runlist. 47 * - This function modifies the runlist.
46 */ 48 */
47int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn) 49int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
48{ 50{
51 VCN end_vcn;
49 ntfs_inode *base_ni; 52 ntfs_inode *base_ni;
50 MFT_RECORD *mrec; 53 MFT_RECORD *m;
54 ATTR_RECORD *a;
51 ntfs_attr_search_ctx *ctx; 55 ntfs_attr_search_ctx *ctx;
52 runlist_element *rl; 56 runlist_element *rl;
53 int err = 0; 57 int err = 0;
@@ -58,26 +62,43 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
58 base_ni = ni; 62 base_ni = ni;
59 else 63 else
60 base_ni = ni->ext.base_ntfs_ino; 64 base_ni = ni->ext.base_ntfs_ino;
61 mrec = map_mft_record(base_ni); 65 m = map_mft_record(base_ni);
62 if (IS_ERR(mrec)) 66 if (IS_ERR(m))
63 return PTR_ERR(mrec); 67 return PTR_ERR(m);
64 ctx = ntfs_attr_get_search_ctx(base_ni, mrec); 68 ctx = ntfs_attr_get_search_ctx(base_ni, m);
65 if (unlikely(!ctx)) { 69 if (unlikely(!ctx)) {
66 err = -ENOMEM; 70 err = -ENOMEM;
67 goto err_out; 71 goto err_out;
68 } 72 }
69 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 73 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
70 CASE_SENSITIVE, vcn, NULL, 0, ctx); 74 CASE_SENSITIVE, vcn, NULL, 0, ctx);
71 if (likely(!err)) { 75 if (unlikely(err)) {
72 rl = ntfs_mapping_pairs_decompress(ni->vol, ctx->attr, 76 if (err == -ENOENT)
73 ni->runlist.rl); 77 err = -EIO;
74 if (IS_ERR(rl)) 78 goto err_out;
75 err = PTR_ERR(rl);
76 else
77 ni->runlist.rl = rl;
78 } 79 }
79 ntfs_attr_put_search_ctx(ctx); 80 a = ctx->attr;
81 /*
82 * Only decompress the mapping pairs if @vcn is inside it. Otherwise
83 * we get into problems when we try to map an out of bounds vcn because
84 * we then try to map the already mapped runlist fragment and
85 * ntfs_mapping_pairs_decompress() fails.
86 */
87 end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1;
88 if (unlikely(!a->data.non_resident.lowest_vcn && end_vcn <= 1))
89 end_vcn = ni->allocated_size >> ni->vol->cluster_size_bits;
90 if (unlikely(vcn >= end_vcn)) {
91 err = -ENOENT;
92 goto err_out;
93 }
94 rl = ntfs_mapping_pairs_decompress(ni->vol, a, ni->runlist.rl);
95 if (IS_ERR(rl))
96 err = PTR_ERR(rl);
97 else
98 ni->runlist.rl = rl;
80err_out: 99err_out:
100 if (likely(ctx))
101 ntfs_attr_put_search_ctx(ctx);
81 unmap_mft_record(base_ni); 102 unmap_mft_record(base_ni);
82 return err; 103 return err;
83} 104}
@@ -89,7 +110,9 @@ err_out:
89 * 110 *
90 * Map the part of a runlist containing the @vcn of the ntfs inode @ni. 111 * Map the part of a runlist containing the @vcn of the ntfs inode @ni.
91 * 112 *
92 * Return 0 on success and -errno on error. 113 * Return 0 on success and -errno on error. There is one special error code
114 * which is not an error as such. This is -ENOENT. It means that @vcn is out
115 * of bounds of the runlist.
93 * 116 *
94 * Locking: - The runlist must be unlocked on entry and is unlocked on return. 117 * Locking: - The runlist must be unlocked on entry and is unlocked on return.
95 * - This function takes the runlist lock for writing and modifies the 118 * - This function takes the runlist lock for writing and modifies the
@@ -287,11 +310,11 @@ retry_remap:
287 goto retry_remap; 310 goto retry_remap;
288 } 311 }
289 /* 312 /*
290 * -EINVAL and -ENOENT coming from a failed mapping attempt are 313 * -EINVAL coming from a failed mapping attempt is equivalent
291 * equivalent to i/o errors for us as they should not happen in 314 * to i/o error for us as it should not happen in our code
292 * our code paths. 315 * paths.
293 */ 316 */
294 if (err == -EINVAL || err == -ENOENT) 317 if (err == -EINVAL)
295 err = -EIO; 318 err = -EIO;
296 } else if (!err) 319 } else if (!err)
297 err = -EIO; 320 err = -EIO;