]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ntfs/mft.c
Pull sim-fixes into release branch
[linux-2.6-omap-h63xx.git] / fs / ntfs / mft.c
index 61ce09f1b6523a4ee57761039aa1e90b717b31a2..2c32b84385a8f693bef3130b9fd5ee32b224c966 100644 (file)
@@ -511,7 +511,6 @@ int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no,
                } while (bh);
                tail->b_this_page = head;
                attach_page_buffers(page, head);
-               BUG_ON(!page_has_buffers(page));
        }
        bh = head = page_buffers(page);
        BUG_ON(!bh);
@@ -533,6 +532,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);
@@ -691,7 +691,6 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
         */
        if (!NInoTestClearDirty(ni))
                goto done;
-       BUG_ON(!page_has_buffers(page));
        bh = head = page_buffers(page);
        BUG_ON(!bh);
        rl = NULL;
@@ -725,6 +724,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 +948,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 +1019,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 +1416,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 +1450,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 +1538,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 +1847,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 +1886,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.");
@@ -1944,7 +1953,7 @@ restore_undo_alloc:
        a = ctx->attr;
        a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1);
 undo_alloc:
-       if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1) < 0) {
+       if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1, TRUE) < 0) {
                ntfs_error(vol->sb, "Failed to free clusters from mft data "
                                "attribute.%s", es);
                NVolSetErrors(vol);
@@ -1959,7 +1968,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);