diff mbox

[09/10] xfs_io: wire up repair ioctl stuff

Message ID 153006772758.20121.12001635681077633355.stgit@magnolia (mailing list archive)
State Accepted
Headers show

Commit Message

Darrick J. Wong June 27, 2018, 2:48 a.m. UTC
From: Darrick J. Wong <darrick.wong@oracle.com>

Wire up the repair ioctl (which is really the scrub ioctl with special
flags) and the force-repair error injection point.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 io/init.c         |    1 +
 io/io.h           |    1 +
 io/scrub.c        |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 man/man8/xfs_io.8 |    8 ++++
 4 files changed, 107 insertions(+)



--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Eric Sandeen July 26, 2018, 1:23 a.m. UTC | #1
On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Wire up the repair ioctl (which is really the scrub ioctl with special
> flags) and the force-repair error injection point.


> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  io/init.c         |    1 +
>  io/io.h           |    1 +
>  io/scrub.c        |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  man/man8/xfs_io.8 |    8 ++++
>  4 files changed, 107 insertions(+)
> 
> 
> diff --git a/io/init.c b/io/init.c
> index 3f637e5a..a65f81d6 100644
> --- a/io/init.c
> +++ b/io/init.c
> @@ -85,6 +85,7 @@ init_commands(void)
>  	quit_init();
>  	readdir_init();
>  	reflink_init();
> +	repair_init();
>  	resblks_init();
>  	scrub_init();
>  	seek_init();
> diff --git a/io/io.h b/io/io.h
> index fa0cdff7..ab217789 100644
> --- a/io/io.h
> +++ b/io/io.h
> @@ -198,3 +198,4 @@ extern void		log_writes_init(void);
>  #endif
>  
>  extern void		scrub_init(void);
> +extern void		repair_init(void);
> diff --git a/io/scrub.c b/io/scrub.c
> index 75a8ff15..c2c08e6b 100644
> --- a/io/scrub.c
> +++ b/io/scrub.c
> @@ -26,6 +26,7 @@
>  #include "io.h"
>  
>  static struct cmdinfo scrub_cmd;
> +static struct cmdinfo repair_cmd;
>  
>  /* Type info and names for the scrub types. */
>  enum scrub_type {
> @@ -249,3 +250,99 @@ scrub_init(void)
>  
>  	add_command(&scrub_cmd);
>  }
> +
> +static void
> +repair_help(void)
> +{
> +	const struct scrub_descr	*d;
> +	int				i;
> +
> +	printf(_(
> +"\n"
> +" Repairs a piece of XFS filesystem metadata.  The first argument is the type\n"
> +" of metadata to examine.  Allocation group metadata types take one AG number\n"
> +" as the second parameter.  Inode metadata types act on the currently open file\n"
> +" or (optionally) take an inode number and generation number to act upon as\n"
> +" the second and third parameters.\n"
> +"\n"
> +" Example:\n"
> +" 'repair inobt 3' - repairs the inode btree in AG 3.\n"
> +" 'repair bmapbtd 128 13525' - repairs the extent map of inode 128 gen 13525.\n"
> +"\n"
> +" Known metadata repairs types are:"));
> +	for (i = 0, d = scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
> +		printf(" %s", d->name);
> +	printf("\n");
> +}
> +
> +static void
> +repair_ioctl(
> +	int				fd,
> +	int				type,
> +	uint64_t			control,
> +	uint32_t			control2)
> +{
> +	struct xfs_scrub_metadata	meta;
> +	const struct scrub_descr	*sc;
> +	int				error;
> +
> +	sc = &scrubbers[type];
> +	memset(&meta, 0, sizeof(meta));
> +	meta.sm_type = type;
> +	switch (sc->type) {
> +	case ST_PERAG:
> +		meta.sm_agno = control;
> +		break;
> +	case ST_INODE:
> +		meta.sm_ino = control;
> +		meta.sm_gen = control2;
> +		break;
> +	case ST_NONE:
> +	case ST_FS:
> +		/* no control parameters */
> +		break;
> +	}
> +	meta.sm_flags = XFS_SCRUB_IFLAG_REPAIR;
> +
> +	error = ioctl(fd, XFS_IOC_SCRUB_METADATA, &meta);
> +	if (error)
> +		perror("scrub");
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
> +		printf(_("Corruption remains.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_PREEN)
> +		printf(_("Optimization possible.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_XFAIL)
> +		printf(_("Cross-referencing failed.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_XCORRUPT)
> +		printf(_("Corruption still detected during cross-referencing.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
> +		printf(_("Repair was not complete.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED)
> +		printf(_("Metadata did not need repair or optimization.\n"));
> +}
> +
> +static int
> +repair_f(
> +	int				argc,
> +	char				**argv)
> +{
> +	return parse_args(argc, argv, &repair_cmd, repair_ioctl);
> +}
> +
> +void
> +repair_init(void)
> +{
> +	if (!expert)
> +		return;
> +	repair_cmd.name = "repair";
> +	repair_cmd.altname = "fix";
> +	repair_cmd.cfunc = repair_f;
> +	repair_cmd.argmin = 1;
> +	repair_cmd.argmax = -1;
> +	repair_cmd.flags = CMD_NOMAP_OK;
> +	repair_cmd.args = _("type [agno|ino gen]");
> +	repair_cmd.oneline = _("repairs filesystem metadata");
> +	repair_cmd.help = repair_help;
> +
> +	add_command(&repair_cmd);
> +}
> diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
> index dd91589b..60f7a21c 100644
> --- a/man/man8/xfs_io.8
> +++ b/man/man8/xfs_io.8
> @@ -1167,6 +1167,14 @@ inode number and generation number are specified.
>  .RE
>  .PD
>  .TP
> +.BI "repair " type " [ " agnumber " | " "ino" " " "gen" " ]"
> +Repair internal XFS filesystem metadata.  The
> +.BI type
> +parameter specifies which type of metadata to repair.
> +For AG metadata, one AG number must be specified.
> +For file metadata, the repair is applied to the open file unless the
> +inode number and generation number are specified.
> +.TP
>  .BI "log_writes \-d " device " \-m "  mark
>  Create a mark named
>  .I mark
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/io/init.c b/io/init.c
index 3f637e5a..a65f81d6 100644
--- a/io/init.c
+++ b/io/init.c
@@ -85,6 +85,7 @@  init_commands(void)
 	quit_init();
 	readdir_init();
 	reflink_init();
+	repair_init();
 	resblks_init();
 	scrub_init();
 	seek_init();
diff --git a/io/io.h b/io/io.h
index fa0cdff7..ab217789 100644
--- a/io/io.h
+++ b/io/io.h
@@ -198,3 +198,4 @@  extern void		log_writes_init(void);
 #endif
 
 extern void		scrub_init(void);
+extern void		repair_init(void);
diff --git a/io/scrub.c b/io/scrub.c
index 75a8ff15..c2c08e6b 100644
--- a/io/scrub.c
+++ b/io/scrub.c
@@ -26,6 +26,7 @@ 
 #include "io.h"
 
 static struct cmdinfo scrub_cmd;
+static struct cmdinfo repair_cmd;
 
 /* Type info and names for the scrub types. */
 enum scrub_type {
@@ -249,3 +250,99 @@  scrub_init(void)
 
 	add_command(&scrub_cmd);
 }
+
+static void
+repair_help(void)
+{
+	const struct scrub_descr	*d;
+	int				i;
+
+	printf(_(
+"\n"
+" Repairs a piece of XFS filesystem metadata.  The first argument is the type\n"
+" of metadata to examine.  Allocation group metadata types take one AG number\n"
+" as the second parameter.  Inode metadata types act on the currently open file\n"
+" or (optionally) take an inode number and generation number to act upon as\n"
+" the second and third parameters.\n"
+"\n"
+" Example:\n"
+" 'repair inobt 3' - repairs the inode btree in AG 3.\n"
+" 'repair bmapbtd 128 13525' - repairs the extent map of inode 128 gen 13525.\n"
+"\n"
+" Known metadata repairs types are:"));
+	for (i = 0, d = scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
+		printf(" %s", d->name);
+	printf("\n");
+}
+
+static void
+repair_ioctl(
+	int				fd,
+	int				type,
+	uint64_t			control,
+	uint32_t			control2)
+{
+	struct xfs_scrub_metadata	meta;
+	const struct scrub_descr	*sc;
+	int				error;
+
+	sc = &scrubbers[type];
+	memset(&meta, 0, sizeof(meta));
+	meta.sm_type = type;
+	switch (sc->type) {
+	case ST_PERAG:
+		meta.sm_agno = control;
+		break;
+	case ST_INODE:
+		meta.sm_ino = control;
+		meta.sm_gen = control2;
+		break;
+	case ST_NONE:
+	case ST_FS:
+		/* no control parameters */
+		break;
+	}
+	meta.sm_flags = XFS_SCRUB_IFLAG_REPAIR;
+
+	error = ioctl(fd, XFS_IOC_SCRUB_METADATA, &meta);
+	if (error)
+		perror("scrub");
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
+		printf(_("Corruption remains.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_PREEN)
+		printf(_("Optimization possible.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_XFAIL)
+		printf(_("Cross-referencing failed.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_XCORRUPT)
+		printf(_("Corruption still detected during cross-referencing.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
+		printf(_("Repair was not complete.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED)
+		printf(_("Metadata did not need repair or optimization.\n"));
+}
+
+static int
+repair_f(
+	int				argc,
+	char				**argv)
+{
+	return parse_args(argc, argv, &repair_cmd, repair_ioctl);
+}
+
+void
+repair_init(void)
+{
+	if (!expert)
+		return;
+	repair_cmd.name = "repair";
+	repair_cmd.altname = "fix";
+	repair_cmd.cfunc = repair_f;
+	repair_cmd.argmin = 1;
+	repair_cmd.argmax = -1;
+	repair_cmd.flags = CMD_NOMAP_OK;
+	repair_cmd.args = _("type [agno|ino gen]");
+	repair_cmd.oneline = _("repairs filesystem metadata");
+	repair_cmd.help = repair_help;
+
+	add_command(&repair_cmd);
+}
diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
index dd91589b..60f7a21c 100644
--- a/man/man8/xfs_io.8
+++ b/man/man8/xfs_io.8
@@ -1167,6 +1167,14 @@  inode number and generation number are specified.
 .RE
 .PD
 .TP
+.BI "repair " type " [ " agnumber " | " "ino" " " "gen" " ]"
+Repair internal XFS filesystem metadata.  The
+.BI type
+parameter specifies which type of metadata to repair.
+For AG metadata, one AG number must be specified.
+For file metadata, the repair is applied to the open file unless the
+inode number and generation number are specified.
+.TP
 .BI "log_writes \-d " device " \-m "  mark
 Create a mark named
 .I mark