summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_fs.h6
-rw-r--r--fs/xfs/scrub/common.h3
-rw-r--r--fs/xfs/scrub/scrub.c5
-rw-r--r--fs/xfs/xfs_ioctl.c3
4 files changed, 14 insertions, 3 deletions
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 7ac2b0a99aae..5911508d8f38 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -791,9 +791,13 @@ struct xfs_scrub_metadata {
/* i: Don't mark inodes DONTCACHE at the end. */
#define XFS_SCRUB_IFLAG_RETAIN_INODES (1 << 9)
+/* i: Rebuild the data structure. */
+#define XFS_SCRUB_IFLAG_FORCE_REBUILD (1 << 10)
+
#define XFS_SCRUB_FLAGS_IN (XFS_SCRUB_IFLAG_REPAIR | \
XFS_SCRUB_IFLAG_FREEZE_OK | \
- XFS_SCRUB_IFLAG_RETAIN_INODES)
+ XFS_SCRUB_IFLAG_RETAIN_INODES | \
+ XFS_SCRUB_IFLAG_FORCE_REBUILD)
#define XFS_SCRUB_FLAGS_OUT (XFS_SCRUB_OFLAG_CORRUPT | \
XFS_SCRUB_OFLAG_PREEN | \
XFS_SCRUB_OFLAG_XFAIL | \
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 70a42897cd22..dc7b2f41c1d2 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -194,7 +194,8 @@ static inline bool xfs_scrub_needs_repair(struct xfs_scrub_metadata *sm)
{
return sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
XFS_SCRUB_OFLAG_XCORRUPT |
- XFS_SCRUB_OFLAG_PREEN);
+ XFS_SCRUB_OFLAG_PREEN |
+ XFS_SCRUB_IFLAG_FORCE_REBUILD);
}
int xchk_iwalk_find_next(struct xfs_mount *mp, struct xfs_trans *tp,
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index d3944a1d0146..3a43fe95dfc8 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -476,6 +476,11 @@ xchk_validate_inputs(
goto out;
}
+ /* No rebuild without repair. */
+ if ((sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD) &&
+ !(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
+ return -EINVAL;
+
/*
* We only want to repair read-write v5+ filesystems. Defer the check
* for ops->repair until after our scrub confirms that we need to
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 8913c27ddd11..525eba22c2a2 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1810,7 +1810,8 @@ xfs_ioc_scrub_metadata(
if (copy_from_user(&scrub, arg, sizeof(scrub)))
return -EFAULT;
- if ((scrub.sm_flags & XFS_SCRUB_IFLAG_FREEZE_OK) &&
+ if ((scrub.sm_flags & (XFS_SCRUB_IFLAG_FREEZE_OK |
+ XFS_SCRUB_IFLAG_FORCE_REBUILD)) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;