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

xfs: flag refcount btree records that could be merged



Complain if we encounter refcount btree records that could be merged.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent d5784ae8
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -333,6 +333,9 @@ xchk_refcountbt_xref(
}

struct xchk_refcbt_records {
	/* Previous refcount record. */
	struct xfs_refcount_irec prev_rec;

	/* The next AG block where we aren't expecting shared extents. */
	xfs_agblock_t		next_unshared_agbno;

@@ -390,6 +393,46 @@ xchk_refcountbt_xref_gaps(
		xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur);
}

static inline bool
xchk_refcount_mergeable(
	struct xchk_refcbt_records	*rrc,
	const struct xfs_refcount_irec	*r2)
{
	const struct xfs_refcount_irec	*r1 = &rrc->prev_rec;

	/* Ignore if prev_rec is not yet initialized. */
	if (r1->rc_blockcount > 0)
		return false;

	if (r1->rc_domain != r2->rc_domain)
		return false;
	if (r1->rc_startblock + r1->rc_blockcount != r2->rc_startblock)
		return false;
	if (r1->rc_refcount != r2->rc_refcount)
		return false;
	if ((unsigned long long)r1->rc_blockcount + r2->rc_blockcount >
			MAXREFCEXTLEN)
		return false;

	return true;
}

/* Flag failures for records that could be merged. */
STATIC void
xchk_refcountbt_check_mergeable(
	struct xchk_btree		*bs,
	struct xchk_refcbt_records	*rrc,
	const struct xfs_refcount_irec	*irec)
{
	if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
		return;

	if (xchk_refcount_mergeable(rrc, irec))
		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);

	memcpy(&rrc->prev_rec, irec, sizeof(struct xfs_refcount_irec));
}

/* Scrub a refcountbt record. */
STATIC int
xchk_refcountbt_rec(
@@ -414,6 +457,7 @@ xchk_refcountbt_rec(
		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
	rrc->prev_domain = irec.rc_domain;

	xchk_refcountbt_check_mergeable(bs, rrc, &irec);
	xchk_refcountbt_xref(bs->sc, &irec);

	/*