diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2018-07-30 14:18:13 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-07-31 16:18:08 -0400 |
commit | 86d969b425d7ecf774799b70142b957dc267575b (patch) | |
tree | 740eb40605ec763a1e53deb6417c03e81647f18d | |
parent | 51d626903083f7bd651d38b031775740ed41758c (diff) |
xfs: refactor the xrep_extent_list into xfs_bitmap
As mentioned previously, the xrep_extent_list basically implements a
bitmap with two functions: set and disjoint union. Rename all these
functions to xfs_bitmap to shorten the name and make it more obvious
what we're doing.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
-rw-r--r-- | fs/xfs/scrub/bitmap.c | 183 | ||||
-rw-r--r-- | fs/xfs/scrub/bitmap.h | 35 | ||||
-rw-r--r-- | fs/xfs/scrub/repair.c | 85 | ||||
-rw-r--r-- | fs/xfs/scrub/repair.h | 8 | ||||
-rw-r--r-- | fs/xfs/scrub/trace.h | 1 |
5 files changed, 149 insertions, 163 deletions
diff --git a/fs/xfs/scrub/bitmap.c b/fs/xfs/scrub/bitmap.c index a7c2f4773f98..c770e2d0b6aa 100644 --- a/fs/xfs/scrub/bitmap.c +++ b/fs/xfs/scrub/bitmap.c | |||
@@ -16,183 +16,186 @@ | |||
16 | #include "scrub/repair.h" | 16 | #include "scrub/repair.h" |
17 | #include "scrub/bitmap.h" | 17 | #include "scrub/bitmap.h" |
18 | 18 | ||
19 | /* Collect a dead btree extent for later disposal. */ | 19 | /* |
20 | * Set a range of this bitmap. Caller must ensure the range is not set. | ||
21 | * | ||
22 | * This is the logical equivalent of bitmap |= mask(start, len). | ||
23 | */ | ||
20 | int | 24 | int |
21 | xrep_collect_btree_extent( | 25 | xfs_bitmap_set( |
22 | struct xfs_scrub *sc, | 26 | struct xfs_bitmap *bitmap, |
23 | struct xrep_extent_list *exlist, | 27 | uint64_t start, |
24 | xfs_fsblock_t fsbno, | 28 | uint64_t len) |
25 | xfs_extlen_t len) | ||
26 | { | 29 | { |
27 | struct xrep_extent *rex; | 30 | struct xfs_bitmap_range *bmr; |
28 | 31 | ||
29 | trace_xrep_collect_btree_extent(sc->mp, | 32 | bmr = kmem_alloc(sizeof(struct xfs_bitmap_range), KM_MAYFAIL); |
30 | XFS_FSB_TO_AGNO(sc->mp, fsbno), | 33 | if (!bmr) |
31 | XFS_FSB_TO_AGBNO(sc->mp, fsbno), len); | ||
32 | |||
33 | rex = kmem_alloc(sizeof(struct xrep_extent), KM_MAYFAIL); | ||
34 | if (!rex) | ||
35 | return -ENOMEM; | 34 | return -ENOMEM; |
36 | 35 | ||
37 | INIT_LIST_HEAD(&rex->list); | 36 | INIT_LIST_HEAD(&bmr->list); |
38 | rex->fsbno = fsbno; | 37 | bmr->start = start; |
39 | rex->len = len; | 38 | bmr->len = len; |
40 | list_add_tail(&rex->list, &exlist->list); | 39 | list_add_tail(&bmr->list, &bitmap->list); |
41 | 40 | ||
42 | return 0; | 41 | return 0; |
43 | } | 42 | } |
44 | 43 | ||
45 | /* | 44 | /* Free everything related to this bitmap. */ |
46 | * An error happened during the rebuild so the transaction will be cancelled. | ||
47 | * The fs will shut down, and the administrator has to unmount and run repair. | ||
48 | * Therefore, free all the memory associated with the list so we can die. | ||
49 | */ | ||
50 | void | 45 | void |
51 | xrep_cancel_btree_extents( | 46 | xfs_bitmap_destroy( |
52 | struct xfs_scrub *sc, | 47 | struct xfs_bitmap *bitmap) |
53 | struct xrep_extent_list *exlist) | ||
54 | { | 48 | { |
55 | struct xrep_extent *rex; | 49 | struct xfs_bitmap_range *bmr; |
56 | struct xrep_extent *n; | 50 | struct xfs_bitmap_range *n; |
57 | 51 | ||
58 | for_each_xrep_extent_safe(rex, n, exlist) { | 52 | for_each_xfs_bitmap_extent(bmr, n, bitmap) { |
59 | list_del(&rex->list); | 53 | list_del(&bmr->list); |
60 | kmem_free(rex); | 54 | kmem_free(bmr); |
61 | } | 55 | } |
62 | } | 56 | } |
63 | 57 | ||
58 | /* Set up a per-AG block bitmap. */ | ||
59 | void | ||
60 | xfs_bitmap_init( | ||
61 | struct xfs_bitmap *bitmap) | ||
62 | { | ||
63 | INIT_LIST_HEAD(&bitmap->list); | ||
64 | } | ||
65 | |||
64 | /* Compare two btree extents. */ | 66 | /* Compare two btree extents. */ |
65 | static int | 67 | static int |
66 | xrep_btree_extent_cmp( | 68 | xfs_bitmap_range_cmp( |
67 | void *priv, | 69 | void *priv, |
68 | struct list_head *a, | 70 | struct list_head *a, |
69 | struct list_head *b) | 71 | struct list_head *b) |
70 | { | 72 | { |
71 | struct xrep_extent *ap; | 73 | struct xfs_bitmap_range *ap; |
72 | struct xrep_extent *bp; | 74 | struct xfs_bitmap_range *bp; |
73 | 75 | ||
74 | ap = container_of(a, struct xrep_extent, list); | 76 | ap = container_of(a, struct xfs_bitmap_range, list); |
75 | bp = container_of(b, struct xrep_extent, list); | 77 | bp = container_of(b, struct xfs_bitmap_range, list); |
76 | 78 | ||
77 | if (ap->fsbno > bp->fsbno) | 79 | if (ap->start > bp->start) |
78 | return 1; | 80 | return 1; |
79 | if (ap->fsbno < bp->fsbno) | 81 | if (ap->start < bp->start) |
80 | return -1; | 82 | return -1; |
81 | return 0; | 83 | return 0; |
82 | } | 84 | } |
83 | 85 | ||
84 | /* | 86 | /* |
85 | * Remove all the blocks mentioned in @sublist from the extents in @exlist. | 87 | * Remove all the blocks mentioned in @sub from the extents in @bitmap. |
86 | * | 88 | * |
87 | * The intent is that callers will iterate the rmapbt for all of its records | 89 | * The intent is that callers will iterate the rmapbt for all of its records |
88 | * for a given owner to generate @exlist; and iterate all the blocks of the | 90 | * for a given owner to generate @bitmap; and iterate all the blocks of the |
89 | * metadata structures that are not being rebuilt and have the same rmapbt | 91 | * metadata structures that are not being rebuilt and have the same rmapbt |
90 | * owner to generate @sublist. This routine subtracts all the extents | 92 | * owner to generate @sub. This routine subtracts all the extents |
91 | * mentioned in sublist from all the extents linked in @exlist, which leaves | 93 | * mentioned in sub from all the extents linked in @bitmap, which leaves |
92 | * @exlist as the list of blocks that are not accounted for, which we assume | 94 | * @bitmap as the list of blocks that are not accounted for, which we assume |
93 | * are the dead blocks of the old metadata structure. The blocks mentioned in | 95 | * are the dead blocks of the old metadata structure. The blocks mentioned in |
94 | * @exlist can be reaped. | 96 | * @bitmap can be reaped. |
97 | * | ||
98 | * This is the logical equivalent of bitmap &= ~sub. | ||
95 | */ | 99 | */ |
96 | #define LEFT_ALIGNED (1 << 0) | 100 | #define LEFT_ALIGNED (1 << 0) |
97 | #define RIGHT_ALIGNED (1 << 1) | 101 | #define RIGHT_ALIGNED (1 << 1) |
98 | int | 102 | int |
99 | xrep_subtract_extents( | 103 | xfs_bitmap_disunion( |
100 | struct xfs_scrub *sc, | 104 | struct xfs_bitmap *bitmap, |
101 | struct xrep_extent_list *exlist, | 105 | struct xfs_bitmap *sub) |
102 | struct xrep_extent_list *sublist) | ||
103 | { | 106 | { |
104 | struct list_head *lp; | 107 | struct list_head *lp; |
105 | struct xrep_extent *ex; | 108 | struct xfs_bitmap_range *br; |
106 | struct xrep_extent *newex; | 109 | struct xfs_bitmap_range *new_br; |
107 | struct xrep_extent *subex; | 110 | struct xfs_bitmap_range *sub_br; |
108 | xfs_fsblock_t sub_fsb; | 111 | uint64_t sub_start; |
109 | xfs_extlen_t sub_len; | 112 | uint64_t sub_len; |
110 | int state; | 113 | int state; |
111 | int error = 0; | 114 | int error = 0; |
112 | 115 | ||
113 | if (list_empty(&exlist->list) || list_empty(&sublist->list)) | 116 | if (list_empty(&bitmap->list) || list_empty(&sub->list)) |
114 | return 0; | 117 | return 0; |
115 | ASSERT(!list_empty(&sublist->list)); | 118 | ASSERT(!list_empty(&sub->list)); |
116 | 119 | ||
117 | list_sort(NULL, &exlist->list, xrep_btree_extent_cmp); | 120 | list_sort(NULL, &bitmap->list, xfs_bitmap_range_cmp); |
118 | list_sort(NULL, &sublist->list, xrep_btree_extent_cmp); | 121 | list_sort(NULL, &sub->list, xfs_bitmap_range_cmp); |
119 | 122 | ||
120 | /* | 123 | /* |
121 | * Now that we've sorted both lists, we iterate exlist once, rolling | 124 | * Now that we've sorted both lists, we iterate bitmap once, rolling |
122 | * forward through sublist and/or exlist as necessary until we find an | 125 | * forward through sub and/or bitmap as necessary until we find an |
123 | * overlap or reach the end of either list. We do not reset lp to the | 126 | * overlap or reach the end of either list. We do not reset lp to the |
124 | * head of exlist nor do we reset subex to the head of sublist. The | 127 | * head of bitmap nor do we reset sub_br to the head of sub. The |
125 | * list traversal is similar to merge sort, but we're deleting | 128 | * list traversal is similar to merge sort, but we're deleting |
126 | * instead. In this manner we avoid O(n^2) operations. | 129 | * instead. In this manner we avoid O(n^2) operations. |
127 | */ | 130 | */ |
128 | subex = list_first_entry(&sublist->list, struct xrep_extent, | 131 | sub_br = list_first_entry(&sub->list, struct xfs_bitmap_range, |
129 | list); | 132 | list); |
130 | lp = exlist->list.next; | 133 | lp = bitmap->list.next; |
131 | while (lp != &exlist->list) { | 134 | while (lp != &bitmap->list) { |
132 | ex = list_entry(lp, struct xrep_extent, list); | 135 | br = list_entry(lp, struct xfs_bitmap_range, list); |
133 | 136 | ||
134 | /* | 137 | /* |
135 | * Advance subex and/or ex until we find a pair that | 138 | * Advance sub_br and/or br until we find a pair that |
136 | * intersect or we run out of extents. | 139 | * intersect or we run out of extents. |
137 | */ | 140 | */ |
138 | while (subex->fsbno + subex->len <= ex->fsbno) { | 141 | while (sub_br->start + sub_br->len <= br->start) { |
139 | if (list_is_last(&subex->list, &sublist->list)) | 142 | if (list_is_last(&sub_br->list, &sub->list)) |
140 | goto out; | 143 | goto out; |
141 | subex = list_next_entry(subex, list); | 144 | sub_br = list_next_entry(sub_br, list); |
142 | } | 145 | } |
143 | if (subex->fsbno >= ex->fsbno + ex->len) { | 146 | if (sub_br->start >= br->start + br->len) { |
144 | lp = lp->next; | 147 | lp = lp->next; |
145 | continue; | 148 | continue; |
146 | } | 149 | } |
147 | 150 | ||
148 | /* trim subex to fit the extent we have */ | 151 | /* trim sub_br to fit the extent we have */ |
149 | sub_fsb = subex->fsbno; | 152 | sub_start = sub_br->start; |
150 | sub_len = subex->len; | 153 | sub_len = sub_br->len; |
151 | if (subex->fsbno < ex->fsbno) { | 154 | if (sub_br->start < br->start) { |
152 | sub_len -= ex->fsbno - subex->fsbno; | 155 | sub_len -= br->start - sub_br->start; |
153 | sub_fsb = ex->fsbno; | 156 | sub_start = br->start; |
154 | } | 157 | } |
155 | if (sub_len > ex->len) | 158 | if (sub_len > br->len) |
156 | sub_len = ex->len; | 159 | sub_len = br->len; |
157 | 160 | ||
158 | state = 0; | 161 | state = 0; |
159 | if (sub_fsb == ex->fsbno) | 162 | if (sub_start == br->start) |
160 | state |= LEFT_ALIGNED; | 163 | state |= LEFT_ALIGNED; |
161 | if (sub_fsb + sub_len == ex->fsbno + ex->len) | 164 | if (sub_start + sub_len == br->start + br->len) |
162 | state |= RIGHT_ALIGNED; | 165 | state |= RIGHT_ALIGNED; |
163 | switch (state) { | 166 | switch (state) { |
164 | case LEFT_ALIGNED: | 167 | case LEFT_ALIGNED: |
165 | /* Coincides with only the left. */ | 168 | /* Coincides with only the left. */ |
166 | ex->fsbno += sub_len; | 169 | br->start += sub_len; |
167 | ex->len -= sub_len; | 170 | br->len -= sub_len; |
168 | break; | 171 | break; |
169 | case RIGHT_ALIGNED: | 172 | case RIGHT_ALIGNED: |
170 | /* Coincides with only the right. */ | 173 | /* Coincides with only the right. */ |
171 | ex->len -= sub_len; | 174 | br->len -= sub_len; |
172 | lp = lp->next; | 175 | lp = lp->next; |
173 | break; | 176 | break; |
174 | case LEFT_ALIGNED | RIGHT_ALIGNED: | 177 | case LEFT_ALIGNED | RIGHT_ALIGNED: |
175 | /* Total overlap, just delete ex. */ | 178 | /* Total overlap, just delete ex. */ |
176 | lp = lp->next; | 179 | lp = lp->next; |
177 | list_del(&ex->list); | 180 | list_del(&br->list); |
178 | kmem_free(ex); | 181 | kmem_free(br); |
179 | break; | 182 | break; |
180 | case 0: | 183 | case 0: |
181 | /* | 184 | /* |
182 | * Deleting from the middle: add the new right extent | 185 | * Deleting from the middle: add the new right extent |
183 | * and then shrink the left extent. | 186 | * and then shrink the left extent. |
184 | */ | 187 | */ |
185 | newex = kmem_alloc(sizeof(struct xrep_extent), | 188 | new_br = kmem_alloc(sizeof(struct xfs_bitmap_range), |
186 | KM_MAYFAIL); | 189 | KM_MAYFAIL); |
187 | if (!newex) { | 190 | if (!new_br) { |
188 | error = -ENOMEM; | 191 | error = -ENOMEM; |
189 | goto out; | 192 | goto out; |
190 | } | 193 | } |
191 | INIT_LIST_HEAD(&newex->list); | 194 | INIT_LIST_HEAD(&new_br->list); |
192 | newex->fsbno = sub_fsb + sub_len; | 195 | new_br->start = sub_start + sub_len; |
193 | newex->len = ex->fsbno + ex->len - newex->fsbno; | 196 | new_br->len = br->start + br->len - new_br->start; |
194 | list_add(&newex->list, &ex->list); | 197 | list_add(&new_br->list, &br->list); |
195 | ex->len = sub_fsb - ex->fsbno; | 198 | br->len = sub_start - br->start; |
196 | lp = lp->next; | 199 | lp = lp->next; |
197 | break; | 200 | break; |
198 | default: | 201 | default: |
diff --git a/fs/xfs/scrub/bitmap.h b/fs/xfs/scrub/bitmap.h index 1038157695a8..dad652ee9177 100644 --- a/fs/xfs/scrub/bitmap.h +++ b/fs/xfs/scrub/bitmap.h | |||
@@ -6,32 +6,27 @@ | |||
6 | #ifndef __XFS_SCRUB_BITMAP_H__ | 6 | #ifndef __XFS_SCRUB_BITMAP_H__ |
7 | #define __XFS_SCRUB_BITMAP_H__ | 7 | #define __XFS_SCRUB_BITMAP_H__ |
8 | 8 | ||
9 | struct xrep_extent { | 9 | struct xfs_bitmap_range { |
10 | struct list_head list; | 10 | struct list_head list; |
11 | xfs_fsblock_t fsbno; | 11 | uint64_t start; |
12 | xfs_extlen_t len; | 12 | uint64_t len; |
13 | }; | 13 | }; |
14 | 14 | ||
15 | struct xrep_extent_list { | 15 | struct xfs_bitmap { |
16 | struct list_head list; | 16 | struct list_head list; |
17 | }; | 17 | }; |
18 | 18 | ||
19 | static inline void | 19 | void xfs_bitmap_init(struct xfs_bitmap *bitmap); |
20 | xrep_init_extent_list( | 20 | void xfs_bitmap_destroy(struct xfs_bitmap *bitmap); |
21 | struct xrep_extent_list *exlist) | ||
22 | { | ||
23 | INIT_LIST_HEAD(&exlist->list); | ||
24 | } | ||
25 | 21 | ||
26 | #define for_each_xrep_extent_safe(rbe, n, exlist) \ | 22 | #define for_each_xfs_bitmap_extent(bex, n, bitmap) \ |
27 | list_for_each_entry_safe((rbe), (n), &(exlist)->list, list) | 23 | list_for_each_entry_safe((bex), (n), &(bitmap)->list, list) |
28 | int xrep_collect_btree_extent(struct xfs_scrub *sc, | 24 | |
29 | struct xrep_extent_list *btlist, xfs_fsblock_t fsbno, | 25 | #define for_each_xfs_bitmap_block(b, bex, n, bitmap) \ |
30 | xfs_extlen_t len); | 26 | list_for_each_entry_safe((bex), (n), &(bitmap)->list, list) \ |
31 | void xrep_cancel_btree_extents(struct xfs_scrub *sc, | 27 | for ((b) = bex->start; (b) < bex->start + bex->len; (b)++) |
32 | struct xrep_extent_list *btlist); | 28 | |
33 | int xrep_subtract_extents(struct xfs_scrub *sc, | 29 | int xfs_bitmap_set(struct xfs_bitmap *bitmap, uint64_t start, uint64_t len); |
34 | struct xrep_extent_list *exlist, | 30 | int xfs_bitmap_disunion(struct xfs_bitmap *bitmap, struct xfs_bitmap *sub); |
35 | struct xrep_extent_list *sublist); | ||
36 | 31 | ||
37 | #endif /* __XFS_SCRUB_BITMAP_H__ */ | 32 | #endif /* __XFS_SCRUB_BITMAP_H__ */ |
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c index 27a904ef6189..85b048b341a0 100644 --- a/fs/xfs/scrub/repair.c +++ b/fs/xfs/scrub/repair.c | |||
@@ -368,17 +368,17 @@ xrep_init_btblock( | |||
368 | * | 368 | * |
369 | * However, that leaves the matter of removing all the metadata describing the | 369 | * However, that leaves the matter of removing all the metadata describing the |
370 | * old broken structure. For primary metadata we use the rmap data to collect | 370 | * old broken structure. For primary metadata we use the rmap data to collect |
371 | * every extent with a matching rmap owner (exlist); we then iterate all other | 371 | * every extent with a matching rmap owner (bitmap); we then iterate all other |
372 | * metadata structures with the same rmap owner to collect the extents that | 372 | * metadata structures with the same rmap owner to collect the extents that |
373 | * cannot be removed (sublist). We then subtract sublist from exlist to | 373 | * cannot be removed (sublist). We then subtract sublist from bitmap to |
374 | * derive the blocks that were used by the old btree. These blocks can be | 374 | * derive the blocks that were used by the old btree. These blocks can be |
375 | * reaped. | 375 | * reaped. |
376 | * | 376 | * |
377 | * For rmapbt reconstructions we must use different tactics for extent | 377 | * For rmapbt reconstructions we must use different tactics for extent |
378 | * collection. First we iterate all primary metadata (this excludes the old | 378 | * collection. First we iterate all primary metadata (this excludes the old |
379 | * rmapbt, obviously) to generate new rmap records. The gaps in the rmap | 379 | * rmapbt, obviously) to generate new rmap records. The gaps in the rmap |
380 | * records are collected as exlist. The bnobt records are collected as | 380 | * records are collected as bitmap. The bnobt records are collected as |
381 | * sublist. As with the other btrees we subtract sublist from exlist, and the | 381 | * sublist. As with the other btrees we subtract sublist from bitmap, and the |
382 | * result (since the rmapbt lives in the free space) are the blocks from the | 382 | * result (since the rmapbt lives in the free space) are the blocks from the |
383 | * old rmapbt. | 383 | * old rmapbt. |
384 | * | 384 | * |
@@ -386,11 +386,11 @@ xrep_init_btblock( | |||
386 | * | 386 | * |
387 | * Now that we've constructed a new btree to replace the damaged one, we want | 387 | * Now that we've constructed a new btree to replace the damaged one, we want |
388 | * to dispose of the blocks that (we think) the old btree was using. | 388 | * to dispose of the blocks that (we think) the old btree was using. |
389 | * Previously, we used the rmapbt to collect the extents (exlist) with the | 389 | * Previously, we used the rmapbt to collect the extents (bitmap) with the |
390 | * rmap owner corresponding to the tree we rebuilt, collected extents for any | 390 | * rmap owner corresponding to the tree we rebuilt, collected extents for any |
391 | * blocks with the same rmap owner that are owned by another data structure | 391 | * blocks with the same rmap owner that are owned by another data structure |
392 | * (sublist), and subtracted sublist from exlist. In theory the extents | 392 | * (sublist), and subtracted sublist from bitmap. In theory the extents |
393 | * remaining in exlist are the old btree's blocks. | 393 | * remaining in bitmap are the old btree's blocks. |
394 | * | 394 | * |
395 | * Unfortunately, it's possible that the btree was crosslinked with other | 395 | * Unfortunately, it's possible that the btree was crosslinked with other |
396 | * blocks on disk. The rmap data can tell us if there are multiple owners, so | 396 | * blocks on disk. The rmap data can tell us if there are multiple owners, so |
@@ -406,7 +406,7 @@ xrep_init_btblock( | |||
406 | * If there are no rmap records at all, we also free the block. If the btree | 406 | * If there are no rmap records at all, we also free the block. If the btree |
407 | * being rebuilt lives in the free space (bnobt/cntbt/rmapbt) then there isn't | 407 | * being rebuilt lives in the free space (bnobt/cntbt/rmapbt) then there isn't |
408 | * supposed to be a rmap record and everything is ok. For other btrees there | 408 | * supposed to be a rmap record and everything is ok. For other btrees there |
409 | * had to have been an rmap entry for the block to have ended up on @exlist, | 409 | * had to have been an rmap entry for the block to have ended up on @bitmap, |
410 | * so if it's gone now there's something wrong and the fs will shut down. | 410 | * so if it's gone now there's something wrong and the fs will shut down. |
411 | * | 411 | * |
412 | * Note: If there are multiple rmap records with only the same rmap owner as | 412 | * Note: If there are multiple rmap records with only the same rmap owner as |
@@ -419,7 +419,7 @@ xrep_init_btblock( | |||
419 | * The caller is responsible for locking the AG headers for the entire rebuild | 419 | * The caller is responsible for locking the AG headers for the entire rebuild |
420 | * operation so that nothing else can sneak in and change the AG state while | 420 | * operation so that nothing else can sneak in and change the AG state while |
421 | * we're not looking. We also assume that the caller already invalidated any | 421 | * we're not looking. We also assume that the caller already invalidated any |
422 | * buffers associated with @exlist. | 422 | * buffers associated with @bitmap. |
423 | */ | 423 | */ |
424 | 424 | ||
425 | /* | 425 | /* |
@@ -429,13 +429,12 @@ xrep_init_btblock( | |||
429 | int | 429 | int |
430 | xrep_invalidate_blocks( | 430 | xrep_invalidate_blocks( |
431 | struct xfs_scrub *sc, | 431 | struct xfs_scrub *sc, |
432 | struct xrep_extent_list *exlist) | 432 | struct xfs_bitmap *bitmap) |
433 | { | 433 | { |
434 | struct xrep_extent *rex; | 434 | struct xfs_bitmap_range *bmr; |
435 | struct xrep_extent *n; | 435 | struct xfs_bitmap_range *n; |
436 | struct xfs_buf *bp; | 436 | struct xfs_buf *bp; |
437 | xfs_fsblock_t fsbno; | 437 | xfs_fsblock_t fsbno; |
438 | xfs_agblock_t i; | ||
439 | 438 | ||
440 | /* | 439 | /* |
441 | * For each block in each extent, see if there's an incore buffer for | 440 | * For each block in each extent, see if there's an incore buffer for |
@@ -445,18 +444,16 @@ xrep_invalidate_blocks( | |||
445 | * because we never own those; and if we can't TRYLOCK the buffer we | 444 | * because we never own those; and if we can't TRYLOCK the buffer we |
446 | * assume it's owned by someone else. | 445 | * assume it's owned by someone else. |
447 | */ | 446 | */ |
448 | for_each_xrep_extent_safe(rex, n, exlist) { | 447 | for_each_xfs_bitmap_block(fsbno, bmr, n, bitmap) { |
449 | for (fsbno = rex->fsbno, i = rex->len; i > 0; fsbno++, i--) { | 448 | /* Skip AG headers and post-EOFS blocks */ |
450 | /* Skip AG headers and post-EOFS blocks */ | 449 | if (!xfs_verify_fsbno(sc->mp, fsbno)) |
451 | if (!xfs_verify_fsbno(sc->mp, fsbno)) | 450 | continue; |
452 | continue; | 451 | bp = xfs_buf_incore(sc->mp->m_ddev_targp, |
453 | bp = xfs_buf_incore(sc->mp->m_ddev_targp, | 452 | XFS_FSB_TO_DADDR(sc->mp, fsbno), |
454 | XFS_FSB_TO_DADDR(sc->mp, fsbno), | 453 | XFS_FSB_TO_BB(sc->mp, 1), XBF_TRYLOCK); |
455 | XFS_FSB_TO_BB(sc->mp, 1), XBF_TRYLOCK); | 454 | if (bp) { |
456 | if (bp) { | 455 | xfs_trans_bjoin(sc->tp, bp); |
457 | xfs_trans_bjoin(sc->tp, bp); | 456 | xfs_trans_binval(sc->tp, bp); |
458 | xfs_trans_binval(sc->tp, bp); | ||
459 | } | ||
460 | } | 457 | } |
461 | } | 458 | } |
462 | 459 | ||
@@ -519,9 +516,9 @@ xrep_put_freelist( | |||
519 | return 0; | 516 | return 0; |
520 | } | 517 | } |
521 | 518 | ||
522 | /* Dispose of a single metadata block. */ | 519 | /* Dispose of a single block. */ |
523 | STATIC int | 520 | STATIC int |
524 | xrep_dispose_btree_block( | 521 | xrep_reap_block( |
525 | struct xfs_scrub *sc, | 522 | struct xfs_scrub *sc, |
526 | xfs_fsblock_t fsbno, | 523 | xfs_fsblock_t fsbno, |
527 | struct xfs_owner_info *oinfo, | 524 | struct xfs_owner_info *oinfo, |
@@ -593,41 +590,35 @@ out_free: | |||
593 | return error; | 590 | return error; |
594 | } | 591 | } |
595 | 592 | ||
596 | /* Dispose of btree blocks from an old per-AG btree. */ | 593 | /* Dispose of every block of every extent in the bitmap. */ |
597 | int | 594 | int |
598 | xrep_reap_btree_extents( | 595 | xrep_reap_extents( |
599 | struct xfs_scrub *sc, | 596 | struct xfs_scrub *sc, |
600 | struct xrep_extent_list *exlist, | 597 | struct xfs_bitmap *bitmap, |
601 | struct xfs_owner_info *oinfo, | 598 | struct xfs_owner_info *oinfo, |
602 | enum xfs_ag_resv_type type) | 599 | enum xfs_ag_resv_type type) |
603 | { | 600 | { |
604 | struct xrep_extent *rex; | 601 | struct xfs_bitmap_range *bmr; |
605 | struct xrep_extent *n; | 602 | struct xfs_bitmap_range *n; |
603 | xfs_fsblock_t fsbno; | ||
606 | int error = 0; | 604 | int error = 0; |
607 | 605 | ||
608 | ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb)); | 606 | ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb)); |
609 | 607 | ||
610 | /* Dispose of every block from the old btree. */ | 608 | for_each_xfs_bitmap_block(fsbno, bmr, n, bitmap) { |
611 | for_each_xrep_extent_safe(rex, n, exlist) { | ||
612 | ASSERT(sc->ip != NULL || | 609 | ASSERT(sc->ip != NULL || |
613 | XFS_FSB_TO_AGNO(sc->mp, rex->fsbno) == sc->sa.agno); | 610 | XFS_FSB_TO_AGNO(sc->mp, fsbno) == sc->sa.agno); |
614 | |||
615 | trace_xrep_dispose_btree_extent(sc->mp, | 611 | trace_xrep_dispose_btree_extent(sc->mp, |
616 | XFS_FSB_TO_AGNO(sc->mp, rex->fsbno), | 612 | XFS_FSB_TO_AGNO(sc->mp, fsbno), |
617 | XFS_FSB_TO_AGBNO(sc->mp, rex->fsbno), rex->len); | 613 | XFS_FSB_TO_AGBNO(sc->mp, fsbno), 1); |
618 | 614 | ||
619 | for (; rex->len > 0; rex->len--, rex->fsbno++) { | 615 | error = xrep_reap_block(sc, fsbno, oinfo, type); |
620 | error = xrep_dispose_btree_block(sc, rex->fsbno, | 616 | if (error) |
621 | oinfo, type); | 617 | goto out; |
622 | if (error) | ||
623 | goto out; | ||
624 | } | ||
625 | list_del(&rex->list); | ||
626 | kmem_free(rex); | ||
627 | } | 618 | } |
628 | 619 | ||
629 | out: | 620 | out: |
630 | xrep_cancel_btree_extents(sc, exlist); | 621 | xfs_bitmap_destroy(bitmap); |
631 | return error; | 622 | return error; |
632 | } | 623 | } |
633 | 624 | ||
diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h index a3d491a438f4..5a4e92221916 100644 --- a/fs/xfs/scrub/repair.h +++ b/fs/xfs/scrub/repair.h | |||
@@ -27,13 +27,11 @@ int xrep_init_btblock(struct xfs_scrub *sc, xfs_fsblock_t fsb, | |||
27 | struct xfs_buf **bpp, xfs_btnum_t btnum, | 27 | struct xfs_buf **bpp, xfs_btnum_t btnum, |
28 | const struct xfs_buf_ops *ops); | 28 | const struct xfs_buf_ops *ops); |
29 | 29 | ||
30 | struct xrep_extent_list; | 30 | struct xfs_bitmap; |
31 | 31 | ||
32 | int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink); | 32 | int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink); |
33 | int xrep_invalidate_blocks(struct xfs_scrub *sc, | 33 | int xrep_invalidate_blocks(struct xfs_scrub *sc, struct xfs_bitmap *btlist); |
34 | struct xrep_extent_list *btlist); | 34 | int xrep_reap_extents(struct xfs_scrub *sc, struct xfs_bitmap *exlist, |
35 | int xrep_reap_btree_extents(struct xfs_scrub *sc, | ||
36 | struct xrep_extent_list *exlist, | ||
37 | struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type); | 35 | struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type); |
38 | 36 | ||
39 | struct xrep_find_ag_btree { | 37 | struct xrep_find_ag_btree { |
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index 93db22c39b51..4e20f0e48232 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h | |||
@@ -511,7 +511,6 @@ DEFINE_EVENT(xrep_extent_class, name, \ | |||
511 | xfs_agblock_t agbno, xfs_extlen_t len), \ | 511 | xfs_agblock_t agbno, xfs_extlen_t len), \ |
512 | TP_ARGS(mp, agno, agbno, len)) | 512 | TP_ARGS(mp, agno, agbno, len)) |
513 | DEFINE_REPAIR_EXTENT_EVENT(xrep_dispose_btree_extent); | 513 | DEFINE_REPAIR_EXTENT_EVENT(xrep_dispose_btree_extent); |
514 | DEFINE_REPAIR_EXTENT_EVENT(xrep_collect_btree_extent); | ||
515 | DEFINE_REPAIR_EXTENT_EVENT(xrep_agfl_insert); | 514 | DEFINE_REPAIR_EXTENT_EVENT(xrep_agfl_insert); |
516 | 515 | ||
517 | DECLARE_EVENT_CLASS(xrep_rmap_class, | 516 | DECLARE_EVENT_CLASS(xrep_rmap_class, |