From: Brian Foster <[email protected]>

Upstream commit: 9a3a5dab63461b84213052888bf38a962b22d035

    An inode in the AIL can be flush locked and marked stale if
    a cluster free transaction occurs at the right time. The
    inode item is then marked as flushing, which causes xfsaild
    to spin and leaves the filesystem stalled. This is
    reproduced by running xfstests 273 in a loop for an
    extended period of time.
 
    Check for stale inodes before the flush lock. This marks
    the inode as pinned, leads to a log flush and allows the
    filesystem to proceed.

    Signed-off-by: Brian Foster <[email protected]>
    Reviewed-by: Dave Chinner <[email protected]>
    Reviewed-by: Christoph Hellwig <[email protected]>
    Reviewed-by: Mark Tinguely <[email protected]>
    Signed-off-by: Ben Myers <[email protected]>


---
 fs/xfs/xfs_inode_item.c |   26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

Index: b/fs/xfs/xfs_inode_item.c
===================================================================
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -588,6 +588,21 @@ xfs_inode_item_trylock(
        if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED))
                return XFS_ITEM_LOCKED;
 
+       /*
+        * Re-check the pincount now that we stabilized the value by
+        * taking the ilock.
+        */
+       if (xfs_ipincount(ip) > 0) {
+               xfs_iunlock(ip, XFS_ILOCK_SHARED);
+               return XFS_ITEM_PINNED;
+       }
+
+       /* Stale items should force out the iclog */
+       if (ip->i_flags & XFS_ISTALE) {
+               xfs_iunlock(ip, XFS_ILOCK_SHARED);
+               return XFS_ITEM_PINNED;
+       }
+
        if (!xfs_iflock_nowait(ip)) {
                /*
                 * inode has already been flushed to the backing buffer,
@@ -597,17 +612,6 @@ xfs_inode_item_trylock(
                return XFS_ITEM_PUSHBUF;
        }
 
-       /* Stale items should force out the iclog */
-       if (ip->i_flags & XFS_ISTALE) {
-               xfs_ifunlock(ip);
-               /*
-                * we hold the AIL lock - notify the unlock routine of this
-                * so it doesn't try to get the lock again.
-                */
-               xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY);
-               return XFS_ITEM_PINNED;
-       }
-
 #ifdef DEBUG
        if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
                ASSERT(iip->ili_format.ilf_fields != 0);


--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to