@@ -53,6 +53,115 @@ shutdown_help(void)
"\n"));
}
+static void
+mediaerror_help(void)
+{
+ printf(_(
+"\n"
+" Report a media error on the data device to the filesystem.\n"
+"\n"
+" -l -- Report against the log device.\n"
+" -r -- Report against the realtime device.\n"
+"\n"
+" offset is the byte offset of the start of the failed range. If offset is\n"
+" specified, mapping length may (optionally) be specified as well."
+"\n"
+" length is the byte length of the failed range.\n"
+"\n"
+" If neither offset nor length are specified, the media error report will\n"
+" be made against the entire device."
+"\n"));
+}
+
+static int
+mediaerror_f(
+ int argc,
+ char **argv)
+{
+ struct xfs_media_error me = {
+ .daddr = 0,
+ .bbcount = -1ULL,
+ .flags = XFS_MEDIA_ERROR_DATADEV,
+ };
+ long long l;
+ size_t fsblocksize, fssectsize;
+ int c, ret;
+
+ init_cvtnum(&fsblocksize, &fssectsize);
+
+ while ((c = getopt(argc, argv, "lr")) != EOF) {
+ switch (c) {
+ case 'l':
+ me.flags = (me.flags & ~XFS_MEDIA_ERROR_DEVMASK) |
+ XFS_MEDIA_ERROR_LOGDEV;
+ break;
+ case 'r':
+ me.flags = (me.flags & ~XFS_MEDIA_ERROR_DEVMASK) |
+ XFS_MEDIA_ERROR_RTDEV;
+ break;
+ default:
+ mediaerror_help();
+ exitcode = 1;
+ return 0;
+ }
+ }
+
+ /* Range start (optional) */
+ if (optind < argc) {
+ l = cvtnum(fsblocksize, fssectsize, argv[optind]);
+ if (l < 0) {
+ printf("non-numeric offset argument -- %s\n",
+ argv[optind]);
+ exitcode = 1;
+ return 0;
+ }
+
+ me.daddr = l / 512;
+ optind++;
+ }
+
+ /* Range length (optional if range start was specified) */
+ if (optind < argc) {
+ l = cvtnum(fsblocksize, fssectsize, argv[optind]);
+ if (l < 0) {
+ printf("non-numeric len argument -- %s\n",
+ argv[optind]);
+ exitcode = 1;
+ return 0;
+ }
+
+ me.bbcount = howmany(l, 512);
+ optind++;
+ }
+
+ if (optind < argc) {
+ printf("too many arguments -- %s\n", argv[optind]);
+ exitcode = 1;
+ return 0;
+ }
+
+ ret = ioctl(file->fd, XFS_IOC_MEDIA_ERROR, &me);
+ if (ret) {
+ fprintf(stderr,
+ "%s: ioctl(XFS_IOC_MEDIA_ERROR) [\"%s\"]: %s\n",
+ progname, file->name, strerror(errno));
+ exitcode = 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+static struct cmdinfo mediaerror_cmd = {
+ .name = "mediaerror",
+ .cfunc = mediaerror_f,
+ .argmin = 0,
+ .argmax = -1,
+ .flags = CMD_FLAG_ONESHOT | CMD_NOMAP_OK,
+ .args = "[-lr] [offset [length]]",
+ .help = mediaerror_help,
+};
+
void
shutdown_init(void)
{
@@ -66,6 +175,8 @@ shutdown_init(void)
shutdown_cmd.oneline =
_("shuts down the filesystem where the current file resides");
- if (expert)
+ if (expert) {
add_command(&shutdown_cmd);
+ add_command(&mediaerror_cmd);
+ }
}
@@ -1452,6 +1452,27 @@ .SH FILESYSTEM COMMANDS
argument, displays the list of error tags available.
Only available in expert mode and requires privileges.
+.TP
+.BI "mediaerror [ \-lr ] [ " offset " [ " length " ]]"
+Report a media error against the data device of an XFS filesystem.
+The
+.I offset
+and
+.I length
+parameters are specified in units of bytes.
+If neither are specified, the entire device will be reported.
+.RE
+.RS 1.0i
+.PD 0
+.TP
+.BI \-l
+Report against the log device instead of the data device.
+.TP
+.BI \-r
+Report against the realtime device instead of the data device.
+.PD
+.RE
+
.TP
.BI "rginfo [ \-r " rgno " ]"
Show information about or update the state of realtime allocation groups.