]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: add support for lba status log page
authorGollu Appalanaidu <anaidu.gollu@samsung.com>
Tue, 23 Feb 2021 18:58:45 +0000 (00:28 +0530)
committerKeith Busch <kbusch@kernel.org>
Wed, 24 Feb 2021 15:28:51 +0000 (08:28 -0700)
This log page is used to provide information about
subsequent actions the host may take to discover which
logical blocks, in namespaces that are attached to
the controller, may no longer be recoverable when read.
For more details see NVM Express 1.4 Spec. Section
5.14.1.14("LBA Status Information (Log Identifier 0Eh)")

Signed-off-by: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Co-Authored-By: Karthik Balan <karthik.b82@samsung.com>
12 files changed:
Documentation/nvme-lba-status-log.1 [new file with mode: 0644]
Documentation/nvme-lba-status-log.html [new file with mode: 0644]
Documentation/nvme-lba-status-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-lba-status-log.1 b/Documentation/nvme-lba-status-log.1
new file mode 100644 (file)
index 0000000..6903a3e
--- /dev/null
@@ -0,0 +1,105 @@
+'\" t
+.\"     Title: nvme-lba-status-log
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 02/24/2021
+.\"    Manual: NVMe Manual
+.\"    Source: NVMe
+.\"  Language: English
+.\"
+.TH "NVME\-LBA\-STATUS\-L" "1" "02/24/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-lba-status-log \- Send LBA Status Log Page request returns result and log
+.SH "SYNOPSIS"
+.sp
+.nf
+\fInvme lba\-status\-log\fR <device> [\-\-rae | \-r] [\-\-output\-format=<fmt> | \-o <fmt>]
+.fi
+.SH "DESCRIPTION"
+.sp
+Retrieves the NVMe LBA Status 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 LBA Status Log Page 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 or the raw buffer may be printed to stdout for another program to parse\&.
+.SH "OPTIONS"
+.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 LBA Status Log page in a normal readable format:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme lba\-status\-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
+.\}
+Show the output in json format
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme lba\-status\-log /dev/nvme0 \-o json
++
+
+NVME
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.sp
+Part of the nvme\-user suite
diff --git a/Documentation/nvme-lba-status-log.html b/Documentation/nvme-lba-status-log.html
new file mode 100644 (file)
index 0000000..64cb938
--- /dev/null
@@ -0,0 +1,838 @@
+<?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-lba-status-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-lba-status-log(1) Manual Page\r
+</h1>\r
+<h2>NAME</h2>\r
+<div class="sectionbody">\r
+<p>nvme-lba-status-log -\r
+   Send LBA Status 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 lba-status-log</em> &lt;device&gt; [--rae | -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 LBA Status Log Page from an NVMe device and provides\r
+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 LBA Status Log Page structure may be returned\r
+in one of several ways depending on the option flags; the structure may\r
+parsed by the program and printed in a readable format or the raw buffer\r
+may be printed to stdout for 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
+-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 <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 LBA Status Log page in a normal readable format:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme lba-status-log /dev/nvme0</code></pre>\r
+</div></div>\r
+</li>\r
+<li>\r
+<p>\r
+Show the output in json format\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme lba-status-log /dev/nvme0 -o json\r
++\r
+\r
+NVME</code></pre>\r
+</div></div>\r
+</li>\r
+</ul></div>\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-23 23:41:13 IST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/Documentation/nvme-lba-status-log.txt b/Documentation/nvme-lba-status-log.txt
new file mode 100644 (file)
index 0000000..0d888f7
--- /dev/null
@@ -0,0 +1,54 @@
+nvme-lba-status-log(1)
+======================
+
+NAME
+----
+nvme-lba-status-log - Send LBA Status Log Page request returns result and log
+
+SYNOPSIS
+--------
+[verse]
+'nvme lba-status-log' <device> [--rae | -r] [--output-format=<fmt> | -o <fmt>]
+
+DESCRIPTION
+-----------
+Retrieves the NVMe LBA Status 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 LBA Status Log Page 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 or the raw buffer
+may be printed to stdout for another program to parse.
+
+OPTIONS
+-------
+-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 LBA Status Log page in a normal readable format:
++
+------------
+# nvme lba-status-log /dev/nvme0
+------------
++
+
+* Show the output in json format
++
+------------
+# nvme lba-status-log /dev/nvme0 -o json
++
+
+NVME
+----
+Part of the nvme-user suite
\ No newline at end of file
index 5faabc7cc73aceaa480e72a0393c582697584db3..71c129752cc06bfc44222d01e1c3f8e9c1ee2783 100644 (file)
@@ -27,6 +27,7 @@ _nvme () {
        'smart-log-add:retrieve additional SMART log'
        'error-log:retrieve error log'
        'endurance-event-agg-log:retrieve endurance group event aggregate log'
+       'lba-status-log:retrieve lba status log'
        'get-feature:display a controller feature'
        'set-feature:set a controller feature and show results'
        'format:apply new block format to namespace'
@@ -311,6 +312,16 @@ _nvme () {
                        _arguments '*:: :->subcmds'
                        _describe -t commands "nvme endurance-event-agg-log options" _enduranceeventagglog
                        ;;
+               (lba-status-log)
+                       local _lbastatuslog
+                       _lbastatuslog=(
+                       /dev/nvme':supply a device to use (required)'
+                       --rae': Retain an Asynchronous Event'
+                       -r':alias to --rae
+                       )
+                       _arguments '*:: :->subcmds'
+                       _describe -t commands "nvme lba-status-log options" _lbastatuslog
+                       ;;
                (get-feature)
                        local _getf
                        _getf=(
@@ -767,7 +778,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 endurance-event-agg-log
+                                pred-lat-event-agg-log nvm-id-ctrl endurance-event-agg-log lba-status-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 44bb146831c33cb934180349c4bb5625a374073b..7ab4226a977e3466beb3c6328ead57b1253553e7 100644 (file)
@@ -11,7 +11,8 @@ _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 endurance-event-agg-log"
+       intel lnvm memblaze list-subsys endurance-event-agg-log \
+       lba-status-log"
 
 nvme_list_opts () {
         local opts=""
@@ -104,6 +105,9 @@ nvme_list_opts () {
                opts+=" --log-entries= -e  --rae -r \
                        --raw-binary -b --output-format= -o"
                        ;;
+               "lba-status-log")
+               opts+=" --rae -r --output-format= -o"
+                       ;;
                "get-feature")
                opts+=" --namespace-id= -n --feature-id= -f --sel= -s \
                        --data-len= -l --cdw11= --raw-binary -b \
index a5e5f5f4d09ee25e90ae2ca7880462dd665c16ac..6ff04abb1c1ab3ba6a8f79c99aef8c6acb7c3735 100644 (file)
@@ -911,6 +911,27 @@ struct nvme_predlat_per_nvmset_log_page {
        __u8    rsvd152[360];
 };
 
+struct nvme_lba_status_range_desc {
+       __le64  rslba;
+       __le32  rnlb;
+       __u8    rsvd12[4];
+};
+
+struct nvme_lba_status_ns_element {
+       __le32  neid;
+       __le32  nlrd;
+       __u8    ratype;
+       __u8    rsvd9[7];
+};
+
+struct nvme_lba_status_hdr {
+       __le32  lslplen;
+       __le32  nlslne;
+       __le32  estulb;
+       __u8    rsvd12[2];
+       __le16  lsgc;
+};
+
 enum {
        NVME_SMART_CRIT_SPARE           = 1 << 0,
        NVME_SMART_CRIT_TEMPERATURE     = 1 << 1,
@@ -1213,6 +1234,7 @@ enum {
        NVME_LOG_ANA            = 0x0c,
        NVME_LOG_PRELAT_EVENT_AGG       = 0x0b,
        NVME_LOG_PERSISTENT_EVENT   = 0x0d,
+       NVME_LOG_LBA_STATUS     = 0x0e,
        NVME_LOG_ENDURANCE_GROUP_EVENT_AGG = 0x0f,
        NVME_LOG_DISC           = 0x70,
        NVME_LOG_RESERVATION    = 0x80,
index d84e5f0c1aea0edf70b0c814fccffbd47a74afa9..296afd65969947a14d0a2df4142a11e0eb51dfb9 100644 (file)
@@ -38,6 +38,7 @@ COMMAND_LIST(
        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("lba-status-log", "Retrieve LBA Status Information Log, show it", get_lba_status_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 82ac67abb2ee65bf57efdd2dd246c9e47d966837..8aba0bcb8c342193b9dc8882d1278fd5f5961669 100644 (file)
@@ -627,6 +627,13 @@ int nvme_endurance_group_event_agg_log(int fd,
                        size, endurance_log);
 }
 
+int nvme_lba_status_log(int fd, void *lba_status, bool rae,
+               __u32 size)
+{
+       return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_LBA_STATUS,
+               rae, NVME_NO_LOG_LSP, size, lba_status);
+}
+
 int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11,
                 __u32 cdw12, __u32 data_len, void *data, __u32 *result)
 {
index 585d4b27a329114a2ae00cb718827a8bea6ffc6f..4f13bdcfdd9fac9e97aed951aa9791e5ddb4e466 100644 (file)
@@ -114,7 +114,8 @@ 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);
-
+int nvme_lba_status_log(int fd, void *lba_status, bool rae,
+               __u32 size);
 int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10,
                 __u32 cdw11, __u32 cdw12, __u32 data_len, void *data,
                 __u32 *result);
index c38deacdc235245b075314736f6c28dca59fe907..85429e1162daaf7172ccf31f32856e2167e4efc3 100755 (executable)
@@ -1614,6 +1614,115 @@ void nvme_show_endurance_group_event_agg_log(
        }
 }
 
+void json_lba_status_log(void *lba_status)
+{
+       struct json_object *root;
+       struct json_object *desc;
+       struct json_object *element;
+       struct json_array *desc_list;
+       struct json_array *elements_list;
+       struct nvme_lba_status_hdr *hdr;
+       struct nvme_lba_status_ns_element *ns_element;
+       struct nvme_lba_status_range_desc *range_desc;
+       int offset = sizeof(*hdr);
+       __u32 num_lba_desc, num_elements;
+
+       root = json_create_object();
+       hdr = lba_status;
+       json_object_add_value_uint(root, "lslplen", le32_to_cpu(hdr->lslplen));
+       num_elements = le32_to_cpu(hdr->nlslne);
+       json_object_add_value_uint(root, "nlslne", num_elements);
+       json_object_add_value_uint(root, "estulb", le32_to_cpu(hdr->estulb));
+       json_object_add_value_uint(root, "lsgc", le16_to_cpu(hdr->lsgc));
+
+       elements_list = json_create_array();
+       for (int ele = 0; ele < num_elements; ele++) {
+               ns_element = lba_status + offset;
+               element = json_create_object();
+               json_object_add_value_uint(element, "neid",
+                       le32_to_cpu(ns_element->neid));
+               num_lba_desc = le32_to_cpu(ns_element->nlrd);
+               json_object_add_value_uint(element, "nlrd", num_lba_desc);
+               json_object_add_value_uint(element, "ratype", ns_element->ratype);
+
+               offset += sizeof(*ns_element);
+               desc_list = json_create_array();
+               if (num_lba_desc != 0xffffffff) {
+                       for (int i = 0; i < num_lba_desc; i++) {
+                               range_desc = lba_status + offset;
+                               desc = json_create_object();
+                               json_object_add_value_uint(desc, "rslba",
+                                       le64_to_cpu(range_desc->rslba));
+                               json_object_add_value_uint(desc, "rnlb",
+                                       le32_to_cpu(range_desc->rnlb));
+
+                               offset += sizeof(*range_desc);
+                               json_array_add_value_object(desc_list, desc);
+                       }
+               } else {
+                       printf("Number of LBA Range Descriptors (NLRD) set to %#x for " \
+                               "NS element %d", num_lba_desc, ele);
+               }
+
+               json_object_add_value_array(element, "descs", desc_list);
+               json_array_add_value_object(elements_list, element);
+    }
+
+       json_object_add_value_array(root, "ns_elements", elements_list);
+       json_print_object(root, NULL);
+       printf("\n");
+       json_free_object(root);
+}
+
+void nvme_show_lba_status_log(void *lba_status, __u32 size,
+       const char *devname, enum nvme_print_flags flags)
+{
+       struct nvme_lba_status_hdr *hdr;
+       struct nvme_lba_status_ns_element *ns_element;
+       struct nvme_lba_status_range_desc *range_desc;
+       int offset = sizeof(*hdr);
+       __u32 num_lba_desc, num_elements;
+
+       if (flags & BINARY)
+               return d_raw((unsigned char *)lba_status, size);
+       if (flags & JSON)
+               return json_lba_status_log(lba_status);
+
+       hdr = lba_status;
+       printf("LBA Status Log for device: %s\n", devname);
+       printf("LBA Status Log Page Length: %"PRIu32"\n",
+               le32_to_cpu(hdr->lslplen));
+       num_elements = le32_to_cpu(hdr->nlslne);
+       printf("Number of LBA Status Log Namespace Elements: %"PRIu32"\n",
+               num_elements);
+       printf("Estimate of Unrecoverable Logical Blocks: %"PRIu32"\n",
+               le32_to_cpu(hdr->estulb));
+       printf("LBA Status Generation Counter: %"PRIu16"\n", le16_to_cpu(hdr->lsgc));
+       for (int ele = 0; ele < num_elements; ele++) {
+               ns_element = lba_status + offset;
+               printf("Namespace Element Identifier: %"PRIu32"\n",
+                       le32_to_cpu(ns_element->neid));
+               num_lba_desc = le32_to_cpu(ns_element->nlrd);
+               printf("Number of LBA Range Descriptors: %"PRIu32"\n", num_lba_desc);
+               printf("Recommended Action Type: %u\n", ns_element->ratype);
+
+               offset += sizeof(*ns_element);
+               if (num_lba_desc != 0xffffffff) {
+                       for (int i = 0; i < num_lba_desc; i++) {
+                               range_desc = lba_status + offset;
+                               printf("RSLBA[%d]: %"PRIu64"\n", i,
+                                       le64_to_cpu(range_desc->rslba));
+                               printf("RNLB[%d]: %"PRIu32"\n", i,
+                                       le32_to_cpu(range_desc->rnlb));
+                               offset += sizeof(*range_desc);
+                       }
+               } else {
+                       printf("Number of LBA Range Descriptors (NLRD) set to %#x for "\
+                               "NS element %d\n", num_lba_desc, ele);
+               }
+       }
+}
+
 static void nvme_show_subsystem(struct nvme_subsystem *s)
 {
        int i;
index 636c88c936a1b4755eb383f7f4924a91b1dfd6d0..d6e1e2abe3756966f6aa240249cf18af40a3b425 100644 (file)
@@ -61,6 +61,9 @@ 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 json_lba_status_log(void *lba_status);
+void nvme_show_lba_status_log(void *lba_status, __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 369688396ae624ba5fdcc9dd7a3aa94541b6f0fc..ea5653c4cd8c00fabb440b0e7d15fff7d4b642f9 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -1097,6 +1097,73 @@ ret:
        return nvme_status_to_errno(err, false);
 }
 
+static int get_lba_status_log(int argc, char **argv,
+               struct command *cmd, struct plugin *plugin)
+{
+       const char *desc = "Retrieve Get LBA Status Info Log " \
+                       "and prints it, for the given device in either " \
+                       "decoded format(default),json or binary.";
+       const char *rae = "Retain an Asynchronous Event";
+       void *lab_status;
+       enum nvme_print_flags flags;
+       int err, fd;
+       __u32 lslplen;
+
+       struct config {
+               bool rae;
+               char *output_format;
+       };
+
+       struct config cfg = {
+               .rae = false,
+               .output_format = "normal",
+       };
+
+       OPT_ARGS(opts) = {
+               OPT_FLAG("rae",          'r', &cfg.rae,           rae),
+               OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+               OPT_END()
+       };
+
+       err = fd = parse_and_open(argc, argv, desc, opts);
+       if (fd < 0)
+               goto ret;
+
+       err = flags = validate_output_format(cfg.output_format);
+       if (flags < 0)
+               goto close_fd;
+
+       err = nvme_lba_status_log(fd, &lslplen, true, sizeof(__u32));
+       if (err < 0) {
+               perror("lba status log page");
+               goto close_fd;
+       } else if (err) {
+               nvme_show_status(err);
+               goto close_fd;
+       }
+
+       lab_status = calloc(lslplen, 1);
+       if (!lab_status) {
+               perror("could not alloc buffer for lba status log");
+               err = -ENOMEM;
+               goto close_fd;
+       }
+
+       err = nvme_lba_status_log(fd, lab_status, cfg.rae, lslplen);
+       if (!err)
+               nvme_show_lba_status_log(lab_status, lslplen, devicename, flags);
+       else if (err > 0)
+               nvme_show_status(err);
+       else
+               perror("lba status log page");
+       free(lab_status);
+
+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 "\