diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2018-05-14 09:34:34 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-05-15 21:12:50 -0400 |
commit | 9f3a080ef19b1c182a8fb1edbfb707fdb811437c (patch) | |
tree | a432e25a91854614b5e6f50288dbb4dc51a4ede9 | |
parent | ddd10c2fe20e7ca6d11ddf84f905edba080b26a7 (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.c | 37 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_alloc.h | 5 | ||||
-rw-r--r-- | fs/xfs/scrub/agheader.c | 78 | ||||
-rw-r--r-- | fs/xfs/scrub/common.h | 4 |
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 | */ | ||
3188 | int | ||
3189 | xfs_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); | |||
262 | int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno, | 262 | int 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 | ||
265 | typedef int (*xfs_agfl_walk_fn)(struct xfs_mount *mp, xfs_agblock_t bno, | ||
266 | void *priv); | ||
267 | int 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 | */ | ||
45 | int | ||
46 | xfs_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. */ |
700 | STATIC int | 639 | STATIC int |
701 | xfs_scrub_agfl_block( | 640 | xfs_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, | |||
129 | void xfs_scrub_ag_btcur_free(struct xfs_scrub_ag *sa); | 129 | void xfs_scrub_ag_btcur_free(struct xfs_scrub_ag *sa); |
130 | int xfs_scrub_ag_btcur_init(struct xfs_scrub_context *sc, | 130 | int xfs_scrub_ag_btcur_init(struct xfs_scrub_context *sc, |
131 | struct xfs_scrub_ag *sa); | 131 | struct xfs_scrub_ag *sa); |
132 | int 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); | ||
136 | int xfs_scrub_count_rmap_ownedby_ag(struct xfs_scrub_context *sc, | 132 | int 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, |