diff options
Diffstat (limited to 'fs/xfs/scrub/bitmap.c')
-rw-r--r-- | fs/xfs/scrub/bitmap.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/fs/xfs/scrub/bitmap.c b/fs/xfs/scrub/bitmap.c index c770e2d0b6aa..fdadc9e1dc49 100644 --- a/fs/xfs/scrub/bitmap.c +++ b/fs/xfs/scrub/bitmap.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "xfs_format.h" | 9 | #include "xfs_format.h" |
10 | #include "xfs_trans_resv.h" | 10 | #include "xfs_trans_resv.h" |
11 | #include "xfs_mount.h" | 11 | #include "xfs_mount.h" |
12 | #include "xfs_btree.h" | ||
12 | #include "scrub/xfs_scrub.h" | 13 | #include "scrub/xfs_scrub.h" |
13 | #include "scrub/scrub.h" | 14 | #include "scrub/scrub.h" |
14 | #include "scrub/common.h" | 15 | #include "scrub/common.h" |
@@ -209,3 +210,94 @@ out: | |||
209 | } | 210 | } |
210 | #undef LEFT_ALIGNED | 211 | #undef LEFT_ALIGNED |
211 | #undef RIGHT_ALIGNED | 212 | #undef RIGHT_ALIGNED |
213 | |||
214 | /* | ||
215 | * Record all btree blocks seen while iterating all records of a btree. | ||
216 | * | ||
217 | * We know that the btree query_all function starts at the left edge and walks | ||
218 | * towards the right edge of the tree. Therefore, we know that we can walk up | ||
219 | * the btree cursor towards the root; if the pointer for a given level points | ||
220 | * to the first record/key in that block, we haven't seen this block before; | ||
221 | * and therefore we need to remember that we saw this block in the btree. | ||
222 | * | ||
223 | * So if our btree is: | ||
224 | * | ||
225 | * 4 | ||
226 | * / | \ | ||
227 | * 1 2 3 | ||
228 | * | ||
229 | * Pretend for this example that each leaf block has 100 btree records. For | ||
230 | * the first btree record, we'll observe that bc_ptrs[0] == 1, so we record | ||
231 | * that we saw block 1. Then we observe that bc_ptrs[1] == 1, so we record | ||
232 | * block 4. The list is [1, 4]. | ||
233 | * | ||
234 | * For the second btree record, we see that bc_ptrs[0] == 2, so we exit the | ||
235 | * loop. The list remains [1, 4]. | ||
236 | * | ||
237 | * For the 101st btree record, we've moved onto leaf block 2. Now | ||
238 | * bc_ptrs[0] == 1 again, so we record that we saw block 2. We see that | ||
239 | * bc_ptrs[1] == 2, so we exit the loop. The list is now [1, 4, 2]. | ||
240 | * | ||
241 | * For the 102nd record, bc_ptrs[0] == 2, so we continue. | ||
242 | * | ||
243 | * For the 201st record, we've moved on to leaf block 3. bc_ptrs[0] == 1, so | ||
244 | * we add 3 to the list. Now it is [1, 4, 2, 3]. | ||
245 | * | ||
246 | * For the 300th record we just exit, with the list being [1, 4, 2, 3]. | ||
247 | */ | ||
248 | |||
249 | /* | ||
250 | * Record all the buffers pointed to by the btree cursor. Callers already | ||
251 | * engaged in a btree walk should call this function to capture the list of | ||
252 | * blocks going from the leaf towards the root. | ||
253 | */ | ||
254 | int | ||
255 | xfs_bitmap_set_btcur_path( | ||
256 | struct xfs_bitmap *bitmap, | ||
257 | struct xfs_btree_cur *cur) | ||
258 | { | ||
259 | struct xfs_buf *bp; | ||
260 | xfs_fsblock_t fsb; | ||
261 | int i; | ||
262 | int error; | ||
263 | |||
264 | for (i = 0; i < cur->bc_nlevels && cur->bc_ptrs[i] == 1; i++) { | ||
265 | xfs_btree_get_block(cur, i, &bp); | ||
266 | if (!bp) | ||
267 | continue; | ||
268 | fsb = XFS_DADDR_TO_FSB(cur->bc_mp, bp->b_bn); | ||
269 | error = xfs_bitmap_set(bitmap, fsb, 1); | ||
270 | if (error) | ||
271 | return error; | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | /* Collect a btree's block in the bitmap. */ | ||
278 | STATIC int | ||
279 | xfs_bitmap_collect_btblock( | ||
280 | struct xfs_btree_cur *cur, | ||
281 | int level, | ||
282 | void *priv) | ||
283 | { | ||
284 | struct xfs_bitmap *bitmap = priv; | ||
285 | struct xfs_buf *bp; | ||
286 | xfs_fsblock_t fsbno; | ||
287 | |||
288 | xfs_btree_get_block(cur, level, &bp); | ||
289 | if (!bp) | ||
290 | return 0; | ||
291 | |||
292 | fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, bp->b_bn); | ||
293 | return xfs_bitmap_set(bitmap, fsbno, 1); | ||
294 | } | ||
295 | |||
296 | /* Walk the btree and mark the bitmap wherever a btree block is found. */ | ||
297 | int | ||
298 | xfs_bitmap_set_btblocks( | ||
299 | struct xfs_bitmap *bitmap, | ||
300 | struct xfs_btree_cur *cur) | ||
301 | { | ||
302 | return xfs_btree_visit_blocks(cur, xfs_bitmap_collect_btblock, bitmap); | ||
303 | } | ||