diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-04-23 01:58:34 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-05-14 17:20:27 -0400 |
commit | 211e4d434bd737be38aabad0247ce3da9964370e (patch) | |
tree | 6fb654a566507d302ff5672c2e66fb775ca3c6cd /fs/xfs/xfs_mount.c | |
parent | 1c30462542bac8abffb4823638b6b1659c1cfcf5 (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.c | 56 |
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 | ||
1591 | int | ||
1592 | xfs_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. |