summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-05-14 09:34:34 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2018-05-15 21:12:50 -0400
commit9f3a080ef19b1c182a8fb1edbfb707fdb811437c (patch)
treea432e25a91854614b5e6f50288dbb4dc51a4ede9
parentddd10c2fe20e7ca6d11ddf84f905edba080b26a7 (diff)
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>
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c37
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h5
-rw-r--r--fs/xfs/scrub/agheader.c78
-rw-r--r--fs/xfs/scrub/common.h4
4 files changed, 55 insertions, 69 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 5410635893df..dc9dd3805d97 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -3180,3 +3180,40 @@ xfs_alloc_has_record(
3180 3180
3181 return xfs_btree_has_record(cur, &low, &high, exists); 3181 return xfs_btree_has_record(cur, &low, &high, exists);
3182} 3182}
3183
3184/*
3185 * Walk all the blocks in the AGFL. The @walk_fn can return any negative
3186 * error code or XFS_BTREE_QUERY_RANGE_ABORT.
3187 */
3188int
3189xfs_agfl_walk(
3190 struct xfs_mount *mp,
3191 struct xfs_agf *agf,
3192 struct xfs_buf *agflbp,
3193 xfs_agfl_walk_fn walk_fn,
3194 void *priv)
3195{
3196 __be32 *agfl_bno;
3197 unsigned int i;
3198 int error;
3199
3200 agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
3201 i = be32_to_cpu(agf->agf_flfirst);
3202
3203 /* Nothing to walk in an empty AGFL. */
3204 if (agf->agf_flcount == cpu_to_be32(0))
3205 return 0;
3206
3207 /* Otherwise, walk from first to last, wrapping as needed. */
3208 for (;;) {
3209 error = walk_fn(mp, be32_to_cpu(agfl_bno[i]), priv);
3210 if (error)
3211 return error;
3212 if (i == be32_to_cpu(agf->agf_fllast))
3213 break;
3214 if (++i == xfs_agfl_size(mp))
3215 i = 0;
3216 }
3217
3218 return 0;
3219}
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 46d48c6f83b7..0747adcd57d6 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -262,4 +262,9 @@ bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
262int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno, 262int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
263 xfs_extlen_t len, bool *exist); 263 xfs_extlen_t len, bool *exist);
264 264
265typedef int (*xfs_agfl_walk_fn)(struct xfs_mount *mp, xfs_agblock_t bno,
266 void *priv);
267int xfs_agfl_walk(struct xfs_mount *mp, struct xfs_agf *agf,
268 struct xfs_buf *agflbp, xfs_agfl_walk_fn walk_fn, void *priv);
269
265#endif /* __XFS_ALLOC_H__ */ 270#endif /* __XFS_ALLOC_H__ */
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index 831acc0a328f..1f71793f7db4 100644
--- a/fs/xfs/scrub/agheader.c
+++ b/fs/xfs/scrub/agheader.c
@@ -38,68 +38,6 @@
38#include "scrub/common.h" 38#include "scrub/common.h"
39#include "scrub/trace.h" 39#include "scrub/trace.h"
40 40
41/*
42 * Walk all the blocks in the AGFL. The fn function can return any negative
43 * error code or XFS_BTREE_QUERY_RANGE_ABORT.
44 */
45int
46xfs_scrub_walk_agfl(
47 struct xfs_scrub_context *sc,
48 int (*fn)(struct xfs_scrub_context *,
49 xfs_agblock_t bno, void *),
50 void *priv)
51{
52 struct xfs_agf *agf;
53 __be32 *agfl_bno;
54 struct xfs_mount *mp = sc->mp;
55 unsigned int flfirst;
56 unsigned int fllast;
57 int i;
58 int error;
59
60 agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
61 agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, sc->sa.agfl_bp);
62 flfirst = be32_to_cpu(agf->agf_flfirst);
63 fllast = be32_to_cpu(agf->agf_fllast);
64
65 /* Nothing to walk in an empty AGFL. */
66 if (agf->agf_flcount == cpu_to_be32(0))
67 return 0;
68
69 /* first to last is a consecutive list. */
70 if (fllast >= flfirst) {
71 for (i = flfirst; i <= fllast; i++) {
72 error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
73 if (error)
74 return error;
75 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
76 return error;
77 }
78
79 return 0;
80 }
81
82 /* first to the end */
83 for (i = flfirst; i < xfs_agfl_size(mp); i++) {
84 error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
85 if (error)
86 return error;
87 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
88 return error;
89 }
90
91 /* the start to last. */
92 for (i = 0; i <= fllast; i++) {
93 error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
94 if (error)
95 return error;
96 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
97 return error;
98 }
99
100 return 0;
101}
102
103/* Superblock */ 41/* Superblock */
104 42
105/* Cross-reference with the other btrees. */ 43/* Cross-reference with the other btrees. */
@@ -678,6 +616,7 @@ struct xfs_scrub_agfl_info {
678 unsigned int sz_entries; 616 unsigned int sz_entries;
679 unsigned int nr_entries; 617 unsigned int nr_entries;
680 xfs_agblock_t *entries; 618 xfs_agblock_t *entries;
619 struct xfs_scrub_context *sc;
681}; 620};
682 621
683/* Cross-reference with the other btrees. */ 622/* Cross-reference with the other btrees. */
@@ -699,12 +638,12 @@ xfs_scrub_agfl_block_xref(
699/* Scrub an AGFL block. */ 638/* Scrub an AGFL block. */
700STATIC int 639STATIC int
701xfs_scrub_agfl_block( 640xfs_scrub_agfl_block(
702 struct xfs_scrub_context *sc, 641 struct xfs_mount *mp,
703 xfs_agblock_t agbno, 642 xfs_agblock_t agbno,
704 void *priv) 643 void *priv)
705{ 644{
706 struct xfs_mount *mp = sc->mp;
707 struct xfs_scrub_agfl_info *sai = priv; 645 struct xfs_scrub_agfl_info *sai = priv;
646 struct xfs_scrub_context *sc = sai->sc;
708 xfs_agnumber_t agno = sc->sa.agno; 647 xfs_agnumber_t agno = sc->sa.agno;
709 648
710 if (xfs_verify_agbno(mp, agno, agbno) && 649 if (xfs_verify_agbno(mp, agno, agbno) &&
@@ -715,6 +654,9 @@ xfs_scrub_agfl_block(
715 654
716 xfs_scrub_agfl_block_xref(sc, agbno, priv); 655 xfs_scrub_agfl_block_xref(sc, agbno, priv);
717 656
657 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
658 return XFS_BTREE_QUERY_RANGE_ABORT;
659
718 return 0; 660 return 0;
719} 661}
720 662
@@ -794,6 +736,7 @@ xfs_scrub_agfl(
794 goto out; 736 goto out;
795 } 737 }
796 memset(&sai, 0, sizeof(sai)); 738 memset(&sai, 0, sizeof(sai));
739 sai.sc = sc;
797 sai.sz_entries = agflcount; 740 sai.sz_entries = agflcount;
798 sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount, 741 sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount,
799 KM_MAYFAIL); 742 KM_MAYFAIL);
@@ -804,7 +747,12 @@ xfs_scrub_agfl(
804 747
805 /* Check the blocks in the AGFL. */ 748 /* Check the blocks in the AGFL. */
806 xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG); 749 xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG);
807 error = xfs_scrub_walk_agfl(sc, xfs_scrub_agfl_block, &sai); 750 error = xfs_agfl_walk(sc->mp, XFS_BUF_TO_AGF(sc->sa.agf_bp),
751 sc->sa.agfl_bp, xfs_scrub_agfl_block, &sai);
752 if (error == XFS_BTREE_QUERY_RANGE_ABORT) {
753 error = 0;
754 goto out_free;
755 }
808 if (error) 756 if (error)
809 goto out_free; 757 goto out_free;
810 758
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 119d9b6db887..a660087b606e 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -129,10 +129,6 @@ int xfs_scrub_ag_read_headers(struct xfs_scrub_context *sc, xfs_agnumber_t agno,
129void xfs_scrub_ag_btcur_free(struct xfs_scrub_ag *sa); 129void xfs_scrub_ag_btcur_free(struct xfs_scrub_ag *sa);
130int xfs_scrub_ag_btcur_init(struct xfs_scrub_context *sc, 130int xfs_scrub_ag_btcur_init(struct xfs_scrub_context *sc,
131 struct xfs_scrub_ag *sa); 131 struct xfs_scrub_ag *sa);
132int xfs_scrub_walk_agfl(struct xfs_scrub_context *sc,
133 int (*fn)(struct xfs_scrub_context *, xfs_agblock_t bno,
134 void *),
135 void *priv);
136int xfs_scrub_count_rmap_ownedby_ag(struct xfs_scrub_context *sc, 132int xfs_scrub_count_rmap_ownedby_ag(struct xfs_scrub_context *sc,
137 struct xfs_btree_cur *cur, 133 struct xfs_btree_cur *cur,
138 struct xfs_owner_info *oinfo, 134 struct xfs_owner_info *oinfo,