diff options
-rw-r--r-- | fs/xfs/libxfs/xfs_fs.h | 3 | ||||
-rw-r--r-- | fs/xfs/scrub/common.h | 6 | ||||
-rw-r--r-- | fs/xfs/scrub/rtbitmap.c | 69 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.c | 7 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.h | 2 | ||||
-rw-r--r-- | fs/xfs/scrub/trace.h | 4 |
6 files changed, 86 insertions, 5 deletions
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 22a08837d3f8..8b58d63427c9 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -742,9 +742,10 @@ struct xfs_scrub_metadata { #define XFS_SCRUB_TYPE_NLINKS 26 /* inode link counts */ #define XFS_SCRUB_TYPE_HEALTHY 27 /* everything checked out ok */ #define XFS_SCRUB_TYPE_RGSUPER 28 /* realtime superblock */ +#define XFS_SCRUB_TYPE_RGBITMAP 29 /* realtime group bitmap */ /* Number of scrub subcommands. */ -#define XFS_SCRUB_TYPE_NR 29 +#define XFS_SCRUB_TYPE_NR 30 /* i: Repair this metadata. */ #define XFS_SCRUB_IFLAG_REPAIR (1u << 0) diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index 2033a30e03d1..79b788d4713b 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -105,10 +105,12 @@ int xchk_setup_parent(struct xfs_scrub *sc); int xchk_setup_rtbitmap(struct xfs_scrub *sc); int xchk_setup_rtsummary(struct xfs_scrub *sc); int xchk_setup_rgsuperblock(struct xfs_scrub *sc); +int xchk_setup_rgbitmap(struct xfs_scrub *sc); #else # define xchk_setup_rtbitmap xchk_setup_nothing # define xchk_setup_rtsummary xchk_setup_nothing # define xchk_setup_rgsuperblock xchk_setup_nothing +# define xchk_setup_rgbitmap xchk_setup_nothing #endif #ifdef CONFIG_XFS_QUOTA @@ -167,6 +169,10 @@ void xchk_rt_init(struct xfs_scrub *sc, struct xchk_rt *sr, void xchk_rt_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); #ifdef CONFIG_XFS_RT + +/* All the locks we need to check an rtgroup. */ +#define XCHK_RTGLOCK_ALL (XFS_RTGLOCK_BITMAP_SHARED) + int xchk_rtgroup_init(struct xfs_scrub *sc, xfs_rgnumber_t rgno, struct xchk_rt *sr, unsigned int rtglock_flags); void xchk_rtgroup_unlock(struct xfs_scrub *sc, struct xchk_rt *sr); diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c index 57dab8ad3bfb..1d3f8d5f3f37 100644 --- a/fs/xfs/scrub/rtbitmap.c +++ b/fs/xfs/scrub/rtbitmap.c @@ -14,10 +14,30 @@ #include "xfs_rtbitmap.h" #include "xfs_inode.h" #include "xfs_bmap.h" +#include "xfs_rtgroup.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/repair.h" +/* Set us up with the realtime group metadata locked. */ +int +xchk_setup_rgbitmap( + struct xfs_scrub *sc) +{ + int error; + + error = xchk_trans_alloc(sc, 0); + if (error) + return error; + + error = xchk_install_live_inode(sc, sc->mp->m_rbmip); + if (error) + return error; + + return xchk_rtgroup_init(sc, sc->sm->sm_agno, &sc->sr, + XCHK_RTGLOCK_ALL); +} + /* Set us up with the realtime metadata locked. */ int xchk_setup_rtbitmap( @@ -101,6 +121,43 @@ xchk_rtbitmap_check_extents( return error; } +/* Scrub this group's realtime bitmap. */ +int +xchk_rgbitmap( + struct xfs_scrub *sc) +{ + struct xfs_rtalloc_rec keys[2]; + struct xfs_rtgroup *rtg = sc->sr.rtg; + xfs_rtblock_t rtbno; + xfs_rgblock_t last_rgbno = rtg->rtg_blockcount - 1; + int error; + + /* Sanity check the realtime bitmap size. */ + if (sc->mp->m_rbmip->i_disk_size != + XFS_FSB_TO_B(sc->mp, sc->mp->m_sb.sb_rbmblocks)) { + xchk_ino_set_corrupt(sc, sc->mp->m_rbmip->i_ino); + return 0; + } + + /* + * Check only the portion of the rtbitmap that corresponds to this + * realtime group. + */ + rtbno = xfs_rgbno_to_rtb(sc->mp, rtg->rtg_rgno, 0); + keys[0].ar_startext = xfs_rtb_to_rtxt(sc->mp, rtbno); + + rtbno = xfs_rgbno_to_rtb(sc->mp, rtg->rtg_rgno, last_rgbno); + keys[1].ar_startext = xfs_rtb_to_rtxt(sc->mp, rtbno); + keys[0].ar_extcount = keys[1].ar_extcount = 0; + + error = xfs_rtalloc_query_range(sc->mp, sc->tp, &keys[0], &keys[1], + xchk_rtbitmap_rec, sc); + if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error)) + return error; + + return 0; +} + /* Scrub the realtime bitmap. */ int xchk_rtbitmap( @@ -124,12 +181,18 @@ xchk_rtbitmap( if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) return error; + /* + * Each rtgroup checks its portion of the rt bitmap, so if we don't + * have that feature, we have to check the bitmap contents now. + */ + if (xfs_has_rtgroups(sc->mp)) + return 0; + error = xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtbitmap_rec, sc); if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error)) - goto out; + return error; -out: - return error; + return 0; } /* xref check that the extent is not free in the rtbitmap */ diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 5e07150e8f14..6066673953cb 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -416,6 +416,13 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .has = xfs_has_rtgroups, .repair = xrep_rgsuperblock, }, + [XFS_SCRUB_TYPE_RGBITMAP] = { /* realtime group bitmap */ + .type = ST_RTGROUP, + .setup = xchk_setup_rgbitmap, + .scrub = xchk_rgbitmap, + .has = xfs_has_rtgroups, + .repair = xrep_notsupported, + }, }; static int diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index 6e5b96b6db81..48114bda2f4a 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -189,10 +189,12 @@ int xchk_parent(struct xfs_scrub *sc); int xchk_rtbitmap(struct xfs_scrub *sc); int xchk_rtsummary(struct xfs_scrub *sc); int xchk_rgsuperblock(struct xfs_scrub *sc); +int xchk_rgbitmap(struct xfs_scrub *sc); #else # define xchk_rtbitmap xchk_nothing # define xchk_rtsummary xchk_nothing # define xchk_rgsuperblock xchk_nothing +# define xchk_rgbitmap xchk_nothing #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 22fa4a6ef1fd..96796d0d6126 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -74,6 +74,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_QUOTACHECK); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_NLINKS); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_HEALTHY); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGSUPER); +TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGBITMAP); #define XFS_SCRUB_TYPE_STRINGS \ { XFS_SCRUB_TYPE_PROBE, "probe" }, \ @@ -104,7 +105,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGSUPER); { XFS_SCRUB_TYPE_QUOTACHECK, "quotacheck" }, \ { XFS_SCRUB_TYPE_NLINKS, "nlinks" }, \ { XFS_SCRUB_TYPE_HEALTHY, "healthy" }, \ - { XFS_SCRUB_TYPE_RGSUPER, "rgsuper" } + { XFS_SCRUB_TYPE_RGSUPER, "rgsuper" }, \ + { XFS_SCRUB_TYPE_RGBITMAP, "rgbitmap" } #define XFS_SCRUB_FLAG_STRINGS \ { XFS_SCRUB_IFLAG_REPAIR, "repair" }, \ |