]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: add options for write command directives
authorKeith Busch <keith.busch@gmail.com>
Sun, 10 Dec 2017 16:42:09 +0000 (09:42 -0700)
committerKeith Busch <keith.busch@gmail.com>
Sun, 10 Dec 2017 16:42:09 +0000 (09:42 -0700)
This patch includes options to specify the directive type and directive
specific. The field is meant to be used for write commands, but since
the code reuse for read, write, and compare currently exists, the options
will appear available to commands other than write.

Since the directive specific is part of the larger DSM field, this patch
also incorporates an option for the non-directive specific portion of
the DSM field.

https://github.com/linux-nvme/nvme-cli/issues/235

Signed-off-by: Keith Busch <keith.busch@gmail.com>
Documentation/nvme-write.txt
nvme-models.h
nvme.c

index 0f307208944ba36433222a6cd500fa275e1a4e65..2fe9b28eee4a7ec55eda49c4b7e890f00ff2c0d7 100644 (file)
@@ -18,6 +18,9 @@ SYNOPSIS
                        [--ref-tag=<reftag> | -r <reftag>]
                        [--app-tag-mask=<appmask> | -m <appmask>]
                        [--app-tag=<apptag> | -a <apptag>]
+                       [--dtype=<dtype> | -T <dtype>]
+                       [--dspec=<dspec> | -S <dspec>]
+                       [--dsm=<dsm> | -D <dsm>]
                        [--limited-retry | -l]
                        [--latency | -t]
                        [--force-unit-access | -f]
@@ -72,6 +75,31 @@ metadata is passes.
 |0|Set to 1 enables checking the reference tag
 |=================
 
+--dtype=<dtype>::
+-T <dtype>::
+       Optional directive type. The nvme-cli only enforces the value
+       be in the defined range for the directive type, though the NVMe
+       specifcation (1.3a) defines only one directive, 01h, for write
+       stream idenfiers.
+
+--dspec=<dspec>::
+-S <dspec>::
+       Optional field for directive specifics. When used with
+       write streams, this value is defined to be the write stream
+       identifier. The nvme-cli will not validate the stream requested
+       is within the controller's capabilities.
+
+--dsm=<dsm>::
+-D <dsm>::
+       The optional data set management attributes for this command. The
+       argument for this is the lower 16 bits of the DSM field in a write
+       command; the upper 16 bits of the field come from the directive
+       specific field, if used. This may be used to set attributes for
+       the LBAs being written, like access frequency, type, latency,
+       among other things, as well as yet to be defined types. Please
+       consult the NVMe specification for detailed breakdown of how to
+       use this field.
+
 --ref-tag=<reftag>::
 -r <reftag>::
        Optional reftag when used with protection information.
index a15cc21d169ddfb3c389c0a3df36920eee6a9268..72983ea9564872c8df7dec4937da74157b5d66ca 100644 (file)
@@ -1,4 +1,6 @@
 #ifndef NVME_MODEL_H
 #define NVME_MODEL_H
+
 char *nvme_product_name(int id);
+
 #endif
diff --git a/nvme.c b/nvme.c
index 7830ea2de4ac216902d1913a7c8d679201177ab7..6912837afe70830d160bd1357578617a98fcefe4 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -2670,6 +2670,7 @@ static int submit_io(int opcode, char *command, const char *desc,
        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;
+       __u32 dsmgmt = 0;
        int phys_sector_size = 0;
        long long buffer_size = 0;
 
@@ -2688,6 +2689,9 @@ static int submit_io(int opcode, char *command, const char *desc,
        const char *force = "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)";
+       const char *dspec = "directive specific (for write-only)";
+       const char *dsm = "dataset management attributes (lower 16 bits)";
 
        struct config {
                __u64 start_block;
@@ -2698,6 +2702,9 @@ static int submit_io(int opcode, char *command, const char *desc,
                char  *data;
                char  *metadata;
                __u8  prinfo;
+               __u8 dtype;
+               __u16 dspec;
+               __u16 dsmgmt;
                __u16 app_tag_mask;
                __u16 app_tag;
                int   limited_retry;
@@ -2733,6 +2740,9 @@ static int submit_io(int opcode, char *command, const char *desc,
                {"app-tag",           'a', "NUM",  CFG_SHORT,       &cfg.app_tag,           required_argument, app_tag},
                {"limited-retry",     'l', "",     CFG_NONE,        &cfg.limited_retry,     no_argument,       limited_retry},
                {"force-unit-access", 'f', "",     CFG_NONE,        &cfg.force_unit_access, no_argument,       force},
+               {"dir-type",          'T', "NUM",  CFG_BYTE,        &cfg.dtype,             required_argument, dtype},
+               {"dir-spec",          'S', "NUM",  CFG_SHORT,       &cfg.dspec,             required_argument, dspec},
+               {"dsm",               'D', "NUM",  CFG_SHORT,       &cfg.dsmgmt,            required_argument, dsm},
                {"show-command",      'v', "",     CFG_NONE,        &cfg.show,              no_argument,       show},
                {"dry-run",           'w', "",     CFG_NONE,        &cfg.dry_run,           no_argument,       dry},
                {"latency",           't', "",     CFG_NONE,        &cfg.latency,           no_argument,       latency},
@@ -2746,11 +2756,23 @@ static int submit_io(int opcode, char *command, const char *desc,
        dfd = mfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO;
        if (cfg.prinfo > 0xf)
                return EINVAL;
+
+       dsmgmt = cfg.dsmgmt;
        control |= (cfg.prinfo << 10);
        if (cfg.limited_retry)
                control |= NVME_RW_LR;
        if (cfg.force_unit_access)
                control |= NVME_RW_FUA;
+       if (cfg.dtype) {
+               if (cfg.dtype > 0xf) {
+                       fprintf(stderr, "Invalid directive type, %x\n",
+                               cfg.dtype);
+                       return EINVAL;
+               }
+               control |= cfg.dtype << 4;
+               dsmgmt |= ((__u32)cfg.dspec) << 16;
+       }
+       
        if (strlen(cfg.data)){
                dfd = open(cfg.data, flags, mode);
                if (dfd < 0) {
@@ -2820,7 +2842,7 @@ static int submit_io(int opcode, char *command, const char *desc,
                printf("metadata     : %"PRIx64"\n", (uint64_t)(uintptr_t)mbuffer);
                printf("addr         : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer);
                printf("sbla         : %"PRIx64"\n", (uint64_t)cfg.start_block);
-               printf("dsmgmt       : %08x\n", 0);
+               printf("dsmgmt       : %08x\n", dsmgmt);
                printf("reftag       : %08x\n", cfg.ref_tag);
                printf("apptag       : %04x\n", cfg.app_tag);
                printf("appmask      : %04x\n", cfg.app_tag_mask);
@@ -2829,7 +2851,7 @@ static int submit_io(int opcode, char *command, const char *desc,
        }
 
        gettimeofday(&start_time, NULL);
-       err = nvme_io(fd, opcode, cfg.start_block, cfg.block_count, control, 0,
+       err = nvme_io(fd, opcode, cfg.start_block, cfg.block_count, control, dsmgmt,
                        cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask, buffer, mbuffer);
        gettimeofday(&end_time, NULL);
        if (cfg.latency)