Skip to content

Commit b89116c

Browse files
dchinnerdgchinner
authored andcommitted
Merge tag 'scrub-strengthen-rmap-checking-6.4_2023-04-11' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into guilt/xfs-for-next
xfs: strengthen rmapbt scrubbing [v24.5] This series strengthens space allocation record cross referencing by using AG block bitmaps to compute the difference between space used according to the rmap records and the primary metadata, and reports cross-referencing errors for any discrepancies. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Dave Chinner <david@fromorbit.com>
2 parents 43223ef + 4f5e304 commit b89116c

5 files changed

Lines changed: 411 additions & 2 deletions

File tree

fs/xfs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ xfs-y += $(addprefix scrub/, \
148148
agheader.o \
149149
alloc.o \
150150
attr.o \
151+
bitmap.o \
151152
bmap.o \
152153
btree.o \
153154
common.o \
@@ -172,7 +173,6 @@ xfs-$(CONFIG_XFS_QUOTA) += scrub/quota.o
172173
ifeq ($(CONFIG_XFS_ONLINE_REPAIR),y)
173174
xfs-y += $(addprefix scrub/, \
174175
agheader_repair.o \
175-
bitmap.o \
176176
repair.o \
177177
)
178178
endif

fs/xfs/scrub/bitmap.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "xfs.h"
77
#include "xfs_fs.h"
88
#include "xfs_shared.h"
9+
#include "xfs_bit.h"
910
#include "xfs_format.h"
1011
#include "xfs_trans_resv.h"
1112
#include "xfs_mount.h"
@@ -262,6 +263,38 @@ xbitmap_disunion(
262263
* For the 300th record we just exit, with the list being [1, 4, 2, 3].
263264
*/
264265

266+
/* Mark a btree block to the agblock bitmap. */
267+
STATIC int
268+
xagb_bitmap_visit_btblock(
269+
struct xfs_btree_cur *cur,
270+
int level,
271+
void *priv)
272+
{
273+
struct xagb_bitmap *bitmap = priv;
274+
struct xfs_buf *bp;
275+
xfs_fsblock_t fsbno;
276+
xfs_agblock_t agbno;
277+
278+
xfs_btree_get_block(cur, level, &bp);
279+
if (!bp)
280+
return 0;
281+
282+
fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
283+
agbno = XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno);
284+
285+
return xagb_bitmap_set(bitmap, agbno, 1);
286+
}
287+
288+
/* Mark all (per-AG) btree blocks in the agblock bitmap. */
289+
int
290+
xagb_bitmap_set_btblocks(
291+
struct xagb_bitmap *bitmap,
292+
struct xfs_btree_cur *cur)
293+
{
294+
return xfs_btree_visit_blocks(cur, xagb_bitmap_visit_btblock,
295+
XFS_BTREE_VISIT_ALL, bitmap);
296+
}
297+
265298
/*
266299
* Record all the buffers pointed to by the btree cursor. Callers already
267300
* engaged in a btree walk should call this function to capture the list of
@@ -396,3 +429,25 @@ xbitmap_empty(
396429
{
397430
return bitmap->xb_root.rb_root.rb_node == NULL;
398431
}
432+
433+
/* Is the start of the range set or clear? And for how long? */
434+
bool
435+
xbitmap_test(
436+
struct xbitmap *bitmap,
437+
uint64_t start,
438+
uint64_t *len)
439+
{
440+
struct xbitmap_node *bn;
441+
uint64_t last = start + *len - 1;
442+
443+
bn = xbitmap_tree_iter_first(&bitmap->xb_root, start, last);
444+
if (!bn)
445+
return false;
446+
if (bn->bn_start <= start) {
447+
if (bn->bn_last < last)
448+
*len = bn->bn_last - start + 1;
449+
return true;
450+
}
451+
*len = bn->bn_start - start;
452+
return false;
453+
}

fs/xfs/scrub/bitmap.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,77 @@ int xbitmap_walk_bits(struct xbitmap *bitmap, xbitmap_walk_bits_fn fn,
3838
void *priv);
3939

4040
bool xbitmap_empty(struct xbitmap *bitmap);
41+
bool xbitmap_test(struct xbitmap *bitmap, uint64_t start, uint64_t *len);
42+
43+
/* Bitmaps, but for type-checked for xfs_agblock_t */
44+
45+
struct xagb_bitmap {
46+
struct xbitmap agbitmap;
47+
};
48+
49+
static inline void xagb_bitmap_init(struct xagb_bitmap *bitmap)
50+
{
51+
xbitmap_init(&bitmap->agbitmap);
52+
}
53+
54+
static inline void xagb_bitmap_destroy(struct xagb_bitmap *bitmap)
55+
{
56+
xbitmap_destroy(&bitmap->agbitmap);
57+
}
58+
59+
static inline int xagb_bitmap_clear(struct xagb_bitmap *bitmap,
60+
xfs_agblock_t start, xfs_extlen_t len)
61+
{
62+
return xbitmap_clear(&bitmap->agbitmap, start, len);
63+
}
64+
static inline int xagb_bitmap_set(struct xagb_bitmap *bitmap,
65+
xfs_agblock_t start, xfs_extlen_t len)
66+
{
67+
return xbitmap_set(&bitmap->agbitmap, start, len);
68+
}
69+
70+
static inline bool
71+
xagb_bitmap_test(
72+
struct xagb_bitmap *bitmap,
73+
xfs_agblock_t start,
74+
xfs_extlen_t *len)
75+
{
76+
uint64_t biglen = *len;
77+
bool ret;
78+
79+
ret = xbitmap_test(&bitmap->agbitmap, start, &biglen);
80+
81+
if (start + biglen >= UINT_MAX) {
82+
ASSERT(0);
83+
biglen = UINT_MAX - start;
84+
}
85+
86+
*len = biglen;
87+
return ret;
88+
}
89+
90+
static inline int xagb_bitmap_disunion(struct xagb_bitmap *bitmap,
91+
struct xagb_bitmap *sub)
92+
{
93+
return xbitmap_disunion(&bitmap->agbitmap, &sub->agbitmap);
94+
}
95+
96+
static inline uint32_t xagb_bitmap_hweight(struct xagb_bitmap *bitmap)
97+
{
98+
return xbitmap_hweight(&bitmap->agbitmap);
99+
}
100+
static inline bool xagb_bitmap_empty(struct xagb_bitmap *bitmap)
101+
{
102+
return xbitmap_empty(&bitmap->agbitmap);
103+
}
104+
105+
static inline int xagb_bitmap_walk(struct xagb_bitmap *bitmap,
106+
xbitmap_walk_fn fn, void *priv)
107+
{
108+
return xbitmap_walk(&bitmap->agbitmap, fn, priv);
109+
}
110+
111+
int xagb_bitmap_set_btblocks(struct xagb_bitmap *bitmap,
112+
struct xfs_btree_cur *cur);
41113

42114
#endif /* __XFS_SCRUB_BITMAP_H__ */

fs/xfs/scrub/repair.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ int xrep_init_btblock(struct xfs_scrub *sc, xfs_fsblock_t fsb,
3131
const struct xfs_buf_ops *ops);
3232

3333
struct xbitmap;
34+
struct xagb_bitmap;
3435

3536
int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink);
3637
int xrep_invalidate_blocks(struct xfs_scrub *sc, struct xbitmap *btlist);

0 commit comments

Comments
 (0)