}
secs = difftime(&this_time, &prev_time);
- if (prev_valid && secs > 1.0) /* someone screwed with the time? */
- printf("%d/%d Total: %f/second\n", non_zero, total_threads,
- total / secs);
+ if (prev_valid && secs > 1.0) { /* someone screwed with the time? */
+ printf("%d/%d Total: %f/second\n", non_zero, total_threads,
+ total / secs);
- memcpy(counter_snapshot[1], counter_snapshot[0],
- total_threads * sizeof(counter_snapshot[0][0]));
- prev_time = this_time;
- if (!prev_valid &&
- running == total_threads)
- prev_valid = 1;
+ memcpy(counter_snapshot[1], counter_snapshot[0],
+ total_threads * sizeof(counter_snapshot[0][0]));
+ prev_time = this_time;
+ }
+ if (!prev_valid && running == total_threads) {
+ prev_valid = 1;
+ /* drop counters when all threads were started */
+ memcpy(counter_snapshot[1], counter_snapshot[0],
+ total_threads * sizeof(counter_snapshot[0][0]));
+ prev_time = this_time;
+ }
}
static void shmem_stop(void)
if (argc < 2 || argc > 4)
return CMD_HELP;
+ errno = 0;
id = strtoull(argv[1], &end, 0);
if (*end || id == 0 || errno != 0) {
fprintf(stderr, "error: %s: invalid objid '%s'\n",
desc.ld_default_stripe_count);
printf("default_stripe_size: %ju\n",
(uintmax_t)desc.ld_default_stripe_size);
- printf("default_stripe_offset: %ju\n",
+ printf("default_stripe_offset: %jd\n",
(uintmax_t)desc.ld_default_stripe_offset);
printf("default_stripe_pattern: %u\n", desc.ld_pattern);
printf("obd_count: %u\n", desc.ld_tgt_count);
* are skipped and recorded with new nids and uuid.
*
* \see mgs_replace_nids
- * \see mgs_replace_nids_log
- * \see mgs_replace_handler
+ * \see mgs_replace_log
+ * \see mgs_replace_nids_handler
*/
int jt_replace_nids(int argc, char **argv)
{
return rc;
}
+/**
+ * Clear config logs for given device or filesystem.
+ * lctl clear_conf <devicename|fsname>
+ * Command has to be run on MGS node having MGS device mounted with -o
+ * nosvc.
+ *
+ * Configuration logs for filesystem or one particular log is
+ * processed. New log is created, original log is read, its records
+ * marked SKIP do not get copied to new log. Others are copied as-is.
+ * Original file is renamed to log.${time}.bak.
+ *
+ * \see mgs_clear_configs
+ * \see mgs_replace_log
+ * \see mgs_clear_config_handler
+ **/
+int jt_lcfg_clear(int argc, char **argv)
+{
+ int rc;
+ char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
+ struct obd_ioctl_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.ioc_dev = get_mgs_device();
+ if (argc != 2)
+ return CMD_HELP;
+
+ data.ioc_inllen1 = strlen(argv[1]) + 1;
+ data.ioc_inlbuf1 = argv[1];
+
+ memset(buf, 0, sizeof(rawbuf));
+ rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
+ if (rc) {
+ fprintf(stderr, "error: %s: invalid ioctl\n",
+ jt_cmdname(argv[0]));
+ return rc;
+ }
+
+ rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLEAR_CONFIGS, buf);
+ if (rc < 0) {
+ fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
+ strerror(rc = errno));
+ }
+
+ return rc;
+}
+
int jt_obd_deactivate(int argc, char **argv)
{
return do_activate(argc, argv, 0);
memset(&data, 0, sizeof(data));
data.ioc_dev = cur_device;
- data.ioc_inllen1 = sizeof(rawbuf) - cfs_size_round(sizeof(data));
+ data.ioc_inllen1 = sizeof(rawbuf) - __ALIGN_KERNEL(sizeof(data), 8);
memset(buf, 0, sizeof(rawbuf));
rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
if (rc) {
int jt_llog_info(int argc, char **argv)
{
- struct obd_ioctl_data data;
- char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
- int rc;
+ const struct option long_opts[] = {
+ /* Allow optional "--catalog" for compatibility with llog commands. */
+ { .val = 'c', .name = "catalog", .has_arg = required_argument },
+ { .val = 'h', .name = "help", .has_arg = no_argument },
+ { .name = NULL } };
+ struct obd_ioctl_data data = { 0 };
+ char rawbuf[MAX_IOC_BUFLEN] = "", *buf = rawbuf;
+ char *cmd = argv[0];
+ char *catalog = NULL;
+ int rc, c;
- if (argc != 2)
- return CMD_HELP;
+ while ((c = getopt_long(argc, argv, "c:h", long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'c':
+ catalog = optarg;
+ break;
+ case 'h':
+ default:
+ return CMD_HELP;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ /* support "logname" positional parameter */
+ if (argc == 1) {
+ if (catalog) {
+ fprintf(stderr,
+ "%s: catalog is set, unknown argument '%s'\n",
+ cmd, optarg);
+ return CMD_HELP;
+ }
+ catalog = argv[0];
+ } else if (!catalog || argc > 1) {
+ return CMD_HELP;
+ }
- memset(&data, 0, sizeof(data));
- data.ioc_dev = cur_device;
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- data.ioc_inllen2 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
- cfs_size_round(data.ioc_inllen1);
- memset(buf, 0, sizeof(rawbuf));
+ data.ioc_dev = cur_device;
+ data.ioc_inllen1 = strlen(catalog) + 1;
+ data.ioc_inlbuf1 = catalog;
+ data.ioc_inllen2 = sizeof(rawbuf) - __ALIGN_KERNEL(sizeof(data), 8) -
+ __ALIGN_KERNEL(data.ioc_inllen1, 8);
rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
- if (rc) {
- fprintf(stderr, "error: %s: invalid ioctl\n",
- jt_cmdname(argv[0]));
- return rc;
- }
+ if (rc) {
+ fprintf(stderr, "%s: ioctl_pack failed for catalog '%s': %s\n",
+ jt_cmdname(cmd), catalog, strerror(-rc));
+ return rc;
+ }
- rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
- if (rc == 0)
- fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
- else
- fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
- strerror(errno));
+ rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
+ if (rc == 0)
+ fprintf(stdout, "%s", ((struct obd_ioctl_data *)buf)->ioc_bulk);
+ else
+ fprintf(stderr, "%s: OBD_IOC_LLOG_INFO failed: %s\n",
+ jt_cmdname(cmd), strerror(errno));
- return rc;
+ return rc;
}
-int jt_llog_print(int argc, char **argv)
+int jt_llog_print_cb(const char *record, void *private)
{
- struct obd_ioctl_data data;
- char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
- int rc;
+ printf("%s\n", record);
- if (argc != 2 && argc != 4)
- return CMD_HELP;
+ return 0;
+}
- memset(&data, 0, sizeof(data));
- data.ioc_dev = cur_device;
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- if (argc == 4) {
- data.ioc_inllen2 = strlen(argv[2]) + 1;
- data.ioc_inlbuf2 = argv[2];
- data.ioc_inllen3 = strlen(argv[3]) + 1;
- data.ioc_inlbuf3 = argv[3];
- } else {
- char from[2] = "1", to[3] = "-1";
- data.ioc_inllen2 = strlen(from) + 1;
- data.ioc_inlbuf2 = from;
- data.ioc_inllen3 = strlen(to) + 1;
- data.ioc_inlbuf3 = to;
- }
- data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
- cfs_size_round(data.ioc_inllen1) -
- cfs_size_round(data.ioc_inllen2) -
- cfs_size_round(data.ioc_inllen3);
- memset(buf, 0, sizeof(rawbuf));
- rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
- if (rc) {
- fprintf(stderr, "error: %s: invalid ioctl\n",
- jt_cmdname(argv[0]));
- return rc;
- }
+/**
+ * Iterate over llog records, typically YAML-formatted configuration logs
+ *
+ * \param logname[in] name of llog file or FID
+ * \param start[in] first record to process
+ * \param end[in] last record to process (inclusive)
+ * \param cb[in] callback for records. Return -ve error, or +ve abort.
+ * \param private[in,out] private data passed to the \a record_cb function
+ */
+int jt_llog_print_iter(char *logname, long start, long end,
+ int (record_cb)(const char *record, void *private),
+ void *private)
+{
+ struct obd_ioctl_data data = { 0 };
+ char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
+ char startbuf[16], endbuf[16];
+ static long inc = sizeof(rawbuf) / 128;
+ long rec;
+ int rc = 0;
- rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
- if (rc == 0)
- fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
- else
- fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
- strerror(errno));
+ if (end == -1)
+ end = 0x7fffffff;
- return rc;
+ data.ioc_dev = cur_device;
+ data.ioc_inlbuf1 = logname;
+ data.ioc_inllen1 = strlen(logname) + 1;
+
+ /*
+ * Estimate about 128 characters per configuration record. Not all
+ * records will be printed in any case, so they should easily fit. If
+ * not, the kernel will return -EOVERFLOW and ask for fewer records.
+ *
+ * We don't want to request records from the kernel one-at-a-time, as
+ * it restarts the config llog iteration from the beginning, so we
+ * fetch multiple records from the kernel per call and split locally.
+ */
+ for (rec = start; rec < end; rec += inc) {
+ char *record = ((struct obd_ioctl_data *)buf)->ioc_bulk;
+ char *ptr;
+
+retry:
+ snprintf(startbuf, sizeof(startbuf), "%lu", rec);
+ snprintf(endbuf, sizeof(endbuf), "%lu",
+ end < rec + inc - 1 ? end : rec + inc - 1);
+
+ /* start and end record numbers are passed as ASCII digits */
+ data.ioc_inlbuf2 = startbuf;
+ data.ioc_inllen2 = strlen(startbuf) + 1;
+ data.ioc_inlbuf3 = endbuf;
+ data.ioc_inllen3 = strlen(endbuf) + 1;
+
+ data.ioc_inllen4 = sizeof(rawbuf) -
+ __ALIGN_KERNEL(sizeof(data), 8) -
+ __ALIGN_KERNEL(data.ioc_inllen1, 8) -
+ __ALIGN_KERNEL(data.ioc_inllen2, 8) -
+ __ALIGN_KERNEL(data.ioc_inllen3, 8);
+ memset(buf, 0, sizeof(rawbuf));
+ rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
+ if (rc) {
+ fprintf(stderr, "%s: invalid ioctl data\n", logname);
+ goto out;
+ }
+
+ rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
+ if (rc == -EOVERFLOW && inc > 2) {
+ inc /= 2;
+ goto retry;
+ }
+ if (rc) {
+ fprintf(stderr, "%s: OBD_IOC_LLOG_PRINT failed: %s\n",
+ logname, strerror(errno));
+ rc = -errno;
+ goto out;
+ }
+
+ /* There is no "end of list" marker, record was not modified */
+ if (strcmp(record, logname) == 0)
+ break;
+
+ do {
+ ptr = strchr(record, '\n');
+ if (ptr)
+ *ptr = '\0';
+ rc = record_cb(record, private);
+ if (rc) {
+ if (rc > 0)
+ rc = 0;
+ goto out;
+ }
+
+ if (ptr)
+ record = ptr + 1;
+ } while (ptr && *(ptr + 1));
+ }
+
+out:
+ return rc;
+}
+
+static int llog_parse_catalog_start_end(int *argc, char **argv[],
+ char **catalog, long *start, long *end)
+{
+ const struct option long_opts[] = {
+ /* the --catalog option is not required, just for consistency */
+ { .val = 'c', .name = "catalog", .has_arg = required_argument },
+ { .val = 'e', .name = "end", .has_arg = required_argument },
+ { .val = 'h', .name = "help", .has_arg = no_argument },
+ { .val = 's', .name = "start", .has_arg = required_argument },
+ { .name = NULL } };
+ char *cmd = (*argv)[0];
+ char *endp;
+ int c;
+
+ if (catalog == NULL || start == NULL || end == NULL)
+ return -EINVAL;
+
+ /* now process command line arguments*/
+ while ((c = getopt_long(*argc, *argv, "c:e:hs:",
+ long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'c':
+ *catalog = optarg;
+ break;
+ case 'e':
+ *end = strtol(optarg, &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "%s: bad end value '%s'\n",
+ cmd, optarg);
+ return CMD_HELP;
+ }
+ break;
+ case 's':
+ *start = strtol(optarg, &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "%s: bad start value '%s'\n",
+ cmd, optarg);
+ return CMD_HELP;
+ }
+ break;
+ case 'h':
+ default:
+ return CMD_HELP;
+ }
+ }
+ *argc -= optind;
+ *argv += optind;
+
+ /* support old optional positional parameters only if they were
+ * not already specified with named arguments: logname [start [end]]
+ */
+ if (*argc >= 1) {
+ if (*catalog) {
+ fprintf(stderr,
+ "%s: catalog is set, unknown argument '%s'\n",
+ cmd, (*argv)[0]);
+ return CMD_HELP;
+ }
+ *catalog = (*argv)[0];
+ (*argc)--;
+ (*argv)++;
+ }
+
+ if (*argc >= 1) {
+ if (*start != 1) {
+ fprintf(stderr,
+ "%s: --start is set, unknown argument '%s'\n",
+ cmd, (*argv)[0]);
+ return CMD_HELP;
+ }
+
+ *start = strtol((*argv)[0], &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "%s: bad start value '%s'\n",
+ cmd, (*argv)[0]);
+ return CMD_HELP;
+ }
+ (*argc)--;
+ (*argv)++;
+ }
+ if (*argc >= 1) {
+ if (*end != -1) {
+ fprintf(stderr,
+ "%s: --end is set, unknown argument '%s'\n",
+ cmd, (*argv)[0]);
+ return CMD_HELP;
+ }
+
+ *end = strtol((*argv)[0], &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "%s: bad end value '%s'\n",
+ cmd, (*argv)[0]);
+ return CMD_HELP;
+ }
+ (*argc)--;
+ (*argv)++;
+ }
+ if (*argc > 1) {
+ fprintf(stderr, "%s: unknown argument '%s'\n", cmd, (*argv)[0]);
+ return CMD_HELP;
+ }
+
+ if (*end != -1 && *end < *start) {
+ fprintf(stderr, "%s: end '%lu' less than than start '%lu'\n",
+ cmd, *end, *start);
+ return CMD_HELP;
+ }
+
+ return 0;
}
-static int llog_cancel_parse_optional(int argc, char **argv,
- struct obd_ioctl_data *data)
+int jt_llog_print(int argc, char **argv)
+{
+ char *catalog = NULL;
+ long start = 1, end = -1;
+ int rc;
+
+ rc = llog_parse_catalog_start_end(&argc, &argv, &catalog, &start, &end);
+ if (rc)
+ return rc;
+
+ rc = jt_llog_print_iter(catalog, start, end, jt_llog_print_cb, NULL);
+
+ return rc;
+}
+
+/* Parse catalog, log ID, and optionally a log index with either optional
+ * arguments or positional arguments. Only the initial catalog argument
+ * may be positional with other optional arguments.
+ *
+ * The positional arguments option should eventually be phased out.
+ */
+static int llog_parse_catalog_log_idx(int *argc, char ***argv, const char *opts,
+ int max_args, struct obd_ioctl_data *data)
{
- int cOpt;
- const char *const short_opts = "c:l:i:h";
const struct option long_opts[] = {
+ /* the --catalog option is not required, just for consistency */
{ .val = 'c', .name = "catalog", .has_arg = required_argument },
{ .val = 'h', .name = "help", .has_arg = no_argument },
{ .val = 'i', .name = "log_idx", .has_arg = required_argument },
{ .val = 'l', .name = "log_id", .has_arg = required_argument },
{ .name = NULL } };
+ int c;
/* sanity check */
- if (!data || argc <= 1) {
+ if (!data || *argc <= 1)
return -1;
- }
- /*now process command line arguments*/
- while ((cOpt = getopt_long(argc, argv, short_opts,
- long_opts, NULL)) != -1) {
- switch (cOpt) {
+ data->ioc_dev = cur_device;
+
+ /* now process command line arguments*/
+ while ((c = getopt_long(*argc, *argv, opts, long_opts, NULL)) != -1) {
+ switch (c) {
case 'c':
data->ioc_inllen1 = strlen(optarg) + 1;
data->ioc_inlbuf1 = optarg;
break;
-
- case 'l':
- data->ioc_inllen2 = strlen(optarg) + 1;
- data->ioc_inlbuf2 = optarg;
- break;
-
case 'i':
data->ioc_inllen3 = strlen(optarg) + 1;
data->ioc_inlbuf3 = optarg;
break;
-
+ case 'l': /* The log_id option isn't currently needed for
+ * cancel as mdt_iocontrol() handles IOC_LLOG_CANCEL,
+ * but we may as well keep it for now.
+ */
+ data->ioc_inllen2 = strlen(optarg) + 1;
+ data->ioc_inlbuf2 = optarg;
+ break;
case 'h':
default:
- return -1;
+ return CMD_HELP;
}
}
- if ((data->ioc_inlbuf1 == NULL) || (data->ioc_inlbuf3 == NULL)) {
- /* missing mandatory parameters */
- return -1;
+ *argc -= optind;
+ *argv += optind;
+
+ /* Allow catalog to be specified as first option without --catalog */
+ if (data->ioc_inlbuf1 == NULL && *argc > 0) {
+ data->ioc_inlbuf1 = (*argv)[0];
+ data->ioc_inllen1 = strlen((*argv)[0]) + 1;
+ (*argc)--;
+ (*argv)++;
}
return 0;
int jt_llog_cancel(int argc, char **argv)
{
- struct obd_ioctl_data data;
- char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
- int rc, i;
+ struct obd_ioctl_data data = { 0 };
+ char rawbuf[MAX_IOC_BUFLEN] = "", *buf = rawbuf;
+ char *cmd = argv[0];
+ int rc;
- /* check that the arguments provided are either all
- * optional or all positional. No mixing allowed
- *
- * if argc is 4 or 3 then check all arguments to ensure that none
- * of them start with a '-'. If so then this is invalid.
- * Otherwise if arg is > 4 then assume that this is optional
- * arguments, and parse as such ignoring any thing that's not
- * optional. The result is that user must use optional arguments
- * for all mandatory parameters. Code will ignore all other args
- *
- * The positional arguments option should eventually be phased out.
- */
- memset(&data, 0, sizeof(data));
- data.ioc_dev = cur_device;
+ /* Parse catalog file (in inlbuf1) and named parameters */
+ rc = llog_parse_catalog_log_idx(&argc, &argv, "c:hi:l:", 3, &data);
- if (argc == 3 || argc == 4) {
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-')
- return CMD_HELP;
- }
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- if (argc == 4) {
- data.ioc_inllen2 = strlen(argv[2]) + 1;
- data.ioc_inlbuf2 = argv[2];
- data.ioc_inllen3 = strlen(argv[3]) + 1;
- data.ioc_inlbuf3 = argv[3];
- } else {
- data.ioc_inllen3 = strlen(argv[2]) + 1;
- data.ioc_inlbuf3 = argv[2];
- }
- } else {
- if (llog_cancel_parse_optional(argc, argv, &data) != 0)
- return CMD_HELP;
+ /* Handle old positional parameters if not using named parameters,
+ * either "<catalog> <log_idx>" or "<catalog> <log_id> <log_idx>".
+ * It was "inlbuf3 = log_idx", and "inlbuf2 = log_id" (ignored by
+ * config log cancel), and shows why I hate positional parameters.
+ */
+ if (argc == 1) {
+ data.ioc_inllen3 = strlen(argv[0]) + 1;
+ data.ioc_inlbuf3 = argv[0];
+ } else if (argc == 2) {
+ data.ioc_inllen2 = strlen(argv[0]) + 1;
+ data.ioc_inlbuf2 = argv[0];
+ data.ioc_inllen3 = strlen(argv[1]) + 1;
+ data.ioc_inlbuf3 = argv[1];
}
- memset(buf, 0, sizeof(rawbuf));
+ if (data.ioc_inlbuf1 == NULL || data.ioc_inlbuf3 == NULL)
+ /* missing mandatory parameters */
+ return CMD_HELP;
+
rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
if (rc) {
- fprintf(stderr, "error: %s: invalid ioctl\n",
- jt_cmdname(argv[0]));
+ fprintf(stderr, "%s: ioctl_pack for catalog '%s' failed: %s\n",
+ jt_cmdname(cmd), data.ioc_inlbuf1, strerror(-rc));
return rc;
}
rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
- if (rc == 0)
- fprintf(stdout, "index %s was canceled.\n",
- argc == 4 ? argv[3] : argv[2]);
- else
- fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
+ if (rc)
+ fprintf(stderr, "%s: cancel catalog '%s:%s' failed: %s\n",
+ jt_cmdname(cmd), data.ioc_inlbuf1, data.ioc_inlbuf3,
strerror(errno));
return rc;
int jt_llog_check(int argc, char **argv)
{
- struct obd_ioctl_data data;
- char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
- int rc;
+ struct obd_ioctl_data data = { 0 };
+ char rawbuf[MAX_IOC_BUFLEN] = "", *buf = rawbuf;
+ char *catalog = NULL;
+ char startbuf[16], endbuf[16];
+ long start = 1, end = -1;
+ char *cmd = argv[0];
+ int rc;
- if (argc != 2 && argc != 4)
- return CMD_HELP;
+ rc = llog_parse_catalog_start_end(&argc, &argv, &catalog, &start, &end);
+ if (rc)
+ return rc;
- memset(&data, 0, sizeof(data));
- data.ioc_dev = cur_device;
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- if (argc == 4) {
- data.ioc_inllen2 = strlen(argv[2]) + 1;
- data.ioc_inlbuf2 = argv[2];
- data.ioc_inllen3 = strlen(argv[3]) + 1;
- data.ioc_inlbuf3 = argv[3];
- } else {
- char from[2] = "1", to[3] = "-1";
- data.ioc_inllen2 = strlen(from) + 1;
- data.ioc_inlbuf2 = from;
- data.ioc_inllen3 = strlen(to) + 1;
- data.ioc_inlbuf3 = to;
- }
- data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
- cfs_size_round(data.ioc_inllen1) -
- cfs_size_round(data.ioc_inllen2) -
- cfs_size_round(data.ioc_inllen3);
- memset(buf, 0, sizeof(rawbuf));
+ if (end == -1)
+ end = 0x7fffffff;
+
+ data.ioc_dev = cur_device;
+ data.ioc_inllen1 = strlen(catalog) + 1;
+ data.ioc_inlbuf1 = catalog;
+
+ snprintf(startbuf, sizeof(startbuf), "%lu", start);
+ snprintf(endbuf, sizeof(endbuf), "%lu", end);
+ /* start and end record numbers are passed as ASCII digits */
+ data.ioc_inllen2 = strlen(startbuf) + 1;
+ data.ioc_inlbuf2 = startbuf;
+ data.ioc_inllen3 = strlen(endbuf) + 1;
+ data.ioc_inlbuf3 = endbuf;
+
+ data.ioc_inllen4 = sizeof(rawbuf) - __ALIGN_KERNEL(sizeof(data), 8) -
+ __ALIGN_KERNEL(data.ioc_inllen1, 8) -
+ __ALIGN_KERNEL(data.ioc_inllen2, 8) -
+ __ALIGN_KERNEL(data.ioc_inllen3, 8);
rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
- if (rc) {
- fprintf(stderr, "error: %s: invalid ioctl\n",
- jt_cmdname(argv[0]));
- return rc;
- }
+ if (rc) {
+ fprintf(stderr, "%s: ioctl_pack failed for catalog '%s': %s\n",
+ jt_cmdname(cmd), data.ioc_inlbuf1, strerror(-rc));
+ return rc;
+ }
- rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
- if (rc == 0)
- fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
- else
- fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
- strerror(errno));
- return rc;
+ rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
+ if (rc == 0)
+ fprintf(stdout, "%s", ((struct obd_ioctl_data *)buf)->ioc_bulk);
+ else
+ fprintf(stderr, "%s: OBD_IOC_LLOG_CHECK failed: %s\n",
+ jt_cmdname(cmd), strerror(errno));
+ return rc;
}
int jt_llog_remove(int argc, char **argv)
{
- struct obd_ioctl_data data;
- char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
- int rc;
+ struct obd_ioctl_data data = { 0 };
+ char rawbuf[MAX_IOC_BUFLEN] = "", *buf = rawbuf;
+ char *cmd = argv[0];
+ int rc;
- if (argc != 3 && argc != 2)
- return CMD_HELP;
+ rc = llog_parse_catalog_log_idx(&argc, &argv, "c:hl:", 2, &data);
+ if (rc)
+ return rc;
- memset(&data, 0, sizeof(data));
- data.ioc_dev = cur_device;
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- if (argc == 3){
- data.ioc_inllen2 = strlen(argv[2]) + 1;
- data.ioc_inlbuf2 = argv[2];
- }
- memset(buf, 0, sizeof(rawbuf));
+ if (argc == 1) {
+ if (data.ioc_inlbuf2) {
+ fprintf(stderr,
+ "%s: --log_id is set, unknown argument '%s'\n",
+ jt_cmdname(cmd), argv[0]);
+ return CMD_HELP;
+ }
+
+ data.ioc_inllen2 = strlen(argv[0]) + 1;
+ data.ioc_inlbuf2 = argv[0];
+ }
rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
- if (rc) {
- fprintf(stderr, "error: %s: invalid ioctl\n",
- jt_cmdname(argv[0]));
- return rc;
- }
+ if (rc) {
+ fprintf(stderr, "%s: ioctl_pack for catalog '%s' failed: %s\n",
+ jt_cmdname(cmd), data.ioc_inlbuf1, strerror(-rc));
+ return rc;
+ }
- rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
- if (rc == 0) {
- if (argc == 2)
- fprintf(stdout, "log %s is removed.\n", argv[1]);
- else
- fprintf(stdout, "the log in catalog %s is removed. \n",
- argv[1]);
- } else
- fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
- strerror(errno));
+ rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
+ if (rc)
+ fprintf(stderr, "%s: cancel catalog '%s:%s' failed: %s\n",
+ jt_cmdname(cmd), data.ioc_inlbuf1, data.ioc_inlbuf2,
+ strerror(-rc));
- return rc;
+ return rc;
}
static void signal_server(int sig)
}
/**
+ * parse nid range
+ *
+ * \param nodemap_range --range string
+ * \param nid_range nid range string, min_nid:max_nid
+ *
+ * \retval 0 on success
+ */
+static int parse_nid_range(char *nodemap_range, char *nid_range, int range_len)
+{
+ char min_nid[LNET_NIDSTR_SIZE + 1];
+ char max_nid[LNET_NIDSTR_SIZE + 1];
+ struct list_head nidlist;
+ int rc = 0;
+
+ INIT_LIST_HEAD(&nidlist);
+
+ if (cfs_parse_nidlist(nodemap_range, strlen(nodemap_range),
+ &nidlist) <= 0) {
+ fprintf(stderr,
+ "error: nodemap_xxx_range: can't parse nid range: %s\n",
+ nodemap_range);
+ return -1;
+ }
+
+ rc = cfs_nidrange_find_min_max(&nidlist, &min_nid[0], &max_nid[0],
+ LNET_NIDSTR_SIZE);
+ if (rc < 0) {
+ if (rc == -EINVAL)
+ fprintf(stderr,
+ "error: nodemap_xxx_range: nid range uses "
+ "currently unsupported features\n");
+ else if (rc == -ERANGE)
+ fprintf(stderr,
+ "error: nodemap_xxx_range: nodemap ranges must "
+ "be contiguous\n");
+
+ return rc;
+ }
+
+ snprintf(nid_range, range_len, "%s:%s", min_nid, max_nid);
+
+ return rc;
+}
+
+/**
* add an nid range to a nodemap
*
* \param argc number of args
{
char *nodemap_name = NULL;
char *nodemap_range = NULL;
- struct list_head nidlist;
- char min_nid[LNET_NIDSTR_SIZE + 1];
- char max_nid[LNET_NIDSTR_SIZE + 1];
char nid_range[2 * LNET_NIDSTR_SIZE + 2];
int rc = 0;
int c;
{ .val = 'r', .name = "range", .has_arg = required_argument },
{ .name = NULL } };
- INIT_LIST_HEAD(&nidlist);
-
while ((c = getopt_long(argc, argv, "n:r:",
long_opts, NULL)) != -1) {
switch (c) {
return -1;
}
- if (cfs_parse_nidlist(nodemap_range, strlen(nodemap_range),
- &nidlist) <= 0) {
- fprintf(stderr, "error: %s: can't parse nid range: %s\n",
- jt_cmdname(argv[0]), nodemap_range);
- return -1;
- }
-
- if (!cfs_nidrange_is_contiguous(&nidlist)) {
- fprintf(stderr, "error: %s: nodemap ranges must be "
- "contiguous\n", jt_cmdname(argv[0]));
- return -1;
+ rc = parse_nid_range(nodemap_range, nid_range, sizeof(nid_range));
+ if (rc) {
+ errno = -rc;
+ return rc;
}
-
- cfs_nidrange_find_min_max(&nidlist, &min_nid[0], &max_nid[0],
- LNET_NIDSTR_SIZE);
- snprintf(nid_range, sizeof(nid_range), "%s:%s", min_nid, max_nid);
-
rc = nodemap_cmd(LCFG_NODEMAP_ADD_RANGE, NULL, 0, argv[0],
nodemap_name, nid_range, NULL);
if (rc != 0) {
{
char *nodemap_name = NULL;
char *nodemap_range = NULL;
- struct list_head nidlist;
- char min_nid[LNET_NIDSTR_SIZE + 1];
- char max_nid[LNET_NIDSTR_SIZE + 1];
char nid_range[2 * LNET_NIDSTR_SIZE + 2];
int rc = 0;
int c;
{ .val = 'r', .name = "range", .has_arg = required_argument },
{ .name = NULL } };
- INIT_LIST_HEAD(&nidlist);
-
while ((c = getopt_long(argc, argv, "n:r:",
long_opts, NULL)) != -1) {
switch (c) {
return -1;
}
- if (cfs_parse_nidlist(nodemap_range, strlen(nodemap_range),
- &nidlist) <= 0) {
- fprintf(stderr, "error: %s: can't parse nid range: %s\n",
- jt_cmdname(argv[0]), nodemap_range);
- return -1;
- }
-
- if (!cfs_nidrange_is_contiguous(&nidlist)) {
- fprintf(stderr, "error: %s: nodemap ranges must be "
- "contiguous\n", jt_cmdname(argv[0]));
- return -1;
+ rc = parse_nid_range(nodemap_range, nid_range, sizeof(nid_range));
+ if (rc) {
+ errno = -rc;
+ return rc;
}
-
- cfs_nidrange_find_min_max(&nidlist, &min_nid[0], &max_nid[0],
- LNET_NIDSTR_SIZE);
- snprintf(nid_range, sizeof(nid_range), "%s:%s", min_nid, max_nid);
-
rc = nodemap_cmd(LCFG_NODEMAP_DEL_RANGE, NULL, 0, argv[0],
nodemap_name, nid_range, NULL);
if (rc != 0) {
}
/**
+ * set SELinux policy info on a nodemap
+ *
+ * \param argc number of args
+ * \param argv[] variable string arguments
+ *
+ * --name nodemap name
+ * --sepol SELinux policy info
+ *
+ * \retval 0 on success
+ */
+int jt_nodemap_set_sepol(int argc, char **argv)
+{
+ char *nodemap_name = NULL;
+ char *sepol = NULL;
+ int rc = 0;
+ int c;
+
+ static struct option long_options[] = {
+ {
+ .name = "name",
+ .has_arg = required_argument,
+ .val = 'n',
+ },
+ {
+ .name = "sepol",
+ .has_arg = required_argument,
+ .val = 's',
+ },
+ {
+ .name = NULL,
+ }
+ };
+
+ while ((c = getopt_long(argc, argv, "n:s:",
+ long_options, NULL)) != -1) {
+ switch (c) {
+ case 'n':
+ nodemap_name = optarg;
+ break;
+ case 's':
+ sepol = optarg;
+ break;
+ }
+ }
+
+ if (nodemap_name == NULL || sepol == NULL) {
+ fprintf(stderr, "usage: nodemap_set_sepol --name <name> "
+ "--sepol <sepol>\n");
+ return -1;
+ }
+
+ rc = nodemap_cmd(LCFG_NODEMAP_SET_SEPOL, NULL, 0, argv[0],
+ nodemap_name, sepol, NULL);
+ if (rc != 0) {
+ errno = -rc;
+ fprintf(stderr, "error: %s: cannot set sepol '%s' on nodemap "
+ "'%s': rc = %d\n",
+ jt_cmdname(argv[0]), sepol, nodemap_name, rc);
+ }
+
+ return rc;
+}
+
+/**
* modify a nodemap's behavior
*
* \param argc number of args
char *ptr;
int rc;
- strlcpy(fsname, arg, PATH_MAX + 1);
+ snprintf(fsname, PATH_MAX + 1, "%s", arg);
ptr = strchr(fsname, '.');
if (ptr == NULL) {
fprintf(stderr, ". is missing in %s\n", fsname);
strncpy(poolname, ptr, LOV_MAXPOOLNAME);
poolname[LOV_MAXPOOLNAME] = '\0';
+
+ if (strncmp(poolname, "none", LOV_MAXPOOLNAME) == 0) {
+ fprintf(stderr, "poolname cannot be 'none'\n");
+ return -EINVAL;
+ }
return 0;
err: