summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Foster2012-06-11 16:39:43 +0200
committerBen Myers2012-06-21 17:53:43 +0200
commit76e8f1386673b864cfca3c24c4d5814740e76465 (patch)
treed40ff79f2b5800c6dcbb3670c6a81b61719575a4
parentxfs: fix typo in comment of xfs_dinode_t. (diff)
downloadkernel-qcow2-linux-76e8f1386673b864cfca3c24c4d5814740e76465.tar.gz
kernel-qcow2-linux-76e8f1386673b864cfca3c24c4d5814740e76465.tar.xz
kernel-qcow2-linux-76e8f1386673b864cfca3c24c4d5814740e76465.zip
xfs: check for stale inode before acquiring iflock on push
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 <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_inode_item.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 6cdbf90c6f7b..d041d47d9d86 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -505,6 +505,14 @@ xfs_inode_item_push(
}
/*
+ * Stale inode items should force out the iclog.
+ */
+ if (ip->i_flags & XFS_ISTALE) {
+ rval = XFS_ITEM_PINNED;
+ goto out_unlock;
+ }
+
+ /*
* Someone else is already flushing the inode. Nothing we can do
* here but wait for the flush to finish and remove the item from
* the AIL.
@@ -514,15 +522,6 @@ xfs_inode_item_push(
goto out_unlock;
}
- /*
- * Stale inode items should force out the iclog.
- */
- if (ip->i_flags & XFS_ISTALE) {
- xfs_ifunlock(ip);
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
- return XFS_ITEM_PINNED;
- }
-
ASSERT(iip->ili_fields != 0 || XFS_FORCED_SHUTDOWN(ip->i_mount));
ASSERT(iip->ili_logged == 0 || XFS_FORCED_SHUTDOWN(ip->i_mount));