1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_btree.h"
13 #include "xfs_alloc.h"
15 #include "scrub/scrub.h"
16 #include "scrub/common.h"
17 #include "scrub/btree.h"
20 * Set us up to scrub free space btrees.
23 xchk_setup_ag_allocbt(
27 return xchk_setup_ag_btree(sc
, ip
, false);
30 /* Free space btree scrubber. */
32 * Ensure there's a corresponding cntbt/bnobt record matching this
33 * bnobt/cntbt record, respectively.
36 xchk_allocbt_xref_other(
41 struct xfs_btree_cur
**pcur
;
47 if (sc
->sm
->sm_type
== XFS_SCRUB_TYPE_BNOBT
)
48 pcur
= &sc
->sa
.cnt_cur
;
50 pcur
= &sc
->sa
.bno_cur
;
51 if (!*pcur
|| xchk_skip_xref(sc
->sm
))
54 error
= xfs_alloc_lookup_le(*pcur
, agbno
, len
, &has_otherrec
);
55 if (!xchk_should_check_xref(sc
, &error
, pcur
))
58 xchk_btree_xref_set_corrupt(sc
, *pcur
, 0);
62 error
= xfs_alloc_get_rec(*pcur
, &fbno
, &flen
, &has_otherrec
);
63 if (!xchk_should_check_xref(sc
, &error
, pcur
))
66 xchk_btree_xref_set_corrupt(sc
, *pcur
, 0);
70 if (fbno
!= agbno
|| flen
!= len
)
71 xchk_btree_xref_set_corrupt(sc
, *pcur
, 0);
74 /* Cross-reference with the other btrees. */
81 if (sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
)
84 xchk_allocbt_xref_other(sc
, agbno
, len
);
85 xchk_xref_is_not_inode_chunk(sc
, agbno
, len
);
86 xchk_xref_has_no_owner(sc
, agbno
, len
);
87 xchk_xref_is_not_shared(sc
, agbno
, len
);
90 /* Scrub a bnobt/cntbt record. */
93 struct xchk_btree
*bs
,
94 union xfs_btree_rec
*rec
)
96 struct xfs_mount
*mp
= bs
->cur
->bc_mp
;
97 xfs_agnumber_t agno
= bs
->cur
->bc_private
.a
.agno
;
101 bno
= be32_to_cpu(rec
->alloc
.ar_startblock
);
102 len
= be32_to_cpu(rec
->alloc
.ar_blockcount
);
104 if (bno
+ len
<= bno
||
105 !xfs_verify_agbno(mp
, agno
, bno
) ||
106 !xfs_verify_agbno(mp
, agno
, bno
+ len
- 1))
107 xchk_btree_set_corrupt(bs
->sc
, bs
->cur
, 0);
109 xchk_allocbt_xref(bs
->sc
, bno
, len
);
114 /* Scrub the freespace btrees for some AG. */
117 struct xfs_scrub
*sc
,
120 struct xfs_btree_cur
*cur
;
122 cur
= which
== XFS_BTNUM_BNO
? sc
->sa
.bno_cur
: sc
->sa
.cnt_cur
;
123 return xchk_btree(sc
, cur
, xchk_allocbt_rec
, &XFS_RMAP_OINFO_AG
, NULL
);
128 struct xfs_scrub
*sc
)
130 return xchk_allocbt(sc
, XFS_BTNUM_BNO
);
135 struct xfs_scrub
*sc
)
137 return xchk_allocbt(sc
, XFS_BTNUM_CNT
);
140 /* xref check that the extent is not free */
142 xchk_xref_is_used_space(
143 struct xfs_scrub
*sc
,
150 if (!sc
->sa
.bno_cur
|| xchk_skip_xref(sc
->sm
))
153 error
= xfs_alloc_has_record(sc
->sa
.bno_cur
, agbno
, len
, &is_freesp
);
154 if (!xchk_should_check_xref(sc
, &error
, &sc
->sa
.bno_cur
))
157 xchk_btree_xref_set_corrupt(sc
, sc
->sa
.bno_cur
, 0);