diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:19:44 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-10-22 16:41:10 -0700 |
commit | 61868eecf1989c1eda421d596d17c27317237e7a (patch) | |
tree | 0633e90ecd264383c5bf968635a1686690332524 /fs/xfs/scrub/rtrefcount.c | |
parent | 732f6fe3d46895365dc7040d5098ff55929cd6d5 (diff) |
xfs: cross-reference chceks with the rt refcount btree
Use the realtime refcount btree to cross-reference other data
structures.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/scrub/rtrefcount.c')
-rw-r--r-- | fs/xfs/scrub/rtrefcount.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/fs/xfs/scrub/rtrefcount.c b/fs/xfs/scrub/rtrefcount.c index 21b74b9923de..ae0897b081ab 100644 --- a/fs/xfs/scrub/rtrefcount.c +++ b/fs/xfs/scrub/rtrefcount.c @@ -447,3 +447,69 @@ xchk_rtrefcountbt( out_unlock: return error; } + +/* xref check that a cow staging extent is marked in the rtrefcountbt. */ +void +xchk_xref_is_rt_cow_staging( + struct xfs_scrub *sc, + xfs_rtblock_t bno, + xfs_filblks_t len) +{ + struct xfs_refcount_irec rc; + bool has_cowflag; + int has_refcount; + int error; + + if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm)) + return; + + /* Find the CoW staging extent. */ + error = xfs_refcount_lookup_le(sc->sr.refc_cur, + bno + XFS_RTREFC_COW_START, &has_refcount); + if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) + return; + if (!has_refcount) { + xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); + return; + } + + error = xfs_refcount_get_rec(sc->sr.refc_cur, &rc, &has_refcount); + if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) + return; + if (!has_refcount) { + xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); + return; + } + + /* CoW flag must be set, refcount must be 1. */ + has_cowflag = (rc.rc_startblock & XFS_RTREFC_COW_START); + if (!has_cowflag || rc.rc_refcount != 1) + xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); + + /* Must be at least as long as what was passed in */ + if (rc.rc_blockcount < len) + xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); +} + +/* + * xref check that the extent is not shared. Only file data blocks + * can have multiple owners. + */ +void +xchk_xref_is_not_shared_rt( + struct xfs_scrub *sc, + xfs_rtblock_t bno, + xfs_filblks_t len) +{ + bool shared; + int error; + + if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm)) + return; + + error = xfs_refcount_has_record(sc->sr.refc_cur, bno, len, &shared); + if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) + return; + if (shared) + xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); +} |