summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-07-30 14:18:13 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2018-07-31 16:18:08 -0400
commit86d969b425d7ecf774799b70142b957dc267575b (patch)
tree740eb40605ec763a1e53deb6417c03e81647f18d
parent51d626903083f7bd651d38b031775740ed41758c (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.c183
-rw-r--r--fs/xfs/scrub/bitmap.h35
-rw-r--r--fs/xfs/scrub/repair.c85
-rw-r--r--fs/xfs/scrub/repair.h8
-rw-r--r--fs/xfs/scrub/trace.h1
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 */
20int 24int
21xrep_collect_btree_extent( 25xfs_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 */
50void 45void
51xrep_cancel_btree_extents( 46xfs_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. */
59void
60xfs_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. */
65static int 67static int
66xrep_btree_extent_cmp( 68xfs_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)
98int 102int
99xrep_subtract_extents( 103xfs_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
9struct xrep_extent { 9struct 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
15struct xrep_extent_list { 15struct xfs_bitmap {
16 struct list_head list; 16 struct list_head list;
17}; 17};
18 18
19static inline void 19void xfs_bitmap_init(struct xfs_bitmap *bitmap);
20xrep_init_extent_list( 20void 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)
28int 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) \
31void 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
33int xrep_subtract_extents(struct xfs_scrub *sc, 29int xfs_bitmap_set(struct xfs_bitmap *bitmap, uint64_t start, uint64_t len);
34 struct xrep_extent_list *exlist, 30int 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(
429int 429int
430xrep_invalidate_blocks( 430xrep_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. */
523STATIC int 520STATIC int
524xrep_dispose_btree_block( 521xrep_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. */
597int 594int
598xrep_reap_btree_extents( 595xrep_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
629out: 620out:
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
30struct xrep_extent_list; 30struct xfs_bitmap;
31 31
32int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink); 32int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink);
33int xrep_invalidate_blocks(struct xfs_scrub *sc, 33int xrep_invalidate_blocks(struct xfs_scrub *sc, struct xfs_bitmap *btlist);
34 struct xrep_extent_list *btlist); 34int xrep_reap_extents(struct xfs_scrub *sc, struct xfs_bitmap *exlist,
35int 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
39struct xrep_find_ag_btree { 37struct 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))
513DEFINE_REPAIR_EXTENT_EVENT(xrep_dispose_btree_extent); 513DEFINE_REPAIR_EXTENT_EVENT(xrep_dispose_btree_extent);
514DEFINE_REPAIR_EXTENT_EVENT(xrep_collect_btree_extent);
515DEFINE_REPAIR_EXTENT_EVENT(xrep_agfl_insert); 514DEFINE_REPAIR_EXTENT_EVENT(xrep_agfl_insert);
516 515
517DECLARE_EVENT_CLASS(xrep_rmap_class, 516DECLARE_EVENT_CLASS(xrep_rmap_class,