xfs: check inode core when scrubbing metadata files
authorDarrick J. Wong <djwong@kernel.org>
Thu, 17 Nov 2022 00:08:03 +0000 (16:08 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 17 Nov 2022 00:11:51 +0000 (16:11 -0800)
Metadata files (e.g. realtime bitmaps and quota files) do not show up in
the bulkstat output, which means that scrub-by-handle does not work;
they can only be checked through a specific scrub type.  Therefore, each
scrub type calls xchk_metadata_inode_forks to check the metadata for
whatever's in the file.

Unfortunately, that function doesn't actually check the inode record
itself.  Refactor the function a bit to make that happen.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/scrub/common.c

index ad70f29..613260b 100644 (file)
@@ -781,6 +781,33 @@ xchk_buffer_recheck(
        trace_xchk_block_error(sc, xfs_buf_daddr(bp), fa);
 }
 
+static inline int
+xchk_metadata_inode_subtype(
+       struct xfs_scrub        *sc,
+       unsigned int            scrub_type)
+{
+       __u32                   smtype = sc->sm->sm_type;
+       int                     error;
+
+       sc->sm->sm_type = scrub_type;
+
+       switch (scrub_type) {
+       case XFS_SCRUB_TYPE_INODE:
+               error = xchk_inode(sc);
+               break;
+       case XFS_SCRUB_TYPE_BMBTD:
+               error = xchk_bmap_data(sc);
+               break;
+       default:
+               ASSERT(0);
+               error = -EFSCORRUPTED;
+               break;
+       }
+
+       sc->sm->sm_type = smtype;
+       return error;
+}
+
 /*
  * Scrub the attr/data forks of a metadata inode.  The metadata inode must be
  * pointed to by sc->ip and the ILOCK must be held.
@@ -789,13 +816,17 @@ int
 xchk_metadata_inode_forks(
        struct xfs_scrub        *sc)
 {
-       __u32                   smtype;
        bool                    shared;
        int                     error;
 
        if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
                return 0;
 
+       /* Check the inode record. */
+       error = xchk_metadata_inode_subtype(sc, XFS_SCRUB_TYPE_INODE);
+       if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
+               return error;
+
        /* Metadata inodes don't live on the rt device. */
        if (sc->ip->i_diflags & XFS_DIFLAG_REALTIME) {
                xchk_ino_set_corrupt(sc, sc->ip->i_ino);
@@ -815,10 +846,7 @@ xchk_metadata_inode_forks(
        }
 
        /* Invoke the data fork scrubber. */
-       smtype = sc->sm->sm_type;
-       sc->sm->sm_type = XFS_SCRUB_TYPE_BMBTD;
-       error = xchk_bmap_data(sc);
-       sc->sm->sm_type = smtype;
+       error = xchk_metadata_inode_subtype(sc, XFS_SCRUB_TYPE_BMBTD);
        if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
                return error;
 
@@ -833,7 +861,7 @@ xchk_metadata_inode_forks(
                        xchk_ino_set_corrupt(sc, sc->ip->i_ino);
        }
 
-       return error;
+       return 0;
 }
 
 /*