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

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

xfs: hoist xfs_scrub_agfl_walk to libxfs as xfs_agfl_walk



This function is basically a generic AGFL block iterator, so promote it
to libxfs ahead of online repair wanting to use it.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent ddd10c2f
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -3180,3 +3180,40 @@ xfs_alloc_has_record(

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

/*
 * Walk all the blocks in the AGFL.  The @walk_fn can return any negative
 * error code or XFS_BTREE_QUERY_RANGE_ABORT.
 */
int
xfs_agfl_walk(
	struct xfs_mount	*mp,
	struct xfs_agf		*agf,
	struct xfs_buf		*agflbp,
	xfs_agfl_walk_fn	walk_fn,
	void			*priv)
{
	__be32			*agfl_bno;
	unsigned int		i;
	int			error;

	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
	i = be32_to_cpu(agf->agf_flfirst);

	/* Nothing to walk in an empty AGFL. */
	if (agf->agf_flcount == cpu_to_be32(0))
		return 0;

	/* Otherwise, walk from first to last, wrapping as needed. */
	for (;;) {
		error = walk_fn(mp, be32_to_cpu(agfl_bno[i]), priv);
		if (error)
			return error;
		if (i == be32_to_cpu(agf->agf_fllast))
			break;
		if (++i == xfs_agfl_size(mp))
			i = 0;
	}

	return 0;
}
+5 −0
Original line number Diff line number Diff line
@@ -262,4 +262,9 @@ bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
		xfs_extlen_t len, bool *exist);

typedef int (*xfs_agfl_walk_fn)(struct xfs_mount *mp, xfs_agblock_t bno,
		void *priv);
int xfs_agfl_walk(struct xfs_mount *mp, struct xfs_agf *agf,
		struct xfs_buf *agflbp, xfs_agfl_walk_fn walk_fn, void *priv);

#endif	/* __XFS_ALLOC_H__ */
+13 −65
Original line number Diff line number Diff line
@@ -38,68 +38,6 @@
#include "scrub/common.h"
#include "scrub/trace.h"

/*
 * Walk all the blocks in the AGFL.  The fn function can return any negative
 * error code or XFS_BTREE_QUERY_RANGE_ABORT.
 */
int
xfs_scrub_walk_agfl(
	struct xfs_scrub_context	*sc,
	int				(*fn)(struct xfs_scrub_context *,
					      xfs_agblock_t bno, void *),
	void				*priv)
{
	struct xfs_agf			*agf;
	__be32				*agfl_bno;
	struct xfs_mount		*mp = sc->mp;
	unsigned int			flfirst;
	unsigned int			fllast;
	int				i;
	int				error;

	agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, sc->sa.agfl_bp);
	flfirst = be32_to_cpu(agf->agf_flfirst);
	fllast = be32_to_cpu(agf->agf_fllast);

	/* Nothing to walk in an empty AGFL. */
	if (agf->agf_flcount == cpu_to_be32(0))
		return 0;

	/* first to last is a consecutive list. */
	if (fllast >= flfirst) {
		for (i = flfirst; i <= fllast; i++) {
			error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
			if (error)
				return error;
			if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
				return error;
		}

		return 0;
	}

	/* first to the end */
	for (i = flfirst; i < xfs_agfl_size(mp); i++) {
		error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
		if (error)
			return error;
		if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
			return error;
	}

	/* the start to last. */
	for (i = 0; i <= fllast; i++) {
		error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
		if (error)
			return error;
		if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
			return error;
	}

	return 0;
}

/* Superblock */

/* Cross-reference with the other btrees. */
@@ -678,6 +616,7 @@ struct xfs_scrub_agfl_info {
	unsigned int			sz_entries;
	unsigned int			nr_entries;
	xfs_agblock_t			*entries;
	struct xfs_scrub_context	*sc;
};

/* Cross-reference with the other btrees. */
@@ -699,12 +638,12 @@ xfs_scrub_agfl_block_xref(
/* Scrub an AGFL block. */
STATIC int
xfs_scrub_agfl_block(
	struct xfs_scrub_context	*sc,
	struct xfs_mount		*mp,
	xfs_agblock_t			agbno,
	void				*priv)
{
	struct xfs_mount		*mp = sc->mp;
	struct xfs_scrub_agfl_info	*sai = priv;
	struct xfs_scrub_context	*sc = sai->sc;
	xfs_agnumber_t			agno = sc->sa.agno;

	if (xfs_verify_agbno(mp, agno, agbno) &&
@@ -715,6 +654,9 @@ xfs_scrub_agfl_block(

	xfs_scrub_agfl_block_xref(sc, agbno, priv);

	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
		return XFS_BTREE_QUERY_RANGE_ABORT;

	return 0;
}

@@ -794,6 +736,7 @@ xfs_scrub_agfl(
		goto out;
	}
	memset(&sai, 0, sizeof(sai));
	sai.sc = sc;
	sai.sz_entries = agflcount;
	sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount,
			KM_MAYFAIL);
@@ -804,7 +747,12 @@ xfs_scrub_agfl(

	/* Check the blocks in the AGFL. */
	xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG);
	error = xfs_scrub_walk_agfl(sc, xfs_scrub_agfl_block, &sai);
	error = xfs_agfl_walk(sc->mp, XFS_BUF_TO_AGF(sc->sa.agf_bp),
			sc->sa.agfl_bp, xfs_scrub_agfl_block, &sai);
	if (error == XFS_BTREE_QUERY_RANGE_ABORT) {
		error = 0;
		goto out_free;
	}
	if (error)
		goto out_free;

+0 −4
Original line number Diff line number Diff line
@@ -129,10 +129,6 @@ int xfs_scrub_ag_read_headers(struct xfs_scrub_context *sc, xfs_agnumber_t agno,
void xfs_scrub_ag_btcur_free(struct xfs_scrub_ag *sa);
int xfs_scrub_ag_btcur_init(struct xfs_scrub_context *sc,
			    struct xfs_scrub_ag *sa);
int xfs_scrub_walk_agfl(struct xfs_scrub_context *sc,
			int (*fn)(struct xfs_scrub_context *, xfs_agblock_t bno,
				  void *),
			void *priv);
int xfs_scrub_count_rmap_ownedby_ag(struct xfs_scrub_context *sc,
				    struct xfs_btree_cur *cur,
				    struct xfs_owner_info *oinfo,