]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: open namespace exclusive by default
authorOlaf Schmerse <olaf.schmerse@ionos.com>
Tue, 19 Oct 2021 10:05:59 +0000 (12:05 +0200)
committerDaniel Wagner <dwagner@suse.de>
Thu, 23 Dec 2021 10:39:24 +0000 (11:39 +0100)
All data modifying functions open the namespace exclusive. With the --force
option this can be bypassed.

Signed-off-by: Olaf Schmerse <olaf.schmerse@ionos.com>
nvme-print.c
nvme-print.h
nvme.c

index 894d25711ede52c55f72df7630eb46248d317b92..433723e130b90b9230e63230de1cf205bbff7f82 100644 (file)
@@ -6909,3 +6909,10 @@ void nvme_show_list_items(nvme_root_t r, enum nvme_print_flags flags)
        else
                nvme_show_simple_list(r);
 }
+
+void nvme_show_busy_namespace(char *namespace) {
+       fprintf(stderr, "Failed to open %s.\n"\
+               "Namespace is currently busy.\n"\
+               "Use the force [--force] option to ignore that.\n",
+               namespace);
+}
index 92cb7f20897ef93536ac7a0e161ddd6991583398..6bf37d9224745a4b74efa005669cac3be5094cf4 100644 (file)
@@ -120,6 +120,7 @@ void nvme_show_zns_report_zones(void *report, __u32 descs,
 void json_nvme_finish_zone_list(__u64 nr_zones, 
        struct json_object *zone_list);
 void nvme_show_list_item(nvme_ns_t n);
+void nvme_show_busy_namespace(char *namespace);
 
 const char *nvme_cmd_to_string(int admin, __u8 opcode);
 const char *nvme_select_to_string(int sel);
diff --git a/nvme.c b/nvme.c
index dd4ba43351aafac385bbe0d0711504b3e882bd12..c6233025f5a77eab9fc23280e9a10ba081937ea4 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -242,29 +242,32 @@ static int get_dev(int argc, char **argv, int flags)
 int parse_and_open(int argc, char **argv, const char *desc,
        const struct argconfig_commandline_options *opts)
 {
+       const struct argconfig_commandline_options *s;
+       int flags = O_RDONLY;
        int ret;
 
        ret = argconfig_parse(argc, argv, desc, opts);
        if (ret)
                return ret;
 
-       ret = get_dev(argc, argv, O_RDONLY);
-       if (ret < 0)
-               argconfig_print_help(desc, opts);
+       for (s = opts; (s->option != NULL) && (s != NULL); s++) {
+               if (!strcmp(s->option, "force")) {
+                       if (! *(int *) s->default_value)
+                               flags |= O_EXCL;
+                       break;
+               }
+       }
 
+       ret = get_dev(argc, argv, flags);
+       if (ret < 0) {
+               if (errno == EBUSY)
+                       nvme_show_busy_namespace(basename(argv[optind]));
+               else
+                       argconfig_print_help(desc, opts);
+       }
        return ret;
 }
 
-int open_exclusive(int argc, char **argv, int force)
-{
-    int flags = O_RDONLY;
-
-       if (!force)
-               flags |= O_EXCL;
-
-    return get_dev(argc, argv, flags);
-}
-
 enum nvme_print_flags validate_output_format(const char *format)
 {
        if (!format)
@@ -3716,6 +3719,7 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
        const char *ause_desc = "Allow unrestricted sanitize exit.";
        const char *sanact_desc = "Sanitize action.";
        const char *ovrpat_desc = "Overwrite pattern.";
+       const char *force_desc = "The \"I know what I'm doing\" flag, skip confirmation before sending command";
 
        int fd, ret;
 
@@ -3726,6 +3730,7 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
                int    ause;
                __u8   sanact;
                __u32  ovrpat;
+               int    force;
        };
 
        struct config cfg = {
@@ -3735,6 +3740,7 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
                .ause = 0,
                .sanact = 0,
                .ovrpat = 0,
+               .force = 0,
        };
 
        OPT_ARGS(opts) = {
@@ -3744,6 +3750,7 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
                OPT_FLAG("ause",       'u', &cfg.ause,       ause_desc),
                OPT_BYTE("sanact",     'a', &cfg.sanact,     sanact_desc),
                OPT_UINT("ovrpat",     'p', &cfg.ovrpat,     ovrpat_desc),
+               OPT_FLAG("force",      'f', &cfg.force,      force_desc),
                OPT_END()
        };
 
@@ -4107,24 +4114,6 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
                OPT_END()
        };
 
-       err = argconfig_parse(argc, argv, desc, opts);
-       if (err)
-               goto ret;
-
-       err = fd = open_exclusive(argc, argv, cfg.force);
-       if (fd < 0) {
-               if (errno == EBUSY) {
-                       fprintf(stderr, "Failed to open %s.\n",
-                basename(argv[optind]));
-                       fprintf(stderr,
-                               "Namespace is currently busy.\n"
-                               "Use the force [--force|-f] option to ignore that.\n");
-               } else {
-                       argconfig_print_help(desc, opts);
-               }
-               goto ret;
-       }
-
        err = fd = parse_and_open(argc, argv, desc, opts);
        if (fd < 0)
                goto ret;
@@ -4738,23 +4727,27 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin
        const char *namespace_id = "desired namespace";
        const char *start_block = "64-bit LBA of first block to access";
        const char *block_count = "number of blocks (zeroes based) on device to access";
+       const char *force_desc = "The \"I know what I'm doing\" flag, skip confirmation before sending command";
 
        struct config {
                __u64 start_block;
                __u32 namespace_id;
                __u16 block_count;
+               int force;
        };
 
        struct config cfg = {
                .start_block     = 0,
                .namespace_id    = 0,
                .block_count     = 0,
+               .force           = 0,
        };
 
        OPT_ARGS(opts) = {
                OPT_UINT("namespace-id",  'n', &cfg.namespace_id, namespace_id),
                OPT_SUFFIX("start-block", 's', &cfg.start_block,  start_block),
                OPT_SHRT("block-count",   'c', &cfg.block_count,  block_count),
+               OPT_FLAG("force",         'f', &cfg.force,        force_desc),
                OPT_END()
        };
 
@@ -4795,7 +4788,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
        const char *start_block = "64-bit LBA of first block to access";
        const char *block_count = "number of blocks (zeroes based) on device to access";
        const char *limited_retry = "limit media access attempts";
-       const char *force = "force device to commit data before command completes";
+       const char *force_unit_access = "force device to commit data before command completes";
        const char *prinfo = "PI and check field";
        const char *ref_tag = "reference tag (for end to end PI)";
        const char *app_tag_mask = "app tag mask (for end to end PI)";
@@ -4805,6 +4798,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
        const char *deac = "Set DEAC bit, requesting controller to deallocate specified logical blocks";
        const char *storage_tag_check = "This bit specifies the Storage Tag field shall be checked as "\
                "part of end-to-end data protection processing";
+       const char *force = "The \"I know what I'm doing\" flag, open device even it is already used";
 
        struct config {
                __u64 start_block;
@@ -4819,6 +4813,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
                int   limited_retry;
                int   force_unit_access;
                int   storage_tag_check;
+               int   force;
        };
 
        struct config cfg = {
@@ -4830,6 +4825,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
                .app_tag                = 0,
                .storage_tag            = 0,
                .storage_tag_check      = 0,
+               .force                  = 0,
        };
 
        OPT_ARGS(opts) = {
@@ -4838,13 +4834,14 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
                OPT_SHRT("block-count",       'c', &cfg.block_count,       block_count),
                OPT_FLAG("deac",              'd', &cfg.deac,              deac),
                OPT_FLAG("limited-retry",     'l', &cfg.limited_retry,     limited_retry),
-               OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force),
+               OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access),
                OPT_BYTE("prinfo",            'p', &cfg.prinfo,            prinfo),
                OPT_UINT("ref-tag",           'r', &cfg.ref_tag,           ref_tag),
                OPT_SHRT("app-tag-mask",      'm', &cfg.app_tag_mask,      app_tag_mask),
                OPT_SHRT("app-tag",           'a', &cfg.app_tag,           app_tag),
                OPT_SUFFIX("storage-tag",     'S', &cfg.storage_tag,       storage_tag),
                OPT_FLAG("storage-tag-check", 'C', &cfg.storage_tag_check, storage_tag_check),
+               OPT_FLAG("force",               0, &cfg.force,             force),
                OPT_END()
        };
 
@@ -5520,7 +5517,7 @@ static int submit_io(int opcode, char *command, const char *desc,
        const char *app_tag = "app tag (for end to end PI)";
        const char *limited_retry = "limit num. media access attempts";
        const char *latency = "output latency statistics";
-       const char *force = "force device to commit data before command completes";
+       const char *force_unit_access = "force device to commit data before command completes";
        const char *show = "show command before sending";
        const char *dry = "show command instead of sending";
        const char *dtype = "directive type (for write-only)";
@@ -5530,6 +5527,7 @@ static int submit_io(int opcode, char *command, const char *desc,
                "checked as part of end-to-end data protection processing";
        const char *storage_tag = "storage tag, CDW2 and CDW3 (00:47) bits "\
                "(for end to end PI)";
+       const char *force = "The \"I know what I'm doing\" flag, open device even it is already in use";
 
        struct config {
                __u32 namespace_id;
@@ -5553,22 +5551,24 @@ static int submit_io(int opcode, char *command, const char *desc,
                int   show;
                int   dry_run;
                int   latency;
+               int   force;
        };
 
        struct config cfg = {
                .namespace_id           = 0,
                .start_block            = 0,
                .block_count            = 0,
-               .data_size              = 0,
+               .data_size                      = 0,
                .metadata_size          = 0,
-               .ref_tag                = 0,
-               .data                   = "",
-               .metadata               = "",
-               .prinfo                 = 0,
+               .ref_tag                        = 0,
+               .data                           = "",
+               .metadata                       = "",
+               .prinfo                         = 0,
                .app_tag_mask           = 0,
-               .app_tag                = 0,
+               .app_tag                        = 0,
                .storage_tag_check      = 0,
                .storage_tag            = 0,
+               .force                          = 0,
        };
 
        OPT_ARGS(opts) = {
@@ -5585,7 +5585,7 @@ static int submit_io(int opcode, char *command, const char *desc,
                OPT_SHRT("app-tag",           'a', &cfg.app_tag,           app_tag),
                OPT_SUFFIX("storage-tag",     'g', &cfg.storage_tag,       storage_tag),
                OPT_FLAG("limited-retry",     'l', &cfg.limited_retry,     limited_retry),
-               OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force),
+               OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access),
                OPT_FLAG("storage-tag-check", 'C', &cfg.storage_tag_check, storage_tag_check),
                OPT_BYTE("dir-type",          'T', &cfg.dtype,             dtype),
                OPT_SHRT("dir-spec",          'S', &cfg.dspec,             dspec),
@@ -5593,9 +5593,13 @@ static int submit_io(int opcode, char *command, const char *desc,
                OPT_FLAG("show-command",      'v', &cfg.show,              show),
                OPT_FLAG("dry-run",           'w', &cfg.dry_run,           dry),
                OPT_FLAG("latency",           't', &cfg.latency,           latency),
+               OPT_FLAG("force",               0, &cfg.force,             force),
                OPT_END()
        };
 
+       if (opcode != nvme_cmd_write)
+               cfg.force = 1;
+
        err = fd = parse_and_open(argc, argv, desc, opts);
        if (fd < 0)
                goto ret;