diff options
Diffstat (limited to 'usr/src/cmd/nvmeadm/nvmeadm.c')
| -rw-r--r-- | usr/src/cmd/nvmeadm/nvmeadm.c | 155 |
1 files changed, 111 insertions, 44 deletions
diff --git a/usr/src/cmd/nvmeadm/nvmeadm.c b/usr/src/cmd/nvmeadm/nvmeadm.c index a13f0555ce..e177e04d82 100644 --- a/usr/src/cmd/nvmeadm/nvmeadm.c +++ b/usr/src/cmd/nvmeadm/nvmeadm.c @@ -49,27 +49,6 @@ #include "nvmeadm.h" -typedef struct nvme_process_arg nvme_process_arg_t; -typedef struct nvme_feature nvme_feature_t; -typedef struct nvmeadm_cmd nvmeadm_cmd_t; - -struct nvme_process_arg { - int npa_argc; - char **npa_argv; - char *npa_name; - char *npa_nsid; - int npa_found; - boolean_t npa_isns; - const nvmeadm_cmd_t *npa_cmd; - di_node_t npa_node; - di_minor_t npa_minor; - char *npa_path; - char *npa_dsk; - nvme_identify_ctrl_t *npa_idctl; - nvme_identify_nsid_t *npa_idns; - nvme_version_t *npa_version; -}; - struct nvme_feature { char *f_name; char *f_short; @@ -87,11 +66,12 @@ struct nvme_feature { struct nvmeadm_cmd { char *c_name; - char *c_desc; - char *c_flagdesc; + const char *c_desc; + const char *c_flagdesc; int (*c_func)(int, const nvme_process_arg_t *); void (*c_usage)(const char *); boolean_t c_multi; + void (*c_optparse)(nvme_process_arg_t *); }; @@ -121,6 +101,8 @@ static int do_firmware_load(int, const nvme_process_arg_t *); static int do_firmware_commit(int, const nvme_process_arg_t *); static int do_firmware_activate(int, const nvme_process_arg_t *); +static void optparse_list(nvme_process_arg_t *); + static void usage_list(const char *); static void usage_identify(const char *); static void usage_get_logpage(const char *); @@ -140,8 +122,9 @@ static const nvmeadm_cmd_t nvmeadm_cmds[] = { { "list", "list controllers and namespaces", - NULL, - do_list, usage_list, B_TRUE + " -p\t\tprint parsable output\n" + " -o field\tselect a field for parsable output\n", + do_list, usage_list, B_TRUE, optparse_list }, { "identify", @@ -257,12 +240,12 @@ int main(int argc, char **argv) { int c; - extern int optind; const nvmeadm_cmd_t *cmd; di_node_t node; nvme_process_arg_t npa = { 0 }; int help = 0; char *tmp, *lasts = NULL; + char *ctrl = NULL; while ((c = getopt(argc, argv, "dhv")) != -1) { switch (c) { @@ -309,25 +292,42 @@ main(int argc, char **argv) optind++; /* - * All commands but "list" require a ctl/ns argument. + * Store the remaining arguments for use by the command. Give the + * command a chance to process the options across the board before going + * into each controller. */ - if ((optind == argc || (strncmp(argv[optind], "nvme", 4) != 0)) && + npa.npa_argc = argc - optind; + npa.npa_argv = &argv[optind]; + + if (cmd->c_optparse != NULL) { + cmd->c_optparse(&npa); + } + + /* + * All commands but "list" require a ctl/ns argument. However, this + * should not be passed through to the command in its subsequent + * arguments. + */ + if ((npa.npa_argc == 0 || (strncmp(npa.npa_argv[0], "nvme", 4) != 0)) && cmd->c_func != do_list) { warnx("missing controller/namespace name"); usage(cmd); exit(-1); } - - /* Store the remaining arguments for use by the command. */ - npa.npa_argc = argc - optind - 1; - npa.npa_argv = &argv[optind + 1]; + if (npa.npa_argc > 0) { + ctrl = npa.npa_argv[0]; + npa.npa_argv++; + npa.npa_argc--; + } else { + ctrl = NULL; + } /* * Make sure we're not running commands on multiple controllers that * aren't allowed to do that. */ - if (argv[optind] != NULL && strchr(argv[optind], ',') != NULL && + if (ctrl != NULL && strchr(ctrl, ',') != NULL && cmd->c_multi == B_FALSE) { warnx("%s not allowed on multiple controllers", cmd->c_name); @@ -338,7 +338,7 @@ main(int argc, char **argv) /* * Get controller/namespace arguments and run command. */ - npa.npa_name = strtok_r(argv[optind], ",", &lasts); + npa.npa_name = strtok_r(ctrl, ",", &lasts); do { if (npa.npa_name != NULL) { tmp = strchr(npa.npa_name, '/'); @@ -373,6 +373,15 @@ main(int argc, char **argv) } static void +nvme_oferr(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verrx(-1, fmt, ap); +} + +static void usage(const nvmeadm_cmd_t *cmd) { (void) fprintf(stderr, "usage:\n"); @@ -394,9 +403,9 @@ usage(const nvmeadm_cmd_t *cmd) cmd->c_name, cmd->c_desc); } (void) fprintf(stderr, "\nflags:\n" - " -h print usage information\n" - " -d print information useful for debugging %s\n" - " -v print verbose information\n", getprogname()); + " -h\t\tprint usage information\n" + " -d\t\tprint information useful for debugging %s\n" + " -v\t\tprint verbose information\n", getprogname()); if (cmd != NULL && cmd->c_flagdesc != NULL) (void) fprintf(stderr, "%s\n", cmd->c_flagdesc); } @@ -554,13 +563,63 @@ nvme_walk(nvme_process_arg_t *npa, di_node_t node) static void usage_list(const char *c_name) { - (void) fprintf(stderr, "%s [<ctl>[/<ns>][,...]\n\n" + (void) fprintf(stderr, "%s " + "[-p -o field[,...]] [<ctl>[/<ns>][,...]\n\n" " List NVMe controllers and their namespaces. If no " "controllers and/or name-\n spaces are specified, all " "controllers and namespaces in the system will be\n " "listed.\n", c_name); } +static void +optparse_list(nvme_process_arg_t *npa) +{ + int c; + uint_t oflags = 0; + boolean_t parse = B_FALSE; + const char *fields = NULL; + + optind = 0; + while ((c = getopt(npa->npa_argc, npa->npa_argv, ":o:p")) != -1) { + switch (c) { + case 'o': + fields = optarg; + break; + case 'p': + parse = B_TRUE; + oflags |= OFMT_PARSABLE; + break; + case '?': + errx(-1, "unknown list option: -%c", optopt); + break; + case ':': + errx(-1, "option -%c requires an argument", optopt); + default: + break; + } + } + + if (fields != NULL && !parse) { + errx(-1, "-o can only be used when in parsable mode (-p)"); + } + + if (parse && fields == NULL) { + errx(-1, "parsable mode (-p) requires one to specify output " + "fields with -o"); + } + + if (parse) { + ofmt_status_t oferr; + + oferr = ofmt_open(fields, nvme_list_ofmt, oflags, 0, + &npa->npa_ofmt); + ofmt_check(oferr, B_TRUE, npa->npa_ofmt, nvme_oferr, warnx); + } + + npa->npa_argc -= optind; + npa->npa_argv += optind; +} + static int do_list_nsid(int fd, const nvme_process_arg_t *npa) { @@ -575,10 +634,14 @@ do_list_nsid(int fd, const nvme_process_arg_t *npa) if ((bshift < 9 || npa->npa_idns->id_nsize == 0) && verbose == 0) return (0); - (void) printf(" %s/%s (%s): ", npa->npa_name, - di_minor_name(npa->npa_minor), - npa->npa_dsk != NULL ? npa->npa_dsk : "unattached"); - nvme_print_nsid_summary(npa->npa_idns); + if (npa->npa_ofmt == NULL) { + (void) printf(" %s/%s (%s): ", npa->npa_name, + di_minor_name(npa->npa_minor), + npa->npa_dsk != NULL ? npa->npa_dsk : "unattached"); + nvme_print_nsid_summary(npa->npa_idns); + } else { + ofmt_print(npa->npa_ofmt, (void *)npa); + } return (0); } @@ -596,8 +659,10 @@ do_list(int fd, const nvme_process_arg_t *npa) di_instance(npa->npa_node)) < 0) err(-1, "do_list()"); - (void) printf("%s: ", name); - nvme_print_ctrl_summary(npa->npa_idctl, npa->npa_version); + if (npa->npa_ofmt == NULL) { + (void) printf("%s: ", name); + nvme_print_ctrl_summary(npa->npa_idctl, npa->npa_version); + } ns_npa.npa_name = name; ns_npa.npa_isns = B_TRUE; @@ -605,6 +670,8 @@ do_list(int fd, const nvme_process_arg_t *npa) cmd = *(npa->npa_cmd); cmd.c_func = do_list_nsid; ns_npa.npa_cmd = &cmd; + ns_npa.npa_ofmt = npa->npa_ofmt; + ns_npa.npa_idctl = npa->npa_idctl; nvme_walk(&ns_npa, npa->npa_node); |
