summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-01-16 10:12:06 -0800
committerDarrick J. Wong <darrick.wong@oracle.com>2019-02-04 09:31:22 -0800
commita885a5755ca84d8f2fda51e67b6c7aba0e2cc18a (patch)
tree89f66370cbf2ae1299a685ed0f77f9dd18a51ec5
parent7f38fff3743deb625a3d7429a4792ce5315483d8 (diff)
xfs: free COW staging extents when freezing filesystemfree-cow-on-freeze_2019-02-04
When we're freezing the filesystem, free all the COW staging extents before we shut the log down so that we can minimize the amount of recovery work that will be necessary during the next mount. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/xfs_icache.c17
-rw-r--r--fs/xfs/xfs_super.c18
2 files changed, 30 insertions, 5 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 3457da5b34fb..ba6fba0f5e04 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -2168,6 +2168,7 @@ xfs_inode_free_cowblocks(
void *args)
{
struct xfs_eofblocks *eofb = args;
+ uint lock_mode = 0;
int ret = 0;
if (!xfs_prep_free_cowblocks(ip))
@@ -2176,9 +2177,15 @@ xfs_inode_free_cowblocks(
if (!xfs_inode_matches_eofb(ip, eofb))
return 0;
- /* Free the CoW blocks */
- xfs_ilock(ip, XFS_IOLOCK_EXCL);
- xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
+ /*
+ * Free the CoW blocks. We don't need to lock the inode if we're in
+ * the process of freezing the filesystem because we've already locked
+ * out writes and page faults.
+ */
+ if (ip->i_mount->m_super->s_writers.frozen == SB_UNFROZEN)
+ lock_mode = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
+ if (lock_mode)
+ xfs_ilock(ip, lock_mode);
/*
* Check again, nobody else should be able to dirty blocks or change
@@ -2187,8 +2194,8 @@ xfs_inode_free_cowblocks(
if (xfs_prep_free_cowblocks(ip))
ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, false);
- xfs_iunlock(ip, XFS_MMAPLOCK_EXCL);
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ if (lock_mode)
+ xfs_iunlock(ip, lock_mode);
return ret;
}
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index b234e484fad0..919c6f4b0c22 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1116,6 +1116,24 @@ xfs_fs_sync_fs(
if (!wait)
return 0;
+ /*
+ * If we're in the middle of freezing the filesystem, this is our last
+ * chance to run regular transactions. Clear all the COW staging
+ * extents so that we can freeze the filesystem with as little recovery
+ * work to do at the next mount as possible. It's safe to do this
+ * without locking inodes because the freezer code flushed all the
+ * dirty data from the page cache and locked out writes and page faults.
+ */
+ if (sb->s_writers.frozen == SB_FREEZE_PAGEFAULT) {
+ int error;
+
+ error = xfs_icache_free_cowblocks(mp, NULL);
+ if (error) {
+ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+ return error;
+ }
+ }
+
xfs_log_force(mp, XFS_LOG_SYNC);
if (laptop_mode) {
/*