aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/mft.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs/mft.c')
-rw-r--r--fs/ntfs/mft.c68
1 files changed, 33 insertions, 35 deletions
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 6499aafc2258..4e72bc7afdf9 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -93,6 +93,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
93 "Run chkdsk.", ni->mft_no); 93 "Run chkdsk.", ni->mft_no);
94 ntfs_unmap_page(page); 94 ntfs_unmap_page(page);
95 page = ERR_PTR(-EIO); 95 page = ERR_PTR(-EIO);
96 NVolSetErrors(vol);
96 } 97 }
97err_out: 98err_out:
98 ni->page = NULL; 99 ni->page = NULL;
@@ -104,8 +105,8 @@ err_out:
104 * map_mft_record - map, pin and lock an mft record 105 * map_mft_record - map, pin and lock an mft record
105 * @ni: ntfs inode whose MFT record to map 106 * @ni: ntfs inode whose MFT record to map
106 * 107 *
107 * First, take the mrec_lock semaphore. We might now be sleeping, while waiting 108 * First, take the mrec_lock mutex. We might now be sleeping, while waiting
108 * for the semaphore if it was already locked by someone else. 109 * for the mutex if it was already locked by someone else.
109 * 110 *
110 * The page of the record is mapped using map_mft_record_page() before being 111 * The page of the record is mapped using map_mft_record_page() before being
111 * returned to the caller. 112 * returned to the caller.
@@ -135,9 +136,9 @@ err_out:
135 * So that code will end up having to own the mrec_lock of all mft 136 * So that code will end up having to own the mrec_lock of all mft
136 * records/inodes present in the page before I/O can proceed. In that case we 137 * records/inodes present in the page before I/O can proceed. In that case we
137 * wouldn't need to bother with PG_locked and PG_uptodate as nobody will be 138 * wouldn't need to bother with PG_locked and PG_uptodate as nobody will be
138 * accessing anything without owning the mrec_lock semaphore. But we do need 139 * accessing anything without owning the mrec_lock mutex. But we do need to
139 * to use them because of the read_cache_page() invocation and the code becomes 140 * use them because of the read_cache_page() invocation and the code becomes so
140 * so much simpler this way that it is well worth it. 141 * much simpler this way that it is well worth it.
141 * 142 *
142 * The mft record is now ours and we return a pointer to it. You need to check 143 * The mft record is now ours and we return a pointer to it. You need to check
143 * the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return 144 * the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return
@@ -160,13 +161,13 @@ MFT_RECORD *map_mft_record(ntfs_inode *ni)
160 atomic_inc(&ni->count); 161 atomic_inc(&ni->count);
161 162
162 /* Serialize access to this mft record. */ 163 /* Serialize access to this mft record. */
163 down(&ni->mrec_lock); 164 mutex_lock(&ni->mrec_lock);
164 165
165 m = map_mft_record_page(ni); 166 m = map_mft_record_page(ni);
166 if (likely(!IS_ERR(m))) 167 if (likely(!IS_ERR(m)))
167 return m; 168 return m;
168 169
169 up(&ni->mrec_lock); 170 mutex_unlock(&ni->mrec_lock);
170 atomic_dec(&ni->count); 171 atomic_dec(&ni->count);
171 ntfs_error(ni->vol->sb, "Failed with error code %lu.", -PTR_ERR(m)); 172 ntfs_error(ni->vol->sb, "Failed with error code %lu.", -PTR_ERR(m));
172 return m; 173 return m;
@@ -217,7 +218,7 @@ void unmap_mft_record(ntfs_inode *ni)
217 ntfs_debug("Entering for mft_no 0x%lx.", ni->mft_no); 218 ntfs_debug("Entering for mft_no 0x%lx.", ni->mft_no);
218 219
219 unmap_mft_record_page(ni); 220 unmap_mft_record_page(ni);
220 up(&ni->mrec_lock); 221 mutex_unlock(&ni->mrec_lock);
221 atomic_dec(&ni->count); 222 atomic_dec(&ni->count);
222 /* 223 /*
223 * If pure ntfs_inode, i.e. no vfs inode attached, we leave it to 224 * If pure ntfs_inode, i.e. no vfs inode attached, we leave it to
@@ -261,7 +262,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
261 * in which case just return it. If not found, add it to the base 262 * in which case just return it. If not found, add it to the base
262 * inode before returning it. 263 * inode before returning it.
263 */ 264 */
264 down(&base_ni->extent_lock); 265 mutex_lock(&base_ni->extent_lock);
265 if (base_ni->nr_extents > 0) { 266 if (base_ni->nr_extents > 0) {
266 extent_nis = base_ni->ext.extent_ntfs_inos; 267 extent_nis = base_ni->ext.extent_ntfs_inos;
267 for (i = 0; i < base_ni->nr_extents; i++) { 268 for (i = 0; i < base_ni->nr_extents; i++) {
@@ -274,7 +275,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
274 } 275 }
275 } 276 }
276 if (likely(ni != NULL)) { 277 if (likely(ni != NULL)) {
277 up(&base_ni->extent_lock); 278 mutex_unlock(&base_ni->extent_lock);
278 atomic_dec(&base_ni->count); 279 atomic_dec(&base_ni->count);
279 /* We found the record; just have to map and return it. */ 280 /* We found the record; just have to map and return it. */
280 m = map_mft_record(ni); 281 m = map_mft_record(ni);
@@ -301,7 +302,7 @@ map_err_out:
301 /* Record wasn't there. Get a new ntfs inode and initialize it. */ 302 /* Record wasn't there. Get a new ntfs inode and initialize it. */
302 ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no); 303 ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no);
303 if (unlikely(!ni)) { 304 if (unlikely(!ni)) {
304 up(&base_ni->extent_lock); 305 mutex_unlock(&base_ni->extent_lock);
305 atomic_dec(&base_ni->count); 306 atomic_dec(&base_ni->count);
306 return ERR_PTR(-ENOMEM); 307 return ERR_PTR(-ENOMEM);
307 } 308 }
@@ -312,7 +313,7 @@ map_err_out:
312 /* Now map the record. */ 313 /* Now map the record. */
313 m = map_mft_record(ni); 314 m = map_mft_record(ni);
314 if (IS_ERR(m)) { 315 if (IS_ERR(m)) {
315 up(&base_ni->extent_lock); 316 mutex_unlock(&base_ni->extent_lock);
316 atomic_dec(&base_ni->count); 317 atomic_dec(&base_ni->count);
317 ntfs_clear_extent_inode(ni); 318 ntfs_clear_extent_inode(ni);
318 goto map_err_out; 319 goto map_err_out;
@@ -347,14 +348,14 @@ map_err_out:
347 base_ni->ext.extent_ntfs_inos = tmp; 348 base_ni->ext.extent_ntfs_inos = tmp;
348 } 349 }
349 base_ni->ext.extent_ntfs_inos[base_ni->nr_extents++] = ni; 350 base_ni->ext.extent_ntfs_inos[base_ni->nr_extents++] = ni;
350 up(&base_ni->extent_lock); 351 mutex_unlock(&base_ni->extent_lock);
351 atomic_dec(&base_ni->count); 352 atomic_dec(&base_ni->count);
352 ntfs_debug("Done 2."); 353 ntfs_debug("Done 2.");
353 *ntfs_ino = ni; 354 *ntfs_ino = ni;
354 return m; 355 return m;
355unm_err_out: 356unm_err_out:
356 unmap_mft_record(ni); 357 unmap_mft_record(ni);
357 up(&base_ni->extent_lock); 358 mutex_unlock(&base_ni->extent_lock);
358 atomic_dec(&base_ni->count); 359 atomic_dec(&base_ni->count);
359 /* 360 /*
360 * If the extent inode was not attached to the base inode we need to 361 * If the extent inode was not attached to the base inode we need to
@@ -399,12 +400,12 @@ void __mark_mft_record_dirty(ntfs_inode *ni)
399 BUG_ON(NInoAttr(ni)); 400 BUG_ON(NInoAttr(ni));
400 mark_ntfs_record_dirty(ni->page, ni->page_ofs); 401 mark_ntfs_record_dirty(ni->page, ni->page_ofs);
401 /* Determine the base vfs inode and mark it dirty, too. */ 402 /* Determine the base vfs inode and mark it dirty, too. */
402 down(&ni->extent_lock); 403 mutex_lock(&ni->extent_lock);
403 if (likely(ni->nr_extents >= 0)) 404 if (likely(ni->nr_extents >= 0))
404 base_ni = ni; 405 base_ni = ni;
405 else 406 else
406 base_ni = ni->ext.base_ntfs_ino; 407 base_ni = ni->ext.base_ntfs_ino;
407 up(&ni->extent_lock); 408 mutex_unlock(&ni->extent_lock);
408 __mark_inode_dirty(VFS_I(base_ni), I_DIRTY_SYNC | I_DIRTY_DATASYNC); 409 __mark_inode_dirty(VFS_I(base_ni), I_DIRTY_SYNC | I_DIRTY_DATASYNC);
409} 410}
410 411
@@ -650,10 +651,7 @@ err_out:
650 * fs/ntfs/aops.c::mark_ntfs_record_dirty(). 651 * fs/ntfs/aops.c::mark_ntfs_record_dirty().
651 * 652 *
652 * On success, clean the mft record and return 0. On error, leave the mft 653 * On success, clean the mft record and return 0. On error, leave the mft
653 * record dirty and return -errno. The caller should call make_bad_inode() on 654 * record dirty and return -errno.
654 * the base inode to ensure no more access happens to this inode. We do not do
655 * it here as the caller may want to finish writing other extent mft records
656 * first to minimize on-disk metadata inconsistencies.
657 * 655 *
658 * NOTE: We always perform synchronous i/o and ignore the @sync parameter. 656 * NOTE: We always perform synchronous i/o and ignore the @sync parameter.
659 * However, if the mft record has a counterpart in the mft mirror and @sync is 657 * However, if the mft record has a counterpart in the mft mirror and @sync is
@@ -983,7 +981,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
983 } 981 }
984 ntfs_debug("Inode 0x%lx is not dirty.", mft_no); 982 ntfs_debug("Inode 0x%lx is not dirty.", mft_no);
985 /* The inode is not dirty, try to take the mft record lock. */ 983 /* The inode is not dirty, try to take the mft record lock. */
986 if (unlikely(down_trylock(&ni->mrec_lock))) { 984 if (unlikely(!mutex_trylock(&ni->mrec_lock))) {
987 ntfs_debug("Mft record 0x%lx is already locked, do " 985 ntfs_debug("Mft record 0x%lx is already locked, do "
988 "not write it.", mft_no); 986 "not write it.", mft_no);
989 atomic_dec(&ni->count); 987 atomic_dec(&ni->count);
@@ -1043,13 +1041,13 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
1043 * corresponding to this extent mft record attached. 1041 * corresponding to this extent mft record attached.
1044 */ 1042 */
1045 ni = NTFS_I(vi); 1043 ni = NTFS_I(vi);
1046 down(&ni->extent_lock); 1044 mutex_lock(&ni->extent_lock);
1047 if (ni->nr_extents <= 0) { 1045 if (ni->nr_extents <= 0) {
1048 /* 1046 /*
1049 * The base inode has no attached extent inodes, write this 1047 * The base inode has no attached extent inodes, write this
1050 * extent mft record. 1048 * extent mft record.
1051 */ 1049 */
1052 up(&ni->extent_lock); 1050 mutex_unlock(&ni->extent_lock);
1053 iput(vi); 1051 iput(vi);
1054 ntfs_debug("Base inode 0x%lx has no attached extent inodes, " 1052 ntfs_debug("Base inode 0x%lx has no attached extent inodes, "
1055 "write the extent record.", na.mft_no); 1053 "write the extent record.", na.mft_no);
@@ -1072,7 +1070,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
1072 * extent mft record. 1070 * extent mft record.
1073 */ 1071 */
1074 if (!eni) { 1072 if (!eni) {
1075 up(&ni->extent_lock); 1073 mutex_unlock(&ni->extent_lock);
1076 iput(vi); 1074 iput(vi);
1077 ntfs_debug("Extent inode 0x%lx is not attached to its base " 1075 ntfs_debug("Extent inode 0x%lx is not attached to its base "
1078 "inode 0x%lx, write the extent record.", 1076 "inode 0x%lx, write the extent record.",
@@ -1083,12 +1081,12 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
1083 mft_no, na.mft_no); 1081 mft_no, na.mft_no);
1084 /* Take a reference to the extent ntfs inode. */ 1082 /* Take a reference to the extent ntfs inode. */
1085 atomic_inc(&eni->count); 1083 atomic_inc(&eni->count);
1086 up(&ni->extent_lock); 1084 mutex_unlock(&ni->extent_lock);
1087 /* 1085 /*
1088 * Found the extent inode coresponding to this extent mft record. 1086 * Found the extent inode coresponding to this extent mft record.
1089 * Try to take the mft record lock. 1087 * Try to take the mft record lock.
1090 */ 1088 */
1091 if (unlikely(down_trylock(&eni->mrec_lock))) { 1089 if (unlikely(!mutex_trylock(&eni->mrec_lock))) {
1092 atomic_dec(&eni->count); 1090 atomic_dec(&eni->count);
1093 iput(vi); 1091 iput(vi);
1094 ntfs_debug("Extent mft record 0x%lx is already locked, do " 1092 ntfs_debug("Extent mft record 0x%lx is already locked, do "
@@ -2711,7 +2709,7 @@ mft_rec_already_initialized:
2711 * have its page mapped and it is very easy to do. 2709 * have its page mapped and it is very easy to do.
2712 */ 2710 */
2713 atomic_inc(&ni->count); 2711 atomic_inc(&ni->count);
2714 down(&ni->mrec_lock); 2712 mutex_lock(&ni->mrec_lock);
2715 ni->page = page; 2713 ni->page = page;
2716 ni->page_ofs = ofs; 2714 ni->page_ofs = ofs;
2717 /* 2715 /*
@@ -2798,22 +2796,22 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m)
2798 BUG_ON(NInoAttr(ni)); 2796 BUG_ON(NInoAttr(ni));
2799 BUG_ON(ni->nr_extents != -1); 2797 BUG_ON(ni->nr_extents != -1);
2800 2798
2801 down(&ni->extent_lock); 2799 mutex_lock(&ni->extent_lock);
2802 base_ni = ni->ext.base_ntfs_ino; 2800 base_ni = ni->ext.base_ntfs_ino;
2803 up(&ni->extent_lock); 2801 mutex_unlock(&ni->extent_lock);
2804 2802
2805 BUG_ON(base_ni->nr_extents <= 0); 2803 BUG_ON(base_ni->nr_extents <= 0);
2806 2804
2807 ntfs_debug("Entering for extent inode 0x%lx, base inode 0x%lx.\n", 2805 ntfs_debug("Entering for extent inode 0x%lx, base inode 0x%lx.\n",
2808 mft_no, base_ni->mft_no); 2806 mft_no, base_ni->mft_no);
2809 2807
2810 down(&base_ni->extent_lock); 2808 mutex_lock(&base_ni->extent_lock);
2811 2809
2812 /* Make sure we are holding the only reference to the extent inode. */ 2810 /* Make sure we are holding the only reference to the extent inode. */
2813 if (atomic_read(&ni->count) > 2) { 2811 if (atomic_read(&ni->count) > 2) {
2814 ntfs_error(vol->sb, "Tried to free busy extent inode 0x%lx, " 2812 ntfs_error(vol->sb, "Tried to free busy extent inode 0x%lx, "
2815 "not freeing.", base_ni->mft_no); 2813 "not freeing.", base_ni->mft_no);
2816 up(&base_ni->extent_lock); 2814 mutex_unlock(&base_ni->extent_lock);
2817 return -EBUSY; 2815 return -EBUSY;
2818 } 2816 }
2819 2817
@@ -2831,7 +2829,7 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m)
2831 break; 2829 break;
2832 } 2830 }
2833 2831
2834 up(&base_ni->extent_lock); 2832 mutex_unlock(&base_ni->extent_lock);
2835 2833
2836 if (unlikely(err)) { 2834 if (unlikely(err)) {
2837 ntfs_error(vol->sb, "Extent inode 0x%lx is not attached to " 2835 ntfs_error(vol->sb, "Extent inode 0x%lx is not attached to "
@@ -2890,7 +2888,7 @@ rollback_error:
2890 return 0; 2888 return 0;
2891rollback: 2889rollback:
2892 /* Rollback what we did... */ 2890 /* Rollback what we did... */
2893 down(&base_ni->extent_lock); 2891 mutex_lock(&base_ni->extent_lock);
2894 extent_nis = base_ni->ext.extent_ntfs_inos; 2892 extent_nis = base_ni->ext.extent_ntfs_inos;
2895 if (!(base_ni->nr_extents & 3)) { 2893 if (!(base_ni->nr_extents & 3)) {
2896 int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode*); 2894 int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode*);
@@ -2899,7 +2897,7 @@ rollback:
2899 if (unlikely(!extent_nis)) { 2897 if (unlikely(!extent_nis)) {
2900 ntfs_error(vol->sb, "Failed to allocate internal " 2898 ntfs_error(vol->sb, "Failed to allocate internal "
2901 "buffer during rollback.%s", es); 2899 "buffer during rollback.%s", es);
2902 up(&base_ni->extent_lock); 2900 mutex_unlock(&base_ni->extent_lock);
2903 NVolSetErrors(vol); 2901 NVolSetErrors(vol);
2904 goto rollback_error; 2902 goto rollback_error;
2905 } 2903 }
@@ -2914,7 +2912,7 @@ rollback:
2914 m->flags |= MFT_RECORD_IN_USE; 2912 m->flags |= MFT_RECORD_IN_USE;
2915 m->sequence_number = old_seq_no; 2913 m->sequence_number = old_seq_no;
2916 extent_nis[base_ni->nr_extents++] = ni; 2914 extent_nis[base_ni->nr_extents++] = ni;
2917 up(&base_ni->extent_lock); 2915 mutex_unlock(&base_ni->extent_lock);
2918 mark_mft_record_dirty(ni); 2916 mark_mft_record_dirty(ni);
2919 return err; 2917 return err;
2920} 2918}