diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:17:56 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-12-15 17:29:17 -0800 |
commit | d4334d0dcc4f1e25869eef89536db6a8d0ef28f1 (patch) | |
tree | 82b6faae429f30c13245571e78bbefbe5b56f47b /fs/xfs/scrub | |
parent | 81603d160bee4e13b11eafe7d72c0140ba50d1c5 (diff) |
xfs: scrub the realtime rmapbt
Check the realtime reverse mapping btree against the rtbitmap, and
modify the rtbitmap scrub to check against the rtrmapbt.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/scrub')
-rw-r--r-- | fs/xfs/scrub/bmap.c | 2 | ||||
-rw-r--r-- | fs/xfs/scrub/common.c | 35 | ||||
-rw-r--r-- | fs/xfs/scrub/common.h | 8 | ||||
-rw-r--r-- | fs/xfs/scrub/health.c | 1 | ||||
-rw-r--r-- | fs/xfs/scrub/repair.c | 1 | ||||
-rw-r--r-- | fs/xfs/scrub/rtrmap.c | 100 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.c | 9 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.h | 8 | ||||
-rw-r--r-- | fs/xfs/scrub/trace.h | 4 |
9 files changed, 165 insertions, 3 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index 81beb8e7e504..bede41ecedb3 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -315,6 +315,7 @@ xchk_bmap_rt_iextent_xref( xchk_xref_is_used_rt_space(info->sc, irec->br_startblock, irec->br_blockcount); + xchk_rt_btcur_free(&info->sc->sr); xchk_rt_unlock(info->sc, &info->sc->sr); } @@ -750,6 +751,7 @@ xchk_bmap( case XFS_DINODE_FMT_UUID: case XFS_DINODE_FMT_DEV: case XFS_DINODE_FMT_LOCAL: + case XFS_DINODE_FMT_RMAP: /* No mappings to check. */ goto out; case XFS_DINODE_FMT_EXTENTS: diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index 615032d69078..4b2582035f5a 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -29,6 +29,7 @@ #include "xfs_ag.h" #include "xfs_error.h" #include "xfs_rtalloc.h" +#include "xfs_rtrmap_btree.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/trace.h" @@ -599,6 +600,16 @@ xchk_ag_init( return 0; } +/* Lock everything we need to work on realtime metadata. */ +void +xchk_rt_lock( + struct xfs_scrub *sc, + struct xchk_rt *sr) +{ + xfs_rtlock(NULL, sc->mp, XFS_RTLOCK_ALL); + sr->locked = true; +} + /* * For scrubbing a realtime file, grab all the in-core resources we'll need to * check the realtime metadata, which means taking the ILOCK of the realtime @@ -610,8 +621,28 @@ xchk_rt_init( struct xfs_scrub *sc, struct xchk_rt *sr) { - xfs_rtlock(NULL, sc->mp, XFS_RTLOCK_ALL); - sr->locked = true; + struct xfs_mount *mp = sc->mp; + + xchk_rt_lock(sc, sr); + + if (xfs_has_rtrmapbt(mp)) + sr->rmap_cur = xfs_rtrmapbt_init_cursor(mp, sc->tp, + mp->m_rrmapip); +} + +/* + * Free all the btree cursors and other incore data relating to the realtime + * volume. This has to be done /before/ committing (or cancelling) the scrub + * transaction. + */ +void +xchk_rt_btcur_free( + struct xchk_rt *sr) +{ + if (sr->rmap_cur) + xfs_btree_del_cursor(sr->rmap_cur, XFS_BTREE_ERROR); + + sr->rmap_cur = NULL; } /* diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index 263dbd9e5b46..a4d9d4abc7f4 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -92,6 +92,7 @@ int xchk_setup_parent(struct xfs_scrub *sc); #ifdef CONFIG_XFS_RT int xchk_setup_rtbitmap(struct xfs_scrub *sc); int xchk_setup_rtsummary(struct xfs_scrub *sc); +int xchk_setup_rtrmapbt(struct xfs_scrub *sc); #else static inline int xchk_setup_rtbitmap(struct xfs_scrub *sc) @@ -103,6 +104,11 @@ xchk_setup_rtsummary(struct xfs_scrub *sc) { return -ENOENT; } +static inline int +xchk_setup_rtrmapbt(struct xfs_scrub *sc) +{ + return -ENOENT; +} #endif #ifdef CONFIG_XFS_QUOTA int xchk_setup_quota(struct xfs_scrub *sc); @@ -143,6 +149,8 @@ xchk_ag_init_existing( } void xchk_rt_init(struct xfs_scrub *sc, struct xchk_rt *sr); +void xchk_rt_btcur_free(struct xchk_rt *sr); +void xchk_rt_lock(struct xfs_scrub *sc, struct xchk_rt *sr); void xchk_rt_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno, struct xchk_ag *sa); diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c index 9fbc10981566..e35c5190a06f 100644 --- a/fs/xfs/scrub/health.c +++ b/fs/xfs/scrub/health.c @@ -107,6 +107,7 @@ static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = { [XFS_SCRUB_TYPE_PQUOTA] = { XHG_FS, XFS_SICK_FS_PQUOTA }, [XFS_SCRUB_TYPE_FSCOUNTERS] = { XHG_FS, XFS_SICK_FS_COUNTERS }, [XFS_SCRUB_TYPE_QUOTACHECK] = { XHG_FS, XFS_SICK_FS_QUOTACHECK }, + [XFS_SCRUB_TYPE_RTRMAPBT] = { XHG_RT, XFS_SICK_RT_RMAPBT }, }; /* Return the health status mask for this scrub type. */ diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c index 94245da9c63a..e3e7f75778d6 100644 --- a/fs/xfs/scrub/repair.c +++ b/fs/xfs/scrub/repair.c @@ -59,6 +59,7 @@ xrep_attempt( trace_xrep_attempt(XFS_I(file_inode(sc->file)), sc->sm, error); xchk_ag_btcur_free(&sc->sa); + xchk_rt_btcur_free(&sc->sr); /* Repair whatever's broken. */ ASSERT(sc->ops->repair); diff --git a/fs/xfs/scrub/rtrmap.c b/fs/xfs/scrub/rtrmap.c new file mode 100644 index 000000000000..2928f57c29ed --- /dev/null +++ b/fs/xfs/scrub/rtrmap.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2021 Oracle. All Rights Reserved. + * Author: Darrick J. Wong <djwong@kernel.org> + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_btree.h" +#include "xfs_bit.h" +#include "xfs_log_format.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_rmap.h" +#include "xfs_rmap_btree.h" +#include "xfs_rtrmap_btree.h" +#include "xfs_inode.h" +#include "xfs_rtalloc.h" +#include "scrub/xfs_scrub.h" +#include "scrub/scrub.h" +#include "scrub/common.h" +#include "scrub/btree.h" +#include "scrub/trace.h" + +/* Set us up with the realtime metadata locked. */ +int +xchk_setup_rtrmapbt( + struct xfs_scrub *sc) +{ + struct xfs_mount *mp = sc->mp; + int error = 0; + + error = xchk_setup_fs(sc); + if (error) + return error; + + error = xchk_install_inode(sc, mp->m_rrmapip); + if (error) + return error; + + xchk_rt_init(sc, &sc->sr); + return 0; +} + +/* Realtime reverse mapping. */ + +/* Scrub a realtime rmapbt record. */ +STATIC int +xchk_rtrmapbt_rec( + struct xchk_btree *bs, + const union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + struct xfs_rmap_irec irec; + bool non_inode; + bool is_bmbt; + bool is_attr; + int error; + + error = xfs_rmap_btrec_to_irec(bs->cur, rec, &irec); + if (!xchk_btree_process_error(bs->sc, bs->cur, 0, &error)) + goto out; + + if (irec.rm_startblock + irec.rm_blockcount <= irec.rm_startblock || + (!xfs_verify_rtbno(mp, irec.rm_startblock) || + !xfs_verify_rtbno(mp, irec.rm_startblock + + irec.rm_blockcount - 1))) + xchk_btree_set_corrupt(bs->sc, bs->cur, 0); + + /* Check flags. */ + non_inode = XFS_RMAP_NON_INODE_OWNER(irec.rm_owner); + is_bmbt = irec.rm_flags & XFS_RMAP_BMBT_BLOCK; + is_attr = irec.rm_flags & XFS_RMAP_ATTR_FORK; + + if (is_bmbt || non_inode || is_attr) + xchk_btree_set_corrupt(bs->sc, bs->cur, 0); + + if (!xfs_verify_ino(mp, irec.rm_owner)) + xchk_btree_set_corrupt(bs->sc, bs->cur, 0); + +out: + return error; +} + +/* Scrub the realtime rmap btree. */ +int +xchk_rtrmapbt( + struct xfs_scrub *sc) +{ + struct xfs_owner_info oinfo; + struct xfs_mount *mp = sc->mp; + + xfs_rmap_ino_bmbt_owner(&oinfo, mp->m_rrmapip->i_ino, XFS_DATA_FORK); + return xchk_btree(sc, sc->sr.rmap_cur, xchk_rtrmapbt_rec, &oinfo, + NULL); +} diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index d7756680aee8..d0b6abb0647d 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -158,6 +158,8 @@ xchk_teardown( int error) { xchk_ag_free(sc, &sc->sa); + xchk_rt_btcur_free(&sc->sr); + if (sc->tp) { if (error == 0 && (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)) error = xfs_trans_commit(sc->tp); @@ -376,6 +378,13 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .scrub = xchk_health_record, .repair = xrep_notsupported, }, + [XFS_SCRUB_TYPE_RTRMAPBT] = { /* realtime rmapbt */ + .type = ST_FS, + .setup = xchk_setup_rtrmapbt, + .scrub = xchk_rtrmapbt, + .has = xfs_has_rtrmapbt, + .repair = xrep_notsupported, + }, }; /* This isn't a stable feature, warn once per day. */ diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index c88279780fe4..fbbc7af5b67e 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -62,6 +62,8 @@ struct xchk_ag { /* Btree cursors for the RT volume. */ struct xchk_rt { bool locked; + + struct xfs_btree_cur *rmap_cur; }; struct xfs_scrub { @@ -158,6 +160,7 @@ int xchk_parent(struct xfs_scrub *sc); #ifdef CONFIG_XFS_RT int xchk_rtbitmap(struct xfs_scrub *sc); int xchk_rtsummary(struct xfs_scrub *sc); +int xchk_rtrmapbt(struct xfs_scrub *sc); #else static inline int xchk_rtbitmap(struct xfs_scrub *sc) @@ -169,6 +172,11 @@ xchk_rtsummary(struct xfs_scrub *sc) { return -ENOENT; } +static inline int +xchk_rtrmapbt(struct xfs_scrub *sc) +{ + return -ENOENT; +} #endif #ifdef CONFIG_XFS_QUOTA int xchk_quota(struct xfs_scrub *sc); diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index c4545d7ff347..dc1019dd4d9f 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -62,6 +62,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_UQUOTA); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_GQUOTA); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PQUOTA); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS); +TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RTRMAPBT); #define XFS_SCRUB_TYPE_STRINGS \ { XFS_SCRUB_TYPE_PROBE, "probe" }, \ @@ -90,7 +91,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS); { XFS_SCRUB_TYPE_PQUOTA, "prjquota" }, \ { XFS_SCRUB_TYPE_FSCOUNTERS, "fscounters" }, \ { XFS_SCRUB_TYPE_QUOTACHECK, "quotacheck" }, \ - { XFS_SCRUB_TYPE_HEALTHY, "healthy" } + { XFS_SCRUB_TYPE_HEALTHY, "healthy" }, \ + { XFS_SCRUB_TYPE_RTRMAPBT, "rtrmapbt" } #define XFS_SCRUB_FLAG_STRINGS \ { XFS_SCRUB_IFLAG_REPAIR, "repair" }, \ |