Commit 7b082b5e authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

Merge tag 'scrub-check-metadata-inode-records-6.2_2022-11-16' of...

Merge tag 'scrub-check-metadata-inode-records-6.2_2022-11-16' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux

 into xfs-6.2-mergeA

xfs: scrub inode core when checking metadata files

Running the online fsck QA fuzz tests, I noticed that we were
consistently missing fuzzed records in the inode cores of the realtime
freespace files and the quota files.  This patch adds the ability to
check inode cores in xchk_metadata_inode_forks.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>

* tag 'scrub-check-metadata-inode-records-6.2_2022-11-16' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: check inode core when scrubbing metadata files
  xfs: don't warn about files that are exactly s_maxbytes long
parents cc5f38fa f36b954a
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -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;
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -365,7 +365,7 @@ xchk_dinode(
	 * pagecache can't cache all the blocks in this file due to
	 * overly large offsets, flag the inode for admin review.
	 */
	if (isize >= mp->m_super->s_maxbytes)
	if (isize > mp->m_super->s_maxbytes)
		xchk_ino_set_warning(sc, ino);

	/* di_nblocks */