Merge /spare/repo/linux-2.6/
[powerpc.git] / fs / ntfs / mft.c
index 61ce09f..317f7c6 100644 (file)
@@ -533,6 +533,7 @@ int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no,
                        LCN lcn;
                        unsigned int vcn_ofs;
 
+                       bh->b_bdev = vol->sb->s_bdev;
                        /* Obtain the vcn and offset of the current block. */
                        vcn = ((VCN)mft_no << vol->mft_record_size_bits) +
                                        (block_start - m_start);
@@ -725,6 +726,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
                        LCN lcn;
                        unsigned int vcn_ofs;
 
+                       bh->b_bdev = vol->sb->s_bdev;
                        /* Obtain the vcn and offset of the current block. */
                        vcn = ((VCN)ni->mft_no << vol->mft_record_size_bits) +
                                        (block_start - m_start);
@@ -948,20 +950,23 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
        na.name_len = 0;
        na.type = AT_UNUSED;
        /*
-        * For inode 0, i.e. $MFT itself, we cannot use ilookup5() from here or
-        * we deadlock because the inode is already locked by the kernel
-        * (fs/fs-writeback.c::__sync_single_inode()) and ilookup5() waits
-        * until the inode is unlocked before returning it and it never gets
-        * unlocked because ntfs_should_write_mft_record() never returns.  )-:
-        * Fortunately, we have inode 0 pinned in icache for the duration of
-        * the mount so we can access it directly.
+        * Optimize inode 0, i.e. $MFT itself, since we have it in memory and
+        * we get here for it rather often.
         */
        if (!mft_no) {
                /* Balance the below iput(). */
                vi = igrab(mft_vi);
                BUG_ON(vi != mft_vi);
-       } else
-               vi = ilookup5(sb, mft_no, (test_t)ntfs_test_inode, &na);
+       } else {
+               /*
+                * Have to use ilookup5_nowait() since ilookup5() waits for the
+                * inode lock which causes ntfs to deadlock when a concurrent
+                * inode write via the inode dirty code paths and the page
+                * dirty code path of the inode dirty code path when writing
+                * $MFT occurs.
+                */
+               vi = ilookup5_nowait(sb, mft_no, (test_t)ntfs_test_inode, &na);
+       }
        if (vi) {
                ntfs_debug("Base inode 0x%lx is in icache.", mft_no);
                /* The inode is in icache. */
@@ -1016,7 +1021,13 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
        na.mft_no = MREF_LE(m->base_mft_record);
        ntfs_debug("Mft record 0x%lx is an extent record.  Looking for base "
                        "inode 0x%lx in icache.", mft_no, na.mft_no);
-       vi = ilookup5(sb, na.mft_no, (test_t)ntfs_test_inode, &na);
+       if (!na.mft_no) {
+               /* Balance the below iput(). */
+               vi = igrab(mft_vi);
+               BUG_ON(vi != mft_vi);
+       } else
+               vi = ilookup5_nowait(sb, na.mft_no, (test_t)ntfs_test_inode,
+                               &na);
        if (!vi) {
                /*
                 * The base inode is not in icache, write this extent mft
@@ -1407,7 +1418,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
        BUG_ON(ll < rl2->vcn);
        BUG_ON(ll >= rl2->vcn + rl2->length);
        /* Get the size for the new mapping pairs array for this extent. */
-       mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll);
+       mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, -1);
        if (unlikely(mp_size <= 0)) {
                ntfs_error(vol->sb, "Get size for mapping pairs failed for "
                                "mft bitmap attribute extent.");
@@ -1441,7 +1452,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
        /* Generate the mapping pairs array directly into the attr record. */
        ret = ntfs_mapping_pairs_build(vol, (u8*)a +
                        le16_to_cpu(a->data.non_resident.mapping_pairs_offset),
-                       mp_size, rl2, ll, NULL);
+                       mp_size, rl2, ll, -1, NULL);
        if (unlikely(ret)) {
                ntfs_error(vol->sb, "Failed to build mapping pairs array for "
                                "mft bitmap attribute.");
@@ -1529,7 +1540,7 @@ undo_alloc:
                                a->data.non_resident.mapping_pairs_offset),
                                old_alen - le16_to_cpu(
                                a->data.non_resident.mapping_pairs_offset),
-                               rl2, ll, NULL)) {
+                               rl2, ll, -1, NULL)) {
                        ntfs_error(vol->sb, "Failed to restore mapping pairs "
                                        "array.%s", es);
                        NVolSetErrors(vol);
@@ -1838,7 +1849,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
        BUG_ON(ll < rl2->vcn);
        BUG_ON(ll >= rl2->vcn + rl2->length);
        /* Get the size for the new mapping pairs array for this extent. */
-       mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll);
+       mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, -1);
        if (unlikely(mp_size <= 0)) {
                ntfs_error(vol->sb, "Get size for mapping pairs failed for "
                                "mft data attribute extent.");
@@ -1877,7 +1888,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
        /* Generate the mapping pairs array directly into the attr record. */
        ret = ntfs_mapping_pairs_build(vol, (u8*)a +
                        le16_to_cpu(a->data.non_resident.mapping_pairs_offset),
-                       mp_size, rl2, ll, NULL);
+                       mp_size, rl2, ll, -1, NULL);
        if (unlikely(ret)) {
                ntfs_error(vol->sb, "Failed to build mapping pairs array of "
                                "mft data attribute.");
@@ -1959,7 +1970,7 @@ undo_alloc:
                                a->data.non_resident.mapping_pairs_offset),
                                old_alen - le16_to_cpu(
                                a->data.non_resident.mapping_pairs_offset),
-                               rl2, ll, NULL)) {
+                               rl2, ll, -1, NULL)) {
                        ntfs_error(vol->sb, "Failed to restore mapping pairs "
                                        "array.%s", es);
                        NVolSetErrors(vol);