]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
Make program have single exit location
authorKeith Busch <keith.busch@intel.com>
Mon, 10 Oct 2016 23:11:19 +0000 (17:11 -0600)
committerKeith Busch <keith.busch@intel.com>
Tue, 6 Dec 2016 20:54:25 +0000 (13:54 -0700)
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 <keith.busch@intel.com>
argconfig.c
argconfig.h
nvme-ioctl.c
nvme-lightnvm.c
nvme.c
plugin.c

index 47c9dc81c99d0c982f486fd900a8ec021880b5f3..d863ffd04cbede4c2e01bec4d94fa7e0f4aa7fee 100644 (file)
@@ -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;
-}
index 9eacc1ff295a75420d206a5cc32cfdd007c20e02..d2ac75ab2df770c29b06d9d5c7f16ab625f1c5dd 100644 (file)
@@ -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
 }
index 9df04ae1247f5b381db20f35b340314a14b18f5a..b74cdc8e18a6acaa9439c9c6222f3e3d0b9292be 100644 (file)
 
 #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]);
index 2c6b5d2e9d1aa98514c4a153f6a070beea8145ea..a8ce4d90d890edeafaee32588d37f905ae164ef2 100644 (file)
@@ -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 170fbec08d4c88a5528b41807bd96c88dd469bae..a570b9cf0ca447c65e35bd0c847d590c76f6a068 100644 (file)
--- 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) {
index ba771f9082f1388c2511256cf9b5d71c1274ec9c..6ca7882adcb48b44b567e300d670d295a18fcad8 100644 (file)
--- 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;
 }