* GPL HEADER END
*/
/*
- * Copyright (c) 2012, 2013, Intel Corporation.
+ * Copyright (c) 2012, 2015, Intel Corporation.
*/
/*
* lustre/utils/lustre_lfsck.c
#include <string.h>
#include <errno.h>
#include <getopt.h>
+#include <sys/ioctl.h>
#include <time.h>
#include "obdctl.h"
#include <lustre/lustre_lfsck_user.h>
-#include <libcfs/libcfsutil.h>
#include <lnet/lnetctl.h>
#include <lustre_ioctl.h>
+/* Needs to be last to avoid clashes */
+#include <libcfs/util/ioctl.h>
static struct option long_opt_start[] = {
{"device", required_argument, 0, 'M'},
{"all", no_argument, 0, 'A'},
{"create_ostobj", optional_argument, 0, 'c'},
+ {"create_mdtobj", optional_argument, 0, 'C'},
{"error", required_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"dryrun", optional_argument, 0, 'n'},
{"device", required_argument, 0, 'M'},
{"all", no_argument, 0, 'A'},
{"help", no_argument, 0, 'h'},
- {0, 0, 0, 0}
+ {0, 0, 0, 0 }
+};
+
+static struct option long_opt_query[] = {
+ {"device", required_argument, 0, 'M'},
+ {"type", required_argument, 0, 't'},
+ {"help", no_argument, 0, 'h'},
+ {"wait", no_argument, 0, 'w'},
+ {0, 0, 0, 0 }
};
struct lfsck_type_name {
return -1;
}
+static const char *lfsck_type2name(__u16 type)
+{
+ int i;
+
+ for (i = 0; lfsck_types_names[i].ltn_name != NULL; i++) {
+ if (type == lfsck_types_names[i].ltn_type)
+ return lfsck_types_names[i].ltn_name;
+ }
+
+ return NULL;
+}
+
static void usage_start(void)
{
fprintf(stderr, "start LFSCK\n"
"usage:\n"
"lfsck_start <-M | --device {MDT,OST}_device>\n"
" [-A | --all] [-c | --create_ostobj [on | off]]\n"
+ " [-C | --create_mdtobj [on | off]]\n"
" [-e | --error {continue | abort}] [-h | --help]\n"
" [-n | --dryrun [on | off]] [-o | --orphan]\n"
" [-r | --reset] [-s | --speed ops_per_sec_limit]\n"
"-A: start LFSCK on all MDT devices\n"
"-c: create the lost OST-object for dangling LOV EA "
"(default 'off', or 'on')\n"
+ "-C: create the lost MDT-object for dangling name entry "
+ "(default 'off', or 'on')\n"
"-e: error handle mode (default 'continue', or 'abort')\n"
"-h: this help message\n"
"-n: check with no modification (default 'off', or 'on')\n"
"-h: this help message\n");
}
+static void usage_query(void)
+{
+ fprintf(stderr, "check the LFSCK global status\n"
+ "usage:\n"
+ "lfsck_query <-M | --device MDT_device> [-h | --help]\n"
+ " [-t | --type check_type[,check_type...]]\n"
+ " [-t | --wait]\n"
+ "options:\n"
+ "-M: device to query LFSCK on\n"
+ "-t: LFSCK type(s) to be queried (default is all)\n"
+ "-h: this help message\n"
+ "-w: do not return until LFSCK not running\n");
+}
+
static int lfsck_pack_dev(struct obd_ioctl_data *data, char *device, char *arg)
{
int len = strlen(arg) + 1;
char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
char device[MAX_OBD_NAME];
struct lfsck_start start;
- char *optstring = "Ac::e:hM:n::ors:t:w:";
+ char *optstring = "Ac::C::e:hM:n::ors:t:w:";
int opt, index, rc, val, i;
memset(&data, 0, sizeof(data));
}
start.ls_valid |= LSV_CREATE_OSTOBJ;
break;
+ case 'C':
+ if (optarg == NULL || strcmp(optarg, "on") == 0) {
+ start.ls_flags |= LPF_CREATE_MDTOBJ;
+ } else if (strcmp(optarg, "off") != 0) {
+ fprintf(stderr, "invalid switch: -C '%s'. "
+ "valid switches are:\n"
+ "empty ('on'), or 'off' without space. "
+ "For example:\n"
+ "'-C', '-Con', '-Coff'\n", optarg);
+ return -EINVAL;
+ }
+ start.ls_valid |= LSV_CREATE_MDTOBJ;
+ break;
case 'e':
if (strcmp(optarg, "abort") == 0) {
start.ls_flags |= LPF_FAILOUT;
}
case 'w':
val = atoi(optarg);
- if (val < 0 || val > LFSCK_ASYNC_WIN_MAX) {
+ if (val < 1 || val > LFSCK_ASYNC_WIN_MAX) {
fprintf(stderr,
- "Too large async window size, "
- "which may cause memory issues. "
- "The valid range is [0 - %u]. "
- "If you do not want to restrict "
- "the window size for async reqeusts "
- "pipeline, just set it as 0.\n",
+ "Invalid async window size that "
+ "may cause memory issues. The valid "
+ "range is [1 - %u].\n",
LFSCK_ASYNC_WIN_MAX);
return -EINVAL;
}
data.ioc_inllen1 = sizeof(start);
memset(buf, 0, sizeof(rawbuf));
rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
- if (rc) {
+ if (rc != 0) {
fprintf(stderr, "Fail to pack ioctl data: rc = %d.\n", rc);
return rc;
}
data.ioc_inllen1 = sizeof(stop);
memset(buf, 0, sizeof(rawbuf));
rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
- if (rc) {
+ if (rc != 0) {
fprintf(stderr, "Fail to pack ioctl data: rc = %d.\n", rc);
return rc;
}
printf("Stopped LFSCK on the device %s.\n", device);
return 0;
}
+
+int jt_lfsck_query(int argc, char **argv)
+{
+ struct obd_ioctl_data data = { 0 };
+ char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
+ char device[MAX_OBD_NAME] = "";
+ struct lfsck_query query = { .lu_types = LFSCK_TYPES_ALL };
+ int opt, index, rc, i;
+ enum lfsck_type type;
+
+ while ((opt = getopt_long(argc, argv, "hM:t:w", long_opt_query,
+ &index)) != EOF) {
+ switch (opt) {
+ case 'h':
+ usage_query();
+ return 0;
+ case 'M':
+ rc = lfsck_pack_dev(&data, device, optarg);
+ if (rc != 0)
+ return rc;
+ break;
+ case 't': {
+ char *typename;
+
+ if (query.lu_types == LFSCK_TYPES_ALL)
+ query.lu_types = 0;
+ while ((typename = strsep(&optarg, ",")) != NULL) {
+ type = lfsck_name2type(typename);
+ if (type == -1)
+ goto bad_type;
+ query.lu_types |= type;
+ }
+ break;
+
+bad_type:
+ fprintf(stderr, "invalid LFSCK type -t '%s'. "
+ "valid types are:\n", typename);
+ for (i = 0; lfsck_types_names[i].ltn_name != NULL; i++)
+ fprintf(stderr, "%s%s", i != 0 ? "," : "",
+ lfsck_types_names[i].ltn_name);
+ fprintf(stderr, "\n");
+ return -EINVAL;
+ }
+ case 'w':
+ query.lu_flags |= LPF_WAIT;
+ break;
+ default:
+ fprintf(stderr, "Invalid option, '-h' for help.\n");
+ usage_query();
+ return -EINVAL;
+ }
+ }
+
+ if (data.ioc_inlbuf4 == NULL) {
+ if (lcfg_get_devname() != NULL) {
+ rc = lfsck_pack_dev(&data, device, lcfg_get_devname());
+ if (rc != 0)
+ return rc;
+ } else {
+ fprintf(stderr,
+ "Must specify device to query LFSCK.\n");
+ return -EINVAL;
+ }
+ }
+
+ data.ioc_inlbuf1 = (char *)&query;
+ data.ioc_inllen1 = sizeof(query);
+ memset(buf, 0, sizeof(rawbuf));
+ rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
+ if (rc != 0) {
+ fprintf(stderr, "Fail to pack ioctl data: rc = %d.\n", rc);
+ return rc;
+ }
+
+ rc = l_ioctl(OBD_DEV_ID, OBD_IOC_QUERY_LFSCK, buf);
+ if (rc < 0) {
+ perror("Fail to query LFSCK");
+ return rc;
+ }
+
+ obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
+ for (i = 0, type = 1 << i; i < LFSCK_TYPE_BITS; i++, type = 1 << i) {
+ const char *name;
+ int j;
+
+ if (!(query.lu_types & type))
+ continue;
+
+ name = lfsck_type2name(type);
+ for (j = 0; j <= LS_MAX; j++)
+ printf("%s_mdts_%s: %d\n", name,
+ lfsck_status2name(j), query.lu_mdts_count[i][j]);
+
+ for (j = 0; j <= LS_MAX; j++)
+ printf("%s_osts_%s: %d\n", name,
+ lfsck_status2name(j), query.lu_osts_count[i][j]);
+
+ printf("%s_repaired: %llu\n", name, query.lu_repaired[i]);
+ }
+
+ return 0;
+}