diff options
author | Darrick J. Wong <djwong@kernel.org> | 2023-04-11 19:00:22 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2023-04-11 19:00:22 -0700 |
commit | 1fc7a0597d237c17b6501f8c33b76d3eaaae9079 (patch) | |
tree | 0a255759b7315e807bc225c5c3be2bc7ffc17394 | |
parent | 38bb13108479f5cac955bb291ea6aa6d24268f4f (diff) | |
download | lwn-1fc7a0597d237c17b6501f8c33b76d3eaaae9079.tar.gz lwn-1fc7a0597d237c17b6501f8c33b76d3eaaae9079.zip |
xfs: don't take the MMAPLOCK when scrubbing file metadata
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.c | 7 | ||||
-rw-r--r-- | fs/xfs/scrub/common.c | 11 | ||||
-rw-r--r-- | fs/xfs/scrub/inode.c | 2 |
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); |