From: Gollu Appalanaidu Date: Wed, 13 Jan 2021 16:27:13 +0000 (+0530) Subject: nvme: add support for predictable latency per NVM set log page X-Git-Tag: v1.14~121 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9f98711cc383fd54c4233baf8f182f999ab9ef93;p=users%2Fsagi%2Fnvme-cli.git nvme: add support for predictable latency per NVM set log page This is to add support for LID = 0x0A, Predictable Latency per NVM Set, used to determine the current window for the specified NVM Set when Predictable Latency Mode is enabled and any events that have occurred for the specified NVM Set. For More details see NVM Express 1.4 Spec. Section 5.14.1.10 ("Predictable Latency Per NVM Set (Log Identifier 0Ah)") Signed-off-by: Gollu Appalanaidu Co-Authored-By: Karthik Balan Reviewed-by: Steven Seungcheol Lee --- diff --git a/Documentation/nvme-predictable-lat-log.1 b/Documentation/nvme-predictable-lat-log.1 new file mode 100644 index 00000000..41dd16c7 --- /dev/null +++ b/Documentation/nvme-predictable-lat-log.1 @@ -0,0 +1,112 @@ +'\" t +.\" Title: nvme-predictable-lat-log +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.79.1 +.\" Date: 01/13/2021 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-PREDICTABLE\-L" "1" "01/13/2021" "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-predictable-lat-log \- Send Predectible latency per NVM set log page request, returns result and log +.SH "SYNOPSIS" +.sp +.nf +\fInvme predictable\-lat\-log\fR [\-\-nvmset\-id= | \-i ] + [\-\-raw\-binary | \-b] + [\-\-output\-format= | \-o ] +.fi +.SH "DESCRIPTION" +.sp +Retrieves the NVMe Predectible latency per NVM set log page from an NVMe device and provides the 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 returned Predectible latency per NVM set log structure may be returned in one ofseveral ways depending on the option flags; the structure may parsed by the program and printed in a readable format or the raw buffer may be printed to stdout for another program to parse\&. +.SH "OPTIONS" +.PP +\-i , \-\-nvmset\-id= +.RS 4 +Retrieve the Predectible latency per NVM set log for the given nvmset id\&. This argument is mandatory and its success may depend on the device\(cqs statistics to provide this log For More details see NVM Express 1\&.4 Spec\&. Section 5\&.14\&.1\&.10\&. The default nvmset id to use is 1 for the device\&. +.RE +.PP +\-b, \-\-raw\-binary +.RS 4 +Print the raw Predectible latency per NVM set log buffer to stdout\&. +.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 +.\} +Print the Predectible latency per NVM set log page in a human readable format: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme predictable\-lat\-log /dev/nvme0 +.fi +.if n \{\ +.RE +.\} +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Print the raw Predectible latency per NVM set log to a file: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme predictable\-lat\-log /dev/nvme0 \-\-raw\-binary > nvmset_log\&.raw +.fi +.if n \{\ +.RE +.\} +.sp +It is probably a bad idea to not redirect stdout when using this mode\&. +.RE +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-predictable-lat-log.html b/Documentation/nvme-predictable-lat-log.html new file mode 100644 index 00000000..42dfda8a --- /dev/null +++ b/Documentation/nvme-predictable-lat-log.html @@ -0,0 +1,857 @@ + + + + + + +nvme-predictable-lat-log(1) + + + + + +
+
+

SYNOPSIS

+
+
+
nvme predictable-lat-log <device> [--nvmset-id=<nvmset_id> | -i <nvmset_id>]
+                        [--raw-binary | -b]
+                        [--output-format=<fmt> | -o <fmt>]
+
+
+
+
+
+

DESCRIPTION

+
+

Retrieves the NVMe Predectible latency per NVM set log page from an NVMe device +and provides the 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 returned Predectible latency per NVM set log structure +may be returned in one ofseveral ways depending on the option flags; the +structure may parsed by the program and printed in a readable format or +the raw buffer may be printed to stdout for another program to parse.

+
+
+
+

OPTIONS

+
+
+
+-i <nvmset_id> +
+
+--nvmset-id=<nvmset_id> +
+
+

+ Retrieve the Predectible latency per NVM set log for the given nvmset id. + This argument is mandatory and its success may depend on the device’s + statistics to provide this log For More details see NVM Express 1.4 Spec. + Section 5.14.1.10. The default nvmset id to use is 1 for the device. +

+
+
+-b +
+
+--raw-binary +
+
+

+ Print the raw Predectible latency per NVM set log buffer to stdout. +

+
+
+-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

+
+
    +
  • +

    +Print the Predectible latency per NVM set log page in a human readable format: +

    +
    +
    +
    # nvme predictable-lat-log /dev/nvme0
    +
    +
  • +
  • +

    +Print the raw Predectible latency per NVM set log to a file: +

    +
    +
    +
    # nvme predictable-lat-log /dev/nvme0 --raw-binary > nvmset_log.raw
    +
    +

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

    +
  • +
+
+
+
+

NVME

+
+

Part of the nvme-user suite

+
+
+
+

+ + + diff --git a/Documentation/nvme-predictable-lat-log.txt b/Documentation/nvme-predictable-lat-log.txt new file mode 100644 index 00000000..b4d7335b --- /dev/null +++ b/Documentation/nvme-predictable-lat-log.txt @@ -0,0 +1,66 @@ +nvme-predictable-lat-log(1) +=========================== + +NAME +---- +nvme-predictable-lat-log - Send Predectible latency per NVM set log page request, +returns result and log + +SYNOPSIS +-------- +[verse] +'nvme predictable-lat-log' [--nvmset-id= | -i ] + [--raw-binary | -b] + [--output-format= | -o ] + +DESCRIPTION +----------- +Retrieves the NVMe Predectible latency per NVM set log page from an NVMe device +and provides the 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 returned Predectible latency per NVM set log structure +may be returned in one ofseveral ways depending on the option flags; the +structure may parsed by the program and printed in a readable format or +the raw buffer may be printed to stdout for another program to parse. + +OPTIONS +------- +-i :: +--nvmset-id=:: + Retrieve the Predectible latency per NVM set log for the given nvmset id. + This argument is mandatory and its success may depend on the device's + statistics to provide this log For More details see NVM Express 1.4 Spec. + Section 5.14.1.10. The default nvmset id to use is 1 for the device. + +-b:: +--raw-binary:: + Print the raw Predectible latency per NVM set log buffer to stdout. + +-o :: +--output-format=:: + Set the reporting format to 'normal', 'json', or + 'binary'. Only one output format can be used at a time. + +EXAMPLES +-------- +* Print the Predectible latency per NVM set log page in a human readable format: ++ +------------ +# nvme predictable-lat-log /dev/nvme0 +------------ ++ + +* Print the raw Predectible latency per NVM set log to a file: ++ +------------ +# nvme predictable-lat-log /dev/nvme0 --raw-binary > nvmset_log.raw +------------ ++ +It is probably a bad idea to not redirect stdout when using this mode. + +NVME +---- +Part of the nvme-user suite diff --git a/completions/_nvme b/completions/_nvme index 94ce3fbe..afa5bab8 100644 --- a/completions/_nvme +++ b/completions/_nvme @@ -18,6 +18,7 @@ _nvme () { 'list-ctrl:identify all controller(s) attached' 'get-ns-id:get namespace id of opened block device' 'get-log:retrieve any log in raw format' + 'predictable-lat-log:retrieve predictable latency per nvmset log' 'pred-lat-event-agg-log:retrieve predictable latency event aggregate log' 'persistent-event-log:retrieve presistent event log' 'fw-log:retrieve fw log' @@ -226,6 +227,18 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme pred-lat-event-agg-log options" _predlateventagglog ;; + (predictablelatlog) + local _predictablelatlog + _predictablelatlog=( + /dev/nvme':supply a device to use (required)' + --nvmset-id=': NVM Set Identifier on which log page retrieve info' + -i':alias to --nvmset-id' + --raw-binary':dump infos in binary format' + -b':alias of --raw-binary' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme predictable-lat-log options" _predictablelatlog + ;; (fw-log) local _fwlog _fwlog=( diff --git a/completions/bash-nvme-completion.sh b/completions/bash-nvme-completion.sh index ba87f4b7..d669e9b2 100644 --- a/completions/bash-nvme-completion.sh +++ b/completions/bash-nvme-completion.sh @@ -5,7 +5,7 @@ _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 persistent-event-log \ pred-lat-event-agg-log fw-log smart-log smart-log-add error-log \ - get-feature set-feature format fw-activate \ + predictable-lat-log get-feature set-feature format fw-activate \ fw-download admin-passthru io-passthru security-send \ security-recv resv-acquire resv-register resv-release \ resv-report dsm flush compare read write write-zeroes \ @@ -79,6 +79,10 @@ nvme_list_opts () { opts+=" --log-entries= -e --rae -r \ --raw-binary -b --output-format= -o" ;; + "predictable-lat-log") + opts+=" --nvmset-id= -i --raw-binary -b \ + --output-format= -o" + ;; "fw-log") opts+=" --raw-binary -b --output-format= -o" ;; diff --git a/linux/nvme.h b/linux/nvme.h index deb1f392..025f6380 100644 --- a/linux/nvme.h +++ b/linux/nvme.h @@ -885,6 +885,23 @@ struct nvme_predlat_event_agg_log_page { __le16 entries[]; }; +struct nvme_predlat_per_nvmset_log_page { + __u8 status; + __u8 rsvd1; + __le16 event_type; + __u8 rsvd4[28]; + __le64 dtwin_rtyp; + __le64 dtwin_wtyp; + __le64 dtwin_timemax; + __le64 ndwin_timemin_high; + __le64 ndwin_timemin_low; + __u8 rsvd72[56]; + __le64 dtwin_restimate; + __le64 dtwin_westimate; + __le64 dtwin_testimate; + __u8 rsvd152[360]; +}; + enum { NVME_SMART_CRIT_SPARE = 1 << 0, NVME_SMART_CRIT_TEMPERATURE = 1 << 1, @@ -1183,6 +1200,7 @@ enum { NVME_LOG_TELEMETRY_HOST = 0x07, NVME_LOG_TELEMETRY_CTRL = 0x08, NVME_LOG_ENDURANCE_GROUP = 0x09, + NVME_LOG_PRELAT_PER_NVMSET = 0x0a, NVME_LOG_ANA = 0x0c, NVME_LOG_PRELAT_EVENT_AGG = 0x0b, NVME_LOG_PERSISTENT_EVENT = 0x0d, diff --git a/nvme-builtin.h b/nvme-builtin.h index 15545cf0..59896dc0 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -33,6 +33,7 @@ COMMAND_LIST( ENTRY("error-log", "Retrieve Error Log, show it", get_error_log) ENTRY("effects-log", "Retrieve Command Effects Log, show it", get_effects_log) ENTRY("endurance-log", "Retrieve Endurance Group Log, show it", get_endurance_log) + ENTRY("predictable-lat-log", "Retrieve Predictable Latency per Nvmset Log, show it", get_pred_lat_per_nvmset_log) ENTRY("pred-lat-event-agg-log", "Retrieve Predictable Latency Event Aggregate Log, show it", get_pred_lat_event_agg_log) ENTRY("persistent-event-log", "Retrieve Presistent Event Log, show it", get_persistent_event_log) ENTRY("get-feature", "Get feature and show the resulting value", get_feature) diff --git a/nvme-ioctl.c b/nvme-ioctl.c index 24ba95b5..7e0ec155 100644 --- a/nvme-ioctl.c +++ b/nvme-ioctl.c @@ -614,6 +614,15 @@ int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log) NVME_NO_LOG_LSP, sizeof(*sanitize_log), sanitize_log); } +int nvme_predictable_latency_per_nvmset_log(int fd, + __u16 nvmset_id, + struct nvme_predlat_per_nvmset_log_page *plpns_log) +{ + return nvme_get_log13(fd, NVME_NSID_ALL, + NVME_LOG_PRELAT_PER_NVMSET, 0, 0, nvmset_id, + false, sizeof(*plpns_log), plpns_log); +} + int nvme_predictable_latency_event_agg_log(int fd, void *pea_log, bool rae, __u32 size) { diff --git a/nvme-ioctl.h b/nvme-ioctl.h index e7bf14fc..24eb2eb7 100644 --- a/nvme-ioctl.h +++ b/nvme-ioctl.h @@ -115,6 +115,8 @@ int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo); int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log); int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size); int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log); +int nvme_predictable_latency_per_nvmset_log(int fd, + __u16 nvmset_id, struct nvme_predlat_per_nvmset_log_page *plpns_log); int nvme_predictable_latency_event_agg_log(int fd, void *pea_log, bool rae, __u32 size); int nvme_persistent_event_log(int fd, __u8 action, __u32 size, diff --git a/nvme-print.c b/nvme-print.c index df728e22..e7eac50e 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -866,6 +866,78 @@ static void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, json_free_object(root); } +void json_predictable_latency_per_nvmset( + struct nvme_predlat_per_nvmset_log_page *plpns_log, + __u16 nvmset_id) +{ + struct json_object *root; + + root = json_create_object(); + json_object_add_value_uint(root, "nvmset_id", + le16_to_cpu(nvmset_id)); + json_object_add_value_uint(root, "status", + plpns_log->status); + json_object_add_value_uint(root, "event_type", + le16_to_cpu(plpns_log->event_type)); + json_object_add_value_uint(root, "dtwin_reads_typical", + le64_to_cpu(plpns_log->dtwin_rtyp)); + json_object_add_value_uint(root, "dtwin_writes_typical", + le64_to_cpu(plpns_log->dtwin_wtyp)); + json_object_add_value_uint(root, "dtwin_time_maximum", + le64_to_cpu(plpns_log->dtwin_timemax)); + json_object_add_value_uint(root, "ndwin_time_minimum_high", + le64_to_cpu(plpns_log->ndwin_timemin_high)); + json_object_add_value_uint(root, "ndwin_time_minimum_low", + le64_to_cpu(plpns_log->ndwin_timemin_low)); + json_object_add_value_uint(root, "dtwin_reads_estimate", + le64_to_cpu(plpns_log->dtwin_restimate)); + json_object_add_value_uint(root, "dtwin_writes_estimate", + le64_to_cpu(plpns_log->dtwin_westimate)); + json_object_add_value_uint(root, "dtwin_time_estimate", + le64_to_cpu(plpns_log->dtwin_testimate)); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_predictable_latency_per_nvmset( + struct nvme_predlat_per_nvmset_log_page *plpns_log, + __u16 nvmset_id, const char *devname, + enum nvme_print_flags flags) +{ + if (flags & BINARY) + return d_raw((unsigned char *)plpns_log, + sizeof(*plpns_log)); + if (flags & JSON) + return json_predictable_latency_per_nvmset(plpns_log, + nvmset_id); + + printf("Predictable Latency Per NVM Set Log for device: %s\n", + devname); + printf("Predictable Latency Per NVM Set Log for NVM Set ID: %u\n", + le16_to_cpu(nvmset_id)); + printf("Status: %u\n", plpns_log->status); + printf("Event Type: %u\n", + le16_to_cpu(plpns_log->event_type)); + printf("DTWIN Reads Typical: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_rtyp)); + printf("DTWIN Writes Typical: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_wtyp)); + printf("DTWIN Time Maximum: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_timemax)); + printf("NDWIN Time Minimum High: %"PRIu64" \n", + le64_to_cpu(plpns_log->ndwin_timemin_high)); + printf("NDWIN Time Minimum Low: %"PRIu64"\n", + le64_to_cpu(plpns_log->ndwin_timemin_low)); + printf("DTWIN Reads Estimate: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_restimate)); + printf("DTWIN Writes Estimate: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_westimate)); + printf("DTWIN Time Estimate: %"PRIu64"\n\n\n", + le64_to_cpu(plpns_log->dtwin_testimate)); +} + void json_predictable_latency_event_agg_log( struct nvme_predlat_event_agg_log_page *pea_log, __u64 log_entries) diff --git a/nvme-print.h b/nvme-print.h index ee1223af..368434c5 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -37,6 +37,12 @@ void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log, __u16 group_id, const char *devname, enum nvme_print_flags flags); void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, const char *devname, enum nvme_print_flags flags); +void json_predictable_latency_per_nvmset( + struct nvme_predlat_per_nvmset_log_page *plpns_log, + __u16 nvmset_id); +void nvme_show_predictable_latency_per_nvmset( + struct nvme_predlat_per_nvmset_log_page *plpns_log, + __u16 nvmset_id, const char *devname, enum nvme_print_flags flags); void json_predictable_latency_event_agg_log( struct nvme_predlat_event_agg_log_page *pea_log, __u64 log_entries); diff --git a/nvme.c b/nvme.c index 59555f16..72064e13 100644 --- a/nvme.c +++ b/nvme.c @@ -747,6 +747,62 @@ ret: return nvme_status_to_errno(err, false); } +static int get_pred_lat_per_nvmset_log(int argc, char **argv, + struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Retrieve Predictable latency per nvm set log "\ + "page and prints it for the given device in either decoded " \ + "format(default),json or binary."; + const char *nvmset_id = "NVM Set Identifier"; + const char *raw = "use binary output"; + struct nvme_predlat_per_nvmset_log_page plpns_log; + enum nvme_print_flags flags; + int err, fd; + + struct config { + __u16 nvmset_id; + char *output_format; + int raw_binary; + }; + + struct config cfg = { + .nvmset_id = 1, + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_UINT("nvmset-id", 'i', &cfg.nvmset_id, nvmset_id), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + 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.raw_binary) + flags = BINARY; + + err = nvme_predictable_latency_per_nvmset_log(fd, + cfg.nvmset_id, &plpns_log); + if (!err) + nvme_show_predictable_latency_per_nvmset(&plpns_log, + cfg.nvmset_id, devicename, flags); + else if (err > 0) + nvme_show_status(err); + else + perror("predictable latency per nvm set"); + +close_fd: + close(fd); +ret: + return nvme_status_to_errno(err, false); +} + static int get_pred_lat_event_agg_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) {