summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2023-04-11 19:00:22 -0700
committerDarrick J. Wong <djwong@kernel.org>2023-04-11 19:00:22 -0700
commit1fc7a0597d237c17b6501f8c33b76d3eaaae9079 (patch)
tree0a255759b7315e807bc225c5c3be2bc7ffc17394
parent38bb13108479f5cac955bb291ea6aa6d24268f4f (diff)
xfs: don't take the MMAPLOCK when scrubbing file metadatascrub-iget-fixes-6.4_2023-04-12scrub-iget-fixes-6.4_2023-04-11
The MMAPLOCK stabilizes mappings in a file's pagecache. Therefore, we do not need it to check directories, symlinks, extended attributes, or file-based metadata. Reduce its usage to the one case that requires it, which is when we want to scrub the data fork of a regular file. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
-rw-r--r--fs/xfs/scrub/bmap.c7
-rw-r--r--fs/xfs/scrub/common.c11
-rw-r--r--fs/xfs/scrub/inode.c2
3 files changed, 14 insertions, 6 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 9cf66a5c2376..e485a546a758 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -38,8 +38,8 @@ xchk_setup_inode_bmap(
if (error)
goto out;
- sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
- xfs_ilock(sc->ip, sc->ilock_flags);
+ sc->ilock_flags = XFS_IOLOCK_EXCL;
+ xfs_ilock(sc->ip, XFS_IOLOCK_EXCL);
/*
* We don't want any ephemeral data fork updates sitting around
@@ -50,6 +50,9 @@ xchk_setup_inode_bmap(
sc->sm->sm_type == XFS_SCRUB_TYPE_BMBTD) {
struct address_space *mapping = VFS_I(sc->ip)->i_mapping;
+ sc->ilock_flags |= XFS_MMAPLOCK_EXCL;
+ xfs_ilock(sc->ip, XFS_MMAPLOCK_EXCL);
+
inode_dio_wait(VFS_I(sc->ip));
/*
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index b3ba87c4bc79..9aa79665c608 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -988,7 +988,11 @@ xchk_irele(
xfs_irele(ip);
}
-/* Set us up to scrub a file's contents. */
+/*
+ * Set us up to scrub metadata mapped by a file's fork. Callers must not use
+ * this to operate on user-accessible regular file data because the MMAPLOCK is
+ * not taken.
+ */
int
xchk_setup_inode_contents(
struct xfs_scrub *sc,
@@ -1000,9 +1004,10 @@ xchk_setup_inode_contents(
if (error)
return error;
- /* Got the inode, lock it and we're ready to go. */
- sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
+ /* Lock the inode so the VFS cannot touch this file. */
+ sc->ilock_flags = XFS_IOLOCK_EXCL;
xfs_ilock(sc->ip, sc->ilock_flags);
+
error = xchk_trans_alloc(sc, resblks);
if (error)
goto out;
diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index 74ded772cb8f..3e1e02e340a6 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -32,7 +32,7 @@ xchk_prepare_iscrub(
{
int error;
- sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
+ sc->ilock_flags = XFS_IOLOCK_EXCL;
xfs_ilock(sc->ip, sc->ilock_flags);
error = xchk_trans_alloc(sc, 0);