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: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com>
This commit is contained in:
parent
ddd10c2fe2
commit
9f3a080ef1
|
@ -3180,3 +3180,40 @@ xfs_alloc_has_record(
|
||||||
|
|
||||||
return xfs_btree_has_record(cur, &low, &high, exists);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||||
xfs_extlen_t len, bool *exist);
|
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__ */
|
#endif /* __XFS_ALLOC_H__ */
|
||||||
|
|
|
@ -38,68 +38,6 @@
|
||||||
#include "scrub/common.h"
|
#include "scrub/common.h"
|
||||||
#include "scrub/trace.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 */
|
/* Superblock */
|
||||||
|
|
||||||
/* Cross-reference with the other btrees. */
|
/* Cross-reference with the other btrees. */
|
||||||
|
@ -678,6 +616,7 @@ struct xfs_scrub_agfl_info {
|
||||||
unsigned int sz_entries;
|
unsigned int sz_entries;
|
||||||
unsigned int nr_entries;
|
unsigned int nr_entries;
|
||||||
xfs_agblock_t *entries;
|
xfs_agblock_t *entries;
|
||||||
|
struct xfs_scrub_context *sc;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Cross-reference with the other btrees. */
|
/* Cross-reference with the other btrees. */
|
||||||
|
@ -699,12 +638,12 @@ xfs_scrub_agfl_block_xref(
|
||||||
/* Scrub an AGFL block. */
|
/* Scrub an AGFL block. */
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_scrub_agfl_block(
|
xfs_scrub_agfl_block(
|
||||||
struct xfs_scrub_context *sc,
|
struct xfs_mount *mp,
|
||||||
xfs_agblock_t agbno,
|
xfs_agblock_t agbno,
|
||||||
void *priv)
|
void *priv)
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp = sc->mp;
|
|
||||||
struct xfs_scrub_agfl_info *sai = priv;
|
struct xfs_scrub_agfl_info *sai = priv;
|
||||||
|
struct xfs_scrub_context *sc = sai->sc;
|
||||||
xfs_agnumber_t agno = sc->sa.agno;
|
xfs_agnumber_t agno = sc->sa.agno;
|
||||||
|
|
||||||
if (xfs_verify_agbno(mp, agno, agbno) &&
|
if (xfs_verify_agbno(mp, agno, agbno) &&
|
||||||
|
@ -715,6 +654,9 @@ xfs_scrub_agfl_block(
|
||||||
|
|
||||||
xfs_scrub_agfl_block_xref(sc, agbno, priv);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,6 +736,7 @@ xfs_scrub_agfl(
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
memset(&sai, 0, sizeof(sai));
|
memset(&sai, 0, sizeof(sai));
|
||||||
|
sai.sc = sc;
|
||||||
sai.sz_entries = agflcount;
|
sai.sz_entries = agflcount;
|
||||||
sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount,
|
sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount,
|
||||||
KM_MAYFAIL);
|
KM_MAYFAIL);
|
||||||
|
@ -804,7 +747,12 @@ xfs_scrub_agfl(
|
||||||
|
|
||||||
/* Check the blocks in the AGFL. */
|
/* Check the blocks in the AGFL. */
|
||||||
xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG);
|
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)
|
if (error)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
void xfs_scrub_ag_btcur_free(struct xfs_scrub_ag *sa);
|
||||||
int xfs_scrub_ag_btcur_init(struct xfs_scrub_context *sc,
|
int xfs_scrub_ag_btcur_init(struct xfs_scrub_context *sc,
|
||||||
struct xfs_scrub_ag *sa);
|
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,
|
int xfs_scrub_count_rmap_ownedby_ag(struct xfs_scrub_context *sc,
|
||||||
struct xfs_btree_cur *cur,
|
struct xfs_btree_cur *cur,
|
||||||
struct xfs_owner_info *oinfo,
|
struct xfs_owner_info *oinfo,
|
||||||
|
|
Loading…
Reference in New Issue