aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_mount.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-04-23 01:58:34 -0400
committerBen Myers <bpm@sgi.com>2012-05-14 17:20:27 -0400
commit211e4d434bd737be38aabad0247ce3da9964370e (patch)
tree6fb654a566507d302ff5672c2e66fb775ca3c6cd /fs/xfs/xfs_mount.c
parent1c30462542bac8abffb4823638b6b1659c1cfcf5 (diff)
xfs: implement freezing by emptying the AIL
Now that we write back all metadata either synchronously or through the AIL we can simply implement metadata freezing in terms of emptying the AIL. The implementation for this is fairly simply and straight-forward: A new routine is added that asks the xfsaild to push the AIL to the end and waits for it to complete and send a wakeup. The routine will then loop if the AIL is not actually empty, and continue to do so until the AIL is compeltely empty. We keep an inode reclaim pass in the freeze process to avoid having memory pressure have to reclaim inodes that require dirtying the filesystem to be reclaimed after the freeze has completed. This means we can also treat unmount in the exact same way as freeze. As an upside we can now remove the radix tree based inode writeback and xfs_unmountfs_writesb. [ Dave Chinner: - Cleaned up commit message. - Added inode reclaim passes back into freeze. - Cleaned up wakeup mechanism to avoid the use of a new sleep counter variable. ] Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r--fs/xfs/xfs_mount.c56
1 files changed, 12 insertions, 44 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 1ffead4b2296..385a3b11d3dd 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -22,6 +22,7 @@
22#include "xfs_log.h" 22#include "xfs_log.h"
23#include "xfs_inum.h" 23#include "xfs_inum.h"
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_trans_priv.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_dir2.h" 28#include "xfs_dir2.h"
@@ -1475,15 +1476,15 @@ xfs_unmountfs(
1475 xfs_log_force(mp, XFS_LOG_SYNC); 1476 xfs_log_force(mp, XFS_LOG_SYNC);
1476 1477
1477 /* 1478 /*
1478 * Do a delwri reclaim pass first so that as many dirty inodes are 1479 * Flush all pending changes from the AIL.
1479 * queued up for IO as possible. Then flush the buffers before making 1480 */
1480 * a synchronous path to catch all the remaining inodes are reclaimed. 1481 xfs_ail_push_all_sync(mp->m_ail);
1481 * This makes the reclaim process as quick as possible by avoiding 1482
1482 * synchronous writeout and blocking on inodes already in the delwri 1483 /*
1483 * state as much as possible. 1484 * And reclaim all inodes. At this point there should be no dirty
1485 * inode, and none should be pinned or locked, but use synchronous
1486 * reclaim just to be sure.
1484 */ 1487 */
1485 xfs_reclaim_inodes(mp, 0);
1486 xfs_flush_buftarg(mp->m_ddev_targp, 1);
1487 xfs_reclaim_inodes(mp, SYNC_WAIT); 1488 xfs_reclaim_inodes(mp, SYNC_WAIT);
1488 1489
1489 xfs_qm_unmount(mp); 1490 xfs_qm_unmount(mp);
@@ -1519,15 +1520,12 @@ xfs_unmountfs(
1519 if (error) 1520 if (error)
1520 xfs_warn(mp, "Unable to update superblock counters. " 1521 xfs_warn(mp, "Unable to update superblock counters. "
1521 "Freespace may not be correct on next mount."); 1522 "Freespace may not be correct on next mount.");
1522 xfs_unmountfs_writesb(mp);
1523 1523
1524 /* 1524 /*
1525 * Make sure all buffers have been flushed and completed before 1525 * At this point we might have modified the superblock again and thus
1526 * unmounting the log. 1526 * added an item to the AIL, thus flush it again.
1527 */ 1527 */
1528 error = xfs_flush_buftarg(mp->m_ddev_targp, 1); 1528 xfs_ail_push_all_sync(mp->m_ail);
1529 if (error)
1530 xfs_warn(mp, "%d busy buffers during unmount.", error);
1531 xfs_wait_buftarg(mp->m_ddev_targp); 1529 xfs_wait_buftarg(mp->m_ddev_targp);
1532 1530
1533 xfs_log_unmount_write(mp); 1531 xfs_log_unmount_write(mp);
@@ -1588,36 +1586,6 @@ xfs_log_sbcount(xfs_mount_t *mp)
1588 return error; 1586 return error;
1589} 1587}
1590 1588
1591int
1592xfs_unmountfs_writesb(xfs_mount_t *mp)
1593{
1594 xfs_buf_t *sbp;
1595 int error = 0;
1596
1597 /*
1598 * skip superblock write if fs is read-only, or
1599 * if we are doing a forced umount.
1600 */
1601 if (!((mp->m_flags & XFS_MOUNT_RDONLY) ||
1602 XFS_FORCED_SHUTDOWN(mp))) {
1603
1604 sbp = xfs_getsb(mp, 0);
1605
1606 XFS_BUF_UNDONE(sbp);
1607 XFS_BUF_UNREAD(sbp);
1608 xfs_buf_delwri_dequeue(sbp);
1609 XFS_BUF_WRITE(sbp);
1610 XFS_BUF_UNASYNC(sbp);
1611 ASSERT(sbp->b_target == mp->m_ddev_targp);
1612 xfsbdstrat(mp, sbp);
1613 error = xfs_buf_iowait(sbp);
1614 if (error)
1615 xfs_buf_ioerror_alert(sbp, __func__);
1616 xfs_buf_relse(sbp);
1617 }
1618 return error;
1619}
1620
1621/* 1589/*
1622 * xfs_mod_sb() can be used to copy arbitrary changes to the 1590 * xfs_mod_sb() can be used to copy arbitrary changes to the
1623 * in-core superblock into the superblock buffer to be logged. 1591 * in-core superblock into the superblock buffer to be logged.