Skip to content

Commit 014ad53

Browse files
author
Darrick J. Wong
committed
xfs: use per-AG bitmaps to reap unused AG metadata blocks during repair
The AGFL repair code uses a series of bitmaps to figure out where there are OWN_AG blocks that are not claimed by the free space and rmap btrees. These blocks become the new AGFL, and any overflow is reaped. The bitmaps current track xfs_fsblock_t even though we already know the AG number. In the last patch, we introduced a new bitmap "type" for tracking xfs_agblock_t extents. Port the reaping code and the AGFL repair to use this new type, which makes it very obvious what we're tracking. This also eliminates a bunch of unnecessary agblock <-> fsblock conversions. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Dave Chinner <[email protected]>
1 parent 1c7ce11 commit 014ad53

File tree

5 files changed

+45
-95
lines changed

5 files changed

+45
-95
lines changed

fs/xfs/scrub/agheader_repair.c

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -445,13 +445,13 @@ xrep_agf(
445445

446446
struct xrep_agfl {
447447
/* Bitmap of alleged AGFL blocks that we're not going to add. */
448-
struct xbitmap crossed;
448+
struct xagb_bitmap crossed;
449449

450450
/* Bitmap of other OWN_AG metadata blocks. */
451-
struct xbitmap agmetablocks;
451+
struct xagb_bitmap agmetablocks;
452452

453453
/* Bitmap of free space. */
454-
struct xbitmap *freesp;
454+
struct xagb_bitmap *freesp;
455455

456456
/* rmapbt cursor for finding crosslinked blocks */
457457
struct xfs_btree_cur *rmap_cur;
@@ -467,22 +467,20 @@ xrep_agfl_walk_rmap(
467467
void *priv)
468468
{
469469
struct xrep_agfl *ra = priv;
470-
xfs_fsblock_t fsb;
471470
int error = 0;
472471

473472
if (xchk_should_terminate(ra->sc, &error))
474473
return error;
475474

476475
/* Record all the OWN_AG blocks. */
477476
if (rec->rm_owner == XFS_RMAP_OWN_AG) {
478-
fsb = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno,
479-
rec->rm_startblock);
480-
error = xbitmap_set(ra->freesp, fsb, rec->rm_blockcount);
477+
error = xagb_bitmap_set(ra->freesp, rec->rm_startblock,
478+
rec->rm_blockcount);
481479
if (error)
482480
return error;
483481
}
484482

485-
return xbitmap_set_btcur_path(&ra->agmetablocks, cur);
483+
return xagb_bitmap_set_btcur_path(&ra->agmetablocks, cur);
486484
}
487485

488486
/* Strike out the blocks that are cross-linked according to the rmapbt. */
@@ -493,12 +491,10 @@ xrep_agfl_check_extent(
493491
void *priv)
494492
{
495493
struct xrep_agfl *ra = priv;
496-
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(ra->sc->mp, start);
494+
xfs_agblock_t agbno = start;
497495
xfs_agblock_t last_agbno = agbno + len - 1;
498496
int error;
499497

500-
ASSERT(XFS_FSB_TO_AGNO(ra->sc->mp, start) == ra->sc->sa.pag->pag_agno);
501-
502498
while (agbno <= last_agbno) {
503499
bool other_owners;
504500

@@ -508,7 +504,7 @@ xrep_agfl_check_extent(
508504
return error;
509505

510506
if (other_owners) {
511-
error = xbitmap_set(&ra->crossed, agbno, 1);
507+
error = xagb_bitmap_set(&ra->crossed, agbno, 1);
512508
if (error)
513509
return error;
514510
}
@@ -534,7 +530,7 @@ STATIC int
534530
xrep_agfl_collect_blocks(
535531
struct xfs_scrub *sc,
536532
struct xfs_buf *agf_bp,
537-
struct xbitmap *agfl_extents,
533+
struct xagb_bitmap *agfl_extents,
538534
xfs_agblock_t *flcount)
539535
{
540536
struct xrep_agfl ra;
@@ -544,8 +540,8 @@ xrep_agfl_collect_blocks(
544540

545541
ra.sc = sc;
546542
ra.freesp = agfl_extents;
547-
xbitmap_init(&ra.agmetablocks);
548-
xbitmap_init(&ra.crossed);
543+
xagb_bitmap_init(&ra.agmetablocks);
544+
xagb_bitmap_init(&ra.crossed);
549545

550546
/* Find all space used by the free space btrees & rmapbt. */
551547
cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
@@ -557,15 +553,15 @@ xrep_agfl_collect_blocks(
557553
/* Find all blocks currently being used by the bnobt. */
558554
cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
559555
sc->sa.pag, XFS_BTNUM_BNO);
560-
error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
556+
error = xagb_bitmap_set_btblocks(&ra.agmetablocks, cur);
561557
xfs_btree_del_cursor(cur, error);
562558
if (error)
563559
goto out_bmp;
564560

565561
/* Find all blocks currently being used by the cntbt. */
566562
cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
567563
sc->sa.pag, XFS_BTNUM_CNT);
568-
error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
564+
error = xagb_bitmap_set_btblocks(&ra.agmetablocks, cur);
569565
xfs_btree_del_cursor(cur, error);
570566
if (error)
571567
goto out_bmp;
@@ -574,30 +570,30 @@ xrep_agfl_collect_blocks(
574570
* Drop the freesp meta blocks that are in use by btrees.
575571
* The remaining blocks /should/ be AGFL blocks.
576572
*/
577-
error = xbitmap_disunion(agfl_extents, &ra.agmetablocks);
573+
error = xagb_bitmap_disunion(agfl_extents, &ra.agmetablocks);
578574
if (error)
579575
goto out_bmp;
580576

581577
/* Strike out the blocks that are cross-linked. */
582578
ra.rmap_cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
583-
error = xbitmap_walk(agfl_extents, xrep_agfl_check_extent, &ra);
579+
error = xagb_bitmap_walk(agfl_extents, xrep_agfl_check_extent, &ra);
584580
xfs_btree_del_cursor(ra.rmap_cur, error);
585581
if (error)
586582
goto out_bmp;
587-
error = xbitmap_disunion(agfl_extents, &ra.crossed);
583+
error = xagb_bitmap_disunion(agfl_extents, &ra.crossed);
588584
if (error)
589585
goto out_bmp;
590586

591587
/*
592588
* Calculate the new AGFL size. If we found more blocks than fit in
593589
* the AGFL we'll free them later.
594590
*/
595-
*flcount = min_t(uint64_t, xbitmap_hweight(agfl_extents),
591+
*flcount = min_t(uint64_t, xagb_bitmap_hweight(agfl_extents),
596592
xfs_agfl_size(mp));
597593

598594
out_bmp:
599-
xbitmap_destroy(&ra.crossed);
600-
xbitmap_destroy(&ra.agmetablocks);
595+
xagb_bitmap_destroy(&ra.crossed);
596+
xagb_bitmap_destroy(&ra.agmetablocks);
601597
return error;
602598
}
603599

@@ -627,7 +623,7 @@ xrep_agfl_update_agf(
627623
}
628624

629625
struct xrep_agfl_fill {
630-
struct xbitmap used_extents;
626+
struct xagb_bitmap used_extents;
631627
struct xfs_scrub *sc;
632628
__be32 *agfl_bno;
633629
xfs_agblock_t flcount;
@@ -643,17 +639,15 @@ xrep_agfl_fill(
643639
{
644640
struct xrep_agfl_fill *af = priv;
645641
struct xfs_scrub *sc = af->sc;
646-
xfs_fsblock_t fsbno = start;
642+
xfs_agblock_t agbno = start;
647643
int error;
648644

649-
trace_xrep_agfl_insert(sc->sa.pag, XFS_FSB_TO_AGBNO(sc->mp, start),
650-
len);
645+
trace_xrep_agfl_insert(sc->sa.pag, agbno, len);
651646

652-
while (fsbno < start + len && af->fl_off < af->flcount)
653-
af->agfl_bno[af->fl_off++] =
654-
cpu_to_be32(XFS_FSB_TO_AGBNO(sc->mp, fsbno++));
647+
while (agbno < start + len && af->fl_off < af->flcount)
648+
af->agfl_bno[af->fl_off++] = cpu_to_be32(agbno++);
655649

656-
error = xbitmap_set(&af->used_extents, start, fsbno - 1);
650+
error = xagb_bitmap_set(&af->used_extents, start, agbno - 1);
657651
if (error)
658652
return error;
659653

@@ -668,7 +662,7 @@ STATIC int
668662
xrep_agfl_init_header(
669663
struct xfs_scrub *sc,
670664
struct xfs_buf *agfl_bp,
671-
struct xbitmap *agfl_extents,
665+
struct xagb_bitmap *agfl_extents,
672666
xfs_agblock_t flcount)
673667
{
674668
struct xrep_agfl_fill af = {
@@ -696,17 +690,17 @@ xrep_agfl_init_header(
696690
* blocks than fit in the AGFL, they will be freed in a subsequent
697691
* step.
698692
*/
699-
xbitmap_init(&af.used_extents);
693+
xagb_bitmap_init(&af.used_extents);
700694
af.agfl_bno = xfs_buf_to_agfl_bno(agfl_bp),
701-
xbitmap_walk(agfl_extents, xrep_agfl_fill, &af);
702-
error = xbitmap_disunion(agfl_extents, &af.used_extents);
695+
xagb_bitmap_walk(agfl_extents, xrep_agfl_fill, &af);
696+
error = xagb_bitmap_disunion(agfl_extents, &af.used_extents);
703697
if (error)
704698
return error;
705699

706700
/* Write new AGFL to disk. */
707701
xfs_trans_buf_set_type(sc->tp, agfl_bp, XFS_BLFT_AGFL_BUF);
708702
xfs_trans_log_buf(sc->tp, agfl_bp, 0, BBTOB(agfl_bp->b_length) - 1);
709-
xbitmap_destroy(&af.used_extents);
703+
xagb_bitmap_destroy(&af.used_extents);
710704
return 0;
711705
}
712706

@@ -715,7 +709,7 @@ int
715709
xrep_agfl(
716710
struct xfs_scrub *sc)
717711
{
718-
struct xbitmap agfl_extents;
712+
struct xagb_bitmap agfl_extents;
719713
struct xfs_mount *mp = sc->mp;
720714
struct xfs_buf *agf_bp;
721715
struct xfs_buf *agfl_bp;
@@ -726,7 +720,7 @@ xrep_agfl(
726720
if (!xfs_has_rmapbt(mp))
727721
return -EOPNOTSUPP;
728722

729-
xbitmap_init(&agfl_extents);
723+
xagb_bitmap_init(&agfl_extents);
730724

731725
/*
732726
* Read the AGF so that we can query the rmapbt. We hope that there's
@@ -775,10 +769,10 @@ xrep_agfl(
775769
goto err;
776770

777771
/* Dump any AGFL overflow. */
778-
error = xrep_reap_ag_metadata(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
772+
error = xrep_reap_agblocks(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
779773
XFS_AG_RESV_AGFL);
780774
err:
781-
xbitmap_destroy(&agfl_extents);
775+
xagb_bitmap_destroy(&agfl_extents);
782776
return error;
783777
}
784778

fs/xfs/scrub/bitmap.c

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -301,57 +301,22 @@ xagb_bitmap_set_btblocks(
301301
* blocks going from the leaf towards the root.
302302
*/
303303
int
304-
xbitmap_set_btcur_path(
305-
struct xbitmap *bitmap,
304+
xagb_bitmap_set_btcur_path(
305+
struct xagb_bitmap *bitmap,
306306
struct xfs_btree_cur *cur)
307307
{
308-
struct xfs_buf *bp;
309-
xfs_fsblock_t fsb;
310308
int i;
311309
int error;
312310

313311
for (i = 0; i < cur->bc_nlevels && cur->bc_levels[i].ptr == 1; i++) {
314-
xfs_btree_get_block(cur, i, &bp);
315-
if (!bp)
316-
continue;
317-
fsb = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
318-
error = xbitmap_set(bitmap, fsb, 1);
312+
error = xagb_bitmap_visit_btblock(cur, i, bitmap);
319313
if (error)
320314
return error;
321315
}
322316

323317
return 0;
324318
}
325319

326-
/* Collect a btree's block in the bitmap. */
327-
STATIC int
328-
xbitmap_collect_btblock(
329-
struct xfs_btree_cur *cur,
330-
int level,
331-
void *priv)
332-
{
333-
struct xbitmap *bitmap = priv;
334-
struct xfs_buf *bp;
335-
xfs_fsblock_t fsbno;
336-
337-
xfs_btree_get_block(cur, level, &bp);
338-
if (!bp)
339-
return 0;
340-
341-
fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
342-
return xbitmap_set(bitmap, fsbno, 1);
343-
}
344-
345-
/* Walk the btree and mark the bitmap wherever a btree block is found. */
346-
int
347-
xbitmap_set_btblocks(
348-
struct xbitmap *bitmap,
349-
struct xfs_btree_cur *cur)
350-
{
351-
return xfs_btree_visit_blocks(cur, xbitmap_collect_btblock,
352-
XFS_BTREE_VISIT_ALL, bitmap);
353-
}
354-
355320
/* How many bits are set in this bitmap? */
356321
uint64_t
357322
xbitmap_hweight(

fs/xfs/scrub/bitmap.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ void xbitmap_destroy(struct xbitmap *bitmap);
1616
int xbitmap_clear(struct xbitmap *bitmap, uint64_t start, uint64_t len);
1717
int xbitmap_set(struct xbitmap *bitmap, uint64_t start, uint64_t len);
1818
int xbitmap_disunion(struct xbitmap *bitmap, struct xbitmap *sub);
19-
int xbitmap_set_btcur_path(struct xbitmap *bitmap,
20-
struct xfs_btree_cur *cur);
21-
int xbitmap_set_btblocks(struct xbitmap *bitmap,
22-
struct xfs_btree_cur *cur);
2319
uint64_t xbitmap_hweight(struct xbitmap *bitmap);
2420

2521
/*
@@ -106,5 +102,7 @@ static inline int xagb_bitmap_walk(struct xagb_bitmap *bitmap,
106102

107103
int xagb_bitmap_set_btblocks(struct xagb_bitmap *bitmap,
108104
struct xfs_btree_cur *cur);
105+
int xagb_bitmap_set_btcur_path(struct xagb_bitmap *bitmap,
106+
struct xfs_btree_cur *cur);
109107

110108
#endif /* __XFS_SCRUB_BITMAP_H__ */

fs/xfs/scrub/reap.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -431,19 +431,13 @@ xreap_agmeta_extent(
431431
{
432432
struct xreap_state *rs = priv;
433433
struct xfs_scrub *sc = rs->sc;
434-
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
435-
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
434+
xfs_agblock_t agbno = fsbno;
436435
xfs_agblock_t agbno_next = agbno + len;
437436
int error = 0;
438437

439438
ASSERT(len <= XFS_MAX_BMBT_EXTLEN);
440439
ASSERT(sc->ip == NULL);
441440

442-
if (agno != sc->sa.pag->pag_agno) {
443-
ASSERT(sc->sa.pag->pag_agno == agno);
444-
return -EFSCORRUPTED;
445-
}
446-
447441
while (agbno < agbno_next) {
448442
xfs_extlen_t aglen;
449443
bool crosslinked;
@@ -477,9 +471,9 @@ xreap_agmeta_extent(
477471

478472
/* Dispose of every block of every AG metadata extent in the bitmap. */
479473
int
480-
xrep_reap_ag_metadata(
474+
xrep_reap_agblocks(
481475
struct xfs_scrub *sc,
482-
struct xbitmap *bitmap,
476+
struct xagb_bitmap *bitmap,
483477
const struct xfs_owner_info *oinfo,
484478
enum xfs_ag_resv_type type)
485479
{
@@ -493,7 +487,7 @@ xrep_reap_ag_metadata(
493487
ASSERT(xfs_has_rmapbt(sc->mp));
494488
ASSERT(sc->ip == NULL);
495489

496-
error = xbitmap_walk(bitmap, xreap_agmeta_extent, &rs);
490+
error = xagb_bitmap_walk(bitmap, xreap_agmeta_extent, &rs);
497491
if (error)
498492
return error;
499493

fs/xfs/scrub/reap.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
#ifndef __XFS_SCRUB_REAP_H__
77
#define __XFS_SCRUB_REAP_H__
88

9-
int xrep_reap_ag_metadata(struct xfs_scrub *sc, struct xbitmap *bitmap,
10-
const struct xfs_owner_info *oinfo,
11-
enum xfs_ag_resv_type type);
9+
int xrep_reap_agblocks(struct xfs_scrub *sc, struct xagb_bitmap *bitmap,
10+
const struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type);
1211

1312
#endif /* __XFS_SCRUB_REAP_H__ */

0 commit comments

Comments
 (0)