aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/scrub/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/scrub/bitmap.c')
-rw-r--r--fs/xfs/scrub/bitmap.c92
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 */
254int
255xfs_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. */
278STATIC int
279xfs_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. */
297int
298xfs_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}