xfs: detect incorrect gaps in rmap btree [v24.5]
Following in the theme of the last two patchsets, this one strengthens the rmap btree record checking so that scrub can count the number of space records that map to a given owner and that do not map to a given owner. This enables us to determine exclusive ownership of space that can't be shared. Signed-off-by: Darrick J. Wong <djwong@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCZDYdpAAKCRBKO3ySh0YR pk9sAQDXcVPG4a2TvTd+j95UkkPovjYjTJekTTlJL/Xo91rAxgD/fEx3I8A8vNes dxVeyT/CwiYOPRYxFE3g3UdJGbaeHQA= =ux+s -----END PGP SIGNATURE----- Merge tag 'scrub-detect-rmapbt-gaps-6.4_2023-04-11' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into guilt/xfs-for-next xfs: detect incorrect gaps in rmap btree [v24.5] Following in the theme of the last two patchsets, this one strengthens the rmap btree record checking so that scrub can count the number of space records that map to a given owner and that do not map to a given owner. This enables us to determine exclusive ownership of space that can't be shared. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
commit
b1bdab2526
@ -2735,65 +2735,141 @@ xfs_rmap_has_records(
|
||||
return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is there a record for this owner completely covering a given physical
|
||||
* extent? If so, *has_rmap will be set to true. If there is no record
|
||||
* or the record only covers part of the range, we set *has_rmap to false.
|
||||
* This function doesn't perform range lookups or offset checks, so it is
|
||||
* not suitable for checking data fork blocks.
|
||||
*/
|
||||
int
|
||||
xfs_rmap_record_exists(
|
||||
struct xfs_btree_cur *cur,
|
||||
struct xfs_rmap_ownercount {
|
||||
/* Owner that we're looking for. */
|
||||
struct xfs_rmap_irec good;
|
||||
|
||||
/* rmap search keys */
|
||||
struct xfs_rmap_irec low;
|
||||
struct xfs_rmap_irec high;
|
||||
|
||||
struct xfs_rmap_matches *results;
|
||||
|
||||
/* Stop early if we find a nonmatch? */
|
||||
bool stop_on_nonmatch;
|
||||
};
|
||||
|
||||
/* Does this rmap represent space that can have multiple owners? */
|
||||
static inline bool
|
||||
xfs_rmap_shareable(
|
||||
struct xfs_mount *mp,
|
||||
const struct xfs_rmap_irec *rmap)
|
||||
{
|
||||
if (!xfs_has_reflink(mp))
|
||||
return false;
|
||||
if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
|
||||
return false;
|
||||
if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
|
||||
XFS_RMAP_BMBT_BLOCK))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_rmap_ownercount_init(
|
||||
struct xfs_rmap_ownercount *roc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap)
|
||||
struct xfs_rmap_matches *results)
|
||||
{
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
int has_record;
|
||||
struct xfs_rmap_irec irec;
|
||||
int error;
|
||||
memset(roc, 0, sizeof(*roc));
|
||||
roc->results = results;
|
||||
|
||||
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
|
||||
ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
|
||||
(flags & XFS_RMAP_BMBT_BLOCK));
|
||||
roc->low.rm_startblock = bno;
|
||||
memset(&roc->high, 0xFF, sizeof(roc->high));
|
||||
roc->high.rm_startblock = bno + len - 1;
|
||||
|
||||
error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &irec,
|
||||
&has_record);
|
||||
if (error)
|
||||
return error;
|
||||
if (!has_record) {
|
||||
*has_rmap = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
|
||||
irec.rm_startblock + irec.rm_blockcount >= bno + len);
|
||||
return 0;
|
||||
memset(results, 0, sizeof(*results));
|
||||
roc->good.rm_startblock = bno;
|
||||
roc->good.rm_blockcount = len;
|
||||
roc->good.rm_owner = oinfo->oi_owner;
|
||||
roc->good.rm_offset = oinfo->oi_offset;
|
||||
if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
|
||||
roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
|
||||
if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
|
||||
roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
|
||||
}
|
||||
|
||||
struct xfs_rmap_key_state {
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/* For each rmap given, figure out if it doesn't match the key we want. */
|
||||
/* Figure out if this is a match for the owner. */
|
||||
STATIC int
|
||||
xfs_rmap_has_other_keys_helper(
|
||||
xfs_rmap_count_owners_helper(
|
||||
struct xfs_btree_cur *cur,
|
||||
const struct xfs_rmap_irec *rec,
|
||||
void *priv)
|
||||
{
|
||||
struct xfs_rmap_key_state *rks = priv;
|
||||
struct xfs_rmap_ownercount *roc = priv;
|
||||
struct xfs_rmap_irec check = *rec;
|
||||
unsigned int keyflags;
|
||||
bool filedata;
|
||||
int64_t delta;
|
||||
|
||||
if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
|
||||
((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
|
||||
return 0;
|
||||
return -ECANCELED;
|
||||
filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
|
||||
!(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
|
||||
|
||||
/* Trim the part of check that comes before the comparison range. */
|
||||
delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
|
||||
if (delta > 0) {
|
||||
check.rm_startblock += delta;
|
||||
check.rm_blockcount -= delta;
|
||||
if (filedata)
|
||||
check.rm_offset += delta;
|
||||
}
|
||||
|
||||
/* Trim the part of check that comes after the comparison range. */
|
||||
delta = (check.rm_startblock + check.rm_blockcount) -
|
||||
(roc->good.rm_startblock + roc->good.rm_blockcount);
|
||||
if (delta > 0)
|
||||
check.rm_blockcount -= delta;
|
||||
|
||||
/* Don't care about unwritten status for establishing ownership. */
|
||||
keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
|
||||
|
||||
if (check.rm_startblock == roc->good.rm_startblock &&
|
||||
check.rm_blockcount == roc->good.rm_blockcount &&
|
||||
check.rm_owner == roc->good.rm_owner &&
|
||||
check.rm_offset == roc->good.rm_offset &&
|
||||
keyflags == roc->good.rm_flags) {
|
||||
roc->results->matches++;
|
||||
} else {
|
||||
roc->results->non_owner_matches++;
|
||||
if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
|
||||
xfs_rmap_shareable(cur->bc_mp, &check))
|
||||
roc->results->bad_non_owner_matches++;
|
||||
}
|
||||
|
||||
if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
|
||||
return -ECANCELED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Count the number of owners and non-owners of this range of blocks. */
|
||||
int
|
||||
xfs_rmap_count_owners(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
struct xfs_rmap_matches *results)
|
||||
{
|
||||
struct xfs_rmap_ownercount roc;
|
||||
int error;
|
||||
|
||||
xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
|
||||
error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
|
||||
xfs_rmap_count_owners_helper, &roc);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* There can't be any non-owner rmaps that conflict with the given
|
||||
* owner if we didn't find any rmaps matching the owner.
|
||||
*/
|
||||
if (!results->matches)
|
||||
results->bad_non_owner_matches = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2806,28 +2882,26 @@ xfs_rmap_has_other_keys(
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap)
|
||||
bool *has_other)
|
||||
{
|
||||
struct xfs_rmap_irec low = {0};
|
||||
struct xfs_rmap_irec high;
|
||||
struct xfs_rmap_key_state rks;
|
||||
struct xfs_rmap_matches res;
|
||||
struct xfs_rmap_ownercount roc;
|
||||
int error;
|
||||
|
||||
xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
|
||||
*has_rmap = false;
|
||||
xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
|
||||
roc.stop_on_nonmatch = true;
|
||||
|
||||
low.rm_startblock = bno;
|
||||
memset(&high, 0xFF, sizeof(high));
|
||||
high.rm_startblock = bno + len - 1;
|
||||
|
||||
error = xfs_rmap_query_range(cur, &low, &high,
|
||||
xfs_rmap_has_other_keys_helper, &rks);
|
||||
error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
|
||||
xfs_rmap_count_owners_helper, &roc);
|
||||
if (error == -ECANCELED) {
|
||||
*has_rmap = true;
|
||||
*has_other = true;
|
||||
return 0;
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return error;
|
||||
*has_other = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
|
||||
|
@ -200,12 +200,24 @@ xfs_failaddr_t xfs_rmap_check_irec(struct xfs_btree_cur *cur,
|
||||
|
||||
int xfs_rmap_has_records(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
xfs_extlen_t len, enum xbtree_recpacking *outcome);
|
||||
int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
|
||||
struct xfs_rmap_matches {
|
||||
/* Number of owner matches. */
|
||||
unsigned long long matches;
|
||||
|
||||
/* Number of non-owner matches. */
|
||||
unsigned long long non_owner_matches;
|
||||
|
||||
/* Number of non-owner matches that conflict with the owner matches. */
|
||||
unsigned long long bad_non_owner_matches;
|
||||
};
|
||||
|
||||
int xfs_rmap_count_owners(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap);
|
||||
struct xfs_rmap_matches *rmatch);
|
||||
int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap);
|
||||
bool *has_other);
|
||||
int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap);
|
||||
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE;
|
||||
|
@ -51,7 +51,7 @@ xchk_superblock_xref(
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_xref_is_not_cow_staging(sc, agbno, 1);
|
||||
|
||||
@ -515,7 +515,7 @@ xchk_agf_xref(
|
||||
xchk_agf_xref_freeblks(sc);
|
||||
xchk_agf_xref_cntbt(sc);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_agf_xref_btreeblks(sc);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_xref_is_not_cow_staging(sc, agbno, 1);
|
||||
@ -644,7 +644,7 @@ xchk_agfl_block_xref(
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG);
|
||||
xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_xref_is_not_cow_staging(sc, agbno, 1);
|
||||
}
|
||||
@ -701,7 +701,7 @@ xchk_agfl_xref(
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_xref_is_not_cow_staging(sc, agbno, 1);
|
||||
|
||||
@ -857,7 +857,7 @@ xchk_agi_xref(
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xchk_agi_xref_icounts(sc);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_xref_is_not_cow_staging(sc, agbno, 1);
|
||||
xchk_agi_xref_fiblocks(sc);
|
||||
|
@ -308,6 +308,7 @@ xchk_bmap_iextent_xref(
|
||||
struct xchk_bmap_info *info,
|
||||
struct xfs_bmbt_irec *irec)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_mount *mp = info->sc->mp;
|
||||
xfs_agnumber_t agno;
|
||||
xfs_agblock_t agbno;
|
||||
@ -328,19 +329,30 @@ xchk_bmap_iextent_xref(
|
||||
xchk_bmap_xref_rmap(info, irec, agbno);
|
||||
switch (info->whichfork) {
|
||||
case XFS_DATA_FORK:
|
||||
if (!xfs_is_reflink_inode(info->sc->ip))
|
||||
if (!xfs_is_reflink_inode(info->sc->ip)) {
|
||||
xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
|
||||
info->whichfork, irec->br_startoff);
|
||||
xchk_xref_is_only_owned_by(info->sc, agbno,
|
||||
irec->br_blockcount, &oinfo);
|
||||
xchk_xref_is_not_shared(info->sc, agbno,
|
||||
irec->br_blockcount);
|
||||
}
|
||||
xchk_xref_is_not_cow_staging(info->sc, agbno,
|
||||
irec->br_blockcount);
|
||||
break;
|
||||
case XFS_ATTR_FORK:
|
||||
xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
|
||||
info->whichfork, irec->br_startoff);
|
||||
xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
|
||||
&oinfo);
|
||||
xchk_xref_is_not_shared(info->sc, agbno,
|
||||
irec->br_blockcount);
|
||||
xchk_xref_is_not_cow_staging(info->sc, agbno,
|
||||
irec->br_blockcount);
|
||||
break;
|
||||
case XFS_COW_FORK:
|
||||
xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
|
||||
&XFS_RMAP_OINFO_COW);
|
||||
xchk_xref_is_cow_staging(info->sc, agbno,
|
||||
irec->br_blockcount);
|
||||
xchk_xref_is_not_shared(info->sc, agbno,
|
||||
|
@ -402,7 +402,7 @@ xchk_btree_check_block_owner(
|
||||
if (!bs->sc->sa.bno_cur && btnum == XFS_BTNUM_BNO)
|
||||
bs->cur = NULL;
|
||||
|
||||
xchk_xref_is_owned_by(bs->sc, agbno, 1, bs->oinfo);
|
||||
xchk_xref_is_only_owned_by(bs->sc, agbno, 1, bs->oinfo);
|
||||
if (!bs->sc->sa.rmap_cur && btnum == XFS_BTNUM_RMAP)
|
||||
bs->cur = NULL;
|
||||
|
||||
|
@ -276,7 +276,7 @@ xchk_iallocbt_chunk(
|
||||
xchk_inobt_chunk_xref_finobt(sc, irec, agino, nr_inodes);
|
||||
else
|
||||
xchk_finobt_chunk_xref_inobt(sc, irec, agino, nr_inodes);
|
||||
xchk_xref_is_owned_by(sc, agbno, len, &XFS_RMAP_OINFO_INODES);
|
||||
xchk_xref_is_only_owned_by(sc, agbno, len, &XFS_RMAP_OINFO_INODES);
|
||||
xchk_xref_is_not_shared(sc, agbno, len);
|
||||
xchk_xref_is_not_cow_staging(sc, agbno, len);
|
||||
return true;
|
||||
@ -428,7 +428,7 @@ xchk_iallocbt_check_cluster(
|
||||
return 0;
|
||||
}
|
||||
|
||||
xchk_xref_is_owned_by(bs->sc, agbno, M_IGEO(mp)->blocks_per_cluster,
|
||||
xchk_xref_is_only_owned_by(bs->sc, agbno, M_IGEO(mp)->blocks_per_cluster,
|
||||
&XFS_RMAP_OINFO_INODES);
|
||||
|
||||
/* Grab the inode cluster buffer. */
|
||||
|
@ -556,7 +556,7 @@ xchk_inode_xref(
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_inode_xref_finobt(sc, ino);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
|
||||
xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_xref_is_not_cow_staging(sc, agbno, 1);
|
||||
xchk_inode_xref_bmap(sc, dip);
|
||||
|
@ -167,38 +167,29 @@ xchk_rmapbt(
|
||||
&XFS_RMAP_OINFO_AG, NULL);
|
||||
}
|
||||
|
||||
/* xref check that the extent is owned by a given owner */
|
||||
static inline void
|
||||
xchk_xref_check_owner(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool should_have_rmap)
|
||||
{
|
||||
bool has_rmap;
|
||||
int error;
|
||||
|
||||
if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
|
||||
return;
|
||||
|
||||
error = xfs_rmap_record_exists(sc->sa.rmap_cur, bno, len, oinfo,
|
||||
&has_rmap);
|
||||
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
|
||||
return;
|
||||
if (has_rmap != should_have_rmap)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
}
|
||||
|
||||
/* xref check that the extent is owned by a given owner */
|
||||
/* xref check that the extent is owned only by a given owner */
|
||||
void
|
||||
xchk_xref_is_owned_by(
|
||||
xchk_xref_is_only_owned_by(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
xchk_xref_check_owner(sc, bno, len, oinfo, true);
|
||||
struct xfs_rmap_matches res;
|
||||
int error;
|
||||
|
||||
if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
|
||||
return;
|
||||
|
||||
error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
|
||||
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
|
||||
return;
|
||||
if (res.matches != 1)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
if (res.bad_non_owner_matches)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
if (res.non_owner_matches)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
}
|
||||
|
||||
/* xref check that the extent is not owned by a given owner */
|
||||
@ -209,7 +200,19 @@ xchk_xref_is_not_owned_by(
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
xchk_xref_check_owner(sc, bno, len, oinfo, false);
|
||||
struct xfs_rmap_matches res;
|
||||
int error;
|
||||
|
||||
if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
|
||||
return;
|
||||
|
||||
error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
|
||||
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
|
||||
return;
|
||||
if (res.matches != 0)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
if (res.bad_non_owner_matches)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
}
|
||||
|
||||
/* xref check that the extent has no reverse mapping at all */
|
||||
|
@ -162,7 +162,7 @@ void xchk_xref_is_not_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len);
|
||||
void xchk_xref_is_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len);
|
||||
void xchk_xref_is_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
void xchk_xref_is_only_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo);
|
||||
void xchk_xref_is_not_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo);
|
||||
|
Loading…
x
Reference in New Issue
Block a user