diff options
-rw-r--r-- | fs/ntfs/ChangeLog | 5 | ||||
-rw-r--r-- | fs/ntfs/attrib.c | 29 | ||||
-rw-r--r-- | fs/ntfs/attrib.h | 4 | ||||
-rw-r--r-- | fs/ntfs/lcnalloc.c | 4 | ||||
-rw-r--r-- | fs/ntfs/mft.c | 6 | ||||
-rw-r--r-- | fs/ntfs/runlist.c | 15 | ||||
-rw-r--r-- | fs/ntfs/runlist.h | 2 |
7 files changed, 39 insertions, 26 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 4af6ae6ff12b..7507a56a4921 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -92,6 +92,11 @@ ToDo/Notes: | |||
92 | non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident(). | 92 | non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident(). |
93 | - Add fs/ntfs/attrib.c::ntfs_attr_vcn_to_lcn_nolock() used by the new | 93 | - Add fs/ntfs/attrib.c::ntfs_attr_vcn_to_lcn_nolock() used by the new |
94 | write code. | 94 | write code. |
95 | - Fix bug in fs/ntfs/attrib.c::ntfs_find_vcn_nolock() where after | ||
96 | dropping the read lock and taking the write lock we were not checking | ||
97 | whether someone else did not already do the work we wanted to do. | ||
98 | - Rename fs/ntfs/attrib.c::ntfs_find_vcn_nolock() to | ||
99 | ntfs_attr_find_vcn_nolock() and update all callers. | ||
95 | 100 | ||
96 | 2.1.22 - Many bug and race fixes and error handling improvements. | 101 | 2.1.22 - Many bug and race fixes and error handling improvements. |
97 | 102 | ||
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 1610f1cd2862..6de5e04e97a2 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -193,19 +193,19 @@ retry_remap: | |||
193 | } | 193 | } |
194 | 194 | ||
195 | /** | 195 | /** |
196 | * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode | 196 | * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode |
197 | * @ni: ntfs inode describing the runlist to search | 197 | * @ni: ntfs inode describing the runlist to search |
198 | * @vcn: vcn to find | 198 | * @vcn: vcn to find |
199 | * @write_locked: true if the runlist is locked for writing | 199 | * @write_locked: true if the runlist is locked for writing |
200 | * | 200 | * |
201 | * Find the virtual cluster number @vcn in the runlist described by the ntfs | 201 | * Find the virtual cluster number @vcn in the runlist described by the ntfs |
202 | * inode @ni and return the address of the runlist element containing the @vcn. | 202 | * inode @ni and return the address of the runlist element containing the @vcn. |
203 | * The runlist is left locked and the caller has to unlock it. In the error | ||
204 | * case, the runlist is left in the same locking state as on entry. | ||
205 | * | 203 | * |
206 | * Note if @write_locked is FALSE the lock may be dropped inside the function | 204 | * If the @vcn is not mapped yet, the attempt is made to map the attribute |
207 | * so you cannot rely on the runlist still being the same when this function | 205 | * extent containing the @vcn and the vcn to lcn conversion is retried. |
208 | * returns. | 206 | * |
207 | * If @write_locked is true the caller has locked the runlist for writing and | ||
208 | * if false for reading. | ||
209 | * | 209 | * |
210 | * Note you need to distinguish between the lcn of the returned runlist element | 210 | * Note you need to distinguish between the lcn of the returned runlist element |
211 | * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on | 211 | * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on |
@@ -221,13 +221,12 @@ retry_remap: | |||
221 | * -ENOMEM - Not enough memory to map runlist. | 221 | * -ENOMEM - Not enough memory to map runlist. |
222 | * -EIO - Critical error (runlist/file is corrupt, i/o error, etc). | 222 | * -EIO - Critical error (runlist/file is corrupt, i/o error, etc). |
223 | * | 223 | * |
224 | * Locking: - The runlist must be unlocked on entry. | 224 | * Locking: - The runlist must be locked on entry and is left locked on return. |
225 | * - On failing return, the runlist is unlocked. | 225 | * - If @write_locked is FALSE, i.e. the runlist is locked for reading, |
226 | * - On successful return, the runlist is locked. If @need_write us | 226 | * the lock may be dropped inside the function so you cannot rely on |
227 | * true, it is locked for writing. Otherwise is is locked for | 227 | * the runlist still being the same when this function returns. |
228 | * reading. | ||
229 | */ | 228 | */ |
230 | runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, | 229 | runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, |
231 | const BOOL write_locked) | 230 | const BOOL write_locked) |
232 | { | 231 | { |
233 | runlist_element *rl; | 232 | runlist_element *rl; |
@@ -268,6 +267,12 @@ retry_remap: | |||
268 | if (!write_locked) { | 267 | if (!write_locked) { |
269 | up_read(&ni->runlist.lock); | 268 | up_read(&ni->runlist.lock); |
270 | down_write(&ni->runlist.lock); | 269 | down_write(&ni->runlist.lock); |
270 | if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) != | ||
271 | LCN_RL_NOT_MAPPED)) { | ||
272 | up_write(&ni->runlist.lock); | ||
273 | down_read(&ni->runlist.lock); | ||
274 | goto retry_remap; | ||
275 | } | ||
271 | } | 276 | } |
272 | err = ntfs_map_runlist_nolock(ni, vcn); | 277 | err = ntfs_map_runlist_nolock(ni, vcn); |
273 | if (!write_locked) { | 278 | if (!write_locked) { |
diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index 75041c89c738..e0a50f1ca76f 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h | |||
@@ -66,8 +66,8 @@ extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn); | |||
66 | extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn, | 66 | extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn, |
67 | const BOOL write_locked); | 67 | const BOOL write_locked); |
68 | 68 | ||
69 | extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, | 69 | extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, |
70 | const BOOL write_locked); | 70 | const VCN vcn, const BOOL write_locked); |
71 | 71 | ||
72 | int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, | 72 | int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, |
73 | const u32 name_len, const IGNORE_CASE_BOOL ic, | 73 | const u32 name_len, const IGNORE_CASE_BOOL ic, |
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index f2b7f8582c59..6e584ab743c5 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c | |||
@@ -850,7 +850,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | |||
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 | down_read(&ni->runlist.lock); | 852 | down_read(&ni->runlist.lock); |
853 | rl = ntfs_find_vcn_nolock(ni, start_vcn, FALSE); | 853 | rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE); |
854 | if (IS_ERR(rl)) { | 854 | if (IS_ERR(rl)) { |
855 | if (!is_rollback) | 855 | if (!is_rollback) |
856 | ntfs_error(vol->sb, "Failed to find first runlist " | 856 | ntfs_error(vol->sb, "Failed to find first runlist " |
@@ -904,7 +904,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | |||
904 | 904 | ||
905 | /* Attempt to map runlist. */ | 905 | /* Attempt to map runlist. */ |
906 | vcn = rl->vcn; | 906 | vcn = rl->vcn; |
907 | rl = ntfs_find_vcn_nolock(ni, vcn, FALSE); | 907 | rl = ntfs_attr_find_vcn_nolock(ni, vcn, FALSE); |
908 | if (IS_ERR(rl)) { | 908 | if (IS_ERR(rl)) { |
909 | err = PTR_ERR(rl); | 909 | err = PTR_ERR(rl); |
910 | if (!is_rollback) | 910 | if (!is_rollback) |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 66ef6e275a48..61ce09f1b652 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
@@ -1297,7 +1297,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
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_nolock(mftbmp_ni, | 1300 | rl = ntfs_attr_find_vcn_nolock(mftbmp_ni, |
1301 | (ll - 1) >> vol->cluster_size_bits, TRUE); | 1301 | (ll - 1) >> vol->cluster_size_bits, TRUE); |
1302 | 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); | 1303 | up_write(&mftbmp_ni->runlist.lock); |
@@ -1727,8 +1727,8 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
1727 | read_lock_irqsave(&mft_ni->size_lock, flags); | 1727 | read_lock_irqsave(&mft_ni->size_lock, flags); |
1728 | ll = mft_ni->allocated_size; | 1728 | ll = mft_ni->allocated_size; |
1729 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | 1729 | read_unlock_irqrestore(&mft_ni->size_lock, flags); |
1730 | rl = ntfs_find_vcn_nolock(mft_ni, (ll - 1) >> vol->cluster_size_bits, | 1730 | rl = ntfs_attr_find_vcn_nolock(mft_ni, |
1731 | TRUE); | 1731 | (ll - 1) >> vol->cluster_size_bits, TRUE); |
1732 | 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); | 1733 | up_write(&mft_ni->runlist.lock); |
1734 | ntfs_error(vol->sb, "Failed to determine last allocated " | 1734 | ntfs_error(vol->sb, "Failed to determine last allocated " |
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 1b344dd4d407..3f479f176610 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c | |||
@@ -933,17 +933,18 @@ err_out: | |||
933 | * | 933 | * |
934 | * It is up to the caller to serialize access to the runlist @rl. | 934 | * It is up to the caller to serialize access to the runlist @rl. |
935 | * | 935 | * |
936 | * Since lcns must be >= 0, we use negative return values with special meaning: | 936 | * Since lcns must be >= 0, we use negative return codes with special meaning: |
937 | * | 937 | * |
938 | * Return value Meaning / Description | 938 | * Return code Meaning / Description |
939 | * ================================================== | 939 | * ================================================== |
940 | * -1 = LCN_HOLE Hole / not allocated on disk. | 940 | * LCN_HOLE Hole / not allocated on disk. |
941 | * -2 = LCN_RL_NOT_MAPPED This is part of the runlist which has not been | 941 | * LCN_RL_NOT_MAPPED This is part of the runlist which has not been |
942 | * inserted into the runlist yet. | 942 | * inserted into the runlist yet. |
943 | * -3 = LCN_ENOENT There is no such vcn in the attribute. | 943 | * LCN_ENOENT There is no such vcn in the attribute. |
944 | * | 944 | * |
945 | * Locking: - The caller must have locked the runlist (for reading or writing). | 945 | * Locking: - The caller must have locked the runlist (for reading or writing). |
946 | * - This function does not touch the lock. | 946 | * - This function does not touch the lock, nor does it modify the |
947 | * runlist. | ||
947 | */ | 948 | */ |
948 | LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) | 949 | LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) |
949 | { | 950 | { |
diff --git a/fs/ntfs/runlist.h b/fs/ntfs/runlist.h index 7107fde59df9..60c42f3a3fc4 100644 --- a/fs/ntfs/runlist.h +++ b/fs/ntfs/runlist.h | |||
@@ -66,6 +66,8 @@ typedef enum { | |||
66 | LCN_HOLE = -1, /* Keep this as highest value or die! */ | 66 | LCN_HOLE = -1, /* Keep this as highest value or die! */ |
67 | LCN_RL_NOT_MAPPED = -2, | 67 | LCN_RL_NOT_MAPPED = -2, |
68 | LCN_ENOENT = -3, | 68 | LCN_ENOENT = -3, |
69 | LCN_ENOMEM = -4, | ||
70 | LCN_EIO = -5, | ||
69 | } LCN_SPECIAL_VALUES; | 71 | } LCN_SPECIAL_VALUES; |
70 | 72 | ||
71 | extern runlist_element *ntfs_runlists_merge(runlist_element *drl, | 73 | extern runlist_element *ntfs_runlists_merge(runlist_element *drl, |