[XFS] Fix remount,readonly path to flush everything correctly.

The remount readonly path can fail to writeback properly because we still
have active transactions after calling xfs_quiesce_fs(). Further
investigation shows that this path is broken in the same ways that the xfs
freeze path was broken so fix it the same way.

SGI-PV: 964464
SGI-Modid: xfs-linux-melb:xfs-kern:28869a

Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Tim Shimmin <tes@sgi.com>
This commit is contained in:
David Chinner
2007-06-18 16:50:48 +10:00
committed by Tim Shimmin
parent 957d0ebed0
commit 516b2e7c26
3 changed files with 46 additions and 23 deletions

View File

@ -640,7 +640,7 @@ xfs_quiesce_fs(
* we can write the unmount record.
*/
do {
xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL);
xfs_syncsub(mp, SYNC_INODE_QUIESCE, NULL);
pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
if (!pincount) {
delay(50);
@ -651,6 +651,30 @@ xfs_quiesce_fs(
return 0;
}
/*
* Second stage of a quiesce. The data is already synced, now we have to take
* care of the metadata. New transactions are already blocked, so we need to
* wait for any remaining transactions to drain out before proceding.
*/
STATIC void
xfs_attr_quiesce(
xfs_mount_t *mp)
{
/* wait for all modifications to complete */
while (atomic_read(&mp->m_active_trans) > 0)
delay(100);
/* flush inodes and push all remaining buffers out to disk */
xfs_quiesce_fs(mp);
ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
/* Push the superblock and write an unmount record */
xfs_log_sbcount(mp, 1);
xfs_log_unmount_write(mp);
xfs_unmountfs_writesb(mp);
}
STATIC int
xfs_mntupdate(
bhv_desc_t *bdp,
@ -670,11 +694,8 @@ xfs_mntupdate(
mp->m_flags &= ~XFS_MOUNT_BARRIER;
}
} else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */
bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL);
xfs_quiesce_fs(mp);
xfs_log_sbcount(mp, 1);
xfs_log_unmount_write(mp);
xfs_unmountfs_writesb(mp);
bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL);
xfs_attr_quiesce(mp);
vfsp->vfs_flag |= VFS_RDONLY;
}
return 0;
@ -1952,9 +1973,9 @@ xfs_showargs(
}
/*
* Second stage of a freeze. The data is already frozen, now we have to take
* care of the metadata. New transactions are already blocked, so we need to
* wait for any remaining transactions to drain out before proceding.
* Second stage of a freeze. The data is already frozen so we only
* need to take care of themetadata. Once that's done write a dummy
* record to dirty the log in case of a crash while frozen.
*/
STATIC void
xfs_freeze(
@ -1962,19 +1983,7 @@ xfs_freeze(
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
/* wait for all modifications to complete */
while (atomic_read(&mp->m_active_trans) > 0)
delay(100);
/* flush inodes and push all remaining buffers out to disk */
xfs_quiesce_fs(mp);
ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
/* Push the superblock and write an unmount record */
xfs_log_sbcount(mp, 1);
xfs_log_unmount_write(mp);
xfs_unmountfs_writesb(mp);
xfs_attr_quiesce(mp);
xfs_fs_log_dummy(mp);
}