]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: add support for endurance group event aggregate log
authorGollu Appalanaidu <anaidu.gollu@samsung.com>
Sat, 20 Feb 2021 16:30:09 +0000 (22:00 +0530)
committerKeith Busch <kbusch@kernel.org>
Tue, 23 Feb 2021 15:46:22 +0000 (08:46 -0700)
This log page indicates if an Endurance Group Event has
occurred for a particular Endurance Group, the details of
the particular event are included in the Endurance Group
Information log page for that Group. For details see
NVM Express 1.4 Spec. Section 5.14.1.15 ("Endurance Group
Event Aggregate (Log Identifier 0Fh)")

Signed-off-by: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Co-Authored-By: Karthik Balan <karthik.b82@samsung.com>
12 files changed:
Documentation/nvme-endurance-event-agg-log.1 [new file with mode: 0644]
Documentation/nvme-endurance-event-agg-log.html [new file with mode: 0644]
Documentation/nvme-endurance-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-endurance-event-agg-log.1 b/Documentation/nvme-endurance-event-agg-log.1
new file mode 100644 (file)
index 0000000..b8f3acc
--- /dev/null
@@ -0,0 +1,112 @@
+'\" t
+.\"     Title: nvme-endurance-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: 02/20/2021
+.\"    Manual: NVMe Manual
+.\"    Source: NVMe
+.\"  Language: English
+.\"
+.TH "NVME\-ENDURANCE\-EVE" "1" "02/20/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-endurance-event-agg-log \- Send NVMe Endurance log page request, returns result and log
+.SH "SYNOPSIS"
+.sp
+.nf
+\fInvme endurance\-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 Endurance 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 endurance event agg log structure may be returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format, the raw buffer may be printed to stdout for another program to parse, or reported in json format\&.
+.SH "OPTIONS"
+.PP
+\-e <log_entries>, \-\-log\-entries=<log_entries>
+.RS 4
+Retrieve the Endurance Group 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\&.15\&. The maximum number of log entries supported is 2044 for the device\&.
+.RE
+.PP
+\-r, \-\-rae
+.RS 4
+Retain an Asynchronous Event\&.
+.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 Endurance log page in a human readable format:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme endurance\-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 Endurance log to a file:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme endurance\-event\-agg\-log /dev/nvme0 \-\-output=binary > endurance_event_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-endurance-event-agg-log.html b/Documentation/nvme-endurance-event-agg-log.html
new file mode 100644 (file)
index 0000000..cf7d32a
--- /dev/null
@@ -0,0 +1,858 @@
+<?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-endurance-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-endurance-event-agg-log(1) Manual Page\r
+</h1>\r
+<h2>NAME</h2>\r
+<div class="sectionbody">\r
+<p>nvme-endurance-event-agg-log -\r
+   Send NVMe Endurance 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 endurance-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 Endurance Event Aggregate log page from an NVMe device and\r
+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 endurance event agg log structure may be returned\r
+in one of several ways depending on the option flags; the structure may parsed\r
+by the program and printed in a readable format, the raw buffer may be\r
+printed to stdout for another program to parse, or reported in json format.</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 Endurance Group 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.15. 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
+-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\r
+              <em>binary</em>. 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 Endurance log page in a human readable format:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme endurance-event-agg-log /dev/nvme0</code></pre>\r
+</div></div>\r
+</li>\r
+<li>\r
+<p>\r
+Print the raw Endurance log to a file:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme endurance-event-agg-log /dev/nvme0 --output=binary &gt; endurance_event_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-02-20 21:58:13 IST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/Documentation/nvme-endurance-event-agg-log.txt b/Documentation/nvme-endurance-event-agg-log.txt
new file mode 100644 (file)
index 0000000..69701e3
--- /dev/null
@@ -0,0 +1,66 @@
+nvme-endurance-event-agg-log(1)
+===============================
+
+NAME
+----
+nvme-endurance-event-agg-log - Send NVMe Endurance log page request, returns result and log
+
+SYNOPSIS
+--------
+[verse]
+'nvme endurance-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 Endurance 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 endurance event agg log structure may be returned
+in one of several ways depending on the option flags; the structure may parsed
+by the program and printed in a readable format, the raw buffer may be
+printed to stdout for another program to parse, or reported in json format.
+
+OPTIONS
+-------
+-e <log_entries>::
+--log-entries=<log_entries>::
+    Retrieve the Endurance Group 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.15. The maximum number of log entries supported is 2044
+    for the device.
+
+-r::
+--rae::
+       Retain an Asynchronous Event.
+
+-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 Endurance log page in a human readable format:
++
+------------
+# nvme endurance-event-agg-log /dev/nvme0
+------------
++
+
+* Print the raw Endurance log to a file:
++
+------------
+# nvme endurance-event-agg-log /dev/nvme0 --output=binary > endurance_event_agg_log.raw
+------------
++
+It is probably a bad idea to not redirect stdout when using this mode.
+
+NVME
+----
+Part of the nvme-user suite
\ No newline at end of file
index 8cb67296ac389a826c6290d57a7c83bcb515e43c..5faabc7cc73aceaa480e72a0393c582697584db3 100644 (file)
@@ -26,6 +26,7 @@ _nvme () {
        'smart-log:retrieve SMART log'
        'smart-log-add:retrieve additional SMART log'
        'error-log:retrieve error log'
+       'endurance-event-agg-log:retrieve endurance group event aggregate log'
        'get-feature:display a controller feature'
        'set-feature:set a controller feature and show results'
        'format:apply new block format to namespace'
@@ -296,6 +297,20 @@ _nvme () {
                        _arguments '*:: :->subcmds'
                        _describe -t commands "nvme error-log options" _errlog
                        ;;
+               (endurance-event-agg-log)
+                       local _enduranceeventagglog
+                       _enduranceeventagglog=(
+                       /dev/nvme':supply a device to use (required)'
+                       --log-entries=': Number of Endurance Group Event Agg 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 endurance-event-agg-log options" _enduranceeventagglog
+                       ;;
                (get-feature)
                        local _getf
                        _getf=(
@@ -752,7 +767,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 nvm-id-ctrl
+                                pred-lat-event-agg-log nvm-id-ctrl endurance-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 456db1b3ba19b14321ad228fcc2a7509a77694cc..44bb146831c33cb934180349c4bb5625a374073b 100644 (file)
@@ -11,7 +11,7 @@ _cmds="list id-ctrl id-ns list-ns id-iocs nvm-id-ctrl create-ns delete-ns \
        resv-report dsm flush compare read write write-zeroes \
        write-uncor copy reset subsystem-reset show-regs discover \
        connect-all connect disconnect version help \
-       intel lnvm memblaze list-subsys"
+       intel lnvm memblaze list-subsys endurance-event-agg-log"
 
 nvme_list_opts () {
         local opts=""
@@ -100,6 +100,10 @@ nvme_list_opts () {
                opts+=" --namespace-id= -n --raw-binary -b --log-entries= -e \
                        --output-format= -o"
                        ;;
+               "endurance-event-agg-log")
+               opts+=" --log-entries= -e  --rae -r \
+                       --raw-binary -b --output-format= -o"
+                       ;;
                "get-feature")
                opts+=" --namespace-id= -n --feature-id= -f --sel= -s \
                        --data-len= -l --cdw11= --raw-binary -b \
index 1e5660ee9b4f068cd8f4ede769cdd2ee36ae593a..a5e5f5f4d09ee25e90ae2ca7880462dd665c16ac 100644 (file)
@@ -882,7 +882,14 @@ enum nvme_persistent_event_log_actions {
        NVME_PEVENT_LOG_RELEASE_CTX                     = 0x2,
 };
 
-struct nvme_predlat_event_agg_log_page {
+/**
+ * struct nvme_event_agg_log_page - is common for both
+ * predictable latency event aggregate log and endurance
+ * group event aggregate log
+ * @num_entries: indicates the number of entries in the list.
+ * @entries: indicates NVMSET ID or ENDURANCE Group ID entries
+ */
+struct nvme_event_agg_log_page {
        __le64  num_entries;
        __le16  entries[];
 };
@@ -1206,6 +1213,7 @@ enum {
        NVME_LOG_ANA            = 0x0c,
        NVME_LOG_PRELAT_EVENT_AGG       = 0x0b,
        NVME_LOG_PERSISTENT_EVENT   = 0x0d,
+       NVME_LOG_ENDURANCE_GROUP_EVENT_AGG = 0x0f,
        NVME_LOG_DISC           = 0x70,
        NVME_LOG_RESERVATION    = 0x80,
        NVME_LOG_SANITIZE       = 0x81,
index 3a7c8a255853b59697f59b2e1b20f44cf059e1cb..d84e5f0c1aea0edf70b0c814fccffbd47a74afa9 100644 (file)
@@ -37,6 +37,7 @@ COMMAND_LIST(
        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("endurance-event-agg-log", "Retrieve Endurance Group Event Aggregate Log, show it", get_endurance_event_agg_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)
        ENTRY("self-test-log", "Retrieve the SELF-TEST Log, show it", self_test_log)
index 186f4f354dec4ffb3b510cdbb4619072acef7a1f..82ac67abb2ee65bf57efdd2dd246c9e47d966837 100644 (file)
@@ -619,6 +619,14 @@ int nvme_persistent_event_log(int fd, __u8 action, __u32 size,
                        false, action, size, pevent_log_info);
 }
 
+int nvme_endurance_group_event_agg_log(int fd,
+               void *endurance_log, bool rae, __u32 size)
+{
+       return nvme_get_log(fd, NVME_NSID_ALL,
+                       NVME_LOG_ENDURANCE_GROUP_EVENT_AGG, rae, NVME_NO_LOG_LSP,
+                       size, endurance_log);
+}
+
 int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11,
                 __u32 cdw12, __u32 data_len, void *data, __u32 *result)
 {
index 3e9682f8a3651b3f64883cf18cc72076886a44da..585d4b27a329114a2ae00cb718827a8bea6ffc6f 100644 (file)
@@ -110,6 +110,8 @@ 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_group_event_agg_log(int fd, void *endurance_log,
+               bool rae, __u32 size);
 int nvme_endurance_log(int fd, __u16 group_id,
                       struct nvme_endurance_group_log *endurance_log);
 
index 8340b3253f1a8ce372fe0daa090def66b007b142..c38deacdc235245b075314736f6c28dca59fe907 100755 (executable)
@@ -935,7 +935,7 @@ void nvme_show_predictable_latency_per_nvmset(
 }
 
 void json_predictable_latency_event_agg_log(
-       struct nvme_predlat_event_agg_log_page *pea_log,
+       struct nvme_event_agg_log_page *pea_log,
        __u64 log_entries)
 {
        struct json_object *root;
@@ -964,7 +964,7 @@ void json_predictable_latency_event_agg_log(
 }
 
 void nvme_show_predictable_latency_event_agg_log(
-       struct nvme_predlat_event_agg_log_page *pea_log,
+       struct nvme_event_agg_log_page *pea_log,
        __u64 log_entries, __u32 size, const char *devname,
        enum nvme_print_flags flags)
 {
@@ -1565,6 +1565,55 @@ void nvme_show_persistent_event_log(void *pevent_log_info,
        }
 }
 
+void json_endurance_group_event_agg_log(
+       struct nvme_event_agg_log_page *endurance_log,
+       __u64 log_entries)
+{
+       struct json_object *root;
+       struct json_object *valid_attrs;
+       struct json_array *valid;
+
+       root = json_create_object();
+       json_object_add_value_uint(root, "num_entries_avail",
+               le64_to_cpu(endurance_log->num_entries));
+       valid = json_create_array();
+
+       for (int i = 0; i < log_entries; i++) {
+               valid_attrs = json_create_object();
+               json_object_add_value_uint(valid_attrs, "entry",
+                       le16_to_cpu(endurance_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_endurance_group_event_agg_log(
+       struct nvme_event_agg_log_page *endurance_log,
+       __u64 log_entries, __u32 size, const char *devname,
+       enum nvme_print_flags flags)
+{
+
+       if (flags & BINARY)
+               return d_raw((unsigned char *)endurance_log, size);
+       if (flags & JSON)
+               return json_endurance_group_event_agg_log(endurance_log,
+                       log_entries);
+
+       printf("Endurance Group Event Aggregate Log for"\
+               " device: %s\n", devname);
+
+       printf("Number of Entries Available: %"PRIu64"\n",
+               le64_to_cpu(endurance_log->num_entries));
+
+       for (int i = 0; i < log_entries; i++) {
+               printf("Entry[%d]: %u\n", i + 1,
+                       le16_to_cpu(endurance_log->entries[i]));
+       }
+}
+
 static void nvme_show_subsystem(struct nvme_subsystem *s)
 {
        int i;
index 8a42400c0ebc3ac5a418903a2872be28021da2db..636c88c936a1b4755eb383f7f4924a91b1dfd6d0 100644 (file)
@@ -44,16 +44,23 @@ 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,
+       struct nvme_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,
+       struct nvme_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);
 void nvme_show_persistent_event_log(void *pevent_log_info,
        __u8 action, __u32 size, const char *devname,
        enum nvme_print_flags flags);
+void json_endurance_group_event_agg_log(
+       struct nvme_event_agg_log_page *endurance_log,
+       __u64 log_entries);
+void nvme_show_endurance_group_event_agg_log(
+       struct nvme_event_agg_log_page *endurance_log,
+       __u64 log_entries, __u32 size, const char *devname,
+       enum nvme_print_flags flags);
 void nvme_show_ctrl_registers(void *bar, bool fabrics, enum nvme_print_flags flags);
 void nvme_show_single_property(int offset, uint64_t prop, int human);
 void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flags);
diff --git a/nvme.c b/nvme.c
index b4f40c6bb411f4d4501d58baaa4d5f306f043588..369688396ae624ba5fdcc9dd7a3aa94541b6f0fc 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -1006,6 +1006,97 @@ ret:
        return nvme_status_to_errno(err, false);
 }
 
+static int get_endurance_event_agg_log(int argc, char **argv,
+               struct command *cmd, struct plugin *plugin)
+{
+       const char *desc = "Retrieve Retrieve Predictable Latency " \
+                       "Event Aggregate page and prints it, for the given " \
+                       "device in either decoded format(default), " \
+                       "json or binary.";
+       const char *log_entries = "Number of pending Endurance Group " \
+                       "Event log Entries list";
+       const char *rae = "Retain an Asynchronous Event";
+       const char *raw = "use binary output";
+       void *endurance_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) {
+               fprintf(stderr, "could not identify controller\n");
+               err = -ENODEV;
+               goto close_fd;
+       }
+
+       cfg.log_entries = min(cfg.log_entries, le16_to_cpu(ctrl.endgidmax));
+       log_size = sizeof(__u64) + cfg.log_entries * sizeof(__u16);
+       endurance_log = calloc(log_size, 1);
+       if (!endurance_log) {
+               fprintf(stderr, "could not alloc buffer for endurance group" \
+                       " event agggregate log entries\n");
+               err = -ENOMEM;
+               goto close_fd;
+       }
+
+       err = nvme_endurance_group_event_agg_log(fd, endurance_log, cfg.rae,
+               log_size);
+       if (!err)
+               nvme_show_endurance_group_event_agg_log(endurance_log, cfg.log_entries,
+                       log_size, devicename, flags);
+       else if (err > 0)
+               nvme_show_status(err);
+       else
+               perror("endurance group event aggregate log page");
+       free(endurance_log);
+
+close_fd:
+       close(fd);
+ret:
+       return nvme_status_to_errno(err, false);
+}
+
 static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
        const char *desc = "Retrieve desired number of bytes "\