From 936769f0fda40dbfffc0eda76a7a97692687665f Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Mon, 10 Oct 2016 17:11:19 -0600 Subject: [PATCH] Make program have single exit location All errors are returned rather than exiting the program. This requires more return code error checking, but it makes it predictable where the program may end and required if we ever implement an interactive mode. Signed-off-by: Keith Busch --- argconfig.c | 225 +++--------------------------- argconfig.h | 22 --- nvme-ioctl.c | 23 +++- nvme-lightnvm.c | 14 +- nvme.c | 353 ++++++++++++++++++++++++++++++------------------ plugin.c | 4 +- 6 files changed, 274 insertions(+), 367 deletions(-) diff --git a/argconfig.c b/argconfig.c index 47c9dc8..d863ffd 100644 --- a/argconfig.c +++ b/argconfig.c @@ -199,7 +199,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, if (c != 0) { if (c == '?' || c == 'h') { argconfig_print_help(program_desc, options); - goto exit; + goto out; } for (option_index = 0; option_index < options_count; option_index++) { @@ -224,7 +224,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } } else if (s->config_type == CFG_INT) { *((int *)value_addr) = strtol(optarg, &endptr, 0); @@ -232,7 +232,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } } else if (s->config_type == CFG_BOOL) { int tmp = strtol(optarg, &endptr, 0); @@ -240,7 +240,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected 0 or 1 argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } *((int *)value_addr) = tmp; } else if (s->config_type == CFG_BYTE) { @@ -249,7 +249,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected byte argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } *((uint8_t *) value_addr) = tmp; } else if (s->config_type == CFG_SHORT) { @@ -258,7 +258,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected short argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } *((uint16_t *) value_addr) = tmp; } else if (s->config_type == CFG_POSITIVE) { @@ -267,7 +267,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected word argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } *((uint32_t *) value_addr) = tmp; } else if (s->config_type == CFG_INCREMENT) { @@ -278,7 +278,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected long integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } } else if (s->config_type == CFG_LONG_SUFFIX) { *((long *)value_addr) = suffix_binary_parse(optarg); @@ -286,7 +286,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected long suffixed integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } } else if (s->config_type == CFG_DOUBLE) { *((double *)value_addr) = strtod(optarg, &endptr); @@ -294,7 +294,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, fprintf(stderr, "Expected float argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); - goto exit; + goto out; } } else if (s->config_type == CFG_SUBOPTS) { char **opts = ((char **)value_addr); @@ -319,10 +319,10 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, if (r == 2) { fprintf(stderr, "Error Parsing Sub-Options: Too many options!\n"); - goto exit; + goto out; } else if (r) { fprintf(stderr, "Error Parsing Sub-Options\n"); - goto exit; + goto out; } } else if (s->config_type == CFG_FILE_A || s->config_type == CFG_FILE_R || @@ -348,7 +348,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, if (f == NULL) { fprintf(stderr, "Unable to open %s file: %s\n", s->option, optarg); - goto exit; + goto out; } *((FILE **) value_addr) = f; } @@ -357,10 +357,10 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, free(long_opts); return 0; - exit: + out: free(short_opts); free(long_opts); - exit(1); + return -EINVAL; } int argconfig_parse_subopt_string(char *string, char **options, @@ -452,12 +452,10 @@ unsigned argconfig_parse_comma_sep_array(char *string, int *val, return 0; val[ret] = strtol(tmp, &p, 0); - if (*p != 0) - exit(1); + return -1; ret++; - while (1) { tmp = strtok(NULL, ","); @@ -465,16 +463,14 @@ unsigned argconfig_parse_comma_sep_array(char *string, int *val, return ret; if (ret >= max_length) - exit(1); + return -1; val[ret] = strtol(tmp, &p, 0); if (*p != 0) - exit(1); - + return -1; ret++; } - } unsigned argconfig_parse_comma_sep_array_long(char *string, @@ -494,7 +490,7 @@ unsigned argconfig_parse_comma_sep_array_long(char *string, val[ret] = strtoll(tmp, &p, 0); if (*p != 0) - exit(1); + return -1; ret++; while (1) { tmp = strtok(NULL, ","); @@ -503,11 +499,11 @@ unsigned argconfig_parse_comma_sep_array_long(char *string, return ret; if (ret >= max_length) - exit(1); + return -1; val[ret] = strtoll(tmp, &p, 0); if (*p != 0) - exit(1); + return -1; ret++; } } @@ -523,182 +519,3 @@ void argconfig_register_help_func(argconfig_help_func * f) } } } - -void argconfig_parse_subopt(char *const opts[], const char *module, - const struct argconfig_sub_options *options, - void *config_out, size_t config_size) -{ - int enddefault = 0; - int tmp; - const struct argconfig_sub_options *s; - char *const *o; - - errno = 0; - - for (o = opts; o != NULL && *o != NULL; o += 2) { - if (*o == END_DEFAULT) { - enddefault = 1; - continue; - } - - for (s = options; s->option != NULL; s++) - if (strcmp(o[0], s->option) == 0) - break; - - if (s->option == NULL && enddefault) { - fprintf(stderr, "%s: Invalid sub-option '%s'.\n", - module, o[0]); - exit(1); - } else if (s->option == NULL) { - continue; - } - - void *value_addr = (void *)(char *)s->default_value; - - if (s->config_type == CFG_STRING) { - *((char **)value_addr) = o[1]; - } else if (s->config_type == CFG_INT) { - *((int *)value_addr) = (int)strtol(o[1], NULL, 0); - } else if (s->config_type == CFG_SIZE) { - *((size_t *) value_addr) = - (size_t) strtol(o[1], NULL, 0); - } else if (s->config_type == CFG_LONG) { - *((long *)value_addr) = strtol(o[1], NULL, 0); - } else if (s->config_type == CFG_LONG_SUFFIX) { - *((long *)value_addr) = suffix_binary_parse(o[1]); - } else if (s->config_type == CFG_DOUBLE) { - *((double *)value_addr) = strtod(o[1], NULL); - } else if (s->config_type == CFG_BOOL) { - tmp = strtol(o[1], NULL, 0); - - if (tmp < 0 || tmp > 1) - errno = 1; - - *((int *)value_addr) = (int)tmp; - } else if (s->config_type == CFG_POSITIVE) { - tmp = strtol(o[1], NULL, 0); - - if (tmp < 0) - errno = 1; - - *((int *)value_addr) = (int)tmp; - } else if (s->config_type == CFG_FILE_A || - s->config_type == CFG_FILE_R || - s->config_type == CFG_FILE_W || - s->config_type == CFG_FILE_AP || - s->config_type == CFG_FILE_RP || - s->config_type == CFG_FILE_WP) { - const char *fopts = ""; - if (s->config_type == CFG_FILE_A) - fopts = "a"; - else if (s->config_type == CFG_FILE_R) - fopts = "r"; - else if (s->config_type == CFG_FILE_W) - fopts = "w"; - else if (s->config_type == CFG_FILE_AP) - fopts = "a+"; - else if (s->config_type == CFG_FILE_RP) - fopts = "r+"; - else if (s->config_type == CFG_FILE_WP) - fopts = "w+"; - - FILE *f = fopen(o[1], fopts); - - if (f == NULL) { - fprintf(stderr, "Unable to open %s file: %s\n", - s->option, o[1]); - exit(1); - } - - *((FILE **) value_addr) = f; - } - - if (errno) { - fprintf(stderr, - "%s: Invalid value '%s' for option '%s'.\n", - module, o[1], o[0]); - exit(1); - } - } -} - -int argconfig_set_subopt(const char *opt, - const struct argconfig_sub_options *options, - void *config_out, va_list argp) -{ - const struct argconfig_sub_options *s; - for (s = options; s->option != NULL; s++) - if (strcmp(opt, s->option) == 0) - break; - - if (s->option == NULL) - return 1; - - void *value_addr = (void *)(char *)s->default_value; - - if (s->config_type == CFG_STRING) { - *((char **)value_addr) = va_arg(argp, char *); - } else if (s->config_type == CFG_INT || - s->config_type == CFG_BOOL || - s->config_type == CFG_POSITIVE) { - *((int *)value_addr) = va_arg(argp, int); - } else if (s->config_type == CFG_SIZE) { - *((size_t *) value_addr) = va_arg(argp, size_t); - } else if (s->config_type == CFG_LONG) { - *((long *)value_addr) = va_arg(argp, long); - } else if (s->config_type == CFG_LONG_SUFFIX) { - *((long *)value_addr) = va_arg(argp, long); - } else if (s->config_type == CFG_DOUBLE) { - *((double *)value_addr) = va_arg(argp, double); - } else if (s->config_type == CFG_FILE_A || - s->config_type == CFG_FILE_R || - s->config_type == CFG_FILE_W || - s->config_type == CFG_FILE_AP || - s->config_type == CFG_FILE_RP || - s->config_type == CFG_FILE_WP) { - - *((FILE **) value_addr) = va_arg(argp, FILE *); - } - - return 0; -} - -int argconfig_get_subopt(const char *opt, - const struct argconfig_sub_options *options, - void *config_out, va_list argp) -{ - const struct argconfig_sub_options *s; - for (s = options; s->option != NULL; s++) - if (strcmp(opt, s->option) == 0) - break; - - if (s->option == NULL) - return 1; - - void *value_addr = (void *)(char *)s->default_value; - - if (s->config_type == CFG_STRING) { - *va_arg(argp, char **) = *((char **)value_addr); - } else if (s->config_type == CFG_INT || - s->config_type == CFG_BOOL || - s->config_type == CFG_POSITIVE) { - *va_arg(argp, int *) = *((int *)value_addr); - } else if (s->config_type == CFG_SIZE) { - *va_arg(argp, size_t *) = *((size_t *) value_addr); - } else if (s->config_type == CFG_LONG) { - *va_arg(argp, long *) = *((long *)value_addr); - } else if (s->config_type == CFG_LONG_SUFFIX) { - *va_arg(argp, long *) = *((long *)value_addr); - } else if (s->config_type == CFG_DOUBLE) { - *va_arg(argp, double *) = *((double *)value_addr); - } else if (s->config_type == CFG_FILE_A || - s->config_type == CFG_FILE_R || - s->config_type == CFG_FILE_W || - s->config_type == CFG_FILE_AP || - s->config_type == CFG_FILE_RP || - s->config_type == CFG_FILE_WP) { - *va_arg(argp, FILE **) = *((FILE **) value_addr); - } - - return 0; -} diff --git a/argconfig.h b/argconfig.h index 9eacc1f..d2ac75a 100644 --- a/argconfig.h +++ b/argconfig.h @@ -72,15 +72,6 @@ struct argconfig_commandline_options { #define CFG_MAX_SUBOPTS 500 #define MAX_HELP_FUNC 20 -struct argconfig_sub_options { - const char *option; - const char short_option; - const char *meta; - enum argconfig_types config_type; - const void *default_value; - const char *help; -}; - #ifdef __cplusplus extern "C" { #endif @@ -99,19 +90,6 @@ unsigned argconfig_parse_comma_sep_array_long(char *string, unsigned max_length); void argconfig_register_help_func(argconfig_help_func * f); -void argconfig_print_subopt_help(const struct argconfig_sub_options - *options, int indent); - -void argconfig_parse_subopt(char *const opts[], const char *module, - const struct argconfig_sub_options *options, - void *config_out, size_t config_size); - -int argconfig_set_subopt(const char *opt, - const struct argconfig_sub_options *options, - void *config_out, va_list arg); -int argconfig_get_subopt(const char *opt, - const struct argconfig_sub_options *options, - void *config_out, va_list arg); void print_word_wrapped(const char *s, int indent, int start); #ifdef __cplusplus } diff --git a/nvme-ioctl.c b/nvme-ioctl.c index 9df04ae..b74cdc8 100644 --- a/nvme-ioctl.c +++ b/nvme-ioctl.c @@ -21,31 +21,40 @@ #include "nvme-ioctl.h" -static void nvme_verify_chr(int fd) +static int nvme_verify_chr(int fd) { static struct stat nvme_stat; int err = fstat(fd, &nvme_stat); if (err < 0) { perror("fstat"); - exit(err); + return errno; } if (!S_ISCHR(nvme_stat.st_mode)) { fprintf(stderr, "Error: requesting reset on non-controller handle\n"); - exit(ENOTBLK); + return ENOTBLK; } + return 0; } int nvme_subsystem_reset(int fd) { - nvme_verify_chr(fd); + int ret; + + ret = nvme_verify_chr(fd); + if (ret) + return ret; return ioctl(fd, NVME_IOCTL_SUBSYS_RESET); } int nvme_reset_controller(int fd) { - nvme_verify_chr(fd); + int ret; + + ret = nvme_verify_chr(fd); + if (ret) + return ret; return ioctl(fd, NVME_IOCTL_RESET); } @@ -60,7 +69,7 @@ int nvme_get_nsid(int fd) if (!S_ISBLK(nvme_stat.st_mode)) { fprintf(stderr, "Error: requesting namespace-id from non-block device\n"); - exit(ENOTBLK); + return ENOTBLK; } return ioctl(fd, NVME_IOCTL_ID); } @@ -232,7 +241,7 @@ struct nvme_dsm_range *nvme_setup_dsm_range(__u32 *ctx_attrs, __u32 *llbas, struct nvme_dsm_range *dsm = malloc(nr_ranges * sizeof(*dsm)); if (!dsm) - exit(ENOMEM); + return NULL; for (i = 0; i < nr_ranges; i++) { dsm[i].cattr = cpu_to_le32(ctx_attrs[i]); dsm[i].nlb = cpu_to_le32(llbas[i]); diff --git a/nvme-lightnvm.c b/nvme-lightnvm.c index 2c6b5d2..a8ce4d9 100644 --- a/nvme-lightnvm.c +++ b/nvme-lightnvm.c @@ -43,7 +43,7 @@ static int lnvm_open(void) if (fd < 0) { printf("Failed to open LightNVM mgmt interface\n"); perror(dev); - exit(errno); + return fd; } return fd; @@ -60,6 +60,8 @@ int lnvm_do_init(char *dev, char *mmtype) int fd, ret; fd = lnvm_open(); + if (fd < 0) + return fd; memset(&init, 0, sizeof(struct nvm_ioctl_dev_init)); strncpy(init.dev, dev, DISK_NAME_LEN); @@ -91,6 +93,8 @@ int lnvm_do_list_devices(void) int fd, ret, i; fd = lnvm_open(); + if (fd < 0) + return fd; ret = ioctl(fd, NVM_GET_DEVICES, &devs); if (ret) @@ -118,6 +122,8 @@ int lnvm_do_info(void) int fd, ret, i; fd = lnvm_open(); + if (fd < 0) + return fd; memset(&c, 0, sizeof(struct nvm_ioctl_info)); ret = ioctl(fd, NVM_INFO, &c); @@ -147,6 +153,8 @@ int lnvm_do_create_tgt(char *devname, char *tgtname, char *tgttype, int fd, ret; fd = lnvm_open(); + if (fd < 0) + return fd; strncpy(c.dev, devname, DISK_NAME_LEN); strncpy(c.tgtname, tgtname, DISK_NAME_LEN); @@ -170,6 +178,8 @@ int lnvm_do_remove_tgt(char *tgtname) int fd, ret; fd = lnvm_open(); + if (fd < 0) + return fd; strncpy(c.tgtname, tgtname, DISK_NAME_LEN); c.flags = 0; @@ -190,6 +200,8 @@ int lnvm_do_factory_init(char *devname, int erase_only_marked, int fd, ret; fd = lnvm_open(); + if (fd < 0) + return fd; memset(&fact, 0, sizeof(struct nvm_ioctl_dev_factory)); diff --git a/nvme.c b/nvme.c index 170fbec..a570b9c 100644 --- a/nvme.c +++ b/nvme.c @@ -59,7 +59,6 @@ #define min(x, y) (x) > (y) ? (y) : (x) #define max(x, y) (x) > (y) ? (x) : (y) -static int fd; static struct stat nvme_stat; const char *devicename; @@ -94,48 +93,62 @@ static unsigned long long elapsed_utime(struct timeval start_time, return ret; } -static void open_dev(const char *dev) +static int open_dev(const char *dev) { - int err; + int err, fd; + devicename = basename(dev); - fd = open(dev, O_RDONLY); - if (fd < 0) + err = open(dev, O_RDONLY); + if (err < 0) goto perror; + fd = err; err = fstat(fd, &nvme_stat); if (err < 0) goto perror; if (!S_ISCHR(nvme_stat.st_mode) && !S_ISBLK(nvme_stat.st_mode)) { fprintf(stderr, "%s is not a block or character device\n", dev); - exit(ENODEV); + return -ENODEV; } - return; + return fd; perror: perror(dev); - exit(errno); + return err; } -static void check_arg_dev(int argc, char **argv) +static int check_arg_dev(int argc, char **argv) { if (optind >= argc) { errno = EINVAL; perror(argv[0]); - exit(errno); + return -EINVAL; } + return 0; } -static void get_dev(int argc, char **argv) +static int get_dev(int argc, char **argv) { - check_arg_dev(argc, argv); - open_dev((const char *)argv[optind]); + int ret; + + ret = check_arg_dev(argc, argv); + if (ret) { + fprintf(stderr, "expected nvme device (ex: /dev/nvme0), none provided\n"); + return ret; + } + + return open_dev((const char *)argv[optind]); } int parse_and_open(int argc, char **argv, const char *desc, const struct argconfig_commandline_options *clo, void *cfg, size_t size) { - argconfig_parse(argc, argv, desc, clo, cfg, size); - get_dev(argc, argv); - return fd; + int ret; + + ret = argconfig_parse(argc, argv, desc, clo, cfg, size); + if (ret) + return ret; + + return get_dev(argc, argv); } static const char *output_format = "Output format: normal|json|binary"; @@ -167,7 +180,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug "(default) or binary."; const char *namespace = "(optional) desired namespace"; const char *raw = "output in binary format"; - int err, fmt; + int err, fmt, fd; struct config { __u32 namespace_id; @@ -187,7 +200,9 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) @@ -207,13 +222,15 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + else + perror("smart log"); return err; } static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_additional_smart_log smart_log; - int err, fmt; + int err, fmt, fd; char *desc = "Get Intel vendor specific additional smart log (optionally, "\ "for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; @@ -236,7 +253,10 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; + fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; @@ -255,6 +275,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + else + perror("intel smart log"); return err; } @@ -267,7 +289,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug const char *log_entries = "number of entries to retrieve"; const char *raw_binary = "dump in binary format"; struct nvme_id_ctrl ctrl; - int err, fmt; + int err, fmt, fd; struct config { __u32 namespace_id; @@ -290,7 +312,9 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) @@ -304,13 +328,15 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug } err = nvme_identify_ctrl(fd, &ctrl); - cfg.log_entries = min(cfg.log_entries, ctrl.elpe + 1); - if (err) { + if (err < 0) + perror("identify controller"); + else if (err) { fprintf(stderr, "could not identify controller\n"); - return ENODEV; + err = ENODEV; } else { struct nvme_error_log_page *err_log; + cfg.log_entries = min(cfg.log_entries, ctrl.elpe + 1); err_log = calloc(cfg.log_entries, sizeof(struct nvme_error_log_page)); if (!err_log) { fprintf(stderr, "could not alloc buffer for error log\n"); @@ -329,6 +355,8 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + else + perror("error log"); free(err_log); } return err; @@ -339,7 +367,7 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin const char *desc = "Retrieve the firmware log for the "\ "specified device in either decoded format (default) or binary."; const char *raw_binary = "use binary output"; - int err, fmt; + int err, fmt, fd; struct nvme_firmware_log_page fw_log; struct config { @@ -357,7 +385,9 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) @@ -391,7 +421,7 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl const char *log_id = "identifier of log to retrieve"; const char *log_len = "how many bytes to retrieve"; const char *raw_binary = "output in raw format"; - int err; + int err, fd; struct config { __u32 namespace_id; @@ -414,7 +444,9 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; if (!cfg.log_len) { fprintf(stderr, "non-zero log-len is required param\n"); @@ -440,6 +472,8 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + else + perror("log page"); free(log); return err; } @@ -451,7 +485,7 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * "given device is part of, or optionally controllers attached to a specific namespace."; const char *controller = "controller to display"; const char *namespace_id = "optional namespace attached to controller"; - int err, i; + int err, i, fd; struct nvme_controller_list *cntlist; struct config { @@ -469,10 +503,14 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; - if (posix_memalign((void *)&cntlist, getpagesize(), 0x1000)) + if (posix_memalign((void *)&cntlist, getpagesize(), 0x1000)) { + fprintf(stderr, "can not allocate controller list payload\n"); return ENOMEM; + } err = nvme_identify_ctrl_list(fd, cfg.namespace_id, cfg.cntid, cntlist); if (!err) { @@ -484,6 +522,8 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) cntid:%d\n", nvme_status_to_string(err), err, cfg.cntid); + else + perror("id controller list"); return err; } @@ -493,7 +533,7 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl "namespace list in a NVMe subsystem, optionally starting with a given namespace"; const char *namespace_id = "namespace number returned list should to start after"; const char *all = "show all namespaces in the subsystem, whether attached or inactive"; - int err, i; + int err, i, fd; __u32 ns_list[1024]; struct config { @@ -511,7 +551,9 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; err = nvme_identify_ns_list(fd, cfg.namespace_id, !!cfg.all, ns_list); if (!err) { @@ -522,6 +564,8 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", nvme_status_to_string(err), err, cfg.namespace_id); + else + perror("id namespace list"); return err; } @@ -534,7 +578,7 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * "becomes inactive when that namespace is detached or, if "\ "the namespace is not already inactive, once deleted."; const char *namespace_id = "namespace to delete"; - int err; + int err, fd; struct config { __u32 namespace_id; @@ -549,7 +593,9 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; if (!cfg.namespace_id) { fprintf(stderr, "%s: namespace-id parameter required\n", @@ -565,13 +611,13 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else - fprintf(stderr, "system error:(%x)\n", err); + perror("delete namespace"); return err; } static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd) { - int err, num, i, list[2048]; + int err, num, i, fd, list[2048]; __u16 ctrlist[2048]; const char *namespace_id = "namespace to attach"; @@ -592,7 +638,9 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; if (!cfg.namespace_id) { fprintf(stderr, "%s: namespace-id parameter required\n", @@ -616,7 +664,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else - fprintf(stderr, "system error:(%x)\n", err); + perror(attach ? "attach namespace" : "detach namespace"); return err; } @@ -646,7 +694,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * "parameters. The next available namespace ID is used for the "\ "create operation. Note that create-ns does not attach the "\ "namespace to a controller, the attach-ns command is needed."; - int err = 0; + int err = 0, fd; __u32 nsid; struct config { @@ -675,7 +723,9 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; err = nvme_ns_create(fd, cfg.nsze, cfg.ncap, cfg.flbas, cfg.dps, cfg.nmic, &nsid); if (!err) @@ -683,6 +733,8 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + else + perror("create namespace"); return err; } @@ -693,7 +745,7 @@ static char *nvme_char_from_block(char *block) if (strncmp("nvme", block, 4)) { fprintf(stderr, "Device %s is not a nvme device.", block); - exit(-1); + return NULL; } sscanf(block, "nvme%d", &len); @@ -718,13 +770,13 @@ static void *get_registers(void) } if (pci_fd < 0) { fprintf(stderr, "%s did not find a pci resource\n", base); - exit(ENODEV); + return NULL; } membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, pci_fd, 0); if (membase == MAP_FAILED) { fprintf(stderr, "%s failed to map\n", base); - exit(ENODEV); + return NULL; } return membase; } @@ -836,6 +888,7 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi required_argument, "Output Format: normal|json"}, {NULL} }; + argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg)); fmt = validate_output_format(cfg.output_format); @@ -847,8 +900,10 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi return n; list_items = calloc(n, sizeof(*list_items)); - if (!list_items) + if (!list_items) { + fprintf(stderr, "can not allocate controller list payload\n"); return ENOMEM; + } for (i = 0; i < n; i++) { snprintf(path, sizeof(path), "%s%s", dev, devices[i]->d_name); @@ -871,7 +926,7 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi return 0; } -static int get_nsid(void) +static int get_nsid(int fd) { int nsid = nvme_get_nsid(fd); @@ -879,7 +934,7 @@ static int get_nsid(void) fprintf(stderr, "%s: failed to return namespace id\n", devicename); - exit(errno); + return errno; } return nsid; } @@ -894,7 +949,7 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, const char *vendor_specific = "dump binary vendor infos"; const char *raw_binary = "show infos in binary format"; const char *human_readable = "show infos in readable format"; - int err, fmt; + int err, fmt, fd; unsigned int flags = 0; struct nvme_id_ctrl ctrl; @@ -917,7 +972,9 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) @@ -944,6 +1001,8 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + else + perror("identify controller"); return err; } @@ -965,7 +1024,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug const char *human_readable = "show infos in readable format"; const char *namespace_id = "identifier of desired namespace"; struct nvme_id_ns ns; - int err, fmt; + int err, fmt, fd; unsigned int flags = 0; struct config { @@ -992,7 +1051,9 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) @@ -1005,7 +1066,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug if (cfg.human_readable) flags |= HUMAN; if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); err = nvme_identify_ns(fd, cfg.namespace_id, cfg.force, &ns); if (!err) { @@ -1021,18 +1082,20 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", nvme_status_to_string(err), err, cfg.namespace_id); + else + perror("identify namespace"); return err; } static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int nsid; + int nsid, fd; - open_dev(argv[1]); + fd = open_dev(argv[1]); nsid = nvme_get_nsid(fd); if (nsid <= 0) { perror(devicename); - exit(errno); + return errno; } printf("%s: namespace-id:%d\n", devicename, nsid); return 0; @@ -1056,7 +1119,7 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin const char *data_len = "buffer len (if) data is returned"; const char *cdw11 = "dword 11 for interrupt vector config"; const char *human_readable = "show infos in readable format"; - int err; + int err, fd; __u32 result; void *buf = NULL; @@ -1089,7 +1152,9 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; if (cfg.sel > 7) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); @@ -1116,8 +1181,10 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin } if (cfg.data_len) { - if (posix_memalign(&buf, getpagesize(), cfg.data_len)) - exit(ENOMEM); + if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { + fprintf(stderr, "can not allocate feature payload\n"); + return ENOMEM; + } memset(buf, 0, cfg.data_len); } @@ -1134,9 +1201,11 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin d(buf, cfg.data_len, 16, 1); } else if (buf) d_raw(buf, cfg.data_len); - } else if (err > 0) + } else if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + } else + perror("get-feature"); if (buf) free(buf); @@ -1156,7 +1225,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin const char *fw = "firmware file (required)"; const char *xfer = "transfer chunksize limit"; const char *offset = "starting dword offset, default 0"; - int err, fw_fd = -1; + int err, fd, fw_fd = -1; unsigned int fw_size; struct stat sb; void *fw_buf; @@ -1180,7 +1249,9 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; fw_fd = open(cfg.fw, O_RDONLY); cfg.offset <<= 2; @@ -1188,10 +1259,11 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin fprintf(stderr, "no firmware file provided\n"); return EINVAL; } + err = fstat(fw_fd, &sb); if (err < 0) { perror("fstat"); - exit(errno); + return errno; } fw_size = sb.st_size; @@ -1214,7 +1286,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin err = nvme_fw_download(fd, cfg.offset, cfg.xfer, fw_buf); if (err < 0) { perror("fw-download"); - exit(errno); + break; } else if (err != 0) { fprintf(stderr, "NVME Admin command error:%s(%x)\n", nvme_status_to_string(err), err); @@ -1248,7 +1320,7 @@ static int fw_activate(int argc, char **argv, struct command *cmd, struct plugin "Ensure nvmeX is the device you just activated before reset."; const char *slot = "firmware slot to activate"; const char *action = "[0-2]: replacement action"; - int err; + int err, fd; struct config { __u8 slot; @@ -1266,7 +1338,9 @@ static int fw_activate(int argc, char **argv, struct command *cmd, struct plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; if (cfg.slot > 7) { fprintf(stderr, "invalid slot:%d\n", cfg.slot); @@ -1299,18 +1373,20 @@ static int fw_activate(int argc, char **argv, struct command *cmd, struct plugin return err; } -static void clear_args(int argc, char **argv) +static int clear_args(int argc, char **argv) { int opt, long_index; + while ((opt = getopt_long(argc, (char **)argv, "", NULL, &long_index)) != -1); - get_dev(argc, argv); + return get_dev(argc, argv); } static int subsystem_reset(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err; - clear_args(argc, argv); + int err, fd; + + fd = clear_args(argc, argv); err = nvme_subsystem_reset(fd); if (err < 0) { perror("Subsystem-reset"); @@ -1321,8 +1397,9 @@ static int subsystem_reset(int argc, char **argv, struct command *cmd, struct pl static int reset(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err; - clear_args(argc, argv); + int err, fd; + + fd = clear_args(argc, argv); err = nvme_reset_controller(fd); if (err < 0) { perror("Reset"); @@ -1351,9 +1428,10 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu const char *desc = "Reads and shows the defined NVMe controller registers "\ "in binary or human-readable format"; const char *human_readable = "show info in readable format"; + void *bar; uint64_t cap, asq, acq; uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc; - void *bar; + int fd; struct config { int human_readable; @@ -1368,9 +1446,14 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; bar = get_registers(); + if (!bar) + return ENODEV; + cap = mmio_read64(bar + NVME_REG_CAP); vs = mmio_read32(bar + NVME_REG_VS); intms = mmio_read32(bar + NVME_REG_INTMS); @@ -1454,7 +1537,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu const char *ms = "[0-1]: extended format off/on"; const char *reset = "Automatically reset the controller after successful format"; const char *timeout = "timeout value, in milliseconds"; - int err; + int err, fd; struct config { __u32 namespace_id; @@ -1488,7 +1571,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); /* ses & pi checks set to 7 for forward-compatibility */ if (cfg.ses > 7) { @@ -1512,7 +1595,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu return EINVAL; } if (S_ISBLK(nvme_stat.st_mode)) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); err = nvme_format(fd, cfg.namespace_id, cfg.lbaf, cfg.ses, cfg.pi, cfg.pil, cfg.ms, cfg.timeout); @@ -1550,7 +1633,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin int err; __u32 result; void *buf = NULL; - int ffd = STDIN_FILENO; + int fd, ffd = STDIN_FILENO; struct config { char *file; @@ -1580,7 +1663,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); @@ -1589,8 +1672,10 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin if (cfg.feature_id == NVME_FEAT_LBA_RANGE) cfg.data_len = 4096; if (cfg.data_len) { - if (posix_memalign(&buf, getpagesize(), cfg.data_len)) - exit(ENOMEM); + if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { + fprintf(stderr, "can not allocate feature payload\n"); + return ENOMEM; + } memset(buf, 0, cfg.data_len); } @@ -1623,7 +1708,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin else d(buf, cfg.data_len, 16, 1); } - } else + } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); if (buf) @@ -1645,7 +1730,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p const char *tl = "transfer length (cf. SPC-4)"; const char *namespace_id = "desired namespace"; const char *nssf = "NVMe Security Specific Field"; - int err, sec_fd = -1; + int err, fd, sec_fd = -1; void *sec_buf; unsigned int sec_size; __u32 result; @@ -1676,7 +1761,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); sec_fd = open(cfg.file, O_RDONLY); if (sec_fd < 0) { @@ -1699,7 +1784,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p err = nvme_sec_send(fd, cfg.namespace_id, cfg.nssf, cfg.spsp, cfg.secp, cfg.tl, sec_size, sec_buf, &result); if (err < 0) - return errno; + perror("security-send"); else if (err != 0) fprintf(stderr, "NVME Security Send Command Error:%d\n", err); else @@ -1709,7 +1794,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err; + int err, fd; const char *desc = "The Write Uncorrectable command is used to set a "\ "range of logical blocks to invalid."; const char *namespace_id = "desired namespace"; @@ -1735,15 +1820,15 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); err = nvme_write_uncorrectable(fd, cfg.namespace_id, cfg.start_block, cfg.block_count); if (err < 0) - return errno; + perror("write uncorrectable"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); @@ -1754,7 +1839,7 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err; + int err, fd; __u16 control = 0; const char *desc = "The Write Zeroes command is used to set a "\ "range of logical blocks to zero."; @@ -1802,7 +1887,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (cfg.prinfo > 0xf) return EINVAL; @@ -1813,12 +1898,12 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi if (cfg.force_unit_access) control |= NVME_RW_FUA; if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); err = nvme_write_zeros(fd, cfg.namespace_id, cfg.start_block, cfg.block_count, control, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask); if (err < 0) - return errno; + perror("write-zeroes"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); @@ -1842,7 +1927,7 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin const char *idr = "Attribute Integral Dataset for Read"; const char *cdw11 = "All the command DWORD 11 attributes. Use instead of specifying individual attributes"; - int err; + int err, fd; uint16_t nr, nc, nb, ns; int ctx_attrs[256] = {0,}; int nlbs[256] = {0,}; @@ -1883,7 +1968,7 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, ctx_attrs, array_len(ctx_attrs)); nb = argconfig_parse_comma_sep_array(cfg.blocks, nlbs, array_len(nlbs)); @@ -1895,17 +1980,20 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin } if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); if (!cfg.cdw11) cfg.cdw11 = (cfg.ad << 2) | (cfg.idw << 1) | (cfg.idr << 0); dsm = nvme_setup_dsm_range((__u32 *)ctx_attrs, (__u32 *)nlbs, (__u64 *)slbas, nr); + if (!dsm) { + fprintf(stderr, "failed to allocate data set payload\n"); + return ENOMEM; + } err = nvme_dsm(fd, cfg.namespace_id, cfg.cdw11, dsm, nr); - if (err < 0) { - fprintf(stderr, "error:%x\n", err); - return errno; - } else if (err != 0) + if (err < 0) + perror("data-set management"); + else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else @@ -1921,7 +2009,7 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug "flushed by the controller, from any namespace, depending on controller and "\ "associated namespace status."; const char *namespace_id = "identifier of desired namespace"; - int err; + int err, fd; struct config { __u32 namespace_id; @@ -1936,11 +2024,11 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); err = nvme_flush(fd, cfg.namespace_id); if (err < 0) - return errno; + perror("flush"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); @@ -1963,7 +2051,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi const char *rtype = "hex reservation type"; const char *racqa = "reservation acquiry action"; const char *iekey = "ignore existing res. key"; - int err; + int err, fd; struct config { __u32 namespace_id; @@ -1992,10 +2080,10 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); if (cfg.racqa > 7) { fprintf(stderr, "invalid racqa:%d\n", cfg.racqa); return EINVAL; @@ -2004,7 +2092,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi err = nvme_resv_acquire(fd, cfg.namespace_id, cfg.rtype, cfg.racqa, !!cfg.iekey, cfg.crkey, cfg.prkey); if (err < 0) - return errno; + perror("reservation acquire"); else if (err != 0) fprintf(stderr, "NVME IO command error:%04x\n", err); else @@ -2023,7 +2111,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug const char *nrkey = "new reservation key"; const char *rrega = "reservation registration action"; const char *cptpl = "change persistence through power loss setting"; - int err; + int err, fd; struct config { __u32 namespace_id; @@ -2052,10 +2140,10 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); if (cfg.cptpl > 3) { fprintf(stderr, "invalid cptpl:%d\n", cfg.cptpl); return EINVAL; @@ -2064,7 +2152,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug err = nvme_resv_register(fd, cfg.namespace_id, cfg.rrega, cfg.cptpl, !!cfg.iekey, cfg.crkey, cfg.nrkey); if (err < 0) - return errno; + perror("reservation register"); else if (err != 0) fprintf(stderr, "NVME IO command error:%04x\n", err); else @@ -2087,7 +2175,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi const char *iekey = "ignore existing res. key"; const char *rtype = "hex reservation type"; const char *rrela = "reservation release action"; - int err; + int err, fd; struct config { __u32 namespace_id; @@ -2114,10 +2202,10 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); if (cfg.iekey > 1) { fprintf(stderr, "invalid iekey:%d\n", cfg.iekey); return EINVAL; @@ -2130,7 +2218,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi err = nvme_resv_release(fd, cfg.namespace_id, cfg.rtype, cfg.rrela, !!cfg.iekey, cfg.crkey); if (err < 0) - return errno; + perror("reservation release"); else if (err != 0) fprintf(stderr, "NVME IO command error:%04x\n", err); else @@ -2149,7 +2237,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin const char *numd = "number of dwords to transfer"; const char *raw_binary = "dump output in binary format"; - int err, fmt; + int err, fmt, fd; struct nvme_reservation_status *status; struct config { @@ -2173,7 +2261,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); fmt = validate_output_format(cfg.output_format); if (fmt < 0) @@ -2182,7 +2270,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin fmt = BINARY; if (!cfg.namespace_id) - cfg.namespace_id = get_nsid(); + cfg.namespace_id = get_nsid(fd); if (!cfg.numd || cfg.numd > (0x1000 >> 2)) cfg.numd = 0x1000 >> 2; @@ -2193,7 +2281,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin err = nvme_resv_report(fd, cfg.namespace_id, cfg.numd, status); if (err < 0) - return errno; + perror("reservation report"); else if (err != 0) fprintf(stderr, "NVME IO command error:%04x\n", err); else { @@ -2215,7 +2303,7 @@ static int submit_io(int opcode, char *command, const char *desc, struct timeval start_time, end_time; void *buffer, *mbuffer = NULL; int err = 0; - int dfd, mfd; + int dfd, mfd, fd; int flags = opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT; int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; __u16 control = 0; @@ -2288,7 +2376,7 @@ static int submit_io(int opcode, char *command, const char *desc, {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); dfd = mfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO; if (cfg.prinfo > 0xf) @@ -2330,14 +2418,17 @@ static int submit_io(int opcode, char *command, const char *desc, buffer_size = cfg.data_size; } - if (posix_memalign(&buffer, getpagesize(), buffer_size)) + if (posix_memalign(&buffer, getpagesize(), buffer_size)) { + fprintf(stderr, "can not allocate io payload\n"); return ENOMEM; + } memset(buffer, 0, cfg.data_size); if (cfg.metadata_size) { mbuffer = malloc(cfg.metadata_size); if (!mbuffer) { free(buffer); + fprintf(stderr, "can not allocate io metadata payload\n"); return ENOMEM; } } @@ -2441,7 +2532,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p const char *raw_binary = "dump output in binary format"; const char *namespace_id = "desired namespace"; const char *nssf = "NVMe Security Specific Field"; - int err; + int err, fd; void *sec_buf = NULL; __u32 result; @@ -2473,7 +2564,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (cfg.size) { if (posix_memalign(&sec_buf, getpagesize(), cfg.size)) { @@ -2486,7 +2577,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p err = nvme_sec_recv(fd, cfg.namespace_id, cfg.nssf, cfg.spsp, cfg.secp, cfg.al, cfg.size, sec_buf, &result); if (err < 0) - return errno; + perror("security receive"); else if (err != 0) fprintf(stderr, "NVME Security Receive Command Error:%d\n", err); @@ -2504,7 +2595,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, struct command *cmd) { void *data = NULL, *metadata = NULL; - int err = 0, wfd = STDIN_FILENO; + int err = 0, wfd = STDIN_FILENO, fd; __u32 result; struct config { @@ -2601,7 +2692,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, stru {NULL} }; - parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (strlen(cfg.input_file)){ wfd = open(cfg.input_file, O_RDONLY, @@ -2615,8 +2706,10 @@ static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, stru if (cfg.metadata_len) metadata = malloc(cfg.metadata_len); if (cfg.data_len) { - if (posix_memalign(&data, getpagesize(), cfg.data_len)) - exit(ENOMEM); + if (posix_memalign(&data, getpagesize(), cfg.data_len)) { + fprintf(stderr, "can not allocate data payload\n"); + return ENOMEM; + } memset(data, cfg.prefill, cfg.data_len); if (!cfg.read && !cfg.write) { diff --git a/plugin.c b/plugin.c index ba771f9..6ca7882 100644 --- a/plugin.c +++ b/plugin.c @@ -31,10 +31,8 @@ static int help(int argc, char **argv, struct plugin *plugin) sprintf(man, "%s-%s-%s", prog->name, plugin->name, argv[1]); else sprintf(man, "%s-%s", prog->name, argv[1]); - if (execlp("man", "man", man, (char *)NULL)) { + if (execlp("man", "man", man, (char *)NULL)) perror(argv[1]); - exit(errno); - } return 0; } -- 2.49.0