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.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 3d0ba8e60adc..ac9ff39aa834 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -948,20 +948,23 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
948 na.name_len = 0; 948 na.name_len = 0;
949 na.type = AT_UNUSED; 949 na.type = AT_UNUSED;
950 /* 950 /*
951 * For inode 0, i.e. $MFT itself, we cannot use ilookup5() from here or 951 * Optimize inode 0, i.e. $MFT itself, since we have it in memory and
952 * we deadlock because the inode is already locked by the kernel 952 * we get here for it rather often.
953 * (fs/fs-writeback.c::__sync_single_inode()) and ilookup5() waits
954 * until the inode is unlocked before returning it and it never gets
955 * unlocked because ntfs_should_write_mft_record() never returns. )-:
956 * Fortunately, we have inode 0 pinned in icache for the duration of
957 * the mount so we can access it directly.
958 */ 953 */
959 if (!mft_no) { 954 if (!mft_no) {
960 /* Balance the below iput(). */ 955 /* Balance the below iput(). */
961 vi = igrab(mft_vi); 956 vi = igrab(mft_vi);
962 BUG_ON(vi != mft_vi); 957 BUG_ON(vi != mft_vi);
963 } else 958 } else {
964 vi = ilookup5(sb, mft_no, (test_t)ntfs_test_inode, &na); 959 /*
960 * Have to use ilookup5_nowait() since ilookup5() waits for the
961 * inode lock which causes ntfs to deadlock when a concurrent
962 * inode write via the inode dirty code paths and the page
963 * dirty code path of the inode dirty code path when writing
964 * $MFT occurs.
965 */
966 vi = ilookup5_nowait(sb, mft_no, (test_t)ntfs_test_inode, &na);
967 }
965 if (vi) { 968 if (vi) {
966 ntfs_debug("Base inode 0x%lx is in icache.", mft_no); 969 ntfs_debug("Base inode 0x%lx is in icache.", mft_no);
967 /* The inode is in icache. */ 970 /* The inode is in icache. */
@@ -1016,7 +1019,13 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
1016 na.mft_no = MREF_LE(m->base_mft_record); 1019 na.mft_no = MREF_LE(m->base_mft_record);
1017 ntfs_debug("Mft record 0x%lx is an extent record. Looking for base " 1020 ntfs_debug("Mft record 0x%lx is an extent record. Looking for base "
1018 "inode 0x%lx in icache.", mft_no, na.mft_no); 1021 "inode 0x%lx in icache.", mft_no, na.mft_no);
1019 vi = ilookup5(sb, na.mft_no, (test_t)ntfs_test_inode, &na); 1022 if (!na.mft_no) {
1023 /* Balance the below iput(). */
1024 vi = igrab(mft_vi);
1025 BUG_ON(vi != mft_vi);
1026 } else
1027 vi = ilookup5_nowait(sb, na.mft_no, (test_t)ntfs_test_inode,
1028 &na);
1020 if (!vi) { 1029 if (!vi) {
1021 /* 1030 /*
1022 * The base inode is not in icache, write this extent mft 1031 * The base inode is not in icache, write this extent mft