Skip to content

Commit 43223ef

Browse files
dchinnerdgchinner
authored andcommitted
Merge tag 'repair-bitmap-rework-6.4_2023-04-11' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into guilt/xfs-for-next
xfs: rework online fsck incore bitmap [v24.5] In this series, we make some changes to the incore bitmap code: First, we shorten the prefix to 'xbitmap'. Then, we rework some utility functions for later use by online repair and clarify how the walk functions are supposed to be used. Finally, we use all these new pieces to convert the incore bitmap to use an interval tree instead of linked lists. This lifts the limitation that callers had to be careful not to set a range that was already set; and gets us ready for the btree rebuilder functions needing to be able to set bits in a bitmap and generate maximal contiguous extents for the set ranges. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Dave Chinner <david@fromorbit.com>
2 parents bb09d76 + 6772fcc commit 43223ef

4 files changed

Lines changed: 358 additions & 245 deletions

File tree

fs/xfs/scrub/agheader_repair.c

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,11 @@ xrep_agfl_walk_rmap(
487487
/* Strike out the blocks that are cross-linked according to the rmapbt. */
488488
STATIC int
489489
xrep_agfl_check_extent(
490-
struct xrep_agfl *ra,
491490
uint64_t start,
492-
uint64_t len)
491+
uint64_t len,
492+
void *priv)
493493
{
494+
struct xrep_agfl *ra = priv;
494495
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(ra->sc->mp, start);
495496
xfs_agblock_t last_agbno = agbno + len - 1;
496497
int error;
@@ -538,7 +539,6 @@ xrep_agfl_collect_blocks(
538539
struct xrep_agfl ra;
539540
struct xfs_mount *mp = sc->mp;
540541
struct xfs_btree_cur *cur;
541-
struct xbitmap_range *br, *n;
542542
int error;
543543

544544
ra.sc = sc;
@@ -579,11 +579,7 @@ xrep_agfl_collect_blocks(
579579

580580
/* Strike out the blocks that are cross-linked. */
581581
ra.rmap_cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
582-
for_each_xbitmap_extent(br, n, agfl_extents) {
583-
error = xrep_agfl_check_extent(&ra, br->start, br->len);
584-
if (error)
585-
break;
586-
}
582+
error = xbitmap_walk(agfl_extents, xrep_agfl_check_extent, &ra);
587583
xfs_btree_del_cursor(ra.rmap_cur, error);
588584
if (error)
589585
goto out_bmp;
@@ -629,21 +625,58 @@ xrep_agfl_update_agf(
629625
XFS_AGF_FLFIRST | XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
630626
}
631627

628+
struct xrep_agfl_fill {
629+
struct xbitmap used_extents;
630+
struct xfs_scrub *sc;
631+
__be32 *agfl_bno;
632+
xfs_agblock_t flcount;
633+
unsigned int fl_off;
634+
};
635+
636+
/* Fill the AGFL with whatever blocks are in this extent. */
637+
static int
638+
xrep_agfl_fill(
639+
uint64_t start,
640+
uint64_t len,
641+
void *priv)
642+
{
643+
struct xrep_agfl_fill *af = priv;
644+
struct xfs_scrub *sc = af->sc;
645+
xfs_fsblock_t fsbno = start;
646+
int error;
647+
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++));
651+
652+
trace_xrep_agfl_insert(sc->mp, sc->sa.pag->pag_agno,
653+
XFS_FSB_TO_AGBNO(sc->mp, start), len);
654+
655+
error = xbitmap_set(&af->used_extents, start, fsbno - 1);
656+
if (error)
657+
return error;
658+
659+
if (af->fl_off == af->flcount)
660+
return -ECANCELED;
661+
662+
return 0;
663+
}
664+
632665
/* Write out a totally new AGFL. */
633-
STATIC void
666+
STATIC int
634667
xrep_agfl_init_header(
635668
struct xfs_scrub *sc,
636669
struct xfs_buf *agfl_bp,
637670
struct xbitmap *agfl_extents,
638671
xfs_agblock_t flcount)
639672
{
673+
struct xrep_agfl_fill af = {
674+
.sc = sc,
675+
.flcount = flcount,
676+
};
640677
struct xfs_mount *mp = sc->mp;
641-
__be32 *agfl_bno;
642-
struct xbitmap_range *br;
643-
struct xbitmap_range *n;
644678
struct xfs_agfl *agfl;
645-
xfs_agblock_t agbno;
646-
unsigned int fl_off;
679+
int error;
647680

648681
ASSERT(flcount <= xfs_agfl_size(mp));
649682

@@ -662,36 +695,18 @@ xrep_agfl_init_header(
662695
* blocks than fit in the AGFL, they will be freed in a subsequent
663696
* step.
664697
*/
665-
fl_off = 0;
666-
agfl_bno = xfs_buf_to_agfl_bno(agfl_bp);
667-
for_each_xbitmap_extent(br, n, agfl_extents) {
668-
agbno = XFS_FSB_TO_AGBNO(mp, br->start);
669-
670-
trace_xrep_agfl_insert(mp, sc->sa.pag->pag_agno, agbno,
671-
br->len);
672-
673-
while (br->len > 0 && fl_off < flcount) {
674-
agfl_bno[fl_off] = cpu_to_be32(agbno);
675-
fl_off++;
676-
agbno++;
677-
678-
/*
679-
* We've now used br->start by putting it in the AGFL,
680-
* so bump br so that we don't reap the block later.
681-
*/
682-
br->start++;
683-
br->len--;
684-
}
685-
686-
if (br->len)
687-
break;
688-
list_del(&br->list);
689-
kfree(br);
690-
}
698+
xbitmap_init(&af.used_extents);
699+
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);
702+
if (error)
703+
return error;
691704

692705
/* Write new AGFL to disk. */
693706
xfs_trans_buf_set_type(sc->tp, agfl_bp, XFS_BLFT_AGFL_BUF);
694707
xfs_trans_log_buf(sc->tp, agfl_bp, 0, BBTOB(agfl_bp->b_length) - 1);
708+
xbitmap_destroy(&af.used_extents);
709+
return 0;
695710
}
696711

697712
/* Repair the AGFL. */
@@ -744,7 +759,9 @@ xrep_agfl(
744759
* buffers until we know that part works.
745760
*/
746761
xrep_agfl_update_agf(sc, agf_bp, flcount);
747-
xrep_agfl_init_header(sc, agfl_bp, &agfl_extents, flcount);
762+
error = xrep_agfl_init_header(sc, agfl_bp, &agfl_extents, flcount);
763+
if (error)
764+
goto err;
748765

749766
/*
750767
* Ok, the AGFL should be ready to go now. Roll the transaction to

0 commit comments

Comments
 (0)