xfs: get our own reference to inodes that we want to scrub
authorDarrick J. Wong <djwong@kernel.org>
Thu, 10 Aug 2023 14:48:08 +0000 (07:48 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 10 Aug 2023 14:48:08 +0000 (07:48 -0700)
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>
fs/xfs/scrub/common.c
fs/xfs/scrub/common.h
fs/xfs/scrub/inode.c
fs/xfs/scrub/quota.c
fs/xfs/scrub/rtbitmap.c
fs/xfs/scrub/scrub.c

index 7a20256..6354cb4 100644 (file)
@@ -832,6 +832,25 @@ xchk_install_handle_inode(
 }
 
 /*
+ * 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
  * inode passed in.  If the inumber does not reference an allocated inode
@@ -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))
index 791235c..065d4bb 100644 (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);
index 3e1e02e..1d8097f 100644 (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);
        }
 
index e6caa35..19bf7f1 100644 (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;
index e7dace7..3bd4d0a 100644 (file)
@@ -28,10 +28,12 @@ xchk_setup_rt(
        if (error)
                return error;
 
+       error = xchk_install_live_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;
 }
 
index e6962cf..91de2b5 100644 (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)