diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-02-04 18:51:58 -0800 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-08-25 22:25:52 -0700 |
commit | 7f70237c4828edb8e96da6a3f69cf943b8c773d6 (patch) | |
tree | 0f3267e1cce845eade2b98ee1f9044018193b9e0 | |
parent | 18c6960dbb452bd154351c74483ee33f3037f993 (diff) |
xfs: get our own reference to inodes that we want to scrub
When we want to scrub a file, get our own reference to the inode
unconditionally. This will make disposal rules simpler in the long run.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r-- | fs/xfs/scrub/common.c | 24 | ||||
-rw-r--r-- | fs/xfs/scrub/common.h | 1 | ||||
-rw-r--r-- | fs/xfs/scrub/quota.c | 6 | ||||
-rw-r--r-- | fs/xfs/scrub/rtbitmap.c | 6 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.c | 6 |
5 files changed, 31 insertions, 12 deletions
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index d40a98507555..9bdd81bca382 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -633,6 +633,24 @@ xchk_checkpoint_log( } /* + * We want to scan the inode that was passed in. Get our own reference to the + * inode to make disposal simpler. The inode had better not be in I_FREEING + * or I_WILL_FREE state! + */ +int +xchk_install_inode( + struct xfs_scrub *sc, + struct xfs_inode *ip) +{ + if (!igrab(VFS_I(ip))) { + xchk_ino_set_corrupt(sc, ip->i_ino); + return -EFSCORRUPTED; + } + sc->ip = ip; + return 0; +} + +/* * Given an inode and the scrub control structure, grab either the * inode referenced in the control structure or the inode passed in. * The inode is not locked. @@ -648,10 +666,8 @@ xchk_get_inode( int error; /* We want to scan the inode we already had opened. */ - if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) { - sc->ip = ip_in; - return 0; - } + if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) + return xchk_install_inode(sc, ip_in); /* Look up the inode, see if the generation number matches. */ if (xfs_internal_inum(mp, sc->sm->sm_ino)) diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index 454145db10e7..645e22b5d0b8 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -134,6 +134,7 @@ int xchk_count_rmap_ownedby_ag(struct xfs_scrub *sc, struct xfs_btree_cur *cur, int xchk_setup_ag_btree(struct xfs_scrub *sc, bool force_log); int xchk_get_inode(struct xfs_scrub *sc); int xchk_setup_inode_contents(struct xfs_scrub *sc, unsigned int resblks); +int xchk_install_inode(struct xfs_scrub *sc, struct xfs_inode *ip); void xchk_buffer_recheck(struct xfs_scrub *sc, struct xfs_buf *bp); /* diff --git a/fs/xfs/scrub/quota.c b/fs/xfs/scrub/quota.c index 5ae515ffd0bf..175055131937 100644 --- a/fs/xfs/scrub/quota.c +++ b/fs/xfs/scrub/quota.c @@ -56,7 +56,11 @@ xchk_setup_quota( error = xchk_setup_fs(sc); if (error) return error; - sc->ip = xfs_quota_inode(sc->mp, dqtype); + + error = xchk_install_inode(sc, xfs_quota_inode(sc->mp, dqtype)); + if (error) + return error; + xfs_ilock(sc->ip, XFS_ILOCK_EXCL); sc->ilock_flags = XFS_ILOCK_EXCL; return 0; diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c index 8fa012057405..907389236033 100644 --- a/fs/xfs/scrub/rtbitmap.c +++ b/fs/xfs/scrub/rtbitmap.c @@ -28,10 +28,12 @@ xchk_setup_rt( if (error) return error; + error = xchk_install_inode(sc, sc->mp->m_rbmip); + if (error) + return error; + sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP; - sc->ip = sc->mp->m_rbmip; xfs_ilock(sc->ip, sc->ilock_flags); - return 0; } diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 9c73951fc4d3..20a92bbb8af7 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -153,8 +153,6 @@ xchk_teardown( struct xfs_scrub *sc, int error) { - struct xfs_inode *ip_in = XFS_I(file_inode(sc->file)); - xchk_ag_free(sc, &sc->sa); if (sc->tp) { if (error == 0 && (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)) @@ -166,9 +164,7 @@ xchk_teardown( if (sc->ip) { if (sc->ilock_flags) xfs_iunlock(sc->ip, sc->ilock_flags); - if (sc->ip != ip_in && - !xfs_internal_inum(sc->mp, sc->ip->i_ino)) - xfs_irele(sc->ip); + xfs_irele(sc->ip); sc->ip = NULL; } if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) |