From: Steven Seungcheol Lee Date: Thu, 6 Jan 2022 07:54:07 +0000 (+0900) Subject: nvme: Add id-ns-lba-format(CNS 09h) command from TP4095 X-Git-Tag: v2.0-rc3~18^2~3 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=5790fec5e868372b1a5d6ad9d80bf0bc4460e14a;p=users%2Fsagi%2Fnvme-cli.git nvme: Add id-ns-lba-format(CNS 09h) command from TP4095 Identify Namespace data structure for the specified User Data Format index containing the namespace capabilities for the NVM Command Set. None capabilities from nvme_id_ns structure are returned as 0 with this command Signed-off-by: Steven Seungcheol Lee --- diff --git a/Documentation/nvme-id-ns-lba-format.1 b/Documentation/nvme-id-ns-lba-format.1 new file mode 100644 index 00000000..cb6c2a94 --- /dev/null +++ b/Documentation/nvme-id-ns-lba-format.1 @@ -0,0 +1,172 @@ +'\" t +.\" Title: nvme-id-ns-lba-format +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 01/07/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-ID\-NS\-LBA\-F" "1" "01/07/2022" "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-ns-lba-format \- Send NVMe Identify Namespace for the specified LBA Format index, display structure +.SH "SYNOPSIS" +.sp +.nf +\fInvme id\-ns\fR [\-\-uuid\-index= | \-U ] + [\-\-lba\-format\-index= | \-i ] + [\-v | \-\-verbose] + [\-\-output\-format= | \-o ] +.fi +.SH "DESCRIPTION" +.sp +For the NVMe device given, sends an identify namespace for the specified LBA Format index command and provides the result that is include capability field only and returned 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)\&. +.sp +On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. +.SH "OPTIONS" +.PP +\-U , \-\-uuid\-index= +.RS 4 +UUID Index of the feature +.RE +.PP +\-i , \-\-lba\-format\-index= +.RS 4 +This field specifies the index into the LBA Format list identifying the LBA Format capabilities that are to be returned +.RE +.PP +\-v, \-\-verbose +.RS 4 +Increase the information detail in the output\&. +.RE +.PP +\-o , \-\-output\-format= +.RS 4 +Set the reporting format to +\fInormal\fR, +\fIjson\fR, or +\fIbinary\fR\&. Only one output format can be used at a time\&. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Has the program interpret the returned buffer and display the known fields in a human readable format: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme id\-ns\-lba\-format /dev/nvme0n1 \-i 0 +.fi +.if n \{\ +.RE +.\} +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Have the program return the raw structure in binary: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme id\-ns\-lba\-format /dev/nvme0n1 \-i 0 \-o binary > id_ns\&.raw +# nvme id\-ns\-lba\-format /dev/nvme0n1 \-i 0 \-\-output\-format=binary > id_ns\&.raw +.fi +.if n \{\ +.RE +.\} +.sp +It is probably a bad idea to not redirect stdout when using this mode\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Alternatively you may want to send the data to another program that can parse the raw buffer\&. +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme id\-ns\-lba\-format /dev/nvme0n1 \-i 0 \-\-raw\-binary | nvme_parse_id_ns +.fi +.if n \{\ +.RE +.\} +.sp +The parse program in the above example can be a program that shows the structure in a way you like\&. The following program is such an example that will parse it and can accept the output through a pipe, +\*(Aq|\*(Aq, as shown in the above example, or you can +\*(Aqcat\*(Aq +a saved output buffer to it\&. +.RE +.sp +.if n \{\ +.RS 4 +.\} +.nf +/* File: nvme_parse_id_ns_lba_format\&.c */ + +#include +#include +#include + +int main(int argc, char **argv) +{ + unsigned char buf[sizeof(struct nvme_id_ns)]; + struct nvme_id_ns *ns = (struct nvme_id_ns *)buf; + + if (read(STDIN_FILENO, buf, sizeof(buf))) + return 1; + + printf("nsze : %#llx\en", ns\->nlbaf); + printf("ncap : %#llx\en", ns\->mc); + return 0; +} +.fi +.if n \{\ +.RE +.\} +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-id-ns-lba-format.html b/Documentation/nvme-id-ns-lba-format.html new file mode 100644 index 00000000..1a4b83ff --- /dev/null +++ b/Documentation/nvme-id-ns-lba-format.html @@ -0,0 +1,901 @@ + + + + + +nvme-id-ns-lba-format(1) + + + + + +
+
+

SYNOPSIS

+
+
+
nvme id-ns <device> [--uuid-index=<uuid-index> | -U <uuid_index>]
+                    [--lba-format-index=<lba_format_index> | -i <lba_format_index>]
+                        [-v | --verbose]
+                        [--output-format=<fmt> | -o <fmt>]
+
+
+
+
+
+

DESCRIPTION

+
+

For the NVMe device given, sends an identify namespace for +the specified LBA Format index command and provides the result +that is include capability field only and returned 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).

+

On success, the structure may be returned in one of several ways depending +on the option flags; the structure may be parsed by the program or the +raw buffer may be printed to stdout.

+
+
+
+

OPTIONS

+
+
+
+-U <uuid-index> +
+
+--uuid-index=<uuid-index> +
+
+

+ UUID Index of the feature +

+
+
+-i <lba_format_index> +
+
+--lba-format-index=<lba_format_index> +
+
+

+ This field specifies the index into the LBA Format list identifying + the LBA Format capabilities that are to be returned +

+
+
+-v +
+
+--verbose +
+
+

+ Increase the information detail in the output. +

+
+
+-o <format> +
+
+--output-format=<format> +
+
+

+ Set the reporting format to normal, json, or + binary. Only one output format can be used at a time. +

+
+
+
+
+
+

EXAMPLES

+
+
    +
  • +

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

    +
    +
    +
    # nvme id-ns-lba-format /dev/nvme0n1 -i 0
    +
    +
  • +
  • +

    +Have the program return the raw structure in binary: +

    +
    +
    +
    # nvme id-ns-lba-format /dev/nvme0n1 -i 0 -o binary > id_ns.raw
    +# nvme id-ns-lba-format /dev/nvme0n1 -i 0 --output-format=binary > id_ns.raw
    +
    +

    It is probably a bad idea to not redirect stdout when using this mode.

    +
  • +
  • +

    +Alternatively you may want to send the data to another program that +can parse the raw buffer. +

    +
    +
    +
    # nvme id-ns-lba-format /dev/nvme0n1 -i 0 --raw-binary | nvme_parse_id_ns
    +
    +

    The parse program in the above example can be a program that shows the +structure in a way you like. The following program is such an example +that will parse it and can accept the output through a pipe, '|', +as shown in the above example, or you can 'cat' a saved output buffer +to it.

    +
  • +
+
+
+
/* File: nvme_parse_id_ns_lba_format.c */
+
+#include <linux/nvme.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+        unsigned char buf[sizeof(struct nvme_id_ns)];
+        struct nvme_id_ns *ns = (struct nvme_id_ns *)buf;
+
+        if (read(STDIN_FILENO, buf, sizeof(buf)))
+                return 1;
+
+        printf("nsze : %#llx\n", ns->nlbaf);
+        printf("ncap : %#llx\n", ns->mc);
+        return 0;
+}
+
+
+
+
+

NVME

+
+

Part of the nvme-user suite

+
+
+
+

+ + + diff --git a/Documentation/nvme-id-ns-lba-format.txt b/Documentation/nvme-id-ns-lba-format.txt new file mode 100644 index 00000000..32df2f61 --- /dev/null +++ b/Documentation/nvme-id-ns-lba-format.txt @@ -0,0 +1,102 @@ +nvme-id-ns-lba-format(1) +======================== + +NAME +---- +nvme-id-ns-lba-format - Send NVMe Identify Namespace for the specified LBA Format index, display structure + +SYNOPSIS +-------- +[verse] +'nvme id-ns' [--uuid-index= | -U ] + [--lba-format-index= | -i ] + [-v | --verbose] + [--output-format= | -o ] + +DESCRIPTION +----------- +For the NVMe device given, sends an identify namespace for +the specified LBA Format index command and provides the result +that is include capability field only and returned structure. + +The parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). + +On success, the structure may be returned in one of several ways depending +on the option flags; the structure may be parsed by the program or the +raw buffer may be printed to stdout. + +OPTIONS +------- +-U :: +--uuid-index=:: + UUID Index of the feature + +-i :: +--lba-format-index=:: + This field specifies the index into the LBA Format list identifying + the LBA Format capabilities that are to be returned + +-v:: +--verbose:: + Increase the information detail in the output. + +-o :: +--output-format=:: + Set the reporting format to 'normal', 'json', or + 'binary'. Only one output format can be used at a time. + +EXAMPLES +-------- +* Has the program interpret the returned buffer and display the known +fields in a human readable format: ++ +------------ +# nvme id-ns-lba-format /dev/nvme0n1 -i 0 +------------ ++ +* Have the program return the raw structure in binary: ++ +------------ +# nvme id-ns-lba-format /dev/nvme0n1 -i 0 -o binary > id_ns.raw +# nvme id-ns-lba-format /dev/nvme0n1 -i 0 --output-format=binary > id_ns.raw +------------ ++ +It is probably a bad idea to not redirect stdout when using this mode. + +* Alternatively you may want to send the data to another program that +can parse the raw buffer. ++ +------------ +# nvme id-ns-lba-format /dev/nvme0n1 -i 0 --raw-binary | nvme_parse_id_ns +------------ ++ +The parse program in the above example can be a program that shows the +structure in a way you like. The following program is such an example +that will parse it and can accept the output through a pipe, `'|'`, +as shown in the above example, or you can `'cat'` a saved output buffer +to it. +------------ +/* File: nvme_parse_id_ns_lba_format.c */ + +#include +#include +#include + +int main(int argc, char **argv) +{ + unsigned char buf[sizeof(struct nvme_id_ns)]; + struct nvme_id_ns *ns = (struct nvme_id_ns *)buf; + + if (read(STDIN_FILENO, buf, sizeof(buf))) + return 1; + + printf("nsze : %#llx\n", ns->nlbaf); + printf("ncap : %#llx\n", ns->mc); + return 0; +} +------------ + +NVME +---- +Part of the nvme-user suite diff --git a/completions/_nvme b/completions/_nvme index b2836158..03398f3a 100644 --- a/completions/_nvme +++ b/completions/_nvme @@ -9,6 +9,7 @@ _nvme () { _cmds=( 'id-ctrl:display information about the controller' 'id-ns:display information about the namespace' + 'id-ns-lba-format:display information about the namespace capability fields for specific LBA format' 'list-ns:identify all namespace(s) attached' 'cmdset-ind-id-ns:display I/O Command Set Independent information about the namespace' 'id-iocs:display information about I/O command sets' @@ -100,6 +101,22 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme id-ns options" _idns ;; + (id-ns-lba-format) + local _idns_lba_format + _idns_lba_format=( + /dev/nvme':supply a device to use (required)' + --lba-format-index=':show infos for lba format index ' + -i':alias of --lba-format-index' + --uuid-index=':uuid index' + -U':alias for --uuid-index' + --output-format=':Output format: normal|json|binary' + -o':alias for --output-format' + --verbose':show infos verbosely' + -v':alias of --verbose' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme id-ns-lba-format options" _idns_lba_format + ;; (list-ns) local _listns _listns=( @@ -914,7 +931,7 @@ _nvme () { resv-report flush compare read write copy show-regs persistent-event-log pred-lat-event-agg-log nvm-id-ctrl endurance-event-agg-log lba-status-log resv-notif-log capacity-mgmt id-domain boot-part-log fid-support-effects-log - supported-log-pages lockdown media-unit-stat-log + supported-log-pages lockdown media-unit-stat-log id-ns-lba-format ) _arguments '*:: :->subcmds' _describe -t commands "help: infos on a specific nvme command, or provide no option to see a synopsis of all nvme commands" _h diff --git a/completions/bash-nvme-completion.sh b/completions/bash-nvme-completion.sh index 469dfb5e..facffb87 100644 --- a/completions/bash-nvme-completion.sh +++ b/completions/bash-nvme-completion.sh @@ -78,6 +78,7 @@ readonly _plugin_funcs=( # Top level commands _cmds="list list-subsys id-ctrl id-ns \ id-ns-granularity list-ns list-ctrl \ + id-ns-lba-format \ nvm-id-ctrl primary-ctrl-caps list-secondary \ ns-descs id-nvmset id-uuid id-iocs create-ns \ delete-ns get-ns-id get-log telemetry-log \ @@ -144,6 +145,10 @@ nvme_list_opts () { "id-ns-granularity") opts+=" --output-format= -o" ;; + "id-ns-lba-format") + opts+=" --lba-format-index= -i --uuid-index= -U \ + --verbose -v --output-format= -o" + ;; "list-ns") opts+=" --namespace-id= -n --al -a --csi= -y \ --outputformat= -o" diff --git a/nvme-builtin.h b/nvme-builtin.h index f64ac24b..89c3c14f 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -12,6 +12,7 @@ COMMAND_LIST( ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl) ENTRY("id-ns", "Send NVMe Identify Namespace, display structure", id_ns) ENTRY("id-ns-granularity", "Send NVMe Identify Namespace Granularity List, display structure", id_ns_granularity) + ENTRY("id-ns-lba-format", "Send NVMe Identify Namespace for the specified LBA Format index, display structure", id_ns_lba_format) ENTRY("list-ns", "Send NVMe Identify List, display structure", list_ns) ENTRY("list-ctrl", "Send NVMe Identify Controller List, display structure", list_ctrl) ENTRY("nvm-id-ctrl", "Send NVMe Identify Controller NVM Command Set, display structure", nvm_id_ctrl) diff --git a/nvme-print.c b/nvme-print.c index 99926675..0da0ba56 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -148,7 +148,7 @@ static const char *get_sanitize_log_sstat_status_str(__u16 status) } } -static void json_nvme_id_ns(struct nvme_id_ns *ns) +static void json_nvme_id_ns(struct nvme_id_ns *ns, bool cap_only) { char nguid_buf[2 * sizeof(ns->nguid) + 1], eui64_buf[2 * sizeof(ns->eui64) + 1]; @@ -161,56 +161,63 @@ static void json_nvme_id_ns(struct nvme_id_ns *ns) root = json_create_object(); - json_object_add_value_uint64(root, "nsze", le64_to_cpu(ns->nsze)); - json_object_add_value_uint64(root, "ncap", le64_to_cpu(ns->ncap)); - json_object_add_value_uint64(root, "nuse", le64_to_cpu(ns->nuse)); - json_object_add_value_int(root, "nsfeat", ns->nsfeat); + if (!cap_only) { + json_object_add_value_uint64(root, "nsze", le64_to_cpu(ns->nsze)); + json_object_add_value_uint64(root, "ncap", le64_to_cpu(ns->ncap)); + json_object_add_value_uint64(root, "nuse", le64_to_cpu(ns->nuse)); + json_object_add_value_int(root, "nsfeat", ns->nsfeat); + } json_object_add_value_int(root, "nlbaf", ns->nlbaf); - json_object_add_value_int(root, "flbas", ns->flbas); + if (!cap_only) + json_object_add_value_int(root, "flbas", ns->flbas); json_object_add_value_int(root, "mc", ns->mc); json_object_add_value_int(root, "dpc", ns->dpc); - json_object_add_value_int(root, "dps", ns->dps); - json_object_add_value_int(root, "nmic", ns->nmic); - json_object_add_value_int(root, "rescap", ns->rescap); - json_object_add_value_int(root, "fpi", ns->fpi); - json_object_add_value_int(root, "dlfeat", ns->dlfeat); - json_object_add_value_int(root, "nawun", le16_to_cpu(ns->nawun)); - json_object_add_value_int(root, "nawupf", le16_to_cpu(ns->nawupf)); - json_object_add_value_int(root, "nacwu", le16_to_cpu(ns->nacwu)); - json_object_add_value_int(root, "nabsn", le16_to_cpu(ns->nabsn)); - json_object_add_value_int(root, "nabo", le16_to_cpu(ns->nabo)); - json_object_add_value_int(root, "nabspf", le16_to_cpu(ns->nabspf)); - json_object_add_value_int(root, "noiob", le16_to_cpu(ns->noiob)); - json_object_add_value_float(root, "nvmcap", nvmcap); - json_object_add_value_int(root, "nsattr", ns->nsattr); - json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid)); + if (!cap_only) { + json_object_add_value_int(root, "dps", ns->dps); + json_object_add_value_int(root, "nmic", ns->nmic); + json_object_add_value_int(root, "rescap", ns->rescap); + json_object_add_value_int(root, "fpi", ns->fpi); + json_object_add_value_int(root, "dlfeat", ns->dlfeat); + json_object_add_value_int(root, "nawun", le16_to_cpu(ns->nawun)); + json_object_add_value_int(root, "nawupf", le16_to_cpu(ns->nawupf)); + json_object_add_value_int(root, "nacwu", le16_to_cpu(ns->nacwu)); + json_object_add_value_int(root, "nabsn", le16_to_cpu(ns->nabsn)); + json_object_add_value_int(root, "nabo", le16_to_cpu(ns->nabo)); + json_object_add_value_int(root, "nabspf", le16_to_cpu(ns->nabspf)); + json_object_add_value_int(root, "noiob", le16_to_cpu(ns->noiob)); + json_object_add_value_float(root, "nvmcap", nvmcap); + json_object_add_value_int(root, "nsattr", ns->nsattr); + json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid)); + + if (ns->nsfeat & 0x10) { + json_object_add_value_int(root, "npwg", le16_to_cpu(ns->npwg)); + json_object_add_value_int(root, "npwa", le16_to_cpu(ns->npwa)); + json_object_add_value_int(root, "npdg", le16_to_cpu(ns->npdg)); + json_object_add_value_int(root, "npda", le16_to_cpu(ns->npda)); + json_object_add_value_int(root, "nows", le16_to_cpu(ns->nows)); + } - if (ns->nsfeat & 0x10) { - json_object_add_value_int(root, "npwg", le16_to_cpu(ns->npwg)); - json_object_add_value_int(root, "npwa", le16_to_cpu(ns->npwa)); - json_object_add_value_int(root, "npdg", le16_to_cpu(ns->npdg)); - json_object_add_value_int(root, "npda", le16_to_cpu(ns->npda)); - json_object_add_value_int(root, "nows", le16_to_cpu(ns->nows)); + json_object_add_value_int(root, "mssrl", le16_to_cpu(ns->mssrl)); + json_object_add_value_int(root, "mcl", le32_to_cpu(ns->mcl)); + json_object_add_value_int(root, "msrc", ns->msrc); } - - json_object_add_value_int(root, "mssrl", le16_to_cpu(ns->mssrl)); - json_object_add_value_int(root, "mcl", le32_to_cpu(ns->mcl)); - json_object_add_value_int(root, "msrc", ns->msrc); json_object_add_value_int(root, "nulbaf", ns->nulbaf); - json_object_add_value_int(root, "anagrpid", le32_to_cpu(ns->anagrpid)); - json_object_add_value_int(root, "endgid", le16_to_cpu(ns->endgid)); + if (!cap_only) { + json_object_add_value_int(root, "anagrpid", le32_to_cpu(ns->anagrpid)); + json_object_add_value_int(root, "endgid", le16_to_cpu(ns->endgid)); - memset(eui64, 0, sizeof(eui64_buf)); - for (i = 0; i < sizeof(ns->eui64); i++) - eui64 += sprintf(eui64, "%02x", ns->eui64[i]); + memset(eui64, 0, sizeof(eui64_buf)); + for (i = 0; i < sizeof(ns->eui64); i++) + eui64 += sprintf(eui64, "%02x", ns->eui64[i]); - memset(nguid, 0, sizeof(nguid_buf)); - for (i = 0; i < sizeof(ns->nguid); i++) - nguid += sprintf(nguid, "%02x", ns->nguid[i]); + memset(nguid, 0, sizeof(nguid_buf)); + for (i = 0; i < sizeof(ns->nguid); i++) + nguid += sprintf(nguid, "%02x", ns->nguid[i]); - json_object_add_value_string(root, "eui64", eui64_buf); - json_object_add_value_string(root, "nguid", nguid_buf); + json_object_add_value_string(root, "eui64", eui64_buf); + json_object_add_value_string(root, "nguid", nguid_buf); + } lbafs = json_create_array(); json_object_add_value_array(root, "lbafs", lbafs); @@ -3780,85 +3787,98 @@ static void nvme_show_id_ns_dlfeat(__u8 dlfeat) } void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, - enum nvme_print_flags flags) + unsigned int lba_index, bool cap_only, enum nvme_print_flags flags) { bool human = flags & VERBOSE; int vs = flags & VS; int i; __u8 flbas; + char *in_use = "(in use)"; if (flags & BINARY) return d_raw((unsigned char *)ns, sizeof(*ns)); if (flags & JSON) - return json_nvme_id_ns(ns); + return json_nvme_id_ns(ns, cap_only); + + if (!cap_only) { + printf("NVME Identify Namespace %d:\n", nsid); + printf("nsze : %#"PRIx64"\n", le64_to_cpu(ns->nsze)); + printf("ncap : %#"PRIx64"\n", le64_to_cpu(ns->ncap)); + printf("nuse : %#"PRIx64"\n", le64_to_cpu(ns->nuse)); + printf("nsfeat : %#x\n", ns->nsfeat); + if (human) + nvme_show_id_ns_nsfeat(ns->nsfeat); + } else + printf("NVMe Identify Namespace for LBA format[%d]:\n", lba_index); - printf("NVME Identify Namespace %d:\n", nsid); - printf("nsze : %#"PRIx64"\n", le64_to_cpu(ns->nsze)); - printf("ncap : %#"PRIx64"\n", le64_to_cpu(ns->ncap)); - printf("nuse : %#"PRIx64"\n", le64_to_cpu(ns->nuse)); - printf("nsfeat : %#x\n", ns->nsfeat); - if (human) - nvme_show_id_ns_nsfeat(ns->nsfeat); printf("nlbaf : %d\n", ns->nlbaf); - printf("flbas : %#x\n", ns->flbas); - if (human) - nvme_show_id_ns_flbas(ns->flbas); + if (!cap_only) { + printf("flbas : %#x\n", ns->flbas); + if (human) + nvme_show_id_ns_flbas(ns->flbas); + } else + in_use = ""; + printf("mc : %#x\n", ns->mc); if (human) nvme_show_id_ns_mc(ns->mc); printf("dpc : %#x\n", ns->dpc); if (human) nvme_show_id_ns_dpc(ns->dpc); - printf("dps : %#x\n", ns->dps); - if (human) - nvme_show_id_ns_dps(ns->dps); - printf("nmic : %#x\n", ns->nmic); - if (human) - nvme_show_id_ns_nmic(ns->nmic); - printf("rescap : %#x\n", ns->rescap); - if (human) - nvme_show_id_ns_rescap(ns->rescap); - printf("fpi : %#x\n", ns->fpi); - if (human) - nvme_show_id_ns_fpi(ns->fpi); - printf("dlfeat : %d\n", ns->dlfeat); - if (human) - nvme_show_id_ns_dlfeat(ns->dlfeat); - printf("nawun : %d\n", le16_to_cpu(ns->nawun)); - printf("nawupf : %d\n", le16_to_cpu(ns->nawupf)); - printf("nacwu : %d\n", le16_to_cpu(ns->nacwu)); - printf("nabsn : %d\n", le16_to_cpu(ns->nabsn)); - printf("nabo : %d\n", le16_to_cpu(ns->nabo)); - printf("nabspf : %d\n", le16_to_cpu(ns->nabspf)); - printf("noiob : %d\n", le16_to_cpu(ns->noiob)); - printf("nvmcap : %.0Lf\n", int128_to_double(ns->nvmcap)); - if (ns->nsfeat & 0x10) { - printf("npwg : %u\n", le16_to_cpu(ns->npwg)); - printf("npwa : %u\n", le16_to_cpu(ns->npwa)); - printf("npdg : %u\n", le16_to_cpu(ns->npdg)); - printf("npda : %u\n", le16_to_cpu(ns->npda)); - printf("nows : %u\n", le16_to_cpu(ns->nows)); - } - printf("mssrl : %u\n", le16_to_cpu(ns->mssrl)); - printf("mcl : %d\n", le32_to_cpu(ns->mcl)); - printf("msrc : %u\n", ns->msrc); + if (!cap_only) { + printf("dps : %#x\n", ns->dps); + if (human) + nvme_show_id_ns_dps(ns->dps); + printf("nmic : %#x\n", ns->nmic); + if (human) + nvme_show_id_ns_nmic(ns->nmic); + printf("rescap : %#x\n", ns->rescap); + if (human) + nvme_show_id_ns_rescap(ns->rescap); + printf("fpi : %#x\n", ns->fpi); + if (human) + nvme_show_id_ns_fpi(ns->fpi); + printf("dlfeat : %d\n", ns->dlfeat); + if (human) + nvme_show_id_ns_dlfeat(ns->dlfeat); + printf("nawun : %d\n", le16_to_cpu(ns->nawun)); + printf("nawupf : %d\n", le16_to_cpu(ns->nawupf)); + printf("nacwu : %d\n", le16_to_cpu(ns->nacwu)); + printf("nabsn : %d\n", le16_to_cpu(ns->nabsn)); + printf("nabo : %d\n", le16_to_cpu(ns->nabo)); + printf("nabspf : %d\n", le16_to_cpu(ns->nabspf)); + printf("noiob : %d\n", le16_to_cpu(ns->noiob)); + printf("nvmcap : %.0Lf\n", int128_to_double(ns->nvmcap)); + if (ns->nsfeat & 0x10) { + printf("npwg : %u\n", le16_to_cpu(ns->npwg)); + printf("npwa : %u\n", le16_to_cpu(ns->npwa)); + printf("npdg : %u\n", le16_to_cpu(ns->npdg)); + printf("npda : %u\n", le16_to_cpu(ns->npda)); + printf("nows : %u\n", le16_to_cpu(ns->nows)); + } + printf("mssrl : %u\n", le16_to_cpu(ns->mssrl)); + printf("mcl : %d\n", le32_to_cpu(ns->mcl)); + printf("msrc : %u\n", ns->msrc); + } printf("nulbaf : %u\n", ns->nulbaf); - printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); - printf("nsattr : %u\n", ns->nsattr); - printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); - printf("endgid : %d\n", le16_to_cpu(ns->endgid)); - - printf("nguid : "); - for (i = 0; i < 16; i++) - printf("%02x", ns->nguid[i]); - printf("\n"); + if (!cap_only) { + printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); + printf("nsattr : %u\n", ns->nsattr); + printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); + printf("endgid : %d\n", le16_to_cpu(ns->endgid)); + + printf("nguid : "); + for (i = 0; i < 16; i++) + printf("%02x", ns->nguid[i]); + printf("\n"); + } printf("eui64 : "); for (i = 0; i < 8; i++) printf("%02x", ns->eui64[i]); printf("\n"); nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); - for (i = 0; i <= ns->nlbaf; i++) { + for (i = 0; i <= ns->nlbaf + ns->nulbaf; i++) { if (human) printf("LBA Format %2d : Metadata Size: %-3d bytes - " "Data Size: %-2d bytes - Relative Performance: %#x %s %s\n", @@ -3867,14 +3887,14 @@ void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, ns->lbaf[i].rp == 3 ? "Degraded" : ns->lbaf[i].rp == 2 ? "Good" : ns->lbaf[i].rp == 1 ? "Better" : "Best", - i == flbas ? "(in use)" : ""); + i == flbas ? in_use : ""); else printf("lbaf %2d : ms:%-3d lbads:%-2d rp:%#x %s\n", i, le16_to_cpu(ns->lbaf[i].ms), ns->lbaf[i].ds, - ns->lbaf[i].rp, i == flbas ? "(in use)" : ""); + ns->lbaf[i].rp, i == flbas ? in_use : ""); } - if (vs) { + if (vs && !cap_only) { printf("vs[]:\n"); d(ns->vs, sizeof(ns->vs), 16, 1); } diff --git a/nvme-print.h b/nvme-print.h index ea2d7e88..073e171e 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -25,7 +25,7 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root)); void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode); void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, - enum nvme_print_flags flags); + unsigned int lba_index, bool cap_only, enum nvme_print_flags flags); void nvme_show_cmd_set_independent_id_ns( struct nvme_id_independent_id_ns *ns, unsigned int nsid, enum nvme_print_flags flags); diff --git a/nvme.c b/nvme.c index d4de5d7f..dbf557b7 100644 --- a/nvme.c +++ b/nvme.c @@ -2010,6 +2010,66 @@ ret: return err; } +static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send an Identify Namespace command to the given "\ + "device, returns capability field properties of the specified "\ + "LBA Format index in various formats."; + const char *lba_format_index = "The index into the LBA Format list "\ + "identifying the LBA Format capabilities that are to be returned"; + const char *uuid_index = "UUID index"; + const char *verbose = "Increase output verbosity"; + enum nvme_print_flags flags; + struct nvme_id_ns ns; + int err = -1, fd; + + struct config { + __u16 lba_format_index; + __u8 uuid_index; + int verbose; + char *output_format; + }; + + struct config cfg = { + .lba_format_index = 0, + .uuid_index = NVME_UUID_NONE, + .verbose = 0, + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_UINT("lba-format-index", 'i', &cfg.lba_format_index, lba_format_index), + OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index), + OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + + if (cfg.verbose) + flags |= VERBOSE; + + err = nvme_identify_ns_csi_user_data_format(fd, cfg.lba_format_index, + cfg.uuid_index, NVME_CSI_NVM, &ns); + if (!err) + nvme_show_id_ns(&ns, 0, cfg.lba_format_index, true, flags); + else if (err > 0) + nvme_show_status(err); + else + perror("identify namespace for specific LBA format"); +close_fd: + close(fd); +ret: + return nvme_status_to_errno(err, false); +} + static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, struct plugin *plugin) { @@ -2729,7 +2789,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug err = nvme_identify_ns(fd, cfg.namespace_id, &ns); if (!err) - nvme_show_id_ns(&ns, cfg.namespace_id, flags); + nvme_show_id_ns(&ns, cfg.namespace_id, 0, false, flags); else if (err > 0) nvme_show_status(err); else