summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r--fs/xfs/xfs_icache.c17
1 files changed, 12 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;
}