Skip to content

Commit 3a3108e

Browse files
author
Darrick J. Wong
committed
xfs: cross-reference rmap records with free space btrees
Strengthen the rmap btree record checker a little more by comparing OWN_AG reverse mappings against the free space btrees, the rmap btree, and the AGFL. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
1 parent fed050f commit 3a3108e

3 files changed

Lines changed: 102 additions & 0 deletions

File tree

fs/xfs/scrub/bitmap.c

Lines changed: 33 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

fs/xfs/scrub/bitmap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,7 @@ static inline int xagb_bitmap_walk(struct xagb_bitmap *bitmap,
108108
return xbitmap_walk(&bitmap->agbitmap, fn, priv);
109109
}
110110

111+
int xagb_bitmap_set_btblocks(struct xagb_bitmap *bitmap,
112+
struct xfs_btree_cur *cur);
113+
111114
#endif /* __XFS_SCRUB_BITMAP_H__ */

fs/xfs/scrub/rmap.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
#include "xfs_fs.h"
88
#include "xfs_shared.h"
99
#include "xfs_format.h"
10+
#include "xfs_log_format.h"
1011
#include "xfs_trans_resv.h"
1112
#include "xfs_mount.h"
13+
#include "xfs_trans.h"
1214
#include "xfs_btree.h"
1315
#include "xfs_rmap.h"
1416
#include "xfs_refcount.h"
1517
#include "xfs_ag.h"
1618
#include "xfs_bit.h"
19+
#include "xfs_alloc.h"
20+
#include "xfs_alloc_btree.h"
1721
#include "scrub/scrub.h"
1822
#include "scrub/common.h"
1923
#include "scrub/btree.h"
@@ -51,6 +55,7 @@ struct xchk_rmap {
5155
/* Bitmaps containing all blocks for each type of AG metadata. */
5256
struct xagb_bitmap fs_owned;
5357
struct xagb_bitmap log_owned;
58+
struct xagb_bitmap ag_owned;
5459

5560
/* Did we complete the AG space metadata bitmaps? */
5661
bool bitmaps_complete;
@@ -291,6 +296,9 @@ xchk_rmapbt_mark_bitmap(
291296
case XFS_RMAP_OWN_LOG:
292297
bmp = &cr->log_owned;
293298
break;
299+
case XFS_RMAP_OWN_AG:
300+
bmp = &cr->ag_owned;
301+
break;
294302
}
295303

296304
if (!bmp)
@@ -343,16 +351,36 @@ xchk_rmapbt_rec(
343351
return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
344352
}
345353

354+
/* Add an AGFL block to the rmap list. */
355+
STATIC int
356+
xchk_rmapbt_walk_agfl(
357+
struct xfs_mount *mp,
358+
xfs_agblock_t agbno,
359+
void *priv)
360+
{
361+
struct xagb_bitmap *bitmap = priv;
362+
363+
return xagb_bitmap_set(bitmap, agbno, 1);
364+
}
365+
346366
/*
347367
* Set up bitmaps mapping all the AG metadata to compare with the rmapbt
348368
* records.
369+
*
370+
* Grab our own btree cursors here if the scrub setup function didn't give us a
371+
* btree cursor due to reports of poor health. We need to find out if the
372+
* rmapbt disagrees with primary metadata btrees to tag the rmapbt as being
373+
* XCORRUPT.
349374
*/
350375
STATIC int
351376
xchk_rmapbt_walk_ag_metadata(
352377
struct xfs_scrub *sc,
353378
struct xchk_rmap *cr)
354379
{
355380
struct xfs_mount *mp = sc->mp;
381+
struct xfs_buf *agfl_bp;
382+
struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
383+
struct xfs_btree_cur *cur;
356384
int error;
357385

358386
/* OWN_FS: AG headers */
@@ -370,6 +398,39 @@ xchk_rmapbt_walk_ag_metadata(
370398
goto out;
371399
}
372400

401+
/* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
402+
cur = sc->sa.bno_cur;
403+
if (!cur)
404+
cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
405+
sc->sa.pag, XFS_BTNUM_BNO);
406+
error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
407+
if (cur != sc->sa.bno_cur)
408+
xfs_btree_del_cursor(cur, error);
409+
if (error)
410+
goto out;
411+
412+
cur = sc->sa.cnt_cur;
413+
if (!cur)
414+
cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
415+
sc->sa.pag, XFS_BTNUM_CNT);
416+
error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
417+
if (cur != sc->sa.cnt_cur)
418+
xfs_btree_del_cursor(cur, error);
419+
if (error)
420+
goto out;
421+
422+
error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
423+
if (error)
424+
goto out;
425+
426+
error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
427+
if (error)
428+
goto out;
429+
430+
error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
431+
&cr->ag_owned);
432+
xfs_trans_brelse(sc->tp, agfl_bp);
433+
373434
out:
374435
/*
375436
* If there's an error, set XFAIL and disable the bitmap
@@ -411,6 +472,9 @@ xchk_rmapbt_check_bitmaps(
411472

412473
if (xagb_bitmap_hweight(&cr->log_owned) != 0)
413474
xchk_btree_xref_set_corrupt(sc, cur, level);
475+
476+
if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
477+
xchk_btree_xref_set_corrupt(sc, cur, level);
414478
}
415479

416480
/* Scrub the rmap btree for some AG. */
@@ -427,6 +491,7 @@ xchk_rmapbt(
427491

428492
xagb_bitmap_init(&cr->fs_owned);
429493
xagb_bitmap_init(&cr->log_owned);
494+
xagb_bitmap_init(&cr->ag_owned);
430495

431496
error = xchk_rmapbt_walk_ag_metadata(sc, cr);
432497
if (error)
@@ -440,6 +505,7 @@ xchk_rmapbt(
440505
xchk_rmapbt_check_bitmaps(sc, cr);
441506

442507
out:
508+
xagb_bitmap_destroy(&cr->ag_owned);
443509
xagb_bitmap_destroy(&cr->log_owned);
444510
xagb_bitmap_destroy(&cr->fs_owned);
445511
kfree(cr);

0 commit comments

Comments
 (0)