xfs: don't take the MMAPLOCK when scrubbing file metadata
authorDarrick J. Wong <djwong@kernel.org>
Wed, 12 Apr 2023 02:00:22 +0000 (19:00 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 12 Apr 2023 02:00:22 +0000 (19:00 -0700)
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>
fs/xfs/scrub/bmap.c
fs/xfs/scrub/common.c
fs/xfs/scrub/inode.c

index 9cf66a5..e485a54 100644 (file)
@@ -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));
 
                /*
index b3ba87c..9aa7966 100644 (file)
@@ -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;
index 74ded77..3e1e02e 100644 (file)
@@ -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);