aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-02-15 05:08:43 -0500
committerAnton Altaparmakov <aia21@cantab.net>2005-05-05 05:56:31 -0400
commitb6ad6c52fe36ab35d0fe28c064f59de2ba670c2a (patch)
treed888c28a2c3c7fa733045dc7dc9c9bc7f157bf4a /fs/ntfs
parent1a0df15acdae065789446aca83021c72b71db9a5 (diff)
NTFS: - Split ntfs_map_runlist() into ntfs_map_runlist() and a non-locking
helper ntfs_map_runlist_nolock() which is used by ntfs_map_runlist(). This allows us to map runlist fragments with the runlist lock already held without having to drop and reacquire it around the call. Adapt all callers. - Change ntfs_find_vcn() to ntfs_find_vcn_nolock() which takes a locked runlist. This allows us to find runlist elements with the runlist lock already held without having to drop and reacquire it around the call. Adapt all callers. Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs')
-rw-r--r--fs/ntfs/ChangeLog9
-rw-r--r--fs/ntfs/aops.c34
-rw-r--r--fs/ntfs/attrib.c107
-rw-r--r--fs/ntfs/attrib.h5
-rw-r--r--fs/ntfs/lcnalloc.c39
-rw-r--r--fs/ntfs/mft.c38
6 files changed, 119 insertions, 113 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index b40c334e616f..9d42393c16c0 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -63,6 +63,15 @@ ToDo/Notes:
63 - Fix a bug in fs/ntfs/runlist.c::ntfs_mapping_pairs_decompress() in 63 - Fix a bug in fs/ntfs/runlist.c::ntfs_mapping_pairs_decompress() in
64 the creation of the unmapped runlist element for the base attribute 64 the creation of the unmapped runlist element for the base attribute
65 extent. 65 extent.
66 - Split ntfs_map_runlist() into ntfs_map_runlist() and a non-locking
67 helper ntfs_map_runlist_nolock() which is used by ntfs_map_runlist().
68 This allows us to map runlist fragments with the runlist lock already
69 held without having to drop and reacquire it around the call. Adapt
70 all callers.
71 - Change ntfs_find_vcn() to ntfs_find_vcn_nolock() which takes a locked
72 runlist. This allows us to find runlist elements with the runlist
73 lock already held without having to drop and reacquire it around the
74 call. Adapt all callers.
66 75
672.1.22 - Many bug and race fixes and error handling improvements. 762.1.22 - Many bug and race fixes and error handling improvements.
68 77
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 812d53e93354..2b4b8b9e8796 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -2,7 +2,7 @@
2 * aops.c - NTFS kernel address space operations and page cache handling. 2 * aops.c - NTFS kernel address space operations and page cache handling.
3 * Part of the Linux-NTFS project. 3 * Part of the Linux-NTFS project.
4 * 4 *
5 * Copyright (c) 2001-2004 Anton Altaparmakov 5 * Copyright (c) 2001-2005 Anton Altaparmakov
6 * Copyright (c) 2002 Richard Russon 6 * Copyright (c) 2002 Richard Russon
7 * 7 *
8 * This program/include file is free software; you can redistribute it and/or 8 * This program/include file is free software; you can redistribute it and/or
@@ -135,7 +135,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
135 i * rec_size), rec_size); 135 i * rec_size), rec_size);
136 flush_dcache_page(page); 136 flush_dcache_page(page);
137 kunmap_atomic(addr, KM_BIO_SRC_IRQ); 137 kunmap_atomic(addr, KM_BIO_SRC_IRQ);
138 if (likely(!PageError(page) && page_uptodate)) 138 if (likely(page_uptodate && !PageError(page)))
139 SetPageUptodate(page); 139 SetPageUptodate(page);
140 } 140 }
141 unlock_page(page); 141 unlock_page(page);
@@ -347,11 +347,11 @@ handle_zblock:
347 */ 347 */
348static int ntfs_readpage(struct file *file, struct page *page) 348static int ntfs_readpage(struct file *file, struct page *page)
349{ 349{
350 loff_t i_size;
351 ntfs_inode *ni, *base_ni; 350 ntfs_inode *ni, *base_ni;
352 u8 *kaddr; 351 u8 *kaddr;
353 ntfs_attr_search_ctx *ctx; 352 ntfs_attr_search_ctx *ctx;
354 MFT_RECORD *mrec; 353 MFT_RECORD *mrec;
354 unsigned long flags;
355 u32 attr_len; 355 u32 attr_len;
356 int err = 0; 356 int err = 0;
357 357
@@ -389,9 +389,9 @@ static int ntfs_readpage(struct file *file, struct page *page)
389 * Attribute is resident, implying it is not compressed or encrypted. 389 * Attribute is resident, implying it is not compressed or encrypted.
390 * This also means the attribute is smaller than an mft record and 390 * This also means the attribute is smaller than an mft record and
391 * hence smaller than a page, so can simply zero out any pages with 391 * hence smaller than a page, so can simply zero out any pages with
392 * index above 0. We can also do this if the file size is 0. 392 * index above 0.
393 */ 393 */
394 if (unlikely(page->index > 0 || !i_size_read(VFS_I(ni)))) { 394 if (unlikely(page->index > 0)) {
395 kaddr = kmap_atomic(page, KM_USER0); 395 kaddr = kmap_atomic(page, KM_USER0);
396 memset(kaddr, 0, PAGE_CACHE_SIZE); 396 memset(kaddr, 0, PAGE_CACHE_SIZE);
397 flush_dcache_page(page); 397 flush_dcache_page(page);
@@ -418,9 +418,10 @@ static int ntfs_readpage(struct file *file, struct page *page)
418 if (unlikely(err)) 418 if (unlikely(err))
419 goto put_unm_err_out; 419 goto put_unm_err_out;
420 attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); 420 attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
421 i_size = i_size_read(VFS_I(ni)); 421 read_lock_irqsave(&ni->size_lock, flags);
422 if (unlikely(attr_len > i_size)) 422 if (unlikely(attr_len > ni->initialized_size))
423 attr_len = i_size; 423 attr_len = ni->initialized_size;
424 read_unlock_irqrestore(&ni->size_lock, flags);
424 kaddr = kmap_atomic(page, KM_USER0); 425 kaddr = kmap_atomic(page, KM_USER0);
425 /* Copy the data to the page. */ 426 /* Copy the data to the page. */
426 memcpy(kaddr, (u8*)ctx->attr + 427 memcpy(kaddr, (u8*)ctx->attr +
@@ -1247,20 +1248,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
1247 int err; 1248 int err;
1248 1249
1249 BUG_ON(!PageLocked(page)); 1250 BUG_ON(!PageLocked(page));
1250 /*
1251 * If a previous ntfs_truncate() failed, repeat it and abort if it
1252 * fails again.
1253 */
1254 if (unlikely(NInoTruncateFailed(ni))) {
1255 down_write(&vi->i_alloc_sem);
1256 err = ntfs_truncate(vi);
1257 up_write(&vi->i_alloc_sem);
1258 if (err || NInoTruncateFailed(ni)) {
1259 if (!err)
1260 err = -EIO;
1261 goto err_out;
1262 }
1263 }
1264 i_size = i_size_read(vi); 1251 i_size = i_size_read(vi);
1265 /* Is the page fully outside i_size? (truncate in progress) */ 1252 /* Is the page fully outside i_size? (truncate in progress) */
1266 if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >> 1253 if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >>
@@ -1490,13 +1477,12 @@ static int ntfs_prepare_nonresident_write(struct page *page,
1490 1477
1491 read_lock_irqsave(&ni->size_lock, flags); 1478 read_lock_irqsave(&ni->size_lock, flags);
1492 /* 1479 /*
1493 * The first out of bounds block for the allocated size. No need to 1480 * The first out of bounds block for the allocated size. No need to
1494 * round up as allocated_size is in multiples of cluster size and the 1481 * round up as allocated_size is in multiples of cluster size and the
1495 * minimum cluster size is 512 bytes, which is equal to the smallest 1482 * minimum cluster size is 512 bytes, which is equal to the smallest
1496 * blocksize. 1483 * blocksize.
1497 */ 1484 */
1498 ablock = ni->allocated_size >> blocksize_bits; 1485 ablock = ni->allocated_size >> blocksize_bits;
1499
1500 i_size = i_size_read(vi); 1486 i_size = i_size_read(vi);
1501 initialized_size = ni->initialized_size; 1487 initialized_size = ni->initialized_size;
1502 read_unlock_irqrestore(&ni->size_lock, flags); 1488 read_unlock_irqrestore(&ni->size_lock, flags);
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 7d668466dcd7..7a16f7ca76d8 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -1,7 +1,7 @@
1/** 1/**
2 * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. 2 * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project.
3 * 3 *
4 * Copyright (c) 2001-2004 Anton Altaparmakov 4 * Copyright (c) 2001-2005 Anton Altaparmakov
5 * Copyright (c) 2002 Richard Russon 5 * Copyright (c) 2002 Richard Russon
6 * 6 *
7 * This program/include file is free software; you can redistribute it and/or 7 * This program/include file is free software; you can redistribute it and/or
@@ -30,7 +30,7 @@
30#include "types.h" 30#include "types.h"
31 31
32/** 32/**
33 * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode 33 * ntfs_map_runlist_nolock - map (a part of) a runlist of an ntfs inode
34 * @ni: ntfs inode for which to map (part of) a runlist 34 * @ni: ntfs inode for which to map (part of) a runlist
35 * @vcn: map runlist part containing this vcn 35 * @vcn: map runlist part containing this vcn
36 * 36 *
@@ -38,24 +38,23 @@
38 * 38 *
39 * Return 0 on success and -errno on error. 39 * Return 0 on success and -errno on error.
40 * 40 *
41 * Locking: - The runlist must be unlocked on entry and is unlocked on return. 41 * Locking: - The runlist must be locked for writing.
42 * - This function takes the lock for writing and modifies the runlist. 42 * - This function modifies the runlist.
43 */ 43 */
44int ntfs_map_runlist(ntfs_inode *ni, VCN vcn) 44int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
45{ 45{
46 ntfs_inode *base_ni; 46 ntfs_inode *base_ni;
47 ntfs_attr_search_ctx *ctx;
48 MFT_RECORD *mrec; 47 MFT_RECORD *mrec;
48 ntfs_attr_search_ctx *ctx;
49 runlist_element *rl;
49 int err = 0; 50 int err = 0;
50 51
51 ntfs_debug("Mapping runlist part containing vcn 0x%llx.", 52 ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
52 (unsigned long long)vcn); 53 (unsigned long long)vcn);
53
54 if (!NInoAttr(ni)) 54 if (!NInoAttr(ni))
55 base_ni = ni; 55 base_ni = ni;
56 else 56 else
57 base_ni = ni->ext.base_ntfs_ino; 57 base_ni = ni->ext.base_ntfs_ino;
58
59 mrec = map_mft_record(base_ni); 58 mrec = map_mft_record(base_ni);
60 if (IS_ERR(mrec)) 59 if (IS_ERR(mrec))
61 return PTR_ERR(mrec); 60 return PTR_ERR(mrec);
@@ -66,15 +65,7 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
66 } 65 }
67 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 66 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
68 CASE_SENSITIVE, vcn, NULL, 0, ctx); 67 CASE_SENSITIVE, vcn, NULL, 0, ctx);
69 if (unlikely(err)) 68 if (likely(!err)) {
70 goto put_err_out;
71
72 down_write(&ni->runlist.lock);
73 /* Make sure someone else didn't do the work while we were sleeping. */
74 if (likely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) <=
75 LCN_RL_NOT_MAPPED)) {
76 runlist_element *rl;
77
78 rl = ntfs_mapping_pairs_decompress(ni->vol, ctx->attr, 69 rl = ntfs_mapping_pairs_decompress(ni->vol, ctx->attr,
79 ni->runlist.rl); 70 ni->runlist.rl);
80 if (IS_ERR(rl)) 71 if (IS_ERR(rl))
@@ -82,9 +73,6 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
82 else 73 else
83 ni->runlist.rl = rl; 74 ni->runlist.rl = rl;
84 } 75 }
85 up_write(&ni->runlist.lock);
86
87put_err_out:
88 ntfs_attr_put_search_ctx(ctx); 76 ntfs_attr_put_search_ctx(ctx);
89err_out: 77err_out:
90 unmap_mft_record(base_ni); 78 unmap_mft_record(base_ni);
@@ -92,17 +80,45 @@ err_out:
92} 80}
93 81
94/** 82/**
95 * ntfs_find_vcn - find a vcn in the runlist described by an ntfs inode 83 * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode
96 * @ni: ntfs inode describing the runlist to search 84 * @ni: ntfs inode for which to map (part of) a runlist
97 * @vcn: vcn to find 85 * @vcn: map runlist part containing this vcn
98 * @need_write: if false, lock for reading and if true, lock for writing 86 *
87 * Map the part of a runlist containing the @vcn of the ntfs inode @ni.
88 *
89 * Return 0 on success and -errno on error.
90 *
91 * Locking: - The runlist must be unlocked on entry and is unlocked on return.
92 * - This function takes the runlist lock for writing and modifies the
93 * runlist.
94 */
95int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
96{
97 int err = 0;
98
99 down_write(&ni->runlist.lock);
100 /* Make sure someone else didn't do the work while we were sleeping. */
101 if (likely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) <=
102 LCN_RL_NOT_MAPPED))
103 err = ntfs_map_runlist_nolock(ni, vcn);
104 up_write(&ni->runlist.lock);
105 return err;
106}
107
108/**
109 * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode
110 * @ni: ntfs inode describing the runlist to search
111 * @vcn: vcn to find
112 * @write_locked: true if the runlist is locked for writing
99 * 113 *
100 * Find the virtual cluster number @vcn in the runlist described by the ntfs 114 * Find the virtual cluster number @vcn in the runlist described by the ntfs
101 * inode @ni and return the address of the runlist element containing the @vcn. 115 * inode @ni and return the address of the runlist element containing the @vcn.
102 * The runlist is left locked and the caller has to unlock it. If @need_write 116 * The runlist is left locked and the caller has to unlock it. In the error
103 * is true, the runlist is locked for writing and if @need_write is false, the 117 * case, the runlist is left in the same locking state as on entry.
104 * runlist is locked for reading. In the error case, the runlist is not left 118 *
105 * locked. 119 * Note if @write_locked is FALSE the lock may be dropped inside the function
120 * so you cannot rely on the runlist still being the same when this function
121 * returns.
106 * 122 *
107 * Note you need to distinguish between the lcn of the returned runlist element 123 * Note you need to distinguish between the lcn of the returned runlist element
108 * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on 124 * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on
@@ -124,28 +140,24 @@ err_out:
124 * true, it is locked for writing. Otherwise is is locked for 140 * true, it is locked for writing. Otherwise is is locked for
125 * reading. 141 * reading.
126 */ 142 */
127runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn, 143runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
128 const BOOL need_write) 144 const BOOL write_locked)
129{ 145{
130 runlist_element *rl; 146 runlist_element *rl;
131 int err = 0; 147 int err = 0;
132 BOOL is_retry = FALSE; 148 BOOL is_retry = FALSE;
133 149
134 ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, lock for %sing.", 150 ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.",
135 ni->mft_no, (unsigned long long)vcn, 151 ni->mft_no, (unsigned long long)vcn,
136 !need_write ? "read" : "writ"); 152 write_locked ? "write" : "read");
137 BUG_ON(!ni); 153 BUG_ON(!ni);
138 BUG_ON(!NInoNonResident(ni)); 154 BUG_ON(!NInoNonResident(ni));
139 BUG_ON(vcn < 0); 155 BUG_ON(vcn < 0);
140lock_retry_remap: 156retry_remap:
141 if (!need_write)
142 down_read(&ni->runlist.lock);
143 else
144 down_write(&ni->runlist.lock);
145 rl = ni->runlist.rl; 157 rl = ni->runlist.rl;
146 if (likely(rl && vcn >= rl[0].vcn)) { 158 if (likely(rl && vcn >= rl[0].vcn)) {
147 while (likely(rl->length)) { 159 while (likely(rl->length)) {
148 if (likely(vcn < rl[1].vcn)) { 160 if (unlikely(vcn < rl[1].vcn)) {
149 if (likely(rl->lcn >= LCN_HOLE)) { 161 if (likely(rl->lcn >= LCN_HOLE)) {
150 ntfs_debug("Done."); 162 ntfs_debug("Done.");
151 return rl; 163 return rl;
@@ -161,19 +173,23 @@ lock_retry_remap:
161 err = -EIO; 173 err = -EIO;
162 } 174 }
163 } 175 }
164 if (!need_write)
165 up_read(&ni->runlist.lock);
166 else
167 up_write(&ni->runlist.lock);
168 if (!err && !is_retry) { 176 if (!err && !is_retry) {
169 /* 177 /*
170 * The @vcn is in an unmapped region, map the runlist and 178 * The @vcn is in an unmapped region, map the runlist and
171 * retry. 179 * retry.
172 */ 180 */
173 err = ntfs_map_runlist(ni, vcn); 181 if (!write_locked) {
182 up_read(&ni->runlist.lock);
183 down_write(&ni->runlist.lock);
184 }
185 err = ntfs_map_runlist_nolock(ni, vcn);
186 if (!write_locked) {
187 up_write(&ni->runlist.lock);
188 down_read(&ni->runlist.lock);
189 }
174 if (likely(!err)) { 190 if (likely(!err)) {
175 is_retry = TRUE; 191 is_retry = TRUE;
176 goto lock_retry_remap; 192 goto retry_remap;
177 } 193 }
178 /* 194 /*
179 * -EINVAL and -ENOENT coming from a failed mapping attempt are 195 * -EINVAL and -ENOENT coming from a failed mapping attempt are
@@ -184,7 +200,8 @@ lock_retry_remap:
184 err = -EIO; 200 err = -EIO;
185 } else if (!err) 201 } else if (!err)
186 err = -EIO; 202 err = -EIO;
187 ntfs_error(ni->vol->sb, "Failed with error code %i.", err); 203 if (err != -ENOENT)
204 ntfs_error(ni->vol->sb, "Failed with error code %i.", err);
188 return ERR_PTR(err); 205 return ERR_PTR(err);
189} 206}
190 207
diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
index e0c2c6c81bc0..3eb451657025 100644
--- a/fs/ntfs/attrib.h
+++ b/fs/ntfs/attrib.h
@@ -60,10 +60,11 @@ typedef struct {
60 ATTR_RECORD *base_attr; 60 ATTR_RECORD *base_attr;
61} ntfs_attr_search_ctx; 61} ntfs_attr_search_ctx;
62 62
63extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn);
63extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn); 64extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
64 65
65extern runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn, 66extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
66 const BOOL need_write); 67 const BOOL write_locked);
67 68
68int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, 69int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
69 const u32 name_len, const IGNORE_CASE_BOOL ic, 70 const u32 name_len, const IGNORE_CASE_BOOL ic,
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
index 5346596fa871..8db4492b139c 100644
--- a/fs/ntfs/lcnalloc.c
+++ b/fs/ntfs/lcnalloc.c
@@ -849,7 +849,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
849 total_freed = real_freed = 0; 849 total_freed = real_freed = 0;
850 850
851 /* This returns with ni->runlist locked for reading on success. */ 851 /* This returns with ni->runlist locked for reading on success. */
852 rl = ntfs_find_vcn(ni, start_vcn, FALSE); 852 down_read(&ni->runlist.lock);
853 rl = ntfs_find_vcn_nolock(ni, start_vcn, FALSE);
853 if (IS_ERR(rl)) { 854 if (IS_ERR(rl)) {
854 if (!is_rollback) 855 if (!is_rollback)
855 ntfs_error(vol->sb, "Failed to find first runlist " 856 ntfs_error(vol->sb, "Failed to find first runlist "
@@ -863,7 +864,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
863 ntfs_error(vol->sb, "First runlist element has " 864 ntfs_error(vol->sb, "First runlist element has "
864 "invalid lcn, aborting."); 865 "invalid lcn, aborting.");
865 err = -EIO; 866 err = -EIO;
866 goto unl_err_out; 867 goto err_out;
867 } 868 }
868 /* Find the starting cluster inside the run that needs freeing. */ 869 /* Find the starting cluster inside the run that needs freeing. */
869 delta = start_vcn - rl->vcn; 870 delta = start_vcn - rl->vcn;
@@ -881,7 +882,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
881 if (!is_rollback) 882 if (!is_rollback)
882 ntfs_error(vol->sb, "Failed to clear first run " 883 ntfs_error(vol->sb, "Failed to clear first run "
883 "(error %i), aborting.", err); 884 "(error %i), aborting.", err);
884 goto unl_err_out; 885 goto err_out;
885 } 886 }
886 /* We have freed @to_free real clusters. */ 887 /* We have freed @to_free real clusters. */
887 real_freed = to_free; 888 real_freed = to_free;
@@ -901,30 +902,15 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
901 if (unlikely(rl->lcn < LCN_HOLE)) { 902 if (unlikely(rl->lcn < LCN_HOLE)) {
902 VCN vcn; 903 VCN vcn;
903 904
904 /* 905 /* Attempt to map runlist. */
905 * Attempt to map runlist, dropping runlist lock for
906 * the duration.
907 */
908 vcn = rl->vcn; 906 vcn = rl->vcn;
909 up_read(&ni->runlist.lock); 907 rl = ntfs_find_vcn_nolock(ni, vcn, FALSE);
910 err = ntfs_map_runlist(ni, vcn);
911 if (err) {
912 if (!is_rollback)
913 ntfs_error(vol->sb, "Failed to map "
914 "runlist fragment.");
915 if (err == -EINVAL || err == -ENOENT)
916 err = -EIO;
917 goto err_out;
918 }
919 /*
920 * This returns with ni->runlist locked for reading on
921 * success.
922 */
923 rl = ntfs_find_vcn(ni, vcn, FALSE);
924 if (IS_ERR(rl)) { 908 if (IS_ERR(rl)) {
925 err = PTR_ERR(rl); 909 err = PTR_ERR(rl);
926 if (!is_rollback) 910 if (!is_rollback)
927 ntfs_error(vol->sb, "Failed to find " 911 ntfs_error(vol->sb, "Failed to map "
912 "runlist fragment or "
913 "failed to find "
928 "subsequent runlist " 914 "subsequent runlist "
929 "element."); 915 "element.");
930 goto err_out; 916 goto err_out;
@@ -937,7 +923,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
937 (unsigned long long) 923 (unsigned long long)
938 rl->lcn); 924 rl->lcn);
939 err = -EIO; 925 err = -EIO;
940 goto unl_err_out; 926 goto err_out;
941 } 927 }
942 } 928 }
943 /* The number of clusters in this run that need freeing. */ 929 /* The number of clusters in this run that need freeing. */
@@ -953,7 +939,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
953 if (!is_rollback) 939 if (!is_rollback)
954 ntfs_error(vol->sb, "Failed to clear " 940 ntfs_error(vol->sb, "Failed to clear "
955 "subsequent run."); 941 "subsequent run.");
956 goto unl_err_out; 942 goto err_out;
957 } 943 }
958 /* We have freed @to_free real clusters. */ 944 /* We have freed @to_free real clusters. */
959 real_freed += to_free; 945 real_freed += to_free;
@@ -974,9 +960,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
974 /* We are done. Return the number of actually freed clusters. */ 960 /* We are done. Return the number of actually freed clusters. */
975 ntfs_debug("Done."); 961 ntfs_debug("Done.");
976 return real_freed; 962 return real_freed;
977unl_err_out:
978 up_read(&ni->runlist.lock);
979err_out: 963err_out:
964 up_read(&ni->runlist.lock);
980 if (is_rollback) 965 if (is_rollback)
981 return err; 966 return err;
982 /* If no real clusters were freed, no need to rollback. */ 967 /* If no real clusters were freed, no need to rollback. */
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 4e0bf39426cf..0975d738834c 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -1,7 +1,7 @@
1/** 1/**
2 * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. 2 * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
3 * 3 *
4 * Copyright (c) 2001-2004 Anton Altaparmakov 4 * Copyright (c) 2001-2005 Anton Altaparmakov
5 * Copyright (c) 2002 Richard Russon 5 * Copyright (c) 2002 Richard Russon
6 * 6 *
7 * This program/include file is free software; you can redistribute it and/or 7 * This program/include file is free software; you can redistribute it and/or
@@ -287,7 +287,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
287 } 287 }
288 unmap_mft_record(ni); 288 unmap_mft_record(ni);
289 ntfs_error(base_ni->vol->sb, "Found stale extent mft " 289 ntfs_error(base_ni->vol->sb, "Found stale extent mft "
290 "reference! Corrupt file system. " 290 "reference! Corrupt filesystem. "
291 "Run chkdsk."); 291 "Run chkdsk.");
292 return ERR_PTR(-EIO); 292 return ERR_PTR(-EIO);
293 } 293 }
@@ -318,7 +318,7 @@ map_err_out:
318 /* Verify the sequence number if it is present. */ 318 /* Verify the sequence number if it is present. */
319 if (seq_no && (le16_to_cpu(m->sequence_number) != seq_no)) { 319 if (seq_no && (le16_to_cpu(m->sequence_number) != seq_no)) {
320 ntfs_error(base_ni->vol->sb, "Found stale extent mft " 320 ntfs_error(base_ni->vol->sb, "Found stale extent mft "
321 "reference! Corrupt file system. Run chkdsk."); 321 "reference! Corrupt filesystem. Run chkdsk.");
322 destroy_ni = TRUE; 322 destroy_ni = TRUE;
323 m = ERR_PTR(-EIO); 323 m = ERR_PTR(-EIO);
324 goto unm_err_out; 324 goto unm_err_out;
@@ -1292,19 +1292,20 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
1292 /* 1292 /*
1293 * Determine the last lcn of the mft bitmap. The allocated size of the 1293 * Determine the last lcn of the mft bitmap. The allocated size of the
1294 * mft bitmap cannot be zero so we are ok to do this. 1294 * mft bitmap cannot be zero so we are ok to do this.
1295 * ntfs_find_vcn() returns the runlist locked on success.
1296 */ 1295 */
1296 down_write(&mftbmp_ni->runlist.lock);
1297 read_lock_irqsave(&mftbmp_ni->size_lock, flags); 1297 read_lock_irqsave(&mftbmp_ni->size_lock, flags);
1298 ll = mftbmp_ni->allocated_size; 1298 ll = mftbmp_ni->allocated_size;
1299 read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); 1299 read_unlock_irqrestore(&mftbmp_ni->size_lock, flags);
1300 rl = ntfs_find_vcn(mftbmp_ni, (ll - 1) >> vol->cluster_size_bits, TRUE); 1300 rl = ntfs_find_vcn_nolock(mftbmp_ni,
1301 (ll - 1) >> vol->cluster_size_bits, TRUE);
1301 if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { 1302 if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
1303 up_write(&mftbmp_ni->runlist.lock);
1302 ntfs_error(vol->sb, "Failed to determine last allocated " 1304 ntfs_error(vol->sb, "Failed to determine last allocated "
1303 "cluster of mft bitmap attribute."); 1305 "cluster of mft bitmap attribute.");
1304 if (!IS_ERR(rl)) { 1306 if (!IS_ERR(rl))
1305 up_write(&mftbmp_ni->runlist.lock);
1306 ret = -EIO; 1307 ret = -EIO;
1307 } else 1308 else
1308 ret = PTR_ERR(rl); 1309 ret = PTR_ERR(rl);
1309 return ret; 1310 return ret;
1310 } 1311 }
@@ -1428,6 +1429,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
1428 // TODO: Deal with this by moving this extent to a new mft 1429 // TODO: Deal with this by moving this extent to a new mft
1429 // record or by starting a new extent in a new mft record or by 1430 // record or by starting a new extent in a new mft record or by
1430 // moving other attributes out of this mft record. 1431 // moving other attributes out of this mft record.
1432 // Note: It will need to be a special mft record and if none of
1433 // those are available it gets rather complicated...
1431 ntfs_error(vol->sb, "Not enough space in this mft record to " 1434 ntfs_error(vol->sb, "Not enough space in this mft record to "
1432 "accomodate extended mft bitmap attribute " 1435 "accomodate extended mft bitmap attribute "
1433 "extent. Cannot handle this yet."); 1436 "extent. Cannot handle this yet.");
@@ -1719,19 +1722,20 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
1719 * Determine the preferred allocation location, i.e. the last lcn of 1722 * Determine the preferred allocation location, i.e. the last lcn of
1720 * the mft data attribute. The allocated size of the mft data 1723 * the mft data attribute. The allocated size of the mft data
1721 * attribute cannot be zero so we are ok to do this. 1724 * attribute cannot be zero so we are ok to do this.
1722 * ntfs_find_vcn() returns the runlist locked on success.
1723 */ 1725 */
1726 down_write(&mft_ni->runlist.lock);
1724 read_lock_irqsave(&mft_ni->size_lock, flags); 1727 read_lock_irqsave(&mft_ni->size_lock, flags);
1725 ll = mft_ni->allocated_size; 1728 ll = mft_ni->allocated_size;
1726 read_unlock_irqrestore(&mft_ni->size_lock, flags); 1729 read_unlock_irqrestore(&mft_ni->size_lock, flags);
1727 rl = ntfs_find_vcn(mft_ni, (ll - 1) >> vol->cluster_size_bits, TRUE); 1730 rl = ntfs_find_vcn_nolock(mft_ni, (ll - 1) >> vol->cluster_size_bits,
1731 TRUE);
1728 if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { 1732 if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
1733 up_write(&mft_ni->runlist.lock);
1729 ntfs_error(vol->sb, "Failed to determine last allocated " 1734 ntfs_error(vol->sb, "Failed to determine last allocated "
1730 "cluster of mft data attribute."); 1735 "cluster of mft data attribute.");
1731 if (!IS_ERR(rl)) { 1736 if (!IS_ERR(rl))
1732 up_write(&mft_ni->runlist.lock);
1733 ret = -EIO; 1737 ret = -EIO;
1734 } else 1738 else
1735 ret = PTR_ERR(rl); 1739 ret = PTR_ERR(rl);
1736 return ret; 1740 return ret;
1737 } 1741 }
@@ -1858,7 +1862,11 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
1858 // moving other attributes out of this mft record. 1862 // moving other attributes out of this mft record.
1859 // Note: Use the special reserved mft records and ensure that 1863 // Note: Use the special reserved mft records and ensure that
1860 // this extent is not required to find the mft record in 1864 // this extent is not required to find the mft record in
1861 // question. 1865 // question. If no free special records left we would need to
1866 // move an existing record away, insert ours in its place, and
1867 // then place the moved record into the newly allocated space
1868 // and we would then need to update all references to this mft
1869 // record appropriately. This is rather complicated...
1862 ntfs_error(vol->sb, "Not enough space in this mft record to " 1870 ntfs_error(vol->sb, "Not enough space in this mft record to "
1863 "accomodate extended mft data attribute " 1871 "accomodate extended mft data attribute "
1864 "extent. Cannot handle this yet."); 1872 "extent. Cannot handle this yet.");
@@ -2021,7 +2029,7 @@ static int ntfs_mft_record_layout(const ntfs_volume *vol, const s64 mft_no,
2021 "reports this as corruption, please email " 2029 "reports this as corruption, please email "
2022 "linux-ntfs-dev@lists.sourceforge.net stating " 2030 "linux-ntfs-dev@lists.sourceforge.net stating "
2023 "that you saw this message and that the " 2031 "that you saw this message and that the "
2024 "modified file system created was corrupt. " 2032 "modified filesystem created was corrupt. "
2025 "Thank you."); 2033 "Thank you.");
2026 } 2034 }
2027 /* Set the update sequence number to 1. */ 2035 /* Set the update sequence number to 1. */