summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_fs.h3
-rw-r--r--fs/xfs/scrub/common.h6
-rw-r--r--fs/xfs/scrub/rtbitmap.c69
-rw-r--r--fs/xfs/scrub/scrub.c7
-rw-r--r--fs/xfs/scrub/scrub.h2
-rw-r--r--fs/xfs/scrub/trace.h4
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" }, \