aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2007-06-18 02:50:17 -0400
committerTim Shimmin <tes@chook.melbourne.sgi.com>2007-07-14 01:33:38 -0400
commit641c56fbfeae85d5ec87fee90a752f7b7224f236 (patch)
treec626d0f48ef54031f3af502e75308c9087e4592f /fs/xfs
parent0164af51cedf46e1d58fd53854373f544150c597 (diff)
[XFS] Prevent deadlock when flushing inodes on unmount
When we are unmounting the filesystem, we flush all the inodes to disk. Unfortunately, if we have an inode cluster that has just been freed and marked stale sitting in an incore log buffer (i.e. hasn't been flushed to disk), it will be holding all the flush locks on the inodes in that cluster. xfs_iflush_all() which is called during unmount walks all the inodes trying to reclaim them, and it doing so calls xfs_finish_reclaim() on each inode. If the inode is dirty, if grabs the flush lock and flushes it. Unfortunately, find dirty inodes that already have their flush lock held and so we sleep. At this point in the unmount process, we are running single-threaded. There is nothing more that can push on the log to force the transaction holding the inode flush locks to disk and hence we deadlock. The fix is to issue a log force before flushing the inodes on unmount so that all the flush locks will be released before we start flushing the inodes. SGI-PV: 964538 SGI-Modid: xfs-linux-melb:xfs-kern:28862a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_mount.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index f6fe47d8c4dc..39cf6f3267c3 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1182,6 +1182,17 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1182 int64_t fsid; 1182 int64_t fsid;
1183#endif 1183#endif
1184 1184
1185 /*
1186 * We can potentially deadlock here if we have an inode cluster
1187 * that has been freed has it's buffer still pinned in memory because
1188 * the transaction is still sitting in a iclog. The stale inodes
1189 * on that buffer will have their flush locks held until the
1190 * transaction hits the disk and the callbacks run. the inode
1191 * flush takes the flush lock unconditionally and with nothing to
1192 * push out the iclog we will never get that unlocked. hence we
1193 * need to force the log first.
1194 */
1195 xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
1185 xfs_iflush_all(mp); 1196 xfs_iflush_all(mp);
1186 1197
1187 XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); 1198 XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);