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>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
This commit is contained in:
Darrick J. Wong 2023-08-10 07:48:08 -07:00
parent d7a74cad8f
commit 1730853950
6 changed files with 37 additions and 14 deletions

View file

@ -831,6 +831,25 @@ xchk_install_handle_inode(
return 0;
}
/*
* Install an already-referenced inode for scrubbing. Get our own reference to
* the inode to make disposal simpler. The inode must not be in I_FREEING or
* I_WILL_FREE state!
*/
int
xchk_install_live_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;
}
/*
* In preparation to scrub metadata structures that hang off of an inode,
* grab either the inode referenced in the scrub control structure or the
@ -854,10 +873,8 @@ xchk_iget_for_scrubbing(
ASSERT(sc->tp == NULL);
/* 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_live_inode(sc, ip_in);
/* Reject internal metadata files and obviously bad inode numbers. */
if (xfs_internal_inum(mp, sc->sm->sm_ino))

View file

@ -137,6 +137,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_iget_for_scrubbing(struct xfs_scrub *sc);
int xchk_setup_inode_contents(struct xfs_scrub *sc, unsigned int resblks);
int xchk_install_live_inode(struct xfs_scrub *sc, struct xfs_inode *ip);
void xchk_buffer_recheck(struct xfs_scrub *sc, struct xfs_buf *bp);
int xchk_iget(struct xfs_scrub *sc, xfs_ino_t inum, struct xfs_inode **ipp);

View file

@ -83,7 +83,10 @@ xchk_setup_inode(
/* We want to scan the opened inode, so lock it and exit. */
if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) {
sc->ip = ip_in;
error = xchk_install_live_inode(sc, ip_in);
if (error)
return error;
return xchk_prepare_iscrub(sc);
}

View file

@ -59,7 +59,11 @@ xchk_setup_quota(
error = xchk_setup_fs(sc);
if (error)
return error;
sc->ip = xfs_quota_inode(sc->mp, dqtype);
error = xchk_install_live_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;

View file

@ -28,10 +28,12 @@ xchk_setup_rt(
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);
error = xchk_install_live_inode(sc, sc->mp->m_rbmip);
if (error)
return error;
sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP;
xfs_ilock(sc->ip, sc->ilock_flags);
return 0;
}

View file

@ -167,8 +167,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))
@ -180,9 +178,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))
xchk_irele(sc, sc->ip);
xchk_irele(sc, sc->ip);
sc->ip = NULL;
}
if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)