Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 516b2e7c authored by David Chinner's avatar David Chinner Committed by Tim Shimmin
Browse files

[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: default avatarDavid Chinner <dgc@sgi.com>
Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarTim Shimmin <tes@sgi.com>
parent 957d0ebe
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -664,7 +664,7 @@ xfs_fs_sync_super(
		 * occur here so don't bother flushing the buftarg (i.e
		 * SYNC_QUIESCE) because it'll just get dirty again.
		 */
		flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT;
		flags = SYNC_DATA_QUIESCE;
	} else
		flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);

+14 −0
Original line number Diff line number Diff line
@@ -94,6 +94,20 @@ typedef enum {
#define SYNC_IOWAIT		0x0100  /* wait for all I/O to complete */
#define SYNC_SUPER		0x0200  /* flush superblock to disk */

/*
 * When remounting a filesystem read-only or freezing the filesystem,
 * we have two phases to execute. This first phase is syncing the data
 * before we quiesce the fielsystem, and the second is flushing all the
 * inodes out after we've waited for all the transactions created by
 * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
 * to ensure that the inodes are written to their location on disk
 * rather than just existing in transactions in the log. This means
 * after a quiesce there is no log replay required to write the inodes
 * to disk (this is the main difference between a sync and a quiesce).
 */
#define SYNC_DATA_QUIESCE	(SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
#define SYNC_INODE_QUIESCE	(SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)

#define SHUTDOWN_META_IO_ERROR	0x0001	/* write attempt to metadata failed */
#define SHUTDOWN_LOG_IO_ERROR	0x0002	/* write attempt to the log failed */
#define SHUTDOWN_FORCE_UMOUNT	0x0004	/* shutdown from a forced unmount */
+31 −22
Original line number Diff line number Diff line
@@ -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);
}