Skip to content

Commit 81fbc5f

Browse files
author
Chandan Babu R
committed
Merge tag 'repair-reap-fixes-6.6_2023-08-10' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.6-mergeA
xfs: fix online repair block reaping These patches fix a few problems that I noticed in the code that deals with old btree blocks after a successful repair. First, I observed that it is possible for repair to incorrectly invalidate and delete old btree blocks if they were crosslinked. The solution here is to consult the reverse mappings for each block in the extent -- singly owned blocks are invalidated and freed, whereas for crosslinked blocks, we merely drop the incorrect reverse mapping. A largeish change in this patchset is moving the reaping code to a separate file, because the code are mostly interrelated static functions. For now this also drops the ability to reap file blocks, which will return when we add the bmbt repair functions. Second, we convert the reap function to use EFIs so that we can commit to freeing as many blocks in as few transactions as we dare. We would like to free as many old blocks as we can in the same transaction that commits the new structure to the ondisk filesystem to minimize the number of blocks that leak if the system crashes before the repair fully completes. The third change made in this series is to avoid tripping buffer cache assertions if we're merely scanning the buffer cache for buffers to invalidate, and find a non-stale buffer of the wrong length. This is primarily cosmetic, but makes my life easier. The fourth change restructures the reaping code to try to process as many blocks in one go as possible, to reduce logging traffic. The last change switches the reaping mechanism to use per-AG bitmaps defined in a previous patchset. This should reduce type confusion when reading the source code. Signed-off-by: Darrick J. Wong <[email protected]> Signed-off-by: Chandan Babu R <[email protected]> * tag 'repair-reap-fixes-6.6_2023-08-10' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: use per-AG bitmaps to reap unused AG metadata blocks during repair xfs: reap large AG metadata extents when possible xfs: allow scanning ranges of the buffer cache for live buffers xfs: rearrange xrep_reap_block to make future code flow easier xfs: use deferred frees to reap old btree blocks xfs: only allow reaping of per-AG blocks in xrep_reap_extents xfs: only invalidate blocks if we're going to free them xfs: move the post-repair block reaping code to a separate file xfs: cull repair code that will never get used
2 parents 3eef001 + 014ad53 commit 81fbc5f

File tree

11 files changed

+673
-479
lines changed

11 files changed

+673
-479
lines changed

fs/xfs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ xfs-$(CONFIG_XFS_QUOTA) += scrub/quota.o
173173
ifeq ($(CONFIG_XFS_ONLINE_REPAIR),y)
174174
xfs-y += $(addprefix scrub/, \
175175
agheader_repair.o \
176+
reap.o \
176177
repair.o \
177178
)
178179
endif

fs/xfs/scrub/agheader_repair.c

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "scrub/trace.h"
2727
#include "scrub/repair.h"
2828
#include "scrub/bitmap.h"
29+
#include "scrub/reap.h"
2930

3031
/* Superblock */
3132

@@ -444,13 +445,13 @@ xrep_agf(
444445

445446
struct xrep_agfl {
446447
/* Bitmap of alleged AGFL blocks that we're not going to add. */
447-
struct xbitmap crossed;
448+
struct xagb_bitmap crossed;
448449

449450
/* Bitmap of other OWN_AG metadata blocks. */
450-
struct xbitmap agmetablocks;
451+
struct xagb_bitmap agmetablocks;
451452

452453
/* Bitmap of free space. */
453-
struct xbitmap *freesp;
454+
struct xagb_bitmap *freesp;
454455

455456
/* rmapbt cursor for finding crosslinked blocks */
456457
struct xfs_btree_cur *rmap_cur;
@@ -466,22 +467,20 @@ xrep_agfl_walk_rmap(
466467
void *priv)
467468
{
468469
struct xrep_agfl *ra = priv;
469-
xfs_fsblock_t fsb;
470470
int error = 0;
471471

472472
if (xchk_should_terminate(ra->sc, &error))
473473
return error;
474474

475475
/* Record all the OWN_AG blocks. */
476476
if (rec->rm_owner == XFS_RMAP_OWN_AG) {
477-
fsb = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno,
478-
rec->rm_startblock);
479-
error = xbitmap_set(ra->freesp, fsb, rec->rm_blockcount);
477+
error = xagb_bitmap_set(ra->freesp, rec->rm_startblock,
478+
rec->rm_blockcount);
480479
if (error)
481480
return error;
482481
}
483482

484-
return xbitmap_set_btcur_path(&ra->agmetablocks, cur);
483+
return xagb_bitmap_set_btcur_path(&ra->agmetablocks, cur);
485484
}
486485

487486
/* Strike out the blocks that are cross-linked according to the rmapbt. */
@@ -492,12 +491,10 @@ xrep_agfl_check_extent(
492491
void *priv)
493492
{
494493
struct xrep_agfl *ra = priv;
495-
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(ra->sc->mp, start);
494+
xfs_agblock_t agbno = start;
496495
xfs_agblock_t last_agbno = agbno + len - 1;
497496
int error;
498497

499-
ASSERT(XFS_FSB_TO_AGNO(ra->sc->mp, start) == ra->sc->sa.pag->pag_agno);
500-
501498
while (agbno <= last_agbno) {
502499
bool other_owners;
503500

@@ -507,7 +504,7 @@ xrep_agfl_check_extent(
507504
return error;
508505

509506
if (other_owners) {
510-
error = xbitmap_set(&ra->crossed, agbno, 1);
507+
error = xagb_bitmap_set(&ra->crossed, agbno, 1);
511508
if (error)
512509
return error;
513510
}
@@ -533,7 +530,7 @@ STATIC int
533530
xrep_agfl_collect_blocks(
534531
struct xfs_scrub *sc,
535532
struct xfs_buf *agf_bp,
536-
struct xbitmap *agfl_extents,
533+
struct xagb_bitmap *agfl_extents,
537534
xfs_agblock_t *flcount)
538535
{
539536
struct xrep_agfl ra;
@@ -543,8 +540,8 @@ xrep_agfl_collect_blocks(
543540

544541
ra.sc = sc;
545542
ra.freesp = agfl_extents;
546-
xbitmap_init(&ra.agmetablocks);
547-
xbitmap_init(&ra.crossed);
543+
xagb_bitmap_init(&ra.agmetablocks);
544+
xagb_bitmap_init(&ra.crossed);
548545

549546
/* Find all space used by the free space btrees & rmapbt. */
550547
cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
@@ -556,15 +553,15 @@ xrep_agfl_collect_blocks(
556553
/* Find all blocks currently being used by the bnobt. */
557554
cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
558555
sc->sa.pag, XFS_BTNUM_BNO);
559-
error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
556+
error = xagb_bitmap_set_btblocks(&ra.agmetablocks, cur);
560557
xfs_btree_del_cursor(cur, error);
561558
if (error)
562559
goto out_bmp;
563560

564561
/* Find all blocks currently being used by the cntbt. */
565562
cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
566563
sc->sa.pag, XFS_BTNUM_CNT);
567-
error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
564+
error = xagb_bitmap_set_btblocks(&ra.agmetablocks, cur);
568565
xfs_btree_del_cursor(cur, error);
569566
if (error)
570567
goto out_bmp;
@@ -573,30 +570,30 @@ xrep_agfl_collect_blocks(
573570
* Drop the freesp meta blocks that are in use by btrees.
574571
* The remaining blocks /should/ be AGFL blocks.
575572
*/
576-
error = xbitmap_disunion(agfl_extents, &ra.agmetablocks);
573+
error = xagb_bitmap_disunion(agfl_extents, &ra.agmetablocks);
577574
if (error)
578575
goto out_bmp;
579576

580577
/* Strike out the blocks that are cross-linked. */
581578
ra.rmap_cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
582-
error = xbitmap_walk(agfl_extents, xrep_agfl_check_extent, &ra);
579+
error = xagb_bitmap_walk(agfl_extents, xrep_agfl_check_extent, &ra);
583580
xfs_btree_del_cursor(ra.rmap_cur, error);
584581
if (error)
585582
goto out_bmp;
586-
error = xbitmap_disunion(agfl_extents, &ra.crossed);
583+
error = xagb_bitmap_disunion(agfl_extents, &ra.crossed);
587584
if (error)
588585
goto out_bmp;
589586

590587
/*
591588
* Calculate the new AGFL size. If we found more blocks than fit in
592589
* the AGFL we'll free them later.
593590
*/
594-
*flcount = min_t(uint64_t, xbitmap_hweight(agfl_extents),
591+
*flcount = min_t(uint64_t, xagb_bitmap_hweight(agfl_extents),
595592
xfs_agfl_size(mp));
596593

597594
out_bmp:
598-
xbitmap_destroy(&ra.crossed);
599-
xbitmap_destroy(&ra.agmetablocks);
595+
xagb_bitmap_destroy(&ra.crossed);
596+
xagb_bitmap_destroy(&ra.agmetablocks);
600597
return error;
601598
}
602599

@@ -626,7 +623,7 @@ xrep_agfl_update_agf(
626623
}
627624

628625
struct xrep_agfl_fill {
629-
struct xbitmap used_extents;
626+
struct xagb_bitmap used_extents;
630627
struct xfs_scrub *sc;
631628
__be32 *agfl_bno;
632629
xfs_agblock_t flcount;
@@ -642,17 +639,15 @@ xrep_agfl_fill(
642639
{
643640
struct xrep_agfl_fill *af = priv;
644641
struct xfs_scrub *sc = af->sc;
645-
xfs_fsblock_t fsbno = start;
642+
xfs_agblock_t agbno = start;
646643
int error;
647644

648-
while (fsbno < start + len && af->fl_off < af->flcount)
649-
af->agfl_bno[af->fl_off++] =
650-
cpu_to_be32(XFS_FSB_TO_AGBNO(sc->mp, fsbno++));
645+
trace_xrep_agfl_insert(sc->sa.pag, agbno, len);
651646

652-
trace_xrep_agfl_insert(sc->mp, sc->sa.pag->pag_agno,
653-
XFS_FSB_TO_AGBNO(sc->mp, start), len);
647+
while (agbno < start + len && af->fl_off < af->flcount)
648+
af->agfl_bno[af->fl_off++] = cpu_to_be32(agbno++);
654649

655-
error = xbitmap_set(&af->used_extents, start, fsbno - 1);
650+
error = xagb_bitmap_set(&af->used_extents, start, agbno - 1);
656651
if (error)
657652
return error;
658653

@@ -667,7 +662,7 @@ STATIC int
667662
xrep_agfl_init_header(
668663
struct xfs_scrub *sc,
669664
struct xfs_buf *agfl_bp,
670-
struct xbitmap *agfl_extents,
665+
struct xagb_bitmap *agfl_extents,
671666
xfs_agblock_t flcount)
672667
{
673668
struct xrep_agfl_fill af = {
@@ -695,17 +690,17 @@ xrep_agfl_init_header(
695690
* blocks than fit in the AGFL, they will be freed in a subsequent
696691
* step.
697692
*/
698-
xbitmap_init(&af.used_extents);
693+
xagb_bitmap_init(&af.used_extents);
699694
af.agfl_bno = xfs_buf_to_agfl_bno(agfl_bp),
700-
xbitmap_walk(agfl_extents, xrep_agfl_fill, &af);
701-
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);
702697
if (error)
703698
return error;
704699

705700
/* Write new AGFL to disk. */
706701
xfs_trans_buf_set_type(sc->tp, agfl_bp, XFS_BLFT_AGFL_BUF);
707702
xfs_trans_log_buf(sc->tp, agfl_bp, 0, BBTOB(agfl_bp->b_length) - 1);
708-
xbitmap_destroy(&af.used_extents);
703+
xagb_bitmap_destroy(&af.used_extents);
709704
return 0;
710705
}
711706

@@ -714,7 +709,7 @@ int
714709
xrep_agfl(
715710
struct xfs_scrub *sc)
716711
{
717-
struct xbitmap agfl_extents;
712+
struct xagb_bitmap agfl_extents;
718713
struct xfs_mount *mp = sc->mp;
719714
struct xfs_buf *agf_bp;
720715
struct xfs_buf *agfl_bp;
@@ -725,7 +720,7 @@ xrep_agfl(
725720
if (!xfs_has_rmapbt(mp))
726721
return -EOPNOTSUPP;
727722

728-
xbitmap_init(&agfl_extents);
723+
xagb_bitmap_init(&agfl_extents);
729724

730725
/*
731726
* Read the AGF so that we can query the rmapbt. We hope that there's
@@ -774,10 +769,10 @@ xrep_agfl(
774769
goto err;
775770

776771
/* Dump any AGFL overflow. */
777-
error = xrep_reap_extents(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
772+
error = xrep_reap_agblocks(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
778773
XFS_AG_RESV_AGFL);
779774
err:
780-
xbitmap_destroy(&agfl_extents);
775+
xagb_bitmap_destroy(&agfl_extents);
781776
return error;
782777
}
783778

fs/xfs/scrub/bitmap.c

Lines changed: 3 additions & 75 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(
@@ -385,43 +350,6 @@ xbitmap_walk(
385350
return error;
386351
}
387352

388-
struct xbitmap_walk_bits {
389-
xbitmap_walk_bits_fn fn;
390-
void *priv;
391-
};
392-
393-
/* Walk all the bits in a run. */
394-
static int
395-
xbitmap_walk_bits_in_run(
396-
uint64_t start,
397-
uint64_t len,
398-
void *priv)
399-
{
400-
struct xbitmap_walk_bits *wb = priv;
401-
uint64_t i;
402-
int error = 0;
403-
404-
for (i = start; i < start + len; i++) {
405-
error = wb->fn(i, wb->priv);
406-
if (error)
407-
break;
408-
}
409-
410-
return error;
411-
}
412-
413-
/* Call a function for every set bit in this bitmap. */
414-
int
415-
xbitmap_walk_bits(
416-
struct xbitmap *bitmap,
417-
xbitmap_walk_bits_fn fn,
418-
void *priv)
419-
{
420-
struct xbitmap_walk_bits wb = {.fn = fn, .priv = priv};
421-
422-
return xbitmap_walk(bitmap, xbitmap_walk_bits_in_run, &wb);
423-
}
424-
425353
/* Does this bitmap have no bits set at all? */
426354
bool
427355
xbitmap_empty(

fs/xfs/scrub/bitmap.h

Lines changed: 2 additions & 8 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
/*
@@ -33,10 +29,6 @@ typedef int (*xbitmap_walk_fn)(uint64_t start, uint64_t len, void *priv);
3329
int xbitmap_walk(struct xbitmap *bitmap, xbitmap_walk_fn fn,
3430
void *priv);
3531

36-
typedef int (*xbitmap_walk_bits_fn)(uint64_t bit, void *priv);
37-
int xbitmap_walk_bits(struct xbitmap *bitmap, xbitmap_walk_bits_fn fn,
38-
void *priv);
39-
4032
bool xbitmap_empty(struct xbitmap *bitmap);
4133
bool xbitmap_test(struct xbitmap *bitmap, uint64_t start, uint64_t *len);
4234

@@ -110,5 +102,7 @@ static inline int xagb_bitmap_walk(struct xagb_bitmap *bitmap,
110102

111103
int xagb_bitmap_set_btblocks(struct xagb_bitmap *bitmap,
112104
struct xfs_btree_cur *cur);
105+
int xagb_bitmap_set_btcur_path(struct xagb_bitmap *bitmap,
106+
struct xfs_btree_cur *cur);
113107

114108
#endif /* __XFS_SCRUB_BITMAP_H__ */

0 commit comments

Comments
 (0)