Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

xfs: add scrub cross-referencing helpers for the rmap btrees



Add a couple of functions to the rmap btrees that will be used
to cross-reference metadata against the rmapbt.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent 2e001266
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -2387,3 +2387,70 @@ xfs_rmap_compare(
	else
		return 0;
}

/* Is there a record covering a given extent? */
int
xfs_rmap_has_record(
	struct xfs_btree_cur	*cur,
	xfs_agblock_t		bno,
	xfs_extlen_t		len,
	bool			*exists)
{
	union xfs_btree_irec	low;
	union xfs_btree_irec	high;

	memset(&low, 0, sizeof(low));
	low.r.rm_startblock = bno;
	memset(&high, 0xFF, sizeof(high));
	high.r.rm_startblock = bno + len - 1;

	return xfs_btree_has_record(cur, &low, &high, exists);
}

/*
 * Is there a record for this owner completely covering a given physical
 * extent?  If so, *has_rmap will be set to true.  If there is no record
 * or the record only covers part of the range, we set *has_rmap to false.
 * This function doesn't perform range lookups or offset checks, so it is
 * not suitable for checking data fork blocks.
 */
int
xfs_rmap_record_exists(
	struct xfs_btree_cur	*cur,
	xfs_agblock_t		bno,
	xfs_extlen_t		len,
	struct xfs_owner_info	*oinfo,
	bool			*has_rmap)
{
	uint64_t		owner;
	uint64_t		offset;
	unsigned int		flags;
	int			has_record;
	struct xfs_rmap_irec	irec;
	int			error;

	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
	ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
	       (flags & XFS_RMAP_BMBT_BLOCK));

	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
			&has_record);
	if (error)
		return error;
	if (!has_record) {
		*has_rmap = false;
		return 0;
	}

	error = xfs_rmap_get_rec(cur, &irec, &has_record);
	if (error)
		return error;
	if (!has_record) {
		*has_rmap = false;
		return 0;
	}

	*has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
		     irec.rm_startblock + irec.rm_blockcount >= bno + len);
	return 0;
}
+5 −0
Original line number Diff line number Diff line
@@ -233,5 +233,10 @@ int xfs_rmap_compare(const struct xfs_rmap_irec *a,
union xfs_btree_rec;
int xfs_rmap_btrec_to_irec(union xfs_btree_rec *rec,
		struct xfs_rmap_irec *irec);
int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
		xfs_extlen_t len, bool *exists);
int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
		xfs_extlen_t len, struct xfs_owner_info *oinfo,
		bool *has_rmap);

#endif	/* __XFS_RMAP_H__ */