Perform simple tests of the realtime bitmap and summary.
Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
fs/xfs/libxfs/xfs_format.h | 5 +++
fs/xfs/libxfs/xfs_fs.h | 4 ++
fs/xfs/libxfs/xfs_rtbitmap.c | 2 +
fs/xfs/xfs_rtalloc.h | 3 ++
fs/xfs/xfs_scrub.c | 78 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index a3aa5e9..5703b57 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -315,6 +315,11 @@ static inline bool xfs_sb_good_version(struct xfs_sb *sbp)
return false;
}
+static inline bool xfs_sb_version_hasrealtime(struct xfs_sb *sbp)
+{
+ return sbp->sb_rblocks > 0;
+}
+
/*
* Detect a mismatched features2 field. Older kernels read/wrote
* this into the wrong slot, so to be safe we keep them in sync.
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index c688deb..211c874 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -549,7 +549,9 @@ struct xfs_scrub_metadata {
#define XFS_SCRUB_TYPE_BMBTD 11 /* data fork block mapping */
#define XFS_SCRUB_TYPE_BMBTA 12 /* attr fork block mapping */
#define XFS_SCRUB_TYPE_BMBTC 13 /* CoW fork block mapping */
-#define XFS_SCRUB_TYPE_MAX 13
+#define XFS_SCRUB_TYPE_RTBITMAP 14 /* realtime bitmap */
+#define XFS_SCRUB_TYPE_RTSUM 15 /* realtime summary */
+#define XFS_SCRUB_TYPE_MAX 15
#define XFS_SCRUB_FLAGS_ALL 0x0 /* no flags yet */
diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c
index ea45584..f4b68c0 100644
--- a/fs/xfs/libxfs/xfs_rtbitmap.c
+++ b/fs/xfs/libxfs/xfs_rtbitmap.c
@@ -70,7 +70,7 @@ const struct xfs_buf_ops xfs_rtbuf_ops = {
* Get a buffer for the bitmap or summary file block specified.
* The buffer is returned read and locked.
*/
-static int
+int
xfs_rtbuf_get(
xfs_mount_t *mp, /* file system mount structure */
xfs_trans_t *tp, /* transaction pointer */
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index 355dd9e..91e48f9 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -98,6 +98,8 @@ xfs_growfs_rt(
/*
* From xfs_rtbitmap.c
*/
+int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp,
+ xfs_rtblock_t block, int issum, struct xfs_buf **bpp);
int xfs_rtcheck_range(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_extlen_t len, int val,
xfs_rtblock_t *new, int *stat);
@@ -126,6 +128,7 @@ int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans
*tp,
# define xfs_rtfree_extent(t,b,l) (ENOSYS)
# define xfs_rtpick_extent(m,t,l,rb) (ENOSYS)
# define xfs_growfs_rt(mp,in) (ENOSYS)
+# define xfs_rtbuf_get(m,t,b,i,p) (ENOSYS)
static inline int /* error */
xfs_rtmount_init(
xfs_mount_t *mp) /* file system mount structure */
diff --git a/fs/xfs/xfs_scrub.c b/fs/xfs/xfs_scrub.c
index 573acd4..22ba07d 100644
--- a/fs/xfs/xfs_scrub.c
+++ b/fs/xfs/xfs_scrub.c
@@ -773,6 +773,7 @@ xfs_scrub_sb(
XFS_SCRUB_SB_FEAT(metauuid);
XFS_SCRUB_SB_FEAT(rmapbt);
XFS_SCRUB_SB_FEAT(reflink);
+ XFS_SCRUB_SB_FEAT(realtime);
#undef XFS_SCRUB_SB_FEAT
out:
@@ -1674,6 +1675,81 @@ xfs_scrub_bmap_cow(
return xfs_scrub_bmap(ip, sm, XFS_COW_FORK);
}
+/* Scrub the realtime bitmap. */
+STATIC int
+xfs_scrub_rtbitmap(
+ struct xfs_inode *ip,
+ struct xfs_scrub_metadata *sm)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_buf *bp = NULL;
+ xfs_rtblock_t rtstart;
+ xfs_rtblock_t rtend;
+ xfs_rtblock_t block;
+ xfs_rtblock_t rem;
+ int is_free;
+ int error = 0;
+ int err2 = 0;
+
+ if (sm->control || sm->flags)
+ return -EINVAL;
+
+ xfs_ilock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
+
+ /* Iterate the bitmap, looking for discrepancies. */
+ rtstart = 0;
+ rem = mp->m_sb.sb_rblocks;
+ while (rem) {
+ if (xfs_scrub_should_terminate(&error))
+ break;
+
+ /* Is the first block free? */
+ err2 = xfs_rtcheck_range(mp, NULL, rtstart, 1, 1, &rtend,
+ &is_free);
+ if (err2)
+ goto out_unlock;
+
+ /* How long does the extent go for? */
+ err2 = xfs_rtfind_forw(mp, NULL, rtstart,
+ mp->m_sb.sb_rblocks - 1, &rtend);
+ if (err2)
+ goto out_unlock;
+
+ /* Find the buffer for error reporting. */
+ block = XFS_BITTOBLOCK(mp, rtstart);
+ err2 = xfs_rtbuf_get(mp, NULL, block, 0, &bp);
+ if (err2)
+ break;
+ XFS_SCRUB_CHECK(mp, bp, "rtbitmap", rtend >= rtstart);
+
+ xfs_buf_relse(bp);
+ bp = NULL;
+ rem -= rtend - rtstart + 1;
+ rtstart = rtend + 1;
+ }
+
+out_unlock:
+ if (bp)
+ xfs_buf_relse(bp);
+ xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
+ if (!error && err2)
+ error = err2;
+ return error;
+}
+
+/* Scrub the realtime summary. */
+STATIC int
+xfs_scrub_rtsummary(
+ struct xfs_inode *ip,
+ struct xfs_scrub_metadata *sm)
+{
+ if (sm->control || sm->flags)
+ return -EINVAL;
+
+ /* XXX: implement this some day */
+ return -ENOENT;
+}
+
/* Scrubbing dispatch. */
struct xfs_scrub_meta_fns {
@@ -1696,6 +1772,8 @@ static const struct xfs_scrub_meta_fns meta_scrub_fns[] =
{
{xfs_scrub_bmap_data, NULL},
{xfs_scrub_bmap_attr, NULL},
{xfs_scrub_bmap_cow, NULL},
+ {xfs_scrub_rtbitmap, xfs_sb_version_hasrealtime},
+ {xfs_scrub_rtsummary, xfs_sb_version_hasrealtime},
};
/* Dispatch metadata scrubbing. */
|