]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: add support for predictable latency event aggregate log page
authorGollu Appalanaidu <anaidu.gollu@samsung.com>
Mon, 11 Jan 2021 18:38:14 +0000 (00:08 +0530)
committerKeith Busch <kbusch@kernel.org>
Tue, 12 Jan 2021 22:08:00 +0000 (15:08 -0700)
This is to add support for LID = 0x0B, Predictable Latency Event
Aggregate Log Page, this is used if a Predictable Latency Event has
occurred for a particular NVM Set. For More details see NVM Express
1.4 Spec. Section 5.14.1.11 ("Predictable Latency Event Aggregate Log
Page (Log Identifier 0Bh)")

Max entries supported by this log page are 2044 which is:
(min xfer size (4096B) - size of num of entries(8B))/entry size (2B)
= 2044 entries

Signed-off-by: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Co-Authored-By: Karthik Balan <karthik.b82@samsung.com>
Reviewed-by: Steven Seungcheol Lee <sc108.lee@samsung.com>
12 files changed:
Documentation/nvme-pred-lat-event-agg-log.1 [new file with mode: 0644]
Documentation/nvme-pred-lat-event-agg-log.html [new file with mode: 0644]
Documentation/nvme-pred-lat-event-agg-log.txt [new file with mode: 0644]
completions/_nvme
completions/bash-nvme-completion.sh
linux/nvme.h
nvme-builtin.h
nvme-ioctl.c
nvme-ioctl.h
nvme-print.c
nvme-print.h
nvme.c

diff --git a/Documentation/nvme-pred-lat-event-agg-log.1 b/Documentation/nvme-pred-lat-event-agg-log.1
new file mode 100644 (file)
index 0000000..69785cb
--- /dev/null
@@ -0,0 +1,117 @@
+'\" t
+.\"     Title: nvme-pred-lat-event-agg-log
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 01/12/2021
+.\"    Manual: NVMe Manual
+.\"    Source: NVMe
+.\"  Language: English
+.\"
+.TH "NVME\-PRED\-LAT\-EVE" "1" "01/12/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-pred-lat-event-agg-log \- Send Predictable Latency Event Aggregate Log Page request, returns result and log
+.SH "SYNOPSIS"
+.sp
+.nf
+\fInvme pred\-lat\-event\-agg\-log\fR <device> [\-\-log\-entries=<log_entries> | \-e <log_entries>]
+                        [\-\-rae | \-r] [\-\-raw\-binary | \-b]
+                        [\-\-output\-format=<fmt> | \-o <fmt>]
+.fi
+.SH "DESCRIPTION"
+.sp
+Retrieves the NVMe Predictable Latency Event Aggregate Log Page from an NVMe device and provides the returned structure\&.
+.sp
+The <device> 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 Predictable Latency Event Aggregate Log Page 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
+\-e <log_entries>, \-\-log\-entries=<log_entries>
+.RS 4
+Retrieve the Predictable Latency Event Aggregate Log pending entries\&. 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\&.11\&. The maximum number of log entries supported is 2044 for the device\&.
+.RE
+.PP
+\-r, \-\-rae
+.RS 4
+Retain an Asynchronous Event\&.
+.RE
+.PP
+\-b, \-\-raw\-binary
+.RS 4
+Print the raw Predectible Latency Event Aggregate log buffer to stdout\&.
+.RE
+.PP
+\-o <format>, \-\-output\-format=<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 Predictable Latency Event Aggregate Log page in a human readable format:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme pred\-lat\-event\-agg\-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 Event Aggregate log to a file:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme pred\-lat\-event\-agg\-log /dev/nvme0 \-\-raw\-binary > pred_lat_agg_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-pred-lat-event-agg-log.html b/Documentation/nvme-pred-lat-event-agg-log.html
new file mode 100644 (file)
index 0000000..42c370f
--- /dev/null
@@ -0,0 +1,870 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.10" />\r
+<title>nvme-pred-lat-event-agg-log(1)</title>\r
+<style type="text/css">\r
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
+\r
+/* Default font. */\r
+body {\r
+  font-family: Georgia,serif;\r
+}\r
+\r
+/* Title font. */\r
+h1, h2, h3, h4, h5, h6,\r
+div.title, caption.title,\r
+thead, p.table.header,\r
+#toctitle,\r
+#author, #revnumber, #revdate, #revremark,\r
+#footer {\r
+  font-family: Arial,Helvetica,sans-serif;\r
+}\r
+\r
+body {\r
+  margin: 1em 5% 1em 5%;\r
+}\r
+\r
+a {\r
+  color: blue;\r
+  text-decoration: underline;\r
+}\r
+a:visited {\r
+  color: fuchsia;\r
+}\r
+\r
+em {\r
+  font-style: italic;\r
+  color: navy;\r
+}\r
+\r
+strong {\r
+  font-weight: bold;\r
+  color: #083194;\r
+}\r
+\r
+h1, h2, h3, h4, h5, h6 {\r
+  color: #527bbd;\r
+  margin-top: 1.2em;\r
+  margin-bottom: 0.5em;\r
+  line-height: 1.3;\r
+}\r
+\r
+h1, h2, h3 {\r
+  border-bottom: 2px solid silver;\r
+}\r
+h2 {\r
+  padding-top: 0.5em;\r
+}\r
+h3 {\r
+  float: left;\r
+}\r
+h3 + * {\r
+  clear: left;\r
+}\r
+h5 {\r
+  font-size: 1.0em;\r
+}\r
+\r
+div.sectionbody {\r
+  margin-left: 0;\r
+}\r
+\r
+hr {\r
+  border: 1px solid silver;\r
+}\r
+\r
+p {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0.5em;\r
+}\r
+\r
+ul, ol, li > p {\r
+  margin-top: 0;\r
+}\r
+ul > li     { color: #aaa; }\r
+ul > li > * { color: black; }\r
+\r
+.monospaced, code, pre {\r
+  font-family: "Courier New", Courier, monospace;\r
+  font-size: inherit;\r
+  color: navy;\r
+  padding: 0;\r
+  margin: 0;\r
+}\r
+pre {\r
+  white-space: pre-wrap;\r
+}\r
+\r
+#author {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  font-size: 1.1em;\r
+}\r
+#email {\r
+}\r
+#revnumber, #revdate, #revremark {\r
+}\r
+\r
+#footer {\r
+  font-size: small;\r
+  border-top: 2px solid silver;\r
+  padding-top: 0.5em;\r
+  margin-top: 4.0em;\r
+}\r
+#footer-text {\r
+  float: left;\r
+  padding-bottom: 0.5em;\r
+}\r
+#footer-badges {\r
+  float: right;\r
+  padding-bottom: 0.5em;\r
+}\r
+\r
+#preamble {\r
+  margin-top: 1.5em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.imageblock, div.exampleblock, div.verseblock,\r
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,\r
+div.admonitionblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.admonitionblock {\r
+  margin-top: 2.0em;\r
+  margin-bottom: 2.0em;\r
+  margin-right: 10%;\r
+  color: #606060;\r
+}\r
+\r
+div.content { /* Block element content. */\r
+  padding: 0;\r
+}\r
+\r
+/* Block element titles. */\r
+div.title, caption.title {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  text-align: left;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.5em;\r
+}\r
+div.title + * {\r
+  margin-top: 0;\r
+}\r
+\r
+td div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content + div.title {\r
+  margin-top: 0.0em;\r
+}\r
+\r
+div.sidebarblock > div.content {\r
+  background: #ffffee;\r
+  border: 1px solid #dddddd;\r
+  border-left: 4px solid #f0f0f0;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.listingblock > div.content {\r
+  border: 1px solid #dddddd;\r
+  border-left: 5px solid #f0f0f0;\r
+  background: #f8f8f8;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.quoteblock, div.verseblock {\r
+  padding-left: 1.0em;\r
+  margin-left: 1.0em;\r
+  margin-right: 10%;\r
+  border-left: 5px solid #f0f0f0;\r
+  color: #888;\r
+}\r
+\r
+div.quoteblock > div.attribution {\r
+  padding-top: 0.5em;\r
+  text-align: right;\r
+}\r
+\r
+div.verseblock > pre.content {\r
+  font-family: inherit;\r
+  font-size: inherit;\r
+}\r
+div.verseblock > div.attribution {\r
+  padding-top: 0.75em;\r
+  text-align: left;\r
+}\r
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */\r
+div.verseblock + div.attribution {\r
+  text-align: left;\r
+}\r
+\r
+div.admonitionblock .icon {\r
+  vertical-align: top;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  text-decoration: underline;\r
+  color: #527bbd;\r
+  padding-right: 0.5em;\r
+}\r
+div.admonitionblock td.content {\r
+  padding-left: 0.5em;\r
+  border-left: 3px solid #dddddd;\r
+}\r
+\r
+div.exampleblock > div.content {\r
+  border-left: 3px solid #dddddd;\r
+  padding-left: 0.5em;\r
+}\r
+\r
+div.imageblock div.content { padding-left: 0; }\r
+span.image img { border-style: none; vertical-align: text-bottom; }\r
+a.image:visited { color: white; }\r
+\r
+dl {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+dt {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0;\r
+  font-style: normal;\r
+  color: navy;\r
+}\r
+dd > *:first-child {\r
+  margin-top: 0.1em;\r
+}\r
+\r
+ul, ol {\r
+    list-style-position: outside;\r
+}\r
+ol.arabic {\r
+  list-style-type: decimal;\r
+}\r
+ol.loweralpha {\r
+  list-style-type: lower-alpha;\r
+}\r
+ol.upperalpha {\r
+  list-style-type: upper-alpha;\r
+}\r
+ol.lowerroman {\r
+  list-style-type: lower-roman;\r
+}\r
+ol.upperroman {\r
+  list-style-type: upper-roman;\r
+}\r
+\r
+div.compact ul, div.compact ol,\r
+div.compact p, div.compact p,\r
+div.compact div, div.compact div {\r
+  margin-top: 0.1em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+tfoot {\r
+  font-weight: bold;\r
+}\r
+td > div.verse {\r
+  white-space: pre;\r
+}\r
+\r
+div.hdlist {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+div.hdlist tr {\r
+  padding-bottom: 15px;\r
+}\r
+dt.hdlist1.strong, td.hdlist1.strong {\r
+  font-weight: bold;\r
+}\r
+td.hdlist1 {\r
+  vertical-align: top;\r
+  font-style: normal;\r
+  padding-right: 0.8em;\r
+  color: navy;\r
+}\r
+td.hdlist2 {\r
+  vertical-align: top;\r
+}\r
+div.hdlist.compact tr {\r
+  margin: 0;\r
+  padding-bottom: 0;\r
+}\r
+\r
+.comment {\r
+  background: yellow;\r
+}\r
+\r
+.footnote, .footnoteref {\r
+  font-size: 0.8em;\r
+}\r
+\r
+span.footnote, span.footnoteref {\r
+  vertical-align: super;\r
+}\r
+\r
+#footnotes {\r
+  margin: 20px 0 20px 0;\r
+  padding: 7px 0 0 0;\r
+}\r
+\r
+#footnotes div.footnote {\r
+  margin: 0 0 5px 0;\r
+}\r
+\r
+#footnotes hr {\r
+  border: none;\r
+  border-top: 1px solid silver;\r
+  height: 1px;\r
+  text-align: left;\r
+  margin-left: 0;\r
+  width: 20%;\r
+  min-width: 100px;\r
+}\r
+\r
+div.colist td {\r
+  padding-right: 0.5em;\r
+  padding-bottom: 0.3em;\r
+  vertical-align: top;\r
+}\r
+div.colist td img {\r
+  margin-top: 0.3em;\r
+}\r
+\r
+@media print {\r
+  #footer-badges { display: none; }\r
+}\r
+\r
+#toc {\r
+  margin-bottom: 2.5em;\r
+}\r
+\r
+#toctitle {\r
+  color: #527bbd;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {\r
+  margin-top: 0;\r
+  margin-bottom: 0;\r
+}\r
+div.toclevel2 {\r
+  margin-left: 2em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel3 {\r
+  margin-left: 4em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel4 {\r
+  margin-left: 6em;\r
+  font-size: 0.9em;\r
+}\r
+\r
+span.aqua { color: aqua; }\r
+span.black { color: black; }\r
+span.blue { color: blue; }\r
+span.fuchsia { color: fuchsia; }\r
+span.gray { color: gray; }\r
+span.green { color: green; }\r
+span.lime { color: lime; }\r
+span.maroon { color: maroon; }\r
+span.navy { color: navy; }\r
+span.olive { color: olive; }\r
+span.purple { color: purple; }\r
+span.red { color: red; }\r
+span.silver { color: silver; }\r
+span.teal { color: teal; }\r
+span.white { color: white; }\r
+span.yellow { color: yellow; }\r
+\r
+span.aqua-background { background: aqua; }\r
+span.black-background { background: black; }\r
+span.blue-background { background: blue; }\r
+span.fuchsia-background { background: fuchsia; }\r
+span.gray-background { background: gray; }\r
+span.green-background { background: green; }\r
+span.lime-background { background: lime; }\r
+span.maroon-background { background: maroon; }\r
+span.navy-background { background: navy; }\r
+span.olive-background { background: olive; }\r
+span.purple-background { background: purple; }\r
+span.red-background { background: red; }\r
+span.silver-background { background: silver; }\r
+span.teal-background { background: teal; }\r
+span.white-background { background: white; }\r
+span.yellow-background { background: yellow; }\r
+\r
+span.big { font-size: 2em; }\r
+span.small { font-size: 0.6em; }\r
+\r
+span.underline { text-decoration: underline; }\r
+span.overline { text-decoration: overline; }\r
+span.line-through { text-decoration: line-through; }\r
+\r
+div.unbreakable { page-break-inside: avoid; }\r
+\r
+\r
+/*\r
+ * xhtml11 specific\r
+ *\r
+ * */\r
+\r
+div.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.tableblock > table {\r
+  border: 3px solid #527bbd;\r
+}\r
+thead, p.table.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.table {\r
+  margin-top: 0;\r
+}\r
+/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+div.tableblock > table[frame="void"] {\r
+  border-style: none;\r
+}\r
+div.tableblock > table[frame="hsides"] {\r
+  border-left-style: none;\r
+  border-right-style: none;\r
+}\r
+div.tableblock > table[frame="vsides"] {\r
+  border-top-style: none;\r
+  border-bottom-style: none;\r
+}\r
+\r
+\r
+/*\r
+ * html5 specific\r
+ *\r
+ * */\r
+\r
+table.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+thead, p.tableblock.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.tableblock {\r
+  margin-top: 0;\r
+}\r
+table.tableblock {\r
+  border-width: 3px;\r
+  border-spacing: 0px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+  border-collapse: collapse;\r
+}\r
+th.tableblock, td.tableblock {\r
+  border-width: 1px;\r
+  padding: 4px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+}\r
+\r
+table.tableblock.frame-topbot {\r
+  border-left-style: hidden;\r
+  border-right-style: hidden;\r
+}\r
+table.tableblock.frame-sides {\r
+  border-top-style: hidden;\r
+  border-bottom-style: hidden;\r
+}\r
+table.tableblock.frame-none {\r
+  border-style: hidden;\r
+}\r
+\r
+th.tableblock.halign-left, td.tableblock.halign-left {\r
+  text-align: left;\r
+}\r
+th.tableblock.halign-center, td.tableblock.halign-center {\r
+  text-align: center;\r
+}\r
+th.tableblock.halign-right, td.tableblock.halign-right {\r
+  text-align: right;\r
+}\r
+\r
+th.tableblock.valign-top, td.tableblock.valign-top {\r
+  vertical-align: top;\r
+}\r
+th.tableblock.valign-middle, td.tableblock.valign-middle {\r
+  vertical-align: middle;\r
+}\r
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {\r
+  vertical-align: bottom;\r
+}\r
+\r
+\r
+/*\r
+ * manpage specific\r
+ *\r
+ * */\r
+\r
+body.manpage h1 {\r
+  padding-top: 0.5em;\r
+  padding-bottom: 0.5em;\r
+  border-top: 2px solid silver;\r
+  border-bottom: 2px solid silver;\r
+}\r
+body.manpage h2 {\r
+  border-style: none;\r
+}\r
+body.manpage div.sectionbody {\r
+  margin-left: 3em;\r
+}\r
+\r
+@media print {\r
+  body.manpage div#toc { display: none; }\r
+}\r
+\r
+\r
+</style>\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+var asciidoc = {  // Namespace.\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Table Of Contents generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Author: Mihai Bazon, September 2002\r
+ * http://students.infoiasi.ro/~mishoo\r
+ *\r
+ * Table Of Content generator\r
+ * Version: 0.4\r
+ *\r
+ * Feel free to use this script under the terms of the GNU General Public\r
+ * License, as long as you do not remove or alter this notice.\r
+ */\r
+\r
+ /* modified by Troy D. Hanson, September 2006. License: GPL */\r
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */\r
+\r
+// toclevels = 1..4.\r
+toc: function (toclevels) {\r
+\r
+  function getText(el) {\r
+    var text = "";\r
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.\r
+        text += i.data;\r
+      else if (i.firstChild != null)\r
+        text += getText(i);\r
+    }\r
+    return text;\r
+  }\r
+\r
+  function TocEntry(el, text, toclevel) {\r
+    this.element = el;\r
+    this.text = text;\r
+    this.toclevel = toclevel;\r
+  }\r
+\r
+  function tocEntries(el, toclevels) {\r
+    var result = new Array;\r
+    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');\r
+    // Function that scans the DOM tree for header elements (the DOM2\r
+    // nodeIterator API would be a better technique but not supported by all\r
+    // browsers).\r
+    var iterate = function (el) {\r
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {\r
+          var mo = re.exec(i.tagName);\r
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {\r
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);\r
+          }\r
+          iterate(i);\r
+        }\r
+      }\r
+    }\r
+    iterate(el);\r
+    return result;\r
+  }\r
+\r
+  var toc = document.getElementById("toc");\r
+  if (!toc) {\r
+    return;\r
+  }\r
+\r
+  // Delete existing TOC entries in case we're reloading the TOC.\r
+  var tocEntriesToRemove = [];\r
+  var i;\r
+  for (i = 0; i < toc.childNodes.length; i++) {\r
+    var entry = toc.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div'\r
+     && entry.getAttribute("class")\r
+     && entry.getAttribute("class").match(/^toclevel/))\r
+      tocEntriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < tocEntriesToRemove.length; i++) {\r
+    toc.removeChild(tocEntriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild TOC entries.\r
+  var entries = tocEntries(document.getElementById("content"), toclevels);\r
+  for (var i = 0; i < entries.length; ++i) {\r
+    var entry = entries[i];\r
+    if (entry.element.id == "")\r
+      entry.element.id = "_toc_" + i;\r
+    var a = document.createElement("a");\r
+    a.href = "#" + entry.element.id;\r
+    a.appendChild(document.createTextNode(entry.text));\r
+    var div = document.createElement("div");\r
+    div.appendChild(a);\r
+    div.className = "toclevel" + entry.toclevel;\r
+    toc.appendChild(div);\r
+  }\r
+  if (entries.length == 0)\r
+    toc.parentNode.removeChild(toc);\r
+},\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Footnotes generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Based on footnote generation code from:\r
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html\r
+ */\r
+\r
+footnotes: function () {\r
+  // Delete existing footnote entries in case we're reloading the footnodes.\r
+  var i;\r
+  var noteholder = document.getElementById("footnotes");\r
+  if (!noteholder) {\r
+    return;\r
+  }\r
+  var entriesToRemove = [];\r
+  for (i = 0; i < noteholder.childNodes.length; i++) {\r
+    var entry = noteholder.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")\r
+      entriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < entriesToRemove.length; i++) {\r
+    noteholder.removeChild(entriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild footnote entries.\r
+  var cont = document.getElementById("content");\r
+  var spans = cont.getElementsByTagName("span");\r
+  var refs = {};\r
+  var n = 0;\r
+  for (i=0; i<spans.length; i++) {\r
+    if (spans[i].className == "footnote") {\r
+      n++;\r
+      var note = spans[i].getAttribute("data-note");\r
+      if (!note) {\r
+        // Use [\s\S] in place of . so multi-line matches work.\r
+        // Because JavaScript has no s (dotall) regex flag.\r
+        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];\r
+        spans[i].innerHTML =\r
+          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+        spans[i].setAttribute("data-note", note);\r
+      }\r
+      noteholder.innerHTML +=\r
+        "<div class='footnote' id='_footnote_" + n + "'>" +\r
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +\r
+        n + "</a>. " + note + "</div>";\r
+      var id =spans[i].getAttribute("id");\r
+      if (id != null) refs["#"+id] = n;\r
+    }\r
+  }\r
+  if (n == 0)\r
+    noteholder.parentNode.removeChild(noteholder);\r
+  else {\r
+    // Process footnoterefs.\r
+    for (i=0; i<spans.length; i++) {\r
+      if (spans[i].className == "footnoteref") {\r
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");\r
+        href = href.match(/#.*/)[0];  // Because IE return full URL.\r
+        n = refs[href];\r
+        spans[i].innerHTML =\r
+          "[<a href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+      }\r
+    }\r
+  }\r
+},\r
+\r
+install: function(toclevels) {\r
+  var timerId;\r
+\r
+  function reinstall() {\r
+    asciidoc.footnotes();\r
+    if (toclevels) {\r
+      asciidoc.toc(toclevels);\r
+    }\r
+  }\r
+\r
+  function reinstallAndRemoveTimer() {\r
+    clearInterval(timerId);\r
+    reinstall();\r
+  }\r
+\r
+  timerId = setInterval(reinstall, 500);\r
+  if (document.addEventListener)\r
+    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);\r
+  else\r
+    window.onload = reinstallAndRemoveTimer;\r
+}\r
+\r
+}\r
+asciidoc.install();\r
+/*]]>*/\r
+</script>\r
+</head>\r
+<body class="manpage">\r
+<div id="header">\r
+<h1>\r
+nvme-pred-lat-event-agg-log(1) Manual Page\r
+</h1>\r
+<h2>NAME</h2>\r
+<div class="sectionbody">\r
+<p>nvme-pred-lat-event-agg-log -\r
+   Send Predictable Latency Event Aggregate Log Page request, returns result and log\r
+</p>\r
+</div>\r
+</div>\r
+<div id="content">\r
+<div class="sect1">\r
+<h2 id="_synopsis">SYNOPSIS</h2>\r
+<div class="sectionbody">\r
+<div class="verseblock">\r
+<pre class="content"><em>nvme pred-lat-event-agg-log</em> &lt;device&gt; [--log-entries=&lt;log_entries&gt; | -e &lt;log_entries&gt;]\r
+                        [--rae | -r] [--raw-binary | -b]\r
+                        [--output-format=&lt;fmt&gt; | -o &lt;fmt&gt;]</pre>\r
+<div class="attribution">\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_description">DESCRIPTION</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Retrieves the NVMe Predictable Latency Event Aggregate Log Page from an\r
+NVMe device and provides the returned structure.</p></div>\r
+<div class="paragraph"><p>The &lt;device&gt; parameter is mandatory and may be either the NVMe character\r
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>\r
+<div class="paragraph"><p>On success, the returned Predictable Latency Event Aggregate Log\r
+Page structure may be returned in one ofseveral ways depending on\r
+the option flags; the structure may parsed by the program and printed\r
+in a readable format or the raw buffer may be printed to stdout for\r
+another program to parse.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_options">OPTIONS</h2>\r
+<div class="sectionbody">\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+-e &lt;log_entries&gt;\r
+</dt>\r
+<dt class="hdlist1">\r
+--log-entries=&lt;log_entries&gt;\r
+</dt>\r
+<dd>\r
+<p>\r
+    Retrieve the Predictable Latency Event Aggregate Log pending entries.\r
+    This argument is mandatory and its success may depend on the device&#8217;s\r
+    statistics to provide this log For More details see NVM Express 1.4 Spec.\r
+    Section 5.14.1.11. The maximum number of log entries supported is 2044\r
+    for the device.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-r\r
+</dt>\r
+<dt class="hdlist1">\r
+--rae\r
+</dt>\r
+<dd>\r
+<p>\r
+        Retain an Asynchronous Event.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-b\r
+</dt>\r
+<dt class="hdlist1">\r
+--raw-binary\r
+</dt>\r
+<dd>\r
+<p>\r
+        Print the raw Predectible Latency Event Aggregate log buffer to stdout.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-o &lt;format&gt;\r
+</dt>\r
+<dt class="hdlist1">\r
+--output-format=&lt;format&gt;\r
+</dt>\r
+<dd>\r
+<p>\r
+    Set the reporting format to <em>normal</em>, <em>json</em>, or <em>binary</em>.\r
+    Only one output format can be used at a time.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_examples">EXAMPLES</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Print the Predictable Latency Event Aggregate Log page in a human readable format:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme pred-lat-event-agg-log /dev/nvme0</code></pre>\r
+</div></div>\r
+</li>\r
+<li>\r
+<p>\r
+Print the raw Predectible Latency Event Aggregate log to a file:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme pred-lat-event-agg-log /dev/nvme0 --raw-binary &gt; pred_lat_agg_log.raw</code></pre>\r
+</div></div>\r
+<div class="paragraph"><p>It is probably a bad idea to not redirect stdout when using this mode.</p></div>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_nvme">NVME</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated\r
+ 2021-01-12 00:04:13 IST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/Documentation/nvme-pred-lat-event-agg-log.txt b/Documentation/nvme-pred-lat-event-agg-log.txt
new file mode 100644 (file)
index 0000000..d7d998b
--- /dev/null
@@ -0,0 +1,72 @@
+nvme-pred-lat-event-agg-log(1)
+==============================
+
+NAME
+----
+nvme-pred-lat-event-agg-log - Send Predictable Latency Event Aggregate Log
+Page request, returns result and log
+
+SYNOPSIS
+--------
+[verse]
+'nvme pred-lat-event-agg-log' <device> [--log-entries=<log_entries> | -e <log_entries>]
+                       [--rae | -r] [--raw-binary | -b]
+                       [--output-format=<fmt> | -o <fmt>]
+
+DESCRIPTION
+-----------
+Retrieves the NVMe Predictable Latency Event Aggregate 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 Predictable Latency Event Aggregate Log
+Page 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
+-------
+-e <log_entries>::
+--log-entries=<log_entries>::
+    Retrieve the Predictable Latency Event Aggregate Log pending entries.
+    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.11. The maximum number of log entries supported is 2044
+    for the device.
+
+-r::
+--rae::
+       Retain an Asynchronous Event.
+
+-b::
+--raw-binary::
+       Print the raw Predectible Latency Event Aggregate 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 Predictable Latency Event Aggregate Log page in a human readable format:
++
+------------
+# nvme pred-lat-event-agg-log /dev/nvme0
+------------
++
+
+* Print the raw Predectible Latency Event Aggregate log to a file:
++
+------------
+# nvme pred-lat-event-agg-log /dev/nvme0 --raw-binary > pred_lat_agg_log.raw
+------------
++
+It is probably a bad idea to not redirect stdout when using this mode.
+
+NVME
+----
+Part of the nvme-user suite
index 6030547a08af811dfdb1f0d257b70de2f7d86c51..94ce3fbe7b2637bf3d6e3331ca17928f36611640 100644 (file)
@@ -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'
+       'pred-lat-event-agg-log:retrieve predictable latency event aggregate log'
        'persistent-event-log:retrieve presistent event log'
        'fw-log:retrieve fw log'
        'smart-log:retrieve SMART log'
@@ -211,6 +212,20 @@ _nvme () {
                        _arguments '*:: :->subcmds'
                        _describe -t commands "persistent-event-log options" _persistenteventlog
                        ;;
+               (pred-lat-event-agg-log)
+                       local _predlateventagglog
+                       _predlateventagglog=(
+                       /dev/nvme':supply a device to use (required)'
+                       --log-entries=': Number of pending NVM Set Entries log list'
+                       -e':alias to --log-entries'
+                       --rae': Retain an Asynchronous Event'
+                       -r':alias to --rae
+                       --raw-binary':dump infos in binary format'
+                       -b':alias of --raw-binary'
+                       )
+                       _arguments '*:: :->subcmds'
+                       _describe -t commands "nvme pred-lat-event-agg-log options" _predlateventagglog
+                       ;;
                (fw-log)
                        local _fwlog
                        _fwlog=(
@@ -715,6 +730,7 @@ _nvme () {
                             set-feature format fw-activate fw-download admin-passthru io-passthru
                             security-send security-recv resv-acquire resv-register resv-release
                             resv-report flush compare read write copy show-regs persistent-event-log
+                                pred-lat-event-agg-log
                           )
                        _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
index 4c308975e119f5521c778466126967c8caba839a..ba87f4b776a56062887b59d075ddd37c9bff3977 100644 (file)
@@ -4,7 +4,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 \
-       fw-log smart-log smart-log-add error-log \
+       pred-lat-event-agg-log fw-log smart-log smart-log-add 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 \
@@ -75,6 +75,10 @@ nvme_list_opts () {
                opts+=" --action= -a --log-len= -l \
                        --raw-binary -b --output-format= -o"
                        ;;
+               "pred-lat-event-agg-log")
+               opts+=" --log-entries= -e  --rae -r \
+                       --raw-binary -b --output-format= -o"
+                       ;;
                "fw-log")
                opts+=" --raw-binary -b --output-format= -o"
                        ;;
index ea32c1abacdda88c3faf6788fa2c855428b37f1d..deb1f392b607e765f184c4dbc8e7c0c7bcfabb2f 100644 (file)
@@ -880,6 +880,11 @@ enum nvme_persistent_event_log_actions {
        NVME_PEVENT_LOG_RELEASE_CTX                     = 0x2,
 };
 
+struct nvme_predlat_event_agg_log_page {
+       __le64  num_entries;
+       __le16  entries[];
+};
+
 enum {
        NVME_SMART_CRIT_SPARE           = 1 << 0,
        NVME_SMART_CRIT_TEMPERATURE     = 1 << 1,
@@ -1179,6 +1184,7 @@ enum {
        NVME_LOG_TELEMETRY_CTRL = 0x08,
        NVME_LOG_ENDURANCE_GROUP = 0x09,
        NVME_LOG_ANA            = 0x0c,
+       NVME_LOG_PRELAT_EVENT_AGG       = 0x0b,
        NVME_LOG_PERSISTENT_EVENT   = 0x0d,
        NVME_LOG_DISC           = 0x70,
        NVME_LOG_RESERVATION    = 0x80,
index f2080254062e13b5553d177a57007f6d9dc341ae..15545cf0579d3c8303d89a81c7cce06479869b84 100644 (file)
@@ -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("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)
        ENTRY("device-self-test", "Perform the necessary tests to observe the performance", device_self_test)
index 0b668666c4e36b87722a8ad707b7911d90cbcac5..452168dd29a46284738918555db230b9b535e334 100644 (file)
@@ -613,6 +613,14 @@ 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_event_agg_log(int fd,
+               void *pea_log, bool rae, __u32 size)
+{
+       return nvme_get_log(fd, NVME_NSID_ALL,
+                       NVME_LOG_PRELAT_EVENT_AGG, rae, NVME_NO_LOG_LSP,
+                       size, pea_log);
+}
+
 int nvme_persistent_event_log(int fd, __u8 action, __u32 size,
        void *pevent_log_info)
 {
index 9f422236fe1aef5133b7c6e91acf3eba6f779495..acdcbd2ef69a1144ea05e1b74f6d4dc6aaf37788 100644 (file)
@@ -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_event_agg_log(int fd, void *pea_log,
+               bool rae, __u32 size);
 int nvme_persistent_event_log(int fd, __u8 action, __u32 size,
                void *pevent_log_info);
 int nvme_endurance_log(int fd, __u16 group_id,
index 03fd37f7b8a2f7eed7fa64e027394a3475760775..5db4488202ea987319ee4de041a3f5441a7e4403 100644 (file)
@@ -866,6 +866,63 @@ static void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log,
        json_free_object(root);
 }
 
+void json_predictable_latency_event_agg_log(
+       struct nvme_predlat_event_agg_log_page *pea_log,
+       __u64 log_entries)
+{
+       struct json_object *root;
+       struct json_object *valid_attrs;
+       struct json_array *valid;
+       __u64 num_iter;
+       __u64 num_entries;
+
+       root = json_create_object();
+       num_entries = le64_to_cpu(pea_log->num_entries);
+       json_object_add_value_uint(root, "num_entries_avail",
+               num_entries);
+       valid = json_create_array();
+
+       num_iter = min(num_entries, log_entries);
+       for (int i = 0; i < num_iter; i++) {
+               valid_attrs = json_create_object();
+               json_object_add_value_uint(valid_attrs, "entry",
+                       le16_to_cpu(pea_log->entries[i]));
+               json_array_add_value_object(valid, valid_attrs);
+       }
+       json_object_add_value_array(root, "list_of_entries", valid);
+       json_print_object(root, NULL);
+       printf("\n");
+       json_free_object(root);
+}
+
+void nvme_show_predictable_latency_event_agg_log(
+       struct nvme_predlat_event_agg_log_page *pea_log,
+       __u64 log_entries, __u32 size, const char *devname,
+       enum nvme_print_flags flags)
+{
+       __u64 num_iter;
+       __u64 num_entries;
+
+       if (flags & BINARY)
+               return d_raw((unsigned char *)pea_log, size);
+       if (flags & JSON)
+               return json_predictable_latency_event_agg_log(pea_log,
+                       log_entries);
+
+       num_entries = le64_to_cpu(pea_log->num_entries);
+       printf("Predictable Latency Event Aggregate Log for"\
+               " device: %s\n", devname);
+
+       printf("Number of Entries Available: %llu\n",
+               num_entries);
+
+       num_iter = min(num_entries, log_entries);
+       for (int i = 0; i < num_iter; i++) {
+               printf("Entry[%d]: %u\n", i + 1,
+                       le16_to_cpu(pea_log->entries[i]));
+       }
+}
+
 static const char *nvme_show_nss_hw_error(__u16 error_code)
 {
        switch(error_code) {
index 6e142d4a1537e029dc6d938b7bea020e4490d6c1..ee1223afa40735726b672072aed083f6dac9a99e 100644 (file)
@@ -37,6 +37,13 @@ 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_event_agg_log(
+       struct nvme_predlat_event_agg_log_page *pea_log,
+       __u64 log_entries);
+void nvme_show_predictable_latency_event_agg_log(
+       struct nvme_predlat_event_agg_log_page *pea_log,
+       __u64 log_entries, __u32 size, const char *devname,
+       enum nvme_print_flags flags);
 void json_persistent_event_log(void *pevent_log_info,
        __u32 size, enum nvme_print_flags flags);
 void nvme_show_persistent_event_log(void *pevent_log_info,
diff --git a/nvme.c b/nvme.c
index a86bc464abb3127784d88d47608ad3f29a0d1ac7..a7c9ea18d0dd5516466c989afde6cff5d37004ff 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -737,6 +737,96 @@ 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)
+{
+       const char *desc = "Retrieve Predictable Latency Event" \
+                       "Aggregate Log page and prints it, for the given" \
+                       "device in either decoded format(default)," \
+                       "json or binary.";
+       const char *log_entries = "Number of pending NVM Set" \
+                       "log Entries list";
+       const char *rae = "Retain an Asynchronous Event";
+       const char *raw = "use binary output";
+       void *pea_log;
+       struct nvme_id_ctrl ctrl;
+       enum nvme_print_flags flags;
+       int err, fd;
+       __u32 log_size;
+
+       struct config {
+               __u64 log_entries;
+               bool rae;
+               char *output_format;
+               int raw_binary;
+       };
+
+       struct config cfg = {
+               .log_entries = 2044,
+               .rae = false,
+               .output_format = "normal",
+       };
+
+       OPT_ARGS(opts) = {
+               OPT_UINT("log-entries",  'e', &cfg.log_entries,   log_entries),
+               OPT_FLAG("rae",          'r', &cfg.rae,           rae),
+               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;
+
+       if (!cfg.log_entries) {
+               fprintf(stderr, "non-zero log-entries is required param\n");
+               err = -EINVAL;
+               goto close_fd;
+       }
+
+       err = nvme_identify_ctrl(fd, &ctrl);
+       if (err < 0) {
+               perror("identify controller");
+               goto close_fd;
+       } else if (err) {
+               nvme_show_status(err);
+               goto close_fd;
+       }
+
+       cfg.log_entries = min(cfg.log_entries, le32_to_cpu(ctrl.nsetidmax));
+       log_size = sizeof(__u64) + cfg.log_entries * sizeof(__u16);
+       pea_log = calloc(log_size, 1);
+       if (!pea_log) {
+               fprintf(stderr, "could not alloc buffer for predictable " \
+                       "latency event agggregate log entries\n");
+               err = -ENOMEM;
+               goto close_fd;
+       }
+
+       err = nvme_predictable_latency_event_agg_log(fd, pea_log, cfg.rae,
+               log_size);
+       if (!err)
+               nvme_show_predictable_latency_event_agg_log(pea_log, cfg.log_entries,
+                       log_size, devicename, flags);
+       else if (err > 0)
+               nvme_show_status(err);
+       else
+               perror("predictable latency event gggregate log page");
+       free(pea_log);
+
+close_fd:
+       close(fd);
+ret:
+       return nvme_status_to_errno(err, false);
+}
+
 static int get_persistent_event_log(int argc, char **argv,
                struct command *cmd, struct plugin *plugin)
 {