aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ntfs/ChangeLog5
-rw-r--r--fs/ntfs/attrib.c29
-rw-r--r--fs/ntfs/attrib.h4
-rw-r--r--fs/ntfs/lcnalloc.c4
-rw-r--r--fs/ntfs/mft.c6
-rw-r--r--fs/ntfs/runlist.c15
-rw-r--r--fs/ntfs/runlist.h2
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
962.1.22 - Many bug and race fixes and error handling improvements. 1012.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 */
230runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, 229runlist_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);
66extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn, 66extern 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
69extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, 69extern 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
72int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, 72int 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 */
948LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) 949LCN 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
71extern runlist_element *ntfs_runlists_merge(runlist_element *drl, 73extern runlist_element *ntfs_runlists_merge(runlist_element *drl,