Index: sbin/nvmecontrol/devlist.c =================================================================== --- sbin/nvmecontrol/devlist.c +++ sbin/nvmecontrol/devlist.c @@ -43,6 +43,9 @@ #include "nvmecontrol.h" +#define DEVLIST_USAGE \ +" nvmecontrol devlist\n" + static void devlist_usage(void) { @@ -64,7 +67,7 @@ return (1 << lbads); } -void +static void devlist(int argc, char *argv[]) { struct nvme_controller_data cdata; @@ -124,3 +127,5 @@ exit(1); } + +NVME_COMMAND(top, devlist, devlist, DEVLIST_USAGE); Index: sbin/nvmecontrol/firmware.c =================================================================== --- sbin/nvmecontrol/firmware.c +++ sbin/nvmecontrol/firmware.c @@ -50,6 +50,10 @@ #include "nvmecontrol.h" +#define FIRMWARE_USAGE \ +" nvmecontrol firmware [-s slot] [-f path_to_firmware] [-a] \n" + + static int slot_has_valid_firmware(int fd, int slot) { @@ -178,7 +182,7 @@ exit(1); } -void +static void firmware(int argc, char *argv[]) { int fd = -1, slot = 0; @@ -338,3 +342,5 @@ close(fd); exit(0); } + +NVME_COMMAND(top, firmware, firmware, FIRMWARE_USAGE); Index: sbin/nvmecontrol/format.c =================================================================== --- sbin/nvmecontrol/format.c +++ sbin/nvmecontrol/format.c @@ -43,6 +43,9 @@ #include "nvmecontrol.h" +#define FORMAT_USAGE \ +" nvmecontrol format [-f fmt] [-m mset] [-p pi] [-l pil] [-E] [-C] \n" + static void format_usage(void) { @@ -51,7 +54,7 @@ exit(1); } -void +static void format(int argc, char *argv[]) { struct nvme_controller_data cd; @@ -185,3 +188,5 @@ close(fd); exit(0); } + +NVME_COMMAND(top, format, format, FORMAT_USAGE); Index: sbin/nvmecontrol/identify.c =================================================================== --- sbin/nvmecontrol/identify.c +++ sbin/nvmecontrol/identify.c @@ -43,6 +43,9 @@ #include "nvmecontrol.h" #include "nvmecontrol_ext.h" +#define IDENTIFY_USAGE \ +" nvmecontrol identify [-x [-v]] \n" + static void print_namespace(struct nvme_namespace_data *nsdata) { @@ -265,7 +268,7 @@ exit(0); } -void +static void identify(int argc, char *argv[]) { char *target; @@ -293,3 +296,5 @@ else identify_ns(argc, argv); } + +NVME_COMMAND(top, identify, identify, IDENTIFY_USAGE); Index: sbin/nvmecontrol/logpage.c =================================================================== --- sbin/nvmecontrol/logpage.c +++ sbin/nvmecontrol/logpage.c @@ -48,6 +48,9 @@ #include "nvmecontrol.h" +#define LOGPAGE_USAGE \ +" nvmecontrol logpage <-p page_id> [-b] [-v vendor] [-x] \n" \ + #define DEFAULT_SIZE (4096) #define MAX_FW_SLOTS (7) @@ -908,7 +911,7 @@ exit(1); } -void +static void logpage(int argc, char *argv[]) { int fd; @@ -1031,3 +1034,5 @@ close(fd); exit(0); } + +NVME_COMMAND(top, logpage, logpage, LOGPAGE_USAGE); Index: sbin/nvmecontrol/ns.c =================================================================== --- sbin/nvmecontrol/ns.c +++ sbin/nvmecontrol/ns.c @@ -41,6 +41,11 @@ #include "nvmecontrol.h" +SET_DECLARE(ns, struct nvme_function); + +#define NS_USAGE \ +" nvmecontrol ns (create|delete|attach|detach)\n" + /* handles NVME_OPC_NAMESPACE_MANAGEMENT and ATTACHMENT admin cmds */ #define NSCREATE_USAGE \ @@ -60,13 +65,10 @@ void nsattach(int argc, char *argv[]); void nsdetach(int argc, char *argv[]); -static struct nvme_function ns_funcs[] = { - {"create", nscreate, NSCREATE_USAGE}, - {"delete", nsdelete, NSDELETE_USAGE}, - {"attach", nsattach, NSATTACH_USAGE}, - {"detach", nsdetach, NSDETACH_USAGE}, - {NULL, NULL, NULL}, -}; +NVME_COMMAND(ns, create, nscreate, NSCREATE_USAGE); +NVME_COMMAND(ns, delete, nsdelete, NSDELETE_USAGE); +NVME_COMMAND(ns, attach, nsattach, NSATTACH_USAGE); +NVME_COMMAND(ns, detach, nsdetach, NSDETACH_USAGE); static void nscreate_usage(void) @@ -466,9 +468,11 @@ exit(0); } -void +static void ns(int argc, char *argv[]) { - dispatch(argc, argv, ns_funcs); + DISPATCH(argc, argv, ns); } + +NVME_COMMAND(top, ns, ns, NS_USAGE); Index: sbin/nvmecontrol/nvmecontrol.h =================================================================== --- sbin/nvmecontrol/nvmecontrol.h +++ sbin/nvmecontrol/nvmecontrol.h @@ -31,8 +31,16 @@ #ifndef __NVMECONTROL_H__ #define __NVMECONTROL_H__ +#include #include +#define NVME_DATASET(set, sym) DATA_SET(set, sym) + +#define NVME_COMMAND(set, name, function, usage) \ + static struct nvme_function function ## _nvme_cmd = \ + { #name, function, usage }; \ + NVME_DATASET(set, function ## _nvme_cmd); + typedef void (*nvme_fn_t)(int argc, char *argv[]); struct nvme_function { @@ -44,50 +52,6 @@ #define NVME_CTRLR_PREFIX "nvme" #define NVME_NS_PREFIX "ns" -#define DEVLIST_USAGE \ -" nvmecontrol devlist\n" - -#define IDENTIFY_USAGE \ -" nvmecontrol identify [-x [-v]] \n" - -#define PERFTEST_USAGE \ -" nvmecontrol perftest <-n num_threads> <-o read|write>\n" \ -" <-s size_in_bytes> <-t time_in_seconds>\n" \ -" <-i intr|wait> [-f refthread] [-p]\n" \ -" \n" - -#define RESET_USAGE \ -" nvmecontrol reset \n" - -#define LOGPAGE_USAGE \ -" nvmecontrol logpage <-p page_id> [-b] [-v vendor] [-x] \n" \ - -#define FIRMWARE_USAGE \ -" nvmecontrol firmware [-s slot] [-f path_to_firmware] [-a] \n" - -#define FORMAT_USAGE \ -" nvmecontrol format [-f fmt] [-m mset] [-p pi] [-l pil] [-E] [-C] \n" - -#define POWER_USAGE \ -" nvmecontrol power [-l] [-p new-state [-w workload-hint]] \n" - -#define WDC_USAGE \ -" nvmecontrol wdc (cap-diag|drive-log|get-crash-dump|purge|purge-montior)\n" - -#define NS_USAGE \ -" nvmecontrol ns (create|delete|attach|detach)\n" - -void devlist(int argc, char *argv[]); -void identify(int argc, char *argv[]); -void perftest(int argc, char *argv[]); -void reset(int argc, char *argv[]); -void logpage(int argc, char *argv[]); -void firmware(int argc, char *argv[]); -void format(int argc, char *argv[]); -void power(int argc, char *argv[]); -void wdc(int argc, char *argv[]); -void ns(int argc, char *argv[]); - int open_dev(const char *str, int *fd, int show_error, int exit_on_error); void parse_ns_str(const char *ns_str, char *ctrlr_str, uint32_t *nsid); void read_controller_data(int fd, struct nvme_controller_data *cdata); @@ -95,8 +59,12 @@ void print_hex(void *data, uint32_t length); void read_logpage(int fd, uint8_t log_page, uint32_t nsid, void *payload, uint32_t payload_size); -void gen_usage(struct nvme_function *); -void dispatch(int argc, char *argv[], struct nvme_function *f); + +void dispatch_set(int argc, char *argv[], struct nvme_function **tbl, + struct nvme_function **tbl_limit); + +#define DISPATCH(argc, argv, set) \ + dispatch_set(argc, argv, SET_BEGIN(set), SET_LIMIT(set)) /* Utility Routines */ /* Index: sbin/nvmecontrol/nvmecontrol.c =================================================================== --- sbin/nvmecontrol/nvmecontrol.c +++ sbin/nvmecontrol/nvmecontrol.c @@ -47,51 +47,39 @@ #include "nvmecontrol.h" +SET_DECLARE(top, struct nvme_function); -static struct nvme_function funcs[] = { - {"devlist", devlist, DEVLIST_USAGE}, - {"identify", identify, IDENTIFY_USAGE}, - {"perftest", perftest, PERFTEST_USAGE}, - {"reset", reset, RESET_USAGE}, - {"logpage", logpage, LOGPAGE_USAGE}, - {"firmware", firmware, FIRMWARE_USAGE}, - {"format", format, FORMAT_USAGE}, - {"power", power, POWER_USAGE}, - {"wdc", wdc, WDC_USAGE}, - {"ns", ns, NS_USAGE}, - {NULL, NULL, NULL}, -}; - -void -gen_usage(struct nvme_function *f) +static void +gen_usage_set(struct nvme_function **f, struct nvme_function **flimit) { fprintf(stderr, "usage:\n"); - while (f->name != NULL) { - fprintf(stderr, "%s", f->usage); + while (f < flimit) { + fprintf(stderr, "%s", (*f)->usage); f++; } exit(1); } void -dispatch(int argc, char *argv[], struct nvme_function *tbl) +dispatch_set(int argc, char *argv[], struct nvme_function **tbl, + struct nvme_function **tbl_limit) { - struct nvme_function *f = tbl; + struct nvme_function **f = tbl; if (argv[1] == NULL) { - gen_usage(tbl); + gen_usage_set(tbl, tbl_limit); return; } - while (f->name != NULL) { - if (strcmp(argv[1], f->name) == 0) - f->fn(argc-1, &argv[1]); + while (f <= tbl_limit) { + if (strcmp(argv[1], (*f)->name) == 0) + (*f)->fn(argc-1, &argv[1]); f++; } fprintf(stderr, "Unknown command: %s\n", argv[1]); - gen_usage(tbl); + gen_usage_set(tbl, tbl_limit); } static void @@ -243,9 +231,9 @@ { if (argc < 2) - gen_usage(funcs); + gen_usage_set(SET_BEGIN(top), SET_LIMIT(top)); - dispatch(argc, argv, funcs); + DISPATCH(argc, argv, top); return (0); } Index: sbin/nvmecontrol/perftest.c =================================================================== --- sbin/nvmecontrol/perftest.c +++ sbin/nvmecontrol/perftest.c @@ -45,6 +45,12 @@ #include "nvmecontrol.h" +#define PERFTEST_USAGE \ +" nvmecontrol perftest <-n num_threads> <-o read|write>\n" \ +" <-s size_in_bytes> <-t time_in_seconds>\n" \ +" <-i intr|wait> [-f refthread] [-p]\n" \ +" \n" + static void print_perftest(struct nvme_io_test *io_test, bool perthread) { @@ -76,7 +82,7 @@ exit(1); } -void +static void perftest(int argc, char *argv[]) { struct nvme_io_test io_test; @@ -176,3 +182,5 @@ print_perftest(&io_test, perthread); exit(0); } + +NVME_COMMAND(top, perftest, perftest, PERFTEST_USAGE); Index: sbin/nvmecontrol/power.c =================================================================== --- sbin/nvmecontrol/power.c +++ sbin/nvmecontrol/power.c @@ -44,6 +44,9 @@ _Static_assert(sizeof(struct nvme_power_state) == 256 / NBBY, "nvme_power_state size wrong"); +#define POWER_USAGE \ +" nvmecontrol power [-l] [-p new-state [-w workload-hint]] \n" + static void power_usage(void) { @@ -133,7 +136,7 @@ printf("Current Power Mode is %d\n", pt.cpl.cdw0); } -void +static void power(int argc, char *argv[]) { struct nvme_controller_data cdata; @@ -193,3 +196,5 @@ close(fd); exit(0); } + +NVME_COMMAND(top, power, power, POWER_USAGE); Index: sbin/nvmecontrol/reset.c =================================================================== --- sbin/nvmecontrol/reset.c +++ sbin/nvmecontrol/reset.c @@ -41,6 +41,9 @@ #include "nvmecontrol.h" +#define RESET_USAGE \ +" nvmecontrol reset \n" + static void reset_usage(void) { @@ -49,7 +52,7 @@ exit(1); } -void +static void reset(int argc, char *argv[]) { int ch, fd; @@ -71,3 +74,5 @@ exit(0); } + +NVME_COMMAND(top, reset, reset, RESET_USAGE); Index: sbin/nvmecontrol/wdc.c =================================================================== --- sbin/nvmecontrol/wdc.c +++ sbin/nvmecontrol/wdc.c @@ -42,6 +42,11 @@ #include "nvmecontrol.h" +#define WDC_USAGE \ +" nvmecontrol wdc (cap-diag|drive-log|get-crash-dump|purge|purge-montior)\n" + +SET_DECLARE(wdc, struct nvme_function); + #define WDC_NVME_TOC_SIZE 8 #define WDC_NVME_CAP_DIAG_OPCODE 0xe6 @@ -51,10 +56,7 @@ #define WDC_CAP_DIAG_USAGE "\tnvmecontrol wdc cap-diag [-o path-template]\n" -static struct nvme_function wdc_funcs[] = { - {"cap-diag", wdc_cap_diag, WDC_CAP_DIAG_USAGE}, - {NULL, NULL, NULL}, -}; +NVME_COMMAND(wdc, cap-diag, wdc_cap_diag, WDC_CAP_DIAG_USAGE); static void wdc_append_serial_name(int fd, char *buf, size_t len, const char *suffix) @@ -188,9 +190,11 @@ exit(1); } -void +static void wdc(int argc, char *argv[]) { - dispatch(argc, argv, wdc_funcs); + DISPATCH(argc, argv, wdc); } + +NVME_COMMAND(top, wdc, wdc, WDC_USAGE);