]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
zns changed zone list log
authorKeith Busch <kbusch@kernel.org>
Fri, 5 Jun 2020 23:25:12 +0000 (16:25 -0700)
committerKeith Busch <kbusch@kernel.org>
Mon, 8 Jun 2020 15:30:33 +0000 (08:30 -0700)
nvme.c
nvme.h
plugins/zns/zns.c
util/user-types.c
util/user-types.h

diff --git a/nvme.c b/nvme.c
index 81f04d52d7f6e1a8f065c399a9a7bec68e342908..ac6814b16b4a1180f2dfa0022d545ef85fb5fff1 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -65,6 +65,7 @@ static struct program nvme = {
 };
 
 const char *output_format = "Output format: normal|json|binary";
+const char *namespace_id = "Identifier of desired namespace";
 
 /* Name of file to output log pages in their raw format */
 static char *raw;
@@ -589,9 +590,10 @@ close_fd:
 
 static int get_endurance_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
-       struct nvme_endurance_group_log log;
        const char *desc = "Retrieves endurance groups log page and prints the log.";
        const char *group_id = "The endurance group identifier";
+
+       struct nvme_endurance_group_log log;
        enum nvme_print_flags flags;
        int err, fd;
 
@@ -798,11 +800,10 @@ close_fd:
 
 static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
-       struct nvme_ns_list ns_list;
-       const char *desc = "Retrieve Changed Namespaces log for the given device "\
-                       "in either decoded format "\
-                       "(default) or binary.";
+       const char *desc = "Retrieve Changed Namespaces log for the given device";
        const char *raw = "output in binary format";
+
+       struct nvme_ns_list ns_list;
        enum nvme_print_flags flags;
        int err, fd;
 
@@ -1043,7 +1044,7 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl
 {
        const char *desc = "For the specified controller handle, show the "\
                "namespace list in the associated NVMe subsystem, optionally starting with a given nsid.";
-       const char *namespace_id = "first nsid returned list should start from";
+       const char *namespace_id = "list's first nsid should start from";
        const char *all = "show all namespaces in the subsystem, whether attached or inactive";
        enum nvme_print_flags flags;
        int err, fd;
@@ -1519,7 +1520,6 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p
                            "given device, returns the namespace identification descriptors "\
                            "of the specific namespace in either human-readable or binary format.";
        const char *raw = "show descriptors in binary format";
-       const char *namespace_id = "identifier of desired namespace";
        enum nvme_print_flags flags;
        void *nsdescs;
        int err, fd;
@@ -1586,7 +1586,6 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
        const char *vendor_specific = "dump binary vendor fields";
        const char *raw = "show identify in binary format";
        const char *human_readable = "show identify in readable format";
-       const char *namespace_id = "identifier of desired namespace";
 
        enum nvme_print_flags flags;
        struct nvme_id_ns ns;
@@ -1942,8 +1941,7 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p
 {
        const char *desc  = "Implementing the device self-test feature"\
                " which provides the necessary log to determine the state of the device";
-       const char *namespace_id = "Indicate the namespace in which the device self-test"\
-               " has to be carried out";
+       const char *namespace_id = "Indicate the namespace the for the device self-test";
        const char * self_test_code = "This field specifies the action taken by the device self-test command : "\
                "\n1h Start a short device self-test operation\n"\
                "2h Start a extended device self-test operation\n"\
@@ -1988,8 +1986,7 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug
        const char *desc = "Retrieve the self-test log for the given device and given test "\
                        "(or optionally a namespace) in either decoded format "\
                        "(default) or binary.";
-       const char *namespace_id = "Indicate the namespace from which the self-test "\
-                                   "log has to be obtained";
+       const char *namespace_id = "The namespace for the self-test log namespace";
        const char *verbose = "Increase output verbosity";
 
        struct nvme_self_test_log log;
@@ -2046,7 +2043,6 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin
                "are vendor-specific and not changeable. Use set-feature to "\
                "change saveable Features.";
        const char *raw = "show feature in binary format";
-       const char *namespace_id = "identifier of desired namespace";
        const char *feature_id = "feature identifier";
        const char *sel = "[0-3]: current/default/saved/supported";
        const char *data_len = "buffer len if data is returned through host memory buffer";
@@ -2649,7 +2645,6 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
                "given device. Can erase all data in namespace (user "\
                "data erase) or delete data encryption key if specified. "\
                "Can also be used to change LBAF to change the namespaces reported physical block format.";
-       const char *namespace_id = "identifier of desired namespace";
        const char *lbaf = "LBA format to apply (required)";
        const char *ses = "[0-2]: secure erase";
        const char *pil = "[0-1]: protection info location last/first 8 bytes of metadata";
@@ -2854,7 +2849,6 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
                "for each Feature are vendor-specific and may not be modified."\
                "Use get-feature to determine which Features are supported by "\
                "the controller and are saveable/changeable.";
-       const char *namespace_id = "desired namespace";
        const char *feature_id = "feature identifier (required)";
        const char *data_len = "buffer length if data required";
        const char *data = "optional file for feature data (default stdin)";
@@ -2966,7 +2960,6 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p
        const char *secp = "security protocol (cf. SPC-4)";
        const char *spsp = "security-protocol-specific (cf. SPC-4)";
        const char *tl = "transfer length (cf. SPC-4)";
-       const char *namespace_id = "desired namespace";
        const char *nssf = "NVMe Security Specific Field";
        int err, fd, sec_fd = -1;
        void *sec_buf;
@@ -3055,7 +3048,6 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
        const char *desc = "Set directive parameters of the "\
                            "specified directive type.";
        const char *raw = "show directive in binary format";
-       const char *namespace_id = "identifier of desired namespace";
        const char *data_len = "buffer len (if) data is returned";
        const char *dtype = "directive type";
        const char *dspec = "directive specification associated with directive type";
@@ -3173,7 +3165,6 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin
        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";
        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";
 
@@ -3219,7 +3210,6 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
        __u16 control = 0;
        const char *desc = "The Write Zeroes command is used to set a "\
                        "range of logical blocks to zero.";
-       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 *limited_retry = "limit media access attempts";
@@ -3298,7 +3288,6 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin
                "indicate attributes for ranges of logical blocks. This includes attributes "\
                "for discarding unused blocks, data read and write frequency, access size, and other "\
                "information that may be used to optimize performance and reliability.";
-       const char *namespace_id = "identifier of desired namespace";
        const char *blocks = "Comma separated list of the number of blocks in each range";
        const char *starting_blocks = "Comma separated list of the starting block in each range";
        const char *context_attrs = "Comma separated list of the context attributes in each range";
@@ -3379,7 +3368,6 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug
                "finished before the flush was submitted. Additional data may also be "\
                "flushed by the controller, from any namespace, depending on controller and "\
                "associated namespace status.";
-       const char *namespace_id = "identifier of desired namespace";
        int err, fd;
 
        struct config {
@@ -3422,7 +3410,6 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi
                "with that namespace. Namespace reservation will abort with "\
                "status Reservation Conflict if the given namespace is "\
                "already reserved.";
-       const char *namespace_id = "identifier of desired namespace";
        const char *crkey = "current reservation key";
        const char *prkey = "pre-empt reservation key";
        const char *rtype = "reservation type";
@@ -3482,7 +3469,6 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug
        const char *desc = "Register, de-register, or "\
                "replace a controller's reservation on a given namespace. "\
                "Only one reservation at a time is allowed on any namespace.";
-       const char *namespace_id = "identifier of desired namespace";
        const char *crkey = "current reservation key";
        const char *iekey = "ignore existing res. key";
        const char *nrkey = "new reservation key";
@@ -3553,7 +3539,6 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi
                "effect. If the reservation type is not Write Exclusive or "\
                "Exclusive Access, all registrants on the namespace except "\
                "the issuing controller are notified.";
-       const char *namespace_id = "desired namespace";
        const char *crkey = "current reservation key";
        const char *iekey = "ignore existing res. key";
        const char *rtype = "reservation type";
@@ -3612,7 +3597,6 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin
                "status of a given namespace. Namespace Reservation Status "\
                "depends on the number of controllers registered for that "\
                "namespace.";
-       const char *namespace_id = "identifier of desired namespace";
        const char *s = "number of bytes to transfer";
        const char *eds = "request extended data structure";
        const char *raw = "dump output in binary format";
@@ -3723,7 +3707,6 @@ static int submit_io(int opcode, char *command, const char *desc,
        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)";
-       const char *namespace_id = "desired namespace";
 
        struct config {
                __u64 start_block;
@@ -3968,7 +3951,6 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
        int err, fd;
        __u16 control = 0;
        const char *desc = "Verify specified logical blocks on the given device.";
-       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 *limited_retry = "limit media access attempts";
@@ -4050,7 +4032,6 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
        const char *spsp = "security-protocol-specific (cf. SPC-4)";
        const char *al = "allocation length (cf. SPC-4)";
        const char *raw = "dump output in binary format";
-       const char *namespace_id = "desired namespace";
        const char *nssf = "NVMe Security Specific Field";
        int err, fd;
        void *sec_buf = NULL;
@@ -4190,7 +4171,6 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin
        const char *desc = "Read directive parameters of the "\
                            "specified directive type.";
        const char *raw = "show directive in binary format";
-       const char *namespace_id = "identifier of desired namespace";
        const char *data_len = "buffer len (if) data is returned";
        const char *dtype = "directive type";
        const char *dspec = "directive specification associated with directive type";
@@ -4307,7 +4287,6 @@ static int passthru(int argc, char **argv, bool admin, const char *desc, struct
        const char *opcode = "opcode (required)";
        const char *flags = "command flags";
        const char *rsvd = "value for reserved field";
-       const char *namespace_id = "desired namespace";
        const char *data_len = "data I/O length (bytes)";
        const char *metadata_len = "metadata seg. length (bytes)";
        const char *timeout = "timeout value, in milliseconds";
diff --git a/nvme.h b/nvme.h
index e601a442ee599eb91fae72baa280a3717fd8d8a5..41d5f092d668699bc8062ee01dec855e76ddabe3 100644 (file)
--- a/nvme.h
+++ b/nvme.h
@@ -31,6 +31,7 @@
 #define VERBOSE (NVME_JSON_DECODE_COMPLEX|NVME_JSON_HUMAN)
 
 extern const char *output_format;
+extern const char *namespace_id;
 
 void register_extension(struct plugin *plugin);
 int parse_and_open(int argc, char **argv, const char *desc,
index 1c58649d110b3ea31718c6d97d7e534d3bb7219a..c9addad163ff45e9349febbaeceab1845fb0668d 100644 (file)
@@ -58,7 +58,6 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
        const char *desc = "Send ZNS specific Identify Namespace command to "\
                "the given device and report information about the specified "\
                "namespace in varios formats.";
-       const char *namespace_id = "identifier of desired namespace";
        const char *verbose = "verbosely decode fields";
 
        enum nvme_print_flags flags;
@@ -141,7 +140,6 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug
        const char *desc, enum nvme_zns_send_action zsa)
 {
        const char *zslba = "starting lba of the zone for this command";
-       const char *namespace_id = "identifier of desired namespace";
        const char *select_all = "send command to all zones";
 
        int err, fd;
@@ -187,7 +185,6 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
 {
        const char *desc = "Zone Management Send";
        const char *zslba = "starting lba of the zone for this command";
-       const char *namespace_id = "identifier of desired namespace";
        const char *select_all = "send command to all zones";
        const char *zsa = "zone send action";
        const char *data_len = "buffer length if data required";
@@ -302,7 +299,6 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
 {
        const char *desc = "Set Zone Descriptor Extension\n";
        const char *zslba = "starting lba of the zone for this command";
-       const char *namespace_id = "identifier of desired namespace";
        const char *data = "optional file for zone extention data (default stdin)";
 
        int fd, ffd = STDIN_FILENO, err;
@@ -355,7 +351,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
                goto close_fd;
        }
 
-       buf = malloc(data_len);
+       buf = calloc(1, data_len);
        if (!buf) {
                err = -1;
                goto close_fd;
@@ -395,7 +391,68 @@ close_fd:
 
 static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
-       return 0;
+       const char *desc = "Zone Management Receive";
+
+       enum nvme_print_flags flags;
+       int fd, err = -1;
+       void *data = NULL;
+
+       struct config {
+               char *output_format;
+               __u64  zslba;
+               __u32  namespace_id;
+               __u16  zra;
+               __u16  zrasf;
+               bool   zrass;
+               __u32  data_len;
+       };
+
+       struct config cfg = {
+               .output_format = "normal",
+       };
+
+
+       OPT_ARGS(opts) = {
+               OPT_END()
+       };
+
+       fd = parse_and_open(argc, argv, desc, opts);
+       if (fd < 0)
+               return errno;
+
+       flags = validate_output_format(cfg.output_format);
+       if (flags < 0)
+               goto close_fd;
+
+       if (!cfg.namespace_id) {
+               err = nvme_get_nsid(fd, &cfg.namespace_id);
+               if (err < 0) {
+                       perror("get-namespace-id");
+                       goto close_fd;
+               }
+       }
+
+       if (cfg.data_len) {
+               data = calloc(1, cfg.data_len);
+               if (!data) {
+                       err = -1;
+                       goto close_fd;
+               }
+       }
+
+       err = nvme_zns_mgmt_recv(fd, cfg.namespace_id, cfg.zslba, cfg.zra,
+               cfg.zrasf, cfg.zrass, cfg.data_len, data);
+       if (!err)
+               printf("zone-mgmt-recv: Success, action:%d zone:%"PRIx64" nsid:%d\n",
+                       cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id);
+       else
+               nvme_show_status("zone-mgmt-recv", err);
+
+       if (data)
+               free(data);
+close_fd:
+       close(fd);
+       return nvme_status_to_errno(err, false);
 }
 
 static int get_zdes(int fd, __u32 nsid)
@@ -430,8 +487,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
        const char *ext = "set to use the extended report zones";
        const char *part = "set to use the partial report";
        const char *verbose = "verbosely decode fields";
-       const char *namespace_id = "identifier of desired namespace";
-       
+
        enum nvme_print_flags flags;
        int fd, zdes = 0, err = -1;
        __u32 report_size;
@@ -448,7 +504,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
                bool  extended;
                bool  partial;
        };
-       
+
        struct config cfg = {
                .output_format = "normal",
        };
@@ -456,8 +512,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
        OPT_ARGS(opts) = {
                OPT_UINT("namespace-id", 'n', &cfg.namespace_id,  namespace_id),
                OPT_SUFFIX("start-lba",  's', &cfg.zslba,         zslba),
-               OPT_UINT("descs",        'd', &cfg.num_descs,  num_descs),
-               OPT_UINT("state",         'S', &cfg.state,         state),
+               OPT_UINT("descs",        'd', &cfg.num_descs,     num_descs),
+               OPT_UINT("state",        'S', &cfg.state,         state),
                OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
                OPT_FLAG("verbose",      'v', &cfg.verbose,       verbose),
                OPT_FLAG("extended",     'e', &cfg.extended,      ext),
@@ -496,7 +552,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
 
        report = nvme_alloc(report_size, &huge);
        if (!report) {
-               perror("malloc");
+               perror("alloc");
                err = -1;
                goto close_fd;
        }
@@ -697,5 +753,53 @@ close_fd:
 
 static int change_zone_list(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
-       return 0;
+       const char *desc = "Retrieve Changed Zone log for the given device";
+       const char *rae = "retain an asynchronous event";
+
+       struct nvme_zns_changed_zone_log log;
+       enum nvme_print_flags flags;
+       int fd, err = -1;
+
+       struct config {
+               char *output_format;
+               __u32 namespace_id;
+               bool  rae;
+       };
+
+       struct config cfg = {
+               .output_format = "normal",
+       };
+
+       OPT_ARGS(opts) = {
+               OPT_UINT("namespace-id", 'n', &cfg.namespace_id,  namespace_id),
+               OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+               OPT_FLAG("rae",          'r', &cfg.rae,           rae),
+               OPT_END()
+       };
+
+       fd = parse_and_open(argc, argv, desc, opts);
+       if (fd < 0)
+               return errno;
+
+       flags = validate_output_format(cfg.output_format);
+       if (flags < 0)
+               goto close_fd;
+
+       if (!cfg.namespace_id) {
+               err = nvme_get_nsid(fd, &cfg.namespace_id);
+               if (err < 0) {
+                       perror("get-namespace-id");
+                       goto close_fd;
+               }
+       }
+
+       err = nvme_get_log_zns_changed_zones(fd, cfg.namespace_id, cfg.rae, &log);
+       if (!err)
+               nvme_print_object(nvme_zns_changed_to_json(&log, flags));
+       else
+               nvme_show_status("change-zone-log", err);
+
+close_fd:
+       close(fd);
+       return nvme_status_to_errno(err, false);
 }
index 458027f2219346e044c7275c77a1b0fd430e3601..4a6225182b0b11787c6936a2947d3d1b8217ee5c 100644 (file)
@@ -8,6 +8,7 @@
 #include <json-c/json.h>
 #include <uuid/uuid.h>
 
+#include <ccan/minmax/minmax.h>
 #include <ccan/array_size/array_size.h>
 
 #include "user-types.h"
@@ -534,7 +535,7 @@ static int __display_human_size(struct json_object *o, struct printbuf *p,
 {
        uint16_t i = 0, major = 0, minor = 0, jmajor = 0, jminor = 0;
        uint64_t v = json_object_get_int64(o);
-       
+
        util_split(v, &i, &major, &minor, &jmajor, &jminor);
        return sprintbuf(p, "%u.%02u %s (%lu.%03lu %s)", major, minor, iec[i],
                jmajor, jminor, jedec[i]);
@@ -555,7 +556,7 @@ static int _display_human_size(struct json_object *o, struct printbuf *p,
 {
        uint64_t v = json_object_get_int64(o);
        uint16_t i = 0, major = 0, minor = 0;
-       
+
        util_split(v, &i, &major, &minor, NULL, NULL);
        if (minor)
                return sprintbuf(p, "%u.%02u %s", major, minor, iec[i]);
@@ -980,7 +981,7 @@ static int display_tree(struct json_object *jso, struct printbuf *p,
 
        if (i > 1)
                char_stack[l] = '|';
-       else    
+       else
                char_stack[l] = ' ';
 
        //printf("%s %d child objects\n", __func__, i);
@@ -2138,7 +2139,7 @@ static void nvme_json_add_id_ctrl_psd_human(struct json_object *j,
        switch (ips) {
        case 1:
                break;
-       case 2: 
+       case 2:
                idlp *= 100;
                break;
        default:
@@ -2149,7 +2150,7 @@ static void nvme_json_add_id_ctrl_psd_human(struct json_object *j,
        switch (aps) {
        case 1:
                break;
-       case 2: 
+       case 2:
                actp *= 100;
                break;
        default:
@@ -3425,7 +3426,7 @@ struct json_object *nvme_ns_list_to_json(
 
        jlist = nvme_json_new_object(flags);
        jarray = nvme_json_new_array();
-       for (i = 0; i < 1024; i++) {
+       for (i = 0; i < NVME_ID_NS_LIST_MAX; i++) {
                struct json_object *jnsid;
                __u32 nsid;
 
@@ -3441,6 +3442,34 @@ struct json_object *nvme_ns_list_to_json(
        return jlist;
 }
 
+struct json_object *nvme_zns_changed_to_json(
+       struct nvme_zns_changed_zone_log *log, unsigned long flags)
+{
+       struct json_object *jlist, *jarray;
+       uint16_t nrzid;
+       int i;
+
+       if (flags & NVME_JSON_BINARY)
+               return nvme_json_new_str_len_flags(log, sizeof(*log), flags);
+
+       jlist = nvme_json_new_object(flags);
+       jarray = nvme_json_new_array();
+
+       nrzid = le16_to_cpu(log->nrzid);
+
+       nvme_json_add_int(jlist, "nr-zone-ids", nrzid);
+       if (nrzid == 0xffff)
+               return jlist;
+
+       for (i = 0; i < min(nrzid, (uint16_t)NVME_ZNS_CHANGED_ZONES_MAX); i++)
+               json_object_array_add(jarray, nvme_json_new_int64(
+                       le64_to_cpu(log->zid[i])));
+
+       json_object_object_add(jlist, "zone-ids", jarray);
+
+       return jlist;
+}
+
 struct json_object *nvme_ctrl_list_to_json(
        struct nvme_ctrl_list *list, unsigned long flags)
 {
index 4a8b16024a839568df41a85e5c63876cb042f2a2..b34f821eec98a3b9ff4be0a11e008f7c55dab94a 100644 (file)
@@ -143,6 +143,9 @@ struct json_object *nvme_zns_id_ns_to_json( struct nvme_zns_id_ns *ns,
 struct json_object *nvme_zns_report_zones_to_json(void *report, __u32 descs,
        __u8 ext_size, __u32 report_size, unsigned long flags);
 
+struct json_object *nvme_zns_changed_to_json(
+       struct nvme_zns_changed_zone_log *log, unsigned long flags);
+
 struct json_object *nvme_json_new_str_len(const char *v, int len);
 struct json_object *nvme_json_new_str_len_flags(const void *v, int len,
        unsigned long flags);