[PATCH 07/25] xfs: create an ioctl to scrub AG metadata
Darrick J. Wong
darrick.wong at oracle.com
Thu Aug 25 18:40:57 CDT 2016
Create an ioctl that can be used to scrub internal filesystem
metadata. The new ioctl takes the metadata type, an (optional)
AG number, and a flags argument. This will be used by the
upcoming XFS online scrub tool.
Signed-off-by: Darrick J. Wong <darrick.wong at oracle.com>
---
fs/xfs/libxfs/xfs_fs.h | 16 ++++++++++++++++
fs/xfs/xfs_ioctl.c | 20 ++++++++++++++++++++
fs/xfs/xfs_scrub.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
fs/xfs/xfs_scrub.h | 2 +-
4 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 58e14b14e..22559ab 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -524,6 +524,21 @@ typedef struct xfs_swapext
#define XFS_FSOP_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
#define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
+/* metadata scrubbing */
+struct xfs_scrub_metadata {
+ __u32 type; /* What to check? */
+ __u32 flags; /* Flags; none defined right now. */
+ __u64 control; /* AG or inode number */
+ __u64 reserved[6]; /* Must be zero. */
+};
+
+/*
+ * Metadata types and flags for scrub operation.
+ */
+#define XFS_SCRUB_TYPE_MAX 0
+
+#define XFS_SCRUB_FLAGS_ALL 0x0 /* no flags yet */
+
/*
* ioctl limits
*/
@@ -567,6 +582,7 @@ typedef struct xfs_swapext
#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64)
#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
#define XFS_IOC_GETFSMAP _IOWR('X', 59, struct getfsmap)
+#define XFS_IOC_SCRUB_METADATA _IOR ('X', 60, struct xfs_scrub_metadata)
/*
* ioctl commands that replace IRIX syssgi()'s
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 936cb45..65f0c03 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -44,6 +44,7 @@
#include "xfs_reflink.h"
#include "xfs_btree.h"
#include "xfs_fsmap.h"
+#include "xfs_scrub.h"
#include <linux/capability.h>
#include <linux/dcache.h>
@@ -1686,6 +1687,22 @@ xfs_ioc_getfsmap(
return 0;
}
+STATIC int
+xfs_ioc_scrub_metadata(
+ struct xfs_inode *ip,
+ void __user *arg)
+{
+ struct xfs_scrub_metadata scrub;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&scrub, arg, sizeof(scrub)))
+ return -EFAULT;
+
+ return xfs_scrub_metadata(ip, &scrub);
+}
+
int
xfs_ioc_swapext(
xfs_swapext_t *sxp)
@@ -1871,6 +1888,9 @@ xfs_file_ioctl(
return -EPERM;
return xfs_ioc_getfsmap(ip, arg);
+ case XFS_IOC_SCRUB_METADATA:
+ return xfs_ioc_scrub_metadata(ip, arg);
+
case XFS_IOC_FD_TO_HANDLE:
case XFS_IOC_PATH_TO_HANDLE:
case XFS_IOC_PATH_TO_FSHANDLE: {
diff --git a/fs/xfs/xfs_scrub.c b/fs/xfs/xfs_scrub.c
index 13bea55..fd24af7 100644
--- a/fs/xfs/xfs_scrub.c
+++ b/fs/xfs/xfs_scrub.c
@@ -703,3 +703,47 @@ out:
out_badcursor:
return error;
}
+
+/* Scrubbing dispatch. */
+
+struct xfs_scrub_meta_fns {
+ int (*scrub_fn)(struct xfs_inode *, struct xfs_scrub_metadata *);
+ bool (*has_fn)(struct xfs_sb *);
+};
+
+static const struct xfs_scrub_meta_fns meta_scrub_fns[] = {
+};
+
+/* Dispatch metadata scrubbing. */
+int
+xfs_scrub_metadata(
+ struct xfs_inode *ip,
+ struct xfs_scrub_metadata *sm)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ const struct xfs_scrub_meta_fns *fns;
+ int i;
+ int error = 0;
+
+ trace_xfs_scrub(ip, sm->type, sm->control, sm->flags, error);
+
+ error = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(sm->reserved); i++)
+ if (sm->reserved[i])
+ goto out;
+ if (sm->type > XFS_SCRUB_TYPE_MAX)
+ goto out;
+ if (sm->flags & ~XFS_SCRUB_FLAGS_ALL)
+ goto out;
+
+ fns = &meta_scrub_fns[sm->type];
+ if (fns->has_fn && !fns->has_fn(&mp->m_sb)) {
+ error = -ENOENT;
+ goto out;
+ }
+ error = fns->scrub_fn(ip, sm);
+
+out:
+ trace_xfs_scrub_done(ip, sm->type, sm->control, sm->flags, error);
+ return error;
+}
diff --git a/fs/xfs/xfs_scrub.h b/fs/xfs/xfs_scrub.h
index 474df7e..f4bb021 100644
--- a/fs/xfs/xfs_scrub.h
+++ b/fs/xfs/xfs_scrub.h
@@ -20,6 +20,6 @@
#ifndef __XFS_SCRUB_H__
#define __XFS_SCRUB_H__
-/* Functions to come later. */
+int xfs_scrub_metadata(struct xfs_inode *ip, struct xfs_scrub_metadata *sm);
#endif /* __XFS_SCRUB_H__ */
More information about the xfs
mailing list