xfs: fix deadlock in xfs_rtfree_extent
authorKamal Dasu <kdasu.kdev@gmail.com>
Thu, 23 Feb 2012 00:41:39 +0000 (00:41 +0000)
committerBen Myers <bpm@sgi.com>
Thu, 22 Mar 2012 20:31:06 +0000 (15:31 -0500)
To fix the deadlock caused by repeatedly calling xfs_rtfree_extent

 - removed xfs_ilock() and xfs_trans_ijoin() from xfs_rtfree_extent(),
   instead added asserts that the inode is locked and has an inode_item
   attached to it.
 - in xfs_bunmapi() when dealing with an inode with the rt flag
   call xfs_ilock() and xfs_trans_ijoin() so that the
   reference count is bumped on the inode and attached it to the
   transaction before calling into xfs_bmap_del_extent, similar to
   what we do in xfs_bmap_rtalloc.

Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
Reviewed-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Ben Myers <bpm@sgi.com>
fs/xfs/xfs_bmap.c
fs/xfs/xfs_rtalloc.c

index 3548c6f..85e7e32 100644 (file)
@@ -5124,6 +5124,15 @@ xfs_bunmapi(
                cur->bc_private.b.flags = 0;
        } else
                cur = NULL;
+
+       if (isrt) {
+               /*
+                * Synchronize by locking the bitmap inode.
+                */
+               xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+               xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+       }
+
        extno = 0;
        while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
               (nexts == 0 || extno < nexts)) {
index 87323f1..ca4f315 100644 (file)
@@ -183,6 +183,7 @@ error_cancel:
                oblocks = map.br_startoff + map.br_blockcount;
        }
        return 0;
+
 error:
        return error;
 }
@@ -2139,11 +2140,9 @@ xfs_rtfree_extent(
        xfs_buf_t       *sumbp;         /* summary file block buffer */
 
        mp = tp->t_mountp;
-       /*
-        * Synchronize by locking the bitmap inode.
-        */
-       xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
-       xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+
+       ASSERT(mp->m_rbmip->i_itemp != NULL);
+       ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
 
 #if defined(__KERNEL__) && defined(DEBUG)
        /*