diff options
Diffstat (limited to 'fs/ntfs/mft.c')
-rw-r--r-- | fs/ntfs/mft.c | 68 |
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 | } |
97 | err_out: | 98 | err_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; |
355 | unm_err_out: | 356 | unm_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; |
2891 | rollback: | 2889 | rollback: |
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 | } |