Skip to content

Commit 178b48d

Browse files
author
Darrick J. Wong
committed
xfs: remove the for_each_xbitmap_ helpers
Remove the for_each_xbitmap_ macros in favor of proper iterator functions. We'll soon be switching this data structure over to an interval tree implementation, which means that we can't allow callers to modify the bitmap during iteration without telling us. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
1 parent 44af6c7 commit 178b48d

4 files changed

Lines changed: 180 additions & 94 deletions

File tree

fs/xfs/scrub/agheader_repair.c

Lines changed: 50 additions & 39 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,6 +625,43 @@ 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. */
633666
STATIC void
634667
xrep_agfl_init_header(
@@ -637,13 +670,12 @@ xrep_agfl_init_header(
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;
647679

648680
ASSERT(flcount <= xfs_agfl_size(mp));
649681

@@ -662,36 +694,15 @@ xrep_agfl_init_header(
662694
* blocks than fit in the AGFL, they will be freed in a subsequent
663695
* step.
664696
*/
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-
}
697+
xbitmap_init(&af.used_extents);
698+
af.agfl_bno = xfs_buf_to_agfl_bno(agfl_bp),
699+
xbitmap_walk(agfl_extents, xrep_agfl_fill, &af);
700+
xbitmap_disunion(agfl_extents, &af.used_extents);
691701

692702
/* Write new AGFL to disk. */
693703
xfs_trans_buf_set_type(sc->tp, agfl_bp, XFS_BLFT_AGFL_BUF);
694704
xfs_trans_log_buf(sc->tp, agfl_bp, 0, BBTOB(agfl_bp->b_length) - 1);
705+
xbitmap_destroy(&af.used_extents);
695706
}
696707

697708
/* Repair the AGFL. */

fs/xfs/scrub/bitmap.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "scrub/scrub.h"
1414
#include "scrub/bitmap.h"
1515

16+
#define for_each_xbitmap_extent(bex, n, bitmap) \
17+
list_for_each_entry_safe((bex), (n), &(bitmap)->list, list)
18+
1619
/*
1720
* Set a range of this bitmap. Caller must ensure the range is not set.
1821
*
@@ -313,3 +316,59 @@ xbitmap_hweight(
313316

314317
return ret;
315318
}
319+
320+
/* Call a function for every run of set bits in this bitmap. */
321+
int
322+
xbitmap_walk(
323+
struct xbitmap *bitmap,
324+
xbitmap_walk_fn fn,
325+
void *priv)
326+
{
327+
struct xbitmap_range *bex, *n;
328+
int error = 0;
329+
330+
for_each_xbitmap_extent(bex, n, bitmap) {
331+
error = fn(bex->start, bex->len, priv);
332+
if (error)
333+
break;
334+
}
335+
336+
return error;
337+
}
338+
339+
struct xbitmap_walk_bits {
340+
xbitmap_walk_bits_fn fn;
341+
void *priv;
342+
};
343+
344+
/* Walk all the bits in a run. */
345+
static int
346+
xbitmap_walk_bits_in_run(
347+
uint64_t start,
348+
uint64_t len,
349+
void *priv)
350+
{
351+
struct xbitmap_walk_bits *wb = priv;
352+
uint64_t i;
353+
int error = 0;
354+
355+
for (i = start; i < start + len; i++) {
356+
error = wb->fn(i, wb->priv);
357+
if (error)
358+
break;
359+
}
360+
361+
return error;
362+
}
363+
364+
/* Call a function for every set bit in this bitmap. */
365+
int
366+
xbitmap_walk_bits(
367+
struct xbitmap *bitmap,
368+
xbitmap_walk_bits_fn fn,
369+
void *priv)
370+
{
371+
struct xbitmap_walk_bits wb = {.fn = fn, .priv = priv};
372+
373+
return xbitmap_walk(bitmap, xbitmap_walk_bits_in_run, &wb);
374+
}

fs/xfs/scrub/bitmap.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@ struct xbitmap {
1919
void xbitmap_init(struct xbitmap *bitmap);
2020
void xbitmap_destroy(struct xbitmap *bitmap);
2121

22-
#define for_each_xbitmap_extent(bex, n, bitmap) \
23-
list_for_each_entry_safe((bex), (n), &(bitmap)->list, list)
24-
25-
#define for_each_xbitmap_block(b, bex, n, bitmap) \
26-
list_for_each_entry_safe((bex), (n), &(bitmap)->list, list) \
27-
for ((b) = (bex)->start; (b) < (bex)->start + (bex)->len; (b)++)
28-
2922
int xbitmap_set(struct xbitmap *bitmap, uint64_t start, uint64_t len);
3023
int xbitmap_disunion(struct xbitmap *bitmap, struct xbitmap *sub);
3124
int xbitmap_set_btcur_path(struct xbitmap *bitmap,
@@ -34,4 +27,19 @@ int xbitmap_set_btblocks(struct xbitmap *bitmap,
3427
struct xfs_btree_cur *cur);
3528
uint64_t xbitmap_hweight(struct xbitmap *bitmap);
3629

30+
/*
31+
* Return codes for the bitmap iterator functions are 0 to continue iterating,
32+
* and non-zero to stop iterating. Any non-zero value will be passed up to the
33+
* iteration caller. The special value -ECANCELED can be used to stop
34+
* iteration, because neither bitmap iterator ever generates that error code on
35+
* its own. Callers must not modify the bitmap while walking it.
36+
*/
37+
typedef int (*xbitmap_walk_fn)(uint64_t start, uint64_t len, void *priv);
38+
int xbitmap_walk(struct xbitmap *bitmap, xbitmap_walk_fn fn,
39+
void *priv);
40+
41+
typedef int (*xbitmap_walk_bits_fn)(uint64_t bit, void *priv);
42+
int xbitmap_walk_bits(struct xbitmap *bitmap, xbitmap_walk_bits_fn fn,
43+
void *priv);
44+
3745
#endif /* __XFS_SCRUB_BITMAP_H__ */

0 commit comments

Comments
 (0)