From dc46f4aedf309045fc7cb47c23fcbd29a042eb57 Mon Sep 17 00:00:00 2001 From: Steven Seungcheol Lee Date: Fri, 19 Jun 2020 10:54:56 +0900 Subject: [PATCH] Identify I/O Command Set data structure command added Spec : NVMe - TP 4056 Namespace Types 2020.06.15 - Ratified Signed-off-by: Steven Seungcheol Lee Co-authored-by: Klaus Jensen --- Documentation/nvme-id-iocs.1 | 72 +++ Documentation/nvme-id-iocs.html | 817 ++++++++++++++++++++++++++++ Documentation/nvme-id-iocs.txt | 39 ++ completions/_nvme | 13 +- completions/bash-nvme-completion.sh | 5 +- linux/nvme.h | 24 + nvme-builtin.h | 1 + nvme-ioctl.c | 5 + nvme-ioctl.h | 1 + nvme-print.c | 25 + nvme-print.h | 1 + nvme.c | 43 ++ 12 files changed, 1044 insertions(+), 2 deletions(-) create mode 100644 Documentation/nvme-id-iocs.1 create mode 100644 Documentation/nvme-id-iocs.html create mode 100644 Documentation/nvme-id-iocs.txt diff --git a/Documentation/nvme-id-iocs.1 b/Documentation/nvme-id-iocs.1 new file mode 100644 index 0000000..ba40992 --- /dev/null +++ b/Documentation/nvme-id-iocs.1 @@ -0,0 +1,72 @@ +'\" t +.\" Title: nvme-id-iocs +.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] +.\" Generator: DocBook XSL Stylesheets vsnapshot +.\" Date: 05/06/2020 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-ID\-IOCS" "1" "05/06/2020" "NVMe" "NVMe Manual" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +nvme-id-iocs \- Send NVMe Identify I/O Command Set, return result and structure +.SH "SYNOPSIS" +.sp +.nf +\fInvme id\-iocs\fR [\-\-controller\-id= | \-c ] +.fi +.SH "DESCRIPTION" +.sp +For the NVMe device given, send an identify command and return the Identify I/O Command Set data structure\&. +.sp +The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. +.SH "OPTIONS" +.PP +\-c , \-\-controller\-id= +.RS 4 +Retrieve the identify I/O Command set data structure for the given cntid\&. If this value is not given, cntid will be 0xffff\&. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Have the program interpret the returned buffer and display the known fields in a human readable format: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme id\-iocs /dev/nvme0 +.fi +.if n \{\ +.RE +.\} +.RE +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-id-iocs.html b/Documentation/nvme-id-iocs.html new file mode 100644 index 0000000..6bc983f --- /dev/null +++ b/Documentation/nvme-id-iocs.html @@ -0,0 +1,817 @@ + + + + + + +nvme-id-iocs(1) + + + + + +
+
+

SYNOPSIS

+
+
+
nvme id-iocs <device> [--controller-id=<cntid> | -c <cntid>]
+
+
+
+
+
+

DESCRIPTION

+
+

For the NVMe device given, send an identify command and return the Identify I/O +Command Set data structure.

+

The <device> parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

+
+
+
+

OPTIONS

+
+
+
+-c <cntid> +
+
+--controller-id=<cntid> +
+
+

+ Retrieve the identify I/O Command set data structure for the given + cntid. If this value is not given, cntid will be 0xffff. +

+
+
+
+
+
+

EXAMPLES

+
+
    +
  • +

    +Have the program interpret the returned buffer and display the known +fields in a human readable format: +

    +
    +
    +
    # nvme id-iocs /dev/nvme0
    +
    +
  • +
+
+
+
+

NVME

+
+

Part of the nvme-user suite

+
+
+
+

+ + + diff --git a/Documentation/nvme-id-iocs.txt b/Documentation/nvme-id-iocs.txt new file mode 100644 index 0000000..9e53207 --- /dev/null +++ b/Documentation/nvme-id-iocs.txt @@ -0,0 +1,39 @@ +nvme-id-iocs(1) +=============== + +NAME +---- +nvme-id-iocs - Send NVMe Identify I/O Command Set, return result and structure + +SYNOPSIS +-------- +[verse] +'nvme id-iocs' [--controller-id= | -c ] + +DESCRIPTION +----------- +For the NVMe device given, send an identify command and return the Identify I/O +Command Set data structure. + +The parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). + +OPTIONS +------- +-c :: +--controller-id=:: + Retrieve the identify I/O Command set data structure for the given + cntid. If this value is not given, cntid will be 0xffff. + +EXAMPLES +-------- +* Have the program interpret the returned buffer and display the known +fields in a human readable format: ++ +------------ +# nvme id-iocs /dev/nvme0 +------------ + +NVME +---- +Part of the nvme-user suite diff --git a/completions/_nvme b/completions/_nvme index e076232..ce6ac68 100644 --- a/completions/_nvme +++ b/completions/_nvme @@ -10,6 +10,7 @@ _nvme () { 'id-ctrl:display information about the controller' 'id-ns:display information about the namespace' 'list-ns:identify all namespace(s) attached' + 'id-iocs:display information about I/O command sets' 'create-ns:create a new namespace before attachment' 'delete-ns:delete a detached namespace' 'attach-ns:attach namespace to controller' @@ -92,6 +93,16 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme list-ns options" _listns ;; + (id-iocs) + local _idiocs + _idiocs=( + /dev/nvme':supply a device to use (required)' + --controller-id=':show infos for controller ' + -c':alias of --controller-id' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme id-iocs options" _idiocs + ;; (create-ns) local _createns _createns=( @@ -639,7 +650,7 @@ _nvme () { ;; (help) local _h - _h=( id-ctrl id-ns list-ns create-ns delete-ns attach-ns detach-ns + _h=( id-ctrl id-ns list-ns id-iocs create-ns delete-ns attach-ns detach-ns list-ctrl get-ns-id get-log fw-log smart-log error-log get-feature set-feature format fw-activate fw-download admin-passthru io-passthru security-send security-recv resv-acquire resv-register resv-release diff --git a/completions/bash-nvme-completion.sh b/completions/bash-nvme-completion.sh index b7c2aa1..c3842c1 100644 --- a/completions/bash-nvme-completion.sh +++ b/completions/bash-nvme-completion.sh @@ -2,7 +2,7 @@ # (unfortunately, bash won't let me add descriptions to cmds) # Kelly Kaoudis kelly.n.kaoudis at intel.com, Aug. 2015 -_cmds="list id-ctrl id-ns list-ns create-ns delete-ns \ +_cmds="list id-ctrl id-ns list-ns id-iocs create-ns delete-ns \ attach-ns detach-ns list-ctrl get-ns-id get-log \ fw-log smart-log smart-log-add error-log \ get-feature set-feature format fw-activate \ @@ -46,6 +46,9 @@ nvme_list_opts () { "list-ns") opts+=" --namespace-id= -n --al -a" ;; + "id-iocs") + opts+=" --controller-id= -c" + ;; "create-ns") opts+=" --nsze= -s --ncap= -c --flbas= -f \ --dps= -d --nmic= -n" diff --git a/linux/nvme.h b/linux/nvme.h index 41b1dbd..5175f13 100644 --- a/linux/nvme.h +++ b/linux/nvme.h @@ -139,6 +139,12 @@ enum { NVMF_TCP_SECTYPE_TLS = 1, /* Transport Layer Security */ }; +/* I/O Command Sets + */ +enum { + NVME_IOCS_NVM = 0x00, +}; + #define NVME_AQ_DEPTH 32 #define NVME_NR_AEN_COMMANDS 1 #define NVME_AQ_BLK_MQ_DEPTH (NVME_AQ_DEPTH - NVME_NR_AEN_COMMANDS) @@ -411,6 +417,15 @@ struct nvme_id_ns { __u8 vs[3712]; }; +struct nvme_iocs_vector { + __le64 nvm : 1; + __le64 rsvd : 63; +}; + +struct nvme_id_iocs { + struct nvme_iocs_vector iocsc[512]; +}; + enum { NVME_ID_CNS_NS = 0x00, NVME_ID_CNS_CTRL = 0x01, @@ -426,6 +441,7 @@ enum { NVME_ID_CNS_SCNDRY_CTRL_LIST = 0x15, NVME_ID_CNS_NS_GRANULARITY = 0x16, NVME_ID_CNS_UUID_LIST = 0x17, + NVME_ID_CNS_CSI = 0x1c, }; enum { @@ -1370,6 +1386,14 @@ enum { NVME_SC_ANA_INVALID_GROUP_ID= 0x124, NVME_SC_ANA_ATTACH_FAIL = 0x125, + /* + * Command Set Specific - Namespace Types commands: + */ + NVME_SC_IOCS_NOT_SUPPORTED = 0x129, + NVME_SC_IOCS_NOT_ENABLED = 0x12A, + NVME_SC_IOCS_COMBINATION_REJECTED = 0x12B, + NVME_SC_INVALID_IOCS = 0x12C, + /* * I/O Command Set Specific - NVM commands: */ diff --git a/nvme-builtin.h b/nvme-builtin.h index bfb907d..6804ffe 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -18,6 +18,7 @@ COMMAND_LIST( ENTRY("ns-descs", "Send NVMe Namespace Descriptor List, display structure", ns_descs) ENTRY("id-nvmset", "Send NVMe Identify NVM Set List, display structure", id_nvmset) ENTRY("id-uuid", "Send NVMe Identify UUID List, display structure", id_uuid) + ENTRY("id-iocs", "Send NVMe Identify I/O Command Set, display structure", id_iocs) ENTRY("create-ns", "Creates a namespace with the provided parameters", create_ns) ENTRY("delete-ns", "Deletes a namespace from the controller", delete_ns) ENTRY("attach-ns", "Attaches a namespace to requested controller(s)", attach_ns) diff --git a/nvme-ioctl.c b/nvme-ioctl.c index 627db2f..f13d7e9 100644 --- a/nvme-ioctl.c +++ b/nvme-ioctl.c @@ -415,6 +415,11 @@ int nvme_zns_identify_ctrl(int fd, void *data) return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 2 << 24, data); } +int nvme_identify_iocs(int fd, __u16 cntid, void *data) +{ + return nvme_identify(fd, 0, (cntid << 16) | NVME_ID_CNS_CSI, data); +} + int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, __u16 lsi, bool rae, __u8 uuid_ix, __u32 data_len, void *data) { diff --git a/nvme-ioctl.h b/nvme-ioctl.h index ad8237e..a8deadc 100644 --- a/nvme-ioctl.h +++ b/nvme-ioctl.h @@ -87,6 +87,7 @@ int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *dat int nvme_identify_ns_granularity(int fd, void *data); int nvme_zns_identify_ctrl(int fd, void *data); int nvme_zns_identify_ns(int fd, __u32 nsid, void *data); +int nvme_identify_iocs(int fd, __u16 cntid, void *data); int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae, __u32 data_len, void *data); int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, diff --git a/nvme-print.c b/nvme-print.c index c0de928..cd60164 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -3272,6 +3272,18 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, } } +void nvme_show_id_iocs(struct nvme_id_iocs *iocs) +{ + __u16 i; + + for (i = 0; i < 512; i++) { + if (iocs->iocsc[i].nvm) { + printf("I/O Command Set Combination[%"PRIu16"] " + "NVM Command Set Supported\n", i); + } + } +} + static const char *nvme_trtype_to_string(__u8 trtype) { switch(trtype) { @@ -3971,6 +3983,14 @@ const char *nvme_status_to_string(__u32 status) return "SANITIZE_FAILED: The most recent sanitize operation failed and no recovery actions has been successfully completed"; case NVME_SC_SANITIZE_IN_PROGRESS: return "SANITIZE_IN_PROGRESS: The requested function is prohibited while a sanitize operation is in progress"; + case NVME_SC_IOCS_NOT_SUPPORTED: + return "IOCS_NOT_SUPPORTED: The I/O command set is not supported"; + case NVME_SC_IOCS_NOT_ENABLED: + return "IOCS_NOT_ENABLED: The I/O command set is not enabled"; + case NVME_SC_IOCS_COMBINATION_REJECTED: + return "IOCS_COMBINATION_REJECTED: The I/O command set combination is rejected"; + case NVME_SC_INVALID_IOCS: + return "INVALID_IOCS: the I/O command set is invalid"; case NVME_SC_LBA_RANGE: return "LBA_RANGE: The command references a LBA that exceeds the size of the namespace"; case NVME_SC_NS_WRITE_PROTECTED: @@ -4323,6 +4343,11 @@ static void nvme_show_plm_config(struct nvme_plm_config *plmcfg) printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_time_thresh)); } +static void nvme_show_iocs_vector(struct nvme_iocs_vector *iocs_vector) +{ + printf("\tNVM Command Set is selected: %s\n", iocs_vector->nvm ? "True":"False"); +} + void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf) { __u8 field; diff --git a/nvme-print.h b/nvme-print.h index 318f708..6c3a45b 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -53,6 +53,7 @@ void nvme_show_id_ns_granularity_list(const struct nvme_id_ns_granularity_list * enum nvme_print_flags flags); void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, enum nvme_print_flags flags); +void nvme_show_id_iocs(struct nvme_id_iocs *iocs); void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf); void nvme_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 result, diff --git a/nvme.c b/nvme.c index f4b2289..859c04d 100644 --- a/nvme.c +++ b/nvme.c @@ -1749,6 +1749,49 @@ close_fd: return err; } +static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send an Identify Command Set Data command to the "\ + "given device, returns properties of the specified controller "\ + "in either human-readable or binary format."; + const char *controller_id = "identifier of desired controller"; + struct nvme_id_iocs iocs; + int err, fd; + + struct config { + __u16 cntid; + }; + + struct config cfg = { + .cntid = 0xffff, + }; + + OPT_ARGS(opts) = { + OPT_SHRT("controller-id", 'c', &cfg.cntid, controller_id), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) { + err = fd; + goto ret; + } + + err = nvme_identify_iocs(fd, cfg.cntid, &iocs); + if (!err) { + printf("NVMe Identify I/O Command Set:\n"); + nvme_show_id_iocs(&iocs); + } + else if (err > 0) + nvme_show_status(err); + else + perror("NVMe Identify I/O Command Set"); + + close(fd); +ret: + return nvme_status_to_errno(err, false); +} + static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int err = 0, nsid, fd; -- 2.49.0