pax_global_header00006660000000000000000000000064132231742360014515gustar00rootroot0000000000000052 comment=121dc80e99ff6e90fb79d57f6ca81527b73364fa nvme-cli-1.5/000077500000000000000000000000001322317423600130745ustar00rootroot00000000000000nvme-cli-1.5/.gitignore000066400000000000000000000002121322317423600150570ustar00rootroot00000000000000nvme *.xml a.out *.o *~ *.swp NVME-VERSION-FILE /debian/files /debian/nvme-cli.debhelper.log /debian/nvme-cli.substvars /debian/nvme-cli nvme-cli-1.5/CONTRIBUTING.md000066400000000000000000000014671322317423600153350ustar00rootroot00000000000000# Contributing to the NVM-e CLI Here you will find instructions on how to contribute to the NVM-Express command line interface. Contributions and new ideas are most welcome! **NOTE: If you do decide to implement code changes and contribute them, please make sure you agree your contribution can be made available under the [GPLv2-style License used for the NVMe CLI](https://github.com/linux-nvme/nvme-cli/blob/master/LICENSE).** ### Code Contributions Please feel free to use the github forums to ask for comments & questions on your code before submitting a pull request. The NVMe CLI project uses the common *fork and merge* workflow used by most GitHub-hosted projects. ### Bug Reports Bugs for the NVM Library project are tracked in our [GitHub Issues Database](https://github.com/linux-nvme/nvme-cli/issues). nvme-cli-1.5/Documentation/000077500000000000000000000000001322317423600157055ustar00rootroot00000000000000nvme-cli-1.5/Documentation/Makefile000066400000000000000000000132351322317423600173510ustar00rootroot00000000000000# Guard against environment variables MAN1_TXT = TECH_DOCS = ARTICLES = SP_ARTICLES = MAN1_TXT += $(filter-out \ $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ $(wildcard nvme-*.txt)) MAN1_TXT += nvme.txt MAN_TXT = $(MAN1_TXT) MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT)) MAN_HTML = $(patsubst %.txt,%.html,$(MAN_TXT)) DOC_HTML = $(MAN_HTML) $(OBSOLETE_HTML) API_DOCS = SP_ARTICLES += $(API_DOCS) SP_ARTICLES += $(TECH_DOCS) DOC_MAN1 = $(patsubst %.txt,%.1,$(MAN1_TXT)) ASCIIDOC = asciidoc ASCIIDOC_EXTRA = ASCIIDOC_DOCBOOK = docbook ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) TXT_TO_XML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_DOCBOOK) MANPAGE_XSL = manpage-normal.xsl XMLTO = xmlto XMLTO_EXTRA = INSTALL ?= install RM ?= rm -f MAN_REPO = ../../nvme-manpages ASCIIDOC_HTML = xhtml11 ASCIIDOC_CONF = -f asciidoc.conf ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) $(ASCIIDOC_CONF) TXT_TO_HTML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_HTML) MAKEINFO = makeinfo INSTALL_INFO = install-info DOCBOOK2X_TEXI = docbook2x-texi DBLATEX = dblatex ASCIIDOC_DBLATEX_DIR = /etc/asciidoc/dblatex ifndef PERL_PATH PERL_PATH = /usr/bin/perl endif ifdef DOCBOOK_XSL_172 MANPAGE_XSL = manpage-1.72.xsl else ifndef ASCIIDOC_ROFF endif endif ifdef MAN_BOLD_LITERAL XMLTO_EXTRA += -m manpage-bold-literal.xsl endif ifdef DOCBOOK_SUPPRESS_SP XMLTO_EXTRA += -m manpage-suppress-sp.xsl endif ifndef MAN_BASE_URL MAN_BASE_URL = file://$(htmldir)/ endif XMLTO_EXTRA += ifdef GNU_ROFF XMLTO_EXTRA += endif SHELL_PATH ?= $(SHELL) # Shell quote; SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) ifdef DEFAULT_PAGER DEFAULT_PAGER_SQ = $(subst ','\'',$(DEFAULT_PAGER)) endif ifdef DEFAULT_EDITOR DEFAULT_EDITOR_SQ = $(subst ','\'',$(DEFAULT_EDITOR)) endif QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir QUIET_SUBDIR1 = ifneq ($(findstring $(MAKEFLAGS),w),w) PRINT_DIR = --no-print-directory else # "make -w" NO_SUBDIR = : endif DESTDIR = PREFIX ?= /usr/local all: man html html: $(DOC_HTML) man: man1 man1: $(DOC_MAN1) install-no-build: $(INSTALL) -d -m 755 $(DESTDIR)$(PREFIX)/share/man/man1 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(PREFIX)/share/man/man1 install: install-man install-man: man $(INSTALL) -d -m 755 $(DESTDIR)$(PREFIX)/share/man/man1 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(PREFIX)/share/man/man1 docdep_prereqs = \ cmd-list.made $(cmds_txt) doc.dep : $(docdep_prereqs) $(wildcard *.txt) build-docdep.perl $(QUIET_GEN)$(RM) $@+ $@ && \ $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \ mv $@+ $@ -include doc.dep cmds_txt = cmds-ancillaryinterrogators.txt \ cmds-ancillarymanipulators.txt \ cmds-mainporcelain.txt \ cmds-plumbinginterrogators.txt \ cmds-plumbingmanipulators.txt \ cmds-synchingrepositories.txt \ cmds-synchelpers.txt \ cmds-purehelpers.txt \ cmds-foreignscminterface.txt $(cmds_txt): cmd-list.made cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) $(QUIET_GEN)$(RM) $@ && \ $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \ date >$@ clean: $(RM) *.xml *.xml+ *.html+ $(RM) *.texi *.texi+ *.texi++ nvme.info nvmeman.info $(RM) *.pdf $(RM) howto-index.txt howto/*.html doc.dep $(RM) technical/*.html technical/api-index.txt $(RM) $(cmds_txt) *.made $(RM) manpage-base-url.xsl $(RM) *~ clobber: clean $(RM) *.html *.1 %.1 : %.xml $(QUIET_XMLTO)$(RM) $@ && \ $(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< %.xml : %.txt $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ $(TXT_TO_XML) -d manpage -o $@+ $< && \ mv $@+ $@ user-manual.xml: user-manual.txt user-manual.conf $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ $(TXT_TO_XML) -d article -o $@+ $< && \ mv $@+ $@ technical/api-index.txt: technical/api-index-skel.txt \ technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS)) $(QUIET_GEN)cd technical && '$(SHELL_PATH_SQ)' ./api-index.sh XSLT = docbook.xsl XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css nvme.info: user-manual.texi $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi user-manual.texi: user-manual.xml $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \ $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \ rm $@++ && \ mv $@+ $@ user-manual.pdf: user-manual.xml $(QUIET_DBLATEX)$(RM) $@+ $@ && \ $(DBLATEX) -o $@+ -p $(ASCIIDOC_DBLATEX_DIR)/asciidoc-dblatex.xsl -s $(ASCIIDOC_DBLATEX_DIR)/asciidoc-dblatex.sty $< && \ mv $@+ $@ nvmeman.texi: $(MAN_XML) cat-texi.perl $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \ --to-stdout $(xml) &&) true) > $@++ && \ $(PERL_PATH) cat-texi.perl $@ <$@++ >$@+ && \ rm $@++ && \ mv $@+ $@ nvmeman.info: nvmeman.texi $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ $(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \ mv $@+ $@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt) $(QUIET_GEN)$(RM) $@+ $@ && \ '$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(wildcard howto/*.txt)) >$@+ && \ mv $@+ $@ WEBDOC_DEST = /pub/software/scm/nvme/docs $(MAN_HTML): %.html : %.txt $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ $(TXT_TO_HTML) -d manpage -o $@+ $< && \ mv $@+ $@ quick-install: quick-install-man $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt install-webdoc : html '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST) require-manrepo:: @if test ! -d $(MAN_REPO); \ then echo "nvme-manpages repository must exist at $(MAN_REPO)"; exit 1; fi quick-install-man: require-manrepo '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(MAN_REPO) $(DESTDIR)$(mandir) print-man1: @for i in $(MAN1_TXT); do echo $$i; done .PHONY: FORCE nvme-cli-1.5/Documentation/asciidoc.conf000066400000000000000000000043371322317423600203410ustar00rootroot00000000000000## linknvme: macro # # Usage: linknvme:command[manpage-section] # # Note, {0} is the manpage section, while {target} is the command. # # Show Git link as: (
); if section is defined, else just show # the command. [macros] (?su)[\\]?(?Plinknvme):(?P\S*?)\[(?P.*?)\]= [attributes] asterisk=* plus=+ caret=^ startsb=[ endsb=] backslash=\ tilde=~ apostrophe=' backtick=` litdd=-- ifdef::backend-docbook[] [linknvme-inlinemacro] {0%{target}} {0#} {0#{target}{0}} {0#} endif::backend-docbook[] ifdef::backend-docbook[] ifndef::git-asciidoc-no-roff[] # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. # v1.72 breaks with this because it replaces dots not in roff requests. [listingblock] {title} | {title#} endif::git-asciidoc-no-roff[] ifdef::git-asciidoc-no-roff[] ifdef::doctype-manpage[] # The following two small workarounds insert a simple paragraph after screen [listingblock] {title} | {title#} [verseblock] {title} {title%} {title#} | {title#} {title%} endif::doctype-manpage[] endif::git-asciidoc-no-roff[] endif::backend-docbook[] ifdef::doctype-manpage[] ifdef::backend-docbook[] [header] template::[header-declarations] {mantitle} {manvolnum} NVMe {nvme_version} NVMe Manual {manname} {manpurpose} endif::backend-docbook[] endif::doctype-manpage[] ifdef::backend-xhtml11[] [attributes] git-relative-html-prefix= [linknvme-inlinemacro] {target}{0?({0})} endif::backend-xhtml11[] nvme-cli-1.5/Documentation/cmds-main.txt000066400000000000000000000040031322317423600203130ustar00rootroot00000000000000linknvme:nvme-admin-passthru[1]:: Admin Passthrough Command linknvme:nvme-compare[1]:: IO Compare linknvme:nvme-error-log[1]:: Retrieve error logs linknvme:nvme-flush[1]:: Submit flush linknvme:nvme-dms[1]:: Submit Data Set Management linknvme:nvme-format[1]:: Format namespace(s) linknvme:nvme-fw-activate[1]:: F/W Activate linknvme:nvme-fw-download[1]:: F/W Download linknvme:nvme-fw-log[1]:: Retrieve f/w log linknvme:nvme-get-feature[1]:: Get Features linknvme:nvme-get-log[1]:: Generic Get Log linknvme:nvme-smart-log[1]:: Retrieve Smart Log linknvme:nvme-get-ns-id[1]:: Retrieve namespace identifier linknvme:nvme-help[1]:: NVMe CLI Help linknvme:nvme-id-ctrl[1]:: Identify Controller linknvme:nvme-id-ns[1]:: Identify Namespace linknvme:nvme-create-ns[1]:: Create a new namespace linknvme:nvme-delete-ns[1]:: Delete existing namespace linknvme:nvme-attach-ns[1]:: Attach namespace linknvme:nvme-detach-ns[1]:: Detach namespace linknvme:nvme-io-passthru[1]:: IO Passthrough Command linknvme:nvme-list-ns[1]:: List all nvme namespaces linknvme:nvme-list[1]:: List all nvme controllers linknvme:nvme-list-ctrl[1]:: List controller in NVMe subsystem linknvme:nvme-read[1]:: Issue IO Read Command linknvme:nvme-write[1]:: Issue IO Write Command linknvme:nvme-write-zeroes[1]:: Issue IO Write Zeroes Command linknvme:nvme-write-uncor[1]:: Issue IO Write Uncorrectable Command linknvme:nvme-resv-acquire[1]:: Acquire Namespace Reservation linknvme:nvme-resv-register[1]:: Register Namespace Reservation linknvme:nvme-resv-release[1]:: Release Namespace Reservation linknvme:nvme-resv-report[1]:: Report Reservation Capabilities linknvme:nvme-security-recv[1]:: Security Receive linknvme:nvme-security-send[1]:: Security Send linknvme:nvme-set-feature[1]:: Set Feature linknvme:nvme-show-regs[1]:: Show NVMe Controller Registers linknvme:nvme-discover[1]:: Send Get Log Page request to Discovery Controller linknvme:nvme-connect[1]:: Connect to an NVMe-over-Fabrics subsystem nvme-cli-1.5/Documentation/install-webdoc.sh000077500000000000000000000013651322317423600211600ustar00rootroot00000000000000#!/bin/sh T="$1" for h in \ *.txt *.html \ howto/*.txt howto/*.html \ technical/*.txt technical/*.html \ RelNotes/*.txt *.css do if test ! -f "$h" then : did not match elif test -f "$T/$h" && $DIFF -u -I'^Last updated ' "$T/$h" "$h" then :; # up to date else echo >&2 "# install $h $T/$h" rm -f "$T/$h" mkdir -p $(dirname "$T/$h") cp "$h" "$T/$h" fi done strip_leading=$(echo "$T/" | sed -e 's|.|.|g') for th in \ "$T"/*.html "$T"/*.txt \ "$T"/howto/*.txt "$T"/howto/*.html \ "$T"/technical/*.txt "$T"/technical/*.html do h=$(expr "$th" : "$strip_leading"'\(.*\)') case "$h" in RelNotes-*.txt | index.html) continue ;; esac test -f "$h" && continue echo >&2 "# rm -f $th" rm -f "$th" done ln -sf git.html "$T/index.html" nvme-cli-1.5/Documentation/manpage-base.xsl000066400000000000000000000022601322317423600207550ustar00rootroot00000000000000 sp br nvme-cli-1.5/Documentation/manpage-normal.xsl000066400000000000000000000007351322317423600213400ustar00rootroot00000000000000 \ . nvme-cli-1.5/Documentation/nvme-admin-passthru.1000066400000000000000000000124361322317423600216770ustar00rootroot00000000000000'\" t .\" Title: nvme-admin-passthru .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ADMIN\-PASSTHR" "1" "12/10/2017" "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-admin-passthru \- Submit an arbitrary admin command, return results .SH "SYNOPSIS" .sp .nf \fInvme\-admin\-passthru\fR [\-\-opcode= | \-o ] [\-\-flags= | \-f ] [\-rsvd= | \-R ] [\-\-namespace\-id=] [\-\-cdw2=] [\-\-cdw3=] [\-\-cdw10=] [\-\-cdw11=] [\-\-cdw12=] [\-\-cdw13=] [\-\-cdw14=] [\-\-cdw15=] [\-\-data\-len= | \-l ] [\-\-metadata\-len= | \-m ] [\-\-input\-file= | \-f ] [\-\-read | \-r ] [\-\-write | \-w] [\-\-timeout= | \-t ] [\-\-show\-command | \-\-dry\-run | \-s] [\-\-raw\-binary | \-b] [\-\-prefill= | \-p ] .fi .SH "DESCRIPTION" .sp Submits an arbitrary NVMe admin command and returns the applicable results\&. This may be the simply the commands result and status, or may also include a buffer if the command returns one\&. This command does no interpretation of the opcodes or options\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned structure (if applicable) may be returned in one of several ways depending on the option flags; the structure may printed by the program as a hex dump, or may be returned as a raw buffer printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-o , \-\-opcode= .RS 4 The NVMe opcode to send to the device in the command .RE .PP \-f , \-\-flags= .RS 4 The NVMe command flags to send to the device in the command .RE .PP \-R , \-\-rsvd= .RS 4 The value for the reserved field in the command\&. .RE .PP \-n , \-\-namespace\-id= .RS 4 The value for the ns\-id in the command\&. .RE .PP \-\-cdw[2\-3,10\-15]= .RS 4 Specifies the command dword value for that specified entry in the command .RE .PP \-r, \-\-read, \-w, \-\-write .RS 4 Used for the data\-direction for the command and required for commands sending/receiving data\&. Don\(cqt use both read and write at the same time\&. .RE .PP \-i , \-\-input\-file= .RS 4 If the command is a data\-out (write) command, use this file to fill the buffer sent to the device\&. If no file is given, assumed to use STDIN\&. .RE .PP \-l , \-\-data\-len= .RS 4 The data length for the buffer used for this command\&. .RE .PP \-m , \-\-metadata\-len= .RS 4 The metadata length for the buffer used for this command\&. .RE .PP \-s, \-\-show\-cmd, \-\-dry\-run .RS 4 Do not actually send the command; print out the command that would be sent\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw returned buffer to stdout if the command returns a structure\&. .RE .PP \-p, \-\-prefill .RS 4 Prefill the buffer with a predetermined byte value\&. Defaults to 0\&. This may be useful if the data you are writing is shorter than the required buffer, and you need to pad it with a known value\&. It may also be useful if you need to confirm if a device is overwriting a buffer for a data\-in command\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} The following will run the admin command with opcode=6 and cdw10=1, which corresponds to an identify controller command\&. This example requires the data\-len param be 4096, which is the size of the returned structure\&. The \-r option is used because it is a data\-in command .sp .if n \{\ .RS 4 .\} .nf # nvme admin\-passthru /dev/nvme0 \-\-opcode=06 \-\-data\-len=4096 \-\-cdw10=1 \-r .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Or if you want to save that structure to a file: .sp .if n \{\ .RS 4 .\} .nf # nvme admin\-passthru /dev/nvme0 \-\-opcode=06 \-\-data\-len=4096 \-\-cdw10=1 \-r \-b > id_ns\&.raw .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-admin-passthru.html000066400000000000000000000540411322317423600225010ustar00rootroot00000000000000 nvme-admin-passthru(1)

SYNOPSIS

nvme-admin-passthru <device> [--opcode=<opcode> | -o <opcode>]
                [--flags=<flags> | -f <flags>] [-rsvd=<rsvd> | -R <rsvd>]
                [--namespace-id=<nsid>] [--cdw2=<cdw2>] [--cdw3=<cdw3>]
                [--cdw10=<cdw10>] [--cdw11=<cdw11>] [--cdw12=<cdw12>]
                [--cdw13=<cdw13>] [--cdw14=<cdw14>] [--cdw15=<cdw15>]
                [--data-len=<data-len> | -l <data-len>]
                [--metadata-len=<len> | -m <len>]
                [--input-file=<file> | -f <file>]
                [--read | -r ] [--write | -w]
                [--timeout=<to> | -t <to>]
                [--show-command | --dry-run | -s]
                [--raw-binary | -b]
                [--prefill=<prefill> | -p <prefill>]

DESCRIPTION

Submits an arbitrary NVMe admin command and returns the applicable results. This may be the simply the commands result and status, or may also include a buffer if the command returns one. This command does no interpretation of the opcodes or options.

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 structure (if applicable) may be returned in one of several ways depending on the option flags; the structure may printed by the program as a hex dump, or may be returned as a raw buffer printed to stdout for another program to parse.

OPTIONS

-o <opcode>
--opcode=<opcode>

The NVMe opcode to send to the device in the command

-f <flags>
--flags=<flags>

The NVMe command flags to send to the device in the command

-R <rsvd>
--rsvd=<rsvd>

The value for the reserved field in the command.

-n <nsid>
--namespace-id=<nsid>

The value for the ns-id in the command.

--cdw[2-3,10-15]=<cdw>

Specifies the command dword value for that specified entry in the command

-r
--read
-w
--write

Used for the data-direction for the command and required for commands sending/receiving data. Don’t use both read and write at the same time.

-i <file>
--input-file=<file>

If the command is a data-out (write) command, use this file to fill the buffer sent to the device. If no file is given, assumed to use STDIN.

-l <data-len>
--data-len=<data-len>

The data length for the buffer used for this command.

-m <data-len>
--metadata-len=<data-len>

The metadata length for the buffer used for this command.

-s
--show-cmd
--dry-run

Do not actually send the command; print out the command that would be sent.

-b
--raw-binary

Print the raw returned buffer to stdout if the command returns a structure.

-p
--prefill

Prefill the buffer with a predetermined byte value. Defaults to 0. This may be useful if the data you are writing is shorter than the required buffer, and you need to pad it with a known value. It may also be useful if you need to confirm if a device is overwriting a buffer for a data-in command.

EXAMPLES

  • The following will run the admin command with opcode=6 and cdw10=1, which corresponds to an identify controller command. This example requires the data-len param be 4096, which is the size of the returned structure. The -r option is used because it is a data-in command

    # nvme admin-passthru /dev/nvme0 --opcode=06 --data-len=4096 --cdw10=1 -r
  • Or if you want to save that structure to a file:

    # nvme admin-passthru /dev/nvme0 --opcode=06 --data-len=4096 --cdw10=1 -r -b > id_ns.raw

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-admin-passthru.txt000066400000000000000000000067421322317423600223610ustar00rootroot00000000000000nvme-admin-passthru(1) ====================== NAME ---- nvme-admin-passthru - Submit an arbitrary admin command, return results SYNOPSIS -------- [verse] 'nvme-admin-passthru' [--opcode= | -o ] [--flags= | -f ] [-rsvd= | -R ] [--namespace-id=] [--cdw2=] [--cdw3=] [--cdw10=] [--cdw11=] [--cdw12=] [--cdw13=] [--cdw14=] [--cdw15=] [--data-len= | -l ] [--metadata-len= | -m ] [--input-file= | -f ] [--read | -r ] [--write | -w] [--timeout= | -t ] [--show-command | --dry-run | -s] [--raw-binary | -b] [--prefill= | -p ] DESCRIPTION ----------- Submits an arbitrary NVMe admin command and returns the applicable results. This may be the simply the commands result and status, or may also include a buffer if the command returns one. This command does no interpretation of the opcodes or options. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned structure (if applicable) may be returned in one of several ways depending on the option flags; the structure may printed by the program as a hex dump, or may be returned as a raw buffer printed to stdout for another program to parse. OPTIONS ------- -o :: --opcode=:: The NVMe opcode to send to the device in the command -f :: --flags=:: The NVMe command flags to send to the device in the command -R :: --rsvd=:: The value for the reserved field in the command. -n :: --namespace-id=:: The value for the ns-id in the command. --cdw[2-3,10-15]=:: Specifies the command dword value for that specified entry in the command -r:: --read:: -w:: --write:: Used for the data-direction for the command and required for commands sending/receiving data. Don't use both read and write at the same time. -i :: --input-file=:: If the command is a data-out (write) command, use this file to fill the buffer sent to the device. If no file is given, assumed to use STDIN. -l :: --data-len=:: The data length for the buffer used for this command. -m :: --metadata-len=:: The metadata length for the buffer used for this command. -s:: --show-cmd:: --dry-run:: Do not actually send the command; print out the command that would be sent. -b:: --raw-binary:: Print the raw returned buffer to stdout if the command returns a structure. -p:: --prefill:: Prefill the buffer with a predetermined byte value. Defaults to 0. This may be useful if the data you are writing is shorter than the required buffer, and you need to pad it with a known value. It may also be useful if you need to confirm if a device is overwriting a buffer for a data-in command. EXAMPLES -------- * The following will run the admin command with opcode=6 and cdw10=1, which corresponds to an identify controller command. This example requires the data-len param be 4096, which is the size of the returned structure. The -r option is used because it is a data-in command + ------------ # nvme admin-passthru /dev/nvme0 --opcode=06 --data-len=4096 --cdw10=1 -r ------------ + * Or if you want to save that structure to a file: + ------------ # nvme admin-passthru /dev/nvme0 --opcode=06 --data-len=4096 --cdw10=1 -r -b > id_ns.raw ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-attach-ns.1000066400000000000000000000037131322317423600206200ustar00rootroot00000000000000'\" t .\" Title: nvme-attach-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ATTACH\-NS" "1" "12/10/2017" "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-attach-ns \- Send NVMe attach namespace, return result\&. .SH "SYNOPSIS" .sp .nf \fInvme attach\-ns\fR [\-\-namespace\-id= | \-n ] [\-\-controllers= | \-c ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends the nvme namespace attach command for the provided namespace identifier, attaching to the provided list of controller identifiers\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 The namespace identifier to attach\&. .RE .PP \-c , \-controllers= .RS 4 The comma separated list of controller identifiers to attach the namesapce too\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-attach-ns.html000066400000000000000000000433051322317423600214250ustar00rootroot00000000000000 nvme-attach-ns(1)

SYNOPSIS

nvme attach-ns <device> [--namespace-id=<nsid> | -n <nsid>]
                        [--controllers=<ctrl-list,> | -c <ctrl-list,>]

DESCRIPTION

For the NVMe device given, sends the nvme namespace attach command for the provided namespace identifier, attaching to the provided list of controller identifiers.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

The namespace identifier to attach.

-c <ctrl-list,>
-controllers=<ctrl-list,>

The comma separated list of controller identifiers to attach the namesapce too.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-attach-ns.txt000066400000000000000000000013311322317423600212710ustar00rootroot00000000000000nvme-attach-ns(1) ================= NAME ---- nvme-attach-ns - Send NVMe attach namespace, return result. SYNOPSIS -------- [verse] 'nvme attach-ns' [--namespace-id= | -n ] [--controllers= | -c ] DESCRIPTION ----------- For the NVMe device given, sends the nvme namespace attach command for the provided namespace identifier, attaching to the provided list of controller identifiers. OPTIONS ------- -n :: --namespace-id=:: The namespace identifier to attach. -c :: -controllers=:: The comma separated list of controller identifiers to attach the namesapce too. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-compare.1000066400000000000000000000051001322317423600203540ustar00rootroot00000000000000'\" t .\" Title: nvme-compare .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-COMPARE" "1" "12/10/2017" "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-compare \- Send an NVMe Compare command, provide results .SH "SYNOPSIS" .sp .nf \fInvme\-compare\fR [\-\-start\-block= | \-s ] [\-\-block\-count= | \-c ] [\-\-data\-size= | \-z ] [\-\-ref\-tag= | \-r ] [\-\-data= | \-d ] [\-\-prinfo= | \-p ] [\-\-app\-tag\-mask= | \-m ] [\-\-app\-tag= | \-a ] [\-\-limited\-retry | \-l] [\-\-force\-unit\-access | \-f] .fi .SH "DESCRIPTION" .sp The Compare command reads the logical blocks specified by the command from the medium and compares the data read to a comparison data buffer transferred as part of the command\&. If the data read from the controller and the comparison data buffer are equivalent with no miscompares, then the command completes successfully\&. If there is any miscompare, the command completes with an error of Compare Failure\&. If metadata is provided, then a comparison is also performed for the metadata\&. .SH "OPTIONS" .PP \-\-start\-block=, \-s .RS 4 Start block\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-compare.html000066400000000000000000000444151322317423600211740ustar00rootroot00000000000000 nvme-compare(1)

SYNOPSIS

nvme-compare <device> [--start-block=<slba> | -s <slba>]
                        [--block-count=<nlb> | -c <nlb>]
                        [--data-size=<size> | -z <size>]
                        [--ref-tag=<reftag> | -r <reftag>]
                        [--data=<data-file> | -d <data-file>]
                        [--prinfo=<prinfo> | -p <prinfo>]
                        [--app-tag-mask=<appmask> | -m <appmask>]
                        [--app-tag=<apptag> | -a <apptag>]
                        [--limited-retry | -l]
                        [--force-unit-access | -f]

DESCRIPTION

The Compare command reads the logical blocks specified by the command from the medium and compares the data read to a comparison data buffer transferred as part of the command. If the data read from the controller and the comparison data buffer are equivalent with no miscompares, then the command completes successfully. If there is any miscompare, the command completes with an error of Compare Failure. If metadata is provided, then a comparison is also performed for the metadata.

OPTIONS

--start-block=<slba>
-s <slba>

Start block.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-compare.txt000066400000000000000000000022201322317423600210330ustar00rootroot00000000000000nvme-compare(1) =============== NAME ---- nvme-compare - Send an NVMe Compare command, provide results SYNOPSIS -------- [verse] 'nvme-compare' [--start-block= | -s ] [--block-count= | -c ] [--data-size= | -z ] [--ref-tag= | -r ] [--data= | -d ] [--prinfo= | -p ] [--app-tag-mask= | -m ] [--app-tag= | -a ] [--limited-retry | -l] [--force-unit-access | -f] DESCRIPTION ----------- The Compare command reads the logical blocks specified by the command from the medium and compares the data read to a comparison data buffer transferred as part of the command. If the data read from the controller and the comparison data buffer are equivalent with no miscompares, then the command completes successfully. If there is any miscompare, the command completes with an error of Compare Failure. If metadata is provided, then a comparison is also performed for the metadata. OPTIONS ------- --start-block=:: -s :: Start block. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-connect-all.1000066400000000000000000000131421322317423600211320ustar00rootroot00000000000000'\" t .\" Title: nvme-connect-all .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-CONNECT\-ALL" "1" "12/10/2017" "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-connect-all \- Discover and Connect to Fabrics controllers\&. .SH "SYNOPSIS" .sp .nf \fInvme connect\-all\fR [\-\-transport= | \-t ] [\-\-traddr= | \-a ] [\-\-trsvcid= | \-s ] [\-\-host\-traddr= | \-w ] [\-\-hostnqn= | \-q ] [\-\-raw= | \-r ] .fi .SH "DESCRIPTION" .sp Send one or more Discovery requests to a NVMe over Fabrics Discovery Controller, and create controllers for the returned discovery records\&. .sp If no parameters are given, then \fInvme connect\-all\fR will attempt to find a /etc/nvme/discovery\&.conf file to use to supply a list of connect\-all commands to run\&. If no /etc/nvme/discovery\&.conf file exists, the command will quit with an error\&. .sp Otherwise a specific Discovery Controller should be specified using the \-\-transport, \-\-traddr and if necessary the \-\-trsvcid and a Diѕcovery request will be sent to the specified Discovery Controller\&. .sp See the documentation for the nvme\-discover(1) command for further background\&. .SH "OPTIONS" .PP \-t , \-\-transport= .RS 4 This field specifies the network fabric being used for a NVMe\-over\-Fabrics network\&. Current string values include: .TS allbox tab(:); lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ rdma T}:T{ The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc) T} T{ fc T}:T{ \fBWIP\fR The network fabric is a Fibre Channel network\&. T} T{ loop T}:T{ Connect to a NVMe over Fabrics target on the local host T} .TE .sp 1 .RE .PP \-a , \-\-traddr= .RS 4 This field specifies the network address of the Discovery Controller\&. For transports using IP addressing (e\&.g\&. rdma) this should be an IP\-based address (ex\&. IPv4)\&. .RE .PP \-s , \-\-trsvcid= .RS 4 This field specifies the transport service id\&. For transports using IP addressing (e\&.g\&. rdma) this field is the port number\&. By default, the IP port number for the RDMA transport is 4420\&. .RE .PP \-w , \-\-host\-traddr= .RS 4 This field specifies the network address used on the host to connect to the Discovery Controller\&. .RE .PP \-q , \-\-hostnqn= .RS 4 Overrides the default Host NQN that identifies the NVMe Host\&. If this option is not specified, the default is read from /etc/nvme/hostnqn first\&. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next\&. The Host NQN uniquely identifies the NVMe Host, and may be used by the the Discovery Controller to control what NVMe Target resources are allocated to the NVMe Host for a connection\&. .RE .PP \-r , \-\-raw= .RS 4 This field will take the output of the \fInvme connect\-all\fR command and dump it to a raw binary file\&. By default \fInvme connect\-all\fR will dump the output to stdout\&. .RE .PP \-Q <#>, \-\-queue\-size=<#> .RS 4 Overrides the default number of elements in the I/O queues created by the driver\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Connect to all records returned by the Discover Controller with IP4 address 192\&.168\&.1\&.3 for all resources allocated for NVMe Host name host1\-rogue\-nqn on the RDMA network\&. Port 4420 is used by default: .sp .if n \{\ .RS 4 .\} .nf # nvme connect\-all \-\-transport=rdma \-\-traddr=192\&.168\&.1\&.3 \e \-\-hostnqn=host1\-rogue\-nqn .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Issue a \fInvme connect\-all\fR command using a /etc/nvme/discovery\&.conf file: .RE .sp .if n \{\ .RS 4 .\} .nf # Machine default \*(Aqnvme discover\*(Aq commands\&. Query the # Discovery Controller\*(Aqs two ports (some resources may only # be accessible on a single port)\&. Note an official # nqn (Host) name defined in the NVMe specification is being used # in this example\&. \-t rdma \-a 192\&.168\&.69\&.33 \-s 4420 \-q nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432 \-t rdma \-a 192\&.168\&.1\&.4 \-s 4420 \-q nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432 At the prompt type "nvme connect\-all"\&. .fi .if n \{\ .RE .\} .SH "SEE ALSO" .sp nvme\-discover(1) nvme\-connect(1) .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-connect-all.html000066400000000000000000000551231322317423600217430ustar00rootroot00000000000000 nvme-connect-all(1)

SYNOPSIS

nvme connect-all
                [--transport=<trtype>     | -t <trtype>]
                [--traddr=<traddr>        | -a <traddr>]
                [--trsvcid=<trsvcid>      | -s <trsvcid>]
                [--host-traddr=<traddr>   | -w <traddr>]
                [--hostnqn=<hostnqn>      | -q <hostnqn>]
                [--raw=<filename>         | -r <filename>]

DESCRIPTION

Send one or more Discovery requests to a NVMe over Fabrics Discovery Controller, and create controllers for the returned discovery records.

If no parameters are given, then nvme connect-all will attempt to find a /etc/nvme/discovery.conf file to use to supply a list of connect-all commands to run. If no /etc/nvme/discovery.conf file exists, the command will quit with an error.

Otherwise a specific Discovery Controller should be specified using the --transport, --traddr and if necessary the --trsvcid and a Diѕcovery request will be sent to the specified Discovery Controller.

See the documentation for the nvme-discover(1) command for further background.

OPTIONS

-t <trtype>
--transport=<trtype>

This field specifies the network fabric being used for a NVMe-over-Fabrics network. Current string values include:

Value

Definition

rdma

The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc)

fc

WIP The network fabric is a Fibre Channel network.

loop

Connect to a NVMe over Fabrics target on the local host

-a <traddr>
--traddr=<traddr>

This field specifies the network address of the Discovery Controller. For transports using IP addressing (e.g. rdma) this should be an IP-based address (ex. IPv4).

-s <trsvcid>
--trsvcid=<trsvcid>

This field specifies the transport service id. For transports using IP addressing (e.g. rdma) this field is the port number. By default, the IP port number for the RDMA transport is 4420.

-w <traddr>
--host-traddr=<traddr>

This field specifies the network address used on the host to connect to the Discovery Controller.

-q <hostnqn>
--hostnqn=<hostnqn>

Overrides the default Host NQN that identifies the NVMe Host. If this option is not specified, the default is read from /etc/nvme/hostnqn first. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next. The Host NQN uniquely identifies the NVMe Host, and may be used by the the Discovery Controller to control what NVMe Target resources are allocated to the NVMe Host for a connection.

-r <filename>
--raw=<filename>

This field will take the output of the nvme connect-all command and dump it to a raw binary file. By default nvme connect-all will dump the output to stdout.

-Q <#>
--queue-size=<#>

Overrides the default number of elements in the I/O queues created by the driver.

EXAMPLES

  • Connect to all records returned by the Discover Controller with IP4 address 192.168.1.3 for all resources allocated for NVMe Host name host1-rogue-nqn on the RDMA network. Port 4420 is used by default:

    # nvme connect-all --transport=rdma --traddr=192.168.1.3 \
    --hostnqn=host1-rogue-nqn
  • Issue a nvme connect-all command using a /etc/nvme/discovery.conf file:

# Machine default 'nvme discover' commands.  Query the
# Discovery Controller's two ports (some resources may only
# be accessible on a single port).  Note an official
# nqn (Host) name defined in the NVMe specification is being used
# in this example.
-t rdma -a 192.168.69.33 -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432
-t rdma -a 192.168.1.4   -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432

At the prompt type "nvme connect-all".

SEE ALSO

nvme-discover(1) nvme-connect(1)

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-connect-all.txt000066400000000000000000000075131322317423600216160ustar00rootroot00000000000000nvme-connect-all(1) =================== NAME ---- nvme-connect-all - Discover and Connect to Fabrics controllers. SYNOPSIS -------- [verse] 'nvme connect-all' [--transport= | -t ] [--traddr= | -a ] [--trsvcid= | -s ] [--host-traddr= | -w ] [--hostnqn= | -q ] [--raw= | -r ] DESCRIPTION ----------- Send one or more Discovery requests to a NVMe over Fabrics Discovery Controller, and create controllers for the returned discovery records. If no parameters are given, then 'nvme connect-all' will attempt to find a /etc/nvme/discovery.conf file to use to supply a list of connect-all commands to run. If no /etc/nvme/discovery.conf file exists, the command will quit with an error. Otherwise a specific Discovery Controller should be specified using the --transport, --traddr and if necessary the --trsvcid and a Diѕcovery request will be sent to the specified Discovery Controller. See the documentation for the nvme-discover(1) command for further background. OPTIONS ------- -t :: --transport=:: This field specifies the network fabric being used for a NVMe-over-Fabrics network. Current string values include: + [] |================= |Value|Definition |rdma|The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc) |fc |*WIP* The network fabric is a Fibre Channel network. |loop|Connect to a NVMe over Fabrics target on the local host |================= -a :: --traddr=:: This field specifies the network address of the Discovery Controller. For transports using IP addressing (e.g. rdma) this should be an IP-based address (ex. IPv4). -s :: --trsvcid=:: This field specifies the transport service id. For transports using IP addressing (e.g. rdma) this field is the port number. By default, the IP port number for the RDMA transport is 4420. -w :: --host-traddr=:: This field specifies the network address used on the host to connect to the Discovery Controller. -q :: --hostnqn=:: Overrides the default Host NQN that identifies the NVMe Host. If this option is not specified, the default is read from /etc/nvme/hostnqn first. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next. The Host NQN uniquely identifies the NVMe Host, and may be used by the the Discovery Controller to control what NVMe Target resources are allocated to the NVMe Host for a connection. -r :: --raw=:: This field will take the output of the 'nvme connect-all' command and dump it to a raw binary file. By default 'nvme connect-all' will dump the output to stdout. -Q <#>:: --queue-size=<#>:: Overrides the default number of elements in the I/O queues created by the driver. EXAMPLES -------- * Connect to all records returned by the Discover Controller with IP4 address 192.168.1.3 for all resources allocated for NVMe Host name host1-rogue-nqn on the RDMA network. Port 4420 is used by default: + ------------ # nvme connect-all --transport=rdma --traddr=192.168.1.3 \ --hostnqn=host1-rogue-nqn ------------ + * Issue a 'nvme connect-all' command using a /etc/nvme/discovery.conf file: ----------- # Machine default 'nvme discover' commands. Query the # Discovery Controller's two ports (some resources may only # be accessible on a single port). Note an official # nqn (Host) name defined in the NVMe specification is being used # in this example. -t rdma -a 192.168.69.33 -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 -t rdma -a 192.168.1.4 -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 At the prompt type "nvme connect-all". ------------ SEE ALSO -------- nvme-discover(1) nvme-connect(1) NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-connect.1000066400000000000000000000121021322317423600203570ustar00rootroot00000000000000'\" t .\" Title: nvme-connect .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-CONNECT" "1" "12/10/2017" "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-connect \- Connect to a Fabrics controller\&. .SH "SYNOPSIS" .sp .nf \fInvme connect\fR [\-\-transport= | \-t ] [\-\-nqn= | \-n ] [\-\-traddr= | \-a ] [\-\-trsvcid= | \-s ] [\-\-host\-traddr= | \-w ] [\-\-hostnqn= | \-q ] [\-\-nr\-io\-queues=<#> | \-i <#>] [\-\-queue\-size=<#> | \-Q <#>] [\-\-keep\-alive\-tmo=<#> | \-k <#>] [\-\-reconnect\-delay=<#> | \-c <#>] .fi .SH "DESCRIPTION" .sp Create a transport connection to a remote system (specified by \-\-traddr and \-\-trsvcid) and create a NVMe over Fabrics controller for the NVMe subsystem specified by the \-\-nqn option\&. .SH "OPTIONS" .PP \-t , \-\-transport= .RS 4 This field specifies the network fabric being used for a NVMe\-over\-Fabrics network\&. Current string values include: .TS allbox tab(:); lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ rdma T}:T{ The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc) T} T{ fc T}:T{ \fBWIP\fR The network fabric is a Fibre Channel network\&. T} T{ loop T}:T{ Connect to a NVMe over Fabrics target on the local host T} .TE .sp 1 .RE .PP \-n , \-\-nqn .RS 4 This field specifies the name for the NVMe subsystem to connect to\&. .RE .PP \-a , \-\-traddr= .RS 4 This field specifies the network address of the Controller\&. For transports using IP addressing (e\&.g\&. rdma) this should be an IP\-based address (ex\&. IPv4)\&. .RE .PP \-s , \-\-trsvcid= .RS 4 This field specifies the transport service id\&. For transports using IP addressing (e\&.g\&. rdma) this field is the port number\&. By default, the IP port number for the RDMA transport is 4420\&. .RE .PP \-w , \-\-host\-traddr= .RS 4 This field specifies the network address used on the host to connect to the Controller\&. .RE .PP \-q , \-\-hostnqn= .RS 4 Overrides the default Host NQN that identifies the NVMe Host\&. If this option is not specified, the default is read from /etc/nvme/hostnqn first\&. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next\&. The Host NQN uniquely identifies the NVMe Host\&. .RE .PP \-i <#>, \-\-nr\-io\-queues=<#> .RS 4 Overrides the default number of I/O queues create by the driver\&. .RE .PP \-Q <#>, \-\-queue\-size=<#> .RS 4 Overrides the default number of elements in the I/O queues created by the driver\&. .RE .PP \-k <#>, \-\-keep\-alive\-tmo=<#> .RS 4 Overrides the default keep alive timeout (in seconds)\&. .RE .PP \-c <#>, \-\-reconnect\-delay=<#> .RS 4 Overrides the default delay (in seconds) before reconnect is attempted after a connect loss\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Connect to a subsystem named nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432 on the IP4 address 192\&.168\&.1\&.3\&. Port 4420 is used by default: .sp .if n \{\ .RS 4 .\} .nf # nvme connect \-\-transport=rdma \-\-traddr=192\&.168\&.1\&.3 \e \-\-nqn=nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432 .fi .if n \{\ .RE .\} .RE .sp .if n \{\ .RS 4 .\} .nf SEE ALSO .fi .if n \{\ .RE .\} .sp nvme\-discover(1) nvme\-connect\-all(1) .SH "AUTHORS" .sp This was co\-written by \m[blue]\fBJay Freyensee\fR\m[]\&\s-2\u[1]\d\s+2 and \m[blue]\fBChristoph Hellwig\fR\m[]\&\s-2\u[2]\d\s+2 for \m[blue]\fBKeith Busch\fR\m[]\&\s-2\u[3]\d\s+2\&. .SH "NVME" .sp Part of the nvme\-user suite .SH "NOTES" .IP " 1." 4 Jay Freyensee .RS 4 \%mailto:james.p.freyensee@intel.com .RE .IP " 2." 4 Christoph Hellwig .RS 4 \%mailto:hch@lst.de .RE .IP " 3." 4 Keith Busch .RS 4 \%mailto:keith.busch@intel.com .RE nvme-cli-1.5/Documentation/nvme-connect.html000066400000000000000000000542561322317423600212030ustar00rootroot00000000000000 nvme-connect(1)

SYNOPSIS

nvme connect
                [--transport=<trtype>     | -t <trtype>]
                [--nqn=<subnqn>           | -n <subnqn>]
                [--traddr=<traddr>        | -a <traddr>]
                [--trsvcid=<trsvcid>      | -s <trsvcid>]
                [--host-traddr=<traddr>   | -w <traddr>]
                [--hostnqn=<hostnqn>      | -q <hostnqn>]
                [--nr-io-queues=<#>       | -i <#>]
                [--queue-size=<#>         | -Q <#>]
                [--keep-alive-tmo=<#>     | -k <#>]
                [--reconnect-delay=<#>    | -c <#>]

DESCRIPTION

Create a transport connection to a remote system (specified by --traddr and --trsvcid) and create a NVMe over Fabrics controller for the NVMe subsystem specified by the --nqn option.

OPTIONS

-t <trtype>
--transport=<trtype>

This field specifies the network fabric being used for a NVMe-over-Fabrics network. Current string values include:

Value

Definition

rdma

The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc)

fc

WIP The network fabric is a Fibre Channel network.

loop

Connect to a NVMe over Fabrics target on the local host

-n <subnqn>
--nqn <subnqn>

This field specifies the name for the NVMe subsystem to connect to.

-a <traddr>
--traddr=<traddr>

This field specifies the network address of the Controller. For transports using IP addressing (e.g. rdma) this should be an IP-based address (ex. IPv4).

-s <trsvcid>
--trsvcid=<trsvcid>

This field specifies the transport service id. For transports using IP addressing (e.g. rdma) this field is the port number. By default, the IP port number for the RDMA transport is 4420.

-w <traddr>
--host-traddr=<traddr>

This field specifies the network address used on the host to connect to the Controller.

-q <hostnqn>
--hostnqn=<hostnqn>

Overrides the default Host NQN that identifies the NVMe Host. If this option is not specified, the default is read from /etc/nvme/hostnqn first. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next. The Host NQN uniquely identifies the NVMe Host.

-i <#>
--nr-io-queues=<#>

Overrides the default number of I/O queues create by the driver.

-Q <#>
--queue-size=<#>

Overrides the default number of elements in the I/O queues created by the driver.

-k <#>
--keep-alive-tmo=<#>

Overrides the default keep alive timeout (in seconds).

-c <#>
--reconnect-delay=<#>

Overrides the default delay (in seconds) before reconnect is attempted after a connect loss.

EXAMPLES

  • Connect to a subsystem named nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 on the IP4 address 192.168.1.3. Port 4420 is used by default:

    # nvme connect --transport=rdma --traddr=192.168.1.3 \
    --nqn=nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432
SEE ALSO

nvme-discover(1) nvme-connect-all(1)

AUTHORS

This was co-written by Jay Freyensee and Christoph Hellwig for Keith Busch.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-connect.txt000066400000000000000000000062051322317423600210450ustar00rootroot00000000000000nvme-connect(1) =============== NAME ---- nvme-connect - Connect to a Fabrics controller. SYNOPSIS -------- [verse] 'nvme connect' [--transport= | -t ] [--nqn= | -n ] [--traddr= | -a ] [--trsvcid= | -s ] [--host-traddr= | -w ] [--hostnqn= | -q ] [--nr-io-queues=<#> | -i <#>] [--queue-size=<#> | -Q <#>] [--keep-alive-tmo=<#> | -k <#>] [--reconnect-delay=<#> | -c <#>] DESCRIPTION ----------- Create a transport connection to a remote system (specified by --traddr and --trsvcid) and create a NVMe over Fabrics controller for the NVMe subsystem specified by the --nqn option. OPTIONS ------- -t :: --transport=:: This field specifies the network fabric being used for a NVMe-over-Fabrics network. Current string values include: + [] |================= |Value|Definition |rdma|The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc) |fc |*WIP* The network fabric is a Fibre Channel network. |loop|Connect to a NVMe over Fabrics target on the local host |================= -n :: --nqn :: This field specifies the name for the NVMe subsystem to connect to. -a :: --traddr=:: This field specifies the network address of the Controller. For transports using IP addressing (e.g. rdma) this should be an IP-based address (ex. IPv4). -s :: --trsvcid=:: This field specifies the transport service id. For transports using IP addressing (e.g. rdma) this field is the port number. By default, the IP port number for the RDMA transport is 4420. -w :: --host-traddr=:: This field specifies the network address used on the host to connect to the Controller. -q :: --hostnqn=:: Overrides the default Host NQN that identifies the NVMe Host. If this option is not specified, the default is read from /etc/nvme/hostnqn first. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next. The Host NQN uniquely identifies the NVMe Host. -i <#>:: --nr-io-queues=<#>:: Overrides the default number of I/O queues create by the driver. -Q <#>:: --queue-size=<#>:: Overrides the default number of elements in the I/O queues created by the driver. -k <#>:: --keep-alive-tmo=<#>:: Overrides the default keep alive timeout (in seconds). -c <#>:: --reconnect-delay=<#>:: Overrides the default delay (in seconds) before reconnect is attempted after a connect loss. EXAMPLES -------- * Connect to a subsystem named nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 on the IP4 address 192.168.1.3. Port 4420 is used by default: + ------------ # nvme connect --transport=rdma --traddr=192.168.1.3 \ --nqn=nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 ------------ ------------ SEE ALSO -------- nvme-discover(1) nvme-connect-all(1) AUTHORS ------- This was co-written by mailto:james.p.freyensee@intel.com[Jay Freyensee] and mailto:hch@lst.de[Christoph Hellwig] for mailto:keith.busch@intel.com[Keith Busch]. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-create-ns.1000066400000000000000000000046171322317423600206230ustar00rootroot00000000000000'\" t .\" Title: nvme-create-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-CREATE\-NS" "1" "12/10/2017" "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-create-ns \- Send NVMe Namespace management command to create namespace, returns results\&. .SH "SYNOPSIS" .sp .nf \fInvme create\-ns\fR [\-\-nsze= | \-s ] [\-\-ncap= | \-c ] [\-\-flbas= | \-f ] [\-\-dps= | \-d ] [\-\-nmic= | \-m ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends a namespace management command to create the namespace with the requested settings\&. On success, the namespace identifier assigned by the controller is returned\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .SH "OPTIONS" .PP \-s, \-\-nsze .RS 4 The namespace size\&. .RE .PP \-c, \-\-ncap .RS 4 The namespace capacity\&. .RE .PP \-f, \-\-flbas .RS 4 The namespace formatted logical block size setting\&. .RE .PP \-d, \-\-dps .RS 4 The data protection settings\&. .RE .PP \-m, \-\-nmic .RS 4 Namespace multipath and sharing capabilities\&. .RE .SH "EXAMPLES" .sp No examples provided yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-create-ns.html000066400000000000000000000446121322317423600214260ustar00rootroot00000000000000 nvme-create-ns(1)

SYNOPSIS

nvme create-ns <device> [--nsze=<nsze> | -s <nsze>]
                        [--ncap=<ncap> | -c <ncap>]
                        [--flbas=<flbas> | -f <flbas>]
                        [--dps=<dps> | -d <dps>]
                        [--nmic=<nmic> | -m <nmic>]

DESCRIPTION

For the NVMe device given, sends a namespace management command to create the namespace with the requested settings. On success, the namespace identifier assigned by the controller is returned.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

OPTIONS

-s
--nsze

The namespace size.

-c
--ncap

The namespace capacity.

-f
--flbas

The namespace formatted logical block size setting.

-d
--dps

The data protection settings.

-m
--nmic

Namespace multipath and sharing capabilities.

EXAMPLES

No examples provided yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-create-ns.txt000066400000000000000000000020511322317423600212700ustar00rootroot00000000000000nvme-create-ns(1) ================= NAME ---- nvme-create-ns - Send NVMe Namespace management command to create namespace, returns results. SYNOPSIS -------- [verse] 'nvme create-ns' [--nsze= | -s ] [--ncap= | -c ] [--flbas= | -f ] [--dps= | -d ] [--nmic= | -m ] DESCRIPTION ----------- For the NVMe device given, sends a namespace management command to create the namespace with the requested settings. On success, the namespace identifier assigned by the controller is returned. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). OPTIONS ------- -s:: --nsze:: The namespace size. -c:: --ncap:: The namespace capacity. -f:: --flbas:: The namespace formatted logical block size setting. -d:: --dps:: The data protection settings. -m:: --nmic:: Namespace multipath and sharing capabilities. EXAMPLES -------- No examples provided yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-delete-ns.1000066400000000000000000000036611322317423600206200ustar00rootroot00000000000000'\" t .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ID\-NS" "1" "12/10/2017" "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-delete-ns \- Send NVMe Namespace Management delete namespace command, return result\&. .SH "SYNOPSIS" .sp .nf \fInvme delete\-ns\fR [\-\-namespace\-id= | \-n ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an nvme namespace management command to delete the requested namespace and provides the result\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. The \*(Aq\-\-namespace\-id\*(Aq option is mandatory\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 The namespace identifier to delete\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-delete-ns.html000066400000000000000000000431541322317423600214250ustar00rootroot00000000000000 nvme-id-ns(1)

SYNOPSIS

nvme delete-ns <device> [--namespace-id=<nsid> | -n <nsid>]

DESCRIPTION

For the NVMe device given, sends an nvme namespace management command to delete the requested namespace and provides the result.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). The '--namespace-id' option is mandatory.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

The namespace identifier to delete.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-delete-ns.txt000066400000000000000000000013271322317423600212740ustar00rootroot00000000000000nvme-id-ns(1) ============= NAME ---- nvme-delete-ns - Send NVMe Namespace Management delete namespace command, return result. SYNOPSIS -------- [verse] 'nvme delete-ns' [--namespace-id= | -n ] DESCRIPTION ----------- For the NVMe device given, sends an nvme namespace management command to delete the requested namespace and provides the result. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). The `'--namespace-id'` option is mandatory. OPTIONS ------- -n :: --namespace-id=:: The namespace identifier to delete. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-detach-ns.1000066400000000000000000000037131322317423600206040ustar00rootroot00000000000000'\" t .\" Title: nvme-detach-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-DETACH\-NS" "1" "12/10/2017" "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-detach-ns \- Send NVMe detach namespace, return result\&. .SH "SYNOPSIS" .sp .nf \fInvme detach\-ns\fR [\-\-namespace\-id= | \-n ] [\-\-controllers= | \-c .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends the nvme namespace detach command for the provided namespace identifier, attaching to the provided list of controller identifiers\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 The namespace identifier to detach\&. .RE .PP \-c , \-controllers= .RS 4 The comma separated list of controller identifiers to detach the namespace from\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-detach-ns.html000066400000000000000000000433051322317423600214110ustar00rootroot00000000000000 nvme-detach-ns(1)

SYNOPSIS

nvme detach-ns <device> [--namespace-id=<nsid> | -n <nsid>]
                        [--controllers=<ctrl-list,> | -c <ctrl-list,>

DESCRIPTION

For the NVMe device given, sends the nvme namespace detach command for the provided namespace identifier, attaching to the provided list of controller identifiers.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

The namespace identifier to detach.

-c <ctrl-list,>
-controllers=<ctrl-list,>

The comma separated list of controller identifiers to detach the namespace from.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-detach-ns.txt000066400000000000000000000013311322317423600212550ustar00rootroot00000000000000nvme-detach-ns(1) ================= NAME ---- nvme-detach-ns - Send NVMe detach namespace, return result. SYNOPSIS -------- [verse] 'nvme detach-ns' [--namespace-id= | -n ] [--controllers= | -c DESCRIPTION ----------- For the NVMe device given, sends the nvme namespace detach command for the provided namespace identifier, attaching to the provided list of controller identifiers. OPTIONS ------- -n :: --namespace-id=:: The namespace identifier to detach. -c :: -controllers=:: The comma separated list of controller identifiers to detach the namespace from. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-dir-receive.1000066400000000000000000000114501322317423600211310ustar00rootroot00000000000000'\" t .\" Title: nvme-dir-receive .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-DIR\-RECEIVE" "1" "12/10/2017" "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-dir-receive \- Send a directive receive command, returns applicable results .SH "SYNOPSIS" .sp .nf \fInvme dir\-receive\fR [\-\-namespace\-id= | \-n ] [\-\-data\-len= | \-l ] [\-\-dir\-type= | \-D ] [\-\-dir\-spec= | \-S ] [\-\-dir\-oper= | \-O ] [\-\-req\-resource= | \-r ] [\-\-human\-readable | \-H] [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp Submits an NVMe Directive Receive admin command and returns the applicable results\&. This may be the combination of directive type, and operation, as well as number of requested resource if specific operation needs it\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned directive\(cqs parameter structure (if applicable) is returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the feature for the given nsid\&. This is optional and most features do not use this value\&. .RE .PP \-D , \-\-dir\-type= .RS 4 Directive type .RE .PP \-S , \-\-dir\-spec= .RS 4 Directive specific .RE .PP \-O , \-\-dir\-oper= .RS 4 Directive operation .RE .PP \-r , \-\-req\-resource= .RS 4 Directive requested resource count .RE .sp + .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt. T{ .sp Select T}:T{ .sp Description T} T{ .sp 0 T}:T{ .sp Current T} T{ .sp 1 T}:T{ .sp Default T} T{ .sp 2 T}:T{ .sp Saved T} T{ .sp 3 T}:T{ .sp Supported capabilities T} T{ .sp 4\(en7 T}:T{ .sp Reserved T} .TE .sp 1 .PP \-l , \-\-data\-len= .RS 4 The data length for the buffer returned for this feature\&. Most known features do not use this value\&. The exception is LBA Range Type .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw receive buffer to stdout if the command returns a structure\&. .RE .PP \-H, \-\-human\-readable .RS 4 Print the decoded receive buffer to stdout if the command returns a structure\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Identify directive type supported : .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-receive /dev/nvme0 \-\-dir\-type 0 \-\-dir\-oper 1 \-\-human\-readable .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Get stream directive parameters : .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-receive /dev/nvme0 \-\-dir\-type 1 \-\-dir\-oper 1 \-\-human\-readable .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Allocate 3 streams for namespace 1 .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-receive /dev/nvme0n1 \-\-dir\-type 1 \-\-dir\-oper 3 \-\-req\-resource 3 \-\-human\-readable .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Get streams directive status : .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-receive /dev/nvme0 \-\-dir\-type 1 \-\-dir\-oper 2 \-\-human\-readable .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 nvme-cli-1.5/Documentation/nvme-dir-receive.html000066400000000000000000000520011322317423600217320ustar00rootroot00000000000000 nvme-dir-receive(1)

SYNOPSIS

nvme dir-receive <device> [--namespace-id=<nsid> | -n <nsid>]
                          [--data-len=<data-len> | -l <data-len>]
                          [--dir-type=<dtype> | -D <dtype>]
                          [--dir-spec=<dspec> | -S <dspec>]
                          [--dir-oper=<doper> | -O <doper>]
                          [--req-resource=<nsr> | -r <nsr>]
                          [--human-readable | -H]
                          [--raw-binary | -b]

DESCRIPTION

Submits an NVMe Directive Receive admin command and returns the applicable results. This may be the combination of directive type, and operation, as well as number of requested resource if specific operation needs it.

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 directive’s parameter structure (if applicable) is returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the feature for the given nsid. This is optional and most features do not use this value.

-D <dtype>
--dir-type=<dtype>

Directive type

-S <dspec>
--dir-spec=<dspec>

Directive specific

-O <doper>
--dir-oper=<doper>

Directive operation

-r <nsr>
--req-resource=<nsr>

Directive requested resource count

+

Select

Description

0

Current

1

Default

2

Saved

3

Supported capabilities

4–7

Reserved

-l <data-len>
--data-len=<data-len>

The data length for the buffer returned for this feature. Most known features do not use this value. The exception is LBA Range Type

-b
--raw-binary

Print the raw receive buffer to stdout if the command returns a structure.

-H
--human-readable

Print the decoded receive buffer to stdout if the command returns a structure.

EXAMPLES

  • Identify directive type supported :

    # nvme dir-receive /dev/nvme0 --dir-type 0 --dir-oper 1 --human-readable
  • Get stream directive parameters :

    # nvme dir-receive /dev/nvme0 --dir-type 1 --dir-oper 1 --human-readable
  • Allocate 3 streams for namespace 1

    # nvme dir-receive /dev/nvme0n1 --dir-type 1 --dir-oper 3 --req-resource 3 --human-readable
  • Get streams directive status :

    # nvme dir-receive /dev/nvme0 --dir-type 1 --dir-oper 2 --human-readable

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-dir-receive.txt000066400000000000000000000054101322317423600216070ustar00rootroot00000000000000nvme-dir-receive(1) =================== NAME ---- nvme-dir-receive - Send a directive receive command, returns applicable results SYNOPSIS -------- [verse] 'nvme dir-receive' [--namespace-id= | -n ] [--data-len= | -l ] [--dir-type= | -D ] [--dir-spec= | -S ] [--dir-oper= | -O ] [--req-resource= | -r ] [--human-readable | -H] [--raw-binary | -b] DESCRIPTION ----------- Submits an NVMe Directive Receive admin command and returns the applicable results. This may be the combination of directive type, and operation, as well as number of requested resource if specific operation needs it. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned directive's parameter structure (if applicable) is returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -n :: --namespace-id=:: Retrieve the feature for the given nsid. This is optional and most features do not use this value. -D :: --dir-type=:: Directive type -S :: --dir-spec=:: Directive specific -O :: --dir-oper=:: Directive operation -r :: --req-resource=:: Directive requested resource count + [] |================== |Select|Description |0|Current |1|Default |2|Saved |3|Supported capabilities |4–7|Reserved |================== -l :: --data-len=:: The data length for the buffer returned for this feature. Most known features do not use this value. The exception is LBA Range Type -b:: --raw-binary:: Print the raw receive buffer to stdout if the command returns a structure. -H:: --human-readable:: Print the decoded receive buffer to stdout if the command returns a structure. EXAMPLES -------- * Identify directive type supported : + ------------ # nvme dir-receive /dev/nvme0 --dir-type 0 --dir-oper 1 --human-readable ------------ + * Get stream directive parameters : + ------------ # nvme dir-receive /dev/nvme0 --dir-type 1 --dir-oper 1 --human-readable ------------ + * Allocate 3 streams for namespace 1 + ------------ # nvme dir-receive /dev/nvme0n1 --dir-type 1 --dir-oper 3 --req-resource 3 --human-readable ------------ + * Get streams directive status : + ------------ # nvme dir-receive /dev/nvme0 --dir-type 1 --dir-oper 2 --human-readable ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-dir-send.1000066400000000000000000000116441322317423600204450ustar00rootroot00000000000000'\" t .\" Title: nvme-dir-send .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-DIR\-SEND" "1" "12/10/2017" "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-dir-send \- Issue a directive send command, returns applicable results .SH "SYNOPSIS" .sp .nf \fInvme dir\-send\fR [\-\-namespace\-id= | \-n ] [\-\-data\-len= | \-l ] [\-\-dir\-type= | \-D ] [\-\-dir\-spec= | \-S ] [\-\-dir\-oper= | \-O ] [\-\-endir= | \-e ] [\-\-target\-dir= | \-T ] [\-\-human\-readable | \-H] [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp Submits an NVMe Directive Send admin command and returns the applicable results\&. This may be the combination of directive type, and operation, as well as target directive and its enable/disable status of the operation, if specific operation needs it\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned directive\(cqs parameter structure (if applicable) is returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the feature for the given nsid\&. This is optional and most features do not use this value\&. .RE .PP \-D , \-\-dir\-type= .RS 4 Directive type .RE .PP \-S , \-\-dir\-spec= .RS 4 Directive specific .RE .PP \-O , \-\-dir\-oper= .RS 4 Directive operation .RE .PP \-T , \-\-target\-dir= .RS 4 Target directive of the operation .RE .PP \-e , \-\-endir= .RS 4 Target directive enable(1) or disable (0) operation .RE .sp + .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt. T{ .sp Select T}:T{ .sp Description T} T{ .sp 0 T}:T{ .sp Current T} T{ .sp 1 T}:T{ .sp Default T} T{ .sp 2 T}:T{ .sp Saved T} T{ .sp 3 T}:T{ .sp Supported capabilities T} T{ .sp 4\(en7 T}:T{ .sp Reserved T} .TE .sp 1 .PP \-l , \-\-data\-len= .RS 4 The data length for the buffer returned for this feature\&. Most known features do not use this value\&. The exception is LBA Range Type .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw receive buffer to stdout if the command returns a structure\&. .RE .PP \-H, \-\-human\-readable .RS 4 Print the decoded receive buffer to stdout if the command returns a structure\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Enable streams directive : .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-send /dev/nvme0n1 \-\-dir\-type 0 \-\-dir\-oper 1 \-\-target\-dir 1 \-\-endir 1 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Disable streams directive : .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-send /dev/nvme0n1 \-\-dir\-type 0 \-\-dir\-oper 1 \-\-target\-dir 1 \-\-endir 0 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Release all allocated streams resource : .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-send /dev/nvme0n1 \-\-dir\-type 1 \-\-dir\-oper 2 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Release stream ID 3 : .sp .if n \{\ .RS 4 .\} .nf # nvme dir\-send /dev/nvme0 \-\-dir\-type 1 \-\-dir\-oper 1 \-\-dir\-spec 3 .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 nvme-cli-1.5/Documentation/nvme-dir-send.html000066400000000000000000000523241322317423600212510ustar00rootroot00000000000000 nvme-dir-send(1)

SYNOPSIS

nvme dir-send <device> [--namespace-id=<nsid> | -n <nsid>]
                          [--data-len=<data-len> | -l <data-len>]
                          [--dir-type=<dtype> | -D <dtype>]
                          [--dir-spec=<dspec> | -S <dspec>]
                          [--dir-oper=<doper> | -O <doper>]
                          [--endir=<endir> | -e <endir>]
                          [--target-dir=<tdir> | -T <tdir>]
                          [--human-readable | -H]
                          [--raw-binary | -b]

DESCRIPTION

Submits an NVMe Directive Send admin command and returns the applicable results. This may be the combination of directive type, and operation, as well as target directive and its enable/disable status of the operation, if specific operation needs it.

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 directive’s parameter structure (if applicable) is returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the feature for the given nsid. This is optional and most features do not use this value.

-D <dtype>
--dir-type=<dtype>

Directive type

-S <dspec>
--dir-spec=<dspec>

Directive specific

-O <doper>
--dir-oper=<doper>

Directive operation

-T <tdir>
--target-dir=<nsr>

Target directive of the operation

-e <endir>
--endir=<endir>

Target directive enable(1) or disable (0) operation

+

Select

Description

0

Current

1

Default

2

Saved

3

Supported capabilities

4–7

Reserved

-l <data-len>
--data-len=<data-len>

The data length for the buffer returned for this feature. Most known features do not use this value. The exception is LBA Range Type

-b
--raw-binary

Print the raw receive buffer to stdout if the command returns a structure.

-H
--human-readable

Print the decoded receive buffer to stdout if the command returns a structure.

EXAMPLES

  • Enable streams directive :

    # nvme dir-send /dev/nvme0n1 --dir-type 0 --dir-oper 1 --target-dir 1 --endir 1
  • Disable streams directive :

    # nvme dir-send /dev/nvme0n1 --dir-type 0 --dir-oper 1 --target-dir 1 --endir 0
  • Release all allocated streams resource :

    # nvme dir-send /dev/nvme0n1 --dir-type 1 --dir-oper 2
  • Release stream ID 3 :

    # nvme dir-send /dev/nvme0 --dir-type 1 --dir-oper 1 --dir-spec 3

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-dir-send.txt000066400000000000000000000055341322317423600211250ustar00rootroot00000000000000nvme-dir-send(1) ================ NAME ---- nvme-dir-send - Issue a directive send command, returns applicable results SYNOPSIS -------- [verse] 'nvme dir-send' [--namespace-id= | -n ] [--data-len= | -l ] [--dir-type= | -D ] [--dir-spec= | -S ] [--dir-oper= | -O ] [--endir= | -e ] [--target-dir= | -T ] [--human-readable | -H] [--raw-binary | -b] DESCRIPTION ----------- Submits an NVMe Directive Send admin command and returns the applicable results. This may be the combination of directive type, and operation, as well as target directive and its enable/disable status of the operation, if specific operation needs it. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned directive's parameter structure (if applicable) is returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -n :: --namespace-id=:: Retrieve the feature for the given nsid. This is optional and most features do not use this value. -D :: --dir-type=:: Directive type -S :: --dir-spec=:: Directive specific -O :: --dir-oper=:: Directive operation -T :: --target-dir=:: Target directive of the operation -e :: --endir=:: Target directive enable(1) or disable (0) operation + [] |================== |Select|Description |0|Current |1|Default |2|Saved |3|Supported capabilities |4–7|Reserved |================== -l :: --data-len=:: The data length for the buffer returned for this feature. Most known features do not use this value. The exception is LBA Range Type -b:: --raw-binary:: Print the raw receive buffer to stdout if the command returns a structure. -H:: --human-readable:: Print the decoded receive buffer to stdout if the command returns a structure. EXAMPLES -------- * Enable streams directive : + ------------ # nvme dir-send /dev/nvme0n1 --dir-type 0 --dir-oper 1 --target-dir 1 --endir 1 ------------ + * Disable streams directive : + ------------ # nvme dir-send /dev/nvme0n1 --dir-type 0 --dir-oper 1 --target-dir 1 --endir 0 ------------ + * Release all allocated streams resource : + ------------ # nvme dir-send /dev/nvme0n1 --dir-type 1 --dir-oper 2 ------------ + * Release stream ID 3 : + ------------ # nvme dir-send /dev/nvme0 --dir-type 1 --dir-oper 1 --dir-spec 3 ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-disconnect.1000066400000000000000000000052631322317423600210710ustar00rootroot00000000000000'\" t .\" Title: nvme-disconnect .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-DISCONNECT" "1" "12/10/2017" "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-disconnect \- Disonnect one or more Fabrics controller(s)\&. .SH "SYNOPSIS" .sp .nf \fInvme connect\fR [\-\-nqn= | \-n ] [\-\-device= | \-d ] .fi .SH "DESCRIPTION" .sp Disconnects and removes one or more existing NVMe over Fabrics controllers\&. If the \-\-nqn option is specified all controllers connecting to the Subsystem identified by subnqn will be removed\&. If the \-\-device option is specified the controller specified by the \-\-device option will be removed\&. .SH "OPTIONS" .PP \-n , \-\-nqn .RS 4 Indicates that all controllers for the NVMe subsystems specified should be removed\&. .RE .PP \-d , \-\-device .RS 4 Indicates that the controller with the specified name should be removed\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Disconnect all controllers for a subsystem named nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432: .sp .if n \{\ .RS 4 .\} .nf # nvme disconnect \-\-nqn=nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Disconnect the controller nvme4 .sp .if n \{\ .RS 4 .\} .nf # nvme disconnect \-\-device=nvme4 .fi .if n \{\ .RE .\} .RE .sp .if n \{\ .RS 4 .\} .nf SEE ALSO .fi .if n \{\ .RE .\} .sp nvme\-connect(1) .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-disconnect.html000066400000000000000000000447101322317423600216750ustar00rootroot00000000000000 nvme-disconnect(1)

SYNOPSIS

nvme connect
                [--nqn=<subnqn>           | -n <subnqn>]
                [--device=<device>        | -d <device>]

DESCRIPTION

Disconnects and removes one or more existing NVMe over Fabrics controllers. If the --nqn option is specified all controllers connecting to the Subsystem identified by subnqn will be removed. If the --device option is specified the controller specified by the --device option will be removed.

OPTIONS

-n <subnqn>
--nqn <subnqn>

Indicates that all controllers for the NVMe subsystems specified should be removed.

-d <device>
--device <device>

Indicates that the controller with the specified name should be removed.

EXAMPLES

  • Disconnect all controllers for a subsystem named nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432:

    # nvme disconnect --nqn=nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432
  • Disconnect the controller nvme4

    # nvme disconnect --device=nvme4
SEE ALSO

nvme-connect(1)

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-disconnect.txt000066400000000000000000000023001322317423600215350ustar00rootroot00000000000000nvme-disconnect(1) ================== NAME ---- nvme-disconnect - Disonnect one or more Fabrics controller(s). SYNOPSIS -------- [verse] 'nvme connect' [--nqn= | -n ] [--device= | -d ] DESCRIPTION ----------- Disconnects and removes one or more existing NVMe over Fabrics controllers. If the --nqn option is specified all controllers connecting to the Subsystem identified by subnqn will be removed. If the --device option is specified the controller specified by the --device option will be removed. OPTIONS ------- -n :: --nqn :: Indicates that all controllers for the NVMe subsystems specified should be removed. -d :: --device :: Indicates that the controller with the specified name should be removed. EXAMPLES -------- * Disconnect all controllers for a subsystem named nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432: + ------------ # nvme disconnect --nqn=nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 ------------ * Disconnect the controller nvme4 + ------------ # nvme disconnect --device=nvme4 ------------ ------------ SEE ALSO -------- nvme-connect(1) NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-discover.1000066400000000000000000000151161322317423600205540ustar00rootroot00000000000000'\" t .\" Title: nvme-discover .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-DISCOVER" "1" "12/10/2017" "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-discover \- Send Get Log Page request to Discovery Controller\&. .SH "SYNOPSIS" .sp .nf \fInvme discover\fR [\-\-transport= | \-t ] [\-\-traddr= | \-a ] [\-\-trsvcid= | \-s ] [\-\-host\-traddr= | \-w ] [\-\-hostnqn= | \-q ] [\-\-raw= | \-r ] .fi .SH "DESCRIPTION" .sp Send one or more Get Log Page requests to a NVMe\-over\-Fabrics Discovery Controller\&. .sp If no parameters are given, then \fInvme discover\fR will attempt to find a /etc/nvme/discovery\&.conf file to use to supply a list of Discovery commands to run\&. If no /etc/nvme/discovery\&.conf file exists, the command will quit with an error\&. .sp Otherwise, a specific Discovery Controller should be specified using the \-\-transport, \-\-traddr, and if necessary the \-\-trsvcid flags\&. A Diѕcovery request will then be sent to the specified Discovery Controller\&. .SH "BACKGROUND" .sp The NVMe\-over\-Fabrics specification defines the concept of a Discovery Controller that an NVMe Host can query on a fabric network to discover NVMe subsystems contained in NVMe Targets which it can connect to on the network\&. The Discovery Controller will return Discovery Log Pages that provide the NVMe Host with specific information (such as network address and unique subsystem NQN) the NVMe Host can use to issue an NVMe connect command to connect itself to a storage resource contained in that NVMe subsystem on the NVMe Target\&. .sp Note that the base NVMe specfication defines the NQN (NVMe Qualified Name) format which an NVMe endpoint (device, subsystem, etc) must follow to guarantee a unique name under the NVMe standard\&. In particular, the Host NQN uniquely identifies the NVMe Host, and may be used by the the Discovery Controller to control what NVMe Target resources are allocated to the NVMe Host for a connection\&. .sp A Discovery Controller has it\(cqs own NQN defined in the NVMe\-over\-Fabrics specification, \fBnqn\&.2014\-08\&.org\&.nvmexpress\&.discovery\fR\&. All Discovery Controllers must use this NQN name\&. This NQN is used by default by nvme\-cli for the \fIdiscover\fR command\&. .SH "OPTIONS" .PP \-t , \-\-transport= .RS 4 This field specifies the network fabric being used for a NVMe\-over\-Fabrics network\&. Current string values include: .TS allbox tab(:); lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ rdma T}:T{ The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc) T} T{ fc T}:T{ \fBWIP\fR The network fabric is a Fibre Channel network\&. T} T{ loop T}:T{ Connect to a NVMe over Fabrics target on the local host T} .TE .sp 1 .RE .PP \-a , \-\-traddr= .RS 4 This field specifies the network address of the Discovery Controller\&. For transports using IP addressing (e\&.g\&. rdma) this should be an IP\-based (ex\&. IPv4) address\&. .RE .PP \-s , \-\-trsvcid= .RS 4 This field specifies the transport service id\&. For transports using IP addressing (e\&.g\&. rdma) this field is the port number\&. By default, the IP port number for the RDMA transport is 4420\&. .RE .PP \-q , \-\-hostnqn= .RS 4 Overrides the default host NQN that identifies the NVMe Host\&. If this option is not specified, the default is read from /etc/nvme/hostnqn first\&. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next\&. .RE .PP \-w , \-\-host\-traddr= .RS 4 This field specifies the network address used on the host to connect to the Discovery Controller\&. .RE .PP \-r , \-\-raw= .RS 4 This field will take the output of the \fInvme discover\fR command and dump it to a raw binary file\&. By default \fInvme discover\fR will dump the output to stdout\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Query the Discover Controller with IP4 address 192\&.168\&.1\&.3 for all resources allocated for NVMe Host name host1\-rogue\-nqn on the RDMA network\&. Port 4420 is used by default: .sp .if n \{\ .RS 4 .\} .nf # nvme discover \-\-transport=rdma \-\-traddr=192\&.168\&.1\&.3 \e \-\-hostnqn=host1\-rogue\-nqn .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Issue a \fInvme discover\fR command using a /etc/nvme/discovery\&.conf file: .RE .sp .if n \{\ .RS 4 .\} .nf # Machine default \*(Aqnvme discover\*(Aq commands\&. Query the # Discovery Controller\*(Aqs two ports (some resources may only # be accessible on a single port)\&. Note an official # nqn (Host) name defined in the NVMe specification is being used # in this example\&. \-t rdma \-a 192\&.168\&.69\&.33 \-s 4420 \-q nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432 \-t rdma \-a 192\&.168\&.1\&.4 \-s 4420 \-q nqn\&.2014\-08\&.com\&.example:nvme:nvm\-subsystem\-sn\-d78432 At the prompt type "nvme discover"\&. .fi .if n \{\ .RE .\} .SH "SEE ALSO" .sp nvme\-connect(1) nvme\-connect\-all(1) .SH "AUTHORS" .sp This was written by \m[blue]\fBJay Freyensee\fR\m[]\&\s-2\u[1]\d\s+2 for \m[blue]\fBKeith Busch\fR\m[]\&\s-2\u[2]\d\s+2\&. .SH "NVME" .sp Part of the nvme\-user suite .SH "NOTES" .IP " 1." 4 Jay Freyensee .RS 4 \%mailto:james.p.freyensee@intel.com .RE .IP " 2." 4 Keith Busch .RS 4 \%mailto:keith.busch@intel.com .RE nvme-cli-1.5/Documentation/nvme-discover.html000066400000000000000000000571721322317423600213700ustar00rootroot00000000000000 nvme-discover(1)

SYNOPSIS

nvme discover
                [--transport=<trtype>     | -t <trtype>]
                [--traddr=<traddr>        | -a <traddr>]
                [--trsvcid=<trsvcid>      | -s <trsvcid>]
                [--host-traddr=<traddr>   | -w <traddr>]
                [--hostnqn=<hostnqn>      | -q <hostnqn>]
                [--raw=<filename>         | -r <filename>]

DESCRIPTION

Send one or more Get Log Page requests to a NVMe-over-Fabrics Discovery Controller.

If no parameters are given, then nvme discover will attempt to find a /etc/nvme/discovery.conf file to use to supply a list of Discovery commands to run. If no /etc/nvme/discovery.conf file exists, the command will quit with an error.

Otherwise, a specific Discovery Controller should be specified using the --transport, --traddr, and if necessary the --trsvcid flags. A Diѕcovery request will then be sent to the specified Discovery Controller.

BACKGROUND

The NVMe-over-Fabrics specification defines the concept of a Discovery Controller that an NVMe Host can query on a fabric network to discover NVMe subsystems contained in NVMe Targets which it can connect to on the network. The Discovery Controller will return Discovery Log Pages that provide the NVMe Host with specific information (such as network address and unique subsystem NQN) the NVMe Host can use to issue an NVMe connect command to connect itself to a storage resource contained in that NVMe subsystem on the NVMe Target.

Note that the base NVMe specfication defines the NQN (NVMe Qualified Name) format which an NVMe endpoint (device, subsystem, etc) must follow to guarantee a unique name under the NVMe standard. In particular, the Host NQN uniquely identifies the NVMe Host, and may be used by the the Discovery Controller to control what NVMe Target resources are allocated to the NVMe Host for a connection.

A Discovery Controller has it’s own NQN defined in the NVMe-over-Fabrics specification, nqn.2014-08.org.nvmexpress.discovery. All Discovery Controllers must use this NQN name. This NQN is used by default by nvme-cli for the discover command.

OPTIONS

-t <trtype>
--transport=<trtype>

This field specifies the network fabric being used for a NVMe-over-Fabrics network. Current string values include:

Value

Definition

rdma

The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc)

fc

WIP The network fabric is a Fibre Channel network.

loop

Connect to a NVMe over Fabrics target on the local host

-a <traddr>
--traddr=<traddr>

This field specifies the network address of the Discovery Controller. For transports using IP addressing (e.g. rdma) this should be an IP-based (ex. IPv4) address.

-s <trsvcid>
--trsvcid=<trsvcid>

This field specifies the transport service id. For transports using IP addressing (e.g. rdma) this field is the port number. By default, the IP port number for the RDMA transport is 4420.

-q <hostnqn>
--hostnqn=<hostnqn>

Overrides the default host NQN that identifies the NVMe Host. If this option is not specified, the default is read from /etc/nvme/hostnqn first. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next.

-w <traddr>
--host-traddr=<traddr>

This field specifies the network address used on the host to connect to the Discovery Controller.

-r <filename>
--raw=<filename>

This field will take the output of the nvme discover command and dump it to a raw binary file. By default nvme discover will dump the output to stdout.

EXAMPLES

  • Query the Discover Controller with IP4 address 192.168.1.3 for all resources allocated for NVMe Host name host1-rogue-nqn on the RDMA network. Port 4420 is used by default:

    # nvme discover --transport=rdma --traddr=192.168.1.3 \
    --hostnqn=host1-rogue-nqn
  • Issue a nvme discover command using a /etc/nvme/discovery.conf file:

# Machine default 'nvme discover' commands.  Query the
# Discovery Controller's two ports (some resources may only
# be accessible on a single port).  Note an official
# nqn (Host) name defined in the NVMe specification is being used
# in this example.
-t rdma -a 192.168.69.33 -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432
-t rdma -a 192.168.1.4   -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432

At the prompt type "nvme discover".

SEE ALSO

nvme-connect(1) nvme-connect-all(1)

AUTHORS

This was written by Jay Freyensee for Keith Busch.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-discover.txt000066400000000000000000000112471322317423600212340ustar00rootroot00000000000000nvme-discover(1) ============== NAME ---- nvme-discover - Send Get Log Page request to Discovery Controller. SYNOPSIS -------- [verse] 'nvme discover' [--transport= | -t ] [--traddr= | -a ] [--trsvcid= | -s ] [--host-traddr= | -w ] [--hostnqn= | -q ] [--raw= | -r ] DESCRIPTION ----------- Send one or more Get Log Page requests to a NVMe-over-Fabrics Discovery Controller. If no parameters are given, then 'nvme discover' will attempt to find a /etc/nvme/discovery.conf file to use to supply a list of Discovery commands to run. If no /etc/nvme/discovery.conf file exists, the command will quit with an error. Otherwise, a specific Discovery Controller should be specified using the --transport, --traddr, and if necessary the --trsvcid flags. A Diѕcovery request will then be sent to the specified Discovery Controller. BACKGROUND ---------- The NVMe-over-Fabrics specification defines the concept of a Discovery Controller that an NVMe Host can query on a fabric network to discover NVMe subsystems contained in NVMe Targets which it can connect to on the network. The Discovery Controller will return Discovery Log Pages that provide the NVMe Host with specific information (such as network address and unique subsystem NQN) the NVMe Host can use to issue an NVMe connect command to connect itself to a storage resource contained in that NVMe subsystem on the NVMe Target. Note that the base NVMe specfication defines the NQN (NVMe Qualified Name) format which an NVMe endpoint (device, subsystem, etc) must follow to guarantee a unique name under the NVMe standard. In particular, the Host NQN uniquely identifies the NVMe Host, and may be used by the the Discovery Controller to control what NVMe Target resources are allocated to the NVMe Host for a connection. A Discovery Controller has it's own NQN defined in the NVMe-over-Fabrics specification, *nqn.2014-08.org.nvmexpress.discovery*. All Discovery Controllers must use this NQN name. This NQN is used by default by nvme-cli for the 'discover' command. OPTIONS ------- -t :: --transport=:: This field specifies the network fabric being used for a NVMe-over-Fabrics network. Current string values include: + [] |================= |Value|Definition |rdma|The network fabric is an rdma network (RoCE, iWARP, Infiniband, basic rdma, etc) |fc |*WIP* The network fabric is a Fibre Channel network. |loop|Connect to a NVMe over Fabrics target on the local host |================= -a :: --traddr=:: This field specifies the network address of the Discovery Controller. For transports using IP addressing (e.g. rdma) this should be an IP-based (ex. IPv4) address. -s :: --trsvcid=:: This field specifies the transport service id. For transports using IP addressing (e.g. rdma) this field is the port number. By default, the IP port number for the RDMA transport is 4420. -q :: --hostnqn=:: Overrides the default host NQN that identifies the NVMe Host. If this option is not specified, the default is read from /etc/nvme/hostnqn first. If that does not exist, the autogenerated NQN value from the NVMe Host kernel module is used next. -w :: --host-traddr=:: This field specifies the network address used on the host to connect to the Discovery Controller. -r :: --raw=:: This field will take the output of the 'nvme discover' command and dump it to a raw binary file. By default 'nvme discover' will dump the output to stdout. EXAMPLES -------- * Query the Discover Controller with IP4 address 192.168.1.3 for all resources allocated for NVMe Host name host1-rogue-nqn on the RDMA network. Port 4420 is used by default: + ------------ # nvme discover --transport=rdma --traddr=192.168.1.3 \ --hostnqn=host1-rogue-nqn ------------ + * Issue a 'nvme discover' command using a /etc/nvme/discovery.conf file: ----------- # Machine default 'nvme discover' commands. Query the # Discovery Controller's two ports (some resources may only # be accessible on a single port). Note an official # nqn (Host) name defined in the NVMe specification is being used # in this example. -t rdma -a 192.168.69.33 -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 -t rdma -a 192.168.1.4 -s 4420 -q nqn.2014-08.com.example:nvme:nvm-subsystem-sn-d78432 At the prompt type "nvme discover". ------------ SEE ALSO -------- nvme-connect(1) nvme-connect-all(1) AUTHORS ------- This was written by mailto:james.p.freyensee@intel.com[Jay Freyensee] for mailto:keith.busch@intel.com[Keith Busch]. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-dsm.1000066400000000000000000000073041322317423600175210ustar00rootroot00000000000000'\" t .\" Title: nvme-dsm .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-DSM" "1" "12/10/2017" "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-dsm \- Send NVMe Data Set Management, return results .SH "SYNOPSIS" .sp .nf \fInvme dsm\fR [ \-\-namespace\-id= | \-n ] [ \-\-ctx\-attrs= | \-a ] [ \-\-blocks= | \-b ] [ \-\-slbs= | \-s ] [ \-\-ad | \-d ] [ \-\-idw | \-w ] [ \-\-idr | \-r ] [ \-\-cdw11= | \-c ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an Data Set Management command and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. If the character device is given, the \*(Aq\-\-namespace\-id\*(Aq option is mandatory, otherwise it will use the ns\-id of the namespace for the block device you opened\&. For block devices, the ns\-id used can be overridden with the same option\&. .sp You must specify at least one of the values for range list\&. If the range lists provided do not list the same number of elements, the default values for the remaining in the range will be set to 0\&. .sp The command dword 11 may be provided at the command line\&. For convenience, the current defined attributes (discard, integral read/write) for a data\-set management have flags\&. If cdw11 is specified, this will override any settings from the flags may have provided\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Sends the command with the requested nsid\&. This is required for the character devices, or overrides the block nsid if given\&. .RE .PP \-a , \-\-ctx\-attrs= .RS 4 Comma separated list of the context attributes in each range .RE .PP \-b , \-\-blocks= .RS 4 Comma separated list of the number of blocks in each range .RE .PP \-s , \-\-slbs= .RS 4 Comma separated list of the starting block in each range .RE .PP \-d , \-\-ad= .RS 4 Attribute Deallocate\&. .RE .PP \-w , \-\-idw= .RS 4 Attribute Integral Dataset for Write\&. .RE .PP \-r , \-\-idr= .RS 4 Attribute Integral Dataset for Read\&. .RE .PP \-c , \-\-cdw11= .RS 4 All the command command dword 11 attributes\&. Use exclusive from specifying individual attributes .RE .SH "EXAMPLES" .sp No examples yet .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-dsm.html000066400000000000000000000500731322317423600203260ustar00rootroot00000000000000 nvme-dsm(1)

SYNOPSIS

nvme dsm <device>  [ --namespace-id=<nsid> | -n <nsid> ]
                        [ --ctx-attrs=<attribute-list,> | -a <attribute-list,> ]
                        [ --blocks=<nlb-list,> | -b <nlb-list,> ]
                        [ --slbs=<slba-list,> | -s <slba-list,> ]
                        [ --ad | -d ] [ --idw | -w ] [ --idr | -r ]
                        [ --cdw11=<cdw11> | -c <cdw11> ]

DESCRIPTION

For the NVMe device given, sends an Data Set Management command and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the character device is given, the '--namespace-id' option is mandatory, otherwise it will use the ns-id of the namespace for the block device you opened. For block devices, the ns-id used can be overridden with the same option.

You must specify at least one of the values for range list. If the range lists provided do not list the same number of elements, the default values for the remaining in the range will be set to 0.

The command dword 11 may be provided at the command line. For convenience, the current defined attributes (discard, integral read/write) for a data-set management have flags. If cdw11 is specified, this will override any settings from the flags may have provided.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Sends the command with the requested nsid. This is required for the character devices, or overrides the block nsid if given.

-a <attribute-list,>
--ctx-attrs=<attribute-list>

Comma separated list of the context attributes in each range

-b <nlb-list,>
--blocks=<nlb-list,>

Comma separated list of the number of blocks in each range

-s <slba-list,>
--slbs=<slba-list,>

Comma separated list of the starting block in each range

-d <deallocate>
--ad=<deallocate>

Attribute Deallocate.

-w <write>
--idw=<write>

Attribute Integral Dataset for Write.

-r <read>
--idr=<read>

Attribute Integral Dataset for Read.

-c <cdw11>
--cdw11=<cdw11>

All the command command dword 11 attributes. Use exclusive from specifying individual attributes

EXAMPLES

No examples yet

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-dsm.txt000066400000000000000000000043641322317423600202030ustar00rootroot00000000000000nvme-dsm(1) =========== NAME ---- nvme-dsm - Send NVMe Data Set Management, return results SYNOPSIS -------- [verse] 'nvme dsm' [ --namespace-id= | -n ] [ --ctx-attrs= | -a ] [ --blocks= | -b ] [ --slbs= | -s ] [ --ad | -d ] [ --idw | -w ] [ --idr | -r ] [ --cdw11= | -c ] DESCRIPTION ----------- For the NVMe device given, sends an Data Set Management command and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the character device is given, the `'--namespace-id'` option is mandatory, otherwise it will use the ns-id of the namespace for the block device you opened. For block devices, the ns-id used can be overridden with the same option. You must specify at least one of the values for range list. If the range lists provided do not list the same number of elements, the default values for the remaining in the range will be set to 0. The command dword 11 may be provided at the command line. For convenience, the current defined attributes (discard, integral read/write) for a data-set management have flags. If cdw11 is specified, this will override any settings from the flags may have provided. OPTIONS ------- -n :: --namespace-id=:: Sends the command with the requested nsid. This is required for the character devices, or overrides the block nsid if given. -a :: --ctx-attrs=:: Comma separated list of the context attributes in each range -b :: --blocks=:: Comma separated list of the number of blocks in each range -s :: --slbs=:: Comma separated list of the starting block in each range -d :: --ad=:: Attribute Deallocate. -w :: --idw=:: Attribute Integral Dataset for Write. -r :: --idr=:: Attribute Integral Dataset for Read. -c :: --cdw11=:: All the command command dword 11 attributes. Use exclusive from specifying individual attributes EXAMPLES -------- No examples yet NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-effects-log.1000066400000000000000000000040141322317423600211270ustar00rootroot00000000000000'\" t .\" Title: nvme-effects-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-EFFECTS\-LOG" "1" "12/10/2017" "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-effects-log \- Send NVMe Command Effects log page request, returns result and log .SH "SYNOPSIS" .sp .nf \fInvme effects\-log\fR .fi .SH "DESCRIPTION" .sp Retrieves the NVMe Command Effects log page from an NVMe device and provides the retuned structure\&. .sp The parameter is mandatory and should be the NVMe character device (ex: /dev/nvme0)\&. .sp On success, the returned command effects log structure will be printed for each command that is supported\&. .SH "OPTIONS" .sp No options\&. .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Print the effects log page in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme effects\-log /dev/nvme0 .fi .if n \{\ .RE .\} .sp Not much to it\&. .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-effects-log.html000066400000000000000000000432321322317423600217400ustar00rootroot00000000000000 nvme-effects-log(1)

SYNOPSIS

nvme effects-log <device>

DESCRIPTION

Retrieves the NVMe Command Effects log page from an NVMe device and provides the retuned structure.

The <device> parameter is mandatory and should be the NVMe character device (ex: /dev/nvme0).

On success, the returned command effects log structure will be printed for each command that is supported.

OPTIONS

No options.

EXAMPLES

  • Print the effects log page in a human readable format:

    # nvme effects-log /dev/nvme0

    Not much to it.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-effects-log.txt000066400000000000000000000013461322317423600216130ustar00rootroot00000000000000nvme-effects-log(1) =================== NAME ---- nvme-effects-log - Send NVMe Command Effects log page request, returns result and log SYNOPSIS -------- [verse] 'nvme effects-log' DESCRIPTION ----------- Retrieves the NVMe Command Effects log page from an NVMe device and provides the retuned structure. The parameter is mandatory and should be the NVMe character device (ex: /dev/nvme0). On success, the returned command effects log structure will be printed for each command that is supported. OPTIONS ------- No options. EXAMPLES -------- * Print the effects log page in a human readable format: + ------------ # nvme effects-log /dev/nvme0 ------------ + Not much to it. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-error-log.1000066400000000000000000000067651322317423600206600ustar00rootroot00000000000000'\" t .\" Title: nvme-error-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ERROR\-LOG" "1" "12/10/2017" "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-error-log \- Send NVME Error log page request, return result and log .SH "SYNOPSIS" .sp .nf \fInvme error\-log\fR [\-\-namespace\-id= | \-n ] [\-\-log\-entries= | \-e ] [\-\-raw\-binary | \-b] [\-\-output\-format= | \-o ] .fi .SH "DESCRIPTION" .sp Retrieves NVMe Error log page from an NVMe device and provides the retuned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned error 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 or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the Error Log for the given nsid\&. This is optional and its success may depend on the device\(cqs capabilities to provide this log on a per\-namespace basis (see the NVMe Identify Controller for this capability)\&. The default nsid to use is 0xffffffff for the device global error log\&. .RE .PP \-e , \-\-log\-entries= .RS 4 Specifies how many log entries the program should request from the device\&. This must be at least one, and shouldn\(cqt exceed the device\(cqs capabilities\&. Defaults to 64 log entries\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw error log buffer to stdout\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Get the error log and print it in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme error\-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 output to a file: .sp .if n \{\ .RS 4 .\} .nf # nvme error\-log /dev/nvme0 \-\-raw\-binary > error_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 nvme-cli-1.5/Documentation/nvme-error-log.html000066400000000000000000000470461322317423600214610ustar00rootroot00000000000000 nvme-error-log(1)

SYNOPSIS

nvme error-log <device>  [--namespace-id=<nsid> | -n <nsid>]
                         [--log-entries=<entries> | -e <entries>]
                         [--raw-binary | -b]
                         [--output-format=<fmt> | -o <fmt>]

DESCRIPTION

Retrieves NVMe Error log page from an NVMe device and provides the retuned 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 error 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 or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the Error Log for the given nsid. This is optional and its success may depend on the device’s capabilities to provide this log on a per-namespace basis (see the NVMe Identify Controller for this capability). The default nsid to use is 0xffffffff for the device global error log.

-e <entries>
--log-entries=<entries>

Specifies how many log entries the program should request from the device. This must be at least one, and shouldn’t exceed the device’s capabilities. Defaults to 64 log entries.

-b
--raw-binary

Print the raw error 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

  • Get the error log and print it in a human readable format:

    # nvme error-log /dev/nvme0
  • Print the raw output to a file:

    # nvme error-log /dev/nvme0 --raw-binary > error_log.raw

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-error-log.txt000066400000000000000000000037411322317423600213260ustar00rootroot00000000000000nvme-error-log(1) ================= NAME ---- nvme-error-log - Send NVME Error log page request, return result and log SYNOPSIS -------- [verse] 'nvme error-log' [--namespace-id= | -n ] [--log-entries= | -e ] [--raw-binary | -b] [--output-format= | -o ] DESCRIPTION ----------- Retrieves NVMe Error log page from an NVMe device and provides the retuned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned error 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 or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -n :: --namespace-id=:: Retrieve the Error Log for the given nsid. This is optional and its success may depend on the device's capabilities to provide this log on a per-namespace basis (see the NVMe Identify Controller for this capability). The default nsid to use is 0xffffffff for the device global error log. -e :: --log-entries=:: Specifies how many log entries the program should request from the device. This must be at least one, and shouldn't exceed the device's capabilities. Defaults to 64 log entries. -b:: --raw-binary:: Print the raw error log buffer to stdout. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Get the error log and print it in a human readable format: + ------------ # nvme error-log /dev/nvme0 ------------ + * Print the raw output to a file: + ------------ # nvme error-log /dev/nvme0 --raw-binary > error_log.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-flush.1000066400000000000000000000036171322317423600200620ustar00rootroot00000000000000'\" t .\" Title: nvme-flush .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-FLUSH" "1" "12/10/2017" "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-flush \- Flush command\&. .SH "SYNOPSIS" .sp .nf \fInvme flush\fR [\-\-namespace\-id= | \-n ] .fi .SH "DESCRIPTION" .sp The Flush command shall commit data and metadata associated with the specified namespace(s) to nonvolatile media\&. The flush applies to all commands completed prior to the submission of the Flush command\&. The controller may also flush additional data and/or metadata from any namespace\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Specify the optional namespace id for this command\&. Defaults to 0xffffffff, indicating flush for all namespaces\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-flush.html000066400000000000000000000430531322317423600206640ustar00rootroot00000000000000 nvme-flush(1)

SYNOPSIS

nvme flush <device> [--namespace-id=<nsid> | -n <nsid>]

DESCRIPTION

The Flush command shall commit data and metadata associated with the specified namespace(s) to nonvolatile media. The flush applies to all commands completed prior to the submission of the Flush command. The controller may also flush additional data and/or metadata from any namespace.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Specify the optional namespace id for this command. Defaults to 0xffffffff, indicating flush for all namespaces.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-flush.txt000066400000000000000000000013021322317423600205260ustar00rootroot00000000000000nvme-flush(1) ============= NAME ---- nvme-flush - Flush command. SYNOPSIS -------- [verse] 'nvme flush' [--namespace-id= | -n ] DESCRIPTION ----------- The Flush command shall commit data and metadata associated with the specified namespace(s) to nonvolatile media. The flush applies to all commands completed prior to the submission of the Flush command. The controller may also flush additional data and/or metadata from any namespace. OPTIONS ------- -n :: --namespace-id=:: Specify the optional namespace id for this command. Defaults to 0xffffffff, indicating flush for all namespaces. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-format.1000066400000000000000000000137321322317423600202300ustar00rootroot00000000000000'\" t .\" Title: nvme-format .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-FORMAT" "1" "12/10/2017" "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-format \- Format an NVMe device .SH "SYNOPSIS" .sp .nf \fInvme format\fR [\-\-namespace\-id= | \-n ] [\-\-lbaf= | \-l ] [\-\-ses= | \-s ] [\-\-pil= | \-p ] [\-\-pi= | \-i ] [\-\-ms= | \-m ] [\-\-reset | \-r ] [\-\-timeout | \-t ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, send an nvme Format Namespace admin command and provides the results\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. If the character device is given, the namespace identifier will default to 0xffffffff to send the format to all namespace, but can be overridden to any namespace with the \fInamespace\-id\fR option\&. If the block device is given, the namespace identifier will default to the namespace id of the block device given, but can be overridden with the same option\&. .sp On success, the program will automatically issue BLKRRPART ioctl to force rescanning the namespaces\&. If the driver is recent enough, this will automatically update the physical block size\&. If it is not recent enough, you will need to remove and rescan your device some other way for the new block size to be visible\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Send the format command for the specified nsid\&. This can be used to override the default value for either character device (0xffffffff) or the block device (result from NVME_IOCTL_ID)\&. .RE .PP \-l , \-\-lbaf= .RS 4 LBA Format: This field specifies the LBA format to apply to the NVM media\&. This corresponds to the LBA formats indicated in the Identify Namespace command\&. Defaults to 0\&. .RE .PP \-s , \-\-ses= .RS 4 Secure Erase Settings: This field specifies whether a secure erase should be performed as part of the format and the type of the secure erase operation\&. The erase applies to all user data, regardless of location (e\&.g\&., within an exposed LBA, within a cache, within deallocated LBAs, etc)\&. Defaults to 0\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0 T}:T{ No secure erase operation requested T} T{ 1 T}:T{ User Data Erase: All user data shall be erased, contents of the user data after the erase is indeterminate (e\&.g\&., the user data may be zero filled, one filled, etc)\&. The controller may perform a cryptographic erase when a User Data Erase is requested if all user data is encrypted\&. T} T{ 2 T}:T{ Cryptographic Erase: All user data shall be erased cryptographically\&. This is accomplished by deleting the encryption key\&. T} T{ 3\(en7 T}:T{ Reserved T} .TE .sp 1 .RE .PP \-p , \-\-pil= .RS 4 Protection Information Location: If set to \(oq1\(cq and protection information is enabled, then protection information is transferred as the first eight bytes of metadata\&. If cleared to \(oq0\(cq and protection information is enabled, then protection information is transferred as the last eight bytes of metadata\&. Defaults to 0\&. .RE .PP \-i , \-\-pi= .RS 4 Protection Information: This field specifies whether end\-to\-end data protection is enabled and the type of protection information\&. Defaults to 0\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0 T}:T{ Protection information is not enabled T} T{ 1 T}:T{ Protection information is enabled, Type 1 T} T{ 2 T}:T{ Protection information is enabled, Type 2 T} T{ 3 T}:T{ Protection information is enabled, Type 3 T} T{ 4\(en7 T}:T{ Reserved T} .TE .sp 1 .RE .PP \-m , \-\-ms= .RS 4 Metadata Settings: This field is set to \(oq1\(cq if the metadata is transferred as part of an extended data LBA\&. This field is cleared to \(oq0\(cq if the metadata is transferred as part of a separate buffer\&. The metadata may include protection information, based on the Protection Information (PI) field\&. Defaults to 0\&. .RE .PP \-r, \-\-reset .RS 4 Issue a reset after successful format\&. Must use the character device for this\&. .RE .PP \-t , \-\-timeout= .RS 4 Override default timeout value\&. In milliseconds\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Format the device using all defaults: .sp .if n \{\ .RS 4 .\} .nf # nvme format /dev/nvme0n1 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Format namespace 1 with user data secure erase settings and protection information: .sp .if n \{\ .RS 4 .\} .nf # nvme format /dev/nvme0 \-\-namespace\-id=1 \-\-ses=1 \-\-pi=1 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-format.html000066400000000000000000000575661322317423600210510ustar00rootroot00000000000000 nvme-format(1)

SYNOPSIS

nvme format <device> [--namespace-id=<nsid> | -n <nsid>]
                    [--lbaf=<lbaf> | -l <lbaf>]
                    [--ses=<ses> | -s <ses>]
                    [--pil=<pil> | -p <pil>]
                    [--pi=<pi> | -i <pi>]
                    [--ms=<ms> | -m <ms>]
                    [--reset | -r ]
                    [--timeout | -t ]

DESCRIPTION

For the NVMe device given, send an nvme Format Namespace admin command and provides the results.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the character device is given, the namespace identifier will default to 0xffffffff to send the format to all namespace, but can be overridden to any namespace with the namespace-id option. If the block device is given, the namespace identifier will default to the namespace id of the block device given, but can be overridden with the same option.

On success, the program will automatically issue BLKRRPART ioctl to force rescanning the namespaces. If the driver is recent enough, this will automatically update the physical block size. If it is not recent enough, you will need to remove and rescan your device some other way for the new block size to be visible.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Send the format command for the specified nsid. This can be used to override the default value for either character device (0xffffffff) or the block device (result from NVME_IOCTL_ID).

-l <lbaf>
--lbaf=<lbaf>

LBA Format: This field specifies the LBA format to apply to the NVM media. This corresponds to the LBA formats indicated in the Identify Namespace command. Defaults to 0.

-s <ses>
--ses=<ses>

Secure Erase Settings: This field specifies whether a secure erase should be performed as part of the format and the type of the secure erase operation. The erase applies to all user data, regardless of location (e.g., within an exposed LBA, within a cache, within deallocated LBAs, etc). Defaults to 0.

Value

Definition

0

No secure erase operation requested

1

User Data Erase: All user data shall be erased, contents of the user data after the erase is indeterminate (e.g., the user data may be zero filled, one filled, etc). The controller may perform a cryptographic erase when a User Data Erase is requested if all user data is encrypted.

2

Cryptographic Erase: All user data shall be erased cryptographically. This is accomplished by deleting the encryption key.

3–7

Reserved

-p <pil>
--pil=<pil>

Protection Information Location: If set to ‘1’ and protection information is enabled, then protection information is transferred as the first eight bytes of metadata. If cleared to ‘0’ and protection information is enabled, then protection information is transferred as the last eight bytes of metadata. Defaults to 0.

-i <pi>
--pi=<pi>

Protection Information: This field specifies whether end-to-end data protection is enabled and the type of protection information. Defaults to 0.

Value

Definition

0

Protection information is not enabled

1

Protection information is enabled, Type 1

2

Protection information is enabled, Type 2

3

Protection information is enabled, Type 3

4–7

Reserved

-m <ms>
--ms=<ms>

Metadata Settings: This field is set to ‘1’ if the metadata is transferred as part of an extended data LBA. This field is cleared to ‘0’ if the metadata is transferred as part of a separate buffer. The metadata may include protection information, based on the Protection Information (PI) field. Defaults to 0.

-r
--reset

Issue a reset after successful format. Must use the character device for this.

-t <timeout>
--timeout=<timeout>

Override default timeout value. In milliseconds.

EXAMPLES

  • Format the device using all defaults:

    # nvme format /dev/nvme0n1
  • Format namespace 1 with user data secure erase settings and protection information:

    # nvme format /dev/nvme0 --namespace-id=1 --ses=1 --pi=1

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-format.txt000066400000000000000000000102311322317423600206760ustar00rootroot00000000000000nvme-format(1) ============== NAME ---- nvme-format - Format an NVMe device SYNOPSIS -------- [verse] 'nvme format' [--namespace-id= | -n ] [--lbaf= | -l ] [--ses= | -s ] [--pil= | -p ] [--pi= | -i ] [--ms= | -m ] [--reset | -r ] [--timeout | -t ] DESCRIPTION ----------- For the NVMe device given, send an nvme Format Namespace admin command and provides the results. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the character device is given, the namespace identifier will default to 0xffffffff to send the format to all namespace, but can be overridden to any namespace with the 'namespace-id' option. If the block device is given, the namespace identifier will default to the namespace id of the block device given, but can be overridden with the same option. On success, the program will automatically issue BLKRRPART ioctl to force rescanning the namespaces. If the driver is recent enough, this will automatically update the physical block size. If it is not recent enough, you will need to remove and rescan your device some other way for the new block size to be visible. OPTIONS ------- -n :: --namespace-id=:: Send the format command for the specified nsid. This can be used to override the default value for either character device (0xffffffff) or the block device (result from NVME_IOCTL_ID). -l :: --lbaf=:: LBA Format: This field specifies the LBA format to apply to the NVM media. This corresponds to the LBA formats indicated in the Identify Namespace command. Defaults to 0. -s :: --ses=:: Secure Erase Settings: This field specifies whether a secure erase should be performed as part of the format and the type of the secure erase operation. The erase applies to all user data, regardless of location (e.g., within an exposed LBA, within a cache, within deallocated LBAs, etc). Defaults to 0. + [] |================= |Value|Definition |0|No secure erase operation requested |1|User Data Erase: All user data shall be erased, contents of the user data after the erase is indeterminate (e.g., the user data may be zero filled, one filled, etc). The controller may perform a cryptographic erase when a User Data Erase is requested if all user data is encrypted. |2|Cryptographic Erase: All user data shall be erased cryptographically. This is accomplished by deleting the encryption key. |3–7|Reserved |================= -p :: --pil=:: Protection Information Location: If set to ‘1’ and protection information is enabled, then protection information is transferred as the first eight bytes of metadata. If cleared to ‘0’ and protection information is enabled, then protection information is transferred as the last eight bytes of metadata. Defaults to 0. -i :: --pi=:: Protection Information: This field specifies whether end-to-end data protection is enabled and the type of protection information. Defaults to 0. + [] |================= |Value|Definition |0|Protection information is not enabled |1|Protection information is enabled, Type 1 |2|Protection information is enabled, Type 2 |3|Protection information is enabled, Type 3 |4–7|Reserved |================= -m :: --ms=:: Metadata Settings: This field is set to ‘1’ if the metadata is transferred as part of an extended data LBA. This field is cleared to ‘0’ if the metadata is transferred as part of a separate buffer. The metadata may include protection information, based on the Protection Information (PI) field. Defaults to 0. -r:: --reset:: Issue a reset after successful format. Must use the character device for this. -t :: --timeout=:: Override default timeout value. In milliseconds. EXAMPLES -------- * Format the device using all defaults: + ------------ # nvme format /dev/nvme0n1 ------------ + * Format namespace 1 with user data secure erase settings and protection information: + ------------ # nvme format /dev/nvme0 --namespace-id=1 --ses=1 --pi=1 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-fw-commit.1000066400000000000000000000105371322317423600206420ustar00rootroot00000000000000'\" t .\" Title: nvme-fw-commit .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 12/19/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-FW\-COMMIT" "1" "12/19/2017" "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-fw-commit \- Used to verify and commit a firmware image\&. .SH "SYNOPSIS" .sp .nf \fInvme fw\-commit\fR [\-\-slot= | \-s ] [\-\-action= | \-a ] [\-\-bpid= | \-b ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, send an nvme Firmware Commit admin command and provides the results\&. .sp The Firmware Commit command is used to verify that a valid firmware image has been downloaded and to commit that revision to a specific firmware slot\&. The host may select the firmware image to commit on the next controller reset (CC\&.EN transitions from \(oq1\(cq to \(oq0\(cq, a PCI function level reset, and/or other Controller or NVM Subsystem Reset) as part of this command\&. The currently executing firmware revision may be determined from the Firmware Revision field of the Identify Controller data structure as indicated in the Firmware Slot Information log page\&. .sp No further action is automatically taken to reset the device, which is usually required to complete the activation process\&. If your kernel and driver are recent enough, you can commit the firmware by issuing a reset through Linux sysfs, for example: .sp .if n \{\ .RS 4 .\} .nf # echo 1 > /sys/class/nvme/nvme0/device/reset .fi .if n \{\ .RE .\} .sp If your kernel is not recent enough, you will need to remove and add the device some other way\&. .SH "OPTIONS" .PP \-a , \-\-action= .RS 4 Commit Action: This field specifies the action that is taken on the image downloaded with the Firmware Image Download command or on a previously downloaded and placed image\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0 T}:T{ Downloaded image replaces the image indicated by the Firmware Slot field\&. This image is not activated\&. T} T{ 1 T}:T{ Downloaded image replaces the image indicated by the Firmware Slot field\&. This image is activated at the next reset\&. T} T{ 2 T}:T{ The image indicated by the Firmware Slot field is activated at the next reset\&. T} T{ 3 T}:T{ The image specified by the Firmware Slot field is requested to be activated immediately without reset\&. T} T{ 6 T}:T{ Downloaded image replaces the Boot Partition specified by the Boot Partition ID field\&. T} T{ 7 T}:T{ Mark the Boot Partition specified in the BPID field as active and update BPINFO\&.ABPID\&. T} .TE .sp 1 .RE .PP \-s , \-\-slot= .RS 4 Firmware Slot: Specifies the firmware slot that shall be used for the Commit Action, if applicable\&. If the value specified is 0h, then the controller shall choose the firmware slot (slot 1 \(en 7) to use for the operation\&. .RE .PP \-\-bpid=, \-b .RS 4 Specifiies the Boot partition that shall be used for the Commit Action, if applicable (default: 0) .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} commit the last downloaded fw to slot 1\&. .sp .if n \{\ .RS 4 .\} .nf # nvme fw\-commit /dev/nvme0 \-\-slot=1 \-\-action=2 .fi .if n \{\ .RE .\} .RE .SH "ALIAS" .sp fw\-activate .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-fw-commit.html000066400000000000000000000525161322317423600214510ustar00rootroot00000000000000 nvme-fw-commit(1)

SYNOPSIS

nvme fw-commit <device> [--slot=<slot> | -s <slot>]
                    [--action=<action> | -a <action>]
                    [--bpid=<boot-partid> | -b <boot-partid> ]

DESCRIPTION

For the NVMe device given, send an nvme Firmware Commit admin command and provides the results.

The Firmware Commit command is used to verify that a valid firmware image has been downloaded and to commit that revision to a specific firmware slot. The host may select the firmware image to commit on the next controller reset (CC.EN transitions from ‘1’ to ‘0’, a PCI function level reset, and/or other Controller or NVM Subsystem Reset) as part of this command. The currently executing firmware revision may be determined from the Firmware Revision field of the Identify Controller data structure as indicated in the Firmware Slot Information log page.

No further action is automatically taken to reset the device, which is usually required to complete the activation process. If your kernel and driver are recent enough, you can commit the firmware by issuing a reset through Linux sysfs, for example:

 # echo 1 > /sys/class/nvme/nvme0/device/reset

If your kernel is not recent enough, you will need to remove and add the device some other way.

OPTIONS

-a <action>
--action=<action>

Commit Action: This field specifies the action that is taken on the image downloaded with the Firmware Image Download command or on a previously downloaded and placed image.

Value

Definition

0

Downloaded image replaces the image indicated by the Firmware Slot field. This image is not activated.

1

Downloaded image replaces the image indicated by the Firmware Slot field. This image is activated at the next reset.

2

The image indicated by the Firmware Slot field is activated at the next reset.

3

The image specified by the Firmware Slot field is requested to be activated immediately without reset.

6

Downloaded image replaces the Boot Partition specified by the Boot Partition ID field.

7

Mark the Boot Partition specified in the BPID field as active and update BPINFO.ABPID.

-s <slot>
--slot=<slot>

Firmware Slot: Specifies the firmware slot that shall be used for the Commit Action, if applicable. If the value specified is 0h, then the controller shall choose the firmware slot (slot 1 – 7) to use for the operation.

--bpid=<boot-partid>
-b <boot-partid>

Specifiies the Boot partition that shall be used for the Commit Action, if applicable (default: 0)

EXAMPLES

  • commit the last downloaded fw to slot 1.

    # nvme fw-commit /dev/nvme0 --slot=1 --action=2

ALIAS

fw-activate

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-fw-commit.txt000066400000000000000000000054701322317423600213210ustar00rootroot00000000000000nvme-fw-commit(1) ================= NAME ---- nvme-fw-commit - Used to verify and commit a firmware image. SYNOPSIS -------- [verse] 'nvme fw-commit' [--slot= | -s ] [--action= | -a ] [--bpid= | -b ] DESCRIPTION ----------- For the NVMe device given, send an nvme Firmware Commit admin command and provides the results. The Firmware Commit command is used to verify that a valid firmware image has been downloaded and to commit that revision to a specific firmware slot. The host may select the firmware image to commit on the next controller reset (CC.EN transitions from ‘1’ to ‘0’, a PCI function level reset, and/or other Controller or NVM Subsystem Reset) as part of this command. The currently executing firmware revision may be determined from the Firmware Revision field of the Identify Controller data structure as indicated in the Firmware Slot Information log page. No further action is automatically taken to reset the device, which is usually required to complete the activation process. If your kernel and driver are recent enough, you can commit the firmware by issuing a reset through Linux sysfs, for example: ------------ # echo 1 > /sys/class/nvme/nvme0/device/reset ------------ If your kernel is not recent enough, you will need to remove and add the device some other way. OPTIONS ------- -a :: --action=:: Commit Action: This field specifies the action that is taken on the image downloaded with the Firmware Image Download command or on a previously downloaded and placed image. + [] |================= |Value|Definition |0|Downloaded image replaces the image indicated by the Firmware Slot field. This image is not activated. |1|Downloaded image replaces the image indicated by the Firmware Slot field. This image is activated at the next reset. |2|The image indicated by the Firmware Slot field is activated at the next reset. |3|The image specified by the Firmware Slot field is requested to be activated immediately without reset. |6|Downloaded image replaces the Boot Partition specified by the Boot Partition ID field. |7|Mark the Boot Partition specified in the BPID field as active and update BPINFO.ABPID. |================= -s :: --slot=:: Firmware Slot: Specifies the firmware slot that shall be used for the Commit Action, if applicable. If the value specified is 0h, then the controller shall choose the firmware slot (slot 1 – 7) to use for the operation. --bpid=:: -b :: Specifiies the Boot partition that shall be used for the Commit Action, if applicable (default: 0) EXAMPLES -------- * commit the last downloaded fw to slot 1. + ------------ # nvme fw-commit /dev/nvme0 --slot=1 --action=2 ------------ ALIAS ----- fw-activate NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-fw-download.1000066400000000000000000000071101322317423600211520ustar00rootroot00000000000000'\" t .\" Title: nvme-fw-download .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-FW\-DOWNLOAD" "1" "12/10/2017" "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-fw-download \- Download all or a portion of an nvme firmware image\&. .SH "SYNOPSIS" .sp .nf \fInvme fw\-download\fR [\-\-fw= | \-f ] [\-\-xfer= | \-x ] [\-\-offset= | \-o ] .fi .SH "DESCRIPTION" .sp The Firmware Image Download command is used to download all or a portion of the firmware image for a future update to the controller\&. The Firmware Image Download command may be submitted while other commands on the Admin Submission Queue or I/O Submission Queues are outstanding\&. The Firmware Image Download command copies the new firmware image (in whole or in part) to the controller\&. .sp The firmware image may be constructed of multiple pieces that are individually downloaded with separate Firmware Image Download commands\&. Each Firmware Image Download command includes a Dword Offset and Number of Dwords that specify a Dword range\&. The host software shall ensure that firmware pieces do not have Dword ranges that overlap\&. Firmware portions may be submitted out of order to the controller\&. .sp The new firmware image is not applied as part of the Firmware Image Download command\&. It is applied following a reset, where the image to apply and the firmware slot it should be committed to is specified with the Firmware Activate command\&. .SH "OPTIONS" .PP \-f , \-\-fw= .RS 4 Required argument\&. This specifies the path to the device\(cqs firmware file on your system that will be read by the program and sent to the device\&. .RE .PP \-x , \-\-xfer= .RS 4 This specifies the size to split each transfer\&. This is useful if the device has a max transfer size requirement for firmware\&. It defaults to 4k\&. .RE .PP \-o , \-\-offset= .RS 4 This specifies the starting offset in dwords\&. This is really only useful if your firmware is split in multiple files; otherwise the offset starts at zero and automatically adjusts based on the \fIxfer\fR size given\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Transfer a firmware size 128KiB at a time: .sp .if n \{\ .RS 4 .\} .nf # nvme fw\-download /dev/nvme0 \-\-fw=/path/to/nvme\&.fw \-\-xfer=0x20000 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-fw-download.html000066400000000000000000000470001322317423600217600ustar00rootroot00000000000000 nvme-fw-download(1)

SYNOPSIS

nvme fw-download <device> [--fw=<firmware-file> | -f <firmware-file>]
                    [--xfer=<transfer-size> | -x <transfer-size>]
                    [--offset=<offset> | -o <offset>]

DESCRIPTION

The Firmware Image Download command is used to download all or a portion of the firmware image for a future update to the controller. The Firmware Image Download command may be submitted while other commands on the Admin Submission Queue or I/O Submission Queues are outstanding. The Firmware Image Download command copies the new firmware image (in whole or in part) to the controller.

The firmware image may be constructed of multiple pieces that are individually downloaded with separate Firmware Image Download commands. Each Firmware Image Download command includes a Dword Offset and Number of Dwords that specify a Dword range. The host software shall ensure that firmware pieces do not have Dword ranges that overlap. Firmware portions may be submitted out of order to the controller.

The new firmware image is not applied as part of the Firmware Image Download command. It is applied following a reset, where the image to apply and the firmware slot it should be committed to is specified with the Firmware Activate command.

OPTIONS

-f <firmware-file>
--fw=<firmeware-file>

Required argument. This specifies the path to the device’s firmware file on your system that will be read by the program and sent to the device.

-x <transfer-size>
--xfer=<transfer-size>

This specifies the size to split each transfer. This is useful if the device has a max transfer size requirement for firmware. It defaults to 4k.

-o <offset>
--offset=<offset>

This specifies the starting offset in dwords. This is really only useful if your firmware is split in multiple files; otherwise the offset starts at zero and automatically adjusts based on the xfer size given.

EXAMPLES

  • Transfer a firmware size 128KiB at a time:

    # nvme fw-download /dev/nvme0 --fw=/path/to/nvme.fw --xfer=0x20000

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-fw-download.txt000066400000000000000000000042661322317423600216420ustar00rootroot00000000000000nvme-fw-download(1) =================== NAME ---- nvme-fw-download - Download all or a portion of an nvme firmware image. SYNOPSIS -------- [verse] 'nvme fw-download' [--fw= | -f ] [--xfer= | -x ] [--offset= | -o ] DESCRIPTION ----------- The Firmware Image Download command is used to download all or a portion of the firmware image for a future update to the controller. The Firmware Image Download command may be submitted while other commands on the Admin Submission Queue or I/O Submission Queues are outstanding. The Firmware Image Download command copies the new firmware image (in whole or in part) to the controller. The firmware image may be constructed of multiple pieces that are individually downloaded with separate Firmware Image Download commands. Each Firmware Image Download command includes a Dword Offset and Number of Dwords that specify a Dword range. The host software shall ensure that firmware pieces do not have Dword ranges that overlap. Firmware portions may be submitted out of order to the controller. The new firmware image is not applied as part of the Firmware Image Download command. It is applied following a reset, where the image to apply and the firmware slot it should be committed to is specified with the Firmware Activate command. OPTIONS ------- -f :: --fw=:: Required argument. This specifies the path to the device's firmware file on your system that will be read by the program and sent to the device. -x :: --xfer=:: This specifies the size to split each transfer. This is useful if the device has a max transfer size requirement for firmware. It defaults to 4k. -o :: --offset=:: This specifies the starting offset in dwords. This is really only useful if your firmware is split in multiple files; otherwise the offset starts at zero and automatically adjusts based on the 'xfer' size given. EXAMPLES -------- * Transfer a firmware size 128KiB at a time: + ------------ # nvme fw-download /dev/nvme0 --fw=/path/to/nvme.fw --xfer=0x20000 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-fw-log.1000066400000000000000000000054111322317423600201260ustar00rootroot00000000000000'\" t .\" Title: nvme-fw-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-FW\-LOG" "1" "12/10/2017" "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-fw-log \- Send NVMe Firmware log page request, returns result and log .SH "SYNOPSIS" .sp .nf \fInvme fw\-log\fR [\-\-raw\-binary | \-b] [\-\-output\-format= | \-o ] .fi .SH "DESCRIPTION" .sp Retrieves the NVMe Firmware log page from an NVMe device and provides the retuned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned f/w 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 or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw fw log buffer to stdout\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Print the firmware log page in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme fw\-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 log firmware to a file: .sp .if n \{\ .RS 4 .\} .nf # nvme fw\-log /dev/nvme0 \-\-raw\-binary > fw_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 nvme-cli-1.5/Documentation/nvme-fw-log.html000066400000000000000000000451121322317423600207340ustar00rootroot00000000000000 nvme-fw-log(1)

SYNOPSIS

nvme fw-log <device> [--raw-binary | -b]
                        [--output-format=<fmt> | -o <fmt>]

DESCRIPTION

Retrieves the NVMe Firmware log page from an NVMe device and provides the retuned 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 f/w 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 or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-b
--raw-binary

Print the raw fw 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 firmware log page in a human readable format:

    # nvme fw-log /dev/nvme0
  • Print the log firmware to a file:

    # nvme fw-log /dev/nvme0 --raw-binary > fw_log.raw

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-fw-log.txt000066400000000000000000000025211322317423600206040ustar00rootroot00000000000000nvme-fw-log(1) ============== NAME ---- nvme-fw-log - Send NVMe Firmware log page request, returns result and log SYNOPSIS -------- [verse] 'nvme fw-log' [--raw-binary | -b] [--output-format= | -o ] DESCRIPTION ----------- Retrieves the NVMe Firmware log page from an NVMe device and provides the retuned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned f/w 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 or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -b:: --raw-binary:: Print the raw fw log buffer to stdout. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Print the firmware log page in a human readable format: + ------------ # nvme fw-log /dev/nvme0 ------------ + * Print the log firmware to a file: + ------------ # nvme fw-log /dev/nvme0 --raw-binary > fw_log.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-gen-hostnqn.1000066400000000000000000000031471322317423600212000ustar00rootroot00000000000000'\" t .\" Title: nvme-gen-hostnqn .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-GEN\-HOSTNQN" "1" "12/10/2017" "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-gen-hostnqn \- Generate a host NVMe Qualified Name .SH "SYNOPSIS" .sp .nf \fInvme gen\-hostnqn\fR .fi .SH "DESCRIPTION" .sp Generate a random host NQN in the form: nqn\&.2014\-08\&.org\&.nvmexpress:uuid:1b4e28ba\-2fa1\-11d2\-883f\-0016d3cca427 and prints it to stdout\&. .SH "OPTIONS" .sp No options needed .SH "EXAMPLES" .sp nvme gen\-hostnqn .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-gen-hostnqn.html000066400000000000000000000422151322317423600220030ustar00rootroot00000000000000 nvme-gen-hostnqn(1)

SYNOPSIS

nvme gen-hostnqn

DESCRIPTION

Generate a random host NQN in the form: nqn.2014-08.org.nvmexpress:uuid:1b4e28ba-2fa1-11d2-883f-0016d3cca427 and prints it to stdout.

OPTIONS

No options needed

EXAMPLES

nvme gen-hostnqn

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-gen-hostnqn.txt000066400000000000000000000006451322317423600216570ustar00rootroot00000000000000nvme-gen-hostnqn(1) =================== NAME ---- nvme-gen-hostnqn - Generate a host NVMe Qualified Name SYNOPSIS -------- [verse] 'nvme gen-hostnqn' DESCRIPTION ----------- Generate a random host NQN in the form: nqn.2014-08.org.nvmexpress:uuid:1b4e28ba-2fa1-11d2-883f-0016d3cca427 and prints it to stdout. OPTIONS ------- No options needed EXAMPLES -------- nvme gen-hostnqn NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-get-feature.1000066400000000000000000000113371322317423600211470ustar00rootroot00000000000000'\" t .\" Title: nvme-get-feature .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-GET\-FEATURE" "1" "12/10/2017" "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-get-feature \- Gets an NVMe feature, returns applicable results .SH "SYNOPSIS" .sp .nf \fInvme get\-feature\fR [\-\-namespace\-id= | \-n ] [\-\-feature\-id= | \-f ] [\-\-cdw11=] [\-\-data\-len= | \-l ] [\-\-sel=] [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp Submits an NVMe Get Feature admin command and returns the applicable results\&. This may be the feature\(cqs value, or may also include a feature structure if the feature requires it (ex: LBA Range Type)\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned feature\(cqs structure (if applicable) 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 if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the feature for the given nsid\&. This is optional and most features do not use this value\&. .RE .PP \-f , \-\-feature\-id= .RS 4 The feature id to send with the command\&. Value provided should be in hex\&. .RE .PP \-s .RS 4 Select (SEL): This field specifies which value of the attributes to return in the provided data: .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt. T{ Select T}:T{ Description T} T{ 0 T}:T{ Current T} T{ 1 T}:T{ Default T} T{ 2 T}:T{ Saved T} T{ 3 T}:T{ Supported capabilities T} T{ 4\(en7 T}:T{ Reserved T} .TE .sp 1 .RE .PP \-l , \-\-data\-len= .RS 4 The data length for the buffer returned for this feature\&. Most known features do not use this value\&. The exception is LBA Range Type .RE .PP \-\-cdw11= .RS 4 The value for command dword 11, if applicable\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw feature buffer to stdout if the feature returns a structure\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Retrieves the feature for Number of Queues, or feature id 7: .sp .if n \{\ .RS 4 .\} .nf # nvme get\-feature /dev/nvme0 \-f 7 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} The following retrieves the feature for the LBA Range Type, which implicitly requires a buffer and will be printed to the screen in human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme get\-feature /dev/nvme0 \-f 3 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Retrieves the feature for the some vendor specific feature and specifically requesting a buffer be allocate for this feature, which will be displayed to the user in as a hex dump: .sp .if n \{\ .RS 4 .\} .nf # nvme get\-feature /dev/nvme0 \-f 0xc0 \-l 512 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} The following retrieves the feature for the LBA Range Type, which implicitly requires a buffer and will be saved to a file in its raw format: .sp .if n \{\ .RS 4 .\} .nf # nvme get\-feature /dev/nvme0 \-f 3 \-\-raw\-binary > lba_range\&.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 nvme-cli-1.5/Documentation/nvme-get-feature.html000066400000000000000000000532231322317423600217530ustar00rootroot00000000000000 nvme-get-feature(1)

SYNOPSIS

nvme get-feature <device> [--namespace-id=<nsid> | -n <nsid>]
                          [--feature-id=<fid> | -f <fid>] [--cdw11=<cdw11>]
                          [--data-len=<data-len> | -l <data-len>]
                          [--sel=<select> | -s <select>]
                          [--raw-binary | -b]

DESCRIPTION

Submits an NVMe Get Feature admin command and returns the applicable results. This may be the feature’s value, or may also include a feature structure if the feature requires it (ex: LBA Range Type).

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 feature’s structure (if applicable) 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 if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the feature for the given nsid. This is optional and most features do not use this value.

-f <fid>
--feature-id=<fid>

The feature id to send with the command. Value provided should be in hex.

-s <select>
--sel=<select>

Select (SEL): This field specifies which value of the attributes to return in the provided data:

Select

Description

0

Current

1

Default

2

Saved

3

Supported capabilities

4–7

Reserved

-l <data-len>
--data-len=<data-len>

The data length for the buffer returned for this feature. Most known features do not use this value. The exception is LBA Range Type

--cdw11=<cdw11>

The value for command dword 11, if applicable.

-b
--raw-binary

Print the raw feature buffer to stdout if the feature returns a structure.

EXAMPLES

  • Retrieves the feature for Number of Queues, or feature id 7:

    # nvme get-feature /dev/nvme0 -f 7
  • The following retrieves the feature for the LBA Range Type, which implicitly requires a buffer and will be printed to the screen in human readable format:

    # nvme get-feature /dev/nvme0 -f 3
  • Retrieves the feature for the some vendor specific feature and specifically requesting a buffer be allocate for this feature, which will be displayed to the user in as a hex dump:

    # nvme get-feature /dev/nvme0 -f 0xc0 -l 512
  • The following retrieves the feature for the LBA Range Type, which implicitly requires a buffer and will be saved to a file in its raw format:

    # nvme get-feature /dev/nvme0 -f 3 --raw-binary > lba_range.raw

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-get-feature.txt000066400000000000000000000055501322317423600216260ustar00rootroot00000000000000nvme-get-feature(1) =================== NAME ---- nvme-get-feature - Gets an NVMe feature, returns applicable results SYNOPSIS -------- [verse] 'nvme get-feature' [--namespace-id= | -n ] [--feature-id= | -f ] [--cdw11=] [--data-len= | -l ] [--sel=] [--raw-binary | -b] DESCRIPTION ----------- Submits an NVMe Get Feature admin command and returns the applicable results. This may be the feature's value, or may also include a feature structure if the feature requires it (ex: LBA Range Type). The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned feature's structure (if applicable) 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 if it is a known structure, displayed in hex, or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -n :: --namespace-id=:: Retrieve the feature for the given nsid. This is optional and most features do not use this value. -f :: --feature-id=:: The feature id to send with the command. Value provided should be in hex. -s :: Select (SEL): This field specifies which value of the attributes to return in the provided data: + [] |================== |Select|Description |0|Current |1|Default |2|Saved |3|Supported capabilities |4–7|Reserved |================== -l :: --data-len=:: The data length for the buffer returned for this feature. Most known features do not use this value. The exception is LBA Range Type --cdw11=:: The value for command dword 11, if applicable. -b:: --raw-binary:: Print the raw feature buffer to stdout if the feature returns a structure. EXAMPLES -------- * Retrieves the feature for Number of Queues, or feature id 7: + ------------ # nvme get-feature /dev/nvme0 -f 7 ------------ + * The following retrieves the feature for the LBA Range Type, which implicitly requires a buffer and will be printed to the screen in human readable format: + ------------ # nvme get-feature /dev/nvme0 -f 3 ------------ + * Retrieves the feature for the some vendor specific feature and specifically requesting a buffer be allocate for this feature, which will be displayed to the user in as a hex dump: + ------------ # nvme get-feature /dev/nvme0 -f 0xc0 -l 512 ------------ + * The following retrieves the feature for the LBA Range Type, which implicitly requires a buffer and will be saved to a file in its raw format: + ------------ # nvme get-feature /dev/nvme0 -f 3 --raw-binary > lba_range.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-get-log.1000066400000000000000000000073751322317423600203040ustar00rootroot00000000000000'\" t .\" Title: nvme-get-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-GET\-LOG" "1" "12/10/2017" "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-get-log \- Retrieves a log page from an NVMe device .SH "SYNOPSIS" .sp .nf \fInvme get\-log\fR [\-\-log\-id= | \-i ] [\-\-log\-len= | \-l ] [\-\-aen= | \-a ] [\-\-namespace\-id= | \-n ] [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp Retrieves an arbitrary NVMe log page from an NVMe device and provides the retuned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned log structure may be returned in one of several ways depending on the option flags; the structure may be displayed in hex by the program or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-l , \-\-log\-len= .RS 4 Allocates a buffer of bytes size and requests this many bytes be returned in the constructed NVMe command\&. This param is mandatory\&. .RE .PP \-i , \-\-log\-id= .RS 4 Sets the commands requested log\-id to \&. Defaults to 0\&. .RE .PP \-a , \-\-aen= .RS 4 Convenience field for extracting log information based on an asynchronous event notification result\&. This will override log\-id and log\-len, if set\&. .RE .PP \-n , \-\-namespace\-id= .RS 4 Sets the command\(cqs nsid value to the given nsid\&. Defaults to 0xffffffff if not given\&. This option may not affect anything depending on the log page, which may or may not be specific to a namespace\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw log buffer to stdout\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Get 512 bytes from log page 2 .sp .if n \{\ .RS 4 .\} .nf # nvme get\-log /dev/nvme0 \-\-log\-id=2 \-\-log\-len=512 .fi .if n \{\ .RE .\} .sp The above example will get log page 2 (SMART), and request 512 bytes\&. On success, the returned log will be dumped in hex and not interpreted by the program\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Have the program return the raw log page in binary: .sp .if n \{\ .RS 4 .\} .nf # nvme get\-log /dev/nvme0 \-log\-id=2 \-\-log\-len=512 \-\-raw\-binary > log_page_2\&.raw # nvme get\-log /dev/nvme0 \-i 2 \-l 512 \-b > log_page_2\&.raw .fi .if n \{\ .RE .\} .sp It is not a good idea to not redirect stdout when using this mode\&. .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-get-log.html000066400000000000000000000476041322317423600211070ustar00rootroot00000000000000 nvme-get-log(1)

SYNOPSIS

nvme get-log <device> [--log-id=<log-id> | -i <log-id>]
                      [--log-len=<log-len> | -l <log-len>]
                      [--aen=<aen> | -a <aen>]
                      [--namespace-id=<nsid> | -n <nsid>]
                      [--raw-binary | -b]

DESCRIPTION

Retrieves an arbitrary NVMe log page from an NVMe device and provides the retuned 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 log structure may be returned in one of several ways depending on the option flags; the structure may be displayed in hex by the program or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-l <log-len>
--log-len=<log-len>

Allocates a buffer of <log-len> bytes size and requests this many bytes be returned in the constructed NVMe command. This param is mandatory.

-i <log-id>
--log-id=<log-id>

Sets the commands requested log-id to <log-id>. Defaults to 0.

-a <aen>
--aen=<aen>

Convenience field for extracting log information based on an asynchronous event notification result. This will override log-id and log-len, if set.

-n <nsid>
--namespace-id=<nsid>

Sets the command’s nsid value to the given nsid. Defaults to 0xffffffff if not given. This option may not affect anything depending on the log page, which may or may not be specific to a namespace.

-b
--raw-binary

Print the raw log buffer to stdout.

EXAMPLES

  • Get 512 bytes from log page 2

    # nvme get-log /dev/nvme0 --log-id=2 --log-len=512

    The above example will get log page 2 (SMART), and request 512 bytes. On success, the returned log will be dumped in hex and not interpreted by the program.

  • Have the program return the raw log page in binary:

    # nvme get-log /dev/nvme0 -log-id=2 --log-len=512 --raw-binary > log_page_2.raw
    # nvme get-log /dev/nvme0 -i 2 -l 512 -b > log_page_2.raw

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-get-log.txt000066400000000000000000000042611322317423600207520ustar00rootroot00000000000000nvme-get-log(1) =============== NAME ---- nvme-get-log - Retrieves a log page from an NVMe device SYNOPSIS -------- [verse] 'nvme get-log' [--log-id= | -i ] [--log-len= | -l ] [--aen= | -a ] [--namespace-id= | -n ] [--raw-binary | -b] DESCRIPTION ----------- Retrieves an arbitrary NVMe log page from an NVMe device and provides the retuned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned log structure may be returned in one of several ways depending on the option flags; the structure may be displayed in hex by the program or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -l :: --log-len=:: Allocates a buffer of bytes size and requests this many bytes be returned in the constructed NVMe command. This param is mandatory. -i :: --log-id=:: Sets the commands requested log-id to . Defaults to 0. -a :: --aen=:: Convenience field for extracting log information based on an asynchronous event notification result. This will override log-id and log-len, if set. -n :: --namespace-id=:: Sets the command's nsid value to the given nsid. Defaults to 0xffffffff if not given. This option may not affect anything depending on the log page, which may or may not be specific to a namespace. -b:: --raw-binary:: Print the raw log buffer to stdout. EXAMPLES -------- * Get 512 bytes from log page 2 + ------------ # nvme get-log /dev/nvme0 --log-id=2 --log-len=512 ------------ + The above example will get log page 2 (SMART), and request 512 bytes. On success, the returned log will be dumped in hex and not interpreted by the program. * Have the program return the raw log page in binary: + ------------ # nvme get-log /dev/nvme0 -log-id=2 --log-len=512 --raw-binary > log_page_2.raw # nvme get-log /dev/nvme0 -i 2 -l 512 -b > log_page_2.raw ------------ + It is not a good idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-get-ns-id.1000066400000000000000000000034501322317423600205230ustar00rootroot00000000000000'\" t .\" Title: nvme-get-ns-id .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-GET\-NS\-ID" "1" "12/10/2017" "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-get-ns-id \- Retrieves the namespace ID for an NVMe block device .SH "SYNOPSIS" .sp .nf \fInvme get\-ns\-id\fR .fi .SH "DESCRIPTION" .sp Retrieves the namespace ID for an NVMe block device\&. The param is mandatory and must be an NVMe block device (ex: /dev/nvme0n1)\&. .SH "OPTIONS" .sp None .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Shows the namespace id for the given block device: .sp .if n \{\ .RS 4 .\} .nf # nvme get\-ns\-id /dev/nvme0n1 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-get-ns-id.html000066400000000000000000000425241322317423600213340ustar00rootroot00000000000000 nvme-get-ns-id(1)

SYNOPSIS

nvme get-ns-id <device>

DESCRIPTION

Retrieves the namespace ID for an NVMe block device. The <device> param is mandatory and must be an NVMe block device (ex: /dev/nvme0n1).

OPTIONS

None

EXAMPLES

  • Shows the namespace id for the given block device:

    # nvme get-ns-id /dev/nvme0n1

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-get-ns-id.txt000066400000000000000000000010131322317423600211730ustar00rootroot00000000000000nvme-get-ns-id(1) ================= NAME ---- nvme-get-ns-id - Retrieves the namespace ID for an NVMe block device SYNOPSIS -------- [verse] 'nvme get-ns-id' DESCRIPTION ----------- Retrieves the namespace ID for an NVMe block device. The param is mandatory and must be an NVMe block device (ex: /dev/nvme0n1). OPTIONS ------- None EXAMPLES -------- * Shows the namespace id for the given block device: + ------------ # nvme get-ns-id /dev/nvme0n1 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-help.1000066400000000000000000000032741322317423600176700ustar00rootroot00000000000000'\" t .\" Title: nvme-help .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-HELP" "1" "12/10/2017" "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-help \- Help information\&. .SH "SYNOPSIS" .sp .nf \fInvme help\fR [] .fi .SH "DESCRIPTION" .sp Provides help information, with detailed information about the given command if provided\&. .SH "OPTIONS" .sp No Options .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Show help for nvme smart log: .sp .if n \{\ .RS 4 .\} .nf # nvme help smart\-log .fi .if n \{\ .RE .\} .sp Not much to it .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-help.html000066400000000000000000000424071322317423600204750ustar00rootroot00000000000000 nvme-help(1)

SYNOPSIS

nvme help [<command>]

DESCRIPTION

Provides help information, with detailed information about the given command if provided.

OPTIONS

No Options

EXAMPLES

  • Show help for nvme smart log:

    # nvme help smart-log

    Not much to it

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-help.txt000066400000000000000000000006431322317423600203440ustar00rootroot00000000000000nvme-help(1) ============= NAME ---- nvme-help - Help information. SYNOPSIS -------- [verse] 'nvme help' [] DESCRIPTION ----------- Provides help information, with detailed information about the given command if provided. OPTIONS ------- No Options EXAMPLES -------- * Show help for nvme smart log: + ------------ # nvme help smart-log ------------ + Not much to it NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-huawei-id-ctrl.1000066400000000000000000000062451322317423600215570ustar00rootroot00000000000000'\" t .\" Title: nvme-huawei-id-ctrl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-HUAWEI\-ID\-CT" "1" "12/10/2017" "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-huawei-id-ctrl \- Send NVMe Identify Controller, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme huawei id\-ctrl\fR [\-v | \-\-vendor\-specific] [\-b | \-\-raw\-binary] [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an identify controller command and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp This will only work on Huawei devices supporting this feature\&. Results for any other device are undefined\&. .sp On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. .sp If having the program decode the output for readability, this version will decode Huawei vendor unique portions of the structure\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-v, \-\-vendor\-specific .RS 4 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&. .RE .PP \-H, \-\-human\-readable .RS 4 This option will parse and format many of the bit fields into human\-readable formats\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program interpret the returned buffer and display the known fields in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme huawei id\-ctrl /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-huawei-id-ctrl.html000066400000000000000000000463041322317423600223630ustar00rootroot00000000000000 nvme-huawei-id-ctrl(1)

SYNOPSIS

nvme huawei id-ctrl <device> [-v | --vendor-specific] [-b | --raw-binary]
                        [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

For the NVMe device given, sends an identify controller command and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

This will only work on Huawei devices supporting this feature. Results for any other device are undefined.

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

If having the program decode the output for readability, this version will decode Huawei vendor unique portions of the structure.

OPTIONS

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options.

-v
--vendor-specific

In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation.

-H
--human-readable

This option will parse and format many of the bit fields into human-readable formats.

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

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

EXAMPLES

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

    # nvme huawei id-ctrl /dev/nvme0

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-huawei-id-ctrl.txt000066400000000000000000000034511322317423600222320ustar00rootroot00000000000000nvme-huawei-id-ctrl(1) ===================== NAME ---- nvme-huawei-id-ctrl - Send NVMe Identify Controller, return result and structure SYNOPSIS -------- [verse] 'nvme huawei id-ctrl' [-v | --vendor-specific] [-b | --raw-binary] [-o | --output-format=] DESCRIPTION ----------- For the NVMe device given, sends an identify controller command and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). This will only work on Huawei devices supporting this feature. Results for any other device are undefined. On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout. If having the program decode the output for readability, this version will decode Huawei vendor unique portions of the structure. OPTIONS ------- -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options. -v:: --vendor-specific:: In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation. -H:: --human-readable:: This option will parse and format many of the bit fields into human-readable formats. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Has the program interpret the returned buffer and display the known fields in a human readable format: + ------------ # nvme huawei id-ctrl /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-huawei-list.1000066400000000000000000000034161322317423600211710ustar00rootroot00000000000000'\" t .\" Title: nvme-list .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LIST" "1" "12/10/2017" "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-huawei-list \- List all recognized Huawei NVMe devices .SH "SYNOPSIS" .sp .nf \fInvme huawei list\fR [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp Scan the sysfs tree for NVM Express devices and return the /dev node for those Huawei devices as well as some pertinent information about them\&. .SH "OPTIONS" .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR or \fIjson\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-huawei-list.html000066400000000000000000000426551322317423600220050ustar00rootroot00000000000000 nvme-list(1)

SYNOPSIS

nvme huawei list [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

Scan the sysfs tree for NVM Express devices and return the /dev node for those Huawei devices as well as some pertinent information about them.

OPTIONS

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

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

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-huawei-list.txt000066400000000000000000000010771322317423600216510ustar00rootroot00000000000000nvme-list(1) ============ NAME ---- nvme-huawei-list - List all recognized Huawei NVMe devices SYNOPSIS -------- [verse] 'nvme huawei list' [-o | --output-format=] DESCRIPTION ----------- Scan the sysfs tree for NVM Express devices and return the /dev node for those Huawei devices as well as some pertinent information about them. OPTIONS ------- -o :: --output-format=:: Set the reporting format to 'normal' or 'json'. Only one output format can be used at a time. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-id-ctrl.1000066400000000000000000000113261322317423600202730ustar00rootroot00000000000000'\" t .\" Title: nvme-id-ctrl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ID\-CTRL" "1" "12/10/2017" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nvme-id-ctrl \- Send NVMe Identify Controller, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme id\-ctrl\fR [\-v | \-\-vendor\-specific] [\-b | \-\-raw\-binary] [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an identify controller command and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-v, \-\-vendor\-specific .RS 4 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&. .RE .PP \-H, \-\-human\-readable .RS 4 This option will parse and format many of the bit fields into human\-readable formats\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program interpret the returned buffer and display the known fields in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ctrl /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 .\} In addition to showing the known fields, has the program to display the vendor unique field: .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ctrl /dev/nvme0 \-\-vendor\-specific # nvme id\-ctrl /dev/nvme0 \-v .fi .if n \{\ .RE .\} .sp The above will dump the \fIvs\fR buffer in hex since it doesn\(cqt know how to interpret it\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Have the program return the raw structure in binary: .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ctrl /dev/nvme0 \-\-raw\-binary > id_ctrl\&.raw # nvme id\-ctrl /dev/nvme0 \-b > id_ctrl\&.raw .fi .if n \{\ .RE .\} .sp It is probably a bad idea to not redirect stdout when using this mode\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Alternatively you may want to send the data to another program that can parse the raw buffer\&. .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ctrl /dev/nvme0 \-\-raw\-binary | nvme_parse_id_ctrl .fi .if n \{\ .RE .\} .sp The parse program in the above example can be a program that shows the structure in a way you like\&. The following program is such an example that will parse it and can accept the output through a pipe, \*(Aq|\*(Aq, as shown in the above example, or you can \*(Aqcat\*(Aq a saved output buffer to it\&. .RE .sp .if n \{\ .RS 4 .\} .nf /* File: nvme_parse_id_ctrl\&.c */ #include #include #include int main(int argc, char **argv) { unsigned char buf[sizeof(struct nvme_id_ctrl)]; struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf; if (read(STDIN_FILENO, buf, sizeof(buf))) return 1; printf("vid : %#x\en", ctrl\->vid); printf("ssvid : %#x\en", ctrl\->ssvid); return 0; } .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-id-ctrl.html000066400000000000000000000514561322317423600211070ustar00rootroot00000000000000 nvme-id-ctrl(1)

SYNOPSIS

nvme id-ctrl <device> [-v | --vendor-specific] [-b | --raw-binary]
                        [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

For the NVMe device given, sends an identify controller command and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

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

OPTIONS

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options.

-v
--vendor-specific

In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation.

-H
--human-readable

This option will parse and format many of the bit fields into human-readable formats.

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

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

EXAMPLES

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

    # nvme id-ctrl /dev/nvme0
  • In addition to showing the known fields, has the program to display the vendor unique field:

    # nvme id-ctrl /dev/nvme0 --vendor-specific
    # nvme id-ctrl /dev/nvme0 -v

    The above will dump the vs buffer in hex since it doesn’t know how to interpret it.

  • Have the program return the raw structure in binary:

    # nvme id-ctrl /dev/nvme0 --raw-binary > id_ctrl.raw
    # nvme id-ctrl /dev/nvme0 -b > id_ctrl.raw

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

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

    # nvme id-ctrl /dev/nvme0 --raw-binary | nvme_parse_id_ctrl

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

/* File: nvme_parse_id_ctrl.c */

#include <linux/nvme.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
        unsigned char buf[sizeof(struct nvme_id_ctrl)];
        struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf;

        if (read(STDIN_FILENO, buf, sizeof(buf)))
                return 1;

        printf("vid   : %#x\n", ctrl->vid);
        printf("ssvid : %#x\n", ctrl->ssvid);
        return 0;
}

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-id-ctrl.txt000066400000000000000000000056511322317423600207560ustar00rootroot00000000000000nvme-id-ctrl(1) =============== NAME ---- nvme-id-ctrl - Send NVMe Identify Controller, return result and structure SYNOPSIS -------- [verse] 'nvme id-ctrl' [-v | --vendor-specific] [-b | --raw-binary] [-o | --output-format=] DESCRIPTION ----------- For the NVMe device given, sends an identify controller command and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout. OPTIONS ------- -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options. -v:: --vendor-specific:: In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation. -H:: --human-readable:: This option will parse and format many of the bit fields into human-readable formats. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Has the program interpret the returned buffer and display the known fields in a human readable format: + ------------ # nvme id-ctrl /dev/nvme0 ------------ + * In addition to showing the known fields, has the program to display the vendor unique field: + ------------ # nvme id-ctrl /dev/nvme0 --vendor-specific # nvme id-ctrl /dev/nvme0 -v ------------ + The above will dump the 'vs' buffer in hex since it doesn't know how to interpret it. * Have the program return the raw structure in binary: + ------------ # nvme id-ctrl /dev/nvme0 --raw-binary > id_ctrl.raw # nvme id-ctrl /dev/nvme0 -b > id_ctrl.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. * Alternatively you may want to send the data to another program that can parse the raw buffer. + ------------ # nvme id-ctrl /dev/nvme0 --raw-binary | nvme_parse_id_ctrl ------------ + The parse program in the above example can be a program that shows the structure in a way you like. The following program is such an example that will parse it and can accept the output through a pipe, `'|'`, as shown in the above example, or you can `'cat'` a saved output buffer to it. ------------ /* File: nvme_parse_id_ctrl.c */ #include #include #include int main(int argc, char **argv) { unsigned char buf[sizeof(struct nvme_id_ctrl)]; struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf; if (read(STDIN_FILENO, buf, sizeof(buf))) return 1; printf("vid : %#x\n", ctrl->vid); printf("ssvid : %#x\n", ctrl->ssvid); return 0; } ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-id-ns.1000066400000000000000000000134361322317423600177530ustar00rootroot00000000000000'\" t .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ID\-NS" "1" "12/10/2017" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nvme-id-ns \- Send NVMe Identify Namespace, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme id\-ns\fR [\-v | \-\-vendor\-specific] [\-b | \-\-raw\-binary] [\-\-namespace\-id= | \-n ] [\-f | \-\-force] [\-\-output\-format= | \-o ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an identify namespace command and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. If the character device is given, the \*(Aq\-\-namespace\-id\*(Aq option is mandatory, otherwise it will use the ns\-id of the namespace for the block device you opened\&. For block devices, the ns\-id used can be overridden with the same option\&. .sp On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the identify namespace structure for the given nsid\&. This is required for the character devices, or overrides the block nsid if given\&. .RE .PP \-f, \-\-force .RS 4 Request controller return the indentify namespace structure even if the namespace is not attached to the controller\&. This is valid only for controllers at or newer than revision 1\&.2\&. Controllers at revision lower than this may interpret the command incorrectly\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-v, \-\-vendor\-specific .RS 4 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&. .RE .PP \-H, \-\-human\-readable .RS 4 This option will parse and format many of the bit fields into human\-readable formats\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program interpret the returned buffer and display the known fields in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ns /dev/nvme0n1 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} If using the character device or overriding namespace id: .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ns /dev/nvme0 \-n 1 # nvme id\-ns /dev/nvme0n1 \-n 1 # nvme id\-ns /dev/nvme0 \-\-namespace\-id=1 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} In addition to showing the known fields, have the program to display the vendor unique field: .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ns /dev/nvme0n1 \-\-vendor\-specific # nvme id\-ns /dev/nvme0n1 \-v .fi .if n \{\ .RE .\} .sp The above will dump the \*(Aqvs\*(Aq buffer in hex since it doesn\(cqt know how to interpret it\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Have the program return the raw structure in binary: .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ns /dev/nvme0n1 \-\-raw\-binary > id_ns\&.raw # nvme id\-ns /dev/nvme0n1 \-b > id_ns\&.raw .fi .if n \{\ .RE .\} .sp It is probably a bad idea to not redirect stdout when using this mode\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Alternatively you may want to send the data to another program that can parse the raw buffer\&. .sp .if n \{\ .RS 4 .\} .nf # nvme id\-ns /dev/nvme0n1 \-\-raw\-binary | nvme_parse_id_ns .fi .if n \{\ .RE .\} .sp The parse program in the above example can be a program that shows the structure in a way you like\&. The following program is such an example that will parse it and can accept the output through a pipe, \*(Aq|\*(Aq, as shown in the above example, or you can \*(Aqcat\*(Aq a saved output buffer to it\&. .RE .sp .if n \{\ .RS 4 .\} .nf /* File: nvme_parse_id_ns\&.c */ #include #include #include int main(int argc, char **argv) { unsigned char buf[sizeof(struct nvme_id_ns)]; struct nvme_id_ns *ns = (struct nvme_id_ns *)buf; if (read(STDIN_FILENO, buf, sizeof(buf))) return 1; printf("nsze : %#llx\en", ns\->nsze); printf("ncap : %#llx\en", ns\->ncap); return 0; } .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-id-ns.html000066400000000000000000000540361322317423600205600ustar00rootroot00000000000000 nvme-id-ns(1)

SYNOPSIS

nvme id-ns <device> [-v | --vendor-specific] [-b | --raw-binary]
                    [--namespace-id=<nsid> | -n <nsid>] [-f | --force]
                    [--output-format=<fmt> | -o <fmt>]

DESCRIPTION

For the NVMe device given, sends an identify namespace command and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the character device is given, the '--namespace-id' option is mandatory, otherwise it will use the ns-id of the namespace for the block device you opened. For block devices, the ns-id used can be overridden with the same option.

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

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the identify namespace structure for the given nsid. This is required for the character devices, or overrides the block nsid if given.

-f
--force

Request controller return the indentify namespace structure even if the namespace is not attached to the controller. This is valid only for controllers at or newer than revision 1.2. Controllers at revision lower than this may interpret the command incorrectly.

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options.

-v
--vendor-specific

In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation.

-H
--human-readable

This option will parse and format many of the bit fields into human-readable formats.

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

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

EXAMPLES

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

    # nvme id-ns /dev/nvme0n1
  • If using the character device or overriding namespace id:

    # nvme id-ns /dev/nvme0 -n 1
    # nvme id-ns /dev/nvme0n1 -n 1
    # nvme id-ns /dev/nvme0 --namespace-id=1
  • In addition to showing the known fields, have the program to display the vendor unique field:

    # nvme id-ns /dev/nvme0n1 --vendor-specific
    # nvme id-ns /dev/nvme0n1 -v

    The above will dump the 'vs' buffer in hex since it doesn’t know how to interpret it.

  • Have the program return the raw structure in binary:

    # nvme id-ns /dev/nvme0n1 --raw-binary > id_ns.raw
    # nvme id-ns /dev/nvme0n1 -b > id_ns.raw

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

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

    # nvme id-ns /dev/nvme0n1 --raw-binary | nvme_parse_id_ns

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

/* File: nvme_parse_id_ns.c */

#include <linux/nvme.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
        unsigned char buf[sizeof(struct nvme_id_ns)];
        struct nvme_id_ns *ns = (struct nvme_id_ns *)buf;

        if (read(STDIN_FILENO, buf, sizeof(buf)))
                return 1;

        printf("nsze : %#llx\n", ns->nsze);
        printf("ncap : %#llx\n", ns->ncap);
        return 0;
}

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-id-ns.txt000066400000000000000000000075111322317423600204270ustar00rootroot00000000000000nvme-id-ns(1) ============= NAME ---- nvme-id-ns - Send NVMe Identify Namespace, return result and structure SYNOPSIS -------- [verse] 'nvme id-ns' [-v | --vendor-specific] [-b | --raw-binary] [--namespace-id= | -n ] [-f | --force] [--output-format= | -o ] DESCRIPTION ----------- For the NVMe device given, sends an identify namespace command and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the character device is given, the `'--namespace-id'` option is mandatory, otherwise it will use the ns-id of the namespace for the block device you opened. For block devices, the ns-id used can be overridden with the same option. On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout. OPTIONS ------- -n :: --namespace-id=:: Retrieve the identify namespace structure for the given nsid. This is required for the character devices, or overrides the block nsid if given. -f:: --force:: Request controller return the indentify namespace structure even if the namespace is not attached to the controller. This is valid only for controllers at or newer than revision 1.2. Controllers at revision lower than this may interpret the command incorrectly. -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options. -v:: --vendor-specific:: In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation. -H:: --human-readable:: This option will parse and format many of the bit fields into human-readable formats. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Has the program interpret the returned buffer and display the known fields in a human readable format: + ------------ # nvme id-ns /dev/nvme0n1 ------------ + * If using the character device or overriding namespace id: + ------------ # nvme id-ns /dev/nvme0 -n 1 # nvme id-ns /dev/nvme0n1 -n 1 # nvme id-ns /dev/nvme0 --namespace-id=1 ------------ + * In addition to showing the known fields, have the program to display the vendor unique field: + ------------ # nvme id-ns /dev/nvme0n1 --vendor-specific # nvme id-ns /dev/nvme0n1 -v ------------ + The above will dump the \'vs' buffer in hex since it doesn't know how to interpret it. * Have the program return the raw structure in binary: + ------------ # nvme id-ns /dev/nvme0n1 --raw-binary > id_ns.raw # nvme id-ns /dev/nvme0n1 -b > id_ns.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. * Alternatively you may want to send the data to another program that can parse the raw buffer. + ------------ # nvme id-ns /dev/nvme0n1 --raw-binary | nvme_parse_id_ns ------------ + The parse program in the above example can be a program that shows the structure in a way you like. The following program is such an example that will parse it and can accept the output through a pipe, `'|'`, as shown in the above example, or you can `'cat'` a saved output buffer to it. ------------ /* File: nvme_parse_id_ns.c */ #include #include #include int main(int argc, char **argv) { unsigned char buf[sizeof(struct nvme_id_ns)]; struct nvme_id_ns *ns = (struct nvme_id_ns *)buf; if (read(STDIN_FILENO, buf, sizeof(buf))) return 1; printf("nsze : %#llx\n", ns->nsze); printf("ncap : %#llx\n", ns->ncap); return 0; } ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-intel-id-ctrl.1000066400000000000000000000060551322317423600214070ustar00rootroot00000000000000'\" t .\" Title: nvme-intel-id-ctrl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-INTEL\-ID\-CTR" "1" "12/10/2017" "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-intel-id-ctrl \- Send NVMe Identify Controller, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme intel id\-ctrl\fR [\-v | \-\-vendor\-specific] [\-b | \-\-raw\-binary] [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an identify controller command and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. .sp If having the program decode the output for readability, this version will decode Intel vendor unique portions of the structure\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-v, \-\-vendor\-specific .RS 4 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&. .RE .PP \-H, \-\-human\-readable .RS 4 This option will parse and format many of the bit fields into human\-readable formats\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program interpret the returned buffer and display the known fields in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme intel id\-ctrl /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-intel-id-ctrl.html000066400000000000000000000460551322317423600222170ustar00rootroot00000000000000 nvme-intel-id-ctrl(1)

SYNOPSIS

nvme intel id-ctrl <device> [-v | --vendor-specific] [-b | --raw-binary]
                        [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

For the NVMe device given, sends an identify controller command and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

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

If having the program decode the output for readability, this version will decode Intel vendor unique portions of the structure.

OPTIONS

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options.

-v
--vendor-specific

In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation.

-H
--human-readable

This option will parse and format many of the bit fields into human-readable formats.

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

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

EXAMPLES

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

    # nvme intel id-ctrl /dev/nvme0

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-intel-id-ctrl.txt000066400000000000000000000032701322317423600220620ustar00rootroot00000000000000nvme-intel-id-ctrl(1) ===================== NAME ---- nvme-intel-id-ctrl - Send NVMe Identify Controller, return result and structure SYNOPSIS -------- [verse] 'nvme intel id-ctrl' [-v | --vendor-specific] [-b | --raw-binary] [-o | --output-format=] DESCRIPTION ----------- For the NVMe device given, sends an identify controller command and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout. If having the program decode the output for readability, this version will decode Intel vendor unique portions of the structure. OPTIONS ------- -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options. -v:: --vendor-specific:: In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation. -H:: --human-readable:: This option will parse and format many of the bit fields into human-readable formats. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Has the program interpret the returned buffer and display the known fields in a human readable format: + ------------ # nvme intel id-ctrl /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-intel-internal-log.1000066400000000000000000000065001322317423600224370ustar00rootroot00000000000000'\" t .\" Title: nvme-intel-internal-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-INTEL\-INTERNA" "1" "12/10/2017" "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-intel-internal-log \- Retrieve Intel device\*(Aqs internal log and save to file\&. .SH "SYNOPSIS" .sp .nf \*(Aqnvme intel internal\-log \*(Aq [\-\-log=, \-l ] [\-\-region=, r ] [\-\-nlognum=, m ] [\-\-namespace\-id=, \-n ] [\-\-output\-file=, \-o ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends the Intel vendor unique device log request and saves the result to a file\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. If using the character device, the namespace id parameter is mandatory\&. .sp This will only work on Intel devices supporting this feature which includes (but not limited to) all the Intel DC P3xxx family of controllers\&. Results for any other device are undefined\&. .SH "OPTIONS" .PP \-l , \-\-log= .RS 4 Log type: 0, 1, or 2 for nlog, event log, and assert log, respectively\&. .RE .PP \-n , \-\-namespace\-id= .RS 4 Namespace to use\&. .RE .PP \-o , \-\-output\-file= .RS 4 Output file; defaults to device name provided .RE .PP \-r , \-\-region= .RS 4 Select which core region to retrieve the log from\&. \-1 for all available, if supported by the device\&. .RE .PP \-m , \-\-nlognum= .RS 4 When used with \fInlog\fR, this specifies which nlog to read\&. \-1 for all, if supported by the device\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the nlog from the device and saves to default file: .sp .if n \{\ .RS 4 .\} .nf # nvme intel internal\-log /dev/nvme0 \-\-namespace\-id=1 \-\-log=0 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the event log from the device and saves to defined file: .sp .if n \{\ .RS 4 .\} .nf # nvme intel internal\-log /dev/nvme0 \-\-namespace\-id=1 \-\-log=1 \-\-output\-file=MyAwesomeEventLog .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-intel-internal-log.html000066400000000000000000000454531322317423600232550ustar00rootroot00000000000000 nvme-intel-internal-log(1)

SYNOPSIS

'nvme intel internal-log ' <device> [--log=<NUM>, -l <NUM>]
                [--namespace-id=<NUM>, -n <NUM>]
                [--output-file=<FILE>, -o <FILE>]

DESCRIPTION

For the NVMe device given, sends the Intel vendor unique device log request and saves the result to a file.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If using the character device, the namespace id parameter is mandatory.

This will only work on Intel devices supporting this feature which includes (but not limited to) all the Intel DC P3xxx family of controllers. Results for any other device are undefined.

OPTIONS

-l <NUM>
--log=<NUM>

Log type: 0, 1, or 2 for nlog, event log, and assert log, respectively.

-n <NUM>
--namespace-id=<NUM>

Namespace to use.

-o <FILE>
--output-file=<FILE>

Output file; defaults to device name provided

EXAMPLES

  • Gets the nlog from the device and saves to default file:

    # nvme intel internal-log /dev/nvme0 --namespace-id=1 --log=0
  • Gets the event log from the device and saves to defined file:

    # nvme intel internal-log /dev/nvme0 --namespace-id=1 --log=1 --output-file=MyAwesomeEventLog

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-intel-internal-log.txt000066400000000000000000000034251322317423600231210ustar00rootroot00000000000000nvme-intel-internal-log(1) ========================== NAME ---- nvme-intel-internal-log - Retrieve Intel device's internal log and save to file. SYNOPSIS -------- [verse] 'nvme intel internal-log ' [--log=, -l ] [--region=, r ] [--nlognum=, m ] [--namespace-id=, -n ] [--output-file=, -o ] DESCRIPTION ----------- For the NVMe device given, sends the Intel vendor unique device log request and saves the result to a file. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If using the character device, the namespace id parameter is mandatory. This will only work on Intel devices supporting this feature which includes (but not limited to) all the Intel DC P3xxx family of controllers. Results for any other device are undefined. OPTIONS ------- -l :: --log=:: Log type: 0, 1, or 2 for nlog, event log, and assert log, respectively. -n :: --namespace-id=:: Namespace to use. -o :: --output-file=:: Output file; defaults to device name provided -r :: --region=:: Select which core region to retrieve the log from. -1 for all available, if supported by the device. -m :: --nlognum=:: When used with 'nlog', this specifies which nlog to read. -1 for all, if supported by the device. EXAMPLES -------- * Gets the nlog from the device and saves to default file: + ------------ # nvme intel internal-log /dev/nvme0 --namespace-id=1 --log=0 ------------ + * Gets the event log from the device and saves to defined file: + ------------ # nvme intel internal-log /dev/nvme0 --namespace-id=1 --log=1 --output-file=MyAwesomeEventLog ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-intel-lat-stats.1000066400000000000000000000051421322317423600217610ustar00rootroot00000000000000'\" t .\" Title: nvme-intel-lat-stats .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-INTEL\-LAT\-ST" "1" "12/10/2017" "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-intel-lat-stats \- Send NVMe Identify Controller, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme intel lat\-stats\fR [\-\-write | \-w] [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp For the NVMe device given, retrieves intel vendor specific latency statistics and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-w, \-\-write .RS 4 Get write statistics\&. Read statistics are returned by default\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Get the read statistics .sp .if n \{\ .RS 4 .\} .nf # nvme intel lat\-stats /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 .\} Get the write statistics .sp .if n \{\ .RS 4 .\} .nf # nvme intel lat\-stats /dev/nvme0 \-w .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-intel-lat-stats.html000066400000000000000000000445261322317423600225760ustar00rootroot00000000000000 nvme-intel-lat-stats(1)

SYNOPSIS

nvme intel lat-stats <device> [--write | -w] [--raw-binary | -b]

DESCRIPTION

For the NVMe device given, retrieves intel vendor specific latency statistics and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

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

OPTIONS

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options.

-w
--write

Get write statistics. Read statistics are returned by default.

EXAMPLES

  • Get the read statistics

    # nvme intel lat-stats /dev/nvme0
  • Get the write statistics

    # nvme intel lat-stats /dev/nvme0 -w

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-intel-lat-stats.txt000066400000000000000000000022701322317423600224370ustar00rootroot00000000000000nvme-intel-lat-stats(1) ======================= NAME ---- nvme-intel-lat-stats - Send NVMe Identify Controller, return result and structure SYNOPSIS -------- [verse] 'nvme intel lat-stats' [--write | -w] [--raw-binary | -b] DESCRIPTION ----------- For the NVMe device given, retrieves intel vendor specific latency statistics and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout. OPTIONS ------- -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options. -w:: --write:: Get write statistics. Read statistics are returned by default. EXAMPLES -------- * Get the read statistics + ------------ # nvme intel lat-stats /dev/nvme0 ------------ + * Get the write statistics + ------------ # nvme intel lat-stats /dev/nvme0 -w ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-intel-market-name.1000066400000000000000000000046171322317423600222540ustar00rootroot00000000000000'\" t .\" Title: nvme-intel-market-name .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-INTEL\-MARKET\" "1" "12/10/2017" "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-intel-market-name \- Send NVMe Identify Controller, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme intel market\-name\fR [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp For the NVMe device given, retrieves intel vendor specific marketing name log page and provides the result and returned structure\&. The output is simply the marketing name used to identify what kind of device it is\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Get the marketing name .sp .if n \{\ .RS 4 .\} .nf # nvme intel market\-name /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-intel-market-name.html000066400000000000000000000441221322317423600230530ustar00rootroot00000000000000 nvme-intel-market-name(1)

SYNOPSIS

nvme intel market-name <device> [--raw-binary | -b]

DESCRIPTION

For the NVMe device given, retrieves intel vendor specific marketing name log page and provides the result and returned structure. The output is simply the marketing name used to identify what kind of device it is.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

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

OPTIONS

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options.

EXAMPLES

  • Get the marketing name

    # nvme intel market-name /dev/nvme0

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-intel-market-name.txt000066400000000000000000000021341322317423600227230ustar00rootroot00000000000000nvme-intel-market-name(1) ========================= NAME ---- nvme-intel-market-name - Send NVMe Identify Controller, return result and structure SYNOPSIS -------- [verse] 'nvme intel market-name' [--raw-binary | -b] DESCRIPTION ----------- For the NVMe device given, retrieves intel vendor specific marketing name log page and provides the result and returned structure. The output is simply the marketing name used to identify what kind of device it is. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout. OPTIONS ------- -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options. EXAMPLES -------- * Get the marketing name + ------------ # nvme intel market-name /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-intel-smart-log-add.1000066400000000000000000000061351322317423600225030ustar00rootroot00000000000000'\" t .\" Title: nvme-intel-smart-log-add .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-INTEL\-SMART\-" "1" "12/10/2017" "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-intel-smart-log-add \- Send NVMe Intel Additional SMART log page request, returns result and log .SH "SYNOPSIS" .sp .nf \fInvme intel smart\-log\-add\fR [\-\-namespace\-id= | \-n ] [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp Retrieves the NVMe Intel Additional SMART log page from the device and provides the retuned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned smart 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 or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the Additional SMART log for the given nsid\&. This is optional and its success may depend on the device\(cqs capabilities to provide this log on a per\-namespace basis (see the NVMe Identify Controller for this capability)\&. The default nsid to use is 0xffffffff for the device global SMART log\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw Intel Additional SMART log buffer to stdout\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Print the Intel Additional SMART log page in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme intel smart\-log\-add /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 Intel Additional SMART log to a file: .sp .if n \{\ .RS 4 .\} .nf # nvme intel smart\-log\-add /dev/nvme0 \-\-raw\-binary > smart_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 nvme-cli-1.5/Documentation/nvme-intel-smart-log-add.html000066400000000000000000000456471322317423600233220ustar00rootroot00000000000000 nvme-intel-smart-log-add(1)

SYNOPSIS

nvme intel smart-log-add <device> [--namespace-id=<nsid> | -n <nsid>]
                        [--raw-binary | -b]

DESCRIPTION

Retrieves the NVMe Intel Additional SMART log page from the device and provides the retuned 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 smart 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 or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the Additional SMART log for the given nsid. This is optional and its success may depend on the device’s capabilities to provide this log on a per-namespace basis (see the NVMe Identify Controller for this capability). The default nsid to use is 0xffffffff for the device global SMART log.

-b
--raw-binary

Print the raw Intel Additional SMART log buffer to stdout.

EXAMPLES

  • Print the Intel Additional SMART log page in a human readable format:

    # nvme intel smart-log-add /dev/nvme0
  • Print the raw Intel Additional SMART log to a file:

    # nvme intel smart-log-add /dev/nvme0 --raw-binary > smart_log.raw

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-intel-smart-log-add.txt000066400000000000000000000032261322317423600231600ustar00rootroot00000000000000nvme-intel-smart-log-add(1) =========================== NAME ---- nvme-intel-smart-log-add - Send NVMe Intel Additional SMART log page request, returns result and log SYNOPSIS -------- [verse] 'nvme intel smart-log-add' [--namespace-id= | -n ] [--raw-binary | -b] DESCRIPTION ----------- Retrieves the NVMe Intel Additional SMART log page from the device and provides the retuned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned smart 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 or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -n :: --namespace-id=:: Retrieve the Additional SMART log for the given nsid. This is optional and its success may depend on the device's capabilities to provide this log on a per-namespace basis (see the NVMe Identify Controller for this capability). The default nsid to use is 0xffffffff for the device global SMART log. -b:: --raw-binary:: Print the raw Intel Additional SMART log buffer to stdout. EXAMPLES -------- * Print the Intel Additional SMART log page in a human readable format: + ------------ # nvme intel smart-log-add /dev/nvme0 ------------ + * Print the raw Intel Additional SMART log to a file: + ------------ # nvme intel smart-log-add /dev/nvme0 --raw-binary > smart_log.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-intel-temp-stats.1000066400000000000000000000051741322317423600221530ustar00rootroot00000000000000'\" t .\" Title: nvme-intel-temp-stats .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-INTEL\-TEMP\-S" "1" "12/10/2017" "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-intel-temp-stats \- Send NVMe SMART log page request, returns result and log .SH "SYNOPSIS" .sp .nf \fInvme intel temp\-stats\fR [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp Retrieves the NVMe Intel Additional SMART log page from the device and provides the retuned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned smart 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 or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw temperature stats log buffer to stdout\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Print the temperature stats log page in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme intel temp\-stats /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 SMART log to a file: .sp .if n \{\ .RS 4 .\} .nf # nvme intel temp\-stats /dev/nvme0 \-\-raw\-binary > temp_stats_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 nvme-cli-1.5/Documentation/nvme-intel-temp-stats.html000066400000000000000000000445071322317423600227620ustar00rootroot00000000000000 nvme-intel-temp-stats(1)

SYNOPSIS

nvme intel temp-stats <device> [--raw-binary | -b]

DESCRIPTION

Retrieves the NVMe Intel Additional SMART log page from the device and provides the retuned 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 smart 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 or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-b
--raw-binary

Print the raw temperature stats log buffer to stdout.

EXAMPLES

  • Print the temperature stats log page in a human readable format:

    # nvme intel temp-stats /dev/nvme0
  • Print the raw SMART log to a file:

    # nvme intel temp-stats /dev/nvme0 --raw-binary > temp_stats_log.raw

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-intel-temp-stats.txt000066400000000000000000000023411322317423600226230ustar00rootroot00000000000000nvme-intel-temp-stats(1) ======================== NAME ---- nvme-intel-temp-stats - Send NVMe SMART log page request, returns result and log SYNOPSIS -------- [verse] 'nvme intel temp-stats' [--raw-binary | -b] DESCRIPTION ----------- Retrieves the NVMe Intel Additional SMART log page from the device and provides the retuned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned smart 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 or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -b:: --raw-binary:: Print the raw temperature stats log buffer to stdout. EXAMPLES -------- * Print the temperature stats log page in a human readable format: + ------------ # nvme intel temp-stats /dev/nvme0 ------------ + * Print the raw SMART log to a file: + ------------ # nvme intel temp-stats /dev/nvme0 --raw-binary > temp_stats_log.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-io-passthru.1000066400000000000000000000114051322317423600212110ustar00rootroot00000000000000'\" t .\" Title: nvme-io-passthru .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-IO\-PASSTHRU" "1" "12/10/2017" "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-io-passthru \- Submit an arbitrary io command, return results .SH "SYNOPSIS" .sp .nf \fInvme\-io\-passthru\fR [\-\-opcode= | \-o ] [\-\-flags= | \-f ] [\-rsvd= | \-R ] [\-\-namespace\-id= | \-nsid ] [\-\-cdw2=] [\-\-cdw3=] [\-\-cdw10=] [\-\-cdw11=] [\-\-cdw12=] [\-\-cdw13=] [\-\-cdw14=] [\-\-cdw15=] [\-\-data\-len= | \-l ] [\-\-metadata\-len= | \-m ] [\-\-read | \-r ] [\-\-write | \-w] [\-\-input\-file= | \-f ] [\-\-timeout= | \-t ] [\-\-show\-command | \-\-dry\-run | \-s] [\-\-raw\-binary | \-b] [\-\-prefill= | \-p ] .fi .SH "DESCRIPTION" .sp Submits an arbitrary NVMe IO command and returns the applicable results\&. This may be the simply the command\(cqs result and status, or may also include a buffer if the command returns one\&. This command does no interpretation of the opcodes or options\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned structure (if applicable) may be returned in one of several ways depending on the option flags; the structure may printed by the program as a hex dump, or may be returned as a raw buffer printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-o , \-\-opcode= .RS 4 The NVMe opcode to send to the device in the command .RE .PP \-f , \-\-flags= .RS 4 The NVMe command flags to send to the device in the command .RE .PP \-R , \-\-rsvd= .RS 4 The value for the reserved field in the command\&. .RE .PP \-n , \-\-namespace\-id= .RS 4 The value for the ns\-id in the command\&. Defaults to \fI0\fR\&. .RE .PP \-\-cdw[2\-3,10\-15]= .RS 4 Specifies the command dword value for that specified entry in the command .RE .PP \-r, \-\-read, \-w, \-\-write .RS 4 Used for the data\-direction for the command and required for commands sending/receiving data\&. Don\(cqt use both read and write at the same time\&. .RE .PP \-i , \-\-input\-file= .RS 4 If the command is a data\-out (write) command, use this file to fill the buffer sent to the device\&. If no file is given, assumed to use STDIN\&. .RE .PP \-l , \-\-data\-len= .RS 4 The data length for the buffer used for this command\&. .RE .PP \-m , \-\-metadata\-len= .RS 4 The metadata length for the buffer used for this command\&. .RE .PP \-s, \-\-show\-cmd .RS 4 Print out the command to be sent\&. .RE .PP \-d, \-\-dry\-run .RS 4 Do not actually send the command\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw returned buffer to stdout if the command returns data or a structure\&. .RE .PP \-p , \-\-prefill .RS 4 Prefill the buffer with a predetermined byte value\&. Defaults to 0\&. This may be useful if the data you are writing is shorter than the required buffer, and you need to pad it with a known value\&. It may also be useful if you need to confirm if a device is overwriting a buffer on a data\-in command\&. .RE .SH "EXAMPLES" .sp nvme io\-passthru /dev/nvme0n1 \-\-opcode=2 \-\-namespace\-id=1 \-\-data\-len=4096 \-\-read \-\-cdw10=0 \-\-cdw11=0 \-\-cdw12=0x70000 \-\-raw\-binary .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-io-passthru.html000066400000000000000000000531341322317423600220220ustar00rootroot00000000000000 nvme-io-passthru(1)

SYNOPSIS

nvme-io-passthru <device> [--opcode=<opcode> | -o <opcode>]
                [--flags=<flags> | -f <flags>] [-rsvd=<rsvd> | -R <rsvd>]
                [--namespace-id=<nsid> | -nsid <nsid>]
                [--cdw2=<cdw2>] [--cdw3=<cdw3>] [--cdw10=<cdw10>]
                [--cdw11=<cdw11>] [--cdw12=<cdw12>] [--cdw13=<cdw13>]
                [--cdw14=<cdw14>] [--cdw15=<cdw15>]
                [--data-len=<data-len> | -l <data-len>]
                [--metadata-len=<len> | -m <len>]
                [--read | -r ] [--write | -w]
                [--input-file=<file> | -f <file>]
                [--timeout=<to> | -t <to>]
                [--show-command | --dry-run | -s]
                [--raw-binary | -b]
                [--prefill=<prefill> | -p <prefill>]

DESCRIPTION

Submits an arbitrary NVMe IO command and returns the applicable results. This may be the simply the command’s result and status, or may also include a buffer if the command returns one. This command does no interpretation of the opcodes or options.

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 structure (if applicable) may be returned in one of several ways depending on the option flags; the structure may printed by the program as a hex dump, or may be returned as a raw buffer printed to stdout for another program to parse.

OPTIONS

-o <opcode>
--opcode=<opcode>

The NVMe opcode to send to the device in the command

-f <flags>
--flags=<flags>

The NVMe command flags to send to the device in the command

-R <rsvd>
--rsvd=<rsvd>

The value for the reserved field in the command.

-n <nsid>
--namespace-id=<nsid>

The value for the ns-id in the command. Defaults to 0.

--cdw[2-3,10-15]=<cdw>

Specifies the command dword value for that specified entry in the command

-r
--read
-w
--write

Used for the data-direction for the command and required for commands sending/receiving data. Don’t use both read and write at the same time.

-i <file>
--input-file=<file>

If the command is a data-out (write) command, use this file to fill the buffer sent to the device. If no file is given, assumed to use STDIN.

-l <data-len>
--data-len=<data-len>

The data length for the buffer used for this command.

-m <data-len>
--metadata-len=<data-len>

The metadata length for the buffer used for this command.

-s
--show-cmd

Print out the command to be sent.

-d
--dry-run

Do not actually send the command.

-b
--raw-binary

Print the raw returned buffer to stdout if the command returns data or a structure.

-p <prefill>
--prefill <prefill>

Prefill the buffer with a predetermined byte value. Defaults to 0. This may be useful if the data you are writing is shorter than the required buffer, and you need to pad it with a known value. It may also be useful if you need to confirm if a device is overwriting a buffer on a data-in command.

EXAMPLES

nvme io-passthru /dev/nvme0n1 --opcode=2 --namespace-id=1 --data-len=4096 --read --cdw10=0 --cdw11=0 --cdw12=0x70000 --raw-binary

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-io-passthru.txt000066400000000000000000000061531322317423600216740ustar00rootroot00000000000000nvme-io-passthru(1) =================== NAME ---- nvme-io-passthru - Submit an arbitrary io command, return results SYNOPSIS -------- [verse] 'nvme-io-passthru' [--opcode= | -o ] [--flags= | -f ] [-rsvd= | -R ] [--namespace-id= | -nsid ] [--cdw2=] [--cdw3=] [--cdw10=] [--cdw11=] [--cdw12=] [--cdw13=] [--cdw14=] [--cdw15=] [--data-len= | -l ] [--metadata-len= | -m ] [--read | -r ] [--write | -w] [--input-file= | -f ] [--timeout= | -t ] [--show-command | --dry-run | -s] [--raw-binary | -b] [--prefill= | -p ] DESCRIPTION ----------- Submits an arbitrary NVMe IO command and returns the applicable results. This may be the simply the command's result and status, or may also include a buffer if the command returns one. This command does no interpretation of the opcodes or options. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned structure (if applicable) may be returned in one of several ways depending on the option flags; the structure may printed by the program as a hex dump, or may be returned as a raw buffer printed to stdout for another program to parse. OPTIONS ------- -o :: --opcode=:: The NVMe opcode to send to the device in the command -f :: --flags=:: The NVMe command flags to send to the device in the command -R :: --rsvd=:: The value for the reserved field in the command. -n :: --namespace-id=:: The value for the ns-id in the command. Defaults to '0'. --cdw[2-3,10-15]=:: Specifies the command dword value for that specified entry in the command -r:: --read:: -w:: --write:: Used for the data-direction for the command and required for commands sending/receiving data. Don't use both read and write at the same time. -i :: --input-file=:: If the command is a data-out (write) command, use this file to fill the buffer sent to the device. If no file is given, assumed to use STDIN. -l :: --data-len=:: The data length for the buffer used for this command. -m :: --metadata-len=:: The metadata length for the buffer used for this command. -s:: --show-cmd:: Print out the command to be sent. -d:: --dry-run:: Do not actually send the command. -b:: --raw-binary:: Print the raw returned buffer to stdout if the command returns data or a structure. -p :: --prefill :: Prefill the buffer with a predetermined byte value. Defaults to 0. This may be useful if the data you are writing is shorter than the required buffer, and you need to pad it with a known value. It may also be useful if you need to confirm if a device is overwriting a buffer on a data-in command. EXAMPLES -------- nvme io-passthru /dev/nvme0n1 --opcode=2 --namespace-id=1 --data-len=4096 --read --cdw10=0 --cdw11=0 --cdw12=0x70000 --raw-binary NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-list-ctrl.1000066400000000000000000000050071322317423600206510ustar00rootroot00000000000000'\" t .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ID\-NS" "1" "12/10/2017" "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-list-ctrl \- Send NVMe Identify List Controllers, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme list\-ctrl\fR [\-\-cntid= | \-c ] [\-\-namespace\-id= | \-n ] DESCRIPTION .fi .sp .nf For the NVMe device given, sends an identify command for controller list and provides the result and returned structure\&. This uses either mode 12h or 13h depending on the requested namespace identifier\&. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. The starting controller in the list always begins with 0 unless the `\*(Aq\-\-cntid\*(Aq` option is given to override\&. On success, the controller array is printed for each index and controller identifier\&. OPTIONS .fi .PP \-c , \-\-cntid= .RS 4 Retrieve the identify list structure starting with the given controller id\&. .RE .PP \-n , \-\-namespace\-id= .RS 4 If provided, will request the controllers attached to the specified namespace\&. If no namespace is given, or set to 0, the command requests the controller list for the entire subsystem, whether or not they are attached to namespace(s)\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-list-ctrl.html000066400000000000000000000442321322317423600214600ustar00rootroot00000000000000 nvme-id-ns(1)

SYNOPSIS

nvme list-ctrl <device> [--cntid=<cntid> | -c <cntid>]
                        [--namespace-id=<nsid> | -n <nsid>]
DESCRIPTION
For the NVMe device given, sends an identify command for controller list
and provides the result and returned structure. This uses either mode
12h or 13h depending on the requested namespace identifier.

The <device> parameter is mandatory and may be either the NVMe character
device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).
The starting controller in the list always begins with 0 unless the
`'--cntid'` option is given to override.

On success, the controller array is printed for each index and controller
identifier.

OPTIONS
-c <cntid>
--cntid=<cntid>

Retrieve the identify list structure starting with the given controller id.

-n <nsid>
--namespace-id=<nsid>

If provided, will request the controllers attached to the specified namespace. If no namespace is given, or set to 0, the command requests the controller list for the entire subsystem, whether or not they are attached to namespace(s).

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-list-ctrl.txt000066400000000000000000000024121322317423600213250ustar00rootroot00000000000000nvme-id-ns(1) ============= NAME ---- nvme-list-ctrl - Send NVMe Identify List Controllers, return result and structure SYNOPSIS -------- [verse] 'nvme list-ctrl' [--cntid= | -c ] [--namespace-id= | -n ] DESCRIPTION ----------- For the NVMe device given, sends an identify command for controller list and provides the result and returned structure. This uses either mode 12h or 13h depending on the requested namespace identifier. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). The starting controller in the list always begins with 0 unless the `'--cntid'` option is given to override. On success, the controller array is printed for each index and controller identifier. OPTIONS ------- -c :: --cntid=:: Retrieve the identify list structure starting with the given controller id. -n :: --namespace-id=:: If provided, will request the controllers attached to the specified namespace. If no namespace is given, or set to 0, the command requests the controller list for the entire subsystem, whether or not they are attached to namespace(s). EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-list-ns.1000066400000000000000000000041361322317423600203270ustar00rootroot00000000000000'\" t .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ID\-NS" "1" "12/10/2017" "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-list-ns \- Send NVMe Identify List Namespaces, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme list\-ns\fR [\-\-namespace\-id= | \-n ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an identify command for namespace list and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. If the starting namespace in the list always begins with 0 unless the \*(Aq\-\-namespace\-id\*(Aq option is given to override\&. .sp On success, the namespace array is printed for each index and nsid for a valid nsid\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the identify list structure starting with the given nsid\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-list-ns.html000066400000000000000000000434741322317423600211430ustar00rootroot00000000000000 nvme-id-ns(1)

SYNOPSIS

nvme list-ns <device> [--namespace-id=<nsid> | -n <nsid>]

DESCRIPTION

For the NVMe device given, sends an identify command for namespace list and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the starting namespace in the list always begins with 0 unless the '--namespace-id' option is given to override.

On success, the namespace array is printed for each index and nsid for a valid nsid.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the identify list structure starting with the given nsid.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-list-ns.txt000066400000000000000000000016011322317423600210000ustar00rootroot00000000000000nvme-id-ns(1) ============= NAME ---- nvme-list-ns - Send NVMe Identify List Namespaces, return result and structure SYNOPSIS -------- [verse] 'nvme list-ns' [--namespace-id= | -n ] DESCRIPTION ----------- For the NVMe device given, sends an identify command for namespace list and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). If the starting namespace in the list always begins with 0 unless the `'--namespace-id'` option is given to override. On success, the namespace array is printed for each index and nsid for a valid nsid. OPTIONS ------- -n :: --namespace-id=:: Retrieve the identify list structure starting with the given nsid. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-list-subsys.1000066400000000000000000000057101322317423600212360ustar00rootroot00000000000000'\" t .\" Title: nvme-list-subsys .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 12/13/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LIST\-SUBSYS" "1" "12/13/2017" "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-list-subsys \- List all NVMe subsystems .SH "SYNOPSIS" .sp .nf \fInvme list\-subsys\fR [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp Scan the sysfs tree for NVM Express subsystems and return the controllers for those subsystems as well as some pertinent information about them\&. .SH "OPTIONS" .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR or \fIjson\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp \m[blue]\fBroot@host\fR\m[]\&\s-2\u[1]\d\s+2# nvme list\-subsys nvme\-subsys0 \- NQN=nvmf\-test \e +\- nvme0 rdma traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.1 +\- nvme1 rdma traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.2 nvme\-subsys1 \- NQN=nvmf\-test2 \e +\- nvme2 rdma traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.2 +\- nvme3 rdma traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.1 .sp \m[blue]\fBroot@host\fR\m[]\&\s-2\u[1]\d\s+2# nvme list\-subsys \-o json { "Subsystems" : [ { "Name" : "nvme\-subsys0", "NQN" : "nvmf\-test" }, { "Paths" : [ { "Name" : "nvme0", "Transport" : "rdma", "Address" : "traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.1" }, { "Name" : "nvme1", "Transport" : "rdma", "Address" : "traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.2" } ] }, { "Name" : "nvme\-subsys1", "NQN" : "nvmf\-test2" }, { "Paths" : [ { "Name" : "nvme2", "Transport" : "rdma", "Address" : "traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.2" }, { "Name" : "nvme3", "Transport" : "rdma", "Address" : "traddr=1\&.1\&.1\&.3 trsvcid=4420 host_traddr=1\&.1\&.1\&.1" } ] } ] } .SH "NVME" .sp Part of the nvme\-user suite .SH "NOTES" .IP " 1." 4 root@host .RS 4 \%mailto:root@host .RE nvme-cli-1.5/Documentation/nvme-list-subsys.html000066400000000000000000000454011322317423600220430ustar00rootroot00000000000000 nvme-list-subsys(1)

SYNOPSIS

nvme list-subsys [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

Scan the sysfs tree for NVM Express subsystems and return the controllers for those subsystems as well as some pertinent information about them.

OPTIONS

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

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

EXAMPLES

root@host# nvme list-subsys nvme-subsys0 - NQN=nvmf-test \ +- nvme0 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1 +- nvme1 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2 nvme-subsys1 - NQN=nvmf-test2 \ +- nvme2 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2 +- nvme3 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1

root@host# nvme list-subsys -o json { "Subsystems" : [ { "Name" : "nvme-subsys0", "NQN" : "nvmf-test" }, { "Paths" : [ { "Name" : "nvme0", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1" }, { "Name" : "nvme1", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2" } ] }, { "Name" : "nvme-subsys1", "NQN" : "nvmf-test2" }, { "Paths" : [ { "Name" : "nvme2", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2" }, { "Name" : "nvme3", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1" } ] } ] }

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-list-subsys.txt000066400000000000000000000034011322317423600217100ustar00rootroot00000000000000nvme-list-subsys(1) =================== NAME ---- nvme-list-subsys - List all NVMe subsystems SYNOPSIS -------- [verse] 'nvme list-subsys' [-o | --output-format=] DESCRIPTION ----------- Scan the sysfs tree for NVM Express subsystems and return the controllers for those subsystems as well as some pertinent information about them. OPTIONS ------- -o :: --output-format=:: Set the reporting format to 'normal' or 'json'. Only one output format can be used at a time. EXAMPLES -------- root@host# nvme list-subsys nvme-subsys0 - NQN=nvmf-test \ +- nvme0 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1 +- nvme1 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2 nvme-subsys1 - NQN=nvmf-test2 \ +- nvme2 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2 +- nvme3 rdma traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1 root@host# nvme list-subsys -o json { "Subsystems" : [ { "Name" : "nvme-subsys0", "NQN" : "nvmf-test" }, { "Paths" : [ { "Name" : "nvme0", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1" }, { "Name" : "nvme1", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2" } ] }, { "Name" : "nvme-subsys1", "NQN" : "nvmf-test2" }, { "Paths" : [ { "Name" : "nvme2", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.2" }, { "Name" : "nvme3", "Transport" : "rdma", "Address" : "traddr=1.1.1.3 trsvcid=4420 host_traddr=1.1.1.1" } ] } ] } NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-list.1000066400000000000000000000033621322317423600177110ustar00rootroot00000000000000'\" t .\" Title: nvme-list .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LIST" "1" "12/10/2017" "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-list \- List all recognized NVMe devices .SH "SYNOPSIS" .sp .nf \fInvme list\fR [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp Scan the sysfs tree for NVM Express devices and return the /dev node for those devices as well as some pertinent information about them\&. .SH "OPTIONS" .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR or \fIjson\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-list.html000066400000000000000000000426211322317423600205160ustar00rootroot00000000000000 nvme-list(1)

SYNOPSIS

nvme list [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

Scan the sysfs tree for NVM Express devices and return the /dev node for those devices as well as some pertinent information about them.

OPTIONS

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

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

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-list.txt000066400000000000000000000010431322317423600203620ustar00rootroot00000000000000nvme-list(1) ============ NAME ---- nvme-list - List all recognized NVMe devices SYNOPSIS -------- [verse] 'nvme list' [-o | --output-format=] DESCRIPTION ----------- Scan the sysfs tree for NVM Express devices and return the /dev node for those devices as well as some pertinent information about them. OPTIONS ------- -o :: --output-format=:: Set the reporting format to 'normal' or 'json'. Only one output format can be used at a time. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-create.1000066400000000000000000000054611322317423600211550ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-create .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-CREATE" "1" "12/10/2017" "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-lnvm-create \- Instantiate a target on top of a LightNVM enabled device .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-create\fR [\-\-device\-name= | \-d ] [\-\-target\-name= | \-n ] [\-\-target\-type= | \-t ] [\-\-lun\-begin | \-b ] [\-\-lun\-end | \-e ] .fi .SH "DESCRIPTION" .sp Instantiate a target on top of a LightNVM enabled device\&. This exposes the physical for the user to use\&. .sp The target name is the name of which the media is exposed as in /dev/ .sp The target type is the target to be instantiated\&. Typically pblk or rrpc\&. .sp LUN begin and end defines the range of LUNs to use for a target instantiation\&. .SH "OPTIONS" .PP \-\-device\-name=, \-d .RS 4 Device name to initialize\&. .RE .PP \-\-target\-name=, \-n .RS 4 Target name of the device to initialize\&. For example: target0\&. .RE .PP \-\-target\-type=, \-t .RS 4 Target type of the device to use\&. For example: pblk .RE .PP \-\-lun\-begin , \-b .RS 4 Begin LUN id offset to use for target .RE .PP \-\-lun\-end , \-e .RS 4 End LUN id offset to use for target .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Initialize nvme0n1 with pblk target with 64 LUNs\&. .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-create \-d nvme0n1 \-t pblk \-n target0 \-b 0 \-e 63 .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-create.html000066400000000000000000000456101322317423600217610ustar00rootroot00000000000000 nvme-lnvm-create(1)

SYNOPSIS

nvme lnvm-create [--device-name=<DEVICE> | -d <DEVICE>]
                        [--target-name=<TARGET> | -n <TARGET>]
                        [--target-type=<TARGETTYPE> | -t <TARGETTYPE>]
                        [--lun-begin <NUM> | -b <NUM>]
                        [--lun-end <NUM> | -e <NUM>]

DESCRIPTION

Instantiate a target on top of a LightNVM enabled device. This exposes the physical for the user to use.

The target name is the name of which the media is exposed as in /dev/<targetname>

The target type is the target to be instantiated. Typically pblk or rrpc.

LUN begin and end defines the range of LUNs to use for a target instantiation.

OPTIONS

--device-name=<DEVICE>
-d <DEVICE>

Device name to initialize.

--target-name=<TARGET>
-n <TARGET>

Target name of the device to initialize. For example: target0.

--target-type=<TARGETTYPE>
-t <TARGETTYPE>

Target type of the device to use. For example: pblk

--lun-begin <NUM>
-b <NUM>

Begin LUN id offset to use for target

--lun-end <NUM>
-e <NUM>

End LUN id offset to use for target

EXAMPLES

  • Initialize nvme0n1 with pblk target with 64 LUNs.

# nvme lnvm-create -d nvme0n1 -t pblk -n target0 -b 0 -e 63

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-create.txt000066400000000000000000000025211322317423600216260ustar00rootroot00000000000000nvme-lnvm-create(1) =================== NAME ---- nvme-lnvm-create - Instantiate a target on top of a LightNVM enabled device SYNOPSIS -------- [verse] 'nvme lnvm-create' [--device-name= | -d ] [--target-name= | -n ] [--target-type= | -t ] [--lun-begin | -b ] [--lun-end | -e ] DESCRIPTION ----------- Instantiate a target on top of a LightNVM enabled device. This exposes the physical for the user to use. The target name is the name of which the media is exposed as in /dev/ The target type is the target to be instantiated. Typically pblk or rrpc. LUN begin and end defines the range of LUNs to use for a target instantiation. OPTIONS ------- --device-name=:: -d :: Device name to initialize. --target-name=:: -n :: Target name of the device to initialize. For example: target0. --target-type=:: -t :: Target type of the device to use. For example: pblk --lun-begin :: -b :: Begin LUN id offset to use for target --lun-end :: -e :: End LUN id offset to use for target EXAMPLES -------- * Initialize nvme0n1 with pblk target with 64 LUNs. ------------ # nvme lnvm-create -d nvme0n1 -t pblk -n target0 -b 0 -e 63 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-diag-bbtbl.1000066400000000000000000000054451322317423600217030ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-diag-bbtbl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-DIAG\-BB" "1" "12/10/2017" "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-lnvm-diag-bbtbl \- Diagnose the bad block table .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-diag\-bbtbl\fR [\-\-namespace\-id= | \-n ] [\-\-channel\-id= | \-c ] [\-\-lun\-id= | \-l ] [\-\-raw\-binary | \-b] .fi .SH "DESCRIPTION" .sp Retrieve the bad block table for a given channel and lun\&. .sp The statistics will be shown in the default case, and the actual output bad block information can be retrieved when \-\-raw\-binary is passed\&. .sp The raw binary output follows this format: .sp Channel 0, LUN0 (Dual plane flash) .sp Byte 0 \(-> Plane 0, Block 0 Byte 1 \(-> Plane 1, Block 0 Byte 2 \(-> Plane 0, Block 1 \&... .SH "OPTIONS" .PP \-\-namespace\-id=, \-n .RS 4 Namespace id to use .RE .PP \-\-channel\-id=, \-c .RS 4 Channel id .RE .PP \-\-lun\-id=, \-l .RS 4 LUN id .RE .PP \-\-raw\-binary, \-b .RS 4 Returns the bad block table in binary form without statistics\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Retrieve bad block table statistics for physical device nvme0, channel 0, and lun 0: .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-diag\-bbtbl /dev/nvme0 \-c 0 \-n 0 .fi .if n \{\ .RE .\} .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Display the bad block table in raw form without statistics for same query: .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-diag\-bbtbl /dev/nvme0 \-c 0 \-n 0 \-b | hexdump .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-diag-bbtbl.html000066400000000000000000000455011322317423600225040ustar00rootroot00000000000000 nvme-lnvm-diag-bbtbl(1)

SYNOPSIS

nvme lnvm-diag-bbtbl [--namespace-id=<NUM> | -n <NUM>]
                        [--channel-id=<CHID> | -c <CHID>]
                        [--lun-id=<LUNID> | -l <LUNID>]
                        [--raw-binary | -b]

DESCRIPTION

Retrieve the bad block table for a given channel and lun.

The statistics will be shown in the default case, and the actual output bad block information can be retrieved when --raw-binary is passed.

The raw binary output follows this format:

Channel 0, LUN0 (Dual plane flash)

Byte 0 → Plane 0, Block 0 Byte 1 → Plane 1, Block 0 Byte 2 → Plane 0, Block 1 …

OPTIONS

--namespace-id=<NUM>
-n <NUM>

Namespace id to use

--channel-id=<NUM>
-c

Channel id

--lun-id=<NUM>
-l

LUN id

--raw-binary
-b

Returns the bad block table in binary form without statistics.

EXAMPLES

  • Retrieve bad block table statistics for physical device nvme0, channel 0, and lun 0:

# nvme lnvm-diag-bbtbl /dev/nvme0 -c 0 -n 0
  • Display the bad block table in raw form without statistics for same query:

# nvme lnvm-diag-bbtbl /dev/nvme0 -c 0 -n 0 -b | hexdump

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-diag-bbtbl.txt000066400000000000000000000024031322317423600223510ustar00rootroot00000000000000nvme-lnvm-diag-bbtbl(1) ======================= NAME ---- nvme-lnvm-diag-bbtbl - Diagnose the bad block table SYNOPSIS -------- [verse] 'nvme lnvm-diag-bbtbl' [--namespace-id= | -n ] [--channel-id= | -c ] [--lun-id= | -l ] [--raw-binary | -b] DESCRIPTION ----------- Retrieve the bad block table for a given channel and lun. The statistics will be shown in the default case, and the actual output bad block information can be retrieved when --raw-binary is passed. The raw binary output follows this format: Channel 0, LUN0 (Dual plane flash) Byte 0 -> Plane 0, Block 0 Byte 1 -> Plane 1, Block 0 Byte 2 -> Plane 0, Block 1 ... OPTIONS ------- --namespace-id=:: -n :: Namespace id to use --channel-id=:: -c:: Channel id --lun-id=:: -l:: LUN id --raw-binary:: -b:: Returns the bad block table in binary form without statistics. EXAMPLES -------- * Retrieve bad block table statistics for physical device nvme0, channel 0, and lun 0: ------------ # nvme lnvm-diag-bbtbl /dev/nvme0 -c 0 -n 0 ------------ * Display the bad block table in raw form without statistics for same query: ------------ # nvme lnvm-diag-bbtbl /dev/nvme0 -c 0 -n 0 -b | hexdump ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-diag-set-bbtbl.1000066400000000000000000000051331322317423600224660ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-diag-set-bbtbl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-DIAG\-SE" "1" "12/10/2017" "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-lnvm-diag-set-bbtbl \- Set a block state in the bad block table .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-diag\-set\-bbtbl\fR [\-\-namespace\-id= | \-n ] [\-\-channel\-id= | \-c ] [\-\-lun\-id= | \-l ] [\-\-plane\-id= | \-p ] [\-\-block\-id= | \-b ] [\-\-value= | \-v ] .fi .SH "DESCRIPTION" .sp Set the bad block table for a given channel, lun, plane and block with value v\&. .sp For each block available, the status byte is read as follows: .sp 0: Good block 1: Bad block 2: Grown bad block 4: Device reserved block 8: Host\-side reserved block 16: Media managed reserved block .SH "OPTIONS" .PP \-\-namespace\-id=, \-n .RS 4 Namespace id to use .RE .PP \-\-channel\-id, \-c .RS 4 Channel id .RE .PP \-\-lun\-id, \-l .RS 4 LUN id .RE .PP \-\-plane\-id, \-p .RS 4 Plane id .RE .PP \-\-block\-id, \-b .RS 4 Block id .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Set channel 0, lun 0, plane 0, block 10 to bad block value 2 (grown bad) on physical device /dev/nvme0 .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-diag\-set\-bbtbl /dev/nvme0 \-c 0 \-l 0 \-p 0 \-b 10 \-v 2 .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-diag-set-bbtbl.html000066400000000000000000000451761322317423600233050ustar00rootroot00000000000000 nvme-lnvm-diag-set-bbtbl(1)

SYNOPSIS

nvme lnvm-diag-set-bbtbl [--namespace-id=<NUM> | -n <NUM>]
                        [--channel-id=<CHID> | -c <CHID>]
                        [--lun-id=<LUNID> | -l <LUNID>]
                        [--plane-id=<PLANEID> | -p <PLANEID>]
                        [--block-id=<BLKID> | -b <BLKID>]
                        [--value=<NUM> | -v <NUM>]

DESCRIPTION

Set the bad block table for a given channel, lun, plane and block with value v.

For each block available, the status byte is read as follows:

0: Good block 1: Bad block 2: Grown bad block 4: Device reserved block 8: Host-side reserved block 16: Media managed reserved block

OPTIONS

--namespace-id=<NUM>
-n <NUM>

Namespace id to use

--channel-id
-c

Channel id

--lun-id
-l

LUN id

--plane-id
-p

Plane id

--block-id
-b

Block id

EXAMPLES

  • Set channel 0, lun 0, plane 0, block 10 to bad block value 2 (grown bad) on physical device /dev/nvme0

# nvme lnvm-diag-set-bbtbl /dev/nvme0 -c 0 -l 0 -p 0 -b 10 -v 2

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-diag-set-bbtbl.txt000066400000000000000000000021731322317423600231460ustar00rootroot00000000000000nvme-lnvm-diag-set-bbtbl(1) =========================== NAME ---- nvme-lnvm-diag-set-bbtbl - Set a block state in the bad block table SYNOPSIS -------- [verse] 'nvme lnvm-diag-set-bbtbl' [--namespace-id= | -n ] [--channel-id= | -c ] [--lun-id= | -l ] [--plane-id= | -p ] [--block-id= | -b ] [--value= | -v ] DESCRIPTION ----------- Set the bad block table for a given channel, lun, plane and block with value v. For each block available, the status byte is read as follows: 0: Good block 1: Bad block 2: Grown bad block 4: Device reserved block 8: Host-side reserved block 16: Media managed reserved block OPTIONS ------- --namespace-id=:: -n :: Namespace id to use --channel-id:: -c:: Channel id --lun-id:: -l:: LUN id --plane-id:: -p:: Plane id --block-id:: -b:: Block id EXAMPLES -------- * Set channel 0, lun 0, plane 0, block 10 to bad block value 2 (grown bad) on physical device /dev/nvme0 ------------ # nvme lnvm-diag-set-bbtbl /dev/nvme0 -c 0 -l 0 -p 0 -b 10 -v 2 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-factory.1000066400000000000000000000050531322317423600213560ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-factory .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-FACTORY" "1" "12/10/2017" "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-lnvm-factory \- Factory reset a LightNVM device .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-factory\fR [\-\-device\-name= | \-d ] [\-\-erase\-only\-marked | \-e] [\-\-clear\-host\-side\-blks | \-s] [\-\-clear\-bb\-blks | \-b] .fi .SH "DESCRIPTION" .sp Instantiate a target on top of a LightNVM enabled device\&. This exposes the physical for the user to use\&. .SH "OPTIONS" .PP \-\-device\-name=, \-d .RS 4 Device name to factory initialize .RE .PP \-\-erase\-only\-marked, \-e .RS 4 Erases only blocks that are marked in the bad block list .RE .PP \-\-clear\-host\-side\-blks, \-s .RS 4 Remove host\-side bad block marks\&. This clear the media manager registration .RE .PP \-\-clear\-bb\-blks, \-b .RS 4 Removes the grown bad block marks\&. Allowing them to be rediscovered\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Factory reset of device nvme0n1 .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-factory \-d nvme0n1 .fi .if n \{\ .RE .\} .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Complete factory reset of device nvme0n1 .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-factory \-d nvme0n1 \-s \-b .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-factory.html000066400000000000000000000446211322317423600221660ustar00rootroot00000000000000 nvme-lnvm-factory(1)

SYNOPSIS

nvme lnvm-factory [--device-name=<DEVICE> | -d <DEVICE>]
                        [--erase-only-marked | -e]
                        [--clear-host-side-blks | -s]
                        [--clear-bb-blks | -b]

DESCRIPTION

Instantiate a target on top of a LightNVM enabled device. This exposes the physical for the user to use.

OPTIONS

--device-name=<DEVICE>
-d <DEVICE>

Device name to factory initialize

--erase-only-marked
-e

Erases only blocks that are marked in the bad block list

--clear-host-side-blks
-s

Remove host-side bad block marks. This clear the media manager registration

--clear-bb-blks
-b

Removes the grown bad block marks. Allowing them to be rediscovered.

EXAMPLES

  • Factory reset of device nvme0n1

# nvme lnvm-factory -d nvme0n1
  • Complete factory reset of device nvme0n1

# nvme lnvm-factory -d nvme0n1 -s -b

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-factory.txt000066400000000000000000000020261322317423600220320ustar00rootroot00000000000000nvme-lnvm-factory(1) ==================== NAME ---- nvme-lnvm-factory - Factory reset a LightNVM device SYNOPSIS -------- [verse] 'nvme lnvm-factory' [--device-name= | -d ] [--erase-only-marked | -e] [--clear-host-side-blks | -s] [--clear-bb-blks | -b] DESCRIPTION ----------- Instantiate a target on top of a LightNVM enabled device. This exposes the physical for the user to use. OPTIONS ------- --device-name=:: -d :: Device name to factory initialize --erase-only-marked:: -e:: Erases only blocks that are marked in the bad block list --clear-host-side-blks:: -s:: Remove host-side bad block marks. This clear the media manager registration --clear-bb-blks:: -b:: Removes the grown bad block marks. Allowing them to be rediscovered. EXAMPLES -------- * Factory reset of device nvme0n1 ------------ # nvme lnvm-factory -d nvme0n1 ------------ * Complete factory reset of device nvme0n1 ------------ # nvme lnvm-factory -d nvme0n1 -s -b ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-id-ns.1000066400000000000000000000044311322317423600207200ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-id-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-ID\-NS" "1" "12/10/2017" "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-lnvm-id-ns \- Identify Geometry for LightNVM NVMe device .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-id\-ns\fR [\-\-namespace\-id= | \-n ] [\-\-force | \-f] [\-\-raw\-binary | \-b] [\-\-human\-readable | \-H] .fi .SH "DESCRIPTION" .sp Send an Identify Geometry command to the given LightNVM device, returns properties of the specified namespace in either human\-readable or binary format\&. .SH "OPTIONS" .PP \-\-namespace\-id=, \-n .RS 4 Retrieve the geometry from the selected namespace\&. .RE .PP \-\-force, \-f .RS 4 Try to read the data and assume it is a LightNVM device .RE .PP \-\-raw\-binary, \-b .RS 4 Output the raw output .RE .PP \-\-human\-readable, \-H .RS 4 Output the status in human readable format .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Retrieve the geometry from nvme0 .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-id\-ns /dev/nvme0 \-n 1 .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-id-ns.html000066400000000000000000000441701322317423600215300ustar00rootroot00000000000000 nvme-lnvm-id-ns(1)

SYNOPSIS

nvme lnvm-id-ns <device> [--namespace-id=<nsid> | -n <nsid>]
                        [--force | -f]
                        [--raw-binary | -b]
                        [--human-readable | -H]

DESCRIPTION

Send an Identify Geometry command to the given LightNVM device, returns properties of the specified namespace in either human-readable or binary format.

OPTIONS

--namespace-id=<nsid>
-n <nsid>

Retrieve the geometry from the selected namespace.

--force
-f

Try to read the data and assume it is a LightNVM device

--raw-binary
-b

Output the raw output

--human-readable
-H

Output the status in human readable format

EXAMPLES

  • Retrieve the geometry from nvme0

# nvme lnvm-id-ns /dev/nvme0 -n 1

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-id-ns.txt000066400000000000000000000015721322317423600214020ustar00rootroot00000000000000nvme-lnvm-id-ns(1) ================== NAME ---- nvme-lnvm-id-ns - Identify Geometry for LightNVM NVMe device SYNOPSIS -------- [verse] 'nvme lnvm-id-ns' [--namespace-id= | -n ] [--force | -f] [--raw-binary | -b] [--human-readable | -H] DESCRIPTION ----------- Send an Identify Geometry command to the given LightNVM device, returns properties of the specified namespace in either human-readable or binary format. OPTIONS ------- --namespace-id=:: -n :: Retrieve the geometry from the selected namespace. --force:: -f:: Try to read the data and assume it is a LightNVM device --raw-binary:: -b:: Output the raw output --human-readable:: -H:: Output the status in human readable format EXAMPLES -------- * Retrieve the geometry from nvme0 ------------ # nvme lnvm-id-ns /dev/nvme0 -n 1 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-info.1000066400000000000000000000030621322317423600206400ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-info .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-INFO" "1" "12/10/2017" "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-lnvm-info \- Show general information and registered target types with LightNVM .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-info\fR .fi .SH "DESCRIPTION" .sp Show general information and registered target types with LightNVM\&. .SH "OPTIONS" .sp No options yet\&. .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-info.html000066400000000000000000000421361322317423600214510ustar00rootroot00000000000000 nvme-lnvm-info(1)

SYNOPSIS

nvme lnvm-info

DESCRIPTION

Show general information and registered target types with LightNVM.

OPTIONS

No options yet.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-info.txt000066400000000000000000000005701322317423600213200ustar00rootroot00000000000000nvme-lnvm-info(1) ================= NAME ---- nvme-lnvm-info - Show general information and registered target types with LightNVM SYNOPSIS -------- [verse] 'nvme lnvm-info' DESCRIPTION ----------- Show general information and registered target types with LightNVM. OPTIONS ------- No options yet. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-init.1000066400000000000000000000045031322317423600206510ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-init .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-INIT" "1" "12/10/2017" "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-lnvm-init \- Initialize LightNVM device with media manager .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-init\fR [\-\-device\-name= | \-d ] [\-\-mediamgr\-name | \-m] .fi .SH "DESCRIPTION" .sp Initialize LightNVM device\&. A LightNVM/Open\-Channel SSD must have a media manager associated before it can be exposed to the user\&. The default is to initialize the general media manager on top of the device\&. .SH "OPTIONS" .PP \-\-device\-name=, \-d .RS 4 Device name to initialize\&. .RE .PP \-\-mediamgr\-name=, \-m .RS 4 Media Manager name to use for initialization\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Initialize nvme0n1 .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-init \-d nvme0n1 .fi .if n \{\ .RE .\} .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Initialize nvme0n1 with gennvm media manager (default media manager) .RE .sp .if n \{\ .RS 4 .\} .nf # nvme lnvm\-init \-d nvme0n1 \-m gennvm .fi .if n \{\ .RE .\} .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-init.html000066400000000000000000000440511322317423600214570ustar00rootroot00000000000000 nvme-lnvm-init(1)

SYNOPSIS

nvme lnvm-init [--device-name=<DEVICE> | -d <DEVICE>]
                        [--mediamgr-name | -m]

DESCRIPTION

Initialize LightNVM device. A LightNVM/Open-Channel SSD must have a media manager associated before it can be exposed to the user. The default is to initialize the general media manager on top of the device.

OPTIONS

--device-name=<DEVICE>
-d <DEVICE>

Device name to initialize.

--mediamgr-name=<MediaMgr>
-m <MediaMgr>

Media Manager name to use for initialization.

EXAMPLES

  • Initialize nvme0n1

# nvme lnvm-init -d nvme0n1
  • Initialize nvme0n1 with gennvm media manager (default media manager)

# nvme lnvm-init -d nvme0n1 -m gennvm

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-init.txt000066400000000000000000000016031322317423600213260ustar00rootroot00000000000000nvme-lnvm-init(1) ================= NAME ---- nvme-lnvm-init - Initialize LightNVM device with media manager SYNOPSIS -------- [verse] 'nvme lnvm-init' [--device-name= | -d ] [--mediamgr-name | -m] DESCRIPTION ----------- Initialize LightNVM device. A LightNVM/Open-Channel SSD must have a media manager associated before it can be exposed to the user. The default is to initialize the general media manager on top of the device. OPTIONS ------- --device-name=:: -d :: Device name to initialize. --mediamgr-name=:: -m :: Media Manager name to use for initialization. EXAMPLES -------- * Initialize nvme0n1 ------------ # nvme lnvm-init -d nvme0n1 ------------ * Initialize nvme0n1 with gennvm media manager (default media manager) ------------ # nvme lnvm-init -d nvme0n1 -m gennvm ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-list.1000066400000000000000000000027731322317423600206700ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-list .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-LIST" "1" "12/10/2017" "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-lnvm-list \- List all recognized LightNVM NVMe devices .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-list\fR .fi .SH "DESCRIPTION" .sp List all registered LightNVM devices\&. .SH "OPTIONS" .sp No options yet\&. .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-list.html000066400000000000000000000420471322317423600214720ustar00rootroot00000000000000 nvme-lnvm-list(1)

SYNOPSIS

nvme lnvm-list

DESCRIPTION

List all registered LightNVM devices.

OPTIONS

No options yet.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-list.txt000066400000000000000000000005021322317423600213330ustar00rootroot00000000000000nvme-lnvm-list(1) ================= NAME ---- nvme-lnvm-list - List all recognized LightNVM NVMe devices SYNOPSIS -------- [verse] 'nvme lnvm-list' DESCRIPTION ----------- List all registered LightNVM devices. OPTIONS ------- No options yet. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-lnvm-remove.1000066400000000000000000000033201322317423600211770ustar00rootroot00000000000000'\" t .\" Title: nvme-lnvm-remove .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-LNVM\-REMOVE" "1" "12/10/2017" "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-lnvm-remove \- Remove an initialized LightNVM target\&. .SH "SYNOPSIS" .sp .nf \fInvme lnvm\-remove\fR [\-\-target\-name= | \-n ] .fi .SH "DESCRIPTION" .sp Remove an initialized target\&. .sp The target name is the name of which the media is exposed as in /dev/ .SH "OPTIONS" .PP \-\-target\-name=, \-n .RS 4 Target name of the device to initialize\&. For example: target0\&. .RE .SH "EXAMPLES" .sp None yet .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-lnvm-remove.html000066400000000000000000000426051322317423600220140ustar00rootroot00000000000000 nvme-lnvm-remove(1)

SYNOPSIS

nvme lnvm-remove [--target-name=<TARGET> | -n <TARGET>]

DESCRIPTION

Remove an initialized target.

The target name is the name of which the media is exposed as in /dev/<TARGET>

OPTIONS

--target-name=<TARGET>
-n <TARGET>

Target name of the device to initialize. For example: target0.

EXAMPLES

None yet

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-lnvm-remove.txt000066400000000000000000000010031322317423600216520ustar00rootroot00000000000000nvme-lnvm-remove(1) =================== NAME ---- nvme-lnvm-remove - Remove an initialized LightNVM target. SYNOPSIS -------- [verse] 'nvme lnvm-remove' [--target-name= | -n ] DESCRIPTION ----------- Remove an initialized target. The target name is the name of which the media is exposed as in /dev/ OPTIONS ------- --target-name=:: -n :: Target name of the device to initialize. For example: target0. EXAMPLES -------- None yet NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-ns-rescan.1000066400000000000000000000033701322317423600206260ustar00rootroot00000000000000'\" t .\" Title: nvme-ns-rescan .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-NS\-RESCAN" "1" "12/10/2017" "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-ns-rescan \- Rescans the nvme namespaces\&. .SH "SYNOPSIS" .sp .nf \fInvme ns\-rescan\fR .fi .SH "DESCRIPTION" .sp Requests NVMe controller rescans the namespaces\&. The param is mandatory and must be an NVMe character device (ex: /dev/nvme0)\&. .SH "OPTIONS" .sp None .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Rescans the nvme namespaces\&. .sp .if n \{\ .RS 4 .\} .nf # nvme ns\-rescan /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-ns-rescan.html000066400000000000000000000173371322317423600214420ustar00rootroot00000000000000 nvme-ns-rescan(1)

SYNOPSIS

nvme ns-rescan <device>

DESCRIPTION

Requests NVMe controller rescans the namespaces. The <device> param is mandatory and must be an NVMe character device (ex: /dev/nvme0).

OPTIONS

None

EXAMPLES

  • Rescans the nvme namespaces.

    # nvme ns-rescan /dev/nvme0

NVME

Part of the nvme-user suite

nvme-cli-1.5/Documentation/nvme-ns-rescan.txt000066400000000000000000000007321322317423600213040ustar00rootroot00000000000000nvme-ns-rescan(1) ================= NAME ---- nvme-ns-rescan - Rescans the nvme namespaces. SYNOPSIS -------- [verse] 'nvme ns-rescan' DESCRIPTION ----------- Requests NVMe controller rescans the namespaces. The param is mandatory and must be an NVMe character device (ex: /dev/nvme0). OPTIONS ------- None EXAMPLES -------- * Rescans the nvme namespaces. + ------------ # nvme ns-rescan /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-read.1000066400000000000000000000077161322317423600176600ustar00rootroot00000000000000'\" t .\" Title: nvme-read .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-READ" "1" "12/10/2017" "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-read \- Send an NVMe Read command, provide results .SH "SYNOPSIS" .sp .nf \fInvme\-read\fR [\-\-start\-block= | \-s ] [\-\-block\-count= | \-c ] [\-\-data\-size= | \-z ] [\-\-metadata\-size= | \-y ] [\-\-ref\-tag= | \-r ] [\-\-data= | \-d ] [\-\-metadata= | \-M ] [\-\-prinfo= | \-p ] [\-\-app\-tag\-mask= | \-m ] [\-\-app\-tag= | \-a ] [\-\-limited\-retry | \-l] [\-\-latency | \-t] [\-\-force\-unit\-access | \-f] .fi .SH "DESCRIPTION" .sp The Read command reads the logical blocks specified by the command from the medium and copies to the data data buffer provided\&. Will use stdout by default if you don\(cqt provide a file\&. .SH "OPTIONS" .PP \-\-start\-block=, \-s .RS 4 Start block\&. .RE .PP \-\-block\-count, \-c .RS 4 The number of blocks to transfer\&. This is a zeroes based value to align with the kernel\(cqs use of this field\&. (ie\&. 0 means transfer 1 block)\&. .RE .PP \-\-data\-size=, \-z .RS 4 Size of data, in bytes\&. .RE .PP \-\-metadata\-size=, \-y .RS 4 Size of metadata in bytes\&. .RE .PP \-\-data=, \-d .RS 4 Data file\&. If none provided, contents are sent to STDOUT\&. .RE .PP \-\-metadata=, \-M .RS 4 Metadata file, if necessary\&. .RE .PP \-\-prinfo=, \-p .RS 4 Protection Information field defintion\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt. T{ Bit T}:T{ Description T} T{ 3 T}:T{ PRACT: Protection Information Action\&. When set to 1, PI is stripped/inserted on read/write when the block format\(cqs metadata size is 8\&. When set to 0, metadata is passes\&. T} T{ 2:0 T}:T{ PRCHK: Protection Information Check: T} T{ 2 T}:T{ Set to 1 enables checking the guard tag T} T{ 1 T}:T{ Set to 1 enables checking the application tag T} T{ 0 T}:T{ Set to 1 enables checking the reference tag T} .TE .sp 1 .RE .PP \-\-ref\-tag=, \-r .RS 4 Optional reftag when used with protection information\&. .RE .PP \-\-app\-tag\-mask=, \-m .RS 4 Optional application tag mask when used with protection information\&. .RE .PP \-\-force\-unit\-access, \-f .RS 4 Set the force\-unit access flag\&. .RE .PP \-\-latency, \-t .RS 4 Print out the latency the IOCTL took (in us)\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-read.html000066400000000000000000000524071322317423600204610ustar00rootroot00000000000000 nvme-read(1)

SYNOPSIS

nvme-read <device> [--start-block=<slba> | -s <slba>]
                        [--block-count=<nlb> | -c <nlb>]
                        [--data-size=<size> | -z <size>]
                        [--metadata-size=<size> | -y <size>]
                        [--ref-tag=<reftag> | -r <reftag>]
                        [--data=<data-file> | -d <data-file>]
                        [--metadata=<metadata-file> | -M <metadata-file>]
                        [--prinfo=<prinfo> | -p <prinfo>]
                        [--app-tag-mask=<appmask> | -m <appmask>]
                        [--app-tag=<apptag> | -a <apptag>]
                        [--limited-retry | -l]
                        [--latency | -t]
                        [--force-unit-access | -f]

DESCRIPTION

The Read command reads the logical blocks specified by the command from the medium and copies to the data data buffer provided. Will use stdout by default if you don’t provide a file.

OPTIONS

--start-block=<slba>
-s <slba>

Start block.

--block-count
-c

The number of blocks to transfer. This is a zeroes based value to align with the kernel’s use of this field. (ie. 0 means transfer 1 block).

--data-size=<size>
-z <size>

Size of data, in bytes.

--metadata-size=<size>
-y <size>

Size of metadata in bytes.

--data=<data-file>
-d <data-file>

Data file. If none provided, contents are sent to STDOUT.

--metadata=<metadata-file>
-M <metadata-file>

Metadata file, if necessary.

--prinfo=<prinfo>
-p <prinfo>

Protection Information field defintion.

Bit

Description

3

PRACT: Protection Information Action. When set to 1, PI is stripped/inserted on read/write when the block format’s metadata size is 8. When set to 0, metadata is passes.

2:0

PRCHK: Protection Information Check:

2

Set to 1 enables checking the guard tag

1

Set to 1 enables checking the application tag

0

Set to 1 enables checking the reference tag

--ref-tag=<reftag>
-r <reftag>

Optional reftag when used with protection information.

--app-tag-mask=<appmask>
-m <appmask>

Optional application tag mask when used with protection information.

--force-unit-access
-f

Set the force-unit access flag.

--latency
-t

Print out the latency the IOCTL took (in us).

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-read.txt000066400000000000000000000043201322317423600203230ustar00rootroot00000000000000nvme-read(1) ============ NAME ---- nvme-read - Send an NVMe Read command, provide results SYNOPSIS -------- [verse] 'nvme-read' [--start-block= | -s ] [--block-count= | -c ] [--data-size= | -z ] [--metadata-size= | -y ] [--ref-tag= | -r ] [--data= | -d ] [--metadata= | -M ] [--prinfo= | -p ] [--app-tag-mask= | -m ] [--app-tag= | -a ] [--limited-retry | -l] [--latency | -t] [--force-unit-access | -f] DESCRIPTION ----------- The Read command reads the logical blocks specified by the command from the medium and copies to the data data buffer provided. Will use stdout by default if you don't provide a file. OPTIONS ------- --start-block=:: -s :: Start block. --block-count:: -c:: The number of blocks to transfer. This is a zeroes based value to align with the kernel's use of this field. (ie. 0 means transfer 1 block). --data-size=:: -z :: Size of data, in bytes. --metadata-size=:: -y :: Size of metadata in bytes. --data=:: -d :: Data file. If none provided, contents are sent to STDOUT. --metadata=:: -M :: Metadata file, if necessary. --prinfo=:: -p :: Protection Information field defintion. + [] |================= |Bit|Description |3|PRACT: Protection Information Action. When set to 1, PI is stripped/inserted on read/write when the block format's metadata size is 8. When set to 0, metadata is passes. |2:0|PRCHK: Protection Information Check: |2|Set to 1 enables checking the guard tag |1|Set to 1 enables checking the application tag |0|Set to 1 enables checking the reference tag |================= --ref-tag=:: -r :: Optional reftag when used with protection information. --app-tag-mask=:: -m :: Optional application tag mask when used with protection information. --force-unit-access:: -f:: Set the force-unit access flag. --latency:: -t:: Print out the latency the IOCTL took (in us). EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-reset.1000066400000000000000000000033101322317423600200510ustar00rootroot00000000000000'\" t .\" Title: nvme-reset .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-RESET" "1" "12/10/2017" "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-reset \- Reset the nvme controller\&. .SH "SYNOPSIS" .sp .nf \fInvme reset\fR .fi .SH "DESCRIPTION" .sp Requests NVMe controller reset\&. The param is mandatory and must be an NVMe character device (ex: /dev/nvme0)\&. .SH "OPTIONS" .sp None .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Resets the controller\&. .sp .if n \{\ .RS 4 .\} .nf # nvme reset /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-reset.html000066400000000000000000000423661322317423600206730ustar00rootroot00000000000000 nvme-reset(1)

SYNOPSIS

nvme reset <device>

DESCRIPTION

Requests NVMe controller reset. The <device> param is mandatory and must be an NVMe character device (ex: /dev/nvme0).

OPTIONS

None

EXAMPLES

  • Resets the controller.

    # nvme reset /dev/nvme0

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-reset.txt000066400000000000000000000006551322317423600205410ustar00rootroot00000000000000nvme-reset(1) ============= NAME ---- nvme-reset - Reset the nvme controller. SYNOPSIS -------- [verse] 'nvme reset' DESCRIPTION ----------- Requests NVMe controller reset. The param is mandatory and must be an NVMe character device (ex: /dev/nvme0). OPTIONS ------- None EXAMPLES -------- * Resets the controller. + ------------ # nvme reset /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-resv-acquire.1000066400000000000000000000070421322317423600213430ustar00rootroot00000000000000'\" t .\" Title: nvme-resv-acquire .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-RESV\-ACQUIRE" "1" "12/10/2017" "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-resv-acquire \- Acquire an nvme reservation .SH "SYNOPSIS" .sp .nf \fInvme resv\-acquire\fR .fi .SH "DESCRIPTION" .sp The Reservation Acquire command is used to acquire a reservation on a namespace, preempt a reservation held on a namespace, and abort a reservation held on a namespace\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Override the nsid field\&. If using the admin character device, this parameter is required\&. .RE .PP \-c , \-\-crkey= .RS 4 Current Reservation Key: The field specifies the current reservation key associated with the host\&. If the IEKEY bit is set to \(oq1\(cq in the command, then the CRKEY check succeeds regardless of the value in this field\&. .RE .PP \-p , \-\-prkey= .RS 4 Preempt Reservation Key: If the Reservation Acquire Action is set to 001b (i\&.e\&., Preempt) or 010b (i\&.e\&., Preempt and Abort), then this field specifies the reservation key to be unregistered from the namespace\&. For all other Reservation Acquire Action values, this field is reserved\&. .RE .PP \-t , \-\-rtyep= .RS 4 Reservation Type: This field specifies the type of reservation to be created\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0h T}:T{ Reserved T} T{ 1h T}:T{ Write Exclusive Reservation T} T{ 2h T}:T{ Exclusive Access Reservation T} T{ 3h T}:T{ Write Exclusive \- Registrants Only Reservation T} T{ 4h T}:T{ Exclusive Access \- Registrants Only Reservation T} T{ 5h T}:T{ Write Exclusive \- All Registrants Reservation T} T{ 6h T}:T{ Exclusive Access \- All Registrants Reservation T} T{ 07h\-FFh T}:T{ Reserved T} .TE .sp 1 .RE .PP \-a , \-\-racqa= .RS 4 Reservation Acquire Action: This field specifies the action that is performed by the command\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0 T}:T{ Acquire T} T{ 1 T}:T{ Preempt T} T{ 2 T}:T{ Preempt and Abort T} T{ 3\-7 T}:T{ Reserved T} .TE .sp 1 .RE .PP \-i, \-\-iekey .RS 4 Ignore Existing Key: If this bit is set to a \fI1\fR, then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value\&. .sp Indicator option, defaults to \fI0\fR\&. .RE .SH "EXAMPLES" .sp No examples yet .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-resv-acquire.html000066400000000000000000000530001322317423600221420ustar00rootroot00000000000000 nvme-resv-acquire(1)

SYNOPSIS

nvme resv-acquire <device>

DESCRIPTION

The Reservation Acquire command is used to acquire a reservation on a namespace, preempt a reservation held on a namespace, and abort a reservation held on a namespace.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Override the nsid field. If using the admin character device, this parameter is required.

-c <crkey>
--crkey=<crkey>

Current Reservation Key: The field specifies the current reservation key associated with the host. If the IEKEY bit is set to ‘1’ in the command, then the CRKEY check succeeds regardless of the value in this field.

-p <prkey>
--prkey=<prkey>

Preempt Reservation Key: If the Reservation Acquire Action is set to 001b (i.e., Preempt) or 010b (i.e., Preempt and Abort), then this field specifies the reservation key to be unregistered from the namespace. For all other Reservation Acquire Action values, this field is reserved.

-t <rtype>
--rtyep=<rtype>

Reservation Type: This field specifies the type of reservation to be created.

Value

Definition

0h

Reserved

1h

Write Exclusive Reservation

2h

Exclusive Access Reservation

3h

Write Exclusive - Registrants Only Reservation

4h

Exclusive Access - Registrants Only Reservation

5h

Write Exclusive - All Registrants Reservation

6h

Exclusive Access - All Registrants Reservation

07h-FFh

Reserved

-a <racqa>
--racqa=<racqa>

Reservation Acquire Action: This field specifies the action that is performed by the command.

Value

Definition

0

Acquire

1

Preempt

2

Preempt and Abort

3-7

Reserved

-i
--iekey

Ignore Existing Key: If this bit is set to a 1, then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value.

Indicator option, defaults to 0.

EXAMPLES

No examples yet

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-resv-acquire.txt000066400000000000000000000040621322317423600220210ustar00rootroot00000000000000nvme-resv-acquire(1) ==================== NAME ---- nvme-resv-acquire - Acquire an nvme reservation SYNOPSIS -------- [verse] 'nvme resv-acquire' DESCRIPTION ----------- The Reservation Acquire command is used to acquire a reservation on a namespace, preempt a reservation held on a namespace, and abort a reservation held on a namespace. OPTIONS ------- -n :: --namespace-id=:: Override the nsid field. If using the admin character device, this parameter is required. -c :: --crkey=:: Current Reservation Key: The field specifies the current reservation key associated with the host. If the IEKEY bit is set to ‘1’ in the command, then the CRKEY check succeeds regardless of the value in this field. -p :: --prkey=:: Preempt Reservation Key: If the Reservation Acquire Action is set to 001b (i.e., Preempt) or 010b (i.e., Preempt and Abort), then this field specifies the reservation key to be unregistered from the namespace. For all other Reservation Acquire Action values, this field is reserved. -t :: --rtyep=:: Reservation Type: This field specifies the type of reservation to be created. + [] |================= |Value|Definition |0h|Reserved |1h|Write Exclusive Reservation |2h|Exclusive Access Reservation |3h|Write Exclusive - Registrants Only Reservation |4h|Exclusive Access - Registrants Only Reservation |5h|Write Exclusive - All Registrants Reservation |6h|Exclusive Access - All Registrants Reservation |07h-FFh|Reserved |================= -a :: --racqa=:: Reservation Acquire Action: This field specifies the action that is performed by the command. + [] |================= |Value|Definition |0|Acquire |1|Preempt |2|Preempt and Abort |3-7|Reserved |================= -i:: --iekey:: Ignore Existing Key: If this bit is set to a '1', then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value. + Indicator option, defaults to '0'. EXAMPLES -------- No examples yet NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-resv-register.1000066400000000000000000000073021322317423600215350ustar00rootroot00000000000000'\" t .\" Title: nvme-resv-register .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-RESV\-REGISTER" "1" "12/10/2017" "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-resv-register \- Register an nvme reservation .SH "SYNOPSIS" .sp .nf \fInvme resv\-register\fR .fi .SH "DESCRIPTION" .sp The Reservation Register command is used to register, unregister, or replace a reservation key\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Override the nsid field\&. If using the admin character device, this parameter is required\&. .RE .PP \-c , \-\-crkey= .RS 4 Current Reservation Key: If the Reservation Register Action is 001b (i\&.e\&., Unregister Reservation Key) or 010b (i\&.e\&., Replace Reservation Key), then this field contains the current reservation key associated with the host\&. For all other Reservation Register Action values, this field is reserved\&. The controller ignores the value of this field when the Ignore Existing Key (IEKEY) bit is set to \(oq1\(cq\&. .RE .PP \-k , \-\-nrkey= .RS 4 New Reservation Key: If the Reservation Register Action is 000b (i\&.e\&., Register Reservation Key) or 010b (i\&.e\&., Replace Reservation Key), then this field contains the new reservation key associated with the host\&. For all other Reservation Register Action values, this field is reserved\&. .RE .PP \-p , \-\-cptpl= .RS 4 Change Persist Through Power Loss State: This field allows the Persist Through Power Loss state associated with the namespace to be modified as a side effect of processing this command\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0 T}:T{ No change to PTPL state T} T{ 1 T}:T{ Reserved T} T{ 2 T}:T{ Set PTPL state to \(oq0\(cq\&. Reservations are released and registrants are cleared on a power on\&. T} T{ 3 T}:T{ Set PTPL state to \(oq1\(cq\&. Reservations and registrants persist across a power loss\&. T} .TE .sp 1 .RE .PP \-a , \-\-rrega= .RS 4 Reservation Register Action: This field specifies the registration action that is performed by the command\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0 T}:T{ Register Reservation Key T} T{ 1 T}:T{ Unregister Reservation Key T} T{ 2 T}:T{ Replace Reservation Key T} T{ 3\-7 T}:T{ Reserved T} .TE .sp 1 .RE .PP \-i, \-\-iekey .RS 4 Ignore Existing Key: If this bit is set to a \fI1\fR, then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value\&. .sp Indicator option, defaults to \fI0\fR\&. .RE .SH "EXAMPLES" .sp No examples yet .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-resv-register.html000066400000000000000000000523771322317423600223550ustar00rootroot00000000000000 nvme-resv-register(1)

SYNOPSIS

nvme resv-register <device>

DESCRIPTION

The Reservation Register command is used to register, unregister, or replace a reservation key.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Override the nsid field. If using the admin character device, this parameter is required.

-c <crkey>
--crkey=<crkey>

Current Reservation Key: If the Reservation Register Action is 001b (i.e., Unregister Reservation Key) or 010b (i.e., Replace Reservation Key), then this field contains the current reservation key associated with the host. For all other Reservation Register Action values, this field is reserved. The controller ignores the value of this field when the Ignore Existing Key (IEKEY) bit is set to ‘1’.

-k <nrkey>
--nrkey=<nrkey>

New Reservation Key: If the Reservation Register Action is 000b (i.e., Register Reservation Key) or 010b (i.e., Replace Reservation Key), then this field contains the new reservation key associated with the host. For all other Reservation Register Action values, this field is reserved.

-p <cptpl>
--cptpl=<cptpl>

Change Persist Through Power Loss State: This field allows the Persist Through Power Loss state associated with the namespace to be modified as a side effect of processing this command.

Value

Definition

0

No change to PTPL state

1

Reserved

2

Set PTPL state to ‘0’. Reservations are released and registrants are cleared on a power on.

3

Set PTPL state to ‘1’. Reservations and registrants persist across a power loss.

-a <rrega>
--rrega=<rrega>

Reservation Register Action: This field specifies the registration action that is performed by the command.

Value

Definition

0

Register Reservation Key

1

Unregister Reservation Key

2

Replace Reservation Key

3-7

Reserved

-i
--iekey

Ignore Existing Key: If this bit is set to a 1, then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value.

Indicator option, defaults to 0.

EXAMPLES

No examples yet

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-resv-register.txt000066400000000000000000000044071322317423600222170ustar00rootroot00000000000000nvme-resv-register(1) ===================== NAME ---- nvme-resv-register - Register an nvme reservation SYNOPSIS -------- [verse] 'nvme resv-register' DESCRIPTION ----------- The Reservation Register command is used to register, unregister, or replace a reservation key. OPTIONS ------- -n :: --namespace-id=:: Override the nsid field. If using the admin character device, this parameter is required. -c :: --crkey=:: Current Reservation Key: If the Reservation Register Action is 001b (i.e., Unregister Reservation Key) or 010b (i.e., Replace Reservation Key), then this field contains the current reservation key associated with the host. For all other Reservation Register Action values, this field is reserved. The controller ignores the value of this field when the Ignore Existing Key (IEKEY) bit is set to ‘1’. -k :: --nrkey=:: New Reservation Key: If the Reservation Register Action is 000b (i.e., Register Reservation Key) or 010b (i.e., Replace Reservation Key), then this field contains the new reservation key associated with the host. For all other Reservation Register Action values, this field is reserved. -p :: --cptpl=:: Change Persist Through Power Loss State: This field allows the Persist Through Power Loss state associated with the namespace to be modified as a side effect of processing this command. + [] |================= |Value|Definition |0|No change to PTPL state |1|Reserved |2|Set PTPL state to ‘0’. Reservations are released and registrants are cleared on a power on. |3|Set PTPL state to ‘1’. Reservations and registrants persist across a power loss. |================= -a :: --rrega=:: Reservation Register Action: This field specifies the registration action that is performed by the command. + [] |================= |Value|Definition |0|Register Reservation Key |1|Unregister Reservation Key |2|Replace Reservation Key |3-7|Reserved |================= -i:: --iekey:: Ignore Existing Key: If this bit is set to a '1', then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value. + Indicator option, defaults to '0'. EXAMPLES -------- No examples yet NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-resv-release.1000066400000000000000000000064541322317423600213400ustar00rootroot00000000000000'\" t .\" Title: nvme-resv-release .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-RESV\-RELEASE" "1" "12/10/2017" "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-resv-release \- Release an nvme reservation .SH "SYNOPSIS" .sp .nf \fInvme resv\-release\fR .fi .SH "DESCRIPTION" .sp The Reservation Release command is used to release or clear a reservation held on a namespace\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Override the nsid field\&. If using the admin character device, this parameter is required\&. .RE .PP \-c , \-\-crkey= .RS 4 Current Reservation Key: If the Reservation Register Action is 001b (i\&.e\&., Unregister Reservation Key) or 010b (i\&.e\&., Replace Reservation Key), then this field contains the current reservation key associated with the host\&. For all other Reservation Register Action values, this field is reserved\&. The controller ignores the value of this field when the Ignore Existing Key (IEKEY) bit is set to \(oq1\(cq\&. .RE .PP \-t , \-\-rtyep= .RS 4 Reservation Type: This field specifies the type of reservation to be created\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0h T}:T{ Reserved T} T{ 1h T}:T{ Write Exclusive Reservation T} T{ 2h T}:T{ Exclusive Access Reservation T} T{ 3h T}:T{ Write Exclusive \- Registrants Only Reservation T} T{ 4h T}:T{ Exclusive Access \- Registrants Only Reservation T} T{ 5h T}:T{ Write Exclusive \- All Registrants Reservation T} T{ 6h T}:T{ Exclusive Access \- All Registrants Reservation T} T{ 07h\-FFh T}:T{ Reserved T} .TE .sp 1 .RE .PP \-a , \-\-rrela= .RS 4 Reservation Release Action: This field specifies the registration action that is performed by the command\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt. T{ Value T}:T{ Definition T} T{ 0 T}:T{ Release T} T{ 1 T}:T{ Clear T} T{ 2\-7 T}:T{ Reserved T} .TE .sp 1 .RE .PP \-i, \-\-iekey .RS 4 Ignore Existing Key: If this bit is set to a \fI1\fR, then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value\&. .sp Indicator option, defaults to \fI0\fR\&. .RE .SH "EXAMPLES" .sp No examples yet .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-resv-release.html000066400000000000000000000520751322317423600221440ustar00rootroot00000000000000 nvme-resv-release(1)

SYNOPSIS

nvme resv-release <device>

DESCRIPTION

The Reservation Release command is used to release or clear a reservation held on a namespace.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Override the nsid field. If using the admin character device, this parameter is required.

-c <crkey>
--crkey=<crkey>

Current Reservation Key: If the Reservation Register Action is 001b (i.e., Unregister Reservation Key) or 010b (i.e., Replace Reservation Key), then this field contains the current reservation key associated with the host. For all other Reservation Register Action values, this field is reserved. The controller ignores the value of this field when the Ignore Existing Key (IEKEY) bit is set to ‘1’.

-t <rtype>
--rtyep=<rtype>

Reservation Type: This field specifies the type of reservation to be created.

Value

Definition

0h

Reserved

1h

Write Exclusive Reservation

2h

Exclusive Access Reservation

3h

Write Exclusive - Registrants Only Reservation

4h

Exclusive Access - Registrants Only Reservation

5h

Write Exclusive - All Registrants Reservation

6h

Exclusive Access - All Registrants Reservation

07h-FFh

Reserved

-a <rrela>
--rrela=<rrela>

Reservation Release Action: This field specifies the registration action that is performed by the command.

Value

Definition

0

Release

1

Clear

2-7

Reserved

-i
--iekey

Ignore Existing Key: If this bit is set to a 1, then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value.

Indicator option, defaults to 0.

EXAMPLES

No examples yet

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-resv-release.txt000066400000000000000000000035311322317423600220100ustar00rootroot00000000000000nvme-resv-release(1) ==================== NAME ---- nvme-resv-release - Release an nvme reservation SYNOPSIS -------- [verse] 'nvme resv-release' DESCRIPTION ----------- The Reservation Release command is used to release or clear a reservation held on a namespace. OPTIONS ------- -n :: --namespace-id=:: Override the nsid field. If using the admin character device, this parameter is required. -c :: --crkey=:: Current Reservation Key: If the Reservation Register Action is 001b (i.e., Unregister Reservation Key) or 010b (i.e., Replace Reservation Key), then this field contains the current reservation key associated with the host. For all other Reservation Register Action values, this field is reserved. The controller ignores the value of this field when the Ignore Existing Key (IEKEY) bit is set to ‘1’. -t :: --rtyep=:: Reservation Type: This field specifies the type of reservation to be created. + [] |================= |Value|Definition |0h|Reserved |1h|Write Exclusive Reservation |2h|Exclusive Access Reservation |3h|Write Exclusive - Registrants Only Reservation |4h|Exclusive Access - Registrants Only Reservation |5h|Write Exclusive - All Registrants Reservation |6h|Exclusive Access - All Registrants Reservation |07h-FFh|Reserved |================= -a :: --rrela=:: Reservation Release Action: This field specifies the registration action that is performed by the command. + [] |================= |Value|Definition |0|Release |1|Clear |2-7|Reserved |================= -i:: --iekey:: Ignore Existing Key: If this bit is set to a '1', then the Current Reservation Key (CRKEY) check is disabled and the command shall succeed regardless of the CRKEY field value. + Indicator option, defaults to '0'. EXAMPLES -------- No examples yet NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-resv-report.1000066400000000000000000000056041322317423600212270ustar00rootroot00000000000000'\" t .\" Title: nvme-resv-report .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-RESV\-REPORT" "1" "12/10/2017" "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-resv-report \- Send NVMe Reservation Report, parse the result .SH "SYNOPSIS" .sp .nf \fInvme resv\-report\fR [\-\-namespace\-id= | \-n ] [\-\-numd= | \-d ] [\-b | \-\-raw\-binary] [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp The Reservation Report command returns a Reservation Status data structure to host memory that describes the registration and reservation status of a namespace\&. .sp The size of the Reservation Status data structure is a function of the number of controllers in the NVM Subsystem that are associated with hosts that are registrants of the namespace (i\&.e\&., there is a Registered Controller data structure for each such controller)\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the reservation report structure for the given nsid\&. This is required for the character devices, or overrides the block nsid if given\&. .RE .PP \-d , \-\-numd= .RS 4 Specify the number of Dwords of the Reservation Status structure to transfer\&. Defaults to 4k\&. .RE .PP \-c , \-\-cdw11= .RS 4 The value for command dword 11\&. Setting bit 0 specifies that the controller returns the Extended Data Structure\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-resv-report.html000066400000000000000000000457141322317423600220410ustar00rootroot00000000000000 nvme-resv-report(1)

SYNOPSIS

nvme resv-report <device> [--namespace-id=<nsid> | -n <nsid>]
                        [--numd=<num-dwords> | -d <num-dwords>]
                        [-b | --raw-binary]
                        [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

The Reservation Report command returns a Reservation Status data structure to host memory that describes the registration and reservation status of a namespace.

The size of the Reservation Status data structure is a function of the number of controllers in the NVM Subsystem that are associated with hosts that are registrants of the namespace (i.e., there is a Registered Controller data structure for each such controller).

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the reservation report structure for the given nsid. This is required for the character devices, or overrides the block nsid if given.

-d <num-dwords>
--numd=<num-dwords>

Specify the number of Dwords of the Reservation Status structure to transfer. Defaults to 4k.

-c <cdw11>
--cdw11=<cdw11>

The value for command dword 11. Setting bit 0 specifies that the controller returns the Extended Data Structure.

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program.

-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

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-resv-report.txt000066400000000000000000000030671322317423600217070ustar00rootroot00000000000000nvme-resv-report(1) =================== NAME ---- nvme-resv-report - Send NVMe Reservation Report, parse the result SYNOPSIS -------- [verse] 'nvme resv-report' [--namespace-id= | -n ] [--numd= | -d ] [-b | --raw-binary] [-o | --output-format=] DESCRIPTION ----------- The Reservation Report command returns a Reservation Status data structure to host memory that describes the registration and reservation status of a namespace. The size of the Reservation Status data structure is a function of the number of controllers in the NVM Subsystem that are associated with hosts that are registrants of the namespace (i.e., there is a Registered Controller data structure for each such controller). OPTIONS ------- -n :: --namespace-id=:: Retrieve the reservation report structure for the given nsid. This is required for the character devices, or overrides the block nsid if given. -d :: --numd=:: Specify the number of Dwords of the Reservation Status structure to transfer. Defaults to 4k. -c :: --cdw11=:: The value for command dword 11. Setting bit 0 specifies that the controller returns the Extended Data Structure. -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-sanitize-log.1000066400000000000000000000056201322317423600213420ustar00rootroot00000000000000'\" t .\" Title: nvme-sanitize-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SANITIZE\-LOG" "1" "12/10/2017" "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-sanitize-log \- Send NVMe sanitize\-log Command, return result .SH "SYNOPSIS" .sp .nf \fInvme sanitize\-log\fR .fi .SH "DESCRIPTION" .sp Retrieves the NVMe Sanitize log page from an NVMe device and provides the status of sanitize command\&. .sp The parameter is mandatory NVMe character device (ex: /dev/nvme0)\&. .sp Expected status and description :\- .TS allbox tab(:); ltB ltB. T{ Status Code T}:T{ Description T} .T& lt lt lt lt lt lt lt lt lt lt. T{ .sp 0x0000 T}:T{ .sp NVM subsystem has never been sanitized\&. T} T{ .sp 0x0001 T}:T{ .sp The most recent sanitize operation completed successfully\&. T} T{ .sp 0x0002 T}:T{ .sp A sanitize operation is currently in progress\&. T} T{ .sp 0x0003 T}:T{ .sp The most recent sanitize operation failed\&. T} T{ .sp 0x0100 T}:T{ .sp Global Data Erased bit If set to 1 then non\-volatile storage in the NVM subsystem has not been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation\&. If cleared to 0, then non\-volatile storage in the NVM subsystem has been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation of the NVM subsystem\&. T} .TE .sp 1 .sp Sanitize Progress \- percentage complete .sp On success it returns 0, error code otherwise\&. .SH "OPTIONS" .sp No options yet\&. .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program issue Sanitize\-log Command : .sp .if n \{\ .RS 4 .\} .nf # nvme sanitize\-log /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite\&. nvme-cli-1.5/Documentation/nvme-sanitize-log.html000066400000000000000000000450331322317423600221500ustar00rootroot00000000000000 nvme-sanitize-log(1)

SYNOPSIS

nvme sanitize-log <device>

DESCRIPTION

Retrieves the NVMe Sanitize log page from an NVMe device and provides the status of sanitize command.

The <device> parameter is mandatory NVMe character device (ex: /dev/nvme0).

Expected status and description :-

Status Code Description

0x0000

NVM subsystem has never been sanitized.

0x0001

The most recent sanitize operation completed successfully.

0x0002

A sanitize operation is currently in progress.

0x0003

The most recent sanitize operation failed.

0x0100

Global Data Erased bit If set to 1 then non-volatile storage in the NVM subsystem has not been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation. If cleared to 0, then non-volatile storage in the NVM subsystem has been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation of the NVM subsystem.

Sanitize Progress - percentage complete

On success it returns 0, error code otherwise.

OPTIONS

No options yet.

EXAMPLES

  • Has the program issue Sanitize-log Command :

    # nvme sanitize-log /dev/nvme0

NVME

Part of the nvme-user suite.


nvme-cli-1.5/Documentation/nvme-sanitize-log.txt000066400000000000000000000027431322317423600220240ustar00rootroot00000000000000nvme-sanitize-log(1) ==================== NAME ---- nvme-sanitize-log - Send NVMe sanitize-log Command, return result SYNOPSIS -------- [verse] 'nvme sanitize-log' DESCRIPTION ----------- Retrieves the NVMe Sanitize log page from an NVMe device and provides the status of sanitize command. The parameter is mandatory NVMe character device (ex: /dev/nvme0). Expected status and description :- [cols="2*", options="header"] |=== |Status Code |Description |0x0000 |NVM subsystem has never been sanitized. |0x0001 |The most recent sanitize operation completed successfully. |0x0002 |A sanitize operation is currently in progress. |0x0003 |The most recent sanitize operation failed. |0x0100 |Global Data Erased bit If set to 1 then non-volatile storage in the NVM subsystem has not been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation. If cleared to 0, then non-volatile storage in the NVM subsystem has been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation of the NVM subsystem. |=== Sanitize Progress - percentage complete On success it returns 0, error code otherwise. OPTIONS ------- No options yet. EXAMPLES -------- * Has the program issue Sanitize-log Command : + ------------ # nvme sanitize-log /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite. nvme-cli-1.5/Documentation/nvme-sanitize.1000066400000000000000000000102611322317423600205600ustar00rootroot00000000000000'\" t .\" Title: nvme-sanitize .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SANITIZE" "1" "12/10/2017" "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-sanitize \- Send NVMe Sanitize Command, return result .SH "SYNOPSIS" .sp .nf \fInvme sanitize\fR [\-\-no\-dealloc | \-d] [\-\-oipbp | \-i] [\-\-owpass= | \-n ] [\-\-ause | \-u] [\-\-sanact= | \-a ] [\-\-ovrpat= | \-p ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends a Sanitize command and provides the result\&. .sp The parameter is mandatory NVMe character device (ex: /dev/nvme0)\&. .sp On success it returns 0, error code otherwise\&. .SH "OPTIONS" .PP \-d, \-\-no\-delloc .RS 4 No Deallocate After Sanitize: If set, then the controller shall not deallocate any logical blocks as a result of successfully completing the sanitize operation\&. If cleared, then the controller should deallocate logical blocks as a result of successfully completing the sanitize operation\&. This bit shall be ignored if the Sanitize Action field is set to 001b (i\&.e\&., Exit Failure Mode)\&. .RE .PP \-i, \-\-oipbp .RS 4 Overwrite Invert Pattern Between Passes: If set, then the Overwrite Pattern shall be inverted between passes\&. If cleared, then the overwrite pattern shall not be inverted between passes\&. This bit shall be ignored unless the Sanitize Action field is set to 011b (i\&.e\&., Overwrite)\&. .RE .PP \-n , \-\-owpass= .RS 4 Overwrite Pass Count: This field specifies the number of overwrite passes (i\&.e\&., how many times the media is to be overwritten) using the data from the Overwrite Pattern field of this command\&. A value of 0 specifies 16 overwrite passes\&. This field shall be ignored unless the Sanitize Action field is set to 011b (i\&.e\&., Overwrite)\&. .RE .PP \-u, \-\-ause .RS 4 Allow Unrestricted Sanitize Exit: If set, then the sanitize operation is performed in unrestricted completion mode\&. If cleared then the sanitize operation is performed in restricted completion mode\&. This bit shall be ignored if the Sanitize Action field is set to 001b (i\&.e\&., Exit Failure Mode)\&. .RE .PP \-a , \-\-sanact= .RS 4 Sanitize Action: 000b \- Reserved 001b \- Exit Failure Mode 010b \- Start a Block Erase sanitize operation 011b \- Start an Overwrite sanitize operation 100b \- Start a Crypto Erase sanitize operation .RE .PP \-p , \-\-ovrpat= .RS 4 Overwrite Pattern: This field is ignored unless the Sanitize Action field in Command Dword 10 is set to 011b (i\&.e\&., Overwrite)\&. This field specifies a 32\-bit pattern that is used for the Overwrite sanitize operation\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program issue Sanitize Command : .sp .if n \{\ .RS 4 .\} .nf # nvme sanitize /dev/nvme0n1 \-a 0x02 # nvme sanitize /dev/nvme0n1 \-\-sanact=0x01 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite\&. nvme-cli-1.5/Documentation/nvme-sanitize.html000066400000000000000000000470101322317423600213660ustar00rootroot00000000000000 nvme-sanitize(1)

SYNOPSIS

nvme sanitize <device> [--no-dealloc | -d]
              [--oipbp | -i]
              [--owpass=<overwrite-pass-count> | -n <overwrite-pass-count>]
              [--ause | -u]
              [--sanact=<action> | -a <action>]
              [--ovrpat=<overwrite-pattern> | -p <overwrite-pattern>]

DESCRIPTION

For the NVMe device given, sends a Sanitize command and provides the result.

The <device> parameter is mandatory NVMe character device (ex: /dev/nvme0).

On success it returns 0, error code otherwise.

OPTIONS

-d
--no-delloc

No Deallocate After Sanitize: If set, then the controller shall not deallocate any logical blocks as a result of successfully completing the sanitize operation. If cleared, then the controller should deallocate logical blocks as a result of successfully completing the sanitize operation. This bit shall be ignored if the Sanitize Action field is set to 001b (i.e., Exit Failure Mode).

-i
--oipbp

Overwrite Invert Pattern Between Passes: If set, then the Overwrite Pattern shall be inverted between passes. If cleared, then the overwrite pattern shall not be inverted between passes. This bit shall be ignored unless the Sanitize Action field is set to 011b (i.e., Overwrite).

-n <overwrite-pass-count>
--owpass=<overwrite-pass-count>

Overwrite Pass Count: This field specifies the number of overwrite passes (i.e., how many times the media is to be overwritten) using the data from the Overwrite Pattern field of this command. A value of 0 specifies 16 overwrite passes. This field shall be ignored unless the Sanitize Action field is set to 011b (i.e., Overwrite).

-u
--ause

Allow Unrestricted Sanitize Exit: If set, then the sanitize operation is performed in unrestricted completion mode. If cleared then the sanitize operation is performed in restricted completion mode. This bit shall be ignored if the Sanitize Action field is set to 001b (i.e., Exit Failure Mode).

-a <action>
--sanact=<action>

Sanitize Action: 000b - Reserved 001b - Exit Failure Mode 010b - Start a Block Erase sanitize operation 011b - Start an Overwrite sanitize operation 100b - Start a Crypto Erase sanitize operation

-p <overwrite-pattern>
--ovrpat=<overwrite-pattern>

Overwrite Pattern: This field is ignored unless the Sanitize Action field in Command Dword 10 is set to 011b (i.e., Overwrite). This field specifies a 32-bit pattern that is used for the Overwrite sanitize operation.

EXAMPLES

  • Has the program issue Sanitize Command :

    # nvme sanitize /dev/nvme0n1 -a 0x02
    # nvme sanitize /dev/nvme0n1 --sanact=0x01

NVME

Part of the nvme-user suite.


nvme-cli-1.5/Documentation/nvme-sanitize.txt000066400000000000000000000055621322317423600212470ustar00rootroot00000000000000nvme-sanitize(1) ================ NAME ---- nvme-sanitize - Send NVMe Sanitize Command, return result SYNOPSIS -------- [verse] 'nvme sanitize' [--no-dealloc | -d] [--oipbp | -i] [--owpass= | -n ] [--ause | -u] [--sanact= | -a ] [--ovrpat= | -p ] DESCRIPTION ----------- For the NVMe device given, sends a Sanitize command and provides the result. The parameter is mandatory NVMe character device (ex: /dev/nvme0). On success it returns 0, error code otherwise. OPTIONS ------- -d:: --no-delloc:: No Deallocate After Sanitize: If set, then the controller shall not deallocate any logical blocks as a result of successfully completing the sanitize operation. If cleared, then the controller should deallocate logical blocks as a result of successfully completing the sanitize operation. This bit shall be ignored if the Sanitize Action field is set to 001b (i.e., Exit Failure Mode). -i:: --oipbp:: Overwrite Invert Pattern Between Passes: If set, then the Overwrite Pattern shall be inverted between passes. If cleared, then the overwrite pattern shall not be inverted between passes. This bit shall be ignored unless the Sanitize Action field is set to 011b (i.e., Overwrite). -n :: --owpass=:: Overwrite Pass Count: This field specifies the number of overwrite passes (i.e., how many times the media is to be overwritten) using the data from the Overwrite Pattern field of this command. A value of 0 specifies 16 overwrite passes. This field shall be ignored unless the Sanitize Action field is set to 011b (i.e., Overwrite). -u:: --ause:: Allow Unrestricted Sanitize Exit: If set, then the sanitize operation is performed in unrestricted completion mode. If cleared then the sanitize operation is performed in restricted completion mode. This bit shall be ignored if the Sanitize Action field is set to 001b (i.e., Exit Failure Mode). -a :: --sanact=:: Sanitize Action: 000b - Reserved 001b - Exit Failure Mode 010b - Start a Block Erase sanitize operation 011b - Start an Overwrite sanitize operation 100b - Start a Crypto Erase sanitize operation -p :: --ovrpat=:: Overwrite Pattern: This field is ignored unless the Sanitize Action field in Command Dword 10 is set to 011b (i.e., Overwrite). This field specifies a 32-bit pattern that is used for the Overwrite sanitize operation. EXAMPLES -------- * Has the program issue Sanitize Command : + ------------ # nvme sanitize /dev/nvme0n1 -a 0x02 # nvme sanitize /dev/nvme0n1 --sanact=0x01 ------------ NVME ---- Part of the nvme-user suite. nvme-cli-1.5/Documentation/nvme-security-recv.1000066400000000000000000000073471322317423600215510ustar00rootroot00000000000000'\" t .\" Title: nvme-security-recv .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SECURITY\-RECV" "1" "12/10/2017" "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-security-recv \- Security Recv command .SH "SYNOPSIS" .sp .nf \fInvme security\-recv\fR [] [\-\-size= | \-x ] [\-\-secp= | \-p ] [\-\-spsp= | \-s ] [\-\-nssf= | \-N ] [\-\-tl= | \-t ] [\-\-namespace\-id= | \-n ] [\-b | \-\-raw\-binary] .fi .SH "DESCRIPTION" .sp The Security Receive command transfers the status and data result of one or more Security Send commands that were previously submitted to the controller\&. .sp The association between a Security Receive command and previous Security Send commands is dependent on the Security Protocol\&. The format of the data to be transferred is dependent on the Security Protocol\&. Refer to SPC\-4 for Security Protocol details\&. .sp Each Security Receive command returns the appropriate data corresponding to a Security Send command as defined by the rules of the Security Protocol\&. The Security Receive command data may not be retained if there is a loss of communication between the controller and host, or if a controller reset occurs\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Target a specific namespace for this security command\&. .RE .PP \-N , \-\-nssf= .RS 4 NVMe Security Specific field\&. If using security protocol EAh assigned for NVMe use, the NVMe security specific field indicates which reply memory buffer target\&. .RE .PP \-x , \-\-size= .RS 4 Size of buffer to allocate\&. One success it will be printed to STDOUT\&. .RE .PP \-p , \-\-secp= .RS 4 Security Protocol: This field specifies the security protocol as defined in SPC\-4\&. The controller shall fail the command with Invalid Parameter indicated if a reserved value of the Security Protocol is specified\&. .RE .PP \-s , \-\-spsp= .RS 4 SP Specific: The value of this field is specific to the Security Protocol as defined in SPC\-4\&. .RE .PP \-a , \-\-al= .RS 4 Allocation Length: The value of this field is specific to the Security Protocol as defined in SPC\-4\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Defaults to print in hex\&. .RE .SH "EXAMPLES" .sp No Examples .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-security-recv.html000066400000000000000000000500131322317423600223410ustar00rootroot00000000000000 nvme-security-recv(1)

SYNOPSIS

nvme security-recv [<device>] [--size=<size> | -x <size>]
                    [--secp=<security-protocol> | -p <security-protocol>]
                    [--spsp=<protocol-specific> | -s <protocol-specific>]
                    [--nssf=<nvme-specific> | -N <nvme-specific>]
                    [--tl=<transfer-length> | -t <transfer-length>]
                    [--namespace-id=<nsid> | -n <nsid>]
                    [-b | --raw-binary]

DESCRIPTION

The Security Receive command transfers the status and data result of one or more Security Send commands that were previously submitted to the controller.

The association between a Security Receive command and previous Security Send commands is dependent on the Security Protocol. The format of the data to be transferred is dependent on the Security Protocol. Refer to SPC-4 for Security Protocol details.

Each Security Receive command returns the appropriate data corresponding to a Security Send command as defined by the rules of the Security Protocol. The Security Receive command data may not be retained if there is a loss of communication between the controller and host, or if a controller reset occurs.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Target a specific namespace for this security command.

-N <nssf>
--nssf=<nssf>

NVMe Security Specific field. If using security protocol EAh assigned for NVMe use, the NVMe security specific field indicates which reply memory buffer target.

-x <size>
--size=<size>

Size of buffer to allocate. One success it will be printed to STDOUT.

-p <security-protocol>
--secp=<security-protocol>

Security Protocol: This field specifies the security protocol as defined in SPC-4. The controller shall fail the command with Invalid Parameter indicated if a reserved value of the Security Protocol is specified.

-s <security-protocol-specific>
--spsp=<security-protocol-specific>

SP Specific: The value of this field is specific to the Security Protocol as defined in SPC-4.

-a <allocation-length>
--al=<allocation-length>

Allocation Length: The value of this field is specific to the Security Protocol as defined in SPC-4.

-b
--raw-binary

Print the raw buffer to stdout. Defaults to print in hex.

EXAMPLES

No Examples

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-security-recv.txt000066400000000000000000000045011322317423600222150ustar00rootroot00000000000000nvme-security-recv(1) ===================== NAME ---- nvme-security-recv - Security Recv command SYNOPSIS -------- [verse] 'nvme security-recv' [] [--size= | -x ] [--secp= | -p ] [--spsp= | -s ] [--nssf= | -N ] [--tl= | -t ] [--namespace-id= | -n ] [-b | --raw-binary] DESCRIPTION ----------- The Security Receive command transfers the status and data result of one or more Security Send commands that were previously submitted to the controller. The association between a Security Receive command and previous Security Send commands is dependent on the Security Protocol. The format of the data to be transferred is dependent on the Security Protocol. Refer to SPC-4 for Security Protocol details. Each Security Receive command returns the appropriate data corresponding to a Security Send command as defined by the rules of the Security Protocol. The Security Receive command data may not be retained if there is a loss of communication between the controller and host, or if a controller reset occurs. OPTIONS ------- -n :: --namespace-id=:: Target a specific namespace for this security command. -N :: --nssf=:: NVMe Security Specific field. If using security protocol EAh assigned for NVMe use, the NVMe security specific field indicates which reply memory buffer target. -x :: --size=:: Size of buffer to allocate. One success it will be printed to STDOUT. -p :: --secp=:: Security Protocol: This field specifies the security protocol as defined in SPC-4. The controller shall fail the command with Invalid Parameter indicated if a reserved value of the Security Protocol is specified. -s :: --spsp=:: SP Specific: The value of this field is specific to the Security Protocol as defined in SPC-4. -a :: --al=:: Allocation Length: The value of this field is specific to the Security Protocol as defined in SPC-4. -b:: --raw-binary:: Print the raw buffer to stdout. Defaults to print in hex. EXAMPLES -------- No Examples NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-security-send.1000066400000000000000000000070501322317423600215320ustar00rootroot00000000000000'\" t .\" Title: nvme-security-send .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SECURITY\-SEND" "1" "12/10/2017" "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-security-send \- Security Send command .SH "SYNOPSIS" .sp .nf \fInvme security\-send\fR [] [\-\-file= | \-f ] [\-\-secp= | \-p ] [\-\-spsp= | \-s ] [\-\-tl= | \-t ] [\-\-nssf= | \-N ] [\-\-namespace\-id= | \-n ] .fi .SH "DESCRIPTION" .sp The Security Send command is used to transfer security protocol data to the controller\&. The data structure transferred to the controller as part of this command contains security protocol specific commands to be performed by the controller\&. The data structure transferred may also contain data or parameters associated with the security protocol commands\&. Status and data that is to be returned to the host for the security protocol commands submitted by a Security Send command are retrieved with the Security Receive command\&. .sp The association between a Security Send command and subsequent Security Receive command is Security Protocol field dependent as defined in SPC\-4\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Target a specific namespace for this security command\&. .RE .PP \-N , \-\-nssf= .RS 4 NVMe Security Specific field\&. If using security protocol EAh assigned for NVMe use, the NVMe security specific field indicates which reply memory buffer target\&. .RE .PP \-f , \-\-file= .RS 4 Path to file used as the security protocol\(cqs payload\&. Required argument\&. .RE .PP \-p , \-\-secp= .RS 4 Security Protocol: This field specifies the security protocol as defined in SPC\-4\&. The controller shall fail the command with Invalid Parameter indicated if a reserved value of the Security Protocol is specified\&. .RE .PP \-s , \-\-spsp= .RS 4 SP Specific: The value of this field is specific to the Security Protocol as defined in SPC\-4\&. .RE .PP \-t , \-\-tl= .RS 4 Transfer Length: The value of this field is specific to the Security Protocol as defined in SPC\-4\&. .RE .SH "EXAMPLES" .sp No Examples .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-security-send.html000066400000000000000000000473541322317423600223510ustar00rootroot00000000000000 nvme-security-send(1)

SYNOPSIS

nvme security-send [<device>] [--file=<file> | -f <file>]
                    [--secp=<security-protocol> | -p <security-protocol>]
                    [--spsp=<protocol-specific> | -s <protocol-specific>]
                    [--tl=<transfer-length> | -t <transfer-length>]
                    [--nssf=<nvme-specific> | -N <nvme-specific>]
                    [--namespace-id=<nsid> | -n <nsid>]

DESCRIPTION

The Security Send command is used to transfer security protocol data to the controller. The data structure transferred to the controller as part of this command contains security protocol specific commands to be performed by the controller. The data structure transferred may also contain data or parameters associated with the security protocol commands. Status and data that is to be returned to the host for the security protocol commands submitted by a Security Send command are retrieved with the Security Receive command.

The association between a Security Send command and subsequent Security Receive command is Security Protocol field dependent as defined in SPC-4.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Target a specific namespace for this security command.

-N <nssf>
--nssf=<nssf>

NVMe Security Specific field. If using security protocol EAh assigned for NVMe use, the NVMe security specific field indicates which reply memory buffer target.

-f <file>
--file=<file>

Path to file used as the security protocol’s payload. Required argument.

-p <security-protocol>
--secp=<security-protocol>

Security Protocol: This field specifies the security protocol as defined in SPC-4. The controller shall fail the command with Invalid Parameter indicated if a reserved value of the Security Protocol is specified.

-s <security-protocol-specific>
--spsp=<security-protocol-specific>

SP Specific: The value of this field is specific to the Security Protocol as defined in SPC-4.

-t <trans-length>
--tl=<trans-length>

Transfer Length: The value of this field is specific to the Security Protocol as defined in SPC-4.

EXAMPLES

No Examples

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-security-send.txt000066400000000000000000000042471322317423600222160ustar00rootroot00000000000000nvme-security-send(1) ===================== NAME ---- nvme-security-send - Security Send command SYNOPSIS -------- [verse] 'nvme security-send' [] [--file= | -f ] [--secp= | -p ] [--spsp= | -s ] [--tl= | -t ] [--nssf= | -N ] [--namespace-id= | -n ] DESCRIPTION ----------- The Security Send command is used to transfer security protocol data to the controller. The data structure transferred to the controller as part of this command contains security protocol specific commands to be performed by the controller. The data structure transferred may also contain data or parameters associated with the security protocol commands. Status and data that is to be returned to the host for the security protocol commands submitted by a Security Send command are retrieved with the Security Receive command. The association between a Security Send command and subsequent Security Receive command is Security Protocol field dependent as defined in SPC-4. OPTIONS ------- -n :: --namespace-id=:: Target a specific namespace for this security command. -N :: --nssf=:: NVMe Security Specific field. If using security protocol EAh assigned for NVMe use, the NVMe security specific field indicates which reply memory buffer target. -f :: --file=:: Path to file used as the security protocol's payload. Required argument. -p :: --secp=:: Security Protocol: This field specifies the security protocol as defined in SPC-4. The controller shall fail the command with Invalid Parameter indicated if a reserved value of the Security Protocol is specified. -s :: --spsp=:: SP Specific: The value of this field is specific to the Security Protocol as defined in SPC-4. -t :: --tl=:: Transfer Length: The value of this field is specific to the Security Protocol as defined in SPC-4. EXAMPLES -------- No Examples NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-set-feature.1000066400000000000000000000071271322317423600211650ustar00rootroot00000000000000'\" t .\" Title: nvme-set-feature .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SET\-FEATURE" "1" "12/10/2017" "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-set-feature \- Sets an NVMe feature, returns applicable results .SH "SYNOPSIS" .sp .nf \fInvme set\-feature\fR [\-\-namespace\-id= | \-n ] [\-\-feature\-id= | \-f ] [\-\-value= | \-v ] [\-\-data\-len= | \-l ] [\-\-data= | \-d ] [\-\-save| \-s] .fi .SH "DESCRIPTION" .sp Submits an NVMe Set Feature admin command and returns the applicable results\&. This may be the feature\(cqs value, or may also include a feature structure if the feature requires it (ex: LBA Range Type)\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the value sent to the device is displayed .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Sets the feature for the given nsid\&. This is optional and most features do not use this value\&. .RE .PP \-f , \-\-feature\-id= .RS 4 The feature id to send with the command\&. Value provided should be in hex\&. .RE .PP \-l , \-\-data\-len= .RS 4 The data length for the buffer submitted for this feature\&. Most known features do not use this value\&. The exceptions are LBA Range Type and host identifier\&. .RE .PP \-d , \-\-data= .RS 4 The data file for the buffer submitted for this feature\&. Most known features do not use this value\&. The exceptions is LBA Range Type and host identifier\&. This defaults to STDIN so files and echo can be piped\&. .RE .PP \-v , \-\-value= .RS 4 The value for command dword 11, the value you want to set the feature to\&. .RE .PP \-s, \-\-save .RS 4 Save the attribute so that it persists through all power states and resets\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Sets the Power State (PS) to 1 in feature id 2: .sp .if n \{\ .RS 4 .\} .nf # nvme set\-feature /dev/nvme0 \-f 2 /dev/nvme0n1 \-v 0x1 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Sets the host id to the ascii string\&. .sp .if n \{\ .RS 4 .\} .nf # echo "abcdefgh" | nvme set\-feature /dev/nvme0 \-f 0x81 \-l 8 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-set-feature.html000066400000000000000000000474061322317423600217750ustar00rootroot00000000000000 nvme-set-feature(1)

SYNOPSIS

nvme set-feature <device> [--namespace-id=<nsid> | -n <nsid>]
                          [--feature-id=<fid> | -f <fid>] [--value=<value> | -v <value>]
                          [--data-len=<data-len> | -l <data-len>]
                          [--data=<data-file> | -d <data-file>]
                          [--save| -s]

DESCRIPTION

Submits an NVMe Set Feature admin command and returns the applicable results. This may be the feature’s value, or may also include a feature structure if the feature requires it (ex: LBA Range Type).

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 value sent to the device is displayed

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Sets the feature for the given nsid. This is optional and most features do not use this value.

-f <fid>
--feature-id=<fid>

The feature id to send with the command. Value provided should be in hex.

-l <data-len>
--data-len=<data-len>

The data length for the buffer submitted for this feature. Most known features do not use this value. The exceptions are LBA Range Type and host identifier.

-d <data-file>
--data=<data-file>

The data file for the buffer submitted for this feature. Most known features do not use this value. The exceptions is LBA Range Type and host identifier. This defaults to STDIN so files and echo can be piped.

-v <value>
--value=<value>

The value for command dword 11, the value you want to set the feature to.

-s
--save

Save the attribute so that it persists through all power states and resets.

EXAMPLES

  • Sets the Power State (PS) to 1 in feature id 2:

    # nvme set-feature /dev/nvme0 -f 2 /dev/nvme0n1 -v 0x1
  • Sets the host id to the ascii string.

    # echo "abcdefgh" | nvme set-feature /dev/nvme0 -f 0x81 -l 8

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-set-feature.txt000066400000000000000000000040001322317423600216270ustar00rootroot00000000000000nvme-set-feature(1) =================== NAME ---- nvme-set-feature - Sets an NVMe feature, returns applicable results SYNOPSIS -------- [verse] 'nvme set-feature' [--namespace-id= | -n ] [--feature-id= | -f ] [--value= | -v ] [--data-len= | -l ] [--data= | -d ] [--save| -s] DESCRIPTION ----------- Submits an NVMe Set Feature admin command and returns the applicable results. This may be the feature's value, or may also include a feature structure if the feature requires it (ex: LBA Range Type). The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the value sent to the device is displayed OPTIONS ------- -n :: --namespace-id=:: Sets the feature for the given nsid. This is optional and most features do not use this value. -f :: --feature-id=:: The feature id to send with the command. Value provided should be in hex. -l :: --data-len=:: The data length for the buffer submitted for this feature. Most known features do not use this value. The exceptions are LBA Range Type and host identifier. -d :: --data=:: The data file for the buffer submitted for this feature. Most known features do not use this value. The exceptions is LBA Range Type and host identifier. This defaults to STDIN so files and echo can be piped. -v :: --value=:: The value for command dword 11, the value you want to set the feature to. -s:: --save:: Save the attribute so that it persists through all power states and resets. EXAMPLES -------- * Sets the Power State (PS) to 1 in feature id 2: + ------------ # nvme set-feature /dev/nvme0 -f 2 /dev/nvme0n1 -v 0x1 ------------ + * Sets the host id to the ascii string. + ------------ # echo "abcdefgh" | nvme set-feature /dev/nvme0 -f 0x81 -l 8 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-set-property.1000066400000000000000000000034611322317423600214130ustar00rootroot00000000000000'\" t .\" Title: nvme-set-property .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 12/13/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SET\-PROPERTY" "1" "12/13/2017" "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-set-property \- Writes and shows the defined NVMe controller property for NVMe ove Fabric .SH "SYNOPSIS" .sp .nf \fInvme set\-property\fR [\-\-offset= | \-o ] [\-\-value= | \-v ] .fi .SH "DESCRIPTION" .sp Writes and shows the defined NVMe controller property for NVMe ove Fabric\&. .SH "OPTIONS" .PP \-o, \-\-offset .RS 4 The offset of the property\&. .RE .PP \-v .RS 4 \-\-value: The value of the property to be set\&. .RE .SH "EXAMPLES" .sp No examples (yet)\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-set-property.html000066400000000000000000000427451322317423600222270ustar00rootroot00000000000000 nvme-set-property(1)

SYNOPSIS

nvme set-property <device> [--offset=<offset> | -o <offset>]
                                [--value=<val> | -v <val>]

DESCRIPTION

Writes and shows the defined NVMe controller property for NVMe ove Fabric.

OPTIONS

-o
--offset

The offset of the property.

-v

--value: The value of the property to be set.

EXAMPLES

No examples (yet).

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-set-property.txt000066400000000000000000000010701322317423600220640ustar00rootroot00000000000000nvme-set-property(1) ==================== NAME ---- nvme-set-property - Writes and shows the defined NVMe controller property for NVMe ove Fabric SYNOPSIS -------- [verse] 'nvme set-property' [--offset= | -o ] [--value= | -v ] DESCRIPTION ----------- Writes and shows the defined NVMe controller property for NVMe ove Fabric. OPTIONS ------- -o:: --offset:: The offset of the property. -v:: --value: The value of the property to be set. EXAMPLES -------- No examples (yet). NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-show-regs.1000066400000000000000000000055361322317423600206610ustar00rootroot00000000000000'\" t .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 12/13/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ID\-NS" "1" "12/13/2017" "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-show-regs \- Reads and shows the defined NVMe controller registers for NVMe over PCIe or the controller properties for NVMe over Fabrics\&. .SH "SYNOPSIS" .sp .nf \fInvme show\-regs\fR [\-\-human\-readable | \-H] .fi .SH "DESCRIPTION" .sp For the NVMe over PCIe device given, sends an identify namespace command and provides the result and returned structure\&. For the NVMe over Fabrics device given, sends a fabric command and provides the result and returned structure\&. .sp The parameter is mandatory and must be the nvme admin character device (ex: /dev/nvme0)\&. For NVMe over PCIe, the program uses knowledge of the sysfs layout to map the device to the pci resource stored there and mmaps the memory to get access to the registers\&. For NVMe over Fabrics, the programs sends a fabric command to get the properties of the target NVMe controller\&. Only the supported properties are displayed\&. .SH "OPTIONS" .PP \-H, \-\-human\-readable .RS 4 Display registers or supported properties in human readable format\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Show the NVMe over PCIe controller registers or the NVMe over Fabric controller properties in a binary format: .sp .if n \{\ .RS 4 .\} .nf # nvme show\-regs /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 NVMe over PCIe controller registers or the NVMe over Fabric controller properties in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme show\-regs /dev/nvme0 \-H .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-show-regs.html000066400000000000000000000447261322317423600214710ustar00rootroot00000000000000 nvme-id-ns(1)

SYNOPSIS

nvme show-regs <device> [--human-readable | -H]

DESCRIPTION

For the NVMe over PCIe device given, sends an identify namespace command and provides the result and returned structure. For the NVMe over Fabrics device given, sends a fabric command and provides the result and returned structure.

The <device> parameter is mandatory and must be the nvme admin character device (ex: /dev/nvme0). For NVMe over PCIe, the program uses knowledge of the sysfs layout to map the device to the pci resource stored there and mmaps the memory to get access to the registers. For NVMe over Fabrics, the programs sends a fabric command to get the properties of the target NVMe controller. Only the supported properties are displayed.

OPTIONS

-H
--human-readable

Display registers or supported properties in human readable format.

EXAMPLES

  • Show the NVMe over PCIe controller registers or the NVMe over Fabric controller properties in a binary format:

    # nvme show-regs /dev/nvme0
  • Show the NVMe over PCIe controller registers or the NVMe over Fabric controller properties in a human readable format:

    # nvme show-regs /dev/nvme0 -H

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-show-regs.txt000066400000000000000000000026721322317423600213360ustar00rootroot00000000000000nvme-id-ns(1) ============= NAME ---- nvme-show-regs - Reads and shows the defined NVMe controller registers for NVMe over PCIe or the controller properties for NVMe over Fabrics. SYNOPSIS -------- [verse] 'nvme show-regs' [--human-readable | -H] DESCRIPTION ----------- For the NVMe over PCIe device given, sends an identify namespace command and provides the result and returned structure. For the NVMe over Fabrics device given, sends a fabric command and provides the result and returned structure. The parameter is mandatory and must be the nvme admin character device (ex: /dev/nvme0). For NVMe over PCIe, the program uses knowledge of the sysfs layout to map the device to the pci resource stored there and mmaps the memory to get access to the registers. For NVMe over Fabrics, the programs sends a fabric command to get the properties of the target NVMe controller. Only the supported properties are displayed. OPTIONS ------- -H:: --human-readable:: Display registers or supported properties in human readable format. EXAMPLES -------- * Show the NVMe over PCIe controller registers or the NVMe over Fabric controller properties in a binary format: + ------------ # nvme show-regs /dev/nvme0 ------------ * Show the NVMe over PCIe controller registers or the NVMe over Fabric controller properties in a human readable format: + ------------ # nvme show-regs /dev/nvme0 -H ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-smart-log.1000066400000000000000000000062701322317423600206440ustar00rootroot00000000000000'\" t .\" Title: nvme-smart-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SMART\-LOG" "1" "12/10/2017" "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-smart-log \- Send NVMe SMART log page request, returns result and log .SH "SYNOPSIS" .sp .nf \fInvme smart\-log\fR [\-\-namespace\-id= | \-n ] [\-\-raw\-binary | \-b] [\-\-output\-format= | \-o ] .fi .SH "DESCRIPTION" .sp Retrieves the NVMe SMART log page from an NVMe device and provides the retuned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp On success, the returned smart 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 or the raw buffer may be printed to stdout for another program to parse\&. .SH "OPTIONS" .PP \-n , \-\-namespace\-id= .RS 4 Retrieve the SMART log for the given nsid\&. This is optional and its success may depend on the device\(cqs capabilities to provide this log on a per\-namespace basis (see the NVMe Identify Controller for this capability)\&. The default nsid to use is 0xffffffff for the device global SMART log\&. .RE .PP \-b, \-\-raw\-binary .RS 4 Print the raw SMART log buffer to stdout\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Print the SMART log page in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme smart\-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 SMART log to a file: .sp .if n \{\ .RS 4 .\} .nf # nvme smart\-log /dev/nvme0 \-\-raw\-binary > smart_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 nvme-cli-1.5/Documentation/nvme-smart-log.html000066400000000000000000000461671322317423600214610ustar00rootroot00000000000000 nvme-smart-log(1)

SYNOPSIS

nvme smart-log <device> [--namespace-id=<nsid> | -n <nsid>]
                        [--raw-binary | -b]
                        [--output-format=<fmt> | -o <fmt>]

DESCRIPTION

Retrieves the NVMe SMART log page from an NVMe device and provides the retuned 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 smart 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 or the raw buffer may be printed to stdout for another program to parse.

OPTIONS

-n <nsid>
--namespace-id=<nsid>

Retrieve the SMART log for the given nsid. This is optional and its success may depend on the device’s capabilities to provide this log on a per-namespace basis (see the NVMe Identify Controller for this capability). The default nsid to use is 0xffffffff for the device global SMART log.

-b
--raw-binary

Print the raw SMART 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 SMART log page in a human readable format:

    # nvme smart-log /dev/nvme0
  • Print the raw SMART log to a file:

    # nvme smart-log /dev/nvme0 --raw-binary > smart_log.raw

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

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-smart-log.txt000066400000000000000000000033231322317423600213170ustar00rootroot00000000000000nvme-smart-log(1) ================= NAME ---- nvme-smart-log - Send NVMe SMART log page request, returns result and log SYNOPSIS -------- [verse] 'nvme smart-log' [--namespace-id= | -n ] [--raw-binary | -b] [--output-format= | -o ] DESCRIPTION ----------- Retrieves the NVMe SMART log page from an NVMe device and provides the retuned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). On success, the returned smart 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 or the raw buffer may be printed to stdout for another program to parse. OPTIONS ------- -n :: --namespace-id=:: Retrieve the SMART log for the given nsid. This is optional and its success may depend on the device's capabilities to provide this log on a per-namespace basis (see the NVMe Identify Controller for this capability). The default nsid to use is 0xffffffff for the device global SMART log. -b:: --raw-binary:: Print the raw SMART log buffer to stdout. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Print the SMART log page in a human readable format: + ------------ # nvme smart-log /dev/nvme0 ------------ + * Print the raw SMART log to a file: + ------------ # nvme smart-log /dev/nvme0 --raw-binary > smart_log.raw ------------ + It is probably a bad idea to not redirect stdout when using this mode. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-subsystem-reset.1000066400000000000000000000033701322317423600221130ustar00rootroot00000000000000'\" t .\" Title: nvme-subsystem-reset .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-SUBSYSTEM\-RES" "1" "12/10/2017" "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-subsystem-reset \- Reset the nvme subsystem\&. .SH "SYNOPSIS" .sp .nf \fInvme subsystem\-reset\fR .fi .SH "DESCRIPTION" .sp Requests NVMe subsystem reset\&. The param is mandatory and must be an NVMe character device (ex: /dev/nvme0)\&. .SH "OPTIONS" .sp None .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Resets the subsystem\&. .sp .if n \{\ .RS 4 .\} .nf # nvme subsystem\-reset /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-subsystem-reset.html000066400000000000000000000424451322317423600227250ustar00rootroot00000000000000 nvme-subsystem-reset(1)

SYNOPSIS

nvme subsystem-reset <device>

DESCRIPTION

Requests NVMe subsystem reset. The <device> param is mandatory and must be an NVMe character device (ex: /dev/nvme0).

OPTIONS

None

EXAMPLES

  • Resets the subsystem.

    # nvme subsystem-reset /dev/nvme0

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-subsystem-reset.txt000066400000000000000000000007341322317423600225730ustar00rootroot00000000000000nvme-subsystem-reset(1) ======================= NAME ---- nvme-subsystem-reset - Reset the nvme subsystem. SYNOPSIS -------- [verse] 'nvme subsystem-reset' DESCRIPTION ----------- Requests NVMe subsystem reset. The param is mandatory and must be an NVMe character device (ex: /dev/nvme0). OPTIONS ------- None EXAMPLES -------- * Resets the subsystem. + ------------ # nvme subsystem-reset /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-wdc-cap-diag.1000066400000000000000000000055111322317423600211540ustar00rootroot00000000000000'\" t .\" Title: nvme-wdc-cap-diag .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WDC\-CAP\-DIAG" "1" "12/10/2017" "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-wdc-cap-diag \- Retrieve WDC device\*(Aqs diagnostic log and save to file\&. .SH "SYNOPSIS" .sp .nf \fInvme wdc cap\-diag\fR [\-\-output\-file=, \-o ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends the WDC Vendor Unique Capture\-Diagnostics request and saves the result to a file\&. .sp The parameter is mandatory NVMe character device (ex: /dev/nvme0)\&. .sp This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .SH "OPTIONS" .PP \-o , \-\-output\-file= .RS 4 Output file; defaults to device serial number followed by "cap_diag" suffix .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the capture diagnostics log from the device and saves to default file in current directory (e\&.g\&. STM00019F3F9cap_diag\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc cap\-diag /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 .\} Gets the capture diagnostics log from the device and saves to defined file in current directory (e\&.g\&. testSTM00019F3F9cap_diag\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc cap\-diag /dev/nvme0 \-o test .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the capture diagnostics log from the device and saves to defined file with pathname (e\&.g\&. /tmp/testSTM00019F3F9cap_diag\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc cap\-diag /dev/nvme0 \-o /tmp/test .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite\&. nvme-cli-1.5/Documentation/nvme-wdc-cap-diag.html000066400000000000000000000447321322317423600217700ustar00rootroot00000000000000 nvme-wdc-cap-diag(1)

SYNOPSIS

nvme wdc cap-diag <device> [--output-file=<FILE>, -o <FILE>]

DESCRIPTION

For the NVMe device given, sends the WDC Vendor Unique Capture-Diagnostics request and saves the result to a file.

The <device> parameter is mandatory NVMe character device (ex: /dev/nvme0).

This will only work on WDC devices supporting this feature. Results for any other device are undefined.

OPTIONS

-o <FILE>
--output-file=<FILE>

Output file; defaults to device serial number followed by "cap_diag" suffix

EXAMPLES

  • Gets the capture diagnostics log from the device and saves to default file in current directory (e.g. STM00019F3F9cap_diag.bin):

    # nvme wdc cap-diag /dev/nvme0
  • Gets the capture diagnostics log from the device and saves to defined file in current directory (e.g. testSTM00019F3F9cap_diag.bin):

    # nvme wdc cap-diag /dev/nvme0 -o test
  • Gets the capture diagnostics log from the device and saves to defined file with pathname (e.g. /tmp/testSTM00019F3F9cap_diag.bin):

    # nvme wdc cap-diag /dev/nvme0 -o /tmp/test

NVME

Part of the nvme-user suite.


nvme-cli-1.5/Documentation/nvme-wdc-cap-diag.txt000066400000000000000000000024561322317423600216400ustar00rootroot00000000000000nvme-wdc-cap-diag(1) ==================== NAME ---- nvme-wdc-cap-diag - Retrieve WDC device's diagnostic log and save to file. SYNOPSIS -------- [verse] 'nvme wdc cap-diag' [--output-file=, -o ] DESCRIPTION ----------- For the NVMe device given, sends the WDC Vendor Unique Capture-Diagnostics request and saves the result to a file. The parameter is mandatory NVMe character device (ex: /dev/nvme0). This will only work on WDC devices supporting this feature. Results for any other device are undefined. OPTIONS ------- -o :: --output-file=:: Output file; defaults to device serial number followed by "cap_diag" suffix EXAMPLES -------- * Gets the capture diagnostics log from the device and saves to default file in current directory (e.g. STM00019F3F9cap_diag.bin): + ------------ # nvme wdc cap-diag /dev/nvme0 ------------ * Gets the capture diagnostics log from the device and saves to defined file in current directory (e.g. testSTM00019F3F9cap_diag.bin): + ------------ # nvme wdc cap-diag /dev/nvme0 -o test ------------ * Gets the capture diagnostics log from the device and saves to defined file with pathname (e.g. /tmp/testSTM00019F3F9cap_diag.bin): + ------------ # nvme wdc cap-diag /dev/nvme0 -o /tmp/test ------------ NVME ---- Part of the nvme-user suite. nvme-cli-1.5/Documentation/nvme-wdc-drive-log.1000066400000000000000000000055341322317423600214040ustar00rootroot00000000000000'\" t .\" Title: nvme-wdc-drive-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WDC\-DRIVE\-LO" "1" "12/10/2017" "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-wdc-drive-log \- Retrieve WDC device\*(Aqs drive log and save to file\&. .SH "SYNOPSIS" .sp .nf \fInvme wdc drive\-log\fR [\-\-output\-file=, \-o ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends the wdc vendor unique drive log request and saves the result to a file\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .SH "OPTIONS" .PP \-o , \-\-output\-file= .RS 4 Output file; defaults to device serial number followed by "drive_log" suffix .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the drive log from the device and saves to default file in current directory (e\&.g\&. STM00019F3F9drive_log\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc drive\-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 .\} Gets the drive log from the device and saves to defined file in current directory (e\&.g\&. testSTM00019F3F9drive_log\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc drive\-log /dev/nvme0 \-o test .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the drive log from the device and saves to defined file with pathname (e\&.g\&. /tmp/testSTM00019F3F9drive_log\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc drive\-log /dev/nvme0 \-o /tmp/test .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-wdc-drive-log.html000066400000000000000000000447631322317423600222170ustar00rootroot00000000000000 nvme-wdc-drive-log(1)

SYNOPSIS

nvme wdc drive-log <device> [--output-file=<FILE>, -o <FILE>]

DESCRIPTION

For the NVMe device given, sends the wdc vendor unique drive log request and saves the result to a file.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

This will only work on WDC devices supporting this feature. Results for any other device are undefined.

OPTIONS

-o <FILE>
--output-file=<FILE>

Output file; defaults to device serial number followed by "drive_log" suffix

EXAMPLES

  • Gets the drive log from the device and saves to default file in current directory (e.g. STM00019F3F9drive_log.bin):

    # nvme wdc drive-log /dev/nvme0
  • Gets the drive log from the device and saves to defined file in current directory (e.g. testSTM00019F3F9drive_log.bin):

    # nvme wdc drive-log /dev/nvme0 -o test
  • Gets the drive log from the device and saves to defined file with pathname (e.g. /tmp/testSTM00019F3F9drive_log.bin):

    # nvme wdc drive-log /dev/nvme0 -o /tmp/test

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-wdc-drive-log.txt000066400000000000000000000025051322317423600220560ustar00rootroot00000000000000nvme-wdc-drive-log(1) ===================== NAME ---- nvme-wdc-drive-log - Retrieve WDC device's drive log and save to file. SYNOPSIS -------- [verse] 'nvme wdc drive-log' [--output-file=, -o ] DESCRIPTION ----------- For the NVMe device given, sends the wdc vendor unique drive log request and saves the result to a file. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). This will only work on WDC devices supporting this feature. Results for any other device are undefined. OPTIONS ------- -o :: --output-file=:: Output file; defaults to device serial number followed by "drive_log" suffix EXAMPLES -------- * Gets the drive log from the device and saves to default file in current directory (e.g. STM00019F3F9drive_log.bin): + ------------ # nvme wdc drive-log /dev/nvme0 ------------ * Gets the drive log from the device and saves to defined file in current directory (e.g. testSTM00019F3F9drive_log.bin): + ------------ # nvme wdc drive-log /dev/nvme0 -o test ------------ * Gets the drive log from the device and saves to defined file with pathname (e.g. /tmp/testSTM00019F3F9drive_log.bin): + ------------ # nvme wdc drive-log /dev/nvme0 -o /tmp/test ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-wdc-get-crash-dump.1000066400000000000000000000060121322317423600223240ustar00rootroot00000000000000'\" t .\" Title: nvme-wdc-get-crash-dump .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WDC\-GET\-CRAS" "1" "12/10/2017" "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-wdc-get-crash-dump \- Retrieve WDC device\*(Aqs crash dump\&. .SH "SYNOPSIS" .sp .nf \fInvme wdc get\-crash\-dump\fR [\-\-output\-file=, \-o ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends the WDC vendor unique crash dump request and saves the result to file\&. In current implementation crash dump is captured if it is present\&. On success it will save the dump in file with appropriate suffix\&. Note that this command will clear the available dump from the device on success\&. .sp The parameter is mandatory NVMe character device (ex: /dev/nvme0)\&. .sp This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .SH "OPTIONS" .PP \-o , \-\-output\-file= .RS 4 Output file; defaults to device serial number followed by "crash_dump" suffix .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the crash dump from the device and saves to default file in current directory (e\&.g\&. STM00019F3F9crash_dump\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc get\-crash\-dump /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 .\} Gets the crash dump from the device and saves to defined file in current directory (e\&.g\&. testSTM00019F3F9crash_dump\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc get\-crash\-dump /dev/nvme0 \-o test .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Gets the crash dump from the device and saves to defined file with pathname (e\&.g\&. /tmp/testSTM00019F3F9crash_dump\&.bin): .sp .if n \{\ .RS 4 .\} .nf # nvme wdc get\-crash\-dump /dev/nvme0 \-o /tmp/test .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-wdc-get-crash-dump.html000066400000000000000000000452351322317423600231420ustar00rootroot00000000000000 nvme-wdc-get-crash-dump(1)

SYNOPSIS

nvme wdc get-crash-dump <device> [--output-file=<FILE>, -o <FILE>]

DESCRIPTION

For the NVMe device given, sends the WDC vendor unique crash dump request and saves the result to file. In current implementation crash dump is captured if it is present. On success it will save the dump in file with appropriate suffix. Note that this command will clear the available dump from the device on success.

The <device> parameter is mandatory NVMe character device (ex: /dev/nvme0).

This will only work on WDC devices supporting this feature. Results for any other device are undefined.

OPTIONS

-o <FILE>
--output-file=<FILE>

Output file; defaults to device serial number followed by "crash_dump" suffix

EXAMPLES

  • Gets the crash dump from the device and saves to default file in current directory (e.g. STM00019F3F9crash_dump.bin):

    # nvme wdc get-crash-dump /dev/nvme0
  • Gets the crash dump from the device and saves to defined file in current directory (e.g. testSTM00019F3F9crash_dump.bin):

    # nvme wdc get-crash-dump /dev/nvme0 -o test
  • Gets the crash dump from the device and saves to defined file with pathname (e.g. /tmp/testSTM00019F3F9crash_dump.bin):

    # nvme wdc get-crash-dump /dev/nvme0 -o /tmp/test

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-wdc-get-crash-dump.txt000066400000000000000000000027551322317423600230150ustar00rootroot00000000000000nvme-wdc-get-crash-dump(1) ========================== NAME ---- nvme-wdc-get-crash-dump - Retrieve WDC device's crash dump. SYNOPSIS -------- [verse] 'nvme wdc get-crash-dump' [--output-file=, -o ] DESCRIPTION ----------- For the NVMe device given, sends the WDC vendor unique crash dump request and saves the result to file. In current implementation crash dump is captured if it is present. On success it will save the dump in file with appropriate suffix. Note that this command will clear the available dump from the device on success. The parameter is mandatory NVMe character device (ex: /dev/nvme0). This will only work on WDC devices supporting this feature. Results for any other device are undefined. OPTIONS ------- -o :: --output-file=:: Output file; defaults to device serial number followed by "crash_dump" suffix EXAMPLES -------- * Gets the crash dump from the device and saves to default file in current directory (e.g. STM00019F3F9crash_dump.bin): + ------------ # nvme wdc get-crash-dump /dev/nvme0 ------------ * Gets the crash dump from the device and saves to defined file in current directory (e.g. testSTM00019F3F9crash_dump.bin): + ------------ # nvme wdc get-crash-dump /dev/nvme0 -o test ------------ * Gets the crash dump from the device and saves to defined file with pathname (e.g. /tmp/testSTM00019F3F9crash_dump.bin): + ------------ # nvme wdc get-crash-dump /dev/nvme0 -o /tmp/test ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-wdc-id-ctrl.1000066400000000000000000000062221322317423600210450ustar00rootroot00000000000000'\" t .\" Title: nvme-wdc-id-ctrl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WDC\-ID\-CTRL" "1" "12/10/2017" "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-wdc-id-ctrl \- Send NVMe Identify Controller, return result and structure .SH "SYNOPSIS" .sp .nf \fInvme wdc id\-ctrl\fR [\-v | \-\-vendor\-specific] [\-b | \-\-raw\-binary] [\-o | \-\-output\-format=] .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends an identify controller command and provides the result and returned structure\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .sp On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout\&. .sp If having the program decode the output for readability, this version will decode WDC vendor unique portions of the structure\&. .SH "OPTIONS" .PP \-b, \-\-raw\-binary .RS 4 Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-v, \-\-vendor\-specific .RS 4 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&. .RE .PP \-H, \-\-human\-readable .RS 4 This option will parse and format many of the bit fields into human\-readable formats\&. .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fInormal\fR, \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program interpret the returned buffer and display the known fields in a human readable format: .sp .if n \{\ .RS 4 .\} .nf # nvme wdc id\-ctrl /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-wdc-id-ctrl.html000066400000000000000000000462571322317423600216650ustar00rootroot00000000000000 nvme-wdc-id-ctrl(1)

SYNOPSIS

nvme wdc id-ctrl <device> [-v | --vendor-specific] [-b | --raw-binary]
                        [-o <fmt> | --output-format=<fmt>]

DESCRIPTION

For the NVMe device given, sends an identify controller command and provides the result and returned structure.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

This will only work on WDC devices supporting this feature. Results for any other device are undefined.

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

If having the program decode the output for readability, this version will decode WDC vendor unique portions of the structure.

OPTIONS

-b
--raw-binary

Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options.

-v
--vendor-specific

In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation.

-H
--human-readable

This option will parse and format many of the bit fields into human-readable formats.

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

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

EXAMPLES

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

    # nvme wdc id-ctrl /dev/nvme0

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-wdc-id-ctrl.txt000066400000000000000000000034271322317423600215300ustar00rootroot00000000000000nvme-wdc-id-ctrl(1) ===================== NAME ---- nvme-wdc-id-ctrl - Send NVMe Identify Controller, return result and structure SYNOPSIS -------- [verse] 'nvme wdc id-ctrl' [-v | --vendor-specific] [-b | --raw-binary] [-o | --output-format=] DESCRIPTION ----------- For the NVMe device given, sends an identify controller command and provides the result and returned structure. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). This will only work on WDC devices supporting this feature. Results for any other device are undefined. On success, the structure may be returned in one of several ways depending on the option flags; the structure may be parsed by the program or the raw buffer may be printed to stdout. If having the program decode the output for readability, this version will decode WDC vendor unique portions of the structure. OPTIONS ------- -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by program. This overrides the vendor specific and human readable options. -v:: --vendor-specific:: In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation. -H:: --human-readable:: This option will parse and format many of the bit fields into human-readable formats. -o :: --output-format=:: Set the reporting format to 'normal', 'json', or 'binary'. Only one output format can be used at a time. EXAMPLES -------- * Has the program interpret the returned buffer and display the known fields in a human readable format: + ------------ # nvme wdc id-ctrl /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-wdc-purge-monitor.1000066400000000000000000000052041322317423600223150ustar00rootroot00000000000000'\" t .\" Title: nvme-wdc-purge-monitor .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WDC\-PURGE\-MO" "1" "12/10/2017" "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-wdc-purge-monitor \- Send NVMe WDC Purge\-Monitor Vendor Unique Command, return result .SH "SYNOPSIS" .sp .nf \fInvme wdc purge\-monitor\fR .fi .SH "DESCRIPTION" .sp For the NVMe device given, send a Vendor Unique WDC Purge\-Monitor command and provide the status of the purge command\&. .sp Expected status and description :\- .TS allbox tab(:); ltB ltB. T{ Status Code T}:T{ Description T} .T& lt lt lt lt lt lt lt lt lt lt. T{ .sp 0x00 T}:T{ .sp Purge State Idle\&. T} T{ .sp 0x01 T}:T{ .sp Purge State Done\&. T} T{ .sp 0x02 T}:T{ .sp Purge State Busy\&. T} T{ .sp 0x03 T}:T{ .sp Purge State Error : Purge operation resulted in error, power cycle required\&. T} T{ .sp 0x04 T}:T{ .sp Purge State Error : Purge operation interrupted by power cycle or reset\&. T} .TE .sp 1 .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .sp On success it returns 0, error code otherwise\&. .SH "OPTIONS" .sp No options yet\&. .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program issue WDC Purge\-Monitor Vendor Unique Command : .sp .if n \{\ .RS 4 .\} .nf # nvme wdc purge\-monitor /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite\&. nvme-cli-1.5/Documentation/nvme-wdc-purge-monitor.html000066400000000000000000000460151322317423600231260ustar00rootroot00000000000000 nvme-wdc-purge-monitor(1)

SYNOPSIS

nvme wdc purge-monitor <device>

DESCRIPTION

For the NVMe device given, send a Vendor Unique WDC Purge-Monitor command and provide the status of the purge command.

Expected status and description :-

Status Code Description

0x00

Purge State Idle.

0x01

Purge State Done.

0x02

Purge State Busy.

0x03

Purge State Error : Purge operation resulted in error, power cycle required.

0x04

Purge State Error : Purge operation interrupted by power cycle or reset.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

This will only work on WDC devices supporting this feature. Results for any other device are undefined.

On success it returns 0, error code otherwise.

OPTIONS

No options yet.

EXAMPLES

  • Has the program issue WDC Purge-Monitor Vendor Unique Command :

    # nvme wdc purge-monitor /dev/nvme0

NVME

Part of the nvme-user suite.


nvme-cli-1.5/Documentation/nvme-wdc-purge-monitor.txt000066400000000000000000000023151322317423600227740ustar00rootroot00000000000000nvme-wdc-purge-monitor(1) ========================== NAME ---- nvme-wdc-purge-monitor - Send NVMe WDC Purge-Monitor Vendor Unique Command, return result SYNOPSIS -------- [verse] 'nvme wdc purge-monitor' DESCRIPTION ----------- For the NVMe device given, send a Vendor Unique WDC Purge-Monitor command and provide the status of the purge command. Expected status and description :- [cols="2*", options="header"] |=== |Status Code |Description |0x00 |Purge State Idle. |0x01 |Purge State Done. |0x02 |Purge State Busy. |0x03 |Purge State Error : Purge operation resulted in error, power cycle required. |0x04 |Purge State Error : Purge operation interrupted by power cycle or reset. |=== The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). This will only work on WDC devices supporting this feature. Results for any other device are undefined. On success it returns 0, error code otherwise. OPTIONS ------- No options yet. EXAMPLES -------- * Has the program issue WDC Purge-Monitor Vendor Unique Command : + ------------ # nvme wdc purge-monitor /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite. nvme-cli-1.5/Documentation/nvme-wdc-purge.1000066400000000000000000000041121322317423600206250ustar00rootroot00000000000000'\" t .\" Title: nvme-wdc-purge .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WDC\-PURGE" "1" "12/10/2017" "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-wdc-purge \- Send NVMe WDC Purge Vendor Unique Command, return result .SH "SYNOPSIS" .sp .nf \fInvme wdc purge\fR .fi .SH "DESCRIPTION" .sp For the NVMe device given, sends a Vendor Unique WDC Purge command and provides the result\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .sp This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .sp On success it returns 0, error code otherwise\&. .SH "OPTIONS" .sp No options yet\&. .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program issue WDC Purge Vendor Unique Command : .sp .if n \{\ .RS 4 .\} .nf # nvme wdc purge /dev/nvme0n1 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite\&. nvme-cli-1.5/Documentation/nvme-wdc-purge.html000066400000000000000000000433261322317423600214430ustar00rootroot00000000000000 nvme-wdc-purge(1)

SYNOPSIS

nvme wdc purge <device>

DESCRIPTION

For the NVMe device given, sends a Vendor Unique WDC Purge command and provides the result.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

This will only work on WDC devices supporting this feature. Results for any other device are undefined.

On success it returns 0, error code otherwise.

OPTIONS

No options yet.

EXAMPLES

  • Has the program issue WDC Purge Vendor Unique Command :

    # nvme wdc purge /dev/nvme0n1

NVME

Part of the nvme-user suite.


nvme-cli-1.5/Documentation/nvme-wdc-purge.txt000066400000000000000000000014401322317423600213050ustar00rootroot00000000000000nvme-wdc-purge(1) ================== NAME ---- nvme-wdc-purge - Send NVMe WDC Purge Vendor Unique Command, return result SYNOPSIS -------- [verse] 'nvme wdc purge' DESCRIPTION ----------- For the NVMe device given, sends a Vendor Unique WDC Purge command and provides the result. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). This will only work on WDC devices supporting this feature. Results for any other device are undefined. On success it returns 0, error code otherwise. OPTIONS ------- No options yet. EXAMPLES -------- * Has the program issue WDC Purge Vendor Unique Command : + ------------ # nvme wdc purge /dev/nvme0n1 ------------ NVME ---- Part of the nvme-user suite. nvme-cli-1.5/Documentation/nvme-wdc-smart-add-log.1000066400000000000000000000311011322317423600221340ustar00rootroot00000000000000'\" t .\" Title: nvme-wdc-smart-add-log .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WDC\-SMART\-AD" "1" "12/10/2017" "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-wdc-smart-add-log \- Send NVMe WDC smart\-add\-log Vendor Unique Command, return result .SH "SYNOPSIS" .sp .nf \fInvme wdc smart\-add\-log\fR [\-\-interval=, \-i ] [\-\-output\-format= \-o ] .fi .SH "DESCRIPTION" .sp For the NVMe device given, send a Vendor Unique WDC smart\-add\-log command and provide the additional smart log\&. The \-\-interval option will return performance statistics from the specified reporting interval\&. .sp The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0)\&. .sp This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .sp On success it returns 0, error code otherwise\&. .SH "OPTIONS" .PP \-i , \-\-interval= .RS 4 Return the statistics from specific interval, defaults to 14 .RE .PP \-o , \-\-output\-format= .RS 4 Set the reporting format to \fIhuman\fR, or \fIjson\fR\&. Only one output format can be used at a time\&. Default is human\&. .RE .sp Valid Interval values and description :\- .TS allbox tab(:); ltB ltB. T{ Value T}:T{ Description T} .T& lt lt lt lt lt lt lt lt lt lt. T{ .sp \fB1\fR T}:T{ .sp Most recent five (5) minute accumulated set\&. T} T{ .sp \fB2\-12\fR T}:T{ .sp Previous five (5) minute accumulated sets\&. T} T{ .sp \fB13\fR T}:T{ .sp The accumulated total of sets 1 through 12 that contain the previous hour of accumulated statistics\&. T} T{ .sp \fB14\fR T}:T{ .sp The statistical set accumulated since power\-up\&. T} T{ .sp \fB15\fR T}:T{ .sp The statistical set accumulated during the entire lifetime of the device\&. T} .TE .sp 1 .SH "CA LOG PAGE DATA OUTPUT EXPLANATION" .TS allbox tab(:); ltB ltB. T{ Field T}:T{ Description T} .T& lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt. T{ .sp \fBPhysical NAND bytes written\&.\fR T}:T{ .sp The number of bytes written to NAND\&. 16 bytes \- hi/lo T} T{ .sp \fBPhysical NAND bytes read\fR T}:T{ .sp The number of bytes read from NAND\&. 16 bytes \- hi/lo T} T{ .sp \fBBad NAND Block Count\fR T}:T{ .sp Raw and normalized count of the number of NAND blocks that have been retired after the drives manufacturing tests (i\&.e\&. grown back blocks)\&. 2 bytes normalized, 6 bytes raw count T} T{ .sp \fBUncorrectable Read Error Count\fR T}:T{ .sp Total count of NAND reads that were not correctable by read retries, all levels of ECC, or XOR (as applicable)\&. 8 bytes T} T{ .sp \fBSoft ECC Error Count\fR T}:T{ .sp Total count of NAND reads that were not correctable by read retries, or first\-level ECC\&. 8 bytes T} T{ .sp \fBSSD End to End Detection Count\fR T}:T{ .sp A count of the detected errors by the SSD end to end error correction which includes DRAM, SRAM, or other storage element ECC/CRC protection mechanism (not NAND ECC)\&. 4 bytes T} T{ .sp \fBSSD End to End Correction Count\fR T}:T{ .sp A count of the corrected errors by the SSD end to end error correction which includes DRAM, SRAM, or other storage element ECC/CRC protection mechanism (not NAND ECC)\&. 4 bytes T} T{ .sp \fBSystem Data % Used\fR T}:T{ .sp A normalized cumulative count of the number of erase cycles per block since leaving the factory for the system (FW and metadata) area\&. Starts at 0 and increments\&. 100 indicates that the estimated endurance has been consumed\&. T} T{ .sp \fBUser Data Max Erase Count\fR T}:T{ .sp The maximum erase count across all NAND blocks in the drive\&. 4 bytes T} T{ .sp \fBUser Data Min Erase Count\fR T}:T{ .sp The minimum erase count across all NAND blocks in the drive\&. 4 bytes T} T{ .sp \fBRefresh Count\fR T}:T{ .sp A count of the number of blocks that have been re\-allocated due to background operations only\&. 8 bytes T} T{ .sp \fBProgram Fail Count\fR T}:T{ .sp Raw and normalized count of total program failures\&. Normalized count starts at 100 and shows the percent of remaining allowable failures\&. 2 bytes normalized, 6 bytes raw count T} T{ .sp \fBUser Data Erase Fail Count\fR T}:T{ .sp Raw and normalized count of total erase failures in the user area\&. Normalized count starts at 100 and shows the percent of remaining allowable failures\&. 2 bytes normalized, 6 bytes raw count T} T{ .sp \fBSystem Area Erase Fail Count\fR T}:T{ .sp Raw and normalized count of total erase failures in the system area\&. Normalized count starts at 100 and shows the percent of remaining allowable failures\&. 2 bytes normalized, 6 bytes raw count T} T{ .sp \fBThermal Throttling Status\fR T}:T{ .sp The current status of thermal throttling (enabled or disabled)\&. 2 bytes T} T{ .sp \fBThermal Throttling Count\fR T}:T{ .sp A count of the number of thermal throttling events\&. 2 bytes T} T{ .sp \fBPCIe Correctable Error Count\fR T}:T{ .sp Summation counter of all PCIe correctable errors (Bad TLP, Bad DLLP, Receiver error, Replay timeouts, Replay rollovers)\&. 8 bytes T} .TE .sp 1 .SH "C1 LOG PAGE DATA OUTPUT EXPLANATION" .TS allbox tab(:); ltB ltB. T{ Field T}:T{ Description T} .T& lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt lt. T{ .sp \fBHost Read Commands\fR T}:T{ .sp Number of host read commands received during the reporting period\&. T} T{ .sp \fBHost Read Blocks\fR T}:T{ .sp Number of 512\-byte blocks requested during the reporting period\&. T} T{ .sp \fBAverage Read Size\fR T}:T{ .sp Average Read size is calculated using (Host Read Blocks/Host Read Commands)\&. T} T{ .sp \fBHost Read Cache Hit Commands\fR T}:T{ .sp Number of host read commands that serviced entirely from the on\-board read cache during the reporting period\&. No access to the NAND flash memory was required\&. This count is only updated if the entire command was serviced from the cache memory\&. T} T{ .sp \fBHost Read Cache Hit Percentage\fR T}:T{ .sp Percentage of host read commands satisfied from the cache\&. T} T{ .sp \fBHost Read Cache Hit Blocks\fR T}:T{ .sp Number of 512\-byte blocks of data that have been returned for Host Read Cache Hit Commands during the reporting period\&. This count is only updated with the blocks returned for host read commands that were serviced entirely from cache memory\&. T} T{ .sp \fBAverage Read Cache Hit Size\fR T}:T{ .sp Average size of read commands satisfied from the cache\&. T} T{ .sp \fBHost Read Commands Stalled\fR T}:T{ .sp Number of host read commands that were stalled due to a lack of resources within the SSD during the reporting period (NAND flash command queue full, low cache page count, cache page contention, etc\&.)\&. Commands are not considered stalled if the only reason for the delay was waiting for the data to be physically read from the NAND flash\&. It is normal to expect this count to equal zero on heavily utilized systems\&. T} T{ .sp \fBHost Read Commands Stalled Percentage\fR T}:T{ .sp Percentage of read commands that were stalled\&. If the figure is consistently high, then consideration should be given to spreading the data across multiple SSDs\&. T} T{ .sp \fBHost Write Commands\fR T}:T{ .sp Number of host write commands received during the reporting period\&. T} T{ .sp \fBHost Write Blocks\fR T}:T{ .sp Number of 512\-byte blocks written during the reporting period\&. T} T{ .sp \fBAverage Write Size\fR T}:T{ .sp Average Write size calculated using (Host Write Blocks/Host Write Commands)\&. T} T{ .sp \fBHost Write Odd Start Commands\fR T}:T{ .sp Number of host write commands that started on a non\-aligned boundary during the reporting period\&. The size of the boundary alignment is normally 4K; therefore this returns the number of commands that started on a non\-4K aligned boundary\&. The SSD requires slightly more time to process non\-aligned write commands than it does to process aligned write commands\&. T} T{ .sp \fBHost Write Odd Start Commands Percentage\fR T}:T{ .sp Percentage of host write commands that started on a non\-aligned boundary\&. If this figure is equal to or near 100%, and the NAND Read Before Write value is also high, then the user should investigate the possibility of offsetting the file system\&. For Microsoft Windows systems, the user can use Diskpart\&. For Unix\-based operating systems, there is normally a method whereby file system partitions can be placed where required\&. T} T{ .sp \fBHost Write Odd End Commands\fR T}:T{ .sp Number of host write commands that ended on a non\-aligned boundary during the reporting period\&. The size of the boundary alignment is normally 4K; therefore this returns the number of commands that ended on a non\-4K aligned boundary\&. T} T{ .sp \fBHost Write Odd End Commands Percentage\fR T}:T{ .sp Percentage of host write commands that ended on a non\-aligned boundary\&. T} T{ .sp \fBHost Write Commands Stalled\fR T}:T{ .sp Number of host write commands that were stalled due to a lack of resources within the SSD during the reporting period\&. The most likely cause is that the write data was being received faster than it could be saved to the NAND flash memory\&. If there was a large volume of read commands being processed simultaneously, then other causes might include the NAND flash command queue being full, low cache page count, or cache page contention, etc\&. It is normal to expect this count to be non\-zero on heavily utilized systems\&. T} T{ .sp \fBHost Write Commands Stalled Percentage\fR T}:T{ .sp Percentage of write commands that were stalled\&. If the figure is consistently high, then consideration should be given to spreading the data across multiple SSDs\&. T} T{ .sp \fBNAND Read Commands\fR T}:T{ .sp Number of read commands issued to the NAND devices during the reporting period\&. This figure will normally be much higher than the host read commands figure, as the data needed to satisfy a single host read command may be spread across several NAND flash devices\&. T} T{ .sp \fBNAND Read Blocks\fR T}:T{ .sp Number of 512\-byte blocks requested from NAND flash devices during the reporting period\&. This figure would normally be about the same as the host read blocks figure T} T{ .sp \fBAverage NAND Read Size\fR T}:T{ .sp Average size of NAND read commands\&. T} T{ .sp \fBNAND Write Commands\fR T}:T{ .sp Number of write commands issued to the NAND devices during the reporting period\&. There is no real correlation between the number of host write commands issued and the number of NAND Write Commands\&. T} T{ .sp \fBNAND Write Blocks\fR T}:T{ .sp Number of 512\-byte blocks written to the NAND flash devices during the reporting period\&. This figure would normally be about the same as the host write blocks figure\&. T} T{ .sp \fBAverage NAND Write Size\fR T}:T{ .sp Average size of NAND write commands\&. This figure should never be greater than 128K, as this is the maximum size write that is ever issued to a NAND device\&. T} T{ .sp \fBNAND Read Before Write\fR T}:T{ .sp This is the number of read before write operations that were required to process non\-aligned host write commands during the reporting period\&. See Host Write Odd Start Commands and Host Write Odd End Commands\&. NAND Read Before Write operations have a detrimental effect on the overall performance of the device\&. T} .TE .sp 1 .SH "EXAMPLES" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Has the program issue WDC smart\-add\-log Vendor Unique Command with default interval (14) : .sp .if n \{\ .RS 4 .\} .nf # nvme wdc smart\-add\-log /dev/nvme0 .fi .if n \{\ .RE .\} .RE .SH "NVME" .sp Part of the nvme\-user suite\&. nvme-cli-1.5/Documentation/nvme-wdc-smart-add-log.html000066400000000000000000001050201322317423600227420ustar00rootroot00000000000000 nvme-wdc-smart-add-log(1)

SYNOPSIS

nvme wdc smart-add-log <device> [--interval=<NUM>, -i <NUM>] [--output-format=<normal|json> -o <normal|json>]

DESCRIPTION

For the NVMe device given, send a Vendor Unique WDC smart-add-log command and provide the additional smart log. The --interval option will return performance statistics from the specified reporting interval.

The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0).

This will only work on WDC devices supporting this feature. Results for any other device are undefined.

On success it returns 0, error code otherwise.

OPTIONS

-i <NUM>
--interval=<NUM>

Return the statistics from specific interval, defaults to 14

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

Set the reporting format to human, or json. Only one output format can be used at a time. Default is human.

Valid Interval values and description :-

Value Description

1

Most recent five (5) minute accumulated set.

2-12

Previous five (5) minute accumulated sets.

13

The accumulated total of sets 1 through 12 that contain the previous hour of accumulated statistics.

14

The statistical set accumulated since power-up.

15

The statistical set accumulated during the entire lifetime of the device.

CA Log Page Data Output Explanation

Field Description

Physical NAND bytes written.

The number of bytes written to NAND. 16 bytes - hi/lo

Physical NAND bytes read

The number of bytes read from NAND. 16 bytes - hi/lo

Bad NAND Block Count

Raw and normalized count of the number of NAND blocks that have been retired after the drives manufacturing tests (i.e. grown back blocks). 2 bytes normalized, 6 bytes raw count

Uncorrectable Read Error Count

Total count of NAND reads that were not correctable by read retries, all levels of ECC, or XOR (as applicable). 8 bytes

Soft ECC Error Count

Total count of NAND reads that were not correctable by read retries, or first-level ECC. 8 bytes

SSD End to End Detection Count

A count of the detected errors by the SSD end to end error correction which includes DRAM, SRAM, or other storage element ECC/CRC protection mechanism (not NAND ECC). 4 bytes

SSD End to End Correction Count

A count of the corrected errors by the SSD end to end error correction which includes DRAM, SRAM, or other storage element ECC/CRC protection mechanism (not NAND ECC). 4 bytes

System Data % Used

A normalized cumulative count of the number of erase cycles per block since leaving the factory for the system (FW and metadata) area. Starts at 0 and increments. 100 indicates that the estimated endurance has been consumed.

User Data Max Erase Count

The maximum erase count across all NAND blocks in the drive. 4 bytes

User Data Min Erase Count

The minimum erase count across all NAND blocks in the drive. 4 bytes

Refresh Count

A count of the number of blocks that have been re-allocated due to background operations only. 8 bytes

Program Fail Count

Raw and normalized count of total program failures. Normalized count starts at 100 and shows the percent of remaining allowable failures. 2 bytes normalized, 6 bytes raw count

User Data Erase Fail Count

Raw and normalized count of total erase failures in the user area. Normalized count starts at 100 and shows the percent of remaining allowable failures. 2 bytes normalized, 6 bytes raw count

System Area Erase Fail Count

Raw and normalized count of total erase failures in the system area. Normalized count starts at 100 and shows the percent of remaining allowable failures. 2 bytes normalized, 6 bytes raw count

Thermal Throttling Status

The current status of thermal throttling (enabled or disabled). 2 bytes

Thermal Throttling Count

A count of the number of thermal throttling events. 2 bytes

PCIe Correctable Error Count

Summation counter of all PCIe correctable errors (Bad TLP, Bad DLLP, Receiver error, Replay timeouts, Replay rollovers). 8 bytes

C1 Log Page Data Output Explanation

Field Description

Host Read Commands

Number of host read commands received during the reporting period.

Host Read Blocks

Number of 512-byte blocks requested during the reporting period.

Average Read Size

Average Read size is calculated using (Host Read Blocks/Host Read Commands).

Host Read Cache Hit Commands

Number of host read commands that serviced entirely from the on-board read cache during the reporting period. No access to the NAND flash memory was required. This count is only updated if the entire command was serviced from the cache memory.

Host Read Cache Hit Percentage

Percentage of host read commands satisfied from the cache.

Host Read Cache Hit Blocks

Number of 512-byte blocks of data that have been returned for Host Read Cache Hit Commands during the reporting period. This count is only updated with the blocks returned for host read commands that were serviced entirely from cache memory.

Average Read Cache Hit Size

Average size of read commands satisfied from the cache.

Host Read Commands Stalled

Number of host read commands that were stalled due to a lack of resources within the SSD during the reporting period (NAND flash command queue full, low cache page count, cache page contention, etc.). Commands are not considered stalled if the only reason for the delay was waiting for the data to be physically read from the NAND flash. It is normal to expect this count to equal zero on heavily utilized systems.

Host Read Commands Stalled Percentage

Percentage of read commands that were stalled. If the figure is consistently high, then consideration should be given to spreading the data across multiple SSDs.

Host Write Commands

Number of host write commands received during the reporting period.

Host Write Blocks

Number of 512-byte blocks written during the reporting period.

Average Write Size

Average Write size calculated using (Host Write Blocks/Host Write Commands).

Host Write Odd Start Commands

Number of host write commands that started on a non-aligned boundary during the reporting period. The size of the boundary alignment is normally 4K; therefore this returns the number of commands that started on a non-4K aligned boundary. The SSD requires slightly more time to process non-aligned write commands than it does to process aligned write commands.

Host Write Odd Start Commands Percentage

Percentage of host write commands that started on a non-aligned boundary. If this figure is equal to or near 100%, and the NAND Read Before Write value is also high, then the user should investigate the possibility of offsetting the file system. For Microsoft Windows systems, the user can use Diskpart. For Unix-based operating systems, there is normally a method whereby file system partitions can be placed where required.

Host Write Odd End Commands

Number of host write commands that ended on a non-aligned boundary during the reporting period. The size of the boundary alignment is normally 4K; therefore this returns the number of commands that ended on a non-4K aligned boundary.

Host Write Odd End Commands Percentage

Percentage of host write commands that ended on a non-aligned boundary.

Host Write Commands Stalled

Number of host write commands that were stalled due to a lack of resources within the SSD during the reporting period. The most likely cause is that the write data was being received faster than it could be saved to the NAND flash memory. If there was a large volume of read commands being processed simultaneously, then other causes might include the NAND flash command queue being full, low cache page count, or cache page contention, etc. It is normal to expect this count to be non-zero on heavily utilized systems.

Host Write Commands Stalled Percentage

Percentage of write commands that were stalled. If the figure is consistently high, then consideration should be given to spreading the data across multiple SSDs.

NAND Read Commands

Number of read commands issued to the NAND devices during the reporting period. This figure will normally be much higher than the host read commands figure, as the data needed to satisfy a single host read command may be spread across several NAND flash devices.

NAND Read Blocks

Number of 512-byte blocks requested from NAND flash devices during the reporting period. This figure would normally be about the same as the host read blocks figure

Average NAND Read Size

Average size of NAND read commands.

NAND Write Commands

Number of write commands issued to the NAND devices during the reporting period. There is no real correlation between the number of host write commands issued and the number of NAND Write Commands.

NAND Write Blocks

Number of 512-byte blocks written to the NAND flash devices during the reporting period. This figure would normally be about the same as the host write blocks figure.

Average NAND Write Size

Average size of NAND write commands. This figure should never be greater than 128K, as this is the maximum size write that is ever issued to a NAND device.

NAND Read Before Write

This is the number of read before write operations that were required to process non-aligned host write commands during the reporting period. See Host Write Odd Start Commands and Host Write Odd End Commands. NAND Read Before Write operations have a detrimental effect on the overall performance of the device.

EXAMPLES

  • Has the program issue WDC smart-add-log Vendor Unique Command with default interval (14) :

    # nvme wdc smart-add-log /dev/nvme0

NVME

Part of the nvme-user suite.


nvme-cli-1.5/Documentation/nvme-wdc-smart-add-log.txt000066400000000000000000000237011322317423600226220ustar00rootroot00000000000000nvme-wdc-smart-add-log(1) ========================= NAME ---- nvme-wdc-smart-add-log - Send NVMe WDC smart-add-log Vendor Unique Command, return result SYNOPSIS -------- [verse] 'nvme wdc smart-add-log' [--interval=, -i ] [--output-format= -o ] DESCRIPTION ----------- For the NVMe device given, send a Vendor Unique WDC smart-add-log command and provide the additional smart log. The --interval option will return performance statistics from the specified reporting interval. The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0). This will only work on WDC devices supporting this feature. Results for any other device are undefined. On success it returns 0, error code otherwise. OPTIONS ------- -i :: --interval=:: Return the statistics from specific interval, defaults to 14 -o :: --output-format=:: Set the reporting format to 'human', or 'json'. Only one output format can be used at a time. Default is human. Valid Interval values and description :- [cols="2*", frame="topbot", align="center", options="header"] |=== |Value |Description |*1* |Most recent five (5) minute accumulated set. |*2-12* |Previous five (5) minute accumulated sets. |*13* |The accumulated total of sets 1 through 12 that contain the previous hour of accumulated statistics. |*14* |The statistical set accumulated since power-up. |*15* |The statistical set accumulated during the entire lifetime of the device. |=== CA Log Page Data Output Explanation ----------------------------------- [cols="2*", frame="topbot", align="center", options="header"] |=== |Field |Description |*Physical NAND bytes written.* |The number of bytes written to NAND. 16 bytes - hi/lo |*Physical NAND bytes read* |The number of bytes read from NAND. 16 bytes - hi/lo |*Bad NAND Block Count* |Raw and normalized count of the number of NAND blocks that have been retired after the drives manufacturing tests (i.e. grown back blocks). 2 bytes normalized, 6 bytes raw count |*Uncorrectable Read Error Count* |Total count of NAND reads that were not correctable by read retries, all levels of ECC, or XOR (as applicable). 8 bytes |*Soft ECC Error Count* |Total count of NAND reads that were not correctable by read retries, or first-level ECC. 8 bytes |*SSD End to End Detection Count* |A count of the detected errors by the SSD end to end error correction which includes DRAM, SRAM, or other storage element ECC/CRC protection mechanism (not NAND ECC). 4 bytes |*SSD End to End Correction Count* |A count of the corrected errors by the SSD end to end error correction which includes DRAM, SRAM, or other storage element ECC/CRC protection mechanism (not NAND ECC). 4 bytes |*System Data % Used* |A normalized cumulative count of the number of erase cycles per block since leaving the factory for the system (FW and metadata) area. Starts at 0 and increments. 100 indicates that the estimated endurance has been consumed. |*User Data Max Erase Count* |The maximum erase count across all NAND blocks in the drive. 4 bytes |*User Data Min Erase Count* |The minimum erase count across all NAND blocks in the drive. 4 bytes |*Refresh Count* |A count of the number of blocks that have been re-allocated due to background operations only. 8 bytes |*Program Fail Count* |Raw and normalized count of total program failures. Normalized count starts at 100 and shows the percent of remaining allowable failures. 2 bytes normalized, 6 bytes raw count |*User Data Erase Fail Count* |Raw and normalized count of total erase failures in the user area. Normalized count starts at 100 and shows the percent of remaining allowable failures. 2 bytes normalized, 6 bytes raw count |*System Area Erase Fail Count* |Raw and normalized count of total erase failures in the system area. Normalized count starts at 100 and shows the percent of remaining allowable failures. 2 bytes normalized, 6 bytes raw count |*Thermal Throttling Status* |The current status of thermal throttling (enabled or disabled). 2 bytes |*Thermal Throttling Count* |A count of the number of thermal throttling events. 2 bytes |*PCIe Correctable Error Count* |Summation counter of all PCIe correctable errors (Bad TLP, Bad DLLP, Receiver error, Replay timeouts, Replay rollovers). 8 bytes |=== C1 Log Page Data Output Explanation ----------------------------------- [cols="2*", frame="topbot", align="center", options="header"] |=== |Field |Description |*Host Read Commands* |Number of host read commands received during the reporting period. |*Host Read Blocks* |Number of 512-byte blocks requested during the reporting period. |*Average Read Size* |Average Read size is calculated using (Host Read Blocks/Host Read Commands). |*Host Read Cache Hit Commands* |Number of host read commands that serviced entirely from the on-board read cache during the reporting period. No access to the NAND flash memory was required. This count is only updated if the entire command was serviced from the cache memory. |*Host Read Cache Hit Percentage* |Percentage of host read commands satisfied from the cache. |*Host Read Cache Hit Blocks* |Number of 512-byte blocks of data that have been returned for Host Read Cache Hit Commands during the reporting period. This count is only updated with the blocks returned for host read commands that were serviced entirely from cache memory. |*Average Read Cache Hit Size* |Average size of read commands satisfied from the cache. |*Host Read Commands Stalled* |Number of host read commands that were stalled due to a lack of resources within the SSD during the reporting period (NAND flash command queue full, low cache page count, cache page contention, etc.). Commands are not considered stalled if the only reason for the delay was waiting for the data to be physically read from the NAND flash. It is normal to expect this count to equal zero on heavily utilized systems. |*Host Read Commands Stalled Percentage* |Percentage of read commands that were stalled. If the figure is consistently high, then consideration should be given to spreading the data across multiple SSDs. |*Host Write Commands* |Number of host write commands received during the reporting period. |*Host Write Blocks* |Number of 512-byte blocks written during the reporting period. |*Average Write Size* |Average Write size calculated using (Host Write Blocks/Host Write Commands). |*Host Write Odd Start Commands* |Number of host write commands that started on a non-aligned boundary during the reporting period. The size of the boundary alignment is normally 4K; therefore this returns the number of commands that started on a non-4K aligned boundary. The SSD requires slightly more time to process non-aligned write commands than it does to process aligned write commands. |*Host Write Odd Start Commands Percentage* |Percentage of host write commands that started on a non-aligned boundary. If this figure is equal to or near 100%, and the NAND Read Before Write value is also high, then the user should investigate the possibility of offsetting the file system. For Microsoft Windows systems, the user can use Diskpart. For Unix-based operating systems, there is normally a method whereby file system partitions can be placed where required. |*Host Write Odd End Commands* |Number of host write commands that ended on a non-aligned boundary during the reporting period. The size of the boundary alignment is normally 4K; therefore this returns the number of commands that ended on a non-4K aligned boundary. |*Host Write Odd End Commands Percentage* |Percentage of host write commands that ended on a non-aligned boundary. |*Host Write Commands Stalled* |Number of host write commands that were stalled due to a lack of resources within the SSD during the reporting period. The most likely cause is that the write data was being received faster than it could be saved to the NAND flash memory. If there was a large volume of read commands being processed simultaneously, then other causes might include the NAND flash command queue being full, low cache page count, or cache page contention, etc. It is normal to expect this count to be non-zero on heavily utilized systems. |*Host Write Commands Stalled Percentage* |Percentage of write commands that were stalled. If the figure is consistently high, then consideration should be given to spreading the data across multiple SSDs. |*NAND Read Commands* |Number of read commands issued to the NAND devices during the reporting period. This figure will normally be much higher than the host read commands figure, as the data needed to satisfy a single host read command may be spread across several NAND flash devices. |*NAND Read Blocks* |Number of 512-byte blocks requested from NAND flash devices during the reporting period. This figure would normally be about the same as the host read blocks figure |*Average NAND Read Size* |Average size of NAND read commands. |*NAND Write Commands* |Number of write commands issued to the NAND devices during the reporting period. There is no real correlation between the number of host write commands issued and the number of NAND Write Commands. |*NAND Write Blocks* |Number of 512-byte blocks written to the NAND flash devices during the reporting period. This figure would normally be about the same as the host write blocks figure. |*Average NAND Write Size* |Average size of NAND write commands. This figure should never be greater than 128K, as this is the maximum size write that is ever issued to a NAND device. |*NAND Read Before Write* |This is the number of read before write operations that were required to process non-aligned host write commands during the reporting period. See Host Write Odd Start Commands and Host Write Odd End Commands. NAND Read Before Write operations have a detrimental effect on the overall performance of the device. |=== EXAMPLES -------- * Has the program issue WDC smart-add-log Vendor Unique Command with default interval (14) : + ------------ # nvme wdc smart-add-log /dev/nvme0 ------------ NVME ---- Part of the nvme-user suite. nvme-cli-1.5/Documentation/nvme-write-uncor.1000066400000000000000000000036751322317423600212230ustar00rootroot00000000000000'\" t .\" Title: nvme-uncor .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-UNCOR" "1" "12/10/2017" "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-write-uncor \- Send an NVMe write uncorrectable command, return results .SH "SYNOPSIS" .sp .nf \fInvme\-write\-uncorr\fR [\-\-start\-block= | \-s ] [\-\-block\-count= | \-c ] [\-\-namespace\-id= | \-n ] .fi .SH "DESCRIPTION" .sp The Write Uncorrectable command is used to invalidate a range of logical blocks\&. .SH "OPTIONS" .PP \-\-start\-block=, \-s .RS 4 Start block\&. .RE .PP \-\-block\-count=, \-c .RS 4 Number of logical blocks to write uncorrectable\&. .RE .PP \-\-namespace\-id=, \-n .RS 4 Namespace ID use in the command\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-write-uncor.html000066400000000000000000000434071322317423600220240ustar00rootroot00000000000000 nvme-uncor(1)

SYNOPSIS

nvme-write-uncorr <device> [--start-block=<slba> | -s <slba>]
                        [--block-count=<nlb> | -c <nlb>]
                        [--namespace-id=<nsid> | -n <nsid>]

DESCRIPTION

The Write Uncorrectable command is used to invalidate a range of logical blocks.

OPTIONS

--start-block=<slba>
-s <slba>

Start block.

--block-count=<nlb>
-c

Number of logical blocks to write uncorrectable.

--namespace-id=<nsid>
-n <nsid>

Namespace ID use in the command.

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-write-uncor.txt000066400000000000000000000012451322317423600216710ustar00rootroot00000000000000nvme-uncor(1) ============= NAME ---- nvme-write-uncor - Send an NVMe write uncorrectable command, return results SYNOPSIS -------- [verse] 'nvme-write-uncorr' [--start-block= | -s ] [--block-count= | -c ] [--namespace-id= | -n ] DESCRIPTION ----------- The Write Uncorrectable command is used to invalidate a range of logical blocks. OPTIONS ------- --start-block=:: -s :: Start block. --block-count=:: -c:: Number of logical blocks to write uncorrectable. --namespace-id=:: -n :: Namespace ID use in the command. EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-write-zeroes.1000066400000000000000000000070501322317423600213730ustar00rootroot00000000000000'\" t .\" Title: nvme-zeroes .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-ZEROES" "1" "12/10/2017" "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-write-zeroes \- Send an NVMe write zeroes command, return results .SH "SYNOPSIS" .sp .nf \fInvme\-write\-zeroes\fR [\-\-start\-block= | \-s ] [\-\-block\-count= | \-c ] [\-\-ref\-tag= | \-r ] [\-\-prinfo= | \-p ] [\-\-app\-tag\-mask= | \-m ] [\-\-app\-tag= | \-a ] [\-\-deac | \-d] [\-\-limited\-retry | \-l] [\-\-force\-unit\-access | \-f] [\-\-namespace\-id= | \-n ] .fi .SH "DESCRIPTION" .sp The Write Zeroes command is used to set a range of logical blocks to 0\&. .SH "OPTIONS" .PP \-\-start\-block=, \-s .RS 4 Start block\&. .RE .PP \-\-block\-count=, \-c .RS 4 Number of logical blocks to write zeroes\&. .RE .PP \-\-prinfo=, \-p .RS 4 Protection Information field defintion\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt. T{ Bit T}:T{ Description T} T{ 3 T}:T{ PRACT: Protection Information Action\&. When set to 1, PI is stripped/inserted on read/write when the block format\(cqs metadata size is 8\&. When set to 0, metadata is passes\&. T} T{ 2:0 T}:T{ PRCHK: Protection Information Check: T} T{ 2 T}:T{ Set to 1 enables checking the guard tag T} T{ 1 T}:T{ Set to 1 enables checking the application tag T} T{ 0 T}:T{ Set to 1 enables checking the reference tag T} .TE .sp 1 .RE .PP \-\-ref\-tag=, \-r .RS 4 Optional reftag when used with protection information\&. .RE .PP \-\-app\-tag\-mask=, \-m .RS 4 Optional application tag mask when used with protection information\&. .RE .PP \-\-app\-tag=, \-a .RS 4 Optional application tag when used with protection information\&. .RE .PP \-\-limited\-retry, \-l .RS 4 Sets the limited retry flag\&. .RE .PP \-\-deac, \-d .RS 4 Sets the DEAC bit, requesting controller deallocate the logical blocks\&. .RE .PP \-\-force\-unit\-access, \-f .RS 4 Set the force\-unit access flag\&. .RE .PP \-\-namespace\-id=, \-n .RS 4 Namespace ID use in the command\&. .RE .sp EXAMPLES EXAMPLES .sp .if n \{\ .RS 4 .\} .nf No examples yet\&. NVME .fi .if n \{\ .RE .\} .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-write-zeroes.html000066400000000000000000000511561322317423600222050ustar00rootroot00000000000000 nvme-zeroes(1)

SYNOPSIS

nvme-write-zeroes <device> [--start-block=<slba> | -s <slba>]
                        [--block-count=<nlb> | -c <nlb>]
                        [--ref-tag=<reftag> | -r <reftag>]
                        [--prinfo=<prinfo> | -p <prinfo>]
                        [--app-tag-mask=<appmask> | -m <appmask>]
                        [--app-tag=<apptag> | -a <apptag>]
                        [--deac | -d]
                        [--limited-retry | -l]
                        [--force-unit-access | -f]
                        [--namespace-id=<nsid> | -n <nsid>]

DESCRIPTION

The Write Zeroes command is used to set a range of logical blocks to 0.

OPTIONS

--start-block=<slba>
-s <slba>

Start block.

--block-count=<nlb>
-c <nlb>

Number of logical blocks to write zeroes.

--prinfo=<prinfo>
-p <prinfo>

Protection Information field defintion.

Bit

Description

3

PRACT: Protection Information Action. When set to 1, PI is stripped/inserted on read/write when the block format’s metadata size is 8. When set to 0, metadata is passes.

2:0

PRCHK: Protection Information Check:

2

Set to 1 enables checking the guard tag

1

Set to 1 enables checking the application tag

0

Set to 1 enables checking the reference tag

--ref-tag=<reftag>
-r <reftag>

Optional reftag when used with protection information.

--app-tag-mask=<appmask>
-m <appmask>

Optional application tag mask when used with protection information.

--app-tag=<apptag>
-a <apptag>

Optional application tag when used with protection information.

--limited-retry
-l

Sets the limited retry flag.

--deac
-d

Sets the DEAC bit, requesting controller deallocate the logical blocks.

--force-unit-access
-f

Set the force-unit access flag.

--namespace-id=<nsid>
-n <nsid>

Namespace ID use in the command.

EXAMPLES EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-write-zeroes.txt000066400000000000000000000035561322317423600220610ustar00rootroot00000000000000nvme-zeroes(1) ============== NAME ---- nvme-write-zeroes - Send an NVMe write zeroes command, return results SYNOPSIS -------- [verse] 'nvme-write-zeroes' [--start-block= | -s ] [--block-count= | -c ] [--ref-tag= | -r ] [--prinfo= | -p ] [--app-tag-mask= | -m ] [--app-tag= | -a ] [--deac | -d] [--limited-retry | -l] [--force-unit-access | -f] [--namespace-id= | -n ] DESCRIPTION ----------- The Write Zeroes command is used to set a range of logical blocks to 0. OPTIONS ------- --start-block=:: -s :: Start block. --block-count=:: -c :: Number of logical blocks to write zeroes. --prinfo=:: -p :: Protection Information field defintion. + [] |================= |Bit|Description |3|PRACT: Protection Information Action. When set to 1, PI is stripped/inserted on read/write when the block format's metadata size is 8. When set to 0, metadata is passes. |2:0|PRCHK: Protection Information Check: |2|Set to 1 enables checking the guard tag |1|Set to 1 enables checking the application tag |0|Set to 1 enables checking the reference tag |================= --ref-tag=:: -r :: Optional reftag when used with protection information. --app-tag-mask=:: -m :: Optional application tag mask when used with protection information. --app-tag=:: -a :: Optional application tag when used with protection information. --limited-retry:: -l:: Sets the limited retry flag. --deac:: -d:: Sets the DEAC bit, requesting controller deallocate the logical blocks. --force-unit-access:: -f:: Set the force-unit access flag. --namespace-id=:: -n :: Namespace ID use in the command. EXAMPLES EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme-write.1000066400000000000000000000125171322317423600200720ustar00rootroot00000000000000'\" t .\" Title: nvme-write .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 12/13/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME\-WRITE" "1" "12/13/2017" "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-write \- Send an NVMe write command, provide results .SH "SYNOPSIS" .sp .nf \fInvme\-write\fR [\-\-start\-block= | \-s ] [\-\-block\-count= | \-c ] [\-\-data\-size= | \-z ] [\-\-metadata\-size= | \-y ] [\-\-data= | \-d ] [\-\-metadata= | \-M ] [\-\-prinfo= | \-p ] [\-\-ref\-tag= | \-r ] [\-\-app\-tag\-mask= | \-m ] [\-\-app\-tag= | \-a ] [\-\-dtype= | \-T ] [\-\-dspec= | \-S ] [\-\-dsm= | \-D ] [\-\-limited\-retry | \-l] [\-\-latency | \-t] [\-\-force\-unit\-access | \-f] .fi .SH "DESCRIPTION" .sp The Write command writes the logical blocks specified by the command to the medium from the data data buffer provided\&. Will use stdin by default if you don\(cqt provide a file\&. .SH "OPTIONS" .PP \-\-start\-block=, \-s .RS 4 Start block\&. .RE .PP \-\-block\-count, \-c .RS 4 The number of blocks to transfer\&. This is a zeroes based value to align with the kernel\(cqs use of this field\&. (ie\&. 0 means transfer 1 block)\&. .RE .PP \-\-data\-size=, \-z .RS 4 Size of data, in bytes\&. .RE .PP \-\-metadata\-size=, \-y .RS 4 Size of metadata in bytes\&. .RE .PP \-\-data=, \-d .RS 4 Data file\&. If none provided, contents are sent from STDIN\&. .RE .PP \-\-metadata=, \-M .RS 4 Metadata file, if necessary\&. .RE .PP \-\-prinfo=, \-p .RS 4 Protection Information field defintion\&. .TS allbox tab(:); lt lt lt lt lt lt lt lt lt lt lt lt. T{ Bit T}:T{ Description T} T{ 3 T}:T{ PRACT: Protection Information Action\&. When set to 1, PI is stripped/inserted on read/write when the block format\(cqs metadata size is 8\&. When set to 0, metadata is passes\&. T} T{ 2:0 T}:T{ PRCHK: Protection Information Check: T} T{ 2 T}:T{ Set to 1 enables checking the guard tag T} T{ 1 T}:T{ Set to 1 enables checking the application tag T} T{ 0 T}:T{ Set to 1 enables checking the reference tag T} .TE .sp 1 .RE .PP \-\-dtype=, \-T .RS 4 Optional directive type\&. The nvme\-cli only enforces the value be in the defined range for the directive type, though the NVMe specifcation (1\&.3a) defines only one directive, 01h, for write stream idenfiers\&. .RE .PP \-\-dspec=, \-S .RS 4 Optional field for directive specifics\&. When used with write streams, this value is defined to be the write stream identifier\&. The nvme\-cli will not validate the stream requested is within the controller\(cqs capabilities\&. .RE .PP \-\-dsm=, \-D .RS 4 The optional data set management attributes for this command\&. The argument for this is the lower 16 bits of the DSM field in a write command; the upper 16 bits of the field come from the directive specific field, if used\&. This may be used to set attributes for the LBAs being written, like access frequency, type, latency, among other things, as well as yet to be defined types\&. Please consult the NVMe specification for detailed breakdown of how to use this field\&. .RE .PP \-\-ref\-tag=, \-r .RS 4 Optional reftag when used with protection information\&. .RE .PP \-\-app\-tag\-mask=, \-m .RS 4 Optional application tag mask when used with protection information\&. .RE .PP \-\-app\-tag=, \-a .RS 4 Optional application tag when used with protection information\&. .RE .PP \-\-limited\-retry, \-l .RS 4 Sets the limited retry flag\&. .RE .PP \-\-force\-unit\-access, \-f .RS 4 Set the force\-unit access flag\&. .RE .PP \-\-latency, \-t .RS 4 Print out the latency the IOCTL took (in us)\&. .RE .SH "EXAMPLES" .sp No examples yet\&. .SH "NVME" .sp Part of the nvme\-user suite nvme-cli-1.5/Documentation/nvme-write.html000066400000000000000000000562341322317423600207020ustar00rootroot00000000000000 nvme-write(1)

SYNOPSIS

nvme-write <device> [--start-block=<slba> | -s <slba>]
                        [--block-count=<nlb> | -c <nlb>]
                        [--data-size=<size> | -z <size>]
                        [--metadata-size=<size> | -y <size>]
                        [--data=<data-file> | -d <data-file>]
                        [--metadata=<metadata-file> | -M <metadata-file>]
                        [--prinfo=<prinfo> | -p <prinfo>]
                        [--ref-tag=<reftag> | -r <reftag>]
                        [--app-tag-mask=<appmask> | -m <appmask>]
                        [--app-tag=<apptag> | -a <apptag>]
                        [--dtype=<dtype> | -T <dtype>]
                        [--dspec=<dspec> | -S <dspec>]
                        [--dsm=<dsm> | -D <dsm>]
                        [--limited-retry | -l]
                        [--latency | -t]
                        [--force-unit-access | -f]

DESCRIPTION

The Write command writes the logical blocks specified by the command to the medium from the data data buffer provided. Will use stdin by default if you don’t provide a file.

OPTIONS

--start-block=<slba>
-s <slba>

Start block.

--block-count
-c

The number of blocks to transfer. This is a zeroes based value to align with the kernel’s use of this field. (ie. 0 means transfer 1 block).

--data-size=<size>
-z <size>

Size of data, in bytes.

--metadata-size=<size>
-y <size>

Size of metadata in bytes.

--data=<data-file>
-d <data-file>

Data file. If none provided, contents are sent from STDIN.

--metadata=<metadata-file>
-M <metadata-file>

Metadata file, if necessary.

--prinfo=<prinfo>
-p <prinfo>

Protection Information field defintion.

Bit

Description

3

PRACT: Protection Information Action. When set to 1, PI is stripped/inserted on read/write when the block format’s metadata size is 8. When set to 0, metadata is passes.

2:0

PRCHK: Protection Information Check:

2

Set to 1 enables checking the guard tag

1

Set to 1 enables checking the application tag

0

Set to 1 enables checking the reference tag

--dtype=<dtype>
-T <dtype>

Optional directive type. The nvme-cli only enforces the value be in the defined range for the directive type, though the NVMe specifcation (1.3a) defines only one directive, 01h, for write stream idenfiers.

--dspec=<dspec>
-S <dspec>

Optional field for directive specifics. When used with write streams, this value is defined to be the write stream identifier. The nvme-cli will not validate the stream requested is within the controller’s capabilities.

--dsm=<dsm>
-D <dsm>

The optional data set management attributes for this command. The argument for this is the lower 16 bits of the DSM field in a write command; the upper 16 bits of the field come from the directive specific field, if used. This may be used to set attributes for the LBAs being written, like access frequency, type, latency, among other things, as well as yet to be defined types. Please consult the NVMe specification for detailed breakdown of how to use this field.

--ref-tag=<reftag>
-r <reftag>

Optional reftag when used with protection information.

--app-tag-mask=<appmask>
-m <appmask>

Optional application tag mask when used with protection information.

--app-tag=<apptag>
-a <apptag>

Optional application tag when used with protection information.

--limited-retry
-l

Sets the limited retry flag.

--force-unit-access
-f

Set the force-unit access flag.

--latency
-t

Print out the latency the IOCTL took (in us).

EXAMPLES

No examples yet.

NVME

Part of the nvme-user suite


nvme-cli-1.5/Documentation/nvme-write.txt000066400000000000000000000066561322317423600205600ustar00rootroot00000000000000nvme-write(1) ============= NAME ---- nvme-write - Send an NVMe write command, provide results SYNOPSIS -------- [verse] 'nvme-write' [--start-block= | -s ] [--block-count= | -c ] [--data-size= | -z ] [--metadata-size= | -y ] [--data= | -d ] [--metadata= | -M ] [--prinfo= | -p ] [--ref-tag= | -r ] [--app-tag-mask= | -m ] [--app-tag= | -a ] [--dtype= | -T ] [--dspec= | -S ] [--dsm= | -D ] [--limited-retry | -l] [--latency | -t] [--force-unit-access | -f] DESCRIPTION ----------- The Write command writes the logical blocks specified by the command to the medium from the data data buffer provided. Will use stdin by default if you don't provide a file. OPTIONS ------- --start-block=:: -s :: Start block. --block-count:: -c:: The number of blocks to transfer. This is a zeroes based value to align with the kernel's use of this field. (ie. 0 means transfer 1 block). --data-size=:: -z :: Size of data, in bytes. --metadata-size=:: -y :: Size of metadata in bytes. --data=:: -d :: Data file. If none provided, contents are sent from STDIN. --metadata=:: -M :: Metadata file, if necessary. --prinfo=:: -p :: Protection Information field defintion. + [] |================= |Bit|Description |3|PRACT: Protection Information Action. When set to 1, PI is stripped/inserted on read/write when the block format's metadata size is 8. When set to 0, metadata is passes. |2:0|PRCHK: Protection Information Check: |2|Set to 1 enables checking the guard tag |1|Set to 1 enables checking the application tag |0|Set to 1 enables checking the reference tag |================= --dtype=:: -T :: Optional directive type. The nvme-cli only enforces the value be in the defined range for the directive type, though the NVMe specifcation (1.3a) defines only one directive, 01h, for write stream idenfiers. --dspec=:: -S :: Optional field for directive specifics. When used with write streams, this value is defined to be the write stream identifier. The nvme-cli will not validate the stream requested is within the controller's capabilities. --dsm=:: -D :: The optional data set management attributes for this command. The argument for this is the lower 16 bits of the DSM field in a write command; the upper 16 bits of the field come from the directive specific field, if used. This may be used to set attributes for the LBAs being written, like access frequency, type, latency, among other things, as well as yet to be defined types. Please consult the NVMe specification for detailed breakdown of how to use this field. --ref-tag=:: -r :: Optional reftag when used with protection information. --app-tag-mask=:: -m :: Optional application tag mask when used with protection information. --app-tag=:: -a :: Optional application tag when used with protection information. --limited-retry:: -l:: Sets the limited retry flag. --force-unit-access:: -f:: Set the force-unit access flag. --latency:: -t:: Print out the latency the IOCTL took (in us). EXAMPLES -------- No examples yet. NVME ---- Part of the nvme-user suite nvme-cli-1.5/Documentation/nvme.1000066400000000000000000000116741322317423600167450ustar00rootroot00000000000000'\" t .\" Title: nvme .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 12/10/2017 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" .TH "NVME" "1" "12/10/2017" "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 \- the dumb pci\-e storage utility .SH "SYNOPSIS" .sp .nf \fInvme\fR [] .fi .SH "DESCRIPTION" .sp NVM\-Express is a fast, scalable host controller interface designed to address the needs for PCI Express based solid state drives\&. .sp This \fInvme\fR program is a user space utility to provide standards compliant tooling for NVM\-Express drives\&. It was made specifically for Linux as it relies on the IOCTLs defined by the mainline kernel driver\&. .SH "NVME COMMANDS" .sp The utility has sub\-commands for all admin and io commands defined in the specification and for displaying controller registers\&. There is also an option to submit completely arbitrary commands\&. For a list of commands available, run "nvme help"\&. .SH "NVME CLI SUB\-COMMANDS" .SS "Main commands" .PP \fBnvme-admin-passthru\fR(1) .RS 4 Admin Passthrough Command .RE .PP \fBnvme-compare\fR(1) .RS 4 IO Compare .RE .PP \fBnvme-error-log\fR(1) .RS 4 Retrieve error logs .RE .PP \fBnvme-flush\fR(1) .RS 4 Submit flush .RE .PP \fBnvme-dms\fR(1) .RS 4 Submit Data Set Management .RE .PP \fBnvme-format\fR(1) .RS 4 Format namespace(s) .RE .PP \fBnvme-fw-activate\fR(1) .RS 4 F/W Activate .RE .PP \fBnvme-fw-download\fR(1) .RS 4 F/W Download .RE .PP \fBnvme-fw-log\fR(1) .RS 4 Retrieve f/w log .RE .PP \fBnvme-get-feature\fR(1) .RS 4 Get Features .RE .PP \fBnvme-get-log\fR(1) .RS 4 Generic Get Log .RE .PP \fBnvme-smart-log\fR(1) .RS 4 Retrieve Smart Log .RE .PP \fBnvme-get-ns-id\fR(1) .RS 4 Retrieve namespace identifier .RE .PP \fBnvme-help\fR(1) .RS 4 NVMe CLI Help .RE .PP \fBnvme-id-ctrl\fR(1) .RS 4 Identify Controller .RE .PP \fBnvme-id-ns\fR(1) .RS 4 Identify Namespace .RE .PP \fBnvme-create-ns\fR(1) .RS 4 Create a new namespace .RE .PP \fBnvme-delete-ns\fR(1) .RS 4 Delete existing namespace .RE .PP \fBnvme-attach-ns\fR(1) .RS 4 Attach namespace .RE .PP \fBnvme-detach-ns\fR(1) .RS 4 Detach namespace .RE .PP \fBnvme-io-passthru\fR(1) .RS 4 IO Passthrough Command .RE .PP \fBnvme-list-ns\fR(1) .RS 4 List all nvme namespaces .RE .PP \fBnvme-list\fR(1) .RS 4 List all nvme controllers .RE .PP \fBnvme-list-ctrl\fR(1) .RS 4 List controller in NVMe subsystem .RE .PP \fBnvme-read\fR(1) .RS 4 Issue IO Read Command .RE .PP \fBnvme-write\fR(1) .RS 4 Issue IO Write Command .RE .PP \fBnvme-write-zeroes\fR(1) .RS 4 Issue IO Write Zeroes Command .RE .PP \fBnvme-write-uncor\fR(1) .RS 4 Issue IO Write Uncorrectable Command .RE .PP \fBnvme-resv-acquire\fR(1) .RS 4 Acquire Namespace Reservation .RE .PP \fBnvme-resv-register\fR(1) .RS 4 Register Namespace Reservation .RE .PP \fBnvme-resv-release\fR(1) .RS 4 Release Namespace Reservation .RE .PP \fBnvme-resv-report\fR(1) .RS 4 Report Reservation Capabilities .RE .PP \fBnvme-security-recv\fR(1) .RS 4 Security Receive .RE .PP \fBnvme-security-send\fR(1) .RS 4 Security Send .RE .PP \fBnvme-set-feature\fR(1) .RS 4 Set Feature .RE .PP \fBnvme-show-regs\fR(1) .RS 4 Show NVMe Controller Registers .RE .PP \fBnvme-discover\fR(1) .RS 4 Send Get Log Page request to Discovery Controller .RE .PP \fBnvme-connect\fR(1) .RS 4 Connect to an NVMe\-over\-Fabrics subsystem .RE .SH "FURTHER DOCUMENTATION" .sp See the freely available references on the \m[blue]\fBOfficial NVM\-Express Site\fR\m[]\&\s-2\u[1]\d\s+2\&. .SH "AUTHORS" .sp This is written and maintained by \m[blue]\fBKeith Busch\fR\m[]\&\s-2\u[2]\d\s+2\&. .SH "REPORTING BUGS" .sp Patches and issues may be submitted to the official repository at \m[blue]\fBhttps://github\&.com/linux\-nvme/nvme\-cli\fR\m[] or the Linux NVMe mailing list \m[blue]\fBlinux\-nvme\fR\m[]\&\s-2\u[3]\d\s+2 .SH "NVME" .sp Part of the nvme suite .SH "NOTES" .IP " 1." 4 Official NVM-Express Site .RS 4 \%http://nvmexpress.org .RE .IP " 2." 4 Keith Busch .RS 4 \%mailto:keith.busch@intel.com .RE .IP " 3." 4 linux-nvme .RS 4 \%mailto:linux-nvme@lists.infradead.org .RE nvme-cli-1.5/Documentation/nvme.html000066400000000000000000000572541322317423600175550ustar00rootroot00000000000000 nvme(1)

SYNOPSIS

nvme <command> <device> [<args>]

DESCRIPTION

NVM-Express is a fast, scalable host controller interface designed to address the needs for PCI Express based solid state drives.

This nvme program is a user space utility to provide standards compliant tooling for NVM-Express drives. It was made specifically for Linux as it relies on the IOCTLs defined by the mainline kernel driver.

NVME COMMANDS

The utility has sub-commands for all admin and io commands defined in the specification and for displaying controller registers. There is also an option to submit completely arbitrary commands. For a list of commands available, run "nvme help".

nvme cli sub-commands

Main commands

nvme-admin-passthru(1)

Admin Passthrough Command

nvme-compare(1)

IO Compare

nvme-error-log(1)

Retrieve error logs

nvme-flush(1)

Submit flush

nvme-dms(1)

Submit Data Set Management

nvme-format(1)

Format namespace(s)

nvme-fw-activate(1)

F/W Activate

nvme-fw-download(1)

F/W Download

nvme-fw-log(1)

Retrieve f/w log

nvme-get-feature(1)

Get Features

nvme-get-log(1)

Generic Get Log

nvme-smart-log(1)

Retrieve Smart Log

nvme-get-ns-id(1)

Retrieve namespace identifier

nvme-help(1)

NVMe CLI Help

nvme-id-ctrl(1)

Identify Controller

nvme-id-ns(1)

Identify Namespace

nvme-create-ns(1)

Create a new namespace

nvme-delete-ns(1)

Delete existing namespace

nvme-attach-ns(1)

Attach namespace

nvme-detach-ns(1)

Detach namespace

nvme-io-passthru(1)

IO Passthrough Command

nvme-list-ns(1)

List all nvme namespaces

nvme-list(1)

List all nvme controllers

nvme-list-ctrl(1)

List controller in NVMe subsystem

nvme-read(1)

Issue IO Read Command

nvme-write(1)

Issue IO Write Command

nvme-write-zeroes(1)

Issue IO Write Zeroes Command

nvme-write-uncor(1)

Issue IO Write Uncorrectable Command

nvme-resv-acquire(1)

Acquire Namespace Reservation

nvme-resv-register(1)

Register Namespace Reservation

nvme-resv-release(1)

Release Namespace Reservation

nvme-resv-report(1)

Report Reservation Capabilities

nvme-security-recv(1)

Security Receive

nvme-security-send(1)

Security Send

nvme-set-feature(1)

Set Feature

nvme-show-regs(1)

Show NVMe Controller Registers

nvme-discover(1)

Send Get Log Page request to Discovery Controller

nvme-connect(1)

Connect to an NVMe-over-Fabrics subsystem

FURTHER DOCUMENTATION

See the freely available references on the Official NVM-Express Site.

Authors

This is written and maintained by Keith Busch.

Reporting Bugs

Patches and issues may be submitted to the official repository at https://github.com/linux-nvme/nvme-cli or the Linux NVMe mailing list linux-nvme

NVME

Part of the nvme suite


nvme-cli-1.5/Documentation/nvme.txt000066400000000000000000000025051322317423600174150ustar00rootroot00000000000000nvme(1) ======= NAME ---- nvme - the dumb pci-e storage utility SYNOPSIS -------- [verse] 'nvme' [] DESCRIPTION ----------- NVM-Express is a fast, scalable host controller interface designed to address the needs for PCI Express based solid state drives. This 'nvme' program is a user space utility to provide standards compliant tooling for NVM-Express drives. It was made specifically for Linux as it relies on the IOCTLs defined by the mainline kernel driver. NVME COMMANDS ------------- The utility has sub-commands for all admin and io commands defined in the specification and for displaying controller registers. There is also an option to submit completely arbitrary commands. For a list of commands available, run "nvme help". nvme cli sub-commands --------------------- Main commands ~~~~~~~~~~~~~ include::cmds-main.txt[] FURTHER DOCUMENTATION --------------------- See the freely available references on the http://nvmexpress.org[Official NVM-Express Site]. Authors ------- This is written and maintained by mailto:keith.busch@intel.com[Keith Busch]. Reporting Bugs -------------- Patches and issues may be submitted to the official repository at https://github.com/linux-nvme/nvme-cli or the Linux NVMe mailing list mailto:linux-nvme@lists.infradead.org[linux-nvme] NVME ---- Part of the nvme suite nvme-cli-1.5/LICENSE000066400000000000000000000431531322317423600141070ustar00rootroot00000000000000GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {description} Copyright (C) {year} {fullname} This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. {signature of Ty Coon}, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. nvme-cli-1.5/Makefile000066400000000000000000000105341322317423600145370ustar00rootroot00000000000000CFLAGS ?= -O2 -g -Wall -Werror CFLAGS += -std=gnu99 CPPFLAGS += -D_GNU_SOURCE -D__CHECK_ENDIAN__ LIBUUID = $(shell $(LD) -o /dev/null -luuid >/dev/null 2>&1; echo $$?) NVME = nvme INSTALL ?= install DESTDIR = PREFIX ?= /usr/local SYSCONFDIR = /etc SBINDIR = $(PREFIX)/sbin LIB_DEPENDS = ifeq ($(LIBUUID),0) override LDFLAGS += -luuid override CFLAGS += -DLIBUUID override LIB_DEPENDS += uuid endif RPMBUILD = rpmbuild TAR = tar RM = rm -f AUTHOR=Keith Busch default: $(NVME) NVME-VERSION-FILE: FORCE @$(SHELL_PATH) ./NVME-VERSION-GEN -include NVME-VERSION-FILE override CFLAGS += -DNVME_VERSION='"$(NVME_VERSION)"' NVME_DPKG_VERSION=1~`lsb_release -sc` OBJS := argconfig.o suffix.o parser.o nvme-print.o nvme-ioctl.o \ nvme-lightnvm.o fabrics.o json.o plugin.o intel-nvme.o \ lnvm-nvme.o memblaze-nvme.o wdc-nvme.o nvme-models.o huawei-nvme.o nvme: nvme.c nvme.h $(OBJS) NVME-VERSION-FILE $(CC) $(CPPFLAGS) $(CFLAGS) nvme.c -o $(NVME) $(OBJS) $(LDFLAGS) nvme.o: nvme.c nvme.h nvme-print.h nvme-ioctl.h argconfig.h suffix.h nvme-lightnvm.h fabrics.h $(CC) $(CPPFLAGS) $(CFLAGS) -c $< %.o: %.c %.h nvme.h linux/nvme_ioctl.h $(CC) $(CPPFLAGS) $(CFLAGS) -c $< doc: $(NVME) $(MAKE) -C Documentation test: $(MAKE) -C tests/ run all: doc clean: $(RM) $(NVME) *.o *~ a.out NVME-VERSION-FILE *.tar* nvme.spec version control nvme-*.deb $(MAKE) -C Documentation clean $(RM) tests/*.pyc clobber: clean $(MAKE) -C Documentation clobber install-man: $(MAKE) -C Documentation install-no-build install-bin: default $(INSTALL) -d $(DESTDIR)$(SBINDIR) $(INSTALL) -m 755 nvme $(DESTDIR)$(SBINDIR) install-bash-completion: $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/bash_completion.d $(INSTALL) -m 644 -T ./completions/bash-nvme-completion.sh $(DESTDIR)$(PREFIX)/share/bash_completion.d/nvme install: install-bin install-man install-bash-completion nvme.spec: nvme.spec.in NVME-VERSION-FILE sed -e 's/@@VERSION@@/$(NVME_VERSION)/g' < $< > $@+ mv $@+ $@ dist: nvme.spec git archive --format=tar --prefix=nvme-$(NVME_VERSION)/ HEAD > nvme-$(NVME_VERSION).tar @echo $(NVME_VERSION) > version $(TAR) rf nvme-$(NVME_VERSION).tar nvme.spec version gzip -f -9 nvme-$(NVME_VERSION).tar control: nvme.control.in NVME-VERSION-FILE sed -e 's/@@VERSION@@/$(NVME_VERSION)/g' < $< > $@+ mv $@+ $@ sed -e 's/@@DEPENDS@@/$(LIB_DEPENDS)/g' < $@ > $@+ mv $@+ $@ pkg: control nvme.control.in mkdir -p nvme-$(NVME_VERSION)$(SBINDIR) mkdir -p nvme-$(NVME_VERSION)$(PREFIX)/share/man/man1 mkdir -p nvme-$(NVME_VERSION)/DEBIAN/ cp Documentation/*.1 nvme-$(NVME_VERSION)$(PREFIX)/share/man/man1 cp nvme nvme-$(NVME_VERSION)$(SBINDIR) cp control nvme-$(NVME_VERSION)/DEBIAN/ # Make a reproducible tar.gz in the super-directory. Uses # git-restore-mtime if available to adjust timestamps. ../nvme-cli_$(NVME_VERSION).orig.tar.gz: find . -type f -perm -u+rwx -exec chmod 0755 '{}' + find . -type f -perm -u+rw '!' -perm -u+x -exec chmod 0644 '{}' + if which git-restore-mtime >/dev/null; then git-restore-mtime; fi git ls-files | tar cf ../nvme-cli_$(NVME_VERSION).orig.tar \ --owner=root --group=root \ --transform='s#^#nvme-cli-$(NVME_VERSION)/#' --files-from - touch -d "`git log --format=%ci -1`" ../nvme-cli_$(NVME_VERSION).orig.tar gzip -f -9 ../nvme-cli_$(NVME_VERSION).orig.tar dist-orig: ../nvme-cli_$(NVME_VERSION).orig.tar.gz # Create a throw-away changelog, which dpkg-buildpackage uses to # determine the package version. deb-changelog: printf '%s\n\n * Auto-release.\n\n %s\n' \ "nvme-cli ($(NVME_VERSION)-$(NVME_DPKG_VERSION)) `lsb_release -sc`; urgency=low" \ "-- $(AUTHOR) `git log -1 --format=%cD`" \ > debian/changelog deb: deb-changelog dist-orig dpkg-buildpackage -uc -us -sa # After this target is build you need to do a debsign and dput on the # ../.changes file to upload onto the relevant PPA. For example: # # > make AUTHOR='First Last ' \ # NVME_DPKG_VERSION='0ubuntu1' deb-ppa # > debsign .changes # > dput ppa:/ppa .changes # # where lid is your launchpad.net ID. deb-ppa: deb-changelog dist-orig debuild -uc -us -S deb-light: $(NVME) pkg nvme.control.in dpkg-deb --build nvme-$(NVME_VERSION) rpm: dist $(RPMBUILD) -ta nvme-$(NVME_VERSION).tar.gz .PHONY: default doc all clean clobber install-man install-bin install .PHONY: dist pkg dist-orig deb deb-light rpm FORCE test nvme-cli-1.5/NVME-VERSION-GEN000077500000000000000000000013711322317423600153230ustar00rootroot00000000000000#!/bin/sh GVF=NVME-VERSION-FILE DEF_VER=v1.5 LF=' ' # First see if there is a version file (included in release tarballs), # then try git-describe, then default. if test -f version then VN=$(cat version) || VN="$DEF_VER" elif test -d .git -o -f .git && VN=$(git describe --tags --match "v[0-9]*" --abbrev=4 HEAD 2>/dev/null) && case "$VN" in *$LF*) (exit 1) ;; v[0-9]*) git update-index -q --refresh test -z "$(git diff-index --name-only HEAD --)" || VN="$VN-dirty" ;; esac then VN=$(echo "$VN" | sed -e 's/-/./g'); else VN="$DEF_VER" fi VN=$(expr "$VN" : v*'\(.*\)') if test -r $GVF then VC=$(sed -e 's/^NVME_VERSION = //' <$GVF) else VC=unset fi test "$VN" = "$VC" || { echo >&2 "NVME_VERSION = $VN" echo "NVME_VERSION = $VN" >$GVF } nvme-cli-1.5/README.md000066400000000000000000000115061322317423600143560ustar00rootroot00000000000000# nvme-cli NVM-Express user space tooling for Linux. To install, run: # make && make install If not sure how to use, find the top-level documentation with: # man nvme Or find a short summary with: # nvme help ## Distro Support ### Fedora nvme-cli is available in Fedora 23 and up. Install it with your favorite package manager. For example: $ sudo dnf install nvme-cli ### Ubuntu nvme-cli is supported in the Universe package sources for Xenial for many architectures. For a complete list try running: ``` rmadison nvme-cli nvme-cli | 0.3-1 | xenial/universe | source, amd64, arm64, armhf, i386, powerpc, ppc64el, s390x ``` A Debian based package for nvme-cli is currently maintained as a Ubuntu PPA. Right now there is support for Trusty, Vivid and Wiley. To install nvme-cli using this approach please perform the following steps: 1. Add the sbates PPA to your sources. One way to do this is to run ``` sudo add-apt-repository ppa:sbates ``` 2. Perform an update of your repository list: ``` sudo apt-get update ``` 3. Get nvme-cli! ``` sudo apt-get install nvme-cli ``` 4. Test the code. ``` sudo nvme list ``` In the case of no NVMe devices you will see ``` No NVMe devices detected. ``` otherwise you will see information about each NVMe device installed in the system. ### Alpine Linux nvme-cli is tested on Alpine Linux 3.3. Install it using: # akp update && apk add nvme-cli nvme-cli-doc if you just use the device you're after, it will work flawless. ``` # nvme smart-log /dev/nvme0 Smart Log for NVME device:/dev/nvme0 namespace-id:ffffffff critical_warning : 0 temperature : 49 C available_spare : 100% ``` ### openSUSE Tumbleweed nvme-cli is available in openSUSE Tumbleweed. You can install it using zypper. For example: $ sudo zypper install nvme-cli ### Arch Linux Install from AUR, e.g.: ``` $ yaourt -S nvme-cli-git ``` ### Nix(OS) The attribute is named `nvme-cli` and can e.g. be installed with: ``` $ nix-env -f '' -iA nvme-cli ``` ### Other Distros TBD ## Developers You may wish to add a new command or possibly an entirely new plug-in for some special extension outside the spec. This project provides macros that help generate the code for you. If you're interested in how that works, it is very similar to how trace events are created by Linux kernel's 'ftrace' component. ### Add command to existing built-in The first thing to do is define a new command entry in the command list. This is declared in nvme-builtin.h. Simply append a new "ENTRY" into the list. The ENTRY takes three arguments: the "name" of the subcommand (this is what the user will type at the command line to invoke your command), a short help description of what your command does, and the name of the function callback that you're going to write. After the ENTRY is defined, you need to implement the callback. It takes four arguments: argc, argv, the command structure associated with the callback, and the plug-in structure that contains that command. The prototype looks like this: ``` int f(int argc, char **argv, struct command *cmd, struct plugin *plugin); ``` The argc and argv are adjusted from the command line arguments to start after the sub-command. So if the command line is "nvme foo --option=bar", the argc is 1 and argv starts at "--option". You can then define argument parsing for your sub-command's specific options then do some command specific action in your callback. ### Add a new plugin The nvme-cli provides macros to make define a new plug-in simpler. You can certainly do all this by hand if you want, but it should be easier to get going using the macros. To start, first create a header file to define your plugin. This is where you will give your plugin a name, description, and define all the sub-commands your plugin implements. There is a very important order on how to define the plugin. The following is a basic example on how to start this: File: foo-plugin.h ``` #undef CMD_INC_FILE #define CMD_INC_FILE foo-plugin #if !defined(FOO) || defined(CMD_HEADER_MULTI_READ) #define FOO #include "cmd.h" PLUGIN(NAME("foo", "Foo plugin"), COMMAND_LIST( ENTRY("bar", "foo bar", bar) ENTRY("baz", "foo baz", baz) ENTRY("qux", "foo quz", qux) ) ); #endif #include "define_cmd.h" ``` In order to have the compiler generate the plugin through the xmacro expansion, you need to include this header in your source file, with pre-defining macro directive to create the commands. To get started from the above example, we just need to define "CREATE_CMD" and include the header: File: foo-plugin.c ``` #define CREATE_CMD #include "foo-plugin.h" ``` After that, you just need to implement the functions you defined in each ENTRY, then append the object file name to the Makefile's "OBJS". nvme-cli-1.5/argconfig.c000066400000000000000000000310451322317423600152020ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////// // // Copyright 2014 PMC-Sierra, Inc. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // // Author: Logan Gunthorpe // // Date: Oct 23 2014 // // Description: // Functions for parsing command line options. // //////////////////////////////////////////////////////////////////////// #include "argconfig.h" #include "suffix.h" #include #include #include #include #include #include #include static argconfig_help_func *help_funcs[MAX_HELP_FUNC] = { NULL }; static char END_DEFAULT[] = "__end_default__"; static const char *append_usage_str = ""; void argconfig_append_usage(const char *str) { append_usage_str = str; } void print_word_wrapped(const char *s, int indent, int start) { const int width = 76; const char *c, *t; int next_space = -1; int last_line = indent; while (start < indent) { putc(' ', stderr); start++; } for (c = s; *c != 0; c++) { if (*c == '\n') goto new_line; if (*c == ' ' || next_space < 0) { next_space = 0; for (t = c + 1; *t != 0 && *t != ' '; t++) next_space++; if (((int)(c - s) + start + next_space) > (last_line - indent + width)) { int i; new_line: last_line = (int) (c-s) + start; putc('\n', stderr); for (i = 0; i < indent; i++) putc(' ', stderr); start = indent; continue; } } putc(*c, stderr); } } static void show_option(const struct argconfig_commandline_options *option) { char buffer[0x1000]; char *b = buffer; b += sprintf(b, " [ "); if (option->option) { b += sprintf(b, " --%s", option->option); if (option->argument_type == optional_argument) b += sprintf(b, "[=<%s>]", option->meta ? option->meta : "arg"); if (option->argument_type == required_argument) b += sprintf(b, "=<%s>", option->meta ? option->meta : "arg"); if (option->short_option) b += sprintf(b, ","); } if (option->short_option) { b += sprintf(b, " -%c", option->short_option); if (option->argument_type == optional_argument) b += sprintf(b, " [<%s>]", option->meta ? option->meta : "arg"); if (option->argument_type == required_argument) b += sprintf(b, " <%s>", option->meta ? option->meta : "arg"); } b += sprintf(b, " ] "); fprintf(stderr, "%s", buffer); if (option->help) { print_word_wrapped("--- ", 40, b - buffer); print_word_wrapped(option->help, 44, 44); } fprintf(stderr, "\n"); } void argconfig_print_help(const char *program_desc, const struct argconfig_commandline_options *options) { const struct argconfig_commandline_options *s; printf("\033[1mUsage: %s\033[0m\n\n", append_usage_str); print_word_wrapped(program_desc, 0, 0); printf("\n\n\033[1mOptions:\033[0m\n"); for (s = options; (s->option != NULL) && (s != NULL); s++) show_option(s); } int argconfig_parse(int argc, char *argv[], const char *program_desc, const struct argconfig_commandline_options *options, void *config_out, size_t config_size) { char *short_opts; char *endptr; struct option *long_opts; const struct argconfig_commandline_options *s; int c, option_index = 0, short_index = 0, options_count = 0; void *value_addr; errno = 0; for (s = options; s->option != NULL; s++) options_count++; long_opts = malloc(sizeof(struct option) * (options_count + 2)); short_opts = malloc(sizeof(*short_opts) * (options_count * 3 + 4)); for (s = options; (s->option != NULL) && (option_index < options_count); s++) { if (s->short_option != 0) { short_opts[short_index++] = s->short_option; if (s->argument_type == required_argument || s->argument_type == optional_argument) short_opts[short_index++] = ':'; if (s->argument_type == optional_argument) short_opts[short_index++] = ':'; } if (s->option && strlen(s->option)) { long_opts[option_index].name = s->option; long_opts[option_index].has_arg = s->argument_type; if (s->argument_type == no_argument && s->default_value != NULL) { value_addr = (void *)(char *)s->default_value; long_opts[option_index].flag = value_addr; long_opts[option_index].val = 1; } else { long_opts[option_index].flag = NULL; long_opts[option_index].val = 0; } } option_index++; } long_opts[option_index].name = "help"; long_opts[option_index].flag = NULL; long_opts[option_index].val = 'h'; option_index++; long_opts[option_index].name = NULL; long_opts[option_index].flag = NULL; long_opts[option_index].val = 0; short_opts[short_index++] = '?'; short_opts[short_index++] = 'h'; short_opts[short_index] = 0; optind = 0; while ((c = getopt_long_only(argc, argv, short_opts, long_opts, &option_index)) != -1) { if (c != 0) { if (c == '?' || c == 'h') { argconfig_print_help(program_desc, options); goto out; } for (option_index = 0; option_index < options_count; option_index++) { if (c == options[option_index].short_option) break; } if (option_index == options_count) continue; if (long_opts[option_index].flag) { *(uint8_t *)(long_opts[option_index].flag) = 1; continue; } } s = &options[option_index]; value_addr = (void *)(char *)s->default_value; if (s->config_type == CFG_STRING) { *((char **)value_addr) = optarg; } else if (s->config_type == CFG_SIZE) { *((size_t *) value_addr) = strtol(optarg, &endptr, 0); if (errno || optarg == endptr) { fprintf(stderr, "Expected integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } } else if (s->config_type == CFG_INT) { *((int *)value_addr) = strtol(optarg, &endptr, 0); if (errno || optarg == endptr) { fprintf(stderr, "Expected integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } } else if (s->config_type == CFG_BOOL) { int tmp = strtol(optarg, &endptr, 0); if (errno || tmp < 0 || tmp > 1 || optarg == endptr) { fprintf(stderr, "Expected 0 or 1 argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } *((int *)value_addr) = tmp; } else if (s->config_type == CFG_BYTE) { unsigned long tmp = strtoul(optarg, &endptr, 0); if (errno || tmp >= (1 << 8) || optarg == endptr) { fprintf(stderr, "Expected byte argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } *((uint8_t *) value_addr) = tmp; } else if (s->config_type == CFG_SHORT) { unsigned long tmp = strtoul(optarg, &endptr, 0); if (errno || tmp >= (1 << 16) || optarg == endptr) { fprintf(stderr, "Expected short argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } *((uint16_t *) value_addr) = tmp; } else if (s->config_type == CFG_POSITIVE) { uint32_t tmp = strtoul(optarg, &endptr, 0); if (errno || optarg == endptr) { fprintf(stderr, "Expected word argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } *((uint32_t *) value_addr) = tmp; } else if (s->config_type == CFG_INCREMENT) { (*((int *)value_addr))++; } else if (s->config_type == CFG_LONG) { *((unsigned long *)value_addr) = strtoul(optarg, &endptr, 0); if (errno || optarg == endptr) { fprintf(stderr, "Expected long integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } } else if (s->config_type == CFG_LONG_SUFFIX) { *((long *)value_addr) = suffix_binary_parse(optarg); if (errno) { fprintf(stderr, "Expected long suffixed integer argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } } else if (s->config_type == CFG_DOUBLE) { *((double *)value_addr) = strtod(optarg, &endptr); if (errno || optarg == endptr) { fprintf(stderr, "Expected float argument for '%s' but got '%s'!\n", long_opts[option_index].name, optarg); goto out; } } else if (s->config_type == CFG_SUBOPTS) { char **opts = ((char **)value_addr); int remaining_space = CFG_MAX_SUBOPTS; int enddefault = 0; while (0 && *opts != NULL) { if (*opts == END_DEFAULT) enddefault = 1; remaining_space--; opts++; } if (!enddefault) { *opts = END_DEFAULT; remaining_space -= 2; opts += 2; } int r = argconfig_parse_subopt_string(optarg, opts, remaining_space); if (r == 2) { fprintf(stderr, "Error Parsing Sub-Options: Too many options!\n"); goto out; } else if (r) { fprintf(stderr, "Error Parsing Sub-Options\n"); goto out; } } else if (s->config_type == CFG_FILE_A || s->config_type == CFG_FILE_R || s->config_type == CFG_FILE_W || s->config_type == CFG_FILE_AP || s->config_type == CFG_FILE_RP || s->config_type == CFG_FILE_WP) { const char *fopts = ""; if (s->config_type == CFG_FILE_A) fopts = "a"; else if (s->config_type == CFG_FILE_R) fopts = "r"; else if (s->config_type == CFG_FILE_W) fopts = "w"; else if (s->config_type == CFG_FILE_AP) fopts = "a+"; else if (s->config_type == CFG_FILE_RP) fopts = "r+"; else if (s->config_type == CFG_FILE_WP) fopts = "w+"; FILE *f = fopen(optarg, fopts); if (f == NULL) { fprintf(stderr, "Unable to open %s file: %s\n", s->option, optarg); goto out; } *((FILE **) value_addr) = f; } } free(short_opts); free(long_opts); return 0; out: free(short_opts); free(long_opts); return -EINVAL; } int argconfig_parse_subopt_string(char *string, char **options, size_t max_options) { char **o = options; char *tmp; if (!string || !strlen(string)) { *(o++) = NULL; *(o++) = NULL; return 0; } tmp = calloc(strlen(string) + 2, 1); strcpy(tmp, string); size_t toklen; toklen = strcspn(tmp, "="); if (!toklen) { free(tmp); return 1; } *(o++) = tmp; tmp[toklen] = 0; tmp += toklen + 1; while (1) { if (*tmp == '"' || *tmp == '\'' || *tmp == '[' || *tmp == '(' || *tmp == '{') { tmp++; toklen = strcspn(tmp, "\"'])}"); if (!toklen) return 1; *(o++) = tmp; tmp[toklen] = 0; tmp += toklen + 1; toklen = strcspn(tmp, ";:,"); tmp[toklen] = 0; tmp += toklen + 1; } else { toklen = strcspn(tmp, ";:,"); if (!toklen) return 1; *(o++) = tmp; tmp[toklen] = 0; tmp += toklen + 1; } toklen = strcspn(tmp, "="); if (!toklen) break; *(o++) = tmp; tmp[toklen] = 0; tmp += toklen + 1; if ((o - options) > (max_options - 2)) return 2; } *(o++) = NULL; *(o++) = NULL; return 0; } unsigned argconfig_parse_comma_sep_array(char *string, int *val, unsigned max_length) { unsigned ret = 0; char *tmp; char *p; if (!string || !strlen(string)) return 0; tmp = strtok(string, ","); if (!tmp) return 0; val[ret] = strtol(tmp, &p, 0); if (*p != 0) return -1; ret++; while (1) { tmp = strtok(NULL, ","); if (tmp == NULL) return ret; if (ret >= max_length) return -1; val[ret] = strtol(tmp, &p, 0); if (*p != 0) return -1; ret++; } } unsigned argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val, unsigned max_length) { unsigned ret = 0; char *tmp; char *p; if (!string || !strlen(string)) return 0; tmp = strtok(string, ","); if (tmp == NULL) return 0; val[ret] = strtoll(tmp, &p, 0); if (*p != 0) return -1; ret++; while (1) { tmp = strtok(NULL, ","); if (tmp == NULL) return ret; if (ret >= max_length) return -1; val[ret] = strtoll(tmp, &p, 0); if (*p != 0) return -1; ret++; } } void argconfig_register_help_func(argconfig_help_func * f) { int i; for (i = 0; i < MAX_HELP_FUNC; i++) { if (help_funcs[i] == NULL) { help_funcs[i] = f; help_funcs[i + 1] = NULL; break; } } } nvme-cli-1.5/argconfig.h000066400000000000000000000052651322317423600152140ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////// // // Copyright 2014 PMC-Sierra, Inc. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // // Author: Logan Gunthorpe // Logan Gunthorpe // // Date: Oct 23 2014 // // Description: // Header file for argconfig.c // //////////////////////////////////////////////////////////////////////// #ifndef argconfig_H #define argconfig_H #include #include #include enum argconfig_types { CFG_NONE, CFG_STRING, CFG_INT, CFG_SIZE, CFG_LONG, CFG_LONG_SUFFIX, CFG_DOUBLE, CFG_BOOL, CFG_BYTE, CFG_SHORT, CFG_POSITIVE, CFG_INCREMENT, CFG_SUBOPTS, CFG_FILE_A, CFG_FILE_W, CFG_FILE_R, CFG_FILE_AP, CFG_FILE_WP, CFG_FILE_RP, }; struct argconfig_commandline_options { const char *option; const char short_option; const char *meta; enum argconfig_types config_type; void *default_value; int argument_type; const char *help; }; #define CFG_MAX_SUBOPTS 500 #define MAX_HELP_FUNC 20 #ifdef __cplusplus extern "C" { #endif typedef void argconfig_help_func(); void argconfig_append_usage(const char *str); void argconfig_print_help(const char *program_desc, const struct argconfig_commandline_options *options); int argconfig_parse(int argc, char *argv[], const char *program_desc, const struct argconfig_commandline_options *options, void *config_out, size_t config_size); int argconfig_parse_subopt_string(char *string, char **options, size_t max_options); unsigned argconfig_parse_comma_sep_array(char *string, int *ret, unsigned max_length); unsigned argconfig_parse_comma_sep_array_long(char *string, unsigned long long *ret, unsigned max_length); void argconfig_register_help_func(argconfig_help_func * f); void print_word_wrapped(const char *s, int indent, int start); #ifdef __cplusplus } #endif #endif nvme-cli-1.5/cmd.h000066400000000000000000000001751322317423600140130ustar00rootroot00000000000000#ifndef _CMD_H #define _CMD_H #undef PLUGIN #define PLUGIN(n, c) #undef COMMAND_LIST #define COMMAND_LIST(args...) #endif nvme-cli-1.5/cmd_handler.h000066400000000000000000000034341322317423600155110ustar00rootroot00000000000000/* * Stage 1 * * Define function prototypes. */ #undef NAME #define NAME(n, d) #undef ENTRY #define ENTRY(n, h, f, ...) \ static int f(int argc, char **argv, struct command *command, struct plugin *plugin); #undef COMMAND_LIST #define COMMAND_LIST(args...) args #undef PLUGIN #define PLUGIN(name, cmds) cmds #include CMD_INCLUDE(CMD_INC_FILE) /* * Stage 2 * * Define command structures. */ #undef NAME #define NAME(n, d) #undef ENTRY_W_ALIAS #define ENTRY_W_ALIAS(n, h, f, a) \ static struct command f ## _cmd = { \ .name = n, \ .help = h, \ .fn = f, \ .alias = a, \ }; #undef ENTRY_WO_ALIAS #define ENTRY_WO_ALIAS(n, h, f) \ ENTRY_W_ALIAS(n, h, f, NULL) #undef ENTRY_SEL #define ENTRY_SEL(n, h, f, a, CMD, ...) CMD #undef ENTRY #define ENTRY(...) \ ENTRY_SEL(__VA_ARGS__, ENTRY_W_ALIAS, ENTRY_WO_ALIAS)(__VA_ARGS__) #undef COMMAND_LIST #define COMMAND_LIST(args...) args #undef PLUGIN #define PLUGIN(name, cmds) cmds #include CMD_INCLUDE(CMD_INC_FILE) /* * Stage 3 * * Generate list of commands for the plugin. */ #undef NAME #define NAME(n, d) #undef ENTRY #define ENTRY(n, h, f, ...) &f ## _cmd, #undef COMMAND_LIST #define COMMAND_LIST(args...) \ static struct command *commands[] = { \ args \ NULL, \ }; #undef PLUGIN #define PLUGIN(name, cmds) cmds #include CMD_INCLUDE(CMD_INC_FILE) /* * Stage 4 * * Define and register plugin */ #undef NAME #define NAME(n, d) .name = n, .desc = d, #undef COMMAND_LIST #define COMMAND_LIST(args...) #undef PLUGIN #define PLUGIN(name, cmds) \ static struct plugin plugin = { \ name \ .commands = commands \ }; \ \ static void init(void) __attribute__((constructor)); \ static void init(void) \ { \ register_extension(&plugin); \ } #include CMD_INCLUDE(CMD_INC_FILE) nvme-cli-1.5/common.h000066400000000000000000000003251322317423600145350ustar00rootroot00000000000000#ifndef _COMMON_H #define _COMMON_H #define __round_mask(x, y) ((__typeof__(x))((y)-1)) #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif nvme-cli-1.5/completions/000077500000000000000000000000001322317423600154305ustar00rootroot00000000000000nvme-cli-1.5/completions/README000066400000000000000000000077651322317423600163270ustar00rootroot00000000000000Kelly Kaoudis, kelly.n.kaoudis at intel.com, June 2015 Setting Up NVMe Tab Autocompletion for bash or zsh ================================================== If your working shell is bash... -------------------------------- the following gets bash autocompletion to behave properly #echo "bind 'set show-all-if-ambiguous on'" >> ~/.bashrc #echo "bind 'set show-all-if-unmodified on'" >> ~/.bashrc #echo "bind 'set completion-ignore-case on'" >> ~/.bashrc #echo "bind 'set completion-map-case on'" >> ~/.bashrc add NVMe autocompletion script to your autocompletes directory #cp `pwd`/bash-nvme-completion.sh /etc/bash_completion.d/nvme make sure this bash knows where everything is #source /etc/bash_completion.d/nvme && source ~/.bashrc you should be able to autocomplete with the nvme utility now (double TABs still apply)! If autocompleting has disappeared, just re-source nvme and .bashrc. To see a full list of auto-completable NVMe commands, type "nvme help " and hit TAB. You may also need to uncomment the "enable bash completion in interactive shells" part of /etc/bash.bashrc, which hopefully looks somehting like: if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fi (don't bother with the shopt part, your Bash version might not support shopt). Bash footnote: for bash vers >= 4.2, it appears to be the case that menu-complete **no longer works.** If the bash dev folks ever re-patch this, try binding TAB to menu-complete to cycle through the NVMe subcommand matches on whatever you typed. if your working shell is zsh... ------------------------------- create the zsh completions directory if you don't have it #if [ ! -e "~/.zsh" ]; then # mkdir ~/.zsh # mkdir ~/.zsh/completion #fi #cp `pwd`/_nvme ~/.zsh/completion/_nvme add compinit if you don't have it in your .zshrc #echo "autoload -Uz compinit && compinit" >> ~/.zshrc add nvme autocompletions to your .zshrc #echo "# source for tab autocompletions" >> ~/.zshrc #echo "fpath=(~/.zsh/completion $fpath)" >> ~/.zshrc #echo "source ~/.zsh/completion/_nvme" >> ~/.zshrc make sure this zsh knows where everything is #source ~/.zsh/completion/_nvme && source ~/.zshrc You should be able to autocomplete with the nvme utility now (single TAB press should get you a completion with descriptions -- sadly, bash doesn't support descriptions within completions). If autocompletes disappear, just re-source _nvme and .zshrc. Also, make sure your .zshrc is ordered correctly: we want to source _nvme before updating our fpath. Both of these should occur before compinit is loaded. Updating NVMe Tab Autocompletions ================================= zsh --- Add your new command to the _cmds array in the following format: 'command:short-form description' Add a case to the zsh case statement for autocompletion of subopts in the following format (as seen in _nvme): (bar) local _list_of_subopts _list_of_subopts=( /dev/nvme':supply a device to use (required)' --foo':do something cool' -f':alias of --foo' ) _arguments '*:: :->subcmds' _describe -t commands "nvme bar options" _list_of_subopts ;; All zsh autocompletion built-ins start with _, and so should anything internal to your autocompletes. _arguments and _describe are built-ins. The '*:: :->subcmds' bit describes the format in which we want our options to be displayed (don't change this, unless you like pain.) _describe -t adds our list of options to the data structure associated with our command `bar'. Add the name of your command to the (help) case as well. Update your ~/.zsh/completion/_nvme with your new changes and re-source as needed. bash ---- Add the name of your command to _cmds in bash_nvme_completion.sh. Add a case to _nvme_list_opts in the following format: "bar") opts+="--foo= -f --baz= -b" ;; Update your /etc/bash_completion.d/nvme version, and re-source things as needed. TO DO ----- Automatically generate man pages and autocompletions for new NVMe commands, possibly with kerneldoc. nvme-cli-1.5/completions/_nvme000066400000000000000000000542001322317423600164600ustar00rootroot00000000000000#compdef _nvme nvme # zsh completions for the nvme command-line interface, # very loosely based on git and adb command completion # Kelly Kaoudis kelly.n.kaoudis at intel.com, June 2015 _nvme () { local -a _cmds _cmds=( 'id-ctrl:display information about the controller' 'id-ns:display information about the namespace' 'list-ns:identify all namespace(s) attached' 'create-ns:create a new namespace before attachment' 'delete-ns:delete a detached namespace' 'attach-ns:attach namespace to controller' 'detach-ns:detach namespace from controller' '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' 'fw-log:retrieve fw log' 'smart-log:retrieve SMART log' 'smart-log-add:retrieve additional SMART log' 'error-log:retrieve error log' 'get-feature:display a controller feature' 'set-feature:set a controller feature and show results' 'format:apply new block format to namespace' 'fw-activate:activate a firmware on the device' 'fw-download:download a firmware to the device' 'admin-passthru:submit a passthrough IOCTL' 'io-passthru:submit a passthrough IOCTL' 'security-send:send security/secure data to controller' 'security-recv:ask for security/secure data from controller' 'resv-acquire:acquire reservation on a namespace' 'resv-register:register reservation on a namespace' 'resv-release:release reservation on a namespace' 'resv-report:report reservation on a namespace' 'flush:submit a flush' 'compare:compare data on device to data elsewhere' 'read:submit a read command' 'write:submit a write command' 'show-regs:shows the controller registers; requires admin character device' 'help:print brief descriptions of all nvme commands' ) local expl _arguments '*:: :->subcmds' && return 0 if (( CURRENT == 1 )); then _describe -t commands "nvme subcommands" _cmds return else case ${words[CURRENT-1]} in (id-ctrl) local _idctrl _idctrl=( /dev/nvme':supply a device to use (required)' --raw-binary':dump infos in binary format' -b':alias of --raw-binary' --human-readable':show infos in readable format' -H':alias of --human-readable' --vendor-specific':also dump binary vendor infos' -v':alias of --vendor-specific' ) _arguments '*:: :->subcmds' _describe -t commands "nvme id-ctrl options" _idctrl ;; (id-ns) local _idns _idns=( /dev/nvme':supply a device to use (required)' --namespace-id=':show infos for namespace ' -n':alias of --namespace-id' --raw-binary':dump infos in binary format' -b':alias of --raw-binary' --human-readable':show infos in readable format' -H':alias of --human-readable' --vendor-specific':also dump binary vendor infos' -v':alias of --vendor-specific' ) _arguments '*:: :->subcmds' _describe -t commands "nvme id-ns options" _idns ;; (list-ns) local _listns _listns=( /dev/nvme':supply a device to use (required)' --namespace-id=':start namespace infos listing with this nsid' -n':alias of --namespace-id' ) _arguments '*:: :->subcmds' _describe -t commands "nvme list-ns options" _listns ;; (create-ns) local _createns _createns=( /dev/nvme':supply a device to use (required)' --nsze=':namespace size to create' -s':alias of --nsze' --ncap=':namespace capacity' -c':alias of --ncap' --flbas=':FLBA size' -f':alias of --flbas' --dps=':data protection?' -d':alias of --dps' --nmic=':multipath and sharing' -n':alias of --nmic' ) _arguments '*:: :->subcmds' _describe -t commands "nvme create-ns options" _createns ;; (delete-ns) local _deletens _deletens=( /dev/nvme':supply a device to use (required)' --namespace-id=':namespace to delete' -n':alias of --namespace-id' ) _arguments '*:: :->subcmds' _describe -t commands "nvme delete-ns options" _deletens ;; (attach-ns) local _attachns _attachns=( /dev/nvme':supply a device to use (required)' --namespace-id=':namespace to attach to the controller' -n':alias of --namespace-id' --controllers=':if a device is not provided, supply a comma-sep list of controllers' -c':alias of --controllers' ) _arguments '*:: :->subcmds' _describe -t commands "nvme attach-ns options" _attachns ;; (detach-ns) local _detachns _detachns=( /dev/nvme':supply a device to use (required)' --namespace-id=':namespace to detach from controller' -n':alias of --namespace-id' --controllers=':if a device is not provided, supply a comma-sep list of controllers' -c':alias of --controllers' ) _arguments '*:: :->subcmds' _describe -t commands "nvme detach-ns options" _detachns ;; (list-ctrl) local _listctrl _listctrl=( /dev/nvme':supply a device to use (required)' --namespace-id=':show controllers attached to this namespace' -n':alias of --namespace-id' --cntid=':start the list with this controller' -c':alias of --cntid' ) _arguments '*:: :->subcmds' _describe -t commands "nvme list-ctrl options" _listctrl ;; (get-ns-id) local _getnsid _getnsid=( /dev/nvme':supply a device to use (required)' ) _arguments '*:: :->subcmds' _describe -t commands "nvme get-ns-id options" _getnsid ;; (get-log) local _getlog _getlog=( /dev/nvme':supply a device to use (required)' --log-id=':requested log number' -i':alias of --log-id' --log-len=':number of bytes to show for requested log' -l':alias of --log-len' --namespace-id=':get log specific to if namespace logs are supported' -n':alias of --namespace-id' --raw-binary':dump infos in binary format' -b':alias of --raw-binary' ) _arguments '*:: :->subcmds' _describe -t commands "nvme get-log options" _getlog ;; (fw-log) local _fwlog _fwlog=( /dev/nvme':supply a device to use (required)' --raw-binary':dump infos in binary format' -b':alias of --raw-binary' ) _arguments '*:: :->subcmds' _describe -t commands "nvme fw-log options" _fwlog ;; (smart-log) local _smartlog _smartlog=( /dev/nvme':supply a device to use (required)' --namespace-id=':get SMART log specific to if namespace logs are supported' -n':alias to --namespace-id' --raw-binary':dump infos in binary format' -b':alias to --raw-binary' ) _arguments '*:: :->subcmds' _describe -t commands "nvme smart-log options" _smartlog ;; (smart-log-add) local _add _add=( /dev/nvme':supply a device to use (required)' --namespace-id=':get additional SMART log specific to if namespace logs supported' -n':alias to --namespace-id' --raw-binary':dump infos in binary format' -b':alias to --raw-binary' ) _arguments '*:: :->subcmds' _describe -t commands "nvme smart-log-add options" _add ;; (error-log) local _errlog _errlog=( /dev/nvme':supply a device to use (required)' --namespace-id=':get log specific to if namespace logs are supported' -n':alias to --namespace-id' --raw-binary':dump infos in binary format' -b':alias to --raw-binary' --log-entries=':request n >= 1 log entries' -e':alias to --log-entries' ) _arguments '*:: :->subcmds' _describe -t commands "nvme error-log options" _errlog ;; (get-feature) local _getf _getf=( /dev/nvme':supply a device to use (required)' --namespace-id=':get feature specific to ' -n':alias to --namespace-id' --feature-id=':hexadecimal name of feature to examine (required)' -f':alias to --feature-id' --sel=':select from 0 - current, 1 - default, 2 - saved, 3 - supported' -s':alias to --sel' --data-len=':buffer len for returned LBA Type Range or host identifier data' -l':alias for --data-len' --cdw11=':dword 11 value, used for interrupt vector configuration only' --raw-binary':dump infos in binary format' -b':alias to --raw-binary' ) _arguments '*:: :->subcmds' _describe -t commands "nvme get-feature options" _getf ;; (set-feature) local _setf _setf=( /dev/nvme':supply a device to use (required)' --namespace-id=':feature is specific to ' -n':alias to --namespace-id' --feature-id=':hexadecimal name of feature to set (required)' -f':alias to --feature-id' --data-len=':buffer length, only used for LBA Type Range or host identifier data' -l':alias for --data-len' --data=':data file for LBA Type Range or host identifier buffer (defaults to stdin)' -d':alias to --data' --value=':new value of feature (required)' -v'alias to --value' ) _arguments '*:: :->subcmds' _describe -t commands "nvme set-feature options" _setf ;; (format) local _format _format=( /dev/nvme':supply a device to use (required)' --namespace-id=': of namespace to format (required)' -n':alias of --namespace-id' --lbaf=':LBA format to apply to namespace (required)' -l':alias of --lbaf' --ses=':secure erase? 0 - no-op (default), 1 - user-data erase, 2 - cryptographic erase' -s':alias of --ses' --pil=':location of protection information? 0 - end, 1 - start' -p':alias of --pil' --pi=':protection information? 0 - off, 1 - Type 1 on, 2 - Type 2 on, 3 - Type 3 on' -i':alias of --pi' --ms=':extended format? 0 - off (metadata in separate buffer), 1 - on (extended LBA used)' -m':alias of --ms' ) _arguments '*:: :->subcmds' _describe -t commands "nvme format options" _format ;; (fw-activate) local _fwact _fwact=( /dev/nvme':supply a device to use (required)' --action=':activation action (required)? 0 - replace fw without activating, 1 - replace with activation, 2 - replace with activation at next reset' -a':alias of --action' --slot=':firmware slot to activate' -s':alias of --slot' ) _arguments '*:: :->subcmds' _describe -t commands "nvme fw-activate options" _fwact ;; (fw-download) local _fwd _fwd=( /dev/nvme':supply a device to use (required)' --fw=':firmware file to download (required)' -f':alias of --fw' --xfer=':limit on chunk-size of transfer (if device has download size limit)' -x':alias of --xfer' --offset=':starting offset, in dwords (defaults to 0, only useful if download is split across multiple files)' -o':alias of --offset' ) _arguments '*:: :->subcmds' _describe -t commands "nvme fw-download options" _fwd ;; (admin-passthru) local _admin _admin=( /dev/nvme':supply a device to use (required)' --opcode=':hexadecimal opcode to send (required)' -o':alias of --opcode' --flags=':command flags' -f':alias of --flags' --rsvd=':value for reserved field' -R':alias of --rsvd' --namespace-id=':value for nsid' -n':alias of --namespace-id' --data-len=':length for data buffer' -l':alias of --data-len' --metadata-len=':length for metadata buffer' -m':alias of --metadata-len' --timeout=':value for timeout' -t':alias of --timeout' --cdw2=':value for command dword 2' -2':alias for --cdw2' --cdw3=':value for command dword 3' -3':alias for --cdw3' --cdw10=':value for command dword 10' -4':alias for --cdw10' --cdw11=':value for command dword 11' -5':alias for --cdw11' --cdw12=':value for command dword 12' -6':alias for --cdw12' --cdw13=':value for command dword 13' -7':alias for --cdw13' --cdw14=':value for command dword 14' -8':alias for command dword 14' --cdw15=':value for command dword 15' -9':alias for command dword 15' --input-file=':defaults to stdin; input for write (send direction)' -i':alias for --input-file' --raw-binary':dump output in binary format' -b':alias for --raw-binary' --show-command':simply print command instead of sending it to ' -s':alias for --show-command' --dry-run':alias for --show-command' -d':alias for --show-command' --read':set dataflow direction to receive' -r':alias for --read' --write':set dataflow direction to send' -w':alias for --write' ) _arguments '*:: :->subcmds' _describe -t commands "nvme admin-passthru options" _admin ;; (io-passthru) local _io _io=( /dev/nvme':supply a device to use (required)' --opcode=':hexadecimal opcode to send (required)' -o':alias of --opcode' --flags=':command flags' -f':alias of --flags' --rsvd=':value for reserved field' -R':alias of --rsvd' --namespace-id=':value for nsid' -n':alias of --namespace-id' --data-len=':length for data buffer' -l':alias of --data-len' --metadata-len=':length for metadata buffer' -m':alias of --metadata-len' --timeout=':value for timeout' -t':alias of --timeout' --cdw2=':value for command dword 2' -2':alias for --cdw2' --cdw3=':value for command dword 3' -3':alias for --cdw3' --cdw10=':value for command dword 10' -4':alias for --cdw10' --cdw11=':value for command dword 11' -5':alias for --cdw11' --cdw12=':value for command dword 12' -6':alias for --cdw12' --cdw13=':value for command dword 13' -7':alias for --cdw13' --cdw14=':value for command dword 14' -8':alias for command dword 14' --cdw15=':value for command dword 15' -9':alias for command dword 15' --input-file=':defaults to stdin; input for write (send direction)' -i':alias for --input-file' --raw-binary':dump output in binary format' -b':alias for --raw-binary' --show-command':simply print command instead of sending it to ' -s':alias for --show-command' --dry-run':alias for --show-command' -d':alias for --show-command' --read':set dataflow direction to receive' -r':alias for --read' --write':set dataflow direction to send' -w':alias for --write' ) _arguments '*:: :->subcmds' _describe -t commands "nvme io-passthru options" _io ;; (security-send) local _ssend _ssend=( /dev/nvme':supply a device to use (required)' --file=':payload' -f':alias for --file' --secp=':security protocol as defined in SPC-4' -p':alias for --secp' --spsp=':send security-protocol-specific data as defined in SPC-4' -s':alias for --spsp' --tl=':transfer length as defined in SPC-4' -t':alias for --tl' ) _arguments '*:: :->subcmds' _describe -t commands "nvme security-send options" _ssend ;; (security-recv) local _srecv _srecv=( /dev/nvme':supply a device to use (required)' --secp=':security protocol as defined in SPC-4' -p':alias for --secp' --spsp=':send security-protocol-specific data as defined in SPC-4' -s':alias for --spsp' --size=':size of buffer (prints to stdout on successful recv)' -x':alias for --size' --al=':allocation length as defined in SPC-4' -a':alias for --al' --raw-binary':dump output in binary format' -b':alias for --raw-binary' ) _arguments '*:: :->subcmds' _describe -t commands "nvme security-recv options" _srecv ;; (resv-acquire) local _acq _acq=( /dev/nvme':supply a device to use (required)' --namespace-id=': of namespace to try to reserve (required)' -n':alias for --namespace-id' --prkey=':pre-empt reservation key' -p':alias for --prkey' --rtype=':hexadecimal reservation type' -t':alias for --rtype' --racqa=':reservation acquiry action' -a':alias for --racqa' --iekey=':ignore existing reservation key' -i':alias for --iekey' --crkey':current reservation key' -c':alias for --crkey' ) _arguments '*:: :->subcmds' _describe -t commands "nvme resv-acquire options" _acq ;; (resv-release) local _rel _rel=( /dev/nvme':supply a device to use (required)' --namespace-id=':nsid' -n':alias of --namespace-id' --rtype=':hexadecimal reservation type' -t':alias of --rtype' --rrela=':reservation release action' -a':alias of --rrela' --iekey':ignore existing reservation key' -i':alias of --iekey' ) _arguments '*:: :->subcmds' _describe -t commands "nvme resv-release options" _rel ;; (resv-report) local _rep _rep=( /dev/nvme':supply a device to use (required)' --namespace-id=':nsid' -n':alias of --namespace-id' --numd=':number of dwords of reservation status to xfer' -d':alias of --numd' --raw-binary':dump output in binary format' -b':alias of --raw-binary' ) _arguments '*:: :->subcmds' _describe -t commands "nvme resv-report options" _rep ;; (resv-register) local _reg _reg=( /dev/nvme':supply a device to use (required)' --namespace-id=':nsid' -n':alias of --namespace-id' --crkey=':current reservation key' -c'alias of --crkey' --nrkey=':new reservation key' -k':alias of --nrkey' --cptpl=':change persistence through power loss setting' -p':alias for --cptpl' --rrega=':reservation registration action to perform' -a':alias for --rrega' --iekey':ignore existing reservation key' -i':alias for --iekey' ) _arguments '*:: :->subcmds' _describe -t commands "nvme resv-register options" _reg ;; (flush) local _flush _flush=( /dev/nvme':supply a device to use (required)' --namespace-id=':nsid' -n':alias of --namespace-id' ) _arguments '*:: :->subcmds' _describe -t commands "nvme flush options" _flush ;; (compare) local _comp _comp=( /dev/nvme':supply a device to use (required)' --start-block=':begin compare at this 64-bit LBA on device' -s':alias of --start-block' --block-count=':number of logical blocks on device to compare to local data' -c':alias of --block-count' --metadata-size=':number of bytes of metadata to compare' -y':alias of --metadata-size' --data-size=':size of local data buffer in bytes' -z':alias of --data-size' --data=':local data file to compare to blocks on device' -d':alias of --data' --prinfo=':protection information action and check field' -p':alias of --prinfo' --app-tag-mask=':application tag mask (for end to end PI)' -m':alias of --app-tag-mask' --app-tag=':application tag (for end to end PI)' -a':alias of --app-tag' --limited-retry':if included, controller should try less hard to retrieve data from media (if not included, all available data recovery means used)' -l':alias of --limited-retry' --force-unit-access':if included, the data shall be read from non-volatile media' -f':alias of --force-unit access' --show-command':show command instead of sending to device' -v':alias of --show-command' --dry-run':show command instead of sending to device' -w':alias of --show-command' ) _arguments '*:: :->subcmds' _describe -t commands "nvme compare options" _comp ;; (read) local _read _read=( /dev/nvme':supply a device to use (required)' --start-block=':64-bit address of the first logical block to be read' -s':alias of --start-block' --block-count=':number of logical blocks on device to read' -c':alias of --block-count' --data-size=':size of data to be read' -z':alias of --data-size' --metadata-size=':size of metadata to be read' -y':alias of --metadata-size' --ref-tag=':reference tag (for end to end PI)' -r':alias of --ref-tag' --data=':file into which data should be read (defaults to stdout)' -d':alias of --data' --prinfo=':protection information and check field' -p':alias of --prinfo' --app-tag-mask=':application tag mask (for end to end PI)' -m':alias of --app-tag-mask' --app-tag=':application tag (for end to end PI)' -a':alias of --app-tag' --limited-retry=':if included, controller should try less hard to retrieve data from media (if not included, all available data-recovery means used)' -l':alias of --limited-retry' --latency':latency statistics will be output following read' -t':alias of --latency' --force-unit-access':data read shall be returned from nonvolatile media before command completion is indicated' -f':alias of --force-unit-access' --show-command':show command instead of sending to device' -v':alias of --show-command' --dry-run':show command instead of sending to device' -w':alias of --show-command' ) _arguments '*:: :->subcmds' _describe -t commands "nvme read options" _read ;; (write) local _wr _wr=( /dev/nvme':supply a device to use (required)' --start-block=':64-bit address of the first logical block to be written' -s':alias of --start-block' --block-count=':number of logical blocks on device to write' -c':alias of --block-count' --data-size=':size of data to be written' -z':alias of --data-size' --metadata-size=':size of metadata to be written' -y':alias of --metadata-size' --ref-tag=':reference tag (for end to end PI)' -r':alias of --ref-tag' --data=':file from which data should be written to device (defaults to stdin)' -d':alias of --data' --prinfo=':protection information and check field' -p':alias of --prinfo' --app-tag-mask=':application tag mask (for end to end PI)' -m':alias of --app-tag-mask' --app-tag=':application tag (for end to end PI)' -a':alias of --app-tag' --limited-retry=':if included, controller should try less hard to send data to media (if not included, all available data-recovery means used)' -l':alias of --limited-retry' --latency':latency statistics will be output following write' -t':alias of --latency' --force-unit-access':data shall be written to nonvolatile media before command completion is indicated' -f':alias of --force-unit-access' --show-command':show command instead of sending to device' -v':alias of --show-command' --dry-run':show command instead of sending to device' -w':alias of --show-command' ) _arguments '*:: :->subcmds' _describe -t commands "nvme write options" _wr ;; (show-regs) local _shor _shor=( /dev/nvme':supply a device to use (required)' ) _arguments '*:: :->subcmds' _describe -t commands "nvme show-regs options" _shor ;; (help) local _h _h=( id-ctrl id-ns list-ns create-ns delete-ns attach-ns detach-ns list-ctrl get-ns-id get-log fw-log smart-log 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 resv-report flush compare read write show-regs ) _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 ;; (*) _files ;; esac return fi _files } nvme-cli-1.5/completions/bash-nvme-completion.sh000066400000000000000000000143401322317423600220150ustar00rootroot00000000000000# bash tab completion for the nvme command line utility # (unfortunately, bash won't let me add descriptions to cmds) # Kelly Kaoudis kelly.n.kaoudis at intel.com, Aug. 2015 _cmds="list id-ctrl id-ns list-ns create-ns delete-ns \ attach-ns detach-ns list-ctrl get-ns-id get-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 \ resv-report dsm flush compare read write write-zeroes \ write-uncor reset subsystem-reset show-regs discover \ connect-all connect disconnect version help \ intel lnvm memblaze list-subsys" nvme_list_opts () { local opts="" local compargs="" local nonopt_args=0 for (( i=0; i < ${#words[@]}-1; i++ )); do if [[ ${words[i]} != -* ]]; then let nonopt_args+=1 fi done if [ $nonopt_args -eq 2 ]; then opts="/dev/nvme* " fi opts+=" " case "$1" in "list") opts="" ;; "id-ctrl") opts+=" --raw-binary -b --human-readable -H \ --vendor-specific -v --output-format= -o" ;; "id-ns") opts+=" --namespace-id= -n --raw-binary -b \ --human-readable -H --vendor-specific -v \ --force -f --output-format= -o" ;; "list-ns") opts+=" --namespace-id= -n --al -a" ;; "create-ns") opts+=" --nsze= -s --ncap= -c --flbas= -f \ --dps= -d --nmic= -n" ;; "delete-ns") opts+=" -namespace-id= -n" ;; "attach-ns") opts+=" --namespace-id= -n --controllers= -c" ;; "detach-ns") opts+=" --namespace-id= -n --controllers= -c" ;; "list-ctrl") opts+=" --namespace-id= -n --cntid= -c" ;; "get-ns-id") ;; "get-log") opts+=" --log-id= -i --log-len= -l --namespace-id= -n \ --raw-binary= -b" ;; "fw-log") opts+=" --raw-binary -b --output-format= -o" ;; "smart-log") opts+=" --namespace-id= -n --raw-binary -b \ --output-format= -o" ;; "smart-log-add") opts+=" --namespace-id= -n --raw-binary -b" ;; "error-log") opts+=" --namespace-id= -n --raw-binary -b --log-entries= -e \ --output-format= -o" ;; "get-feature") opts+=" --namespace-id= -n --feature-id= -f --sel= -s \ --data-len= -l --cdw11= --raw-binary -b \ --human-readable -H" ;; "set-feature") opts+=" --namespace-id= -n --feature-id= -f --value= -v \ --data-len= -l -data= -d --value= --save -s" ;; "format") opts+=" --namespace-id= -n --timeout= -t --lbaf= -l \ --ses= -s --pil= -p -pi= -i --ms= -m --reset -r" ;; "fw-activate") opts+=" --action= -a --slot= -s" ;; "fw-download") opts+=" --fw= -f --xfer= -x --offset= -o" ;; "admin-passthru") opts+=" --opcode= -o --flags= -f --prefil= -p --rsvd= -R \ --namespace-id= -n --data-len= -l --metadata-len= -m \ --timeout= -t --cdw2= -2 --cdw3= -3 --cdw10= -4 \ --cdw11= -5 --cdw12= -6 --cdw13= -7 --cdw14= -8 \ --cdw15= -9 --input-file= -i --raw-binary= -b \ --show-command -s --dry-run -d --read -r --write -w" ;; "io-passthru") opts+=" --opcode= -o --flags= -f --prefill= -p --rsvd= -R \ --namespace-id= -n --data-len= -l --metadata-len= -m \ --timeout= -t --cdw2= -2 --cdw3= -3 --cdw10= -4 \ --cdw11= -5 --cdw12= -6 --cdw13= -7 --cdw14= -8 \ --cdw15= -9 --input-file= -i --raw-binary= -b \ --show-command -s --dry-run -d --read -r --write -w" ;; "security-send") opts+=" --namespace-id= -n --file= -f --nssf= -N --secp= -p \ --spsp= -s --tl= -t" ;; "security-recv") opts+=" --namespace-id= -n --size= -x --secp= -p --spsp= -s \ --al= -t --raw-binary -b" ;; "resv-acquire") opts+=" --namespace-id= -n --crkey= -c --prkey= -p \ --rtype= -t --racqa= -a --iekey= -i" ;; "resv-register") opts+=" --namespace-id= -n --crkey= -c --nrkey= -k \ --rrega= -r --cptpl= -p --iekey -i" ;; "resv-release") opts+=" --namespace-id= -n --crkey -c --rtype= -t \ --rrela= -a --iekey -i" ;; "resv-report") opts+=" --namespace-id= -n --numd= -d --raw-binary= -b \ --output-format= -o" ;; "dsm") opts+=" --namespace-id= -n --ctx-attrs= -a --blocks= -b\ -slbs= -s --ad -d --idw -w --idr -r --cdw11= -c" ;; "flush") opts+=" --namespace-id= -n" ;; "compare") opts+=" --start-block= -s --block-count= -c --data-size= -z \ --metadata-size= -y --ref-tag= -r --data= -d \ --metadata= -M --prinfo= -p --app-tag-mask= -m \ --app-tag= -a --limited-retry -l \ --force-unit-access -f --show-command -v \ --dry-run -w --latency -t" ;; "read") opts+=" --start-block= -s --block-count= -c --data-size= -z \ --metadata-size= -y --ref-tag= -r --data= -d \ --metadata= -M --prinfo= -p --app-tag-mask= -m \ --app-tag= -a --limited-retry -l \ --force-unit-access -f --show-command -v \ --dry-run -w --latency -t" ;; "write") opts+=" --start-block= -s --block-count= -c --data-size= -z \ --metadata-size= -y --ref-tag= -r --data= -d \ --metadata= -M --prinfo= -p --app-tag-mask= -m \ --app-tag= -a --limited-retry -l \ --force-unit-access -f --show-command -v \ --dry-run -w --latency -t" ;; "write-zeros") opts+=" --namespace-id= -n --start-block= -s \ --block-count= -c --limited-retry -l \ --force-unit-access -f --prinfo= -p --ref-tag= -r \ --app-tag-mask= -m --app-tag= -a" ;; "write-uncor") opts+=" --namespace-id= -n --start-block= -s \ --block-count= -c" ;; "reset") opts+="" ;; "subsystem-reset") opts+="" ;; "show-regs") opts+=" --human-readable -H" ;; "discover") opts+=" --transport= -t -traddr= -a -trsvcid= -s \ --hostnqn= -q --raw= -r" ;; "connect-all") opts+=" --transport= -t --traddr= -a --trsvcid= -s --hostnqn= -q --raw= -r" ;; "connect") opts+=" --transport= -t --nqn= -n --traddr= -a --trsvcid -s \ --hostnqn= -q --nr-io-queues= -i --keep-alive-tmo -k \ --reconnect-delay -r" ;; "disconnect") opts+=" --nqn -n --device -d" ;; "version") opts+="" ;; "help") opts=$_cmds ;; esac opts+=" -h --help" COMPREPLY+=( $( compgen $compargs -W "$opts" -- $cur ) ) return 0 } _nvme_subcmds () { local cur prev words cword _init_completion || return if [[ ${#words[*]} -lt 3 ]]; then COMPREPLY+=( $(compgen -W "$_cmds" -- $cur ) ) else nvme_list_opts ${words[1]} $prev fi return 0 } complete -o default -F _nvme_subcmds nvme nvme-cli-1.5/define_cmd.h000066400000000000000000000005411322317423600153220ustar00rootroot00000000000000#ifdef CREATE_CMD #undef CREATE_CMD #define __stringify_1(x...) #x #define __stringify(x...) __stringify_1(x) #define __CMD_INCLUDE(cmd) __stringify(cmd.h) #define CMD_INCLUDE(cmd) __CMD_INCLUDE(cmd) #define CMD_HEADER_MULTI_READ #include CMD_INCLUDE(CMD_INC_FILE) #include "cmd_handler.h" #undef CMD_HEADER_MULTI_READ #define CREATE_CMD #endif nvme-cli-1.5/fabrics.c000066400000000000000000000563161322317423600146640ustar00rootroot00000000000000/* * Copyright (C) 2016 Intel Corporation. All rights reserved. * Copyright (c) 2016 HGST, a Western Digital Company. * Copyright (c) 2016 Samsung Electronics Co., Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This file implements the discovery controller feature of NVMe over * Fabrics specification standard. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "parser.h" #include "nvme-ioctl.h" #include "fabrics.h" #include "nvme.h" #include "argconfig.h" #include "common.h" #define NVMF_HOSTID_SIZE 36 static struct config { char *nqn; char *transport; char *traddr; char *trsvcid; char *host_traddr; char *hostnqn; char *hostid; char *nr_io_queues; char *queue_size; char *keep_alive_tmo; char *reconnect_delay; char *ctrl_loss_tmo; char *raw; char *device; int duplicate_connect; } cfg = { NULL }; #define BUF_SIZE 4096 #define PATH_NVME_FABRICS "/dev/nvme-fabrics" #define PATH_NVMF_DISC "/etc/nvme/discovery.conf" #define PATH_NVMF_HOSTNQN "/etc/nvme/hostnqn" #define PATH_NVMF_HOSTID "/etc/nvme/hostid" #define SYS_NVME "/sys/class/nvme" #define MAX_DISC_ARGS 10 enum { OPT_INSTANCE, OPT_CNTLID, OPT_ERR }; static const match_table_t opt_tokens = { { OPT_INSTANCE, "instance=%d" }, { OPT_CNTLID, "cntlid=%d" }, { OPT_ERR, NULL }, }; static const char *arg_str(const char * const *strings, size_t array_size, size_t idx) { if (idx < array_size && strings[idx]) return strings[idx]; return "unrecognized"; } static const char * const trtypes[] = { [NVMF_TRTYPE_RDMA] = "rdma", [NVMF_TRTYPE_FC] = "fibre-channel", [NVMF_TRTYPE_LOOP] = "loop", }; static const char *trtype_str(__u8 trtype) { return arg_str(trtypes, ARRAY_SIZE(trtypes), trtype); } static const char * const adrfams[] = { [NVMF_ADDR_FAMILY_PCI] = "pci", [NVMF_ADDR_FAMILY_IP4] = "ipv4", [NVMF_ADDR_FAMILY_IP6] = "ipv6", [NVMF_ADDR_FAMILY_IB] = "infiniband", [NVMF_ADDR_FAMILY_FC] = "fibre-channel", }; static inline const char *adrfam_str(__u8 adrfam) { return arg_str(adrfams, ARRAY_SIZE(adrfams), adrfam); } static const char * const subtypes[] = { [NVME_NQN_DISC] = "discovery subsystem", [NVME_NQN_NVME] = "nvme subsystem", }; static inline const char *subtype_str(__u8 subtype) { return arg_str(subtypes, ARRAY_SIZE(subtypes), subtype); } static const char * const treqs[] = { [NVMF_TREQ_NOT_SPECIFIED] = "not specified", [NVMF_TREQ_REQUIRED] = "required", [NVMF_TREQ_NOT_REQUIRED] = "not required", }; static inline const char *treq_str(__u8 treq) { return arg_str(treqs, ARRAY_SIZE(treqs), treq); } static const char * const prtypes[] = { [NVMF_RDMA_PRTYPE_NOT_SPECIFIED] = "not specified", [NVMF_RDMA_PRTYPE_IB] = "infiniband", [NVMF_RDMA_PRTYPE_ROCE] = "roce", [NVMF_RDMA_PRTYPE_ROCEV2] = "roce-v2", [NVMF_RDMA_PRTYPE_IWARP] = "iwarp", }; static inline const char *prtype_str(__u8 prtype) { return arg_str(prtypes, ARRAY_SIZE(prtypes), prtype); } static const char * const qptypes[] = { [NVMF_RDMA_QPTYPE_CONNECTED] = "connected", [NVMF_RDMA_QPTYPE_DATAGRAM] = "datagram", }; static inline const char *qptype_str(__u8 qptype) { return arg_str(qptypes, ARRAY_SIZE(qptypes), qptype); } static const char * const cms[] = { [NVMF_RDMA_CMS_RDMA_CM] = "rdma-cm", }; static const char *cms_str(__u8 cm) { return arg_str(cms, ARRAY_SIZE(cms), cm); } static int do_discover(char *argstr, bool connect); static int add_ctrl(const char *argstr) { substring_t args[MAX_OPT_ARGS]; char buf[BUF_SIZE], *options, *p; int token, ret, fd, len = strlen(argstr); fd = open(PATH_NVME_FABRICS, O_RDWR); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", PATH_NVME_FABRICS, strerror(errno)); ret = -errno; goto out; } if (write(fd, argstr, len) != len) { fprintf(stderr, "Failed to write to %s: %s\n", PATH_NVME_FABRICS, strerror(errno)); ret = -errno; goto out_close; } len = read(fd, buf, BUF_SIZE); if (len < 0) { fprintf(stderr, "Failed to read from %s: %s\n", PATH_NVME_FABRICS, strerror(errno)); ret = -errno; goto out_close; } buf[len] = '\0'; options = buf; while ((p = strsep(&options, ",\n")) != NULL) { if (!*p) continue; token = match_token(p, opt_tokens, args); switch (token) { case OPT_INSTANCE: if (match_int(args, &token)) goto out_fail; ret = token; goto out_close; default: /* ignore */ break; } } out_fail: fprintf(stderr, "Failed to parse ctrl info for \"%s\"\n", argstr); ret = -EINVAL; out_close: close(fd); out: return ret; } static int remove_ctrl_by_path(char *sysfs_path) { int ret, fd; fd = open(sysfs_path, O_WRONLY); if (fd < 0) { ret = errno; goto out; } if (write(fd, "1", 1) != 1) { ret = errno; goto out_close; } ret = 0; out_close: close(fd); out: return ret; } static int remove_ctrl(int instance) { char *sysfs_path; int ret; if (asprintf(&sysfs_path, "/sys/class/nvme/nvme%d/delete_controller", instance) < 0) { ret = errno; goto out; } ret = remove_ctrl_by_path(sysfs_path); free(sysfs_path); out: return ret; } enum { DISC_OK, DISC_NO_LOG, DISC_GET_NUMRECS, DISC_GET_LOG, DISC_NOT_EQUAL, }; static int nvmf_get_log_page_discovery(const char *dev_path, struct nvmf_disc_rsp_page_hdr **logp, int *numrec) { struct nvmf_disc_rsp_page_hdr *log; unsigned int log_size = 0; unsigned long genctr; int error, fd; fd = open(dev_path, O_RDWR); if (fd < 0) { error = -errno; goto out; } /* first get_log_page we just need numrec entry from discovery hdr. * host supplies its desired bytes via dwords, per NVMe spec. */ log_size = round_up((offsetof(struct nvmf_disc_rsp_page_hdr, numrec) + sizeof(log->numrec)), sizeof(__u32)); /* * Issue first get log page w/numdl small enough to retrieve numrec. * We just want to know how many records to retrieve. */ log = calloc(1, log_size); if (!log) { error = -ENOMEM; goto out_close; } error = nvme_discovery_log(fd, log, log_size); if (error) { error = DISC_GET_NUMRECS; goto out_free_log; } /* check numrec limits */ *numrec = le64_to_cpu(log->numrec); genctr = le64_to_cpu(log->genctr); free(log); if (*numrec == 0) { error = DISC_NO_LOG; goto out_close; } /* we are actually retrieving the entire discovery tables * for the second get_log_page(), per * NVMe spec so no need to round_up(), or there is something * seriously wrong with the standard */ log_size = sizeof(struct nvmf_disc_rsp_page_hdr) + sizeof(struct nvmf_disc_rsp_page_entry) * *numrec; /* allocate discovery log pages based on page_hdr->numrec */ log = calloc(1, log_size); if (!log) { error = -ENOMEM; goto out_close; } /* * issue new get_log_page w/numdl+numdh set to get all records, * up to MAX_DISC_LOGS. */ error = nvme_discovery_log(fd, log, log_size); if (error) { error = DISC_GET_LOG; goto out_free_log; } if (*numrec != le32_to_cpu(log->numrec) || genctr != le64_to_cpu(log->genctr)) { error = DISC_NOT_EQUAL; goto out_free_log; } /* needs to be freed by the caller */ *logp = log; goto out_close; error = DISC_OK; out_free_log: free(log); out_close: close(fd); out: return error; } static int space_strip_len(int max, const char *str) { int i; for (i = max - 1; i >= 0; i--) if (str[i] != '\0' && str[i] != ' ') break; return i + 1; } static void print_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec) { int i; printf("\nDiscovery Log Number of Records %d, " "Generation counter %"PRIu64"\n", numrec, (uint64_t)le64_to_cpu(log->genctr)); for (i = 0; i < numrec; i++) { struct nvmf_disc_rsp_page_entry *e = &log->entries[i]; printf("=====Discovery Log Entry %d======\n", i); printf("trtype: %s\n", trtype_str(e->trtype)); printf("adrfam: %s\n", adrfam_str(e->adrfam)); printf("subtype: %s\n", subtype_str(e->subtype)); printf("treq: %s\n", treq_str(e->treq)); printf("portid: %d\n", e->portid); printf("trsvcid: %.*s\n", space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid), e->trsvcid); printf("subnqn: %s\n", e->subnqn); printf("traddr: %.*s\n", space_strip_len(NVMF_TRADDR_SIZE, e->traddr), e->traddr); switch (e->trtype) { case NVMF_TRTYPE_RDMA: printf("rdma_prtype: %s\n", prtype_str(e->tsas.rdma.prtype)); printf("rdma_qptype: %s\n", qptype_str(e->tsas.rdma.qptype)); printf("rdma_cms: %s\n", cms_str(e->tsas.rdma.cms)); printf("rdma_pkey: 0x%04x\n", e->tsas.rdma.pkey); break; } } } static void save_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec) { int fd; int len, ret; fd = open(cfg.raw, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); if (fd < 0) { fprintf(stderr, "failed to open %s: %s\n", cfg.raw, strerror(errno)); return; } len = sizeof(struct nvmf_disc_rsp_page_hdr) + numrec * sizeof(struct nvmf_disc_rsp_page_entry); ret = write(fd, log, len); if (ret < 0) fprintf(stderr, "failed to write to %s: %s\n", cfg.raw, strerror(errno)); else printf("Discovery log is saved to %s\n", cfg.raw); close(fd); } static int nvmf_hostnqn_file(void) { FILE *f; char hostnqn[NVMF_NQN_SIZE]; int ret = false; f = fopen(PATH_NVMF_HOSTNQN, "r"); if (f == NULL) return false; if (fgets(hostnqn, sizeof(hostnqn), f) == NULL) goto out; cfg.hostnqn = strdup(hostnqn); if (!cfg.hostnqn) goto out; ret = true; out: fclose(f); return ret; } static int nvmf_hostid_file(void) { FILE *f; char hostid[NVMF_HOSTID_SIZE + 1]; int ret = false; f = fopen(PATH_NVMF_HOSTID, "r"); if (f == NULL) return false; if (fgets(hostid, sizeof(hostid), f) == NULL) goto out; cfg.hostid = strdup(hostid); if (!cfg.hostid) goto out; ret = true; out: fclose(f); return ret; } static int add_bool_argument(char **argstr, int *max_len, char *arg_str, bool arg) { int len; if (arg) { len = snprintf(*argstr, *max_len, ",%s", arg_str); if (len < 0) return -EINVAL; *argstr += len; *max_len -= len; } return 0; } static int add_argument(char **argstr, int *max_len, char *arg_str, char *arg) { int len; if (arg) { len = snprintf(*argstr, *max_len, ",%s=%s", arg_str, arg); if (len < 0) return -EINVAL; *argstr += len; *max_len -= len; } return 0; } static int build_options(char *argstr, int max_len) { int len; if (!cfg.transport) { fprintf(stderr, "need a transport (-t) argument\n"); return -EINVAL; } if (strncmp(cfg.transport, "loop", 4)) { if (!cfg.traddr) { fprintf(stderr, "need a address (-a) argument\n"); return -EINVAL; } } /* always specify nqn as first arg - this will init the string */ len = snprintf(argstr, max_len, "nqn=%s", cfg.nqn); if (len < 0) return -EINVAL; argstr += len; max_len -= len; if (add_argument(&argstr, &max_len, "transport", cfg.transport) || add_argument(&argstr, &max_len, "traddr", cfg.traddr) || add_argument(&argstr, &max_len, "host_traddr", cfg.host_traddr) || add_argument(&argstr, &max_len, "trsvcid", cfg.trsvcid) || ((cfg.hostnqn || nvmf_hostnqn_file()) && add_argument(&argstr, &max_len, "hostnqn", cfg.hostnqn)) || ((cfg.hostid || nvmf_hostid_file()) && add_argument(&argstr, &max_len, "hostid", cfg.hostid)) || add_argument(&argstr, &max_len, "nr_io_queues", cfg.nr_io_queues) || add_argument(&argstr, &max_len, "queue_size", cfg.queue_size) || add_argument(&argstr, &max_len, "keep_alive_tmo", cfg.keep_alive_tmo) || add_argument(&argstr, &max_len, "reconnect_delay", cfg.reconnect_delay) || add_argument(&argstr, &max_len, "ctrl_loss_tmo", cfg.ctrl_loss_tmo) || add_bool_argument(&argstr, &max_len, "duplicate_connect", cfg.duplicate_connect)) return -EINVAL; return 0; } static int connect_ctrl(struct nvmf_disc_rsp_page_entry *e) { char argstr[BUF_SIZE], *p = argstr; bool discover = false; int len; switch (e->subtype) { case NVME_NQN_DISC: discover = true; case NVME_NQN_NVME: break; default: fprintf(stderr, "skipping unsupported subtype %d\n", e->subtype); return -EINVAL; } len = sprintf(p, "nqn=%s", e->subnqn); if (len < 0) return -EINVAL; p += len; if (cfg.hostnqn) { len = sprintf(p, ",hostnqn=%s", cfg.hostnqn); if (len < 0) return -EINVAL; p += len; } if (cfg.hostid) { len = sprintf(p, ",hostid=%s", cfg.hostid); if (len < 0) return -EINVAL; p += len; } if (cfg.queue_size) { len = sprintf(p, ",queue_size=%s", cfg.queue_size); if (len < 0) return -EINVAL; p += len; } if (cfg.nr_io_queues) { len = sprintf(p, ",nr_io_queues=%s", cfg.nr_io_queues); if (len < 0) return -EINVAL; p += len; } switch (e->trtype) { case NVMF_TRTYPE_LOOP: /* loop */ len = sprintf(p, ",transport=loop"); if (len < 0) return -EINVAL; p += len; /* we can safely ignore the rest of the entries */ break; case NVMF_TRTYPE_RDMA: switch (e->adrfam) { case NVMF_ADDR_FAMILY_IP4: case NVMF_ADDR_FAMILY_IP6: /* FALLTHRU */ len = sprintf(p, ",transport=rdma"); if (len < 0) return -EINVAL; p += len; len = sprintf(p, ",traddr=%.*s", space_strip_len(NVMF_TRADDR_SIZE, e->traddr), e->traddr); if (len < 0) return -EINVAL; p += len; len = sprintf(p, ",trsvcid=%.*s", space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid), e->trsvcid); if (len < 0) return -EINVAL; p += len; break; default: fprintf(stderr, "skipping unsupported adrfam\n"); return -EINVAL; } break; case NVMF_TRTYPE_FC: switch (e->adrfam) { case NVMF_ADDR_FAMILY_FC: len = sprintf(p, ",transport=fc"); if (len < 0) return -EINVAL; p += len; len = sprintf(p, ",host_traddr=%s", cfg.host_traddr); if (len < 0) return -EINVAL; p+= len; len = sprintf(p, ",traddr=%.*s", space_strip_len(NVMF_TRADDR_SIZE, e->traddr), e->traddr); if (len < 0) return -EINVAL; p += len; break; default: fprintf(stderr, "skipping unsupported adrfam\n"); return -EINVAL; } break; default: fprintf(stderr, "skipping unsupported transport %d\n", e->trtype); return -EINVAL; } if (discover) return do_discover(argstr, true); else return add_ctrl(argstr); } static void connect_ctrls(struct nvmf_disc_rsp_page_hdr *log, int numrec) { int i; for (i = 0; i < numrec; i++) connect_ctrl(&log->entries[i]); } static int do_discover(char *argstr, bool connect) { struct nvmf_disc_rsp_page_hdr *log = NULL; char *dev_name; int instance, numrec = 0, ret; instance = add_ctrl(argstr); if (instance < 0) return instance; if (asprintf(&dev_name, "/dev/nvme%d", instance) < 0) return errno; ret = nvmf_get_log_page_discovery(dev_name, &log, &numrec); free(dev_name); remove_ctrl(instance); switch (ret) { case DISC_OK: if (connect) connect_ctrls(log, numrec); else if (cfg.raw) save_discovery_log(log, numrec); else print_discovery_log(log, numrec); break; case DISC_GET_NUMRECS: fprintf(stderr, "Get number of discovery log entries failed.\n"); break; case DISC_GET_LOG: fprintf(stderr, "Get discovery log entries failed.\n"); break; case DISC_NO_LOG: fprintf(stderr, "No discovery log entries to fetch.\n"); break; case DISC_NOT_EQUAL: fprintf(stderr, "Numrec values of last two get dicovery log page not equal\n"); break; default: fprintf(stderr, "Get dicovery log page failed: %d\n", ret); break; } return ret; } static int discover_from_conf_file(const char *desc, char *argstr, const struct argconfig_commandline_options *opts, bool connect) { FILE *f; char line[256], *ptr, *args, **argv; int argc, err, ret = 0; f = fopen(PATH_NVMF_DISC, "r"); if (f == NULL) { fprintf(stderr, "No discover params given and no %s conf\n", PATH_NVMF_DISC); return -EINVAL; } while (fgets(line, sizeof(line), f) != NULL) { if (line[0] == '#' || line[0] == '\n') continue; args = strdup(line); if (!args) { fprintf(stderr, "failed to strdup args\n"); ret = -ENOMEM; goto out; } argv = calloc(MAX_DISC_ARGS, BUF_SIZE); if (!argv) { fprintf(stderr, "failed to allocate argv vector\n"); free(args); ret = -ENOMEM; goto out; } argc = 0; argv[argc++] = "discover"; while ((ptr = strsep(&args, " =\n")) != NULL) argv[argc++] = ptr; argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg)); err = build_options(argstr, BUF_SIZE); if (err) { ret = err; continue; } err = do_discover(argstr, connect); if (err) { ret = err; continue; } free(args); free(argv); } out: fclose(f); return ret; } int discover(const char *desc, int argc, char **argv, bool connect) { char argstr[BUF_SIZE]; int ret; const struct argconfig_commandline_options command_line_options[] = { {"transport", 't', "LIST", CFG_STRING, &cfg.transport, required_argument, "transport type" }, {"traddr", 'a', "LIST", CFG_STRING, &cfg.traddr, required_argument, "transport address" }, {"trsvcid", 's', "LIST", CFG_STRING, &cfg.trsvcid, required_argument, "transport service id (e.g. IP port)" }, {"host-traddr", 'w', "LIST", CFG_STRING, &cfg.host_traddr, required_argument, "host traddr (e.g. FC WWN's)" }, {"hostnqn", 'q', "LIST", CFG_STRING, &cfg.hostnqn, required_argument, "user-defined hostnqn (if default not used)" }, {"hostid", 'I', "LIST", CFG_STRING, &cfg.hostid, required_argument, "user-defined hostid (if default not used)"}, {"queue-size", 'Q', "LIST", CFG_STRING, &cfg.queue_size, required_argument, "number of io queue elements to use (default 128)" }, {"nr-io-queues",'i', "LIST", CFG_STRING, &cfg.nr_io_queues,required_argument, "number of io queues to use (default is core count)" }, {"raw", 'r', "LIST", CFG_STRING, &cfg.raw, required_argument, "raw output file" }, {NULL}, }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); cfg.nqn = NVME_DISC_SUBSYS_NAME; if (!cfg.transport && !cfg.traddr) { return discover_from_conf_file(desc, argstr, command_line_options, connect); } else { ret = build_options(argstr, BUF_SIZE); if (ret) return ret; return do_discover(argstr, connect); } } int connect(const char *desc, int argc, char **argv) { char argstr[BUF_SIZE]; int instance, ret; const struct argconfig_commandline_options command_line_options[] = { {"transport", 't', "LIST", CFG_STRING, &cfg.transport, required_argument, "transport type" }, {"nqn", 'n', "LIST", CFG_STRING, &cfg.nqn, required_argument, "nqn name" }, {"traddr", 'a', "LIST", CFG_STRING, &cfg.traddr, required_argument, "transport address" }, {"trsvcid", 's', "LIST", CFG_STRING, &cfg.trsvcid, required_argument, "transport service id (e.g. IP port)" }, {"host-traddr", 'w', "LIST", CFG_STRING, &cfg.host_traddr, required_argument, "host traddr (e.g. FC WWN's)" }, {"hostnqn", 'q', "LIST", CFG_STRING, &cfg.hostnqn, required_argument, "user-defined hostnqn" }, {"hostid", 'I', "LIST", CFG_STRING, &cfg.hostid, required_argument, "user-defined hostid (if default not used)"}, {"nr-io-queues", 'i', "LIST", CFG_STRING, &cfg.nr_io_queues, required_argument, "number of io queues to use (default is core count)" }, {"queue-size", 'Q', "LIST", CFG_STRING, &cfg.queue_size, required_argument, "number of io queue elements to use (default 128)" }, {"keep-alive-tmo", 'k', "LIST", CFG_STRING, &cfg.keep_alive_tmo, required_argument, "keep alive timeout period in seconds" }, {"reconnect-delay", 'c', "LIST", CFG_STRING, &cfg.reconnect_delay, required_argument, "reconnect timeout period in seconds" }, {"ctrl-loss-tmo", 'l', "LIST", CFG_STRING, &cfg.ctrl_loss_tmo, required_argument, "controller loss timeout period in seconds" }, {"duplicate_connect", 'D', "", CFG_NONE, &cfg.duplicate_connect, no_argument, "allow duplicate connections between same transport host and subsystem port" }, {NULL}, }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); ret = build_options(argstr, BUF_SIZE); if (ret) return ret; if (!cfg.nqn) { fprintf(stderr, "need a -n argument\n"); return -EINVAL; } instance = add_ctrl(argstr); if (instance < 0) return instance; return 0; } static int scan_sys_nvme_filter(const struct dirent *d) { if (!strcmp(d->d_name, ".")) return 0; if (!strcmp(d->d_name, "..")) return 0; return 1; } /* * Returns 1 if disconnect occurred, 0 otherwise. */ static int disconnect_subsys(char *nqn, char *ctrl) { char *sysfs_nqn_path = NULL, *sysfs_del_path = NULL; char subsysnqn[NVMF_NQN_SIZE] = {}; int fd, ret = 0; if (asprintf(&sysfs_nqn_path, "%s/%s/subsysnqn", SYS_NVME, ctrl) < 0) goto free; if (asprintf(&sysfs_del_path, "%s/%s/delete_controller", SYS_NVME, ctrl) < 0) goto free; fd = open(sysfs_nqn_path, O_RDONLY); if (fd < 0) goto free; if (read(fd, subsysnqn, NVMF_NQN_SIZE) < 0) goto close; subsysnqn[strcspn(subsysnqn, "\n")] = '\0'; if (strcmp(subsysnqn, nqn)) goto close; if (!remove_ctrl_by_path(sysfs_del_path)) ret = 1; close: close(fd); free: free(sysfs_del_path); free(sysfs_nqn_path); return ret; } /* * Returns the number of controllers successfully disconnected. */ static int disconnect_by_nqn(char *nqn) { struct dirent **devices = NULL; int i, n, ret = 0; if (strlen(nqn) > NVMF_NQN_SIZE) return -EINVAL; n = scandir(SYS_NVME, &devices, scan_sys_nvme_filter, alphasort); if (n < 0) return n; for (i = 0; i < n; i++) ret += disconnect_subsys(nqn, devices[i]->d_name); for (i = 0; i < n; i++) free(devices[i]); free(devices); return ret; } static int disconnect_by_device(char *device) { int instance; int ret; device = basename(device); ret = sscanf(device, "nvme%d", &instance); if (ret < 0) return ret; if (!ret) return -1; return remove_ctrl(instance); } int disconnect(const char *desc, int argc, char **argv) { const char *nqn = "nqn name"; const char *device = "nvme device"; int ret = 0; const struct argconfig_commandline_options command_line_options[] = { {"nqn", 'n', "LIST", CFG_STRING, &cfg.nqn, required_argument, nqn}, {"device", 'd', "LIST", CFG_STRING, &cfg.device, required_argument, device}, {NULL}, }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!cfg.nqn && !cfg.device) { fprintf(stderr, "need a -n or -d argument\n"); return -EINVAL; } if (cfg.nqn) { ret = disconnect_by_nqn(cfg.nqn); if (ret < 0) fprintf(stderr, "Failed to disconnect by NQN: %s\n", cfg.nqn); else { printf("NQN:%s disconnected %d controller(s)\n", cfg.nqn, ret); ret = 0; } } if (cfg.device) { ret = disconnect_by_device(cfg.device); if (ret) fprintf(stderr, "Failed to disconnect by device name: %s\n", cfg.device); } return ret; } nvme-cli-1.5/fabrics.h000066400000000000000000000003721322317423600146600ustar00rootroot00000000000000#ifndef _DISCOVER_H #define _DISCOVER_H extern int discover(const char *desc, int argc, char **argv, bool connect); extern int connect(const char *desc, int argc, char **argv); extern int disconnect(const char *desc, int argc, char **argv); #endif nvme-cli-1.5/huawei-nvme.c000066400000000000000000000241001322317423600154620ustar00rootroot00000000000000/* * Copyright (c) 2017-2019 Huawei Corporation or its affiliates. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Author: Zou Ming, * Yang Feng */ #include #include #include #include #include #include #include #include #include #include #include "linux/nvme_ioctl.h" #include "nvme.h" #include "nvme-print.h" #include "nvme-ioctl.h" #include "plugin.h" #include "json.h" #include "argconfig.h" #include "suffix.h" #include #define CREATE_CMD #include "huawei-nvme.h" #define ARRAY_NAME_LEN 80 #define NS_NAME_LEN 40 #define MIN_ARRAY_NAME_LEN 16 #define MIN_NS_NAME_LEN 16 struct huawei_list_item { char node[1024]; struct nvme_id_ctrl ctrl; int nsid; struct nvme_id_ns ns; unsigned block; char ns_name[NS_NAME_LEN]; char array_name[ARRAY_NAME_LEN]; bool huawei_device; }; struct huawei_list_element_len { unsigned int node; unsigned int ns_name; unsigned int nguid; unsigned int ns_id; unsigned int useage; unsigned int array_name; }; static const char *dev = "/dev/"; /* Assume every block device starting with /dev/nvme is an nvme namespace */ static int huawei_scan_dev_filter(const struct dirent *d) { char path[264]; struct stat bd; int ctrl, ns, part; if (d->d_name[0] == '.') return 0; if (strstr(d->d_name, "nvme")) { snprintf(path, sizeof(path), "%s%s", dev, d->d_name); if (stat(path, &bd)) return 0; if (!S_ISBLK(bd.st_mode)) return 0; if (sscanf(d->d_name, "nvme%dn%dp%d", &ctrl, &ns, &part) == 3) return 0; return 1; } return 0; } static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const char *node) { int err; int len; struct stat nvme_stat_info; memset(item, 0, sizeof(*item)); err = nvme_identify_ctrl(fd, &item->ctrl); if (err) return err; /*identify huawei device*/ if (strstr(item->ctrl.mn, "Huawei") == NULL) { item->huawei_device = false; return 0; } else item->huawei_device = true; item->nsid = nvme_get_nsid(fd); err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); if (err) return err; err = fstat(fd, &nvme_stat_info); if (err < 0) return err; strcpy(item->node, node); item->block = S_ISBLK(nvme_stat_info.st_mode); if (item->ns.vs[0] == 0) { len = snprintf(item->ns_name, NS_NAME_LEN, "%s", "----"); if (len < 0) return -EINVAL; } else { memcpy(item->ns_name, item->ns.vs, NS_NAME_LEN); item->ns_name[NS_NAME_LEN - 1] = '\0'; } if (item->ctrl.vs[0] == 0) { len = snprintf(item->array_name, ARRAY_NAME_LEN, "%s", "----"); if (len < 0) return -EINVAL; } else { memcpy(item->array_name, item->ctrl.vs, ARRAY_NAME_LEN); item->array_name[ARRAY_NAME_LEN - 1] = '\0'; } return 0; } static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz) { fmt_sz = snprintf(formatter,fmt_sz, "%-*.*s", (int)tofmtsz, (int)tofmtsz, tofmt); /* trim() the obnoxious trailing white lines */ while (fmt_sz) { if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') { formatter[fmt_sz] = '\0'; break; } fmt_sz--; } } void huawei_json_print_list_items(struct huawei_list_item *list_items, unsigned len) { struct json_object *root; struct json_array *devices; struct json_object *device_attrs; char formatter[128] = { 0 }; int index, i = 0; root = json_create_object(); devices = json_create_array(); for (i = 0; i < len; i++) { device_attrs = json_create_object(); json_object_add_value_string(device_attrs, "DevicePath", list_items[i].node); if (sscanf(list_items[i].node, "/dev/nvme%d", &index) == 1) json_object_add_value_int(device_attrs, "Index", index); format(formatter, sizeof(formatter), list_items[i].ns_name, sizeof(list_items[i].ns_name)); json_object_add_value_string(device_attrs, "NS Name", formatter); format(formatter, sizeof(formatter), list_items[i].array_name, sizeof(list_items[i].array_name)); json_object_add_value_string(device_attrs, "Array Name", formatter); json_array_add_value_object(devices, device_attrs); } json_object_add_value_array(root, "Devices", devices); json_print_object(root, NULL); printf("\n"); json_free_object(root); } static void huawei_print_list_head(struct huawei_list_element_len element_len) { char dash[128]; int i; for (i = 0; i < 128; i++) dash[i] = '-'; dash[127] = '\0'; printf("%-*.*s %-*.*s %-*.*s %-*.*s %-*.*s %-*.*s\n", element_len.node, element_len.node, "Node", element_len.ns_name, element_len.ns_name, "NS Name", element_len.nguid, element_len.nguid, "Nguid", element_len.ns_id, element_len.ns_id, "NS ID", element_len.useage, element_len.useage, "Usage", element_len.array_name, element_len.array_name, "Array Name"); printf("%-.*s %-.*s %-.*s %-.*s %-.*s %-.*s\n", element_len.node, dash, element_len.ns_name, dash, element_len.nguid, dash, element_len.ns_id, dash, element_len.useage, dash, element_len.array_name, dash); } static void huawei_print_list_item(struct huawei_list_item list_item, struct huawei_list_element_len element_len) { long long int lba = 1 << list_item.ns.lbaf[(list_item.ns.flbas & 0x0f)].ds; double nsze = le64_to_cpu(list_item.ns.nsze) * lba; double nuse = le64_to_cpu(list_item.ns.nuse) * lba; const char *s_suffix = suffix_si_get(&nsze); const char *u_suffix = suffix_si_get(&nuse); char usage[128]; char nguid_buf[2 * sizeof(list_item.ns.nguid) + 1]; char *nguid = nguid_buf; sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix); memset(nguid, 0, sizeof(nguid_buf)); for (int i = 0; i < sizeof(list_item.ns.nguid); i++) nguid += sprintf(nguid, "%02x", list_item.ns.nguid[i]); printf("%-*.*s %-*.*s %-*.*s %-*d %-*.*s %-*.*s\n", element_len.node, element_len.node, list_item.node, element_len.ns_name, element_len.ns_name, list_item.ns_name, element_len.nguid, element_len.nguid, nguid_buf, element_len.ns_id, list_item.nsid, element_len.useage, element_len.useage, usage, element_len.array_name, element_len.array_name, list_item.array_name); } static unsigned int choose_len(unsigned int old_len, unsigned int cur_len, unsigned int default_len) { unsigned int temp_len; temp_len = (cur_len > default_len) ? cur_len : default_len; if (temp_len > old_len) { return temp_len; } return old_len; } static unsigned int huawei_get_ns_len(struct huawei_list_item *list_items, unsigned len, unsigned default_len) { int i; unsigned int min_len = default_len; for (i = 0 ; i < len ; i++) min_len = choose_len(min_len , strlen(list_items->ns_name), default_len); return min_len; } static int huawei_get_array_len(struct huawei_list_item *list_items, unsigned len, unsigned default_len) { int i; int min_len = default_len; for (i = 0 ; i < len ; i++) min_len = choose_len(min_len , strlen(list_items->array_name), default_len); return min_len; } static void huawei_print_list_items(struct huawei_list_item *list_items, unsigned len) { unsigned i; struct huawei_list_element_len element_len; element_len.node = 16; element_len.nguid = 2 * sizeof(list_items->ns.nguid) + 1; element_len.ns_id = 9; element_len.useage = 26; element_len.ns_name = huawei_get_ns_len(list_items, len, MIN_NS_NAME_LEN); element_len.array_name = huawei_get_array_len(list_items, len, MIN_ARRAY_NAME_LEN); huawei_print_list_head(element_len); for (i = 0 ; i < len ; i++) huawei_print_list_item(list_items[i], element_len); } static int huawei_list(int argc, char **argv, struct command *command, struct plugin *plugin) { char path[264]; struct dirent **devices; struct huawei_list_item *list_items; unsigned int i, n, fd, ret; unsigned int huawei_num = 0; int fmt; const char *desc = "Retrieve basic information for the given huawei device"; struct config { char *output_format; }; struct config cfg = { .output_format = "normal", }; const struct argconfig_commandline_options opts[] = { {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, "Output Format: normal|json"}, {NULL} }; argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg)); fmt = validate_output_format(cfg.output_format); if (fmt != JSON && fmt != NORMAL) return -EINVAL; n = scandir(dev, &devices, huawei_scan_dev_filter, alphasort); if (n <= 0) return n; list_items = calloc(n, sizeof(*list_items)); if (!list_items) { fprintf(stderr, "can not allocate controller list payload\n"); return ENOMEM; } for (i = 0; i < n; i++) { snprintf(path, sizeof(path), "%s%s", dev, devices[i]->d_name); fd = open(path, O_RDONLY); ret = huawei_get_nvme_info(fd, &list_items[huawei_num], path); if (ret) return ret; if (list_items[huawei_num].huawei_device == true) { huawei_num++; } } if (huawei_num > 0){ if (fmt == JSON) huawei_json_print_list_items(list_items, huawei_num); else huawei_print_list_items(list_items, huawei_num); } for (i = 0; i < n; i++) free(devices[i]); free(devices); free(list_items); return 0; } static void huawei_do_id_ctrl(__u8 *vs, struct json_object *root) { char array_name[ARRAY_NAME_LEN + 1] = {0}; memcpy(array_name, vs, ARRAY_NAME_LEN); if (root) json_object_add_value_string(root, "array name", strlen(array_name) > 1 ? array_name : "NULL"); else printf("array name : %s\n", strlen(array_name) > 1 ? array_name : "NULL"); } static int huawei_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return __id_ctrl(argc, argv, cmd, plugin, huawei_do_id_ctrl); } nvme-cli-1.5/huawei-nvme.h000066400000000000000000000006431322317423600154750ustar00rootroot00000000000000#undef CMD_INC_FILE #define CMD_INC_FILE huawei-nvme #if !defined(HUAWEI_NVME) || defined(CMD_HEADER_MULTI_READ) #define HUAWEI_NVME #include "cmd.h" PLUGIN(NAME("huawei", "Huawei vendor specific extensions"), COMMAND_LIST( ENTRY("list", "List all Huawei NVMe devices and namespaces on machine", huawei_list) ENTRY("id-ctrl", "Huawei identify controller", huawei_id_ctrl) ) ); #endif #include "define_cmd.h" nvme-cli-1.5/intel-nvme.c000066400000000000000000000623351322317423600153270ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "linux/nvme_ioctl.h" #include "nvme.h" #include "nvme-print.h" #include "nvme-ioctl.h" #include "json.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" #define CREATE_CMD #include "intel-nvme.h" #pragma pack(push,1) struct nvme_additional_smart_log_item { __u8 key; __u8 _kp[2]; __u8 norm; __u8 _np; union { __u8 raw[6]; struct wear_level { __le16 min; __le16 max; __le16 avg; } wear_level ; struct thermal_throttle { __u8 pct; __u32 count; } thermal_throttle; }; __u8 _rp; }; #pragma pack(pop) struct nvme_additional_smart_log { struct nvme_additional_smart_log_item program_fail_cnt; struct nvme_additional_smart_log_item erase_fail_cnt; struct nvme_additional_smart_log_item wear_leveling_cnt; struct nvme_additional_smart_log_item e2e_err_cnt; struct nvme_additional_smart_log_item crc_err_cnt; struct nvme_additional_smart_log_item timed_workload_media_wear; struct nvme_additional_smart_log_item timed_workload_host_reads; struct nvme_additional_smart_log_item timed_workload_timer; struct nvme_additional_smart_log_item thermal_throttle_status; struct nvme_additional_smart_log_item retry_buffer_overflow_cnt; struct nvme_additional_smart_log_item pll_lock_loss_cnt; struct nvme_additional_smart_log_item nand_bytes_written; struct nvme_additional_smart_log_item host_bytes_written; }; static void intel_id_ctrl(__u8 *vs, struct json_object *root) { char bl[9]; char health[21]; memcpy(bl, &vs[28], sizeof(bl)); memcpy(health, &vs[4], sizeof(health)); bl[sizeof(bl) - 1] = '\0'; health[sizeof(health) - 1] = '\0'; if (root) { json_object_add_value_int(root, "ss", vs[3]); json_object_add_value_string(root, "health", health[0] ? health : "healthy"); json_object_add_value_string(root, "bl", bl); } else { printf("ss : %d\n", vs[3]); printf("health : %s\n", health[0] ? health : "healthy"); printf("bl : %s\n", bl); } } static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return __id_ctrl(argc, argv, cmd, plugin, intel_id_ctrl); } static void show_intel_smart_log_jsn(struct nvme_additional_smart_log *smart, unsigned int nsid, const char *devname) { struct json_object *root, *entry_stats, *dev_stats, *multi; root = json_create_object(); json_object_add_value_string(root, "Intel Smart log", devname); dev_stats = json_create_object(); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->program_fail_cnt.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->program_fail_cnt.raw)); json_object_add_value_object(dev_stats, "program_fail_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->erase_fail_cnt.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->erase_fail_cnt.raw)); json_object_add_value_object(dev_stats, "erase_fail_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->wear_leveling_cnt.norm); multi = json_create_object(); json_object_add_value_int(multi, "min", le16_to_cpu(smart->wear_leveling_cnt.wear_level.min)); json_object_add_value_int(multi, "max", le16_to_cpu(smart->wear_leveling_cnt.wear_level.max)); json_object_add_value_int(multi, "avg", le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg)); json_object_add_value_object(entry_stats, "raw", multi); json_object_add_value_object(dev_stats, "wear_leveling", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->e2e_err_cnt.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->e2e_err_cnt.raw)); json_object_add_value_object(dev_stats, "end_to_end_error_detection_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->crc_err_cnt.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->crc_err_cnt.raw)); json_object_add_value_object(dev_stats, "crc_error_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_media_wear.norm); json_object_add_value_float(entry_stats, "raw", ((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024); json_object_add_value_object(dev_stats, "timed_workload_media_wear", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_host_reads.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->timed_workload_host_reads.raw)); json_object_add_value_object(dev_stats, "timed_workload_host_reads", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_timer.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->timed_workload_timer.raw)); json_object_add_value_object(dev_stats, "timed_workload_timer", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->thermal_throttle_status.norm); multi = json_create_object(); json_object_add_value_int(multi, "pct", smart->thermal_throttle_status.thermal_throttle.pct); json_object_add_value_int(multi, "cnt", smart->thermal_throttle_status.thermal_throttle.count); json_object_add_value_object(entry_stats, "raw", multi); json_object_add_value_object(dev_stats, "thermal_throttle_status", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->retry_buffer_overflow_cnt.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->retry_buffer_overflow_cnt.raw)); json_object_add_value_object(dev_stats, "retry_buffer_overflow_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->pll_lock_loss_cnt.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->pll_lock_loss_cnt.raw)); json_object_add_value_object(dev_stats, "pll_lock_loss_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_written.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_written.raw)); json_object_add_value_object(dev_stats, "nand_bytes_written", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->host_bytes_written.norm); json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw)); json_object_add_value_object(dev_stats, "host_bytes_written", entry_stats); json_object_add_value_object(root, "Device stats", dev_stats); json_print_object(root, NULL); printf("/n"); json_free_object(root); } static void show_intel_smart_log(struct nvme_additional_smart_log *smart, unsigned int nsid, const char *devname) { printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); printf("key normalized raw\n"); printf("program_fail_count : %3d%% %"PRIu64"\n", smart->program_fail_cnt.norm, int48_to_long(smart->program_fail_cnt.raw)); printf("erase_fail_count : %3d%% %"PRIu64"\n", smart->erase_fail_cnt.norm, int48_to_long(smart->erase_fail_cnt.raw)); printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n", smart->wear_leveling_cnt.norm, le16_to_cpu(smart->wear_leveling_cnt.wear_level.min), le16_to_cpu(smart->wear_leveling_cnt.wear_level.max), le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg)); printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n", smart->e2e_err_cnt.norm, int48_to_long(smart->e2e_err_cnt.raw)); printf("crc_error_count : %3d%% %"PRIu64"\n", smart->crc_err_cnt.norm, int48_to_long(smart->crc_err_cnt.raw)); printf("timed_workload_media_wear : %3d%% %.3f%%\n", smart->timed_workload_media_wear.norm, ((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024); printf("timed_workload_host_reads : %3d%% %"PRIu64"%%\n", smart->timed_workload_host_reads.norm, int48_to_long(smart->timed_workload_host_reads.raw)); printf("timed_workload_timer : %3d%% %"PRIu64" min\n", smart->timed_workload_timer.norm, int48_to_long(smart->timed_workload_timer.raw)); printf("thermal_throttle_status : %3d%% %u%%, cnt: %u\n", smart->thermal_throttle_status.norm, smart->thermal_throttle_status.thermal_throttle.pct, smart->thermal_throttle_status.thermal_throttle.count); printf("retry_buffer_overflow_count : %3d%% %"PRIu64"\n", smart->retry_buffer_overflow_cnt.norm, int48_to_long(smart->retry_buffer_overflow_cnt.raw)); printf("pll_lock_loss_count : %3d%% %"PRIu64"\n", smart->pll_lock_loss_cnt.norm, int48_to_long(smart->pll_lock_loss_cnt.raw)); printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n", smart->nand_bytes_written.norm, int48_to_long(smart->nand_bytes_written.raw)); printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n", smart->host_bytes_written.norm, int48_to_long(smart->host_bytes_written.raw)); } static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_additional_smart_log smart_log; int err, fd; char *desc = "Get Intel vendor specific additional smart log (optionally, "\ "for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; const char *json= "Dump output in json format"; struct config { __u32 namespace_id; int raw_binary; int json; }; struct config cfg = { .namespace_id = NVME_NSID_ALL, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw}, {"json", 'j', "", CFG_NONE, &cfg.json, no_argument, json}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); err = nvme_get_log(fd, cfg.namespace_id, 0xca, sizeof(smart_log), &smart_log); if (!err) { if (cfg.json) show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename); else if (!cfg.raw_binary) show_intel_smart_log(&smart_log, cfg.namespace_id, devicename); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } static int get_market_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { char log[512]; int err, fd; char *desc = "Get Intel Marketing Name log and show it."; const char *raw = "dump output in binary format"; struct config { int raw_binary; }; struct config cfg = { }; const struct argconfig_commandline_options command_line_options[] = { {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); err = nvme_get_log(fd, NVME_NSID_ALL, 0xdd, sizeof(log), log); if (!err) { if (!cfg.raw_binary) printf("Intel Marketing Name Log:\n%s\n", log); else d_raw((unsigned char *)&log, sizeof(log)); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } struct intel_temp_stats { __u64 curr; __u64 last_overtemp; __u64 life_overtemp; __u64 highest_temp; __u64 lowest_temp; __u8 rsvd[40]; __u64 max_operating_temp; __u64 min_operating_temp; __u64 est_offset; }; static void show_temp_stats(struct intel_temp_stats *stats) { printf(" Intel Temperature Statistics\n"); printf("--------------------------------\n"); printf("Current temperature : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->curr)); printf("Last critical overtemp flag : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->last_overtemp)); printf("Life critical overtemp flag : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->life_overtemp)); printf("Highest temperature : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->highest_temp)); printf("Lowest temperature : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->lowest_temp)); printf("Max operating temperature : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->max_operating_temp)); printf("Min operating temperature : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->min_operating_temp)); printf("Estimated offset : %"PRIu64"\n", (uint64_t)le64_to_cpu(stats->est_offset)); } static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct intel_temp_stats stats; int err, fd; char *desc = "Get Intel Marketing Name log and show it."; const char *raw = "dump output in binary format"; struct config { int raw_binary; }; struct config cfg = { }; const struct argconfig_commandline_options command_line_options[] = { {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); err = nvme_get_log(fd, NVME_NSID_ALL, 0xc5, sizeof(stats), &stats); if (!err) { if (!cfg.raw_binary) show_temp_stats(&stats); else d_raw((unsigned char *)&stats, sizeof(stats)); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } struct intel_lat_stats { __u16 maj; __u16 min; __u32 bucket_1[32]; __u32 bucket_2[31]; __u32 bucket_3[31]; }; static void show_lat_stats(struct intel_lat_stats *stats, int write) { int i; printf(" Intel IO %s Command Latency Statistics\n", write ? "Write" : "Read"); printf("-------------------------------------\n"); printf("Major Revision : %u\n", stats->maj); printf("Minor Revision : %u\n", stats->min); printf("\nGroup 1: Range is 0-1ms, step is 32us\n"); for (i = 0; i < 32; i++) printf("Bucket %2d: %u\n", i, stats->bucket_1[i]); printf("\nGroup 2: Range is 1-32ms, step is 1ms\n"); for (i = 0; i < 31; i++) printf("Bucket %2d: %u\n", i, stats->bucket_1[i]); printf("\nGroup 3: Range is 32-1s, step is 32ms:\n"); for (i = 0; i < 31; i++) printf("Bucket %2d: %u\n", i, stats->bucket_1[i]); } static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct intel_lat_stats stats; int err, fd; char *desc = "Get Intel Latency Statistics log and show it."; const char *raw = "dump output in binary format"; const char *write = "Get write statistics (read default)"; struct config { int raw_binary; int write; }; struct config cfg = { }; const struct argconfig_commandline_options command_line_options[] = { {"write", 'w', "", CFG_NONE, &cfg.write, no_argument, write}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, sizeof(stats), &stats); if (!err) { if (!cfg.raw_binary) show_lat_stats(&stats, cfg.write); else d_raw((unsigned char *)&stats, sizeof(stats)); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } struct intel_assert_dump { __u32 coreoffset; __u32 assertsize; __u8 assertdumptype; __u8 assertvalid; __u8 reserved[2]; }; struct intel_event_dump { __u32 numeventdumps; __u32 coresize; __u32 coreoffset; __u32 eventidoffset[16]; __u8 eventIdValidity[16]; }; struct intel_vu_version { __u16 major; __u16 minor; }; struct intel_event_header { __u32 eventidsize; struct intel_event_dump edumps[0]; }; struct intel_vu_log { struct intel_vu_version ver; __u32 header; __u32 size; __u32 numcores; __u8 reserved[4080]; }; struct intel_vu_nlog { struct intel_vu_version ver; __u32 logselect; __u32 totalnlogs; __u32 nlognum; __u32 nlogname; __u32 nlogbytesize; __u32 nlogprimarybuffsize; __u32 tickspersecond; __u32 corecount; __u32 nlogpausestatus; __u32 selectoffsetref; __u32 selectnlogpause; __u32 selectaddedoffset; __u32 nlogbufnum; __u32 nlogbufnummax; __u32 coreselected; __u32 reserved[3]; }; struct intel_cd_log { union { struct { __u32 selectLog : 3; __u32 selectCore : 2; __u32 selectNlog : 8; __u8 selectOffsetRef : 1; __u32 selectNlogPause : 2; __u32 reserved2 : 16; }fields; __u32 entireDword; }u; }; #define max(x,y) (x) > (y) ? (x) : (y) #define min(x,y) (x) > (y) ? (y) : (x) static void print_intel_nlog(struct intel_vu_nlog *intel_nlog) { printf("Version Major %u\n" "Version Minor %u\n" "Log_select %u\n" "totalnlogs %u\n" "nlognum %u\n" "nlogname %u\n" "nlogbytesze %u\n" "nlogprimarybuffsize %u\n" "tickspersecond %u\n" "corecount %u\n" "nlogpausestatus %u\n" "selectoffsetref %u\n" "selectnlogpause %u\n" "selectaddedoffset %u\n" "nlogbufnum %u\n" "nlogbufnummax %u\n" "coreselected %u\n", intel_nlog->ver.major, intel_nlog->ver.minor, intel_nlog->logselect, intel_nlog->totalnlogs, intel_nlog->nlognum, intel_nlog->nlogname, intel_nlog->nlogbytesize, intel_nlog->nlogprimarybuffsize, intel_nlog->tickspersecond, intel_nlog->corecount, intel_nlog->nlogpausestatus, intel_nlog->selectoffsetref, intel_nlog->selectnlogpause, intel_nlog->selectaddedoffset, intel_nlog->nlogbufnum, intel_nlog->nlogbufnummax, intel_nlog->coreselected); } static int read_entire_cmd(struct nvme_passthru_cmd *cmd, int total_size, const size_t max_tfer, int out_fd, int ioctl_fd, __u8 *buf) { int err = 0; size_t dword_tfer = 0; dword_tfer = min(max_tfer, total_size); while (total_size > 0) { err = nvme_submit_passthru(ioctl_fd, NVME_IOCTL_ADMIN_CMD, cmd); if (err) { printf("failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n", cmd->data_len, cmd->cdw13, cmd->cdw12, cmd->cdw10, err, total_size); goto out; } if (out_fd > 0) { err = write(out_fd, buf, cmd->data_len); if (err < 0) { perror("write failure"); goto out; } err = 0; } total_size -= dword_tfer; cmd->cdw13 += dword_tfer; cmd->cdw10 = dword_tfer = min(max_tfer, total_size); cmd->data_len = (min(max_tfer, total_size)) * 4; } out: return err; } static int write_header(__u8 *buf, int fd, size_t amnt) { if (write(fd, buf, amnt) < 0) return 1; return 0; } static int read_header(struct nvme_passthru_cmd *cmd,__u8 *buf, int ioctl_fd, __u32 dw12, int nsid) { memset(cmd, 0, sizeof(*cmd)); memset(buf, 0, 4096); cmd->opcode = 0xd2; cmd->nsid = nsid; cmd->cdw10 = 0x400; cmd->cdw12 = dw12; cmd->data_len = 0x1000; cmd->addr = (unsigned long)(void *)buf; return read_entire_cmd(cmd, 0x400, 0x400, -1, ioctl_fd, buf); } static int setup_file(char *f, char *file, int fd, int type) { struct nvme_id_ctrl ctrl; int err = 0, i = sizeof(ctrl.sn) - 1; err = nvme_identify_ctrl(fd, &ctrl); if (err) return err; /* Remove trailing spaces from the name */ while (i && ctrl.sn[i] == ' ') { ctrl.sn[i] = '\0'; i--; } sprintf(f, "%s_%-.*s.bin", type == 0 ? "Nlog" : type == 1 ? "EventLog" : "AssertLog", (int)sizeof(ctrl.sn), ctrl.sn); return err; } static int get_internal_log_old(__u8 *buf, int output, int fd, struct nvme_passthru_cmd *cmd) { struct intel_vu_log *intel; int err = 0; const int dwmax = 0x400; const int dmamax = 0x1000; intel = (struct intel_vu_log *)buf; printf("Log major:%d minor:%d header:%d size:%d\n", intel->ver.major, intel->ver.minor, intel->header, intel->size); err = write(output, buf, 0x1000); if (err < 0) { perror("write failure"); goto out; } intel->size -= 0x400; cmd->opcode = 0xd2; cmd->cdw10 = min(dwmax, intel->size); cmd->data_len = min(dmamax, intel->size); err = read_entire_cmd(cmd, intel->size, dwmax, output, fd, buf); if (err) goto out; err = 0; out: return err; } static int get_internal_log(int argc, char **argv, struct command *command, struct plugin *plugin) { __u8 buf[0x2000]; char f[0x100]; int err, fd, output, i, j, count = 0, core_num = 1;//, remainder; struct nvme_passthru_cmd cmd; struct intel_cd_log cdlog; struct intel_vu_log *intel = malloc(sizeof(struct intel_vu_log)); struct intel_vu_nlog *intel_nlog = (struct intel_vu_nlog *)buf; struct intel_assert_dump *ad = (struct intel_assert_dump *) intel->reserved; struct intel_event_header *ehdr = (struct intel_event_header *)intel->reserved; char *desc = "Get Intel Firmware Log and save it."; char *log = "Log type: 0, 1, or 2 for nlog, event log, and assert log, respectively."; char *core = "Select which region log should come from. -1 for all"; char *nlognum = "Select which nlog to read. -1 for all nlogs"; char *file = "Output file; defaults to device name provided"; char *verbose = "To print out verbose nlog info"; const char *namespace_id = "Namespace to get logs from"; struct config { __u32 namespace_id; __u32 log; int core; int lnum; char *file; bool verbose; }; struct config cfg = { .namespace_id = -1, .file = NULL, .lnum = -1, .core = -1 }; const struct argconfig_commandline_options command_line_options[] = { {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, required_argument, log}, {"region", 'r', "NUM", CFG_INT, &cfg.core, required_argument, core}, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, required_argument, nlognum}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"output-file", 'o', "FILE", CFG_STRING, &cfg.file, required_argument, file}, {"verbose_nlog", 'v', "" , CFG_NONE, &cfg.verbose, no_argument, verbose}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.log > 2 || cfg.core > 4 || cfg.lnum > 255) { free(intel); return EINVAL; } if (!cfg.file) { err = setup_file(f, cfg.file, fd, cfg.log); if (err) goto out; cfg.file = f; } cdlog.u.entireDword = 0; cdlog.u.fields.selectLog = cfg.log; cdlog.u.fields.selectCore = cfg.core < 0 ? 0 : cfg.core; cdlog.u.fields.selectNlog = cfg.lnum < 0 ? 0 : cfg.lnum; output = open(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666); err = read_header(&cmd, buf, fd, cdlog.u.entireDword, cfg.namespace_id); if (err) goto out; memcpy(intel, buf, sizeof(*intel)); /* for 1.1 Fultondales will use old nlog, but current assert/event */ if ((intel->ver.major < 1 && intel->ver.minor < 1) || (intel->ver.major <= 1 && intel->ver.minor <= 1 && cfg.log == 0)) { cmd.addr = (unsigned long)(void *)buf; err = get_internal_log_old(buf, output, fd, &cmd); goto out; } if (cfg.log == 2) { if (cfg.verbose) printf("Log major:%d minor:%d header:%d size:%d numcores:%d\n", intel->ver.major, intel->ver.minor, intel->header, intel->size, intel->numcores); err = write_header(buf, output, 0x1000); if (err) { perror("write failure"); goto out; } count = intel->numcores; } else if (cfg.log == 0) { if (cfg.lnum < 0) count = intel_nlog->totalnlogs; else count = 1; if (cfg.core < 0) core_num = intel_nlog->corecount; } else if (cfg.log == 1) { core_num = intel->numcores; count = 1; err = write_header(buf, output, sizeof(*intel)); if (err) goto out; } for (j = (cfg.core < 0 ? 0 : cfg.core); j < (cfg.core < 0 ? core_num : cfg.core + 1); j++) { cdlog.u.fields.selectCore = j; for (i = 0; i < count; i++) { if (cfg.log == 2) { if (!ad[i].assertvalid) continue; cmd.cdw13 = ad[i].coreoffset; cmd.cdw10 = 0x400; cmd.data_len = min(0x400, ad[i].assertsize) * 4; err = read_entire_cmd(&cmd, ad[i].assertsize, 0x400, output, fd, buf); if (err) goto out; } else if(cfg.log == 0) { /* If the user selected to read the entire nlog */ if (count > 1) cdlog.u.fields.selectNlog = i; err = read_header(&cmd, buf, fd, cdlog.u.entireDword, cfg.namespace_id); if (err) goto out; err = write_header(buf, output, sizeof(*intel_nlog)); if (err) goto out; if (cfg.verbose) print_intel_nlog(intel_nlog); cmd.cdw13 = 0x400; cmd.cdw10 = 0x400; cmd.data_len = min(0x1000, intel_nlog->nlogbytesize); err = read_entire_cmd(&cmd, intel_nlog->nlogbytesize / 4, 0x400, output, fd, buf); if (err) goto out; } else if (cfg.log == 1) { cmd.cdw13 = ehdr->edumps[j].coreoffset; cmd.cdw10 = 0x400; cmd.data_len = 0x400; err = read_entire_cmd(&cmd, ehdr->edumps[j].coresize, 0x400, output, fd, buf); if (err) goto out; } } } err = 0; out: if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); } else if (err < 0) { perror("intel log"); err = EIO; } else printf("Successfully wrote log to %s\n", cfg.file); free(intel); return err; } nvme-cli-1.5/intel-nvme.h000066400000000000000000000014101322317423600153170ustar00rootroot00000000000000#undef CMD_INC_FILE #define CMD_INC_FILE intel-nvme #if !defined(INTEL_NVME) || defined(CMD_HEADER_MULTI_READ) #define INTEL_NVME #include "cmd.h" PLUGIN(NAME("intel", "Intel vendor specific extensions"), COMMAND_LIST( ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl) ENTRY("smart-log-add", "Retrieve Intel SMART Log, show it", get_additional_smart_log) ENTRY("market-name", "Retrieve Intel Marketing Name log, show it", get_market_log) ENTRY("temp-stats", "Retrieve Intel Temperature Statistics log, show it", get_temp_stats_log) ENTRY("lat-stats", "Retrieve Intel IO Latency Statistics log, show it", get_lat_stats_log) ENTRY("internal-log", "Retrieve Intel internal firmware log, save it", get_internal_log) ) ); #endif #include "define_cmd.h" nvme-cli-1.5/json.c000066400000000000000000000203531322317423600142140ustar00rootroot00000000000000#include #include #include #include #include #include "json.h" static inline void fail_and_notify(void) { fprintf(stderr, "Allocation of memory for json object failed, aborting.\n"); abort(); } struct json_object *json_create_object(void) { void *test = calloc(1, sizeof(struct json_object)); if (!test) fail_and_notify(); return test; } struct json_array *json_create_array(void) { void *test = calloc(1, sizeof(struct json_array)); if (!test) fail_and_notify(); return test; } static struct json_pair *json_create_pair(const char *name, struct json_value *value) { struct json_pair *pair = malloc(sizeof(struct json_pair)); if (pair) { pair->name = strdup(name); pair->value = value; value->parent_type = JSON_PARENT_TYPE_PAIR; value->parent_pair = pair; } else fail_and_notify(); return pair; } static struct json_value *json_create_value_int(long long number) { struct json_value *value = malloc(sizeof(struct json_value)); if (value) { value->type = JSON_TYPE_INTEGER; value->integer_number = number; } else fail_and_notify(); return value; } static struct json_value *json_create_value_float(long double number) { struct json_value *value = malloc(sizeof(struct json_value)); if (value) { value->type = JSON_TYPE_FLOAT; value->float_number = number; } else fail_and_notify(); return value; } static char *strdup_escape(const char *str) { const char *input = str; char *p, *ret; int escapes; if (!strlen(str)) return NULL; escapes = 0; while ((input = strpbrk(input, "\\\"")) != NULL) { escapes++; input++; } p = ret = malloc(strlen(str) + escapes + 1); if (!ret) fail_and_notify(); while (*str) { if (*str == '\\' || *str == '\"') *p++ = '\\'; *p++ = *str++; } *p = '\0'; return ret; } /* * Valid JSON strings must escape '"' and '/' with a preceding '/' */ static struct json_value *json_create_value_string(const char *str) { struct json_value *value = malloc(sizeof(struct json_value)); if (value) { value->type = JSON_TYPE_STRING; value->string = strdup_escape(str); if (!value->string) { free(value); value = NULL; } } if (!value) fail_and_notify(); return value; } static struct json_value *json_create_value_object(struct json_object *obj) { struct json_value *value = malloc(sizeof(struct json_value)); if (value) { value->type = JSON_TYPE_OBJECT; value->object = obj; obj->parent = value; } else fail_and_notify(); return value; } static struct json_value *json_create_value_array(struct json_array *array) { struct json_value *value = malloc(sizeof(struct json_value)); if (value) { value->type = JSON_TYPE_ARRAY; value->array = array; array->parent = value; } else fail_and_notify(); return value; } static void json_free_pair(struct json_pair *pair); static void json_free_value(struct json_value *value); void json_free_object(struct json_object *obj) { int i; for (i = 0; i < obj->pair_cnt; i++) json_free_pair(obj->pairs[i]); free(obj->pairs); free(obj); } static void json_free_array(struct json_array *array) { int i; for (i = 0; i < array->value_cnt; i++) json_free_value(array->values[i]); free(array->values); free(array); } static void json_free_pair(struct json_pair *pair) { json_free_value(pair->value); free(pair->name); free(pair); } static void json_free_value(struct json_value *value) { switch (value->type) { case JSON_TYPE_STRING: free(value->string); break; case JSON_TYPE_OBJECT: json_free_object(value->object); break; case JSON_TYPE_ARRAY: json_free_array(value->array); break; } free(value); } static int json_array_add_value(struct json_array *array, struct json_value *value) { struct json_value **values = realloc(array->values, sizeof(struct json_value *) * (array->value_cnt + 1)); if (!values) return ENOMEM; values[array->value_cnt] = value; array->value_cnt++; array->values = values; value->parent_type = JSON_PARENT_TYPE_ARRAY; value->parent_array = array; return 0; } static int json_object_add_pair(struct json_object *obj, struct json_pair *pair) { struct json_pair **pairs = realloc(obj->pairs, sizeof(struct json_pair *) * (obj->pair_cnt + 1)); if (!pairs) return ENOMEM; pairs[obj->pair_cnt] = pair; obj->pair_cnt++; obj->pairs = pairs; pair->parent = obj; return 0; } int json_object_add_value_type(struct json_object *obj, const char *name, int type, ...) { struct json_value *value; struct json_pair *pair; va_list args; int ret; va_start(args, type); if (type == JSON_TYPE_STRING) value = json_create_value_string(va_arg(args, char *)); else if (type == JSON_TYPE_INTEGER) value = json_create_value_int(va_arg(args, long long)); else if (type == JSON_TYPE_FLOAT) value = json_create_value_float(va_arg(args, long double)); else if (type == JSON_TYPE_OBJECT) value = json_create_value_object(va_arg(args, struct json_object *)); else value = json_create_value_array(va_arg(args, struct json_array *)); va_end(args); if (!value) return ENOMEM; pair = json_create_pair(name, value); if (!pair) { json_free_value(value); return ENOMEM; } ret = json_object_add_pair(obj, pair); if (ret) { json_free_pair(pair); return ENOMEM; } return 0; } static void json_print_array(struct json_array *array, void *); int json_array_add_value_type(struct json_array *array, int type, ...) { struct json_value *value; va_list args; int ret; va_start(args, type); if (type == JSON_TYPE_STRING) value = json_create_value_string(va_arg(args, char *)); else if (type == JSON_TYPE_INTEGER) value = json_create_value_int(va_arg(args, long long)); else if (type == JSON_TYPE_FLOAT) value = json_create_value_float(va_arg(args, double)); else if (type == JSON_TYPE_OBJECT) value = json_create_value_object(va_arg(args, struct json_object *)); else value = json_create_value_array(va_arg(args, struct json_array *)); va_end(args); if (!value) return ENOMEM; ret = json_array_add_value(array, value); if (ret) { json_free_value(value); return ENOMEM; } return 0; } static int json_value_level(struct json_value *value); static int json_pair_level(struct json_pair *pair); static int json_array_level(struct json_array *array); static int json_object_level(struct json_object *object) { if (object->parent == NULL) return 0; return json_value_level(object->parent); } static int json_pair_level(struct json_pair *pair) { return json_object_level(pair->parent) + 1; } static int json_array_level(struct json_array *array) { return json_value_level(array->parent); } static int json_value_level(struct json_value *value) { if (value->parent_type == JSON_PARENT_TYPE_PAIR) return json_pair_level(value->parent_pair); else return json_array_level(value->parent_array) + 1; } static void json_print_level(int level, void *out) { while (level-- > 0) printf(" "); } static void json_print_pair(struct json_pair *pair, void *); static void json_print_array(struct json_array *array, void *); static void json_print_value(struct json_value *value, void *); void json_print_object(struct json_object *obj, void *out) { int i; printf("{\n"); for (i = 0; i < obj->pair_cnt; i++) { if (i > 0) printf(",\n"); json_print_pair(obj->pairs[i], out); } printf("\n"); json_print_level(json_object_level(obj), out); printf("}"); } static void json_print_pair(struct json_pair *pair, void *out) { json_print_level(json_pair_level(pair), out); printf("\"%s\" : ", pair->name); json_print_value(pair->value, out); } static void json_print_array(struct json_array *array, void *out) { int i; printf("[\n"); for (i = 0; i < array->value_cnt; i++) { if (i > 0) printf(",\n"); json_print_level(json_value_level(array->values[i]), out); json_print_value(array->values[i], out); } printf("\n"); json_print_level(json_array_level(array), out); printf("]"); } static void json_print_value(struct json_value *value, void *out) { switch (value->type) { case JSON_TYPE_STRING: printf( "\"%s\"", value->string); break; case JSON_TYPE_INTEGER: printf( "%lld", value->integer_number); break; case JSON_TYPE_FLOAT: printf( "%.0Lf", value->float_number); break; case JSON_TYPE_OBJECT: json_print_object(value->object, out); break; case JSON_TYPE_ARRAY: json_print_array(value->array, out); break; } } nvme-cli-1.5/json.h000066400000000000000000000046221322317423600142220ustar00rootroot00000000000000#ifndef __JSON__H #define __JSON__H struct json_object; struct json_array; struct json_pair; #define JSON_TYPE_STRING 0 #define JSON_TYPE_INTEGER 1 #define JSON_TYPE_FLOAT 2 #define JSON_TYPE_OBJECT 3 #define JSON_TYPE_ARRAY 4 #define JSON_PARENT_TYPE_PAIR 0 #define JSON_PARENT_TYPE_ARRAY 1 struct json_value { int type; union { long long integer_number; long double float_number; char *string; struct json_object *object; struct json_array *array; }; int parent_type; union { struct json_pair *parent_pair; struct json_array *parent_array; }; }; struct json_array { struct json_value **values; int value_cnt; struct json_value *parent; }; struct json_object { struct json_pair **pairs; int pair_cnt; struct json_value *parent; }; struct json_pair { char *name; struct json_value *value; struct json_object *parent; }; struct json_object *json_create_object(void); struct json_array *json_create_array(void); void json_free_object(struct json_object *obj); int json_object_add_value_type(struct json_object *obj, const char *name, int type, ...); #define json_object_add_value_int(obj, name, val) \ json_object_add_value_type((obj), name, JSON_TYPE_INTEGER, (long long) (val)) #define json_object_add_value_float(obj, name, val) \ json_object_add_value_type((obj), name, JSON_TYPE_FLOAT, (val)) #define json_object_add_value_string(obj, name, val) \ json_object_add_value_type((obj), name, JSON_TYPE_STRING, (val)) #define json_object_add_value_object(obj, name, val) \ json_object_add_value_type((obj), name, JSON_TYPE_OBJECT, (val)) #define json_object_add_value_array(obj, name, val) \ json_object_add_value_type((obj), name, JSON_TYPE_ARRAY, (val)) int json_array_add_value_type(struct json_array *array, int type, ...); #define json_array_add_value_int(obj, val) \ json_array_add_value_type((obj), JSON_TYPE_INTEGER, (val)) #define json_array_add_value_float(obj, val) \ json_array_add_value_type((obj), JSON_TYPE_FLOAT, (val)) #define json_array_add_value_string(obj, val) \ json_array_add_value_type((obj), JSON_TYPE_STRING, (val)) #define json_array_add_value_object(obj, val) \ json_array_add_value_type((obj), JSON_TYPE_OBJECT, (val)) #define json_array_add_value_array(obj, val) \ json_array_add_value_type((obj), JSON_TYPE_ARRAY, (val)) #define json_array_last_value_object(obj) \ (obj->values[obj->value_cnt - 1]->object) void json_print_object(struct json_object *obj, void *); #endif nvme-cli-1.5/linux/000077500000000000000000000000001322317423600142335ustar00rootroot00000000000000nvme-cli-1.5/linux/lightnvm.h000066400000000000000000000076141322317423600162440ustar00rootroot00000000000000/* * Copyright (C) 2015 CNEX Labs. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, * USA. */ #ifndef _UAPI_LINUX_LIGHTNVM_H #define _UAPI_LINUX_LIGHTNVM_H #ifdef __KERNEL__ #include #include #else /* __KERNEL__ */ #include #include #define DISK_NAME_LEN 32 #endif /* __KERNEL__ */ #include #include #define NVM_TTYPE_NAME_MAX 48 #define NVM_TTYPE_MAX 63 #define NVM_MMTYPE_LEN 8 #define NVM_CTRL_FILE "/dev/lightnvm/control" struct nvm_ioctl_info_tgt { __u32 version[3]; __u32 reserved; char tgtname[NVM_TTYPE_NAME_MAX]; }; struct nvm_ioctl_info { __u32 version[3]; /* in/out - major, minor, patch */ __u16 tgtsize; /* number of targets */ __u16 reserved16; /* pad to 4K page */ __u32 reserved[12]; struct nvm_ioctl_info_tgt tgts[NVM_TTYPE_MAX]; }; enum { NVM_DEVICE_ACTIVE = 1 << 0, }; struct nvm_ioctl_device_info { char devname[DISK_NAME_LEN]; char bmname[NVM_TTYPE_NAME_MAX]; __u32 bmversion[3]; __u32 flags; __u32 reserved[8]; }; struct nvm_ioctl_get_devices { __u32 nr_devices; __u32 reserved[31]; struct nvm_ioctl_device_info info[31]; }; struct nvm_ioctl_create_simple { __u32 lun_begin; __u32 lun_end; }; enum { NVM_CONFIG_TYPE_SIMPLE = 0, }; struct nvm_ioctl_create_conf { __u32 type; union { struct nvm_ioctl_create_simple s; }; }; enum { NVM_TARGET_FACTORY = 1 << 0, /* Init target in factory mode */ }; struct nvm_ioctl_create { char dev[DISK_NAME_LEN]; /* open-channel SSD device */ char tgttype[NVM_TTYPE_NAME_MAX]; /* target type name */ char tgtname[DISK_NAME_LEN]; /* dev to expose target as */ __u32 flags; struct nvm_ioctl_create_conf conf; }; struct nvm_ioctl_remove { char tgtname[DISK_NAME_LEN]; __u32 flags; }; struct nvm_ioctl_dev_init { char dev[DISK_NAME_LEN]; /* open-channel SSD device */ char mmtype[NVM_MMTYPE_LEN]; /* register to media manager */ __u32 flags; }; enum { NVM_FACTORY_ERASE_ONLY_USER = 1 << 0, /* erase only blocks used as * host blks or grown blks */ NVM_FACTORY_RESET_HOST_BLKS = 1 << 1, /* remove host blk marks */ NVM_FACTORY_RESET_GRWN_BBLKS = 1 << 2, /* remove grown blk marks */ NVM_FACTORY_NR_BITS = 1 << 3, /* stops here */ }; struct nvm_ioctl_dev_factory { char dev[DISK_NAME_LEN]; __u32 flags; }; /* The ioctl type, 'L', 0x20 - 0x2F documented in ioctl-number.txt */ enum { /* top level cmds */ NVM_INFO_CMD = 0x20, NVM_GET_DEVICES_CMD, /* device level cmds */ NVM_DEV_CREATE_CMD, NVM_DEV_REMOVE_CMD, /* Init a device to support LightNVM media managers */ NVM_DEV_INIT_CMD, /* Factory reset device */ NVM_DEV_FACTORY_CMD, }; #define NVM_IOCTL 'L' /* 0x4c */ #define NVM_INFO _IOWR(NVM_IOCTL, NVM_INFO_CMD, \ struct nvm_ioctl_info) #define NVM_GET_DEVICES _IOR(NVM_IOCTL, NVM_GET_DEVICES_CMD, \ struct nvm_ioctl_get_devices) #define NVM_DEV_CREATE _IOW(NVM_IOCTL, NVM_DEV_CREATE_CMD, \ struct nvm_ioctl_create) #define NVM_DEV_REMOVE _IOW(NVM_IOCTL, NVM_DEV_REMOVE_CMD, \ struct nvm_ioctl_remove) #define NVM_DEV_INIT _IOW(NVM_IOCTL, NVM_DEV_INIT_CMD, \ struct nvm_ioctl_dev_init) #define NVM_DEV_FACTORY _IOW(NVM_IOCTL, NVM_DEV_FACTORY_CMD, \ struct nvm_ioctl_dev_factory) #define NVM_VERSION_MAJOR 1 #define NVM_VERSION_MINOR 0 #define NVM_VERSION_PATCHLEVEL 0 #endif nvme-cli-1.5/linux/nvme.h000066400000000000000000000704301322317423600153550ustar00rootroot00000000000000/* * Definitions for the NVM Express interface * Copyright (c) 2011-2014, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ #ifndef _LINUX_NVME_H #define _LINUX_NVME_H #include #include /* NQN names in commands fields specified one size */ #define NVMF_NQN_FIELD_LEN 256 /* However the max length of a qualified name is another size */ #define NVMF_NQN_SIZE 223 #define NVMF_TRSVCID_SIZE 32 #define NVMF_TRADDR_SIZE 256 #define NVMF_TSAS_SIZE 256 #define NVME_DISC_SUBSYS_NAME "nqn.2014-08.org.nvmexpress.discovery" #define NVME_RDMA_IP_PORT 4420 #define NVME_NSID_ALL 0xffffffff enum nvme_subsys_type { NVME_NQN_DISC = 1, /* Discovery type target subsystem */ NVME_NQN_NVME = 2, /* NVME type target subsystem */ }; /* Address Family codes for Discovery Log Page entry ADRFAM field */ enum { NVMF_ADDR_FAMILY_PCI = 0, /* PCIe */ NVMF_ADDR_FAMILY_IP4 = 1, /* IP4 */ NVMF_ADDR_FAMILY_IP6 = 2, /* IP6 */ NVMF_ADDR_FAMILY_IB = 3, /* InfiniBand */ NVMF_ADDR_FAMILY_FC = 4, /* Fibre Channel */ }; /* Transport Type codes for Discovery Log Page entry TRTYPE field */ enum { NVMF_TRTYPE_RDMA = 1, /* RDMA */ NVMF_TRTYPE_FC = 2, /* Fibre Channel */ NVMF_TRTYPE_LOOP = 254, /* Reserved for host usage */ NVMF_TRTYPE_MAX, }; /* Transport Requirements codes for Discovery Log Page entry TREQ field */ enum { NVMF_TREQ_NOT_SPECIFIED = 0, /* Not specified */ NVMF_TREQ_REQUIRED = 1, /* Required */ NVMF_TREQ_NOT_REQUIRED = 2, /* Not Required */ }; /* RDMA QP Service Type codes for Discovery Log Page entry TSAS * RDMA_QPTYPE field */ enum { NVMF_RDMA_QPTYPE_CONNECTED = 1, /* Reliable Connected */ NVMF_RDMA_QPTYPE_DATAGRAM = 2, /* Reliable Datagram */ }; /* RDMA QP Service Type codes for Discovery Log Page entry TSAS * RDMA_QPTYPE field */ enum { NVMF_RDMA_PRTYPE_NOT_SPECIFIED = 1, /* No Provider Specified */ NVMF_RDMA_PRTYPE_IB = 2, /* InfiniBand */ NVMF_RDMA_PRTYPE_ROCE = 3, /* InfiniBand RoCE */ NVMF_RDMA_PRTYPE_ROCEV2 = 4, /* InfiniBand RoCEV2 */ NVMF_RDMA_PRTYPE_IWARP = 5, /* IWARP */ }; /* RDMA Connection Management Service Type codes for Discovery Log Page * entry TSAS RDMA_CMS field */ enum { NVMF_RDMA_CMS_RDMA_CM = 1, /* Sockets based endpoint addressing */ }; #define NVME_AQ_DEPTH 32 #define NVME_NR_AEN_COMMANDS 1 #define NVME_AQ_BLK_MQ_DEPTH (NVME_AQ_DEPTH - NVME_NR_AEN_COMMANDS) /* * Subtract one to leave an empty queue entry for 'Full Queue' condition. See * NVM-Express 1.2 specification, section 4.1.2. */ #define NVME_AQ_MQ_TAG_DEPTH (NVME_AQ_BLK_MQ_DEPTH - 1) enum { NVME_REG_CAP = 0x0000, /* Controller Capabilities */ NVME_REG_VS = 0x0008, /* Version */ NVME_REG_INTMS = 0x000c, /* Interrupt Mask Set */ NVME_REG_INTMC = 0x0010, /* Interrupt Mask Clear */ NVME_REG_CC = 0x0014, /* Controller Configuration */ NVME_REG_CSTS = 0x001c, /* Controller Status */ NVME_REG_NSSR = 0x0020, /* NVM Subsystem Reset */ NVME_REG_AQA = 0x0024, /* Admin Queue Attributes */ NVME_REG_ASQ = 0x0028, /* Admin SQ Base Address */ NVME_REG_ACQ = 0x0030, /* Admin CQ Base Address */ NVME_REG_CMBLOC = 0x0038, /* Controller Memory Buffer Location */ NVME_REG_CMBSZ = 0x003c, /* Controller Memory Buffer Size */ NVME_REG_BPINFO = 0x0040, /* Boot Partition Information */ NVME_REG_BPRSEL = 0x0044, /* Boot Partition Read Select */ NVME_REG_BPMBL = 0x0048, /* Boot Partition Memory Buffer Location */ NVME_REG_DBS = 0x1000, /* SQ 0 Tail Doorbell */ }; #define NVME_CAP_MQES(cap) ((cap) & 0xffff) #define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) #define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) #define NVME_CAP_NSSRC(cap) (((cap) >> 36) & 0x1) #define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf) #define NVME_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf) #define NVME_CMB_BIR(cmbloc) ((cmbloc) & 0x7) #define NVME_CMB_OFST(cmbloc) (((cmbloc) >> 12) & 0xfffff) #define NVME_CMB_SZ(cmbsz) (((cmbsz) >> 12) & 0xfffff) #define NVME_CMB_SZU(cmbsz) (((cmbsz) >> 8) & 0xf) #define NVME_CMB_WDS(cmbsz) ((cmbsz) & 0x10) #define NVME_CMB_RDS(cmbsz) ((cmbsz) & 0x8) #define NVME_CMB_LISTS(cmbsz) ((cmbsz) & 0x4) #define NVME_CMB_CQS(cmbsz) ((cmbsz) & 0x2) #define NVME_CMB_SQS(cmbsz) ((cmbsz) & 0x1) /* * Submission and Completion Queue Entry Sizes for the NVM command set. * (In bytes and specified as a power of two (2^n)). */ #define NVME_NVM_IOSQES 6 #define NVME_NVM_IOCQES 4 enum { NVME_CC_ENABLE = 1 << 0, NVME_CC_CSS_NVM = 0 << 4, NVME_CC_EN_SHIFT = 0, NVME_CC_CSS_SHIFT = 4, NVME_CC_MPS_SHIFT = 7, NVME_CC_AMS_SHIFT = 11, NVME_CC_SHN_SHIFT = 14, NVME_CC_IOSQES_SHIFT = 16, NVME_CC_IOCQES_SHIFT = 20, NVME_CC_AMS_RR = 0 << NVME_CC_AMS_SHIFT, NVME_CC_AMS_WRRU = 1 << NVME_CC_AMS_SHIFT, NVME_CC_AMS_VS = 7 << NVME_CC_AMS_SHIFT, NVME_CC_SHN_NONE = 0 << NVME_CC_SHN_SHIFT, NVME_CC_SHN_NORMAL = 1 << NVME_CC_SHN_SHIFT, NVME_CC_SHN_ABRUPT = 2 << NVME_CC_SHN_SHIFT, NVME_CC_SHN_MASK = 3 << NVME_CC_SHN_SHIFT, NVME_CC_IOSQES = NVME_NVM_IOSQES << NVME_CC_IOSQES_SHIFT, NVME_CC_IOCQES = NVME_NVM_IOCQES << NVME_CC_IOCQES_SHIFT, NVME_CSTS_RDY = 1 << 0, NVME_CSTS_CFS = 1 << 1, NVME_CSTS_NSSRO = 1 << 4, NVME_CSTS_PP = 1 << 5, NVME_CSTS_SHST_NORMAL = 0 << 2, NVME_CSTS_SHST_OCCUR = 1 << 2, NVME_CSTS_SHST_CMPLT = 2 << 2, NVME_CSTS_SHST_MASK = 3 << 2, }; struct nvme_id_power_state { __le16 max_power; /* centiwatts */ __u8 rsvd2; __u8 flags; __le32 entry_lat; /* microseconds */ __le32 exit_lat; /* microseconds */ __u8 read_tput; __u8 read_lat; __u8 write_tput; __u8 write_lat; __le16 idle_power; __u8 idle_scale; __u8 rsvd19; __le16 active_power; __u8 active_work_scale; __u8 rsvd23[9]; }; enum { NVME_PS_FLAGS_MAX_POWER_SCALE = 1 << 0, NVME_PS_FLAGS_NON_OP_STATE = 1 << 1, }; struct nvme_id_ctrl { __le16 vid; __le16 ssvid; char sn[20]; char mn[40]; char fr[8]; __u8 rab; __u8 ieee[3]; __u8 cmic; __u8 mdts; __le16 cntlid; __le32 ver; __le32 rtd3r; __le32 rtd3e; __le32 oaes; __le32 ctratt; __u8 rsvd100[156]; __le16 oacs; __u8 acl; __u8 aerl; __u8 frmw; __u8 lpa; __u8 elpe; __u8 npss; __u8 avscc; __u8 apsta; __le16 wctemp; __le16 cctemp; __le16 mtfa; __le32 hmpre; __le32 hmmin; __u8 tnvmcap[16]; __u8 unvmcap[16]; __le32 rpmbs; __le16 edstt; __u8 dsto; __u8 fwug; __le16 kas; __le16 hctma; __le16 mntmt; __le16 mxtmt; __le32 sanicap; __le32 hmminds; __le16 hmmaxd; __u8 rsvd338[174]; __u8 sqes; __u8 cqes; __le16 maxcmd; __le32 nn; __le16 oncs; __le16 fuses; __u8 fna; __u8 vwc; __le16 awun; __le16 awupf; __u8 nvscc; __u8 rsvd531; __le16 acwu; __u8 rsvd534[2]; __le32 sgls; __u8 rsvd540[228]; char subnqn[256]; __u8 rsvd1024[768]; __le32 ioccsz; __le32 iorcsz; __le16 icdoff; __u8 ctrattr; __u8 msdbd; __u8 rsvd1804[244]; struct nvme_id_power_state psd[32]; __u8 vs[1024]; }; enum { NVME_CTRL_ONCS_COMPARE = 1 << 0, NVME_CTRL_ONCS_WRITE_UNCORRECTABLE = 1 << 1, NVME_CTRL_ONCS_DSM = 1 << 2, NVME_CTRL_ONCS_WRITE_ZEROES = 1 << 3, NVME_CTRL_ONCS_TIMESTAMP = 1 << 6, NVME_CTRL_VWC_PRESENT = 1 << 0, NVME_CTRL_OACS_SEC_SUPP = 1 << 0, NVME_CTRL_OACS_DIRECTIVES = 1 << 5, NVME_CTRL_OACS_DBBUF_SUPP = 1 << 8, NVME_CTRL_LPA_CMD_EFFECTS_LOG = 1 << 1, }; struct nvme_lbaf { __le16 ms; __u8 ds; __u8 rp; }; struct nvme_id_ns { __le64 nsze; __le64 ncap; __le64 nuse; __u8 nsfeat; __u8 nlbaf; __u8 flbas; __u8 mc; __u8 dpc; __u8 dps; __u8 nmic; __u8 rescap; __u8 fpi; __u8 rsvd33; __le16 nawun; __le16 nawupf; __le16 nacwu; __le16 nabsn; __le16 nabo; __le16 nabspf; __le16 noiob; __u8 nvmcap[16]; __u8 rsvd64[40]; __u8 nguid[16]; __u8 eui64[8]; struct nvme_lbaf lbaf[16]; __u8 rsvd192[192]; __u8 vs[3712]; }; enum { NVME_ID_CNS_NS = 0x00, NVME_ID_CNS_CTRL = 0x01, NVME_ID_CNS_NS_ACTIVE_LIST = 0x02, NVME_ID_CNS_NS_DESC_LIST = 0x03, NVME_ID_CNS_NS_PRESENT_LIST = 0x10, NVME_ID_CNS_NS_PRESENT = 0x11, NVME_ID_CNS_CTRL_NS_LIST = 0x12, NVME_ID_CNS_CTRL_LIST = 0x13, }; enum { NVME_DIR_IDENTIFY = 0x00, NVME_DIR_STREAMS = 0x01, NVME_DIR_SND_ID_OP_ENABLE = 0x01, NVME_DIR_SND_ST_OP_REL_ID = 0x01, NVME_DIR_SND_ST_OP_REL_RSC = 0x02, NVME_DIR_RCV_ID_OP_PARAM = 0x01, NVME_DIR_RCV_ST_OP_PARAM = 0x01, NVME_DIR_RCV_ST_OP_STATUS = 0x02, NVME_DIR_RCV_ST_OP_RESOURCE = 0x03, NVME_DIR_ENDIR = 0x01, }; enum { NVME_NS_FEAT_THIN = 1 << 0, NVME_NS_FLBAS_LBA_MASK = 0xf, NVME_NS_FLBAS_META_EXT = 0x10, NVME_LBAF_RP_BEST = 0, NVME_LBAF_RP_BETTER = 1, NVME_LBAF_RP_GOOD = 2, NVME_LBAF_RP_DEGRADED = 3, NVME_NS_DPC_PI_LAST = 1 << 4, NVME_NS_DPC_PI_FIRST = 1 << 3, NVME_NS_DPC_PI_TYPE3 = 1 << 2, NVME_NS_DPC_PI_TYPE2 = 1 << 1, NVME_NS_DPC_PI_TYPE1 = 1 << 0, NVME_NS_DPS_PI_FIRST = 1 << 3, NVME_NS_DPS_PI_MASK = 0x7, NVME_NS_DPS_PI_TYPE1 = 1, NVME_NS_DPS_PI_TYPE2 = 2, NVME_NS_DPS_PI_TYPE3 = 3, }; struct nvme_ns_id_desc { __u8 nidt; __u8 nidl; __le16 reserved; }; #define NVME_NIDT_EUI64_LEN 8 #define NVME_NIDT_NGUID_LEN 16 #define NVME_NIDT_UUID_LEN 16 enum { NVME_NIDT_EUI64 = 0x01, NVME_NIDT_NGUID = 0x02, NVME_NIDT_UUID = 0x03, }; struct nvme_smart_log { __u8 critical_warning; __u8 temperature[2]; __u8 avail_spare; __u8 spare_thresh; __u8 percent_used; __u8 rsvd6[26]; __u8 data_units_read[16]; __u8 data_units_written[16]; __u8 host_reads[16]; __u8 host_writes[16]; __u8 ctrl_busy_time[16]; __u8 power_cycles[16]; __u8 power_on_hours[16]; __u8 unsafe_shutdowns[16]; __u8 media_errors[16]; __u8 num_err_log_entries[16]; __le32 warning_temp_time; __le32 critical_comp_time; __le16 temp_sensor[8]; __le32 thm_temp1_trans_count; __le32 thm_temp2_trans_count; __le32 thm_temp1_total_time; __le32 thm_temp2_total_time; __u8 rsvd232[280]; }; struct nvme_fw_slot_info_log { __u8 afi; __u8 rsvd1[7]; __le64 frs[7]; __u8 rsvd64[448]; }; enum { NVME_CMD_EFFECTS_CSUPP = 1 << 0, NVME_CMD_EFFECTS_LBCC = 1 << 1, NVME_CMD_EFFECTS_NCC = 1 << 2, NVME_CMD_EFFECTS_NIC = 1 << 3, NVME_CMD_EFFECTS_CCC = 1 << 4, NVME_CMD_EFFECTS_CSE_MASK = 3 << 16, }; struct nvme_effects_log { __le32 acs[256]; __le32 iocs[256]; __u8 resv[2048]; }; enum { NVME_SMART_CRIT_SPARE = 1 << 0, NVME_SMART_CRIT_TEMPERATURE = 1 << 1, NVME_SMART_CRIT_RELIABILITY = 1 << 2, NVME_SMART_CRIT_MEDIA = 1 << 3, NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4, }; enum { NVME_AER_ERROR = 0, NVME_AER_SMART = 1, NVME_AER_CSS = 6, NVME_AER_VS = 7, NVME_AER_NOTICE_NS_CHANGED = 0x0002, NVME_AER_NOTICE_FW_ACT_STARTING = 0x0102, }; struct nvme_lba_range_type { __u8 type; __u8 attributes; __u8 rsvd2[14]; __u64 slba; __u64 nlb; __u8 guid[16]; __u8 rsvd48[16]; }; enum { NVME_LBART_TYPE_FS = 0x01, NVME_LBART_TYPE_RAID = 0x02, NVME_LBART_TYPE_CACHE = 0x03, NVME_LBART_TYPE_SWAP = 0x04, NVME_LBART_ATTRIB_TEMP = 1 << 0, NVME_LBART_ATTRIB_HIDE = 1 << 1, }; struct nvme_reservation_status { __le32 gen; __u8 rtype; __u8 regctl[2]; __u8 resv5[2]; __u8 ptpls; __u8 resv10[13]; struct { __le16 cntlid; __u8 rcsts; __u8 resv3[5]; __le64 hostid; __le64 rkey; } regctl_ds[]; }; struct nvme_reservation_status_ext { __le32 gen; __u8 rtype; __u8 regctl[2]; __u8 resv5[2]; __u8 ptpls; __u8 resv10[14]; __u8 resv24[40]; struct { __le16 cntlid; __u8 rcsts; __u8 resv3[5]; __le64 rkey; __u8 hostid[16]; __u8 resv32[32]; } regctl_eds[]; }; enum nvme_async_event_type { NVME_AER_TYPE_ERROR = 0, NVME_AER_TYPE_SMART = 1, NVME_AER_TYPE_NOTICE = 2, }; /* I/O commands */ enum nvme_opcode { nvme_cmd_flush = 0x00, nvme_cmd_write = 0x01, nvme_cmd_read = 0x02, nvme_cmd_write_uncor = 0x04, nvme_cmd_compare = 0x05, nvme_cmd_write_zeroes = 0x08, nvme_cmd_dsm = 0x09, nvme_cmd_resv_register = 0x0d, nvme_cmd_resv_report = 0x0e, nvme_cmd_resv_acquire = 0x11, nvme_cmd_resv_release = 0x15, }; /* * Descriptor subtype - lower 4 bits of nvme_(keyed_)sgl_desc identifier * * @NVME_SGL_FMT_ADDRESS: absolute address of the data block * @NVME_SGL_FMT_OFFSET: relative offset of the in-capsule data block * @NVME_SGL_FMT_TRANSPORT_A: transport defined format, value 0xA * @NVME_SGL_FMT_INVALIDATE: RDMA transport specific remote invalidation * request subtype */ enum { NVME_SGL_FMT_ADDRESS = 0x00, NVME_SGL_FMT_OFFSET = 0x01, NVME_SGL_FMT_TRANSPORT_A = 0x0A, NVME_SGL_FMT_INVALIDATE = 0x0f, }; /* * Descriptor type - upper 4 bits of nvme_(keyed_)sgl_desc identifier * * For struct nvme_sgl_desc: * @NVME_SGL_FMT_DATA_DESC: data block descriptor * @NVME_SGL_FMT_SEG_DESC: sgl segment descriptor * @NVME_SGL_FMT_LAST_SEG_DESC: last sgl segment descriptor * * For struct nvme_keyed_sgl_desc: * @NVME_KEY_SGL_FMT_DATA_DESC: keyed data block descriptor * * Transport-specific SGL types: * @NVME_TRANSPORT_SGL_DATA_DESC: Transport SGL data dlock descriptor */ enum { NVME_SGL_FMT_DATA_DESC = 0x00, NVME_SGL_FMT_SEG_DESC = 0x02, NVME_SGL_FMT_LAST_SEG_DESC = 0x03, NVME_KEY_SGL_FMT_DATA_DESC = 0x04, NVME_TRANSPORT_SGL_DATA_DESC = 0x05, }; struct nvme_sgl_desc { __le64 addr; __le32 length; __u8 rsvd[3]; __u8 type; }; struct nvme_keyed_sgl_desc { __le64 addr; __u8 length[3]; __u8 key[4]; __u8 type; }; union nvme_data_ptr { struct { __le64 prp1; __le64 prp2; }; struct nvme_sgl_desc sgl; struct nvme_keyed_sgl_desc ksgl; }; /* * Lowest two bits of our flags field (FUSE field in the spec): * * @NVME_CMD_FUSE_FIRST: Fused Operation, first command * @NVME_CMD_FUSE_SECOND: Fused Operation, second command * * Highest two bits in our flags field (PSDT field in the spec): * * @NVME_CMD_PSDT_SGL_METABUF: Use SGLS for this transfer, * If used, MPTR contains addr of single physical buffer (byte aligned). * @NVME_CMD_PSDT_SGL_METASEG: Use SGLS for this transfer, * If used, MPTR contains an address of an SGL segment containing * exactly 1 SGL descriptor (qword aligned). */ enum { NVME_CMD_FUSE_FIRST = (1 << 0), NVME_CMD_FUSE_SECOND = (1 << 1), NVME_CMD_SGL_METABUF = (1 << 6), NVME_CMD_SGL_METASEG = (1 << 7), NVME_CMD_SGL_ALL = NVME_CMD_SGL_METABUF | NVME_CMD_SGL_METASEG, }; struct nvme_common_command { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __le32 cdw2[2]; __le64 metadata; union nvme_data_ptr dptr; __le32 cdw10[6]; }; struct nvme_rw_command { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2; __le64 metadata; union nvme_data_ptr dptr; __le64 slba; __le16 length; __le16 control; __le32 dsmgmt; __le32 reftag; __le16 apptag; __le16 appmask; }; enum { NVME_RW_LR = 1 << 15, NVME_RW_FUA = 1 << 14, NVME_RW_DEAC = 1 << 9, NVME_RW_DSM_FREQ_UNSPEC = 0, NVME_RW_DSM_FREQ_TYPICAL = 1, NVME_RW_DSM_FREQ_RARE = 2, NVME_RW_DSM_FREQ_READS = 3, NVME_RW_DSM_FREQ_WRITES = 4, NVME_RW_DSM_FREQ_RW = 5, NVME_RW_DSM_FREQ_ONCE = 6, NVME_RW_DSM_FREQ_PREFETCH = 7, NVME_RW_DSM_FREQ_TEMP = 8, NVME_RW_DSM_LATENCY_NONE = 0 << 4, NVME_RW_DSM_LATENCY_IDLE = 1 << 4, NVME_RW_DSM_LATENCY_NORM = 2 << 4, NVME_RW_DSM_LATENCY_LOW = 3 << 4, NVME_RW_DSM_SEQ_REQ = 1 << 6, NVME_RW_DSM_COMPRESSED = 1 << 7, NVME_RW_PRINFO_PRCHK_REF = 1 << 10, NVME_RW_PRINFO_PRCHK_APP = 1 << 11, NVME_RW_PRINFO_PRCHK_GUARD = 1 << 12, NVME_RW_PRINFO_PRACT = 1 << 13, NVME_RW_DTYPE_STREAMS = 1 << 4, }; struct nvme_dsm_cmd { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2[2]; union nvme_data_ptr dptr; __le32 nr; __le32 attributes; __u32 rsvd12[4]; }; enum { NVME_DSMGMT_IDR = 1 << 0, NVME_DSMGMT_IDW = 1 << 1, NVME_DSMGMT_AD = 1 << 2, }; #define NVME_DSM_MAX_RANGES 256 struct nvme_dsm_range { __le32 cattr; __le32 nlb; __le64 slba; }; struct nvme_write_zeroes_cmd { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2; __le64 metadata; union nvme_data_ptr dptr; __le64 slba; __le16 length; __le16 control; __le32 dsmgmt; __le32 reftag; __le16 apptag; __le16 appmask; }; /* Features */ struct nvme_feat_auto_pst { __le64 entries[32]; }; enum { NVME_HOST_MEM_ENABLE = (1 << 0), NVME_HOST_MEM_RETURN = (1 << 1), }; /* Admin commands */ enum nvme_admin_opcode { nvme_admin_delete_sq = 0x00, nvme_admin_create_sq = 0x01, nvme_admin_get_log_page = 0x02, nvme_admin_delete_cq = 0x04, nvme_admin_create_cq = 0x05, nvme_admin_identify = 0x06, nvme_admin_abort_cmd = 0x08, nvme_admin_set_features = 0x09, nvme_admin_get_features = 0x0a, nvme_admin_async_event = 0x0c, nvme_admin_ns_mgmt = 0x0d, nvme_admin_activate_fw = 0x10, nvme_admin_download_fw = 0x11, nvme_admin_ns_attach = 0x15, nvme_admin_keep_alive = 0x18, nvme_admin_directive_send = 0x19, nvme_admin_directive_recv = 0x1a, nvme_admin_dbbuf = 0x7C, nvme_admin_format_nvm = 0x80, nvme_admin_security_send = 0x81, nvme_admin_security_recv = 0x82, nvme_admin_sanitize_nvm = 0x84, }; enum { NVME_QUEUE_PHYS_CONTIG = (1 << 0), NVME_CQ_IRQ_ENABLED = (1 << 1), NVME_SQ_PRIO_URGENT = (0 << 1), NVME_SQ_PRIO_HIGH = (1 << 1), NVME_SQ_PRIO_MEDIUM = (2 << 1), NVME_SQ_PRIO_LOW = (3 << 1), NVME_FEAT_ARBITRATION = 0x01, NVME_FEAT_POWER_MGMT = 0x02, NVME_FEAT_LBA_RANGE = 0x03, NVME_FEAT_TEMP_THRESH = 0x04, NVME_FEAT_ERR_RECOVERY = 0x05, NVME_FEAT_VOLATILE_WC = 0x06, NVME_FEAT_NUM_QUEUES = 0x07, NVME_FEAT_IRQ_COALESCE = 0x08, NVME_FEAT_IRQ_CONFIG = 0x09, NVME_FEAT_WRITE_ATOMIC = 0x0a, NVME_FEAT_ASYNC_EVENT = 0x0b, NVME_FEAT_AUTO_PST = 0x0c, NVME_FEAT_HOST_MEM_BUF = 0x0d, NVME_FEAT_TIMESTAMP = 0x0e, NVME_FEAT_KATO = 0x0f, NVME_FEAT_SW_PROGRESS = 0x80, NVME_FEAT_HOST_ID = 0x81, NVME_FEAT_RESV_MASK = 0x82, NVME_FEAT_RESV_PERSIST = 0x83, NVME_LOG_ERROR = 0x01, NVME_LOG_SMART = 0x02, NVME_LOG_FW_SLOT = 0x03, NVME_LOG_CMD_EFFECTS = 0x05, NVME_LOG_DISC = 0x70, NVME_LOG_RESERVATION = 0x80, NVME_LOG_SANITIZE = 0x81, NVME_FWACT_REPL = (0 << 3), NVME_FWACT_REPL_ACTV = (1 << 3), NVME_FWACT_ACTV = (2 << 3), }; /* Sanitize and Sanitize Monitor/Log */ enum { /* Sanitize */ NVME_SANITIZE_NO_DEALLOC = 0x00000200, NVME_SANITIZE_OIPBP = 0x00000100, NVME_SANITIZE_OWPASS_SHIFT = 0x00000004, NVME_SANITIZE_AUSE = 0x00000008, NVME_SANITIZE_ACT_CRYPTO_ERASE = 0x00000004, NVME_SANITIZE_ACT_OVERWRITE = 0x00000003, NVME_SANITIZE_ACT_BLOCK_ERASE = 0x00000002, NVME_SANITIZE_ACT_EXIT = 0x00000001, /* Sanitize Monitor/Log */ NVME_SANITIZE_LOG_DATA_LEN = 0x0014, NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED = 0x0100, NVME_SANITIZE_LOG_STATUS_MASK = 0x0007, NVME_SANITIZE_LOG_NEVER_SANITIZED = 0x0000, NVME_SANITIZE_LOG_COMPLETED_SUCCESS = 0x0001, NVME_SANITIZE_LOG_IN_PROGESS = 0x0002, NVME_SANITIZE_LOG_COMPLETED_FAILED = 0x0003, }; struct nvme_identify { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2[2]; union nvme_data_ptr dptr; __u8 cns; __u8 rsvd3; __le16 ctrlid; __u32 rsvd11[5]; }; #define NVME_IDENTIFY_DATA_SIZE 4096 struct nvme_features { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2[2]; union nvme_data_ptr dptr; __le32 fid; __le32 dword11; __le32 dword12; __le32 dword13; __le32 dword14; __le32 dword15; }; struct nvme_host_mem_buf_desc { __le64 addr; __le32 size; __u32 rsvd; }; struct nvme_create_cq { __u8 opcode; __u8 flags; __u16 command_id; __u32 rsvd1[5]; __le64 prp1; __u64 rsvd8; __le16 cqid; __le16 qsize; __le16 cq_flags; __le16 irq_vector; __u32 rsvd12[4]; }; struct nvme_create_sq { __u8 opcode; __u8 flags; __u16 command_id; __u32 rsvd1[5]; __le64 prp1; __u64 rsvd8; __le16 sqid; __le16 qsize; __le16 sq_flags; __le16 cqid; __u32 rsvd12[4]; }; struct nvme_delete_queue { __u8 opcode; __u8 flags; __u16 command_id; __u32 rsvd1[9]; __le16 qid; __u16 rsvd10; __u32 rsvd11[5]; }; struct nvme_abort_cmd { __u8 opcode; __u8 flags; __u16 command_id; __u32 rsvd1[9]; __le16 sqid; __u16 cid; __u32 rsvd11[5]; }; struct nvme_download_firmware { __u8 opcode; __u8 flags; __u16 command_id; __u32 rsvd1[5]; union nvme_data_ptr dptr; __le32 numd; __le32 offset; __u32 rsvd12[4]; }; struct nvme_format_cmd { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2[4]; __le32 cdw10; __u32 rsvd11[5]; }; struct nvme_get_log_page_command { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2[2]; union nvme_data_ptr dptr; __u8 lid; __u8 rsvd10; __le16 numdl; __le16 numdu; __u16 rsvd11; __le32 lpol; __le32 lpou; __u32 rsvd14[2]; }; struct nvme_directive_cmd { __u8 opcode; __u8 flags; __u16 command_id; __le32 nsid; __u64 rsvd2[2]; union nvme_data_ptr dptr; __le32 numd; __u8 doper; __u8 dtype; __le16 dspec; __u8 endir; __u8 tdtype; __u16 rsvd15; __u32 rsvd16[3]; }; /* Sanitize Log Page */ struct nvme_sanitize_log_page { __le16 progress; __le16 status; __le32 cdw10_info; __le32 est_ovrwrt_time; __le32 est_blk_erase_time; __le32 est_crypto_erase_time; }; /* * Fabrics subcommands. */ enum nvmf_fabrics_opcode { nvme_fabrics_command = 0x7f, }; enum nvmf_capsule_command { nvme_fabrics_type_property_set = 0x00, nvme_fabrics_type_connect = 0x01, nvme_fabrics_type_property_get = 0x04, }; struct nvmf_common_command { __u8 opcode; __u8 resv1; __u16 command_id; __u8 fctype; __u8 resv2[35]; __u8 ts[24]; }; /* * The legal cntlid range a NVMe Target will provide. * Note that cntlid of value 0 is considered illegal in the fabrics world. * Devices based on earlier specs did not have the subsystem concept; * therefore, those devices had their cntlid value set to 0 as a result. */ #define NVME_CNTLID_MIN 1 #define NVME_CNTLID_MAX 0xffef #define NVME_CNTLID_DYNAMIC 0xffff #define MAX_DISC_LOGS 255 /* Discovery log page entry */ struct nvmf_disc_rsp_page_entry { __u8 trtype; __u8 adrfam; __u8 subtype; __u8 treq; __le16 portid; __le16 cntlid; __le16 asqsz; __u8 resv8[22]; char trsvcid[NVMF_TRSVCID_SIZE]; __u8 resv64[192]; char subnqn[NVMF_NQN_FIELD_LEN]; char traddr[NVMF_TRADDR_SIZE]; union tsas { char common[NVMF_TSAS_SIZE]; struct rdma { __u8 qptype; __u8 prtype; __u8 cms; __u8 resv3[5]; __u16 pkey; __u8 resv10[246]; } rdma; } tsas; }; /* Discovery log page header */ struct nvmf_disc_rsp_page_hdr { __le64 genctr; __le64 numrec; __le16 recfmt; __u8 resv14[1006]; struct nvmf_disc_rsp_page_entry entries[0]; }; struct nvmf_connect_command { __u8 opcode; __u8 resv1; __u16 command_id; __u8 fctype; __u8 resv2[19]; union nvme_data_ptr dptr; __le16 recfmt; __le16 qid; __le16 sqsize; __u8 cattr; __u8 resv3; __le32 kato; __u8 resv4[12]; }; struct nvmf_connect_data { uuid_t hostid; __le16 cntlid; char resv4[238]; char subsysnqn[NVMF_NQN_FIELD_LEN]; char hostnqn[NVMF_NQN_FIELD_LEN]; char resv5[256]; }; struct nvmf_property_set_command { __u8 opcode; __u8 resv1; __u16 command_id; __u8 fctype; __u8 resv2[35]; __u8 attrib; __u8 resv3[3]; __le32 offset; __le64 value; __u8 resv4[8]; }; struct nvmf_property_get_command { __u8 opcode; __u8 resv1; __u16 command_id; __u8 fctype; __u8 resv2[35]; __u8 attrib; __u8 resv3[3]; __le32 offset; __u8 resv4[16]; }; struct nvme_dbbuf { __u8 opcode; __u8 flags; __u16 command_id; __u32 rsvd1[5]; __le64 prp1; __le64 prp2; __u32 rsvd12[6]; }; struct streams_directive_params { __le16 msl; __le16 nssa; __le16 nsso; __u8 rsvd[10]; __le32 sws; __le16 sgs; __le16 nsa; __le16 nso; __u8 rsvd2[6]; }; struct nvme_command { union { struct nvme_common_command common; struct nvme_rw_command rw; struct nvme_identify identify; struct nvme_features features; struct nvme_create_cq create_cq; struct nvme_create_sq create_sq; struct nvme_delete_queue delete_queue; struct nvme_download_firmware dlfw; struct nvme_format_cmd format; struct nvme_dsm_cmd dsm; struct nvme_write_zeroes_cmd write_zeroes; struct nvme_abort_cmd abort; struct nvme_get_log_page_command get_log_page; struct nvmf_common_command fabrics; struct nvmf_connect_command connect; struct nvmf_property_set_command prop_set; struct nvmf_property_get_command prop_get; struct nvme_dbbuf dbbuf; struct nvme_directive_cmd directive; }; }; static inline bool nvme_is_write(struct nvme_command *cmd) { /* * What a mess... * * Why can't we simply have a Fabrics In and Fabrics out command? */ if (unlikely(cmd->common.opcode == nvme_fabrics_command)) return cmd->fabrics.fctype & 1; return cmd->common.opcode & 1; } enum { /* * Generic Command Status: */ NVME_SC_SUCCESS = 0x0, NVME_SC_INVALID_OPCODE = 0x1, NVME_SC_INVALID_FIELD = 0x2, NVME_SC_CMDID_CONFLICT = 0x3, NVME_SC_DATA_XFER_ERROR = 0x4, NVME_SC_POWER_LOSS = 0x5, NVME_SC_INTERNAL = 0x6, NVME_SC_ABORT_REQ = 0x7, NVME_SC_ABORT_QUEUE = 0x8, NVME_SC_FUSED_FAIL = 0x9, NVME_SC_FUSED_MISSING = 0xa, NVME_SC_INVALID_NS = 0xb, NVME_SC_CMD_SEQ_ERROR = 0xc, NVME_SC_SGL_INVALID_LAST = 0xd, NVME_SC_SGL_INVALID_COUNT = 0xe, NVME_SC_SGL_INVALID_DATA = 0xf, NVME_SC_SGL_INVALID_METADATA = 0x10, NVME_SC_SGL_INVALID_TYPE = 0x11, NVME_SC_SGL_INVALID_OFFSET = 0x16, NVME_SC_SGL_INVALID_SUBTYPE = 0x17, NVME_SC_SANITIZE_FAILED = 0x1C, NVME_SC_SANITIZE_IN_PROGRESS = 0x1D, NVME_SC_LBA_RANGE = 0x80, NVME_SC_CAP_EXCEEDED = 0x81, NVME_SC_NS_NOT_READY = 0x82, NVME_SC_RESERVATION_CONFLICT = 0x83, /* * Command Specific Status: */ NVME_SC_CQ_INVALID = 0x100, NVME_SC_QID_INVALID = 0x101, NVME_SC_QUEUE_SIZE = 0x102, NVME_SC_ABORT_LIMIT = 0x103, NVME_SC_ABORT_MISSING = 0x104, NVME_SC_ASYNC_LIMIT = 0x105, NVME_SC_FIRMWARE_SLOT = 0x106, NVME_SC_FIRMWARE_IMAGE = 0x107, NVME_SC_INVALID_VECTOR = 0x108, NVME_SC_INVALID_LOG_PAGE = 0x109, NVME_SC_INVALID_FORMAT = 0x10a, NVME_SC_FW_NEEDS_CONV_RESET = 0x10b, NVME_SC_INVALID_QUEUE = 0x10c, NVME_SC_FEATURE_NOT_SAVEABLE = 0x10d, NVME_SC_FEATURE_NOT_CHANGEABLE = 0x10e, NVME_SC_FEATURE_NOT_PER_NS = 0x10f, NVME_SC_FW_NEEDS_SUBSYS_RESET = 0x110, NVME_SC_FW_NEEDS_RESET = 0x111, NVME_SC_FW_NEEDS_MAX_TIME = 0x112, NVME_SC_FW_ACIVATE_PROHIBITED = 0x113, NVME_SC_OVERLAPPING_RANGE = 0x114, NVME_SC_NS_INSUFFICENT_CAP = 0x115, NVME_SC_NS_ID_UNAVAILABLE = 0x116, NVME_SC_NS_ALREADY_ATTACHED = 0x118, NVME_SC_NS_IS_PRIVATE = 0x119, NVME_SC_NS_NOT_ATTACHED = 0x11a, NVME_SC_THIN_PROV_NOT_SUPP = 0x11b, NVME_SC_CTRL_LIST_INVALID = 0x11c, NVME_SC_BP_WRITE_PROHIBITED = 0x11e, /* * I/O Command Set Specific - NVM commands: */ NVME_SC_BAD_ATTRIBUTES = 0x180, NVME_SC_INVALID_PI = 0x181, NVME_SC_READ_ONLY = 0x182, NVME_SC_ONCS_NOT_SUPPORTED = 0x183, /* * I/O Command Set Specific - Fabrics commands: */ NVME_SC_CONNECT_FORMAT = 0x180, NVME_SC_CONNECT_CTRL_BUSY = 0x181, NVME_SC_CONNECT_INVALID_PARAM = 0x182, NVME_SC_CONNECT_RESTART_DISC = 0x183, NVME_SC_CONNECT_INVALID_HOST = 0x184, NVME_SC_DISCOVERY_RESTART = 0x190, NVME_SC_AUTH_REQUIRED = 0x191, /* * Media and Data Integrity Errors: */ NVME_SC_WRITE_FAULT = 0x280, NVME_SC_READ_ERROR = 0x281, NVME_SC_GUARD_CHECK = 0x282, NVME_SC_APPTAG_CHECK = 0x283, NVME_SC_REFTAG_CHECK = 0x284, NVME_SC_COMPARE_FAILED = 0x285, NVME_SC_ACCESS_DENIED = 0x286, NVME_SC_UNWRITTEN_BLOCK = 0x287, NVME_SC_DNR = 0x4000, }; struct nvme_completion { /* * Used by Admin and Fabrics commands to return data: */ union nvme_result { __le16 u16; __le32 u32; __le64 u64; } result; __le16 sq_head; /* how much of this queue may be reclaimed */ __le16 sq_id; /* submission queue that generated this entry */ __u16 command_id; /* of the command which completed */ __le16 status; /* did the command fail, and if so, why? */ }; #define NVME_VS(major, minor, tertiary) \ (((major) << 16) | ((minor) << 8) | (tertiary)) #define NVME_MAJOR(ver) ((ver) >> 16) #define NVME_MINOR(ver) (((ver) >> 8) & 0xff) #define NVME_TERTIARY(ver) ((ver) & 0xff) #endif /* _LINUX_NVME_H */ nvme-cli-1.5/linux/nvme_ioctl.h000066400000000000000000000031001322317423600165350ustar00rootroot00000000000000/* * Definitions for the NVM Express ioctl interface * Copyright (c) 2011-2014, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ #ifndef _UAPI_LINUX_NVME_IOCTL_H #define _UAPI_LINUX_NVME_IOCTL_H #include struct nvme_user_io { __u8 opcode; __u8 flags; __u16 control; __u16 nblocks; __u16 rsvd; __u64 metadata; __u64 addr; __u64 slba; __u32 dsmgmt; __u32 reftag; __u16 apptag; __u16 appmask; }; struct nvme_passthru_cmd { __u8 opcode; __u8 flags; __u16 rsvd1; __u32 nsid; __u32 cdw2; __u32 cdw3; __u64 metadata; __u64 addr; __u32 metadata_len; __u32 data_len; __u32 cdw10; __u32 cdw11; __u32 cdw12; __u32 cdw13; __u32 cdw14; __u32 cdw15; __u32 timeout_ms; __u32 result; }; #define nvme_admin_cmd nvme_passthru_cmd #define NVME_IOCTL_ID _IO('N', 0x40) #define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) #define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) #define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct nvme_passthru_cmd) #define NVME_IOCTL_RESET _IO('N', 0x44) #define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45) #define NVME_IOCTL_RESCAN _IO('N', 0x46) #endif /* _UAPI_LINUX_NVME_IOCTL_H */ nvme-cli-1.5/lnvm-nvme.c000066400000000000000000000252041322317423600151620ustar00rootroot00000000000000#include #include #include "nvme.h" #include "nvme-print.h" #include "nvme-ioctl.h" #include "plugin.h" #include "nvme-lightnvm.h" #include "argconfig.h" #include "suffix.h" #define CREATE_CMD #include "lnvm-nvme.h" static int lnvm_init(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Initialize LightNVM device. A LightNVM/Open-Channel SSD"\ " must have a media manager associated before it can "\ " be exposed to the user. The default is to initialize" " the general media manager on top of the device.\n\n" "Example:" " lnvm-init -d nvme0n1"; const char *devname = "identifier of desired device. e.g. nvme0n1."; const char *mmtype = "media manager to initialize on top of device. Default: gennvm."; struct config { char *devname; char *mmtype; }; struct config cfg = { .devname = "", .mmtype = "gennvm", }; const struct argconfig_commandline_options command_line_options[] = { {"device-name", 'd', "DEVICE", CFG_STRING, &cfg.devname, required_argument, devname}, {"mediamgr-name", 'm', "MM", CFG_STRING, &cfg.mmtype, required_argument, mmtype}, {NULL} }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!strlen(cfg.devname)) { fprintf(stderr, "device name missing %d\n", (int)strlen(cfg.devname)); return -EINVAL; } return lnvm_do_init(cfg.devname, cfg.mmtype); } static int lnvm_list(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "List all devices registered with LightNVM."; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; argconfig_parse(argc, argv, desc, command_line_options, NULL, 0); return lnvm_do_list_devices(); } static int lnvm_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Show general information and registered target types with LightNVM"; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; argconfig_parse(argc, argv, desc, command_line_options, NULL, 0); return lnvm_do_info(); } static int lnvm_id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send an Identify Geometry command to the "\ "given LightNVM device, returns properties of the specified"\ "namespace in either human-readable or binary format."; const char *force = "Return this namespace, even if not supported"; const char *raw_binary = "show infos in binary format"; const char *human_readable = "show infos in readable format"; const char *namespace_id = "identifier of desired namespace. default: 1"; unsigned int fd, flags = 0; struct config { __u32 namespace_id; int raw_binary; int human_readable; int force; }; struct config cfg = { .namespace_id = 1, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"force", 'f', "FLAG", CFG_NONE, &cfg.force, no_argument, force}, {"raw-binary", 'b', "FLAG", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"human-readable", 'H', "FLAG", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (cfg.human_readable) flags |= HUMAN; else if (cfg.raw_binary) flags |= RAW; return lnvm_do_id_ns(fd, cfg.namespace_id, flags); } static int lnvm_create_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Instantiate a target on top of a LightNVM enabled device."; const char *devname = "identifier of desired device. e.g. nvme0n1."; const char *tgtname = "target name of the device to initialize. e.g. target0."; const char *tgttype = "identifier of target type. e.g. pblk."; const char *lun_begin = "Define begin of luns to use for target."; const char *lun_end = "Define set of luns to use for target."; const char *flag_factory = "Create target in factory mode"; int flags; struct config { char *devname; char *tgtname; char *tgttype; __u32 lun_begin; __u32 lun_end; /* flags */ __u32 factory; }; struct config cfg = { .devname = "", .tgtname = "", .tgttype = "", .lun_begin = -1, .lun_end = -1, .factory = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"device-name", 'd', "DEVICE", CFG_STRING, &cfg.devname, required_argument, devname}, {"target-name", 'n', "TARGET", CFG_STRING, &cfg.tgtname, required_argument, tgtname}, {"target-type", 't', "TARGETTYPE", CFG_STRING, &cfg.tgttype, required_argument, tgttype}, {"lun-begin", 'b', "NUM", CFG_POSITIVE, &cfg.lun_begin, required_argument, lun_begin}, {"lun-end", 'e', "NUM", CFG_POSITIVE, &cfg.lun_end, required_argument, lun_end}, {"factory", 'f', "FLAG", CFG_NONE, &cfg.factory, no_argument, flag_factory}, {NULL} }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!strlen(cfg.devname)) { fprintf(stderr, "device name missing %d\n", (int)strlen(cfg.devname)); return -EINVAL; } if (!strlen(cfg.tgtname)) { fprintf(stderr, "target name missing\n"); return -EINVAL; } if (!strlen(cfg.tgttype)) { fprintf(stderr, "target type missing\n"); return -EINVAL; } flags = 0; if (cfg.factory) flags |= NVM_TARGET_FACTORY; return lnvm_do_create_tgt(cfg.devname, cfg.tgtname, cfg.tgttype, cfg.lun_begin, cfg.lun_end, flags); } static int lnvm_remove_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Remove an initialized LightNVM target."; const char *tgtname = "target name of the device to initialize. e.g. target0."; struct config { char *tgtname; }; struct config cfg = { .tgtname = "", }; const struct argconfig_commandline_options command_line_options[] = { {"target-name", 'n', "TARGET", CFG_STRING, &cfg.tgtname, required_argument, tgtname}, {NULL} }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!strlen(cfg.tgtname)) { fprintf(stderr, "target name missing\n"); return -EINVAL; } return lnvm_do_remove_tgt(cfg.tgtname); } static int lnvm_factory_init(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Factory initialize a LightNVM enabled device."; const char *devname = "identifier of desired device. e.g. nvme0n1."; const char *erase_only_marked = "only erase marked blocks. default: all blocks."; const char *host_marks = "remove host side blocks list. default: keep."; const char *bb_marks = "remove grown bad blocks list. default: keep"; struct config { char *devname; int erase_only_marked; int clear_host_marks; int clear_bb_marks; }; struct config cfg = { .devname = "", }; const struct argconfig_commandline_options command_line_options[] = { {"device-name", 'd', "DEVICE", CFG_STRING, &cfg.devname, required_argument, devname}, {"erase-only-marked", 'e', "", CFG_NONE, &cfg.erase_only_marked, no_argument, erase_only_marked}, {"clear-host-side-blks", 's', "", CFG_NONE, &cfg.clear_host_marks, no_argument, host_marks}, {"clear-bb-blks", 'b', "", CFG_NONE, &cfg.clear_bb_marks, no_argument, bb_marks}, {NULL} }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!strlen(cfg.devname)) { fprintf(stderr, "device name missing %d\n", (int)strlen(cfg.devname)); return -EINVAL; } return lnvm_do_factory_init(cfg.devname, cfg.erase_only_marked, cfg.clear_host_marks, cfg.clear_bb_marks); } static int lnvm_get_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Receive bad block table from a LightNVM compatible"\ " device."; const char *namespace = "(optional) desired namespace"; const char *ch = "channel identifier"; const char *lun = "lun identifier (within a channel)"; const char *raw_binary = "show infos in binary format"; unsigned int fd, flags = 0; struct config { __u32 namespace_id; __u16 lunid; __u16 chid; int raw_binary; }; struct config cfg = { .namespace_id = 1, .lunid = 0, .chid = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace}, {"channel-id", 'c', "", CFG_SHORT, &cfg.chid, required_argument, ch}, {"lun-id", 'l', "", CFG_SHORT, &cfg.lunid, required_argument, lun}, {"raw-binary", 'b', "FLAG", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (cfg.raw_binary) flags |= RAW; return lnvm_do_get_bbtbl(fd, cfg.namespace_id, cfg.lunid, cfg.chid, flags); } static int lnvm_set_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Update bad block table on a LightNVM compatible"\ " device."; const char *namespace = "(optional) desired namespace"; const char *ch = "channel identifier"; const char *lun = "lun identifier (within a channel)"; const char *pln = "plane identifier (within a lun)"; const char *blk = "block identifier (within a plane)"; const char *value = "value to update the specific block to."; int fd; struct config { __u32 namespace_id; __u16 lunid; __u16 chid; __u16 plnid; __u16 blkid; __u16 value; }; struct config cfg = { .namespace_id = 1, .lunid = 0, .chid = 0, .plnid = 0, .blkid = 0, .value = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace}, {"channel-id", 'c', "NUM", CFG_SHORT, &cfg.chid, required_argument, ch}, {"lun-id", 'l', "NUM", CFG_SHORT, &cfg.lunid, required_argument, lun}, {"plane-id", 'p', "NUM", CFG_SHORT, &cfg.plnid, required_argument, pln}, {"block-id", 'b', "NUM", CFG_SHORT, &cfg.blkid, required_argument, blk}, {"value", 'v', "NUM", CFG_SHORT, &cfg.value, required_argument, value}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); printf("Updating: Ch.: %u LUN: %u Plane: %u Block: %u -> %u\n", cfg.chid, cfg.lunid, cfg.plnid, cfg.blkid, cfg.value); return lnvm_do_set_bbtbl(fd, cfg.namespace_id, cfg.chid, cfg.lunid, cfg.plnid, cfg.blkid, cfg.value); } nvme-cli-1.5/lnvm-nvme.h000066400000000000000000000015721322317423600151710ustar00rootroot00000000000000 #undef CMD_INC_FILE #define CMD_INC_FILE lnvm-nvme #if !defined(LNVM_NVME) || defined(CMD_HEADER_MULTI_READ) #define LNVM_NVME #include "cmd.h" PLUGIN(NAME("lnvm", "LightNVM specific extensions"), COMMAND_LIST( ENTRY("list", "List available LightNVM devices", lnvm_list) ENTRY("info", "List general information and available target engines", lnvm_info) ENTRY("id-ns", "List geometry for LightNVM device", lnvm_id_ns) ENTRY("init", "Initialize media manager on LightNVM device", lnvm_init) ENTRY("create", "Create target on top of a LightNVM device", lnvm_create_tgt) ENTRY("remove", "Remove target from device", lnvm_remove_tgt) ENTRY("factory", "Reset device to factory state", lnvm_factory_init) ENTRY("diag-bbtbl", "Diagnose bad block table", lnvm_get_bbtbl) ENTRY("diag-set-bbtbl", "Update bad block table", lnvm_set_bbtbl) ) ); #endif #include "define_cmd.h" nvme-cli-1.5/memblaze-nvme.c000066400000000000000000000317421322317423600160060ustar00rootroot00000000000000#include #include #include #include #include #include #include "linux/nvme_ioctl.h" #include "nvme.h" #include "nvme-print.h" #include "nvme-ioctl.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" #define CREATE_CMD #include "memblaze-nvme.h" enum { TOTAL_WRITE, TOTAL_READ, THERMAL_THROTTLE, TEMPT_SINCE_RESET, POWER_CONSUMPTION, TEMPT_SINCE_BOOTUP, POWER_LOSS_PROTECTION, WEARLEVELING_COUNT, HOST_WRITE, THERMAL_THROTTLE_CNT, NR_SMART_ITEMS, }; enum { MB_FEAT_POWER_MGMT = 0Xc6, }; #pragma pack(push, 1) struct nvme_memblaze_smart_log_item { __u8 id[3]; union { __u8 __nmval[2]; __le16 nmval; }; union { __u8 rawval[6]; struct temperature { __le16 max; __le16 min; __le16 curr; } temperature; struct power { __le16 max; __le16 min; __le16 curr; } power; struct thermal_throttle_mb { __u8 on; __u32 count; } thermal_throttle; struct temperature_p { __le16 max; __le16 min; } temperature_p; struct power_loss_protection { __u8 curr; } power_loss_protection; struct wearleveling_count { __le16 min; __le16 max; __le16 avg; } wearleveling_count; struct thermal_throttle_cnt { __u8 active; __le32 cnt; } thermal_throttle_cnt; }; __u8 resv; }; #pragma pack(pop) struct nvme_memblaze_smart_log { struct nvme_memblaze_smart_log_item items[NR_SMART_ITEMS]; __u8 resv[512 - sizeof(struct nvme_memblaze_smart_log_item) * NR_SMART_ITEMS]; }; /* * Return -1 if @fw1 < @fw2 * Return 0 if @fw1 == @fw2 * Return 1 if @fw1 > @fw2 */ static int compare_fw_version(const char *fw1, const char *fw2) { while (*fw1 != '\0') { if (*fw2 == '\0' || *fw1 > *fw2) return 1; if (*fw1 < *fw2) return -1; fw1++; fw2++; } if (*fw2 != '\0') return -1; return 0; } static __u32 item_id_2_u32(struct nvme_memblaze_smart_log_item *item) { __le32 __id = 0; memcpy(&__id, item->id, 3); return le32_to_cpu(__id); } static __u64 raw_2_u64(const __u8 *buf, size_t len) { __le64 val = 0; memcpy(&val, buf, len); return le64_to_cpu(val); } static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname, struct nvme_memblaze_smart_log *smart) { struct nvme_id_ctrl ctrl; char fw_ver[10]; int err = 0; struct nvme_memblaze_smart_log_item *item; err = nvme_identify_ctrl(fd, &ctrl); if (err) return err; snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c", ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3], ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]); printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); printf("Total write in GB since last factory reset : %"PRIu64"\n", int48_to_long(smart->items[TOTAL_WRITE].rawval)); printf("Total read in GB since last factory reset : %"PRIu64"\n", int48_to_long(smart->items[TOTAL_READ].rawval)); printf("Thermal throttling status[1:HTP in progress] : %u\n", smart->items[THERMAL_THROTTLE].thermal_throttle.on); printf("Total thermal throttling minutes since power on : %u\n", smart->items[THERMAL_THROTTLE].thermal_throttle.count); printf("Maximum temperature in Kelvin since last factory reset : %u\n", le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.max)); printf("Minimum temperature in Kelvin since last factory reset : %u\n", le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.min)); if (compare_fw_version(fw_ver, "0.09.0300") != 0) { printf("Maximum temperature in Kelvin since power on : %u\n", le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.max)); printf("Minimum temperature in Kelvin since power on : %u\n", le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.min)); } printf("Current temperature in Kelvin : %u\n", le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.curr)); printf("Maximum power in watt since power on : %u\n", le16_to_cpu(smart->items[POWER_CONSUMPTION].power.max)); printf("Minimum power in watt since power on : %u\n", le16_to_cpu(smart->items[POWER_CONSUMPTION].power.min)); printf("Current power in watt : %u\n", le16_to_cpu(smart->items[POWER_CONSUMPTION].power.curr)); item = &smart->items[POWER_LOSS_PROTECTION]; if (item_id_2_u32(item) == 0xEC) printf("Power loss protection normalized value : %u\n", item->power_loss_protection.curr); item = &smart->items[WEARLEVELING_COUNT]; if (item_id_2_u32(item) == 0xAD) { printf("Percentage of wearleveling count left : %u\n", le16_to_cpu(item->nmval)); printf("Wearleveling count min erase cycle : %u\n", le16_to_cpu(item->wearleveling_count.min)); printf("Wearleveling count max erase cycle : %u\n", le16_to_cpu(item->wearleveling_count.max)); printf("Wearleveling count avg erase cycle : %u\n", le16_to_cpu(item->wearleveling_count.avg)); } item = &smart->items[HOST_WRITE]; if (item_id_2_u32(item) == 0xF5) printf("Total host write in GiB since device born : %llu\n", (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); item = &smart->items[THERMAL_THROTTLE_CNT]; if (item_id_2_u32(item) == 0xEB) printf("Thermal throttling count since device born : %u\n", item->thermal_throttle_cnt.cnt); return err; } static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_memblaze_smart_log smart_log; int err, fd; char *desc = "Get Memblaze vendor specific additional smart log (optionally, "\ "for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; struct config { __u32 namespace_id; int raw_binary; }; struct config cfg = { .namespace_id = NVME_NSID_ALL, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); err = nvme_get_log(fd, cfg.namespace_id, 0xca, sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } static char *mb_feature_to_string(int feature) { switch (feature) { case MB_FEAT_POWER_MGMT: return "Memblaze power management"; default: return "Unknown"; } } static int get_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Read operating parameters of the "\ "specified controller. Operating parameters are grouped "\ "and identified by Feature Identifiers; each Feature "\ "Identifier contains one or more attributes that may affect "\ "behaviour of the feature. Each Feature has three possible "\ "settings: default, saveable, and current. If a Feature is "\ "saveable, it may be modified by set-feature. Default values "\ "are vendor-specific and not changeable. Use set-feature to "\ "change saveable Features.\n\n"\ "Available additional feature id:\n"\ "0xc6: Memblaze power management\n"\ " (value 0 - 25w, 1 - 20w, 2 - 15w)"; const char *raw_binary = "show infos in binary format"; const char *namespace_id = "identifier of desired namespace"; const char *feature_id = "hexadecimal feature name"; const char *sel = "[0-3]: curr./default/saved/supp."; const char *data_len = "buffer len (if) data is returned"; const char *cdw11 = "dword 11 for interrupt vector config"; const char *human_readable = "show infos in readable format"; int err, fd; __u32 result; void *buf = NULL; struct config { __u32 namespace_id; __u32 feature_id; __u8 sel; __u32 cdw11; __u32 data_len; int raw_binary; int human_readable; }; struct config cfg = { .namespace_id = 1, .feature_id = 0, .sel = 0, .cdw11 = 0, .data_len = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"feature-id", 'f', "NUM", CFG_POSITIVE, &cfg.feature_id, required_argument, feature_id}, {"sel", 's', "NUM", CFG_BYTE, &cfg.sel, required_argument, sel}, {"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len}, {"raw-binary", 'b', "FLAG", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"cdw11", 'c', "NUM", CFG_POSITIVE, &cfg.cdw11, required_argument, cdw11}, {"human-readable", 'H', "FLAG", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (cfg.sel > 7) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); return EINVAL; } if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); return EINVAL; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) exit(ENOMEM); memset(buf, 0, cfg.data_len); } err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11, cfg.data_len, buf, &result); if (!err) { printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), nvme_select_to_string(cfg.sel), result); if (cfg.human_readable) nvme_feature_show_fields(cfg.feature_id, result, buf); else { if (buf) { if (!cfg.raw_binary) d(buf, cfg.data_len, 16, 1); else d_raw(buf, cfg.data_len); } } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); if (buf) free(buf); return err; } static int set_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Modify the saveable or changeable "\ "current operating parameters of the controller. Operating "\ "parameters are grouped and identified by Feature "\ "Identifiers. Feature settings can be applied to the entire "\ "controller and all associated namespaces, or to only a few "\ "namespace(s) associated with the controller. Default values "\ "for each Feature are vendor-specific and may not be modified."\ "Use get-feature to determine which Features are supported by "\ "the controller and are saveable/changeable.\n\n"\ "Available additional feature id:\n"\ "0xc6: Memblaze power management\n"\ " (value 0 - 25w, 1 - 20w, 2 - 15w)"; const char *namespace_id = "desired namespace"; const char *feature_id = "hex feature name (required)"; const char *data_len = "buffer length if data required"; const char *data = "optional file for feature data (default stdin)"; const char *value = "new value of feature (required)"; const char *save = "specifies that the controller shall save the attribute"; int err, fd; __u32 result; void *buf = NULL; int ffd = STDIN_FILENO; struct config { char *file; __u32 namespace_id; __u32 feature_id; __u32 value; __u32 data_len; int save; }; struct config cfg = { .file = "", .namespace_id = 0, .feature_id = 0, .value = 0, .data_len = 0, .save = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"feature-id", 'f', "NUM", CFG_POSITIVE, &cfg.feature_id, required_argument, feature_id}, {"value", 'v', "NUM", CFG_POSITIVE, &cfg.value, required_argument, value}, {"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len}, {"data", 'd', "FILE", CFG_STRING, &cfg.file, required_argument, data}, {"save", 's', "FLAG", CFG_NONE, &cfg.save, no_argument, save}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); return EINVAL; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) exit(ENOMEM); memset(buf, 0, cfg.data_len); } if (buf) { if (strlen(cfg.file)) { ffd = open(cfg.file, O_RDONLY); if (ffd <= 0) { fprintf(stderr, "no firmware file provided\n"); return -EINVAL; } } if (read(ffd, (void *)buf, cfg.data_len) < 0) { fprintf(stderr, "failed to read data buffer from input file\n"); return EINVAL; } } err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, cfg.save, cfg.data_len, buf, &result); if (err < 0) { perror("set-feature"); return errno; } if (!err) { printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); if (buf) d(buf, cfg.data_len, 16, 1); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); if (buf) free(buf); return err; } nvme-cli-1.5/memblaze-nvme.h000066400000000000000000000011021322317423600157760ustar00rootroot00000000000000#undef CMD_INC_FILE #define CMD_INC_FILE memblaze-nvme #if !defined(MEMBLAZE_NVME) || defined(CMD_HEADER_MULTI_READ) #define MEMBLAZE_NVME #include "cmd.h" PLUGIN(NAME("memblaze", "Memblaze vendor specific extensions"), COMMAND_LIST( ENTRY("smart-log-add", "Retrieve Memblaze SMART Log, show it", get_additional_smart_log) ENTRY("get-feature-add", "Get Memblaze feature and show the resulting value", get_additional_feature) ENTRY("set-feature-add", "Set a Memblaze feature and show the resulting value", set_additional_feature) ) ); #endif #include "define_cmd.h" nvme-cli-1.5/nvme-builtin.h000066400000000000000000000100311322317423600156510ustar00rootroot00000000000000#undef CMD_INC_FILE #define CMD_INC_FILE nvme-builtin #if !defined(NVME_BUILTIN) || defined(CMD_HEADER_MULTI_READ) #define NVME_BUILTIN #include "cmd.h" COMMAND_LIST( ENTRY("list", "List all NVMe devices and namespaces on machine", list) ENTRY("list-subsys", "List nvme subsystems", list_subsys) ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl) ENTRY("id-ns", "Send NVMe Identify Namespace, display structure", id_ns) ENTRY("list-ns", "Send NVMe Identify List, display structure", list_ns) ENTRY("ns-descs", "Send NVMe Namespace Descriptor List, display structure", ns_descs) ENTRY("create-ns", "Creates a namespace with the provided parameters", create_ns) ENTRY("delete-ns", "Deletes a namespace from the controller", delete_ns) ENTRY("attach-ns", "Attaches a namespace to requested controller(s)", attach_ns) ENTRY("detach-ns", "Detaches a namespace from requested controller(s)", detach_ns) ENTRY("list-ctrl", "Send NVMe Identify Controller List, display structure", list_ctrl) ENTRY("get-ns-id", "Retrieve the namespace ID of opened block device", get_ns_id) ENTRY("get-log", "Generic NVMe get log, returns log in raw format", get_log) ENTRY("fw-log", "Retrieve FW Log, show it", get_fw_log) ENTRY("smart-log", "Retrieve SMART Log, show it", get_smart_log) ENTRY("error-log", "Retrieve Error Log, show it", get_error_log) ENTRY("effects-log", "Retrieve Command Effects Log, show it", get_effects_log) ENTRY("get-feature", "Get feature and show the resulting value", get_feature) ENTRY("set-feature", "Set a feature and show the resulting value", set_feature) ENTRY("set-property", "Set a property and show the resulting value", set_property) ENTRY("format", "Format namespace with new block format", format) ENTRY("fw-commit", "Verify and commit firmware to a specific slot (fw-activate in old version < 1.2)", fw_commit, "fw-activate") ENTRY("fw-download", "Download new firmware", fw_download) ENTRY("admin-passthru", "Submit an arbitrary admin command, return results", admin_passthru) ENTRY("io-passthru", "Submit an arbitrary IO command, return results", io_passthru) ENTRY("security-send", "Submit a Security Send command, return results", sec_send) ENTRY("security-recv", "Submit a Security Receive command, return results", sec_recv) ENTRY("resv-acquire", "Submit a Reservation Acquire, return results", resv_acquire) ENTRY("resv-register", "Submit a Reservation Register, return results", resv_register) ENTRY("resv-release", "Submit a Reservation Release, return results", resv_release) ENTRY("resv-report", "Submit a Reservation Report, return results", resv_report) ENTRY("dsm", "Submit a Data Set Management command, return results", dsm) ENTRY("flush", "Submit a Flush command, return results", flush) ENTRY("compare", "Submit a Compare command, return results", compare) ENTRY("read", "Submit a read command, return results", read_cmd) ENTRY("write", "Submit a write command, return results", write_cmd) ENTRY("write-zeroes", "Submit a write zeroes command, return results", write_zeroes) ENTRY("write-uncor", "Submit a write uncorrectable command, return results", write_uncor) ENTRY("sanitize", "Submit a sanitize command", sanitize) ENTRY("sanitize-log", "Retrive sanitize log, show it", sanitize_log) ENTRY("reset", "Resets the controller", reset) ENTRY("subsystem-reset", "Resets the controller", subsystem_reset) ENTRY("ns-rescan", "Rescans the NVME namespaces", ns_rescan) ENTRY("show-regs", "Shows the controller registers or properties. Requires character device", show_registers) ENTRY("discover", "Discover NVMeoF subsystems", discover_cmd) ENTRY("connect-all", "Discover and Connect to NVMeoF subsystems", connect_all_cmd) ENTRY("connect", "Connect to NVMeoF subsystem", connect_cmd) ENTRY("disconnect", "Disconnect from NVMeoF subsystem", disconnect_cmd) ENTRY("gen-hostnqn", "Generate NVMeoF host NQN", gen_hostnqn_cmd) ENTRY("dir-receive", "Submit a Directive Receive command, return results", dir_receive) ENTRY("dir-send", "Submit a Directive Send command, return results", dir_send) ); #endif #include "define_cmd.h" nvme-cli-1.5/nvme-ioctl.c000066400000000000000000000437441322317423600153310ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nvme-ioctl.h" static int nvme_verify_chr(int fd) { static struct stat nvme_stat; int err = fstat(fd, &nvme_stat); if (err < 0) { perror("fstat"); return errno; } if (!S_ISCHR(nvme_stat.st_mode)) { fprintf(stderr, "Error: requesting reset on non-controller handle\n"); return ENOTBLK; } return 0; } int nvme_subsystem_reset(int fd) { int ret; ret = nvme_verify_chr(fd); if (ret) return ret; return ioctl(fd, NVME_IOCTL_SUBSYS_RESET); } int nvme_reset_controller(int fd) { int ret; ret = nvme_verify_chr(fd); if (ret) return ret; return ioctl(fd, NVME_IOCTL_RESET); } int nvme_ns_rescan(int fd) { int ret; ret = nvme_verify_chr(fd); if (ret) return ret; return ioctl(fd, NVME_IOCTL_RESCAN); } int nvme_get_nsid(int fd) { static struct stat nvme_stat; int err = fstat(fd, &nvme_stat); if (err < 0) return err; if (!S_ISBLK(nvme_stat.st_mode)) { fprintf(stderr, "Error: requesting namespace-id from non-block device\n"); return ENOTBLK; } return ioctl(fd, NVME_IOCTL_ID); } int nvme_submit_passthru(int fd, int ioctl_cmd, struct nvme_passthru_cmd *cmd) { return ioctl(fd, ioctl_cmd, cmd); } static int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd) { return ioctl(fd, NVME_IOCTL_ADMIN_CMD, cmd); } static int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd) { return ioctl(fd, NVME_IOCTL_IO_CMD, cmd); } int nvme_passthru(int fd, int ioctl_cmd, __u8 opcode, __u8 flags, __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout_ms, __u32 *result) { struct nvme_passthru_cmd cmd = { .opcode = opcode, .flags = flags, .rsvd1 = rsvd, .nsid = nsid, .cdw2 = cdw2, .cdw3 = cdw3, .metadata = (__u64)(uintptr_t) metadata, .addr = (__u64)(uintptr_t) data, .metadata_len = metadata_len, .data_len = data_len, .cdw10 = cdw10, .cdw11 = cdw11, .cdw12 = cdw12, .cdw13 = cdw13, .cdw14 = cdw14, .cdw15 = cdw15, .timeout_ms = timeout_ms, .result = 0, }; int err; err = nvme_submit_passthru(fd, ioctl_cmd, &cmd); if (!err && result) *result = cmd.result; return err; } int nvme_io(int fd, __u8 opcode, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata) { struct nvme_user_io io = { .opcode = opcode, .flags = 0, .control = control, .nblocks = nblocks, .rsvd = 0, .metadata = (__u64)(uintptr_t) metadata, .addr = (__u64)(uintptr_t) data, .slba = slba, .dsmgmt = dsmgmt, .reftag = reftag, .appmask = appmask, .apptag = apptag, }; return ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io); } int nvme_read(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata) { return nvme_io(fd, nvme_cmd_read, slba, nblocks, control, dsmgmt, reftag, apptag, appmask, data, metadata); } int nvme_write(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata) { return nvme_io(fd, nvme_cmd_write, slba, nblocks, control, dsmgmt, reftag, apptag, appmask, data, metadata); } int nvme_compare(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata) { return nvme_io(fd, nvme_cmd_compare, slba, nblocks, control, dsmgmt, reftag, apptag, appmask, data, metadata); } int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout_ms) { return nvme_passthru(fd, NVME_IOCTL_IO_CMD, opcode, flags, rsvd, nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, timeout_ms, NULL); } int nvme_write_zeros(int fd, __u32 nsid, __u64 slba, __u16 nlb, __u16 control, __u32 reftag, __u16 apptag, __u16 appmask) { struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_write_zeroes, .nsid = nsid, .cdw10 = slba & 0xffffffff, .cdw11 = slba >> 32, .cdw12 = nlb | (control << 16), .cdw14 = reftag, .cdw15 = apptag | (appmask << 16), }; return nvme_submit_io_passthru(fd, &cmd); } int nvme_write_uncorrectable(int fd, __u32 nsid, __u64 slba, __u16 nlb) { struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_write_uncor, .nsid = nsid, .cdw10 = slba & 0xffffffff, .cdw11 = slba >> 32, .cdw12 = nlb, }; return nvme_submit_io_passthru(fd, &cmd); } int nvme_flush(int fd, __u32 nsid) { struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_flush, .nsid = nsid, }; return nvme_submit_io_passthru(fd, &cmd); } int nvme_dsm(int fd, __u32 nsid, __u32 cdw11, struct nvme_dsm_range *dsm, __u16 nr_ranges) { struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_dsm, .nsid = nsid, .addr = (__u64)(uintptr_t) dsm, .data_len = nr_ranges * sizeof(*dsm), .cdw10 = nr_ranges - 1, .cdw11 = cdw11, }; return nvme_submit_io_passthru(fd, &cmd); } struct nvme_dsm_range *nvme_setup_dsm_range(__u32 *ctx_attrs, __u32 *llbas, __u64 *slbas, __u16 nr_ranges) { int i; struct nvme_dsm_range *dsm = malloc(nr_ranges * sizeof(*dsm)); if (!dsm) return NULL; for (i = 0; i < nr_ranges; i++) { dsm[i].cattr = cpu_to_le32(ctx_attrs[i]); dsm[i].nlb = cpu_to_le32(llbas[i]); dsm[i].slba = cpu_to_le64(slbas[i]); } return dsm; } int nvme_resv_acquire(int fd, __u32 nsid, __u8 rtype, __u8 racqa, bool iekey, __u64 crkey, __u64 nrkey) { __le64 payload[2] = { cpu_to_le64(crkey), cpu_to_le64(nrkey) }; __u32 cdw10 = racqa | (iekey ? 1 << 3 : 0) | rtype << 8; struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_resv_acquire, .nsid = nsid, .cdw10 = cdw10, .addr = (__u64)(uintptr_t) (payload), .data_len = sizeof(payload), }; return nvme_submit_io_passthru(fd, &cmd); } int nvme_resv_register(int fd, __u32 nsid, __u8 rrega, __u8 cptpl, bool iekey, __u64 crkey, __u64 nrkey) { __le64 payload[2] = { cpu_to_le64(crkey), cpu_to_le64(nrkey) }; __u32 cdw10 = rrega | (iekey ? 1 << 3 : 0) | cptpl << 30; struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_resv_register, .nsid = nsid, .cdw10 = cdw10, .addr = (__u64)(uintptr_t) (payload), .data_len = sizeof(payload), }; return nvme_submit_io_passthru(fd, &cmd); } int nvme_resv_release(int fd, __u32 nsid, __u8 rtype, __u8 rrela, bool iekey, __u64 crkey) { __le64 payload[1] = { cpu_to_le64(crkey) }; __u32 cdw10 = rrela | (iekey ? 1 << 3 : 0) | rtype << 8; struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_resv_release, .nsid = nsid, .cdw10 = cdw10, .addr = (__u64)(uintptr_t) (payload), .data_len = sizeof(payload), }; return nvme_submit_io_passthru(fd, &cmd); } int nvme_resv_report(int fd, __u32 nsid, __u32 numd, __u32 cdw11, void *data) { struct nvme_passthru_cmd cmd = { .opcode = nvme_cmd_resv_report, .nsid = nsid, .cdw10 = numd, .cdw11 = cdw11, .addr = (__u64)(uintptr_t) data, .data_len = numd << 2, }; return nvme_submit_io_passthru(fd, &cmd); } int nvme_passthru_admin(int fd, __u8 opcode, __u8 flags, __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout_ms) { return nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd, nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, timeout_ms, NULL); } int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_identify, .nsid = nsid, .addr = (__u64)(uintptr_t) data, .data_len = 0x1000, .cdw10 = cdw10, }; return nvme_submit_admin_passthru(fd, &cmd); } int nvme_identify_ctrl(int fd, void *data) { return nvme_identify(fd, 0, 1, data); } int nvme_identify_ns(int fd, __u32 nsid, bool present, void *data) { int cns = present ? NVME_ID_CNS_NS_PRESENT : NVME_ID_CNS_NS; return nvme_identify(fd, nsid, cns, data); } int nvme_identify_ns_list(int fd, __u32 nsid, bool all, void *data) { int cns = all ? NVME_ID_CNS_NS_PRESENT_LIST : NVME_ID_CNS_NS_ACTIVE_LIST; return nvme_identify(fd, nsid, cns, data); } int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data) { int cns = nsid ? NVME_ID_CNS_CTRL_NS_LIST : NVME_ID_CNS_CTRL_LIST; return nvme_identify(fd, nsid, (cntid << 16) | cns, data); } int nvme_identify_ns_descs(int fd, __u32 nsid, void *data) { return nvme_identify(fd, nsid, NVME_ID_CNS_NS_DESC_LIST, data); } int nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_get_log_page, .nsid = nsid, .addr = (__u64)(uintptr_t) data, .data_len = data_len, }; __u32 numd = (data_len >> 2) - 1; __u16 numdu = numd >> 16, numdl = numd & 0xffff; cmd.cdw10 = log_id | (numdl << 16); cmd.cdw11 = numdu; return nvme_submit_admin_passthru(fd, &cmd); } int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log) { return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_FW_SLOT, sizeof(*fw_log), fw_log); } int nvme_error_log(int fd, __u32 nsid, int entries, struct nvme_error_log_page *err_log) { return nvme_get_log(fd, nsid, NVME_LOG_ERROR, entries * sizeof(*err_log), err_log); } int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log) { return nvme_get_log(fd, nsid, NVME_LOG_SMART, sizeof(*smart_log), smart_log); } int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size) { return nvme_get_log(fd, 0, NVME_LOG_DISC, size, log); } int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11, __u32 data_len, void *data, __u32 *result) { struct nvme_admin_cmd cmd = { .opcode = opcode, .nsid = nsid, .cdw10 = cdw10, .cdw11 = cdw11, .addr = (__u64)(uintptr_t) data, .data_len = data_len, }; int err; err = nvme_submit_admin_passthru(fd, &cmd); if (!err && result) *result = cmd.result; return err; } int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, bool save, __u32 data_len, void *data, __u32 *result) { __u32 cdw10 = fid | (save ? 1 << 31 : 0); return nvme_feature(fd, nvme_admin_set_features, nsid, cdw10, value, data_len, data, result); } int nvme_property(int fd, __u8 fctype, __le32 off, __le64 *value, __u8 attrib) { int err; struct nvmf_property_get_command *prop_get_cmd; struct nvmf_property_set_command *prop_set_cmd; struct nvme_admin_cmd cmd = { .opcode = nvme_fabrics_command, }; if (!value) { errno = EINVAL; return -errno; } if (fctype == nvme_fabrics_type_property_get){ prop_get_cmd = (struct nvmf_property_get_command *)&cmd; prop_get_cmd->fctype = nvme_fabrics_type_property_get; prop_get_cmd->offset = off; prop_get_cmd->attrib = attrib; } else if(fctype == nvme_fabrics_type_property_set) { prop_set_cmd = (struct nvmf_property_set_command *)&cmd; prop_set_cmd->fctype = nvme_fabrics_type_property_set; prop_set_cmd->offset = off; prop_set_cmd->attrib = attrib; prop_set_cmd->value = *value; } else { errno = EINVAL; return -errno; } err = nvme_submit_admin_passthru(fd, &cmd); if (!err && fctype == nvme_fabrics_type_property_get) { *value = cpu_to_le64(cmd.result); } return err; } int nvme_get_properties(int fd, void **pbar) { __le64 value64; __le32 off; int err, ret = -EINVAL; bool is64bit; int size = getpagesize(); *pbar = malloc(size); if (!*pbar) return ret; memset(*pbar, 0xff, size); for (off = NVME_REG_CAP; off <= NVME_REG_CMBSZ; off += 4) { switch (off) { case NVME_REG_CAP: case NVME_REG_ASQ: case NVME_REG_ACQ: is64bit = true; break; default: is64bit = false; } err = nvme_property(fd, nvme_fabrics_type_property_get, off, &value64, is64bit ? 1: 0); if (err) { if (is64bit) off += 4; continue; } ret = 0; if (is64bit) *(uint64_t *)(*pbar + off) = le64_to_cpu(value64); else *(uint32_t *)(*pbar + off) = le32_to_cpu(value64); } return ret; } int nvme_set_property(int fd, int offset, int value) { __le64 val = cpu_to_le64(value); __le32 off = cpu_to_le32(offset); bool is64bit; switch (off) { case NVME_REG_CAP: case NVME_REG_ASQ: case NVME_REG_ACQ: is64bit = true; break; default: is64bit = false; } return nvme_property(fd, nvme_fabrics_type_property_set, off, &val, is64bit ? 1: 0); } int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel, __u32 cdw11, __u32 data_len, void *data, __u32 *result) { __u32 cdw10 = fid | sel << 8; return nvme_feature(fd, nvme_admin_get_features, nsid, cdw10, cdw11, data_len, data, result); } int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi, __u8 pil, __u8 ms, __u32 timeout) { __u32 cdw10 = lbaf | ms << 4 | pi << 5 | pil << 8 | ses << 9; struct nvme_admin_cmd cmd = { .opcode = nvme_admin_format_nvm, .nsid = nsid, .cdw10 = cdw10, .timeout_ms = timeout, }; return nvme_submit_admin_passthru(fd, &cmd); } int nvme_ns_create(int fd, __u64 nsze, __u64 ncap, __u8 flbas, __u8 dps, __u8 nmic, __u32 *result) { struct nvme_id_ns ns = { .nsze = cpu_to_le64(nsze), .ncap = cpu_to_le64(ncap), .flbas = flbas, .dps = dps, .nmic = nmic, }; struct nvme_admin_cmd cmd = { .opcode = nvme_admin_ns_mgmt, .addr = (__u64)(uintptr_t) ((void *)&ns), .cdw10 = 0, .data_len = 0x1000, }; int err; err = nvme_submit_admin_passthru(fd, &cmd); if (!err && result) *result = cmd.result; return err; } int nvme_ns_delete(int fd, __u32 nsid) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_ns_mgmt, .nsid = nsid, .cdw10 = 1, }; return nvme_submit_admin_passthru(fd, &cmd); } int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist, bool attach) { int i; __u8 buf[0x1000]; struct nvme_controller_list *cntlist = (struct nvme_controller_list *)buf; struct nvme_admin_cmd cmd = { .opcode = nvme_admin_ns_attach, .nsid = nsid, .addr = (__u64)(uintptr_t) cntlist, .cdw10 = attach ? 0 : 1, .data_len = 0x1000, }; memset(buf, 0, sizeof(buf)); cntlist->num = cpu_to_le16(num_ctrls); for (i = 0; i < num_ctrls; i++) cntlist->identifier[i] = cpu_to_le16(ctrlist[i]); return nvme_submit_admin_passthru(fd, &cmd); } int nvme_ns_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) { return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, true); } int nvme_ns_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) { return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, false); } int nvme_fw_download(int fd, __u32 offset, __u32 data_len, void *data) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_download_fw, .addr = (__u64)(uintptr_t) data, .data_len = data_len, .cdw10 = (data_len >> 2) - 1, .cdw11 = offset >> 2, }; return nvme_submit_admin_passthru(fd, &cmd); } int nvme_fw_commit(int fd, __u8 slot, __u8 action, __u8 bpid) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_activate_fw, .cdw10 = (action << 3) | slot, }; return nvme_submit_admin_passthru(fd, &cmd); } int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp, __u8 secp, __u32 tl, __u32 data_len, void *data, __u32 *result) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_security_send, .addr = (__u64)(uintptr_t) data, .data_len = data_len, .nsid = nsid, .cdw10 = secp << 24 | spsp << 8 | nssf, .cdw11 = tl, }; int err; err = nvme_submit_admin_passthru(fd, &cmd); if (!err && result) *result = cmd.result; return err; } int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp, __u8 secp, __u32 al, __u32 data_len, void *data, __u32 *result) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_security_recv, .nsid = nsid, .cdw10 = secp << 24 | spsp << 8 | nssf, .cdw11 = al, .addr = (__u64)(uintptr_t) data, .data_len = data_len, }; int err; err = nvme_submit_admin_passthru(fd, &cmd); if (!err && result) *result = cmd.result; return err; } int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, __u32 data_len, __u32 dw12, void *data, __u32 *result) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_directive_send, .addr = (__u64)(uintptr_t) data, .data_len = data_len, .nsid = nsid, .cdw10 = data_len? (data_len >> 2) - 1 : 0, .cdw11 = dspec << 16 | dtype << 8 | doper, .cdw12 = dw12, }; int err; err = nvme_submit_admin_passthru(fd, &cmd); if (!err && result) *result = cmd.result; return err; } int nvme_dir_recv(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, __u32 data_len, __u32 dw12, void *data, __u32 *result) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_directive_recv, .addr = (__u64)(uintptr_t) data, .data_len = data_len, .nsid = nsid, .cdw10 = data_len? (data_len >> 2) - 1 : 0, .cdw11 = dspec << 16 | dtype << 8 | doper, .cdw12 = dw12, }; int err; err = nvme_submit_admin_passthru(fd, &cmd); if (!err && result) *result = cmd.result; return err; } nvme-cli-1.5/nvme-ioctl.h000066400000000000000000000122771322317423600153330ustar00rootroot00000000000000#ifndef _NVME_LIB_H #define _NVME_LIB_H #include #include #include "linux/nvme_ioctl.h" #include "nvme.h" int nvme_get_nsid(int fd); /* Generic passthrough */ int nvme_submit_passthru(int fd, int ioctl_cmd, struct nvme_passthru_cmd *cmd); int nvme_passthru(int fd, int ioctl_cmd, __u8 opcode, __u8 flags, __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout_ms, __u32 *result); /* NVME_SUBMIT_IO */ int nvme_io(int fd, __u8 opcode, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata); int nvme_read(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata); int nvme_write(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata); int nvme_compare(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, void *metadata); /* NVME_IO_CMD */ int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout); int nvme_write_zeros(int fd, __u32 nsid, __u64 slba, __u16 nlb, __u16 control, __u32 reftag, __u16 apptag, __u16 appmask); int nvme_write_uncorrectable(int fd, __u32 nsid, __u64 slba, __u16 nlb); int nvme_flush(int fd, __u32 nsid); int nvme_dsm(int fd, __u32 nsid, __u32 cdw11, struct nvme_dsm_range *dsm, __u16 nr_ranges); struct nvme_dsm_range *nvme_setup_dsm_range(__u32 *ctx_attrs, __u32 *llbas, __u64 *slbas, __u16 nr_ranges); int nvme_resv_acquire(int fd, __u32 nsid, __u8 rtype, __u8 racqa, bool iekey, __u64 crkey, __u64 nrkey); int nvme_resv_register(int fd, __u32 nsid, __u8 rrega, __u8 cptpl, bool iekey, __u64 crkey, __u64 nrkey); int nvme_resv_release(int fd, __u32 nsid, __u8 rtype, __u8 rrela, bool iekey, __u64 crkey); int nvme_resv_report(int fd, __u32 nsid, __u32 numd, __u32 cdw11, void *data); /* NVME_ADMIN_CMD */ int nvme_passthru_admin(int fd, __u8 opcode, __u8 flags, __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout); int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data); int nvme_identify_ctrl(int fd, void *data); int nvme_identify_ns(int fd, __u32 nsid, bool present, void *data); int nvme_identify_ns_list(int fd, __u32 nsid, bool all, void *data); int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data); int nvme_identify_ns_descs(int fd, __u32 nsid, void *data); int nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data); int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log); int nvme_error_log(int fd, __u32 nsid, int entries, struct nvme_error_log_page *err_log); int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log); int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size); int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11, __u32 data_len, void *data, __u32 *result); int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, bool save, __u32 data_len, void *data, __u32 *result); int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel, __u32 cdw11, __u32 data_len, void *data, __u32 *result); int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi, __u8 pil, __u8 ms, __u32 timeout); int nvme_ns_create(int fd, __u64 nsze, __u64 ncap, __u8 flbas, __u8 dps, __u8 nmic, __u32 *result); int nvme_ns_delete(int fd, __u32 nsid); int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist, bool attach); int nvme_ns_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); int nvme_ns_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); int nvme_fw_download(int fd, __u32 offset, __u32 data_len, void *data); int nvme_fw_commit(int fd, __u8 slot, __u8 action, __u8 bpid); int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp, __u8 secp, __u32 tl, __u32 data_len, void *data, __u32 *result); int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp, __u8 secp, __u32 al, __u32 data_len, void *data, __u32 *result); int nvme_subsystem_reset(int fd); int nvme_reset_controller(int fd); int nvme_ns_rescan(int fd); int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, __u32 data_len, __u32 dw12, void *data, __u32 *result); int nvme_dir_recv(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, __u32 data_len, __u32 dw12, void *data, __u32 *result); int nvme_get_properties(int fd, void **pbar); int nvme_set_property(int fd, int offset, int value); #endif /* _NVME_LIB_H */ nvme-cli-1.5/nvme-lightnvm.c000066400000000000000000000260441322317423600160410ustar00rootroot00000000000000/* * lightnvm.c -- LightNVM NVMe integration. * * Copyright (c) 2016, CNEX Labs. * * Written by Matias Bjoerling * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include "nvme-lightnvm.h" #include "nvme-print.h" #include "nvme-ioctl.h" static int lnvm_open(void) { char dev[FILENAME_MAX] = NVM_CTRL_FILE; int fd; fd = open(dev, O_WRONLY); if (fd < 0) { printf("Failed to open LightNVM mgmt interface\n"); perror(dev); return fd; } return fd; } static void lnvm_close(int fd) { close(fd); } int lnvm_do_init(char *dev, char *mmtype) { struct nvm_ioctl_dev_init init; int fd, ret; fd = lnvm_open(); if (fd < 0) return fd; memset(&init, 0, sizeof(struct nvm_ioctl_dev_init)); strncpy(init.dev, dev, DISK_NAME_LEN); strncpy(init.mmtype, mmtype, NVM_MMTYPE_LEN); ret = ioctl(fd, NVM_DEV_INIT, &init); switch (errno) { case EINVAL: printf("Initialization failed.\n"); break; case EEXIST: printf("Device has already been initialized.\n"); break; case 0: break; default: printf("Unknown error occurred (%d)\n", errno); break; } lnvm_close(fd); return ret; } int lnvm_do_list_devices(void) { struct nvm_ioctl_get_devices devs; int fd, ret, i; fd = lnvm_open(); if (fd < 0) return fd; ret = ioctl(fd, NVM_GET_DEVICES, &devs); if (ret) return ret; printf("Number of devices: %u\n", devs.nr_devices); printf("%-12s\t%-12s\tVersion\n", "Device", "Block manager"); for (i = 0; i < devs.nr_devices && i < 31; i++) { struct nvm_ioctl_device_info *info = &devs.info[i]; printf("%-12s\t%-12s\t(%u,%u,%u)\n", info->devname, info->bmname, info->bmversion[0], info->bmversion[1], info->bmversion[2]); } lnvm_close(fd); return 0; } int lnvm_do_info(void) { struct nvm_ioctl_info c; int fd, ret, i; fd = lnvm_open(); if (fd < 0) return fd; memset(&c, 0, sizeof(struct nvm_ioctl_info)); ret = ioctl(fd, NVM_INFO, &c); if (ret) return ret; printf("LightNVM (%u,%u,%u). %u target type(s) registered.\n", c.version[0], c.version[1], c.version[2], c.tgtsize); printf("Type\tVersion\n"); for (i = 0; i < c.tgtsize; i++) { struct nvm_ioctl_info_tgt *tgt = &c.tgts[i]; printf("%s\t(%u,%u,%u)\n", tgt->tgtname, tgt->version[0], tgt->version[1], tgt->version[2]); } lnvm_close(fd); return 0; } int lnvm_do_create_tgt(char *devname, char *tgtname, char *tgttype, int lun_begin, int lun_end, int flags) { struct nvm_ioctl_create c; int fd, ret; fd = lnvm_open(); if (fd < 0) return fd; strncpy(c.dev, devname, DISK_NAME_LEN); strncpy(c.tgtname, tgtname, DISK_NAME_LEN); strncpy(c.tgttype, tgttype, NVM_TTYPE_NAME_MAX); c.flags = 0; c.conf.type = 0; c.conf.s.lun_begin = lun_begin; c.conf.s.lun_end = lun_end; c.flags = flags; ret = ioctl(fd, NVM_DEV_CREATE, &c); if (ret) fprintf(stderr, "Creation of target failed. Please see dmesg.\n"); lnvm_close(fd); return ret; } int lnvm_do_remove_tgt(char *tgtname) { struct nvm_ioctl_remove c; int fd, ret; fd = lnvm_open(); if (fd < 0) return fd; strncpy(c.tgtname, tgtname, DISK_NAME_LEN); c.flags = 0; ret = ioctl(fd, NVM_DEV_REMOVE, &c); if (ret) fprintf(stderr, "Remove of target failed. Please see dmesg.\n"); lnvm_close(fd); return ret; } int lnvm_do_factory_init(char *devname, int erase_only_marked, int clear_host_marks, int clear_bb_marks) { struct nvm_ioctl_dev_factory fact; int fd, ret; fd = lnvm_open(); if (fd < 0) return fd; memset(&fact, 0, sizeof(struct nvm_ioctl_dev_factory)); strncpy(fact.dev, devname, DISK_NAME_LEN); if (erase_only_marked) fact.flags |= NVM_FACTORY_ERASE_ONLY_USER; if (clear_host_marks) fact.flags |= NVM_FACTORY_RESET_HOST_BLKS; if (clear_bb_marks) fact.flags |= NVM_FACTORY_RESET_GRWN_BBLKS; ret = ioctl(fd, NVM_DEV_FACTORY, &fact); switch (errno) { case EINVAL: fprintf(stderr, "Factory reset failed.\n"); break; case 0: break; default: fprintf(stderr, "Unknown error occurred (%d)\n", errno); break; } lnvm_close(fd); return ret; } static void show_lnvm_id_grp(struct nvme_nvm_id_group *grp) { printf(" mtype : %d\n", grp->mtype); printf(" fmtype : %d\n", grp->fmtype); printf(" chnls : %d\n", grp->num_ch); printf(" luns : %d\n", grp->num_lun); printf(" plns : %d\n", grp->num_pln); printf(" blks : %d\n", (uint16_t)le16_to_cpu(grp->num_blk)); printf(" pgs : %d\n", (uint16_t)le16_to_cpu(grp->num_pg)); printf(" fpg_sz : %d\n", (uint16_t)le16_to_cpu(grp->fpg_sz)); printf(" csecs : %d\n", (uint16_t)le16_to_cpu(grp->csecs)); printf(" sos : %d\n", (uint16_t)le16_to_cpu(grp->sos)); printf(" trdt : %d\n", (uint32_t)le32_to_cpu(grp->trdt)); printf(" trdm : %d\n", (uint32_t)le32_to_cpu(grp->trdm)); printf(" tprt : %d\n", (uint32_t)le32_to_cpu(grp->tprt)); printf(" tprm : %d\n", (uint32_t)le32_to_cpu(grp->tprm)); printf(" tbet : %d\n", (uint32_t)le32_to_cpu(grp->tbet)); printf(" tbem : %d\n", (uint32_t)le32_to_cpu(grp->tbem)); printf(" mpos : %#x\n", (uint32_t)le32_to_cpu(grp->mpos)); printf(" mccap : %#x\n", (uint32_t)le32_to_cpu(grp->mccap)); printf(" cpar : %#x\n", (uint16_t)le16_to_cpu(grp->cpar)); } static void show_lnvm_ppaf(struct nvme_nvm_addr_format *ppaf) { printf("ppaf :\n"); printf(" ch offs : %d ch bits : %d\n", ppaf->ch_offset, ppaf->ch_len); printf(" lun offs: %d lun bits : %d\n", ppaf->lun_offset, ppaf->lun_len); printf(" pl offs : %d pl bits : %d\n", ppaf->pln_offset, ppaf->pln_len); printf(" blk offs: %d blk bits : %d\n", ppaf->blk_offset, ppaf->blk_len); printf(" pg offs : %d pg bits : %d\n", ppaf->pg_offset, ppaf->pg_len); printf(" sec offs: %d sec bits : %d\n", ppaf->sect_offset, ppaf->sect_len); } static void show_lnvm_id_ns(struct nvme_nvm_id *id) { int i; if (id->cgrps > 4) { fprintf(stderr, "invalid identify geometry returned\n"); return; } printf("verid : %#x\n", id->ver_id); printf("vmnt : %#x\n", id->vmnt); printf("cgrps : %d\n", id->cgrps); printf("cap : %#x\n", (uint32_t)le32_to_cpu(id->cap)); printf("dom : %#x\n", (uint32_t)le32_to_cpu(id->dom)); show_lnvm_ppaf(&id->ppaf); for (i = 0; i < id->cgrps; i++) { printf("grp : %d\n", i); show_lnvm_id_grp(&id->groups[i]); } } static int lnvm_get_identity(int fd, int nsid, struct nvme_nvm_id *nvm_id) { struct nvme_admin_cmd cmd = { .opcode = nvme_nvm_admin_identity, .nsid = nsid, .addr = (__u64)(uintptr_t)nvm_id, .data_len = 0x1000, }; return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd); } int lnvm_do_id_ns(int fd, int nsid, unsigned int flags) { struct nvme_nvm_id nvm_id; int err; err = lnvm_get_identity(fd, nsid, &nvm_id); if (!err) { if (flags & RAW) d_raw((unsigned char *)&nvm_id, sizeof(nvm_id)); else { printf("LightNVM Identify Geometry (%d):\n", nsid); show_lnvm_id_ns(&nvm_id); } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", nvme_status_to_string(err), err, nsid); return err; } static void show_lnvm_bbtbl(struct nvme_nvm_bb_tbl *tbl) { printf("verid : %#x\n", (uint16_t)le16_to_cpu(tbl->verid)); printf("tblks : %d\n", (uint32_t)le32_to_cpu(tbl->tblks)); printf("tfact : %d\n", (uint32_t)le32_to_cpu(tbl->tfact)); printf("tgrown : %d\n", (uint32_t)le32_to_cpu(tbl->tgrown)); printf("tdresv : %d\n", (uint32_t)le32_to_cpu(tbl->tdresv)); printf("thresv : %d\n", (uint32_t)le32_to_cpu(tbl->thresv)); printf("Use raw output to retrieve table.\n"); } static int __lnvm_do_get_bbtbl(int fd, struct nvme_nvm_id *id, struct ppa_addr ppa, unsigned int flags) { struct nvme_nvm_id_group *grp = &id->groups[0]; int bbtblsz = ((uint16_t)le16_to_cpu(grp->num_blk) * grp->num_pln); int bufsz = bbtblsz + sizeof(struct nvme_nvm_bb_tbl); struct nvme_nvm_bb_tbl *bbtbl; int err; bbtbl = calloc(1, bufsz); if (!bbtbl) return -ENOMEM; struct nvme_nvm_getbbtbl cmd = { .opcode = nvme_nvm_admin_get_bb_tbl, .nsid = cpu_to_le32(1), .addr = (__u64)(uintptr_t)bbtbl, .data_len = cpu_to_le32(bufsz), .ppa = cpu_to_le64(ppa.ppa), }; err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, (struct nvme_passthru_cmd *)&cmd); if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); free(bbtbl); return err; } if (flags & RAW) d_raw((unsigned char *)&bbtbl->blk, bbtblsz); else { printf("LightNVM Bad Block Stats:\n"); show_lnvm_bbtbl(bbtbl); } free(bbtbl); return 0; } int lnvm_do_get_bbtbl(int fd, int nsid, int lunid, int chid, unsigned int flags) { struct nvme_nvm_id nvm_id; struct ppa_addr ppa; int err; err = lnvm_get_identity(fd, nsid, &nvm_id); if (err) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } if (chid >= nvm_id.groups[0].num_ch || lunid >= nvm_id.groups[0].num_lun) { fprintf(stderr, "Out of bound channel id or LUN id\n"); return -EINVAL; } ppa.ppa = 0; ppa.g.lun = lunid; ppa.g.ch = chid; ppa = generic_to_dev_addr(&nvm_id.ppaf, ppa); return __lnvm_do_get_bbtbl(fd, &nvm_id, ppa, flags); } static int __lnvm_do_set_bbtbl(int fd, struct ppa_addr ppa, __u8 value) { int err; struct nvme_nvm_setbbtbl cmd = { .opcode = nvme_nvm_admin_set_bb_tbl, .nsid = cpu_to_le32(1), .ppa = cpu_to_le64(ppa.ppa), .nlb = cpu_to_le16(0), .value = value, }; err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, (struct nvme_passthru_cmd *)&cmd); if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } return 0; } int lnvm_do_set_bbtbl(int fd, int nsid, int chid, int lunid, int plnid, int blkid, __u8 value) { struct nvme_nvm_id nvm_id; struct ppa_addr ppa; int err; err = lnvm_get_identity(fd, nsid, &nvm_id); if (err) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } if (chid >= nvm_id.groups[0].num_ch || lunid >= nvm_id.groups[0].num_lun || plnid >= nvm_id.groups[0].num_pln || blkid >= le16_to_cpu(nvm_id.groups[0].num_blk)) { fprintf(stderr, "Out of bound channel id, LUN id, plane id, or"\ "block id\n"); return -EINVAL; } ppa.ppa = 0; ppa.g.lun = lunid; ppa.g.ch = chid; ppa.g.pl = plnid; ppa.g.blk = blkid; ppa = generic_to_dev_addr(&nvm_id.ppaf, ppa); return __lnvm_do_set_bbtbl(fd, ppa, value); } nvme-cli-1.5/nvme-lightnvm.h000066400000000000000000000114531322317423600160440ustar00rootroot00000000000000/* * Copyright (C) 2016 CNEX Labs. All rights reserved. * * Author: Matias Bjoerling * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, * USA. */ #ifndef NVME_LIGHTNVM_H_ #define NVME_LIGHTNVM_H_ #include "linux/lightnvm.h" enum nvme_nvm_admin_opcode { nvme_nvm_admin_identity = 0xe2, nvme_nvm_admin_get_bb_tbl = 0xf2, nvme_nvm_admin_set_bb_tbl = 0xf1, }; struct nvme_nvm_identity { __u8 opcode; __u8 flags; __le16 command_id; __le32 nsid; __le64 rsvd[2]; __le64 prp1; __le64 prp2; __le32 chnl_off; __le32 rsvd11[5]; }; struct nvme_nvm_setbbtbl { __u8 opcode; __u8 flags; __le16 rsvd1; __le32 nsid; __le32 cdw2; __le32 cdw3; __le64 metadata; __u64 addr; __le32 metadata_len; __le32 data_len; __le64 ppa; __le16 nlb; __u8 value; __u8 rsvd2; __le32 cdw14; __le32 cdw15; __le32 timeout_ms; __le32 result; }; struct nvme_nvm_getbbtbl { __u8 opcode; __u8 flags; __le16 rsvd1; __le32 nsid; __le32 cdw2; __le32 cdw3; __le64 metadata; __u64 addr; __le32 metadata_len; __le32 data_len; __le64 ppa; __le32 cdw11; __le32 cdw12; __le32 cdw13; __le32 cdw14; __le32 cdw15; __le32 timeout_ms; __le32 result; }; struct nvme_nvm_command { union { struct nvme_nvm_identity identity; struct nvme_nvm_getbbtbl get_bb; }; }; struct nvme_nvm_completion { __le64 result; /* Used by LightNVM to return ppa completions */ __le16 sq_head; /* how much of this queue may be reclaimed */ __le16 sq_id; /* submission queue that generated this entry */ __le16 command_id; /* of the command which completed */ __le16 status; /* did the command fail, and if so, why? */ }; #define NVME_NVM_LP_MLC_PAIRS 886 struct nvme_nvm_lp_mlc { __le16 num_pairs; __u8 pairs[NVME_NVM_LP_MLC_PAIRS]; }; struct nvme_nvm_lp_tbl { __u8 id[8]; struct nvme_nvm_lp_mlc mlc; }; struct nvme_nvm_id_group { __u8 mtype; __u8 fmtype; __le16 res16; __u8 num_ch; __u8 num_lun; __u8 num_pln; __u8 rsvd1; __le16 num_blk; __le16 num_pg; __le16 fpg_sz; __le16 csecs; __le16 sos; __le16 rsvd2; __le32 trdt; __le32 trdm; __le32 tprt; __le32 tprm; __le32 tbet; __le32 tbem; __le32 mpos; __le32 mccap; __le16 cpar; __u8 reserved[10]; struct nvme_nvm_lp_tbl lptbl; } __attribute__((packed)); struct nvme_nvm_addr_format { __u8 ch_offset; __u8 ch_len; __u8 lun_offset; __u8 lun_len; __u8 pln_offset; __u8 pln_len; __u8 blk_offset; __u8 blk_len; __u8 pg_offset; __u8 pg_len; __u8 sect_offset; __u8 sect_len; __u8 res[4]; } __attribute__((packed)); struct nvme_nvm_id { __u8 ver_id; __u8 vmnt; __u8 cgrps; __u8 res; __le32 cap; __le32 dom; struct nvme_nvm_addr_format ppaf; __u8 resv[228]; struct nvme_nvm_id_group groups[4]; } __attribute__((packed)); struct nvme_nvm_bb_tbl { __u8 tblid[4]; __le16 verid; __le16 revid; __le32 rvsd1; __le32 tblks; __le32 tfact; __le32 tgrown; __le32 tdresv; __le32 thresv; __le32 rsvd2[8]; __u8 blk[0]; }; #define NVM_BLK_BITS (16) #define NVM_PG_BITS (16) #define NVM_SEC_BITS (8) #define NVM_PL_BITS (8) #define NVM_LUN_BITS (8) #define NVM_CH_BITS (7) struct ppa_addr { /* Generic structure for all addresses */ union { struct { __u64 blk : NVM_BLK_BITS; __u64 pg : NVM_PG_BITS; __u64 sec : NVM_SEC_BITS; __u64 pl : NVM_PL_BITS; __u64 lun : NVM_LUN_BITS; __u64 ch : NVM_CH_BITS; __u64 reserved : 1; } g; __u64 ppa; }; }; static inline struct ppa_addr generic_to_dev_addr( struct nvme_nvm_addr_format *ppaf, struct ppa_addr r) { struct ppa_addr l; l.ppa = ((__u64)r.g.blk) << ppaf->blk_offset; l.ppa |= ((__u64)r.g.pg) << ppaf->pg_offset; l.ppa |= ((__u64)r.g.sec) << ppaf->sect_offset; l.ppa |= ((__u64)r.g.pl) << ppaf->pln_offset; l.ppa |= ((__u64)r.g.lun) << ppaf->lun_offset; l.ppa |= ((__u64)r.g.ch) << ppaf->ch_offset; return l; } int lnvm_do_init(char *, char *); int lnvm_do_list_devices(void); int lnvm_do_info(void); int lnvm_do_create_tgt(char *, char *, char *, int, int, int); int lnvm_do_remove_tgt(char *); int lnvm_do_factory_init(char *, int, int, int); int lnvm_do_id_ns(int, int, unsigned int); int lnvm_do_get_bbtbl(int, int, int, int, unsigned int); int lnvm_do_set_bbtbl(int, int, int, int, int, int, __u8); #endif nvme-cli-1.5/nvme-models.c000066400000000000000000000150271322317423600154730ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include static char *_fmt1 = "/sys/class/nvme/nvme%d/device/subsystem_vendor"; static char *_fmt2 = "/sys/class/nvme/nvme%d/device/subsystem_device"; static char *_fmt3 = "/sys/class/nvme/nvme%d/device/vendor"; static char *_fmt4 = "/sys/class/nvme/nvme%d/device/device"; static char *_fmt5 = "/sys/class/nvme/nvme%d/device/class"; static char fmt1[78]; static char fmt2[78]; static char fmt3[78]; static char fmt4[78]; static char fmt5[78]; static char *device_top; static char *device_mid; static char *device_final; static char *class_top; static char *class_mid; static char *class_final; static void free_all(void) { free(device_top); device_top = NULL; free(device_mid); device_mid = NULL; free(device_final); device_final = NULL; free(class_top); class_top = NULL; free(class_mid); class_mid = NULL; free(class_final); class_final = NULL; } static char *find_data(char *data) { while (*data != '\0') { if (*data >= '0' && *data <= '9') return data; data++; } return NULL; } static char *locate_info(char *data, bool is_inner, bool is_class) { char *orig = data; char *locate = find_data(data); if (!data) return orig; if (is_class) return locate + 4; if (!is_inner) /* 4 to get over the number, 2 for spaces */ return locate + 4 + 2; /* Inner data, has "sub_ven(space)sub_dev(space)(space)string */ return locate + 4 + 1 + 4 + 2; } static void format_and_print(char *save) { if (!class_mid) snprintf(save, 1024, "%s %s %s", locate_info(device_top, false, false), locate_info(device_mid, false, false), locate_info(device_final, true, false)); else snprintf(save, 1024, "%s: %s %s %s", locate_info(class_mid, false, true), locate_info(device_top, false, false), locate_info(device_mid, false, false), locate_info(device_final, true, false)); } static void format_all(char *save, char *vendor, char *device) { if (device_top && device_mid && device_final) format_and_print(save); else if (device_top && !device_mid && class_mid) snprintf(save, 1024, "%s: %s Device %s", locate_info(class_mid, false, true), locate_info(device_top, false, false), device); else if (!device_top && class_mid) snprintf(save, 1024, "%s: Vendor %s Device %s", locate_info(class_mid, false, true), vendor, device); else snprintf(save, 1024, "Unknown device"); } static int is_final_match(char *line, char *search) { return !memcmp(&line[2], search, 2); } static int is_inner_sub_vendev(char *line, char *search, char *search2) { char combine[10]; snprintf(combine, sizeof(combine), "%s %s", &search[2], &search2[2]); if (line[0] != '\t' && line[1] != '\t') return 0; return !memcmp(combine, &line[2], 9); } static int is_mid_level_match(char *line, char *device, bool class) { if (!class) return !memcmp(&line[1], &device[2], 4); return !memcmp(&line[1], device, 2); } static inline bool is_comment(char *line) { return line[0] == '#'; } static int is_top_level_match(char *line, const char* device, bool class) { if (line[0] == '\t') return false; if (line[0] == '#') return false; if (!class) return !memcmp(line, &device[2], 4); if (line[0] != 'C') return false; /* Skipping C(SPACE) 0x */ return !memcmp(&line[2], &device[2], 2); } static inline int is_tab(char *line) { return line[0] == '\t'; } static inline int is_class_info(char *line) { return !memcmp(line, "# C class", 9); } static void parse_vendor_device(char **line, FILE *file, char *device, char *subdev, char *subven) { bool device_single_found = false; size_t amnt = 1024; size_t found = 0; char *newline; while ((found = getline(line, &amnt, file)) != -1) { newline = *line; if (is_comment(newline)) continue; if (!is_tab(newline)) return; newline[found - 1] = '\0'; if (!device_single_found && is_mid_level_match(newline, device, false)) { device_single_found = true; device_mid = strdup(newline); continue; } if (device_single_found && is_inner_sub_vendev(newline, subven, subdev)) { device_final = strdup(newline); break; } } } static void pull_class_info(char **_newline, FILE *file, char *class) { size_t amnt; size_t size = 1024; bool top_found = false; bool mid_found = false; char *newline; while ((amnt = getline(_newline, &size, file)) != -1) { newline = *_newline; newline[amnt - 1] = '\0'; if (!top_found && is_top_level_match(newline, class, true)) { class_top = strdup(newline); top_found = true; continue; } if (!mid_found && top_found && is_mid_level_match(newline, &class[4], true)) { class_mid = strdup(newline); mid_found = true; continue; } if (top_found && mid_found && is_final_match(newline, &class[6])) { class_final = strdup(newline); break; } } } static int read_sys_node(char *where, char *save, size_t savesz) { char *new; int fd, ret = 0; fd = open(where, O_RDONLY); if (fd < 0) { fprintf(stderr, "Failed to open %s with errno %s\n", where, strerror(errno)); return 1; } /* -1 so we can safely use strstr below */ if(!read(fd, save, savesz - 1)) ret = 1; new = strstr(save, "\n"); if (new) new[0] = '\0'; close(fd); return ret; } char *nvme_product_name(int id) { char *line; ssize_t amnt; FILE *file = fopen("/usr/share/hwdata/pci.ids", "r"); char vendor[7] = { 0 }; char device[7] = { 0 }; char sub_device[7] = { 0 }; char sub_vendor[7] = { 0 }; char class[13] = { 0 }; size_t size = 1024; char ret; if (!file) goto error1; snprintf(fmt1, 78, _fmt1, id); snprintf(fmt2, 78, _fmt2, id); snprintf(fmt3, 78, _fmt3, id); snprintf(fmt4, 78, _fmt4, id); snprintf(fmt5, 78, _fmt5, id); ret = read_sys_node(fmt1, sub_vendor, 7); ret |= read_sys_node(fmt2, sub_device, 7); ret |= read_sys_node(fmt3, vendor, 7); ret |= read_sys_node(fmt4, device, 7); ret |= read_sys_node(fmt5, class, 13); if (ret) goto error1; line = malloc(1024); if (!line) goto error1; while ((amnt = getline(&line, &size, file)) != -1) { if (is_comment(line) && !is_class_info(line)) continue; if (is_top_level_match(line, vendor, false)) { line[amnt - 1] = '\0'; device_top = strdup(line); parse_vendor_device(&line, file, device, sub_device, sub_vendor); } if (is_class_info(line)) pull_class_info(&line, file, class); } format_all(line, vendor, device); free_all(); return line; error1: return strdup("Unknown Device"); } nvme-cli-1.5/nvme-models.h000066400000000000000000000001241322317423600154700ustar00rootroot00000000000000#ifndef NVME_MODEL_H #define NVME_MODEL_H char *nvme_product_name(int id); #endif nvme-cli-1.5/nvme-print.c000066400000000000000000002312261322317423600153450ustar00rootroot00000000000000#include #include #include #include #include "nvme-print.h" #include "json.h" #include "nvme-models.h" static long double int128_to_double(__u8 *data) { int i; long double result = 0; for (i = 0; i < 16; i++) { result *= 256; result += data[15 - i]; } return result; } void d(unsigned char *buf, int len, int width, int group) { int i, offset = 0, line_done = 0; char ascii[width + 1]; printf(" "); for (i = 0; i <= 15; i++) printf("%3x", i); for (i = 0; i < len; i++) { line_done = 0; if (i % width == 0) printf( "\n%04x:", offset); if (i % group == 0) printf( " %02x", buf[i]); else printf( "%02x", buf[i]); ascii[i % width] = (buf[i] >= '!' && buf[i] <= '~') ? buf[i] : '.'; if (((i + 1) % width) == 0) { ascii[i % width + 1] = '\0'; printf( " \"%.*s\"", width, ascii); offset += width; line_done = 1; } } if (!line_done) { unsigned b = width - (i % width); ascii[i % width + 1] = '\0'; printf( " %*s \"%.*s\"", 2 * b + b / group + (b % group ? 1 : 0), "", width, ascii); } printf( "\n"); } void d_raw(unsigned char *buf, unsigned len) { unsigned i; for (i = 0; i < len; i++) putchar(*(buf+i)); } static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz) { fmt_sz = snprintf(formatter,fmt_sz, "%-*.*s", (int)tofmtsz, (int)tofmtsz, tofmt); /* trim() the obnoxious trailing white lines */ while (fmt_sz) { if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') { formatter[fmt_sz] = '\0'; break; } fmt_sz--; } } static void show_nvme_id_ctrl_cmic(__u8 cmic) { __u8 rsvd = (cmic & 0xF8) >> 3; __u8 sriov = (cmic & 0x4) >> 2; __u8 mctl = (cmic & 0x2) >> 1; __u8 mp = cmic & 0x1; if (rsvd) printf(" [7:3] : %#x\tReserved\n", rsvd); printf(" [2:2] : %#x\t%s\n", sriov, sriov ? "SR-IOV" : "PCI"); printf(" [1:1] : %#x\t%s Controller\n", mctl, mctl ? "Multi" : "Single"); printf(" [0:0] : %#x\t%s Port\n", mp, mp ? "Multi" : "Single"); printf("\n"); } static void show_nvme_id_ctrl_oaes(__le32 ctrl_oaes) { __u32 oaes = le32_to_cpu(ctrl_oaes); __u32 rsvd0 = (oaes & 0xFFFFFE00) >> 9; __u32 nace = (oaes & 0x100) >> 8; __u32 rsvd1 = oaes & 0xFF; if (rsvd0) printf(" [31:9] : %#x\tReserved\n", rsvd0); printf(" [8:8] : %#x\tNamespace Attribute Changed Event %sSupported\n", nace, nace ? "" : "Not "); if (rsvd1) printf(" [7:0] : %#x\tReserved\n", rsvd1); printf("\n"); } static void show_nvme_id_ctrl_ctratt(__le32 ctrl_ctratt) { __u32 ctratt = le32_to_cpu(ctrl_ctratt); __u32 rsvd0 = (ctratt & 0xFFFFFFFE) >> 1; __u32 hostid128 = ctratt & 0x1; if (rsvd0) printf(" [31:1] : %#x\tReserved\n", rsvd0); printf(" [0:0] : %#x\t128-bit Host Identifier %sSupported\n", hostid128, hostid128 ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_oacs(__le16 ctrl_oacs) { __u16 oacs = le16_to_cpu(ctrl_oacs); __u16 rsvd = (oacs & 0xFE00) >> 9; __u16 dbc = (oacs & 0x100) >> 8; __u16 vir = (oacs & 0x80) >> 7; __u16 nmi = (oacs & 0x40) >> 6; __u16 dir = (oacs & 0x20) >> 5; __u16 sft = (oacs & 0x10) >> 4; __u16 nsm = (oacs & 0x8) >> 3; __u16 fwc = (oacs & 0x4) >> 2; __u16 fmt = (oacs & 0x2) >> 1; __u16 sec = oacs & 0x1; if (rsvd) printf(" [15:9] : %#x\tReserved\n", rsvd); printf(" [8:8] : %#x\tDoorbell Buffer Config %sSupported\n", dbc, dbc ? "" : "Not "); printf(" [7:7] : %#x\tVirtualization Management %sSupported\n", vir, vir ? "" : "Not "); printf(" [6:6] : %#x\tNVMe-MI Send and Receive %sSupported\n", nmi, nmi ? "" : "Not "); printf(" [5:5] : %#x\tDirectives %sSupported\n", dir, dir ? "" : "Not "); printf(" [4:4] : %#x\tDevice Self-test %sSupported\n", sft, sft ? "" : "Not "); printf(" [3:3] : %#x\tNS Management and Attachment %sSupported\n", nsm, nsm ? "" : "Not "); printf(" [2:2] : %#x\tFW Commit and Download %sSupported\n", fwc, fwc ? "" : "Not "); printf(" [1:1] : %#x\tFormat NVM %sSupported\n", fmt, fmt ? "" : "Not "); printf(" [0:0] : %#x\tSecurity Send and Receive %sSupported\n", sec, sec ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_frmw(__u8 frmw) { __u8 rsvd = (frmw & 0xE0) >> 5; __u8 fawr = (frmw & 0x10) >> 4; __u8 nfws = (frmw & 0xE) >> 1; __u8 s1ro = frmw & 0x1; if (rsvd) printf(" [7:5] : %#x\tReserved\n", rsvd); printf(" [4:4] : %#x\tFirmware Activate Without Reset %sSupported\n", fawr, fawr ? "" : "Not "); printf(" [3:1] : %#x\tNumber of Firmware Slots\n", nfws); printf(" [0:0] : %#x\tFirmware Slot 1 Read%s\n", s1ro, s1ro ? "-Only" : "/Write"); printf("\n"); } static void show_nvme_id_ctrl_lpa(__u8 lpa) { __u8 rsvd = (lpa & 0xF8) >> 3; __u8 ed = (lpa & 0x4) >> 2; __u8 celp = (lpa & 0x2) >> 1; __u8 smlp = lpa & 0x1; if (rsvd) printf(" [7:3] : %#x\tReserved\n", rsvd); printf(" [2:2] : %#x\tExtended data for Get Log Page %sSupported\n", ed, ed ? "" : "Not "); printf(" [1:1] : %#x\tCommand Effects Log Page %sSupported\n", celp, celp ? "" : "Not "); printf(" [0:0] : %#x\tSMART/Health Log Page per NS %sSupported\n", smlp, smlp ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_avscc(__u8 avscc) { __u8 rsvd = (avscc & 0xFE) >> 1; __u8 fmt = avscc & 0x1; if (rsvd) printf(" [7:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\tAdmin Vendor Specific Commands uses %s Format\n", fmt, fmt ? "NVMe" : "Vendor Specific"); printf("\n"); } static void show_nvme_id_ctrl_apsta(__u8 apsta) { __u8 rsvd = (apsta & 0xFE) >> 1; __u8 apst = apsta & 0x1; if (rsvd) printf(" [7:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\tAutonomous Power State Transitions %sSupported\n", apst, apst ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_rpmbs(__le32 ctrl_rpmbs) { __u32 rpmbs = le32_to_cpu(ctrl_rpmbs); __u32 asz = (rpmbs & 0xFF000000) >> 24; __u32 tsz = (rpmbs & 0xFF0000) >> 16; __u32 rsvd = (rpmbs & 0xFFC0) >> 6; __u32 auth = (rpmbs & 0x38) >> 3; __u32 rpmb = rpmbs & 0x7; printf(" [31:24]: %#x\tAccess Size\n", asz); printf(" [23:16]: %#x\tTotal Size\n", tsz); if (rsvd) printf(" [15:6] : %#x\tReserved\n", rsvd); printf(" [5:3] : %#x\tAuthentication Method\n", auth); printf(" [2:0] : %#x\tNumber of RPMB Units\n", rpmb); printf("\n"); } static void show_nvme_id_ctrl_hctma(__le16 ctrl_hctma) { __u16 hctma = le16_to_cpu(ctrl_hctma); __u16 rsvd = (hctma & 0xFFFE) >> 1; __u16 hctm = hctma & 0x1; if (rsvd) printf(" [15:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\tHost Controlled Thermal Management %sSupported\n", hctm, hctm ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_sanicap(__le32 ctrl_sanicap) { __u32 sanicap = le32_to_cpu(ctrl_sanicap); __u32 rsvd = (sanicap & 0xFFFFFFF8) >> 3; __u32 owr = (sanicap & 0x4) >> 2; __u32 ber = (sanicap & 0x2) >> 1; __u32 cer = sanicap & 0x1; if (rsvd) printf(" [31:3] : %#x\tReserved\n", rsvd); printf(" [2:2] : %#x\tOverwrite Sanitize Operation %sSupported\n", owr, owr ? "" : "Not "); printf(" [1:1] : %#x\tBlock Erase Sanitize Operation %sSupported\n", ber, ber ? "" : "Not "); printf(" [0:0] : %#x\tCrypto Erase Sanitize Operation %sSupported\n", cer, cer ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_sqes(__u8 sqes) { __u8 msqes = (sqes & 0xF0) >> 4; __u8 rsqes = sqes & 0xF; printf(" [7:4] : %#x\tMax SQ Entry Size (%d)\n", msqes, 1 << msqes); printf(" [3:0] : %#x\tMin SQ Entry Size (%d)\n", rsqes, 1 << rsqes); printf("\n"); } static void show_nvme_id_ctrl_cqes(__u8 cqes) { __u8 mcqes = (cqes & 0xF0) >> 4; __u8 rcqes = cqes & 0xF; printf(" [7:4] : %#x\tMax CQ Entry Size (%d)\n", mcqes, 1 << mcqes); printf(" [3:0] : %#x\tMin CQ Entry Size (%d)\n", rcqes, 1 << rcqes); printf("\n"); } static void show_nvme_id_ctrl_oncs(__le16 ctrl_oncs) { __u16 oncs = le16_to_cpu(ctrl_oncs); __u16 rsvd = (oncs & 0xFF80) >> 7; __u16 tmst = (oncs & 0x40) >> 6; __u16 resv = (oncs & 0x20) >> 5; __u16 save = (oncs & 0x10) >> 4; __u16 wzro = (oncs & 0x8) >> 3; __u16 dsms = (oncs & 0x4) >> 2; __u16 wunc = (oncs & 0x2) >> 1; __u16 cmp = oncs & 0x1; if (rsvd) printf(" [15:6] : %#x\tReserved\n", rsvd); printf(" [6:6] : %#x\tTimestamp %sSupported\n", tmst, tmst ? "" : "Not "); printf(" [5:5] : %#x\tReservations %sSupported\n", resv, resv ? "" : "Not "); printf(" [4:4] : %#x\tSave and Select %sSupported\n", save, save ? "" : "Not "); printf(" [3:3] : %#x\tWrite Zeroes %sSupported\n", wzro, wzro ? "" : "Not "); printf(" [2:2] : %#x\tData Set Management %sSupported\n", dsms, dsms ? "" : "Not "); printf(" [1:1] : %#x\tWrite Uncorrectable %sSupported\n", wunc, wunc ? "" : "Not "); printf(" [0:0] : %#x\tCompare %sSupported\n", cmp, cmp ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_fuses(__le16 ctrl_fuses) { __u16 fuses = le16_to_cpu(ctrl_fuses); __u16 rsvd = (fuses & 0xFE) >> 1; __u16 cmpw = fuses & 0x1; if (rsvd) printf(" [15:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\tFused Compare and Write %sSupported\n", cmpw, cmpw ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_fna(__u8 fna) { __u8 rsvd = (fna & 0xF8) >> 3; __u8 cese = (fna & 0x4) >> 2; __u8 cens = (fna & 0x2) >> 1; __u8 fmns = fna & 0x1; if (rsvd) printf(" [7:3] : %#x\tReserved\n", rsvd); printf(" [2:2] : %#x\tCrypto Erase %sSupported as part of Secure Erase\n", cese, cese ? "" : "Not "); printf(" [1:1] : %#x\tCrypto Erase Applies to %s Namespace(s)\n", cens, cens ? "All" : "Single"); printf(" [0:0] : %#x\tFormat Applies to %s Namespace(s)\n", fmns, fmns ? "All" : "Single"); printf("\n"); } static void show_nvme_id_ctrl_vwc(__u8 vwc) { __u8 rsvd = (vwc & 0xFE) >> 1; __u8 vwcp = vwc & 0x1; if (rsvd) printf(" [7:3] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\tVolatile Write Cache %sPresent\n", vwcp, vwcp ? "" : "Not "); printf("\n"); } static void show_nvme_id_ctrl_nvscc(__u8 nvscc) { __u8 rsvd = (nvscc & 0xFE) >> 1; __u8 fmt = nvscc & 0x1; if (rsvd) printf(" [7:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\tNVM Vendor Specific Commands uses %s Format\n", fmt, fmt ? "NVMe" : "Vendor Specific"); printf("\n"); } static void show_nvme_id_ctrl_sgls(__le32 ctrl_sgls) { __u32 sgls = le32_to_cpu(ctrl_sgls); __u32 rsvd0 = (sgls & 0xFF700000) >> 21; __u32 aofdsl = (sgls & 0x100000) >> 20; __u32 mpcsd = (sgls & 0x80000) >> 19; __u32 sglltb = (sgls & 0x40000) >> 18; __u32 bacmdb = (sgls & 0x20000) >> 17; __u32 bbs = (sgls & 0x10000) >> 16; __u32 rsvd1 = (sgls & 0xFFF8) >> 3; __u32 key = (sgls & 0x4) >> 2; __u32 sglsp = sgls & 0x3; if (rsvd0) printf(" [31:21]: %#x\tReserved\n", rsvd0); if (sglsp || (!sglsp && aofdsl)) printf(" [20:20]: %#x\tAddress Offsets %sSupported\n", aofdsl, aofdsl ? "" : "Not "); if (sglsp || (!sglsp && mpcsd)) printf(" [19:19]: %#x\tMetadata Pointer Containing " "SGL Descriptor is %sSupported\n", mpcsd, mpcsd ? "" : "Not "); if (sglsp || (!sglsp && sglltb)) printf(" [18:18]: %#x\tSGL Length Larger than Buffer %sSupported\n", sglltb, sglltb ? "" : "Not "); if (sglsp || (!sglsp && bacmdb)) printf(" [17:17]: %#x\tByte-Aligned Contig. MD Buffer %sSupported\n", bacmdb, bacmdb ? "" : "Not "); if (sglsp || (!sglsp && bbs)) printf(" [16:16]: %#x\tSGL Bit-Bucket %sSupported\n", bbs, bbs ? "" : "Not "); if (rsvd1) printf(" [15:3] : %#x\tReserved\n", rsvd1); if (sglsp || (!sglsp && key)) printf(" [2:2] : %#x\tKeyed SGL Data Block descriptor %sSupported\n", key, key ? "" : "Not "); if (sglsp == 0x3) printf(" [1:0] : %#x\tReserved\n", sglsp); else if (sglsp == 0x2) printf(" [1:0] : %#x\tScatter-Gather Lists Supported." " Dword alignment required.\n", sglsp); else if (sglsp == 0x1) printf(" [1:0] : %#x\tScatter-Gather Lists Supported." " No Dword alignment required.\n", sglsp); else printf(" [1:0] : %#x\tScatter-Gather Lists Not Supported\n", sglsp); printf("\n"); } static void show_nvme_id_ctrl_ctrattr(__u8 ctrattr) { __u8 rsvd = (ctrattr & 0xFE) >> 1; __u8 scm = ctrattr & 0x1; if (rsvd) printf(" [7:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\t%s Controller Model\n", scm, scm ? "Static" : "Dynamic"); printf("\n"); } static void show_nvme_id_ns_nsfeat(__u8 nsfeat) { __u8 rsvd = (nsfeat & 0xF8) >> 3; __u8 dulbe = (nsfeat & 0x4) >> 2; __u8 na = (nsfeat & 0x2) >> 1; __u8 thin = nsfeat & 0x1; if (rsvd) printf(" [7:3] : %#x\tReserved\n", rsvd); printf(" [2:2] : %#x\tDeallocated or Unwritten Logical Block error %sSupported\n", dulbe, dulbe ? "" : "Not "); printf(" [1:1] : %#x\tNamespace uses %s\n", na, na ? "NAWUN, NAWUPF, and NACWU" : "AWUN, AWUPF, and ACWU"); printf(" [0:0] : %#x\tThin Provisioning %sSupported\n", thin, thin ? "" : "Not "); printf("\n"); } static void show_nvme_id_ns_flbas(__u8 flbas) { __u8 rsvd = (flbas & 0xE0) >> 5; __u8 mdedata = (flbas & 0x10) >> 4; __u8 lbaf = flbas & 0xF; if (rsvd) printf(" [7:5] : %#x\tReserved\n", rsvd); printf(" [4:4] : %#x\tMetadata Transferred %s\n", mdedata, mdedata ? "at End of Data LBA" : "in Separate Contiguous Buffer"); printf(" [3:0] : %#x\tCurrent LBA Format Selected\n", lbaf); printf("\n"); } static void show_nvme_id_ns_mc(__u8 mc) { __u8 rsvd = (mc & 0xFC) >> 2; __u8 mdp = (mc & 0x2) >> 1; __u8 extdlba = mc & 0x1; if (rsvd) printf(" [7:2] : %#x\tReserved\n", rsvd); printf(" [1:1] : %#x\tMetadata Pointer %sSupported\n", mdp, mdp ? "" : "Not "); printf(" [0:0] : %#x\tMetadata as Part of Extended Data LBA %sSupported\n", extdlba, extdlba ? "" : "Not "); printf("\n"); } static void show_nvme_id_ns_dpc(__u8 dpc) { __u8 rsvd = (dpc & 0xE0) >> 5; __u8 pil8 = (dpc & 0x10) >> 4; __u8 pif8 = (dpc & 0x8) >> 3; __u8 pit3 = (dpc & 0x4) >> 2; __u8 pit2 = (dpc & 0x2) >> 1; __u8 pit1 = dpc & 0x1; if (rsvd) printf(" [7:5] : %#x\tReserved\n", rsvd); printf(" [4:4] : %#x\tProtection Information Transferred as Last 8 Bytes of Metadata %sSupported\n", pil8, pil8 ? "" : "Not "); printf(" [3:3] : %#x\tProtection Information Transferred as First 8 Bytes of Metadata %sSupported\n", pif8, pif8 ? "" : "Not "); printf(" [2:2] : %#x\tProtection Information Type 3 %sSupported\n", pit3, pit3 ? "" : "Not "); printf(" [1:1] : %#x\tProtection Information Type 2 %sSupported\n", pit2, pit2 ? "" : "Not "); printf(" [0:0] : %#x\tProtection Information Type 1 %sSupported\n", pit1, pit1 ? "" : "Not "); printf("\n"); } static void show_nvme_id_ns_dps(__u8 dps) { __u8 rsvd = (dps & 0xF0) >> 4; __u8 pif8 = (dps & 0x8) >> 3; __u8 pit = dps & 0x7; if (rsvd) printf(" [7:4] : %#x\tReserved\n", rsvd); printf(" [3:3] : %#x\tProtection Information is Transferred as %s 8 Bytes of Metadata\n", pif8, pif8 ? "First" : "Last"); printf(" [2:0] : %#x\tProtection Information %s\n", pit, pit == 3 ? "Type 3 Enabled" : pit == 2 ? "Type 2 Enabled" : pit == 1 ? "Type 1 Enabled" : pit == 0 ? "Disabled" : "Reserved Enabled"); printf("\n"); } static void show_nvme_id_ns_nmic(__u8 nmic) { __u8 rsvd = (nmic & 0xFE) >> 1; __u8 mp = nmic & 0x1; if (rsvd) printf(" [7:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\tNamespace Multipath %sCapable\n", mp, mp ? "" : "Not "); printf("\n"); } static void show_nvme_id_ns_rescap(__u8 rescap) { __u8 rsvd = (rescap & 0x80) >> 7; __u8 eaar = (rescap & 0x40) >> 6; __u8 wear = (rescap & 0x20) >> 5; __u8 earo = (rescap & 0x10) >> 4; __u8 wero = (rescap & 0x8) >> 3; __u8 ea = (rescap & 0x4) >> 2; __u8 we = (rescap & 0x2) >> 1; __u8 ptpl = rescap & 0x1; if (rsvd) printf(" [7:7] : %#x\tReserved\n", rsvd); printf(" [6:6] : %#x\tExclusive Access - All Registrants %sSupported\n", eaar, eaar ? "" : "Not "); printf(" [5:5] : %#x\tWrite Exclusive - All Registrants %sSupported\n", wear, wear ? "" : "Not "); printf(" [4:4] : %#x\tExclusive Access - Registrants Only %sSupported\n", earo, earo ? "" : "Not "); printf(" [3:3] : %#x\tWrite Exclusive - Registrants Only %sSupported\n", wero, wero ? "" : "Not "); printf(" [2:2] : %#x\tExclusive Access %sSupported\n", ea, ea ? "" : "Not "); printf(" [1:1] : %#x\tWrite Exclusive %sSupported\n", we, we ? "" : "Not "); printf(" [0:0] : %#x\tPersist Through Power Loss %sSupported\n", ptpl, ptpl ? "" : "Not "); printf("\n"); } static void show_nvme_id_ns_fpi(__u8 fpi) { __u8 fpis = (fpi & 0x80) >> 7; __u8 fpii = fpi & 0x7F; printf(" [7:7] : %#x\tFormat Progress Indicator %sSupported\n", fpis, fpis ? "" : "Not "); if (fpis || (!fpis && fpii)) printf(" [6:0] : %#x\tFormat Progress Indicator (Remaining %d%%)\n", fpii, 100 - fpii); printf("\n"); } void show_nvme_id_ns(struct nvme_id_ns *ns, unsigned int mode) { int i; int human = mode & HUMAN, vs = mode & VS; printf("nsze : %#"PRIx64"\n", (uint64_t)le64_to_cpu(ns->nsze)); printf("ncap : %#"PRIx64"\n", (uint64_t)le64_to_cpu(ns->ncap)); printf("nuse : %#"PRIx64"\n", (uint64_t)le64_to_cpu(ns->nuse)); printf("nsfeat : %#x\n", ns->nsfeat); if (human) show_nvme_id_ns_nsfeat(ns->nsfeat); printf("nlbaf : %d\n", ns->nlbaf); printf("flbas : %#x\n", ns->flbas); if (human) show_nvme_id_ns_flbas(ns->flbas); printf("mc : %#x\n", ns->mc); if (human) show_nvme_id_ns_mc(ns->mc); printf("dpc : %#x\n", ns->dpc); if (human) show_nvme_id_ns_dpc(ns->dpc); printf("dps : %#x\n", ns->dps); if (human) show_nvme_id_ns_dps(ns->dps); printf("nmic : %#x\n", ns->nmic); if (human) show_nvme_id_ns_nmic(ns->nmic); printf("rescap : %#x\n", ns->rescap); if (human) show_nvme_id_ns_rescap(ns->rescap); printf("fpi : %#x\n", ns->fpi); if (human) show_nvme_id_ns_fpi(ns->fpi); printf("nawun : %d\n", le16_to_cpu(ns->nawun)); printf("nawupf : %d\n", le16_to_cpu(ns->nawupf)); printf("nacwu : %d\n", le16_to_cpu(ns->nacwu)); printf("nabsn : %d\n", le16_to_cpu(ns->nabsn)); printf("nabo : %d\n", le16_to_cpu(ns->nabo)); printf("nabspf : %d\n", le16_to_cpu(ns->nabspf)); printf("noiob : %d\n", le16_to_cpu(ns->noiob)); printf("nvmcap : %.0Lf\n", int128_to_double(ns->nvmcap)); printf("nguid : "); for (i = 0; i < 16; i++) printf("%02x", ns->nguid[i]); printf("\n"); printf("eui64 : "); for (i = 0; i < 8; i++) printf("%02x", ns->eui64[i]); printf("\n"); for (i = 0; i <= ns->nlbaf; i++) { if (human) printf("LBA Format %2d : Metadata Size: %-3d bytes - " "Data Size: %-2d bytes - Relative Performance: %#x %s %s\n", i, le16_to_cpu(ns->lbaf[i].ms), 1 << ns->lbaf[i].ds, ns->lbaf[i].rp, ns->lbaf[i].rp == 3 ? "Degraded" : ns->lbaf[i].rp == 2 ? "Good" : ns->lbaf[i].rp == 1 ? "Better" : "Best", i == (ns->flbas & 0xf) ? "(in use)" : ""); else printf("lbaf %2d : ms:%-3d lbads:%-2d rp:%#x %s\n", i, le16_to_cpu(ns->lbaf[i].ms), ns->lbaf[i].ds, ns->lbaf[i].rp, i == (ns->flbas & 0xf) ? "(in use)" : ""); } if (vs) { printf("vs[]:\n"); d(ns->vs, sizeof(ns->vs), 16, 1); } } void json_nvme_id_ns_descs(void *data) { #ifdef LIBUUID uuid_t uuid; char uuid_str[37]; #endif __u8 eui64_desc[8]; __u8 nguid_desc[16]; char nguid_str[2 * sizeof(nguid_desc) + 1]; char eui64_str[2 * sizeof(eui64_desc) + 1]; char *eui64 = eui64_str; char *nguid = nguid_str; struct json_object *root; off_t off; int pos, len = 0; int i; root = json_create_object(); for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) { struct nvme_ns_id_desc *cur = data + pos; off = pos + sizeof(*cur); if (cur->nidl == 0) break; switch (cur->nidt) { case NVME_NIDT_EUI64: memset(eui64, 0, sizeof(eui64_str)); memcpy(eui64_desc, data + off, sizeof(eui64_desc)); for (i = 0; i < sizeof(eui64); i++) eui64 += sprintf(eui64, "%02x", eui64_desc[i]); len += sizeof(eui64); json_object_add_value_string(root, "eui64", eui64_str); break; case NVME_NIDT_NGUID: memset(nguid, 0, sizeof(nguid_str)); memcpy(nguid_desc, data + off, sizeof(nguid_desc)); for (i = 0; i < sizeof(nguid); i++) nguid += sprintf(nguid, "%02x", nguid_desc[i]); len += sizeof(nguid); json_object_add_value_string(root, "nguid", nguid_str); break; #ifdef LIBUUID case NVME_NIDT_UUID: memcpy(uuid, data + off, 16); uuid_unparse_lower(uuid, uuid_str); len += sizeof(uuid); json_object_add_value_string(root, "uuid", uuid_str); break; #endif default: /* Skip unnkown types */ len = cur->nidl; break; } len += sizeof(*cur); } json_print_object(root, NULL); printf("\n"); json_free_object(root); } void show_nvme_id_ns_descs(void *data) { int pos, len = 0; int i; #ifdef LIBUUID uuid_t uuid; char uuid_str[37]; #endif __u8 eui64[8]; __u8 nguid[16]; for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) { struct nvme_ns_id_desc *cur = data + pos; if (cur->nidl == 0) break; switch (cur->nidt) { case NVME_NIDT_EUI64: memcpy(eui64, data + pos + sizeof(*cur), sizeof(eui64)); printf("eui64 : "); for (i = 0; i < 8; i++) printf("%02x", eui64[i]); printf("\n"); len += sizeof(eui64); break; case NVME_NIDT_NGUID: memcpy(nguid, data + pos + sizeof(*cur), sizeof(nguid)); printf("nguid : "); for (i = 0; i < 16; i++) printf("%02x", nguid[i]); printf("\n"); len += sizeof(nguid); break; #ifdef LIBUUID case NVME_NIDT_UUID: memcpy(uuid, data + pos + sizeof(*cur), 16); uuid_unparse_lower(uuid, uuid_str); printf("uuid : %s\n", uuid_str); len += sizeof(uuid); break; #endif default: /* Skip unnkown types */ len = cur->nidl; break; } len += sizeof(*cur); } } static void print_ps_power_and_scale(__le16 ctr_power, __u8 scale) { __u16 power = le16_to_cpu(ctr_power); switch (scale & 0x3) { case 0: /* Not reported for this power state */ printf("-"); break; case 1: /* Units of 0.0001W */ printf("%01u.%04uW", power / 10000, power % 10000); break; case 2: /* Units of 0.01W */ printf("%01u.%02uW", power / 100, scale % 100); break; default: printf("reserved"); } } static void show_nvme_id_ctrl_power(struct nvme_id_ctrl *ctrl) { int i; for (i = 0; i <= ctrl->npss; i++) { __u16 max_power = le16_to_cpu(ctrl->psd[i].max_power); printf("ps %4d : mp:", i); if (ctrl->psd[i].flags & NVME_PS_FLAGS_MAX_POWER_SCALE) printf("%01u.%04uW ", max_power / 10000, max_power % 10000); else printf("%01u.%02uW ", max_power / 100, max_power % 100); if (ctrl->psd[i].flags & NVME_PS_FLAGS_NON_OP_STATE) printf("non-"); printf("operational enlat:%d exlat:%d rrt:%d rrl:%d\n" " rwt:%d rwl:%d idle_power:", le32_to_cpu(ctrl->psd[i].entry_lat), le32_to_cpu(ctrl->psd[i].exit_lat), ctrl->psd[i].read_tput, ctrl->psd[i].read_lat, ctrl->psd[i].write_tput, ctrl->psd[i].write_lat); print_ps_power_and_scale(ctrl->psd[i].idle_power, POWER_SCALE(ctrl->psd[i].idle_scale)); printf(" active_power:"); print_ps_power_and_scale(ctrl->psd[i].active_power, POWER_SCALE(ctrl->psd[i].active_work_scale)); printf("\n"); } } void __show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root)) { int human = mode & HUMAN, vs = mode & VS; printf("vid : %#x\n", le16_to_cpu(ctrl->vid)); printf("ssvid : %#x\n", le16_to_cpu(ctrl->ssvid)); printf("sn : %-.*s\n", (int)sizeof(ctrl->sn), ctrl->sn); printf("mn : %-.*s\n", (int)sizeof(ctrl->mn), ctrl->mn); printf("fr : %-.*s\n", (int)sizeof(ctrl->fr), ctrl->fr); printf("rab : %d\n", ctrl->rab); printf("ieee : %02x%02x%02x\n", ctrl->ieee[2], ctrl->ieee[1], ctrl->ieee[0]); printf("cmic : %#x\n", ctrl->cmic); if (human) show_nvme_id_ctrl_cmic(ctrl->cmic); printf("mdts : %d\n", ctrl->mdts); printf("cntlid : %x\n", le16_to_cpu(ctrl->cntlid)); printf("ver : %x\n", le32_to_cpu(ctrl->ver)); printf("rtd3r : %x\n", le32_to_cpu(ctrl->rtd3r)); printf("rtd3e : %x\n", le32_to_cpu(ctrl->rtd3e)); printf("oaes : %#x\n", le32_to_cpu(ctrl->oaes)); if (human) show_nvme_id_ctrl_oaes(ctrl->oaes); printf("ctratt : %#x\n", le32_to_cpu(ctrl->ctratt)); if (human) show_nvme_id_ctrl_ctratt(ctrl->ctratt); printf("oacs : %#x\n", le16_to_cpu(ctrl->oacs)); if (human) show_nvme_id_ctrl_oacs(ctrl->oacs); printf("acl : %d\n", ctrl->acl); printf("aerl : %d\n", ctrl->aerl); printf("frmw : %#x\n", ctrl->frmw); if (human) show_nvme_id_ctrl_frmw(ctrl->frmw); printf("lpa : %#x\n", ctrl->lpa); if (human) show_nvme_id_ctrl_lpa(ctrl->lpa); printf("elpe : %d\n", ctrl->elpe); printf("npss : %d\n", ctrl->npss); printf("avscc : %#x\n", ctrl->avscc); if (human) show_nvme_id_ctrl_avscc(ctrl->avscc); printf("apsta : %#x\n", ctrl->apsta); if (human) show_nvme_id_ctrl_apsta(ctrl->apsta); printf("wctemp : %d\n", le16_to_cpu(ctrl->wctemp)); printf("cctemp : %d\n", le16_to_cpu(ctrl->cctemp)); printf("mtfa : %d\n", le16_to_cpu(ctrl->mtfa)); printf("hmpre : %d\n", le32_to_cpu(ctrl->hmpre)); printf("hmmin : %d\n", le32_to_cpu(ctrl->hmmin)); printf("tnvmcap : %.0Lf\n", int128_to_double(ctrl->tnvmcap)); printf("unvmcap : %.0Lf\n", int128_to_double(ctrl->unvmcap)); printf("rpmbs : %#x\n", le32_to_cpu(ctrl->rpmbs)); if (human) show_nvme_id_ctrl_rpmbs(ctrl->rpmbs); printf("edstt : %d\n", le16_to_cpu(ctrl->edstt)); printf("dsto : %d\n", ctrl->dsto); printf("fwug : %d\n", ctrl->fwug); printf("kas : %d\n", le16_to_cpu(ctrl->kas)); printf("hctma : %#x\n", le16_to_cpu(ctrl->hctma)); if (human) show_nvme_id_ctrl_hctma(ctrl->hctma); printf("mntmt : %d\n", le16_to_cpu(ctrl->mntmt)); printf("mxtmt : %d\n", le16_to_cpu(ctrl->mxtmt)); printf("sanicap : %#x\n", le32_to_cpu(ctrl->sanicap)); if (human) show_nvme_id_ctrl_sanicap(ctrl->sanicap); printf("hmminds : %d\n", le32_to_cpu(ctrl->hmminds)); printf("hmmaxd : %d\n", le16_to_cpu(ctrl->hmmaxd)); printf("sqes : %#x\n", ctrl->sqes); if (human) show_nvme_id_ctrl_sqes(ctrl->sqes); printf("cqes : %#x\n", ctrl->cqes); if (human) show_nvme_id_ctrl_cqes(ctrl->cqes); printf("maxcmd : %d\n", le16_to_cpu(ctrl->maxcmd)); printf("nn : %d\n", le32_to_cpu(ctrl->nn)); printf("oncs : %#x\n", le16_to_cpu(ctrl->oncs)); if (human) show_nvme_id_ctrl_oncs(ctrl->oncs); printf("fuses : %#x\n", le16_to_cpu(ctrl->fuses)); if (human) show_nvme_id_ctrl_fuses(ctrl->fuses); printf("fna : %#x\n", ctrl->fna); if (human) show_nvme_id_ctrl_fna(ctrl->fna); printf("vwc : %#x\n", ctrl->vwc); if (human) show_nvme_id_ctrl_vwc(ctrl->vwc); printf("awun : %d\n", le16_to_cpu(ctrl->awun)); printf("awupf : %d\n", le16_to_cpu(ctrl->awupf)); printf("nvscc : %d\n", ctrl->nvscc); if (human) show_nvme_id_ctrl_nvscc(ctrl->nvscc); printf("acwu : %d\n", le16_to_cpu(ctrl->acwu)); printf("sgls : %x\n", le32_to_cpu(ctrl->sgls)); if (human) show_nvme_id_ctrl_sgls(ctrl->sgls); printf("subnqn : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn); printf("ioccsz : %d\n", le32_to_cpu(ctrl->ioccsz)); printf("iorcsz : %d\n", le32_to_cpu(ctrl->iorcsz)); printf("icdoff : %d\n", le16_to_cpu(ctrl->icdoff)); printf("ctrattr : %x\n", ctrl->ctrattr); if (human) show_nvme_id_ctrl_ctrattr(ctrl->ctrattr); printf("msdbd : %d\n", ctrl->msdbd); show_nvme_id_ctrl_power(ctrl); if (vendor_show) vendor_show(ctrl->vs, NULL); else if (vs) { printf("vs[]:\n"); d(ctrl->vs, sizeof(ctrl->vs), 16, 1); } } void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode) { __show_nvme_id_ctrl(ctrl, mode, NULL); } void show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname) { int i; printf("Error Log Entries for device:%s entries:%d\n", devname, entries); printf(".................\n"); for (i = 0; i < entries; i++) { printf(" Entry[%2d] \n", i); printf(".................\n"); printf("error_count : %"PRIu64"\n", (uint64_t)le64_to_cpu(err_log[i].error_count)); printf("sqid : %d\n", err_log[i].sqid); printf("cmdid : %#x\n", err_log[i].cmdid); printf("status_field : %#x(%s)\n", err_log[i].status_field, nvme_status_to_string(err_log[i].status_field >> 1)); printf("parm_err_loc : %#x\n", err_log[i].parm_error_location); printf("lba : %#"PRIx64"\n",(uint64_t)le64_to_cpu(err_log[i].lba)); printf("nsid : %#x\n", err_log[i].nsid); printf("vs : %d\n", err_log[i].vs); printf(".................\n"); } } void show_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11) { int i, j, regctl, entries; regctl = status->regctl[0] | (status->regctl[1] << 8); printf("\nNVME Reservation status:\n\n"); printf("gen : %d\n", le32_to_cpu(status->gen)); printf("rtype : %d\n", status->rtype); printf("regctl : %d\n", regctl); printf("ptpls : %d\n", status->ptpls); /* check Extended Data Structure bit */ if ((cdw11 & 0x1) == 0) { /* if status buffer was too small, don't loop past the end of the buffer */ entries = (bytes - 24) / 24; if (entries < regctl) regctl = entries; for (i = 0; i < regctl; i++) { printf("regctl[%d] :\n", i); printf(" cntlid : %x\n", le16_to_cpu(status->regctl_ds[i].cntlid)); printf(" rcsts : %x\n", status->regctl_ds[i].rcsts); printf(" hostid : %"PRIx64"\n", (uint64_t)le64_to_cpu(status->regctl_ds[i].hostid)); printf(" rkey : %"PRIx64"\n", (uint64_t)le64_to_cpu(status->regctl_ds[i].rkey)); } } else { struct nvme_reservation_status_ext *ext_status = (struct nvme_reservation_status_ext *)status; /* if status buffer was too small, don't loop past the end of the buffer */ entries = (bytes - 64) / 64; if (entries < regctl) regctl = entries; for (i = 0; i < regctl; i++) { printf("regctlext[%d] :\n", i); printf(" cntlid : %x\n", le16_to_cpu(ext_status->regctl_eds[i].cntlid)); printf(" rcsts : %x\n", ext_status->regctl_eds[i].rcsts); printf(" rkey : %"PRIx64"\n", (uint64_t)le64_to_cpu(ext_status->regctl_eds[i].rkey)); printf(" hostid : "); for (j = 0; j < 16; j++) printf("%x", ext_status->regctl_eds[i].hostid[j]); printf("\n"); } } printf("\n"); } static char *fw_to_string(__u64 fw) { static char ret[9]; char *c = (char *)&fw; int i; for (i = 0; i < 8; i++) ret[i] = c[i] >= '!' && c[i] <= '~' ? c[i] : '.'; ret[i] = '\0'; return ret; } void show_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname) { int i; printf("Firmware Log for device:%s\n", devname); printf("afi : %#x\n", fw_log->afi); for (i = 0; i < 7; i++) if (fw_log->frs[i]) printf("frs%d : %#016"PRIx64" (%s)\n", i + 1, (uint64_t)fw_log->frs[i], fw_to_string(fw_log->frs[i])); } void show_effects_log(struct nvme_effects_log_page *effects) { int i; __u32 effect; for (i = 0; i < 256; i++) { effect = le32_to_cpu(effects->acs[i]); if (effect & 1) printf("ACS%-4d: %08x\n", i, effects->acs[i]); } for (i = 0; i < 256; i++) { effect = le32_to_cpu(effects->acs[i]); if (effect & 1) printf("IOCS%-3d: %08x\n", i, effects->iocs[i]); } } uint64_t int48_to_long(__u8 *data) { int i; uint64_t result = 0; for (i = 0; i < 6; i++) { result *= 256; result += data[5 - i]; } return result; } void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname) { /* convert temperature from Kelvin to Celsius */ int temperature = ((smart->temperature[1] << 8) | smart->temperature[0]) - 273; int i; printf("Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); printf("critical_warning : %#x\n", smart->critical_warning); printf("temperature : %d C\n", temperature); printf("available_spare : %u%%\n", smart->avail_spare); printf("available_spare_threshold : %u%%\n", smart->spare_thresh); printf("percentage_used : %u%%\n", smart->percent_used); printf("data_units_read : %'.0Lf\n", int128_to_double(smart->data_units_read)); printf("data_units_written : %'.0Lf\n", int128_to_double(smart->data_units_written)); printf("host_read_commands : %'.0Lf\n", int128_to_double(smart->host_reads)); printf("host_write_commands : %'.0Lf\n", int128_to_double(smart->host_writes)); printf("controller_busy_time : %'.0Lf\n", int128_to_double(smart->ctrl_busy_time)); printf("power_cycles : %'.0Lf\n", int128_to_double(smart->power_cycles)); printf("power_on_hours : %'.0Lf\n", int128_to_double(smart->power_on_hours)); printf("unsafe_shutdowns : %'.0Lf\n", int128_to_double(smart->unsafe_shutdowns)); printf("media_errors : %'.0Lf\n", int128_to_double(smart->media_errors)); printf("num_err_log_entries : %'.0Lf\n", int128_to_double(smart->num_err_log_entries)); printf("Warning Temperature Time : %u\n", le32_to_cpu(smart->warning_temp_time)); printf("Critical Composite Temperature Time : %u\n", le32_to_cpu(smart->critical_comp_time)); for (i = 0; i < 8; i++) { __s32 temp = le16_to_cpu(smart->temp_sensor[i]); if (temp == 0) continue; printf("Temperature Sensor %d : %d C\n", i + 1, temp - 273); } printf("Thermal Management T1 Trans Count : %u\n", le32_to_cpu(smart->thm_temp1_trans_count)); printf("Thermal Management T2 Trans Count : %u\n", le32_to_cpu(smart->thm_temp2_trans_count)); printf("Thermal Management T1 Total Time : %u\n", le32_to_cpu(smart->thm_temp1_total_time)); printf("Thermal Management T2 Total Time : %u\n", le32_to_cpu(smart->thm_temp2_total_time)); } char *nvme_feature_to_string(int feature) { switch (feature) { case NVME_FEAT_ARBITRATION: return "Arbitration"; case NVME_FEAT_POWER_MGMT: return "Power Management"; case NVME_FEAT_LBA_RANGE: return "LBA Range Type"; case NVME_FEAT_TEMP_THRESH: return "Temperature Threshold"; case NVME_FEAT_ERR_RECOVERY: return "Error Recovery"; case NVME_FEAT_VOLATILE_WC: return "Volatile Write Cache"; case NVME_FEAT_NUM_QUEUES: return "Number of Queues"; case NVME_FEAT_IRQ_COALESCE: return "Interrupt Coalescing"; case NVME_FEAT_IRQ_CONFIG: return "Interrupt Vector Configuration"; case NVME_FEAT_WRITE_ATOMIC: return "Write Atomicity Normal"; case NVME_FEAT_ASYNC_EVENT: return "Async Event Configuration"; case NVME_FEAT_AUTO_PST: return "Autonomous Power State Transition"; case NVME_FEAT_HOST_MEM_BUF: return "Host Memory Buffer"; case NVME_FEAT_KATO: return "Keep Alive Timer"; case NVME_FEAT_SW_PROGRESS: return "Software Progress"; case NVME_FEAT_HOST_ID: return "Host Identifier"; case NVME_FEAT_RESV_MASK: return "Reservation Notification Mask"; case NVME_FEAT_RESV_PERSIST: return "Reservation Persistence"; default: return "Unknown"; } } char *nvme_register_to_string(int reg) { switch (reg) { case NVME_REG_CAP: return "Controller Capabilities"; case NVME_REG_VS: return "Version"; case NVME_REG_INTMS: return "Interrupt Vector Mask Set"; case NVME_REG_INTMC: return "Interrupt Vector Mask Clear"; case NVME_REG_CC: return "Controller Configuration"; case NVME_REG_CSTS: return "Controller Status"; case NVME_REG_NSSR: return "NVM Subsystem Reset"; case NVME_REG_AQA: return "Admin Queue Attributes"; case NVME_REG_ASQ: return "Admin Submission Queue Base Address"; case NVME_REG_ACQ: return "Admin Completion Queue Base Address"; case NVME_REG_CMBLOC: return "Controller Memory Buffer Location"; case NVME_REG_CMBSZ: return "Controller Memory Buffer Size"; default: return "Unknown"; } } char* nvme_select_to_string(int sel) { switch (sel) { case 0: return "Current"; case 1: return "Default"; case 2: return "Saved"; case 3: return "Supported capabilities"; default: return "Reserved"; } } char *nvme_status_to_string(__u32 status) { switch (status & 0x3ff) { case NVME_SC_SUCCESS: return "SUCCESS"; case NVME_SC_INVALID_OPCODE: return "INVALID_OPCODE"; case NVME_SC_INVALID_FIELD: return "INVALID_FIELD"; case NVME_SC_CMDID_CONFLICT: return "CMDID_CONFLICT"; case NVME_SC_DATA_XFER_ERROR: return "DATA_XFER_ERROR"; case NVME_SC_POWER_LOSS: return "POWER_LOSS"; case NVME_SC_INTERNAL: return "INTERNAL"; case NVME_SC_ABORT_REQ: return "ABORT_REQ"; case NVME_SC_ABORT_QUEUE: return "ABORT_QUEUE"; case NVME_SC_FUSED_FAIL: return "FUSED_FAIL"; case NVME_SC_FUSED_MISSING: return "FUSED_MISSING"; case NVME_SC_INVALID_NS: return "INVALID_NS"; case NVME_SC_CMD_SEQ_ERROR: return "CMD_SEQ_ERROR"; case NVME_SC_SANITIZE_FAILED: return "SANITIZE_FAILED"; case NVME_SC_SANITIZE_IN_PROGRESS: return "SANITIZE_IN_PROGRESS"; case NVME_SC_LBA_RANGE: return "LBA_RANGE"; case NVME_SC_CAP_EXCEEDED: return "CAP_EXCEEDED"; case NVME_SC_NS_NOT_READY: return "NS_NOT_READY"; case NVME_SC_RESERVATION_CONFLICT: return "RESERVATION_CONFLICT"; case NVME_SC_CQ_INVALID: return "CQ_INVALID"; case NVME_SC_QID_INVALID: return "QID_INVALID"; case NVME_SC_QUEUE_SIZE: return "QUEUE_SIZE"; case NVME_SC_ABORT_LIMIT: return "ABORT_LIMIT"; case NVME_SC_ABORT_MISSING: return "ABORT_MISSING"; case NVME_SC_ASYNC_LIMIT: return "ASYNC_LIMIT"; case NVME_SC_FIRMWARE_SLOT: return "FIRMWARE_SLOT"; case NVME_SC_FIRMWARE_IMAGE: return "FIRMWARE_IMAGE"; case NVME_SC_INVALID_VECTOR: return "INVALID_VECTOR"; case NVME_SC_INVALID_LOG_PAGE: return "INVALID_LOG_PAGE"; case NVME_SC_INVALID_FORMAT: return "INVALID_FORMAT"; case NVME_SC_FW_NEEDS_CONV_RESET: return "FW_NEEDS_CONVENTIONAL_RESET"; case NVME_SC_INVALID_QUEUE: return "INVALID_QUEUE"; case NVME_SC_FEATURE_NOT_SAVEABLE: return "FEATURE_NOT_SAVEABLE"; case NVME_SC_FEATURE_NOT_CHANGEABLE: return "FEATURE_NOT_CHANGEABLE"; case NVME_SC_FEATURE_NOT_PER_NS: return "FEATURE_NOT_PER_NS"; case NVME_SC_FW_NEEDS_SUBSYS_RESET: return "FW_NEEDS_SUBSYSTEM_RESET"; case NVME_SC_FW_NEEDS_RESET: return "FW_NEEDS_RESET"; case NVME_SC_FW_NEEDS_MAX_TIME: return "FW_NEEDS_MAX_TIME_VIOLATION"; case NVME_SC_FW_ACIVATE_PROHIBITED: return "FW_ACTIVATION_PROHIBITED"; case NVME_SC_OVERLAPPING_RANGE: return "OVERLAPPING_RANGE"; case NVME_SC_NS_INSUFFICENT_CAP: return "NS_INSUFFICIENT_CAPACITY"; case NVME_SC_NS_ID_UNAVAILABLE: return "NS_ID_UNAVAILABLE"; case NVME_SC_NS_ALREADY_ATTACHED: return "NS_ALREADY_ATTACHED"; case NVME_SC_NS_IS_PRIVATE: return "NS_IS_PRIVATE"; case NVME_SC_NS_NOT_ATTACHED: return "NS_NOT_ATTACHED"; case NVME_SC_THIN_PROV_NOT_SUPP: return "THIN_PROVISIONING_NOT_SUPPORTED"; case NVME_SC_CTRL_LIST_INVALID: return "CONTROLLER_LIST_INVALID"; case NVME_SC_BP_WRITE_PROHIBITED: return "BOOT PARTITION WRITE PROHIBITED"; case NVME_SC_BAD_ATTRIBUTES: return "BAD_ATTRIBUTES"; case NVME_SC_WRITE_FAULT: return "WRITE_FAULT"; case NVME_SC_READ_ERROR: return "READ_ERROR"; case NVME_SC_GUARD_CHECK: return "GUARD_CHECK"; case NVME_SC_APPTAG_CHECK: return "APPTAG_CHECK"; case NVME_SC_REFTAG_CHECK: return "REFTAG_CHECK"; case NVME_SC_COMPARE_FAILED: return "COMPARE_FAILED"; case NVME_SC_ACCESS_DENIED: return "ACCESS_DENIED"; case NVME_SC_UNWRITTEN_BLOCK: return "UNWRITTEN_BLOCK"; default: return "Unknown"; } } static char* nvme_feature_lba_type_to_string(__u8 type) { switch (type) { case 0: return "Reserved"; case 1: return "Filesystem"; case 2: return "RAID"; case 3: return "Cache"; case 4: return "Page / Swap file"; default: if (type>=0x05 && type<=0x7f) return "Reserved"; else return "Vendor Specific"; } } void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges) { int i, j; for (i = 0; i <= nr_ranges; i++) { printf("\ttype : %#x - %s\n", lbrt[i].type, nvme_feature_lba_type_to_string(lbrt[i].type)); printf("\tattributes : %#x - %s, %s\n", lbrt[i].attributes, (lbrt[i].attributes & 0x0001) ? "LBA range may be overwritten":"LBA range should not be overwritten", ((lbrt[i].attributes & 0x0002) >> 1) ? "LBA range should be hidden from the OS/EFI/BIOS":"LBA range should be visible from the OS/EFI/BIOS"); printf("\tslba : %#"PRIx64"\n", (uint64_t)(lbrt[i].slba)); printf("\tnlb : %#"PRIx64"\n", (uint64_t)(lbrt[i].nlb)); printf("\tguid : "); for (j = 0; j < 16; j++) printf("%02x", lbrt[i].guid[j]); printf("\n"); } } static char *nvme_feature_wl_hints_to_string(__u8 wh) { switch (wh) { case 0: return "No Workload"; case 1: return "Extended Idle Period with a Burst of Random Writes"; case 2: return "Heavy Sequential Writes"; default:return "Reserved"; } } static char *nvme_feature_temp_type_to_string(__u8 type) { switch (type) { case 0: return "Over Temperature Threshold"; case 1: return "Under Temperature Threshold"; default:return "Reserved"; } } static char *nvme_feature_temp_sel_to_string(__u8 sel) { switch (sel) { case 0: return "Composite Temperature"; case 1: return "Temperature Sensor 1"; case 2: return "Temperature Sensor 2"; case 3: return "Temperature Sensor 3"; case 4: return "Temperature Sensor 4"; case 5: return "Temperature Sensor 5"; case 6: return "Temperature Sensor 6"; case 7: return "Temperature Sensor 7"; case 8: return "Temperature Sensor 8"; default:return "Reserved"; } } static void show_auto_pst(struct nvme_auto_pst *apst) { int i; printf( "\tAuto PST Entries"); printf("\t.................\n"); for (i = 0; i < 32; i++) { printf("\tEntry[%2d] \n", i); printf("\t.................\n"); printf("\tIdle Time Prior to Transition (ITPT): %u ms\n", (apst[i].data & 0xffffff00) >> 8); printf("\tIdle Transition Power State (ITPS): %u\n", (apst[i].data & 0x000000f8) >> 3); printf("\t.................\n"); } } static void show_host_mem_buffer(struct nvme_host_mem_buffer *hmb) { printf("\tHost Memory Descriptor List Entry Count (HMDLEC): %u\n", hmb->hmdlec); printf("\tHost Memory Descriptor List Address (HMDLAU): 0x%x\n", hmb->hmdlau); printf("\tHost Memory Descriptor List Address (HMDLAL): 0x%x\n", hmb->hmdlal); printf("\tHost Memory Buffer Size (HSIZE): %u\n", hmb->hsize); } void nvme_directive_show_fields(__u8 dtype, __u8 doper, unsigned int result, unsigned char *buf) { __u8 *field = buf; int count, i; switch (dtype) { case NVME_DIR_IDENTIFY: switch (doper) { case NVME_DIR_RCV_ID_OP_PARAM: printf("\tDirective support \n"); printf("\t\tIdentify Directive : %s\n", (*field & 0x1) ? "supported":"not supported"); printf("\t\tStream Directive : %s\n", (*field & 0x2) ? "supported":"not supported"); printf("\tDirective status \n"); printf("\t\tIdentify Directive : %s\n", (*(field + 32) & 0x1) ? "enabled" : "disabled"); printf("\t\tStream Directive : %s\n", (*(field + 32) & 0x2) ? "enabled" : "disabled"); break; default: fprintf(stderr, "invalid directive operations for Identify Directives\n"); } break; case NVME_DIR_STREAMS: switch (doper) { case NVME_DIR_RCV_ST_OP_PARAM: printf("\tMax Streams Limit (MSL): %u\n", *(__u16 *) field); printf("\tNVM Subsystem Streams Available (NSSA): %u\n", *(__u16 *) (field + 2)); printf("\tNVM Subsystem Streams Open (NSSO): %u\n", *(__u16 *) (field + 4)); printf("\tStream Write Size (in unit of LB size) (SWS): %u\n", *(__u32 *) (field + 16)); printf("\tStream Granularity Size (in unit of SWS) (SGS): %u\n", *(__u16 *) (field + 20)); printf("\tNamespece Streams Allocated (NSA): %u\n", *(__u16 *) (field + 22)); printf("\tNamespace Streams Open (NSO): %u\n", *(__u16 *) (field + 24)); break; case NVME_DIR_RCV_ST_OP_STATUS: count = *(__u16 *) field; printf("\tOpen Stream Count : %u\n", *(__u16 *) field); for ( i = 0; i < count; i++ ) { printf("\tStream Identifier %.6u : %u\n", i + 1, *(__u16 *) (field + ((i + 1) * 2))); } break; case NVME_DIR_RCV_ST_OP_RESOURCE: printf("\tNamespace Streams Allocated (NSA): %u\n", result & 0xffff); break; default: fprintf(stderr, "invalid directive operations for Streams Directives\n"); } break; default: fprintf(stderr, "invalid directive type\n"); break; } return; } void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf) { __u8 field; uint64_t ull; switch (fid) { case NVME_FEAT_ARBITRATION: printf("\tHigh Priority Weight (HPW): %u\n", ((result & 0xff000000) >> 24) + 1); printf("\tMedium Priority Weight (MPW): %u\n", ((result & 0x00ff0000) >> 16) + 1); printf("\tLow Priority Weight (LPW): %u\n", ((result & 0x0000ff00) >> 8) + 1); printf("\tArbitration Burst (AB): "); if ((result & 0x00000007) == 7) printf("No limit\n"); else printf("%u\n", 1 << (result & 0x00000007)); break; case NVME_FEAT_POWER_MGMT: field = (result & 0x000000E0) >> 5; printf("\tWorkload Hint (WH): %u - %s\n", field, nvme_feature_wl_hints_to_string(field)); printf("\tPower State (PS): %u\n", result & 0x0000001f); break; case NVME_FEAT_LBA_RANGE: field = result & 0x0000003f; printf("\tNumber of LBA Ranges (NUM): %u\n", field + 1); show_lba_range((struct nvme_lba_range_type *)buf, field); break; case NVME_FEAT_TEMP_THRESH: field = (result & 0x00300000) >> 20; printf("\tThreshold Type Select (THSEL): %u - %s\n", field, nvme_feature_temp_type_to_string(field)); field = (result & 0x000f0000) >> 16; printf("\tThreshold Temperature Select (TMPSEL): %u - %s\n", field, nvme_feature_temp_sel_to_string(field)); printf("\tTemperature Threshold (TMPTH): %d C\n", (result & 0x0000ffff) - 273); break; case NVME_FEAT_ERR_RECOVERY: printf("\tDeallocated or Unwritten Logical Block Error Enable (DULBE): %s\n", ((result & 0x00010000) >> 16) ? "Enabled":"Disabled"); printf("\tTime Limited Error Recovery (TLER): %u ms\n", (result & 0x0000ffff) * 100); break; case NVME_FEAT_VOLATILE_WC: printf("\tVolatile Write Cache Enable (WCE): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); break; case NVME_FEAT_NUM_QUEUES: printf("\tNumber of IO Completion Queues Allocated (NCQA): %u\n", ((result & 0xffff0000) >> 16) + 1); printf("\tNumber of IO Submission Queues Allocated (NSQA): %u\n", (result & 0x0000ffff) + 1); break; case NVME_FEAT_IRQ_COALESCE: printf("\tAggregation Time (TIME): %u ms\n", ((result & 0x0000ff00) >> 8) * 100); printf("\tAggregation Threshold (THR): %u\n", (result & 0x000000ff) + 1); break; case NVME_FEAT_IRQ_CONFIG: printf("\tCoalescing Disable (CD): %s\n", ((result & 0x00010000) >> 16) ? "True":"False"); printf("\tInterrupt Vector (IV): %u\n", result & 0x0000ffff); break; case NVME_FEAT_WRITE_ATOMIC: printf("\tDisable Normal (DN): %s\n", (result & 0x00000001) ? "True":"False"); break; case NVME_FEAT_ASYNC_EVENT: printf("\tFirmware Activation Notices : %s\n", ((result & 0x00000200) >> 9) ? "Send async event":"Do not send async event"); printf("\tNamespace Attribute Notices : %s\n", ((result & 0x00000100) >> 8) ? "Send NameSpace Attribute Changed event":"Do not send NameSpace Attribute Changed event"); printf("\tSMART / Health Critical Warnings: %s\n", (result & 0x000000ff) ? "Send async event":"Do not send async event"); break; case NVME_FEAT_AUTO_PST: printf("\tAutonomous Power State Transition Enable (APSTE): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); show_auto_pst((struct nvme_auto_pst *)buf); break; case NVME_FEAT_HOST_MEM_BUF: printf("\tMemory Return (MR): %s\n", ((result & 0x00000002) >> 1) ? "True":"False"); printf("\tEnable Host Memory (EHM): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); show_host_mem_buffer((struct nvme_host_mem_buffer *)buf); break; case NVME_FEAT_SW_PROGRESS: printf("\tPre-boot Software Load Count (PBSLC): %u\n", result & 0x000000ff); break; case NVME_FEAT_HOST_ID: ull = buf[7]; ull <<= 8; ull |= buf[6]; ull <<= 8; ull |= buf[5]; ull <<= 8; ull |= buf[4]; ull <<= 8; ull |= buf[3]; ull <<= 8; ull |= buf[2]; ull <<= 8; ull |= buf[1]; ull <<= 8; ull |= buf[0]; printf("\tHost Identifier (HOSTID): %" PRIu64 "\n", ull); break; case NVME_FEAT_RESV_MASK: printf("\tMask Reservation Preempted Notification (RESPRE): %s\n", ((result & 0x00000008) >> 3) ? "True":"False"); printf("\tMask Reservation Released Notification (RESREL): %s\n", ((result & 0x00000004) >> 2) ? "True":"False"); printf("\tMask Registration Preempted Notification (REGPRE): %s\n", ((result & 0x00000002) >> 1) ? "True":"False"); break; case NVME_FEAT_RESV_PERSIST: printf("\tPersist Through Power Loss (PTPL): %s\n", (result & 0x00000001) ? "True":"False"); break; } } void json_print_list_items(struct list_item *list_items, unsigned len) { struct json_object *root; struct json_array *devices; struct json_object *device_attrs; char formatter[41] = { 0 }; int index, i = 0; char *product; long long int lba; double nsze; double nuse; root = json_create_object(); devices = json_create_array(); for (i = 0; i < len; i++) { device_attrs = json_create_object(); json_object_add_value_string(device_attrs, "DevicePath", list_items[i].node); format(formatter, sizeof(formatter), list_items[i].ctrl.fr, sizeof(list_items[i].ctrl.fr)); json_object_add_value_string(device_attrs, "Firmware", formatter); if (sscanf(list_items[i].node, "/dev/nvme%d", &index) == 1) json_object_add_value_int(device_attrs, "Index", index); format(formatter, sizeof(formatter), list_items[i].ctrl.mn, sizeof(list_items[i].ctrl.mn)); json_object_add_value_string(device_attrs, "ModelNumber", formatter); product = nvme_product_name(index); json_object_add_value_string(device_attrs, "ProductName", product); format(formatter, sizeof(formatter), list_items[i].ctrl.sn, sizeof(list_items[i].ctrl.sn)); json_object_add_value_string(device_attrs, "SerialNumber", formatter); json_array_add_value_object(devices, device_attrs); lba = 1 << list_items[i].ns.lbaf[(list_items[i].ns.flbas & 0x0f)].ds; nsze = le64_to_cpu(list_items[i].ns.nsze) * lba; nuse = le64_to_cpu(list_items[i].ns.nuse) * lba; json_object_add_value_int(device_attrs, "UsedBytes", nuse); json_object_add_value_int(device_attrs, "MaximiumLBA", le64_to_cpu(list_items[i].ns.nsze)); json_object_add_value_int(device_attrs, "PhysicalSize", nsze); json_object_add_value_int(device_attrs, "SectorSize", lba); free((void*)product); } if (i) json_object_add_value_array(root, "Devices", devices); json_print_object(root, NULL); } void json_nvme_id_ns(struct nvme_id_ns *ns, unsigned int mode) { char nguid_buf[2 * sizeof(ns->nguid) + 1], eui64_buf[2 * sizeof(ns->eui64) + 1]; char *nguid = nguid_buf, *eui64 = eui64_buf; struct json_object *root; struct json_array *lbafs; int i; long double nvmcap = int128_to_double(ns->nvmcap); root = json_create_object(); json_object_add_value_int(root, "nsze", le64_to_cpu(ns->nsze)); json_object_add_value_int(root, "ncap", le64_to_cpu(ns->ncap)); json_object_add_value_int(root, "nuse", le64_to_cpu(ns->nuse)); json_object_add_value_int(root, "nsfeat", ns->nsfeat); json_object_add_value_int(root, "nlbaf", ns->nlbaf); json_object_add_value_int(root, "flbas", ns->flbas); json_object_add_value_int(root, "mc", ns->mc); json_object_add_value_int(root, "dpc", ns->dpc); json_object_add_value_int(root, "dps", ns->dps); json_object_add_value_int(root, "nmic", ns->nmic); json_object_add_value_int(root, "rescap", ns->rescap); json_object_add_value_int(root, "fpi", ns->fpi); json_object_add_value_int(root, "nawun", le16_to_cpu(ns->nawun)); json_object_add_value_int(root, "nawupf", le16_to_cpu(ns->nawupf)); json_object_add_value_int(root, "nacwu", le16_to_cpu(ns->nacwu)); json_object_add_value_int(root, "nabsn", le16_to_cpu(ns->nabsn)); json_object_add_value_int(root, "nabo", le16_to_cpu(ns->nabo)); json_object_add_value_int(root, "nabspf", le16_to_cpu(ns->nabspf)); json_object_add_value_int(root, "noiob", le16_to_cpu(ns->noiob)); json_object_add_value_float(root, "nvmcap", nvmcap); memset(eui64, 0, sizeof(eui64_buf)); for (i = 0; i < sizeof(ns->eui64); i++) eui64 += sprintf(eui64, "%02x", ns->eui64[i]); memset(nguid, 0, sizeof(nguid_buf)); for (i = 0; i < sizeof(ns->nguid); i++) nguid += sprintf(nguid, "%02x", ns->nguid[i]); json_object_add_value_string(root, "eui64", eui64_buf); json_object_add_value_string(root, "nguid", nguid_buf); lbafs = json_create_array(); json_object_add_value_array(root, "lbafs", lbafs); for (i = 0; i <= ns->nlbaf; i++) { struct json_object *lbaf = json_create_object(); json_object_add_value_int(lbaf, "ms", le16_to_cpu(ns->lbaf[i].ms)); json_object_add_value_int(lbaf, "ds", le16_to_cpu(ns->lbaf[i].ds)); json_object_add_value_int(lbaf, "rp", le16_to_cpu(ns->lbaf[i].rp)); json_array_add_value_object(lbafs, lbaf); } json_print_object(root, NULL); printf("\n"); json_free_object(root); } void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vs)(__u8 *vs, struct json_object *root)) { struct json_object *root; struct json_array *psds; long double tnvmcap = int128_to_double(ctrl->tnvmcap); long double unvmcap = int128_to_double(ctrl->unvmcap); char sn[sizeof(ctrl->sn) + 1], mn[sizeof(ctrl->mn) + 1], fr[sizeof(ctrl->fr) + 1], subnqn[sizeof(ctrl->subnqn) + 1]; __u32 ieee = ctrl->ieee[2] << 16 | ctrl->ieee[1] << 8 | ctrl->ieee[0]; int i; snprintf(sn, sizeof(sn), "%-.*s", (int)sizeof(ctrl->sn), ctrl->sn); snprintf(mn, sizeof(mn), "%-.*s", (int)sizeof(ctrl->mn), ctrl->mn); snprintf(fr, sizeof(fr), "%-.*s", (int)sizeof(ctrl->fr), ctrl->fr); snprintf(subnqn, sizeof(subnqn), "%-.*s", (int)sizeof(ctrl->subnqn), ctrl->subnqn); root = json_create_object(); json_object_add_value_int(root, "vid", le16_to_cpu(ctrl->vid)); json_object_add_value_int(root, "ssvid", le16_to_cpu(ctrl->ssvid)); json_object_add_value_string(root, "sn", sn); json_object_add_value_string(root, "mn", mn); json_object_add_value_string(root, "fr", fr); json_object_add_value_int(root, "rab", ctrl->rab); json_object_add_value_int(root, "ieee", ieee); json_object_add_value_int(root, "cmic", ctrl->cmic); json_object_add_value_int(root, "mdts", ctrl->mdts); json_object_add_value_int(root, "cntlid", le16_to_cpu(ctrl->cntlid)); json_object_add_value_int(root, "ver", le32_to_cpu(ctrl->ver)); json_object_add_value_int(root, "rtd3r", le32_to_cpu(ctrl->rtd3r)); json_object_add_value_int(root, "rtd3e", le32_to_cpu(ctrl->rtd3e)); json_object_add_value_int(root, "oaes", le32_to_cpu(ctrl->oaes)); json_object_add_value_int(root, "ctratt", le32_to_cpu(ctrl->ctratt)); json_object_add_value_int(root, "oacs", le16_to_cpu(ctrl->oacs)); json_object_add_value_int(root, "acl", ctrl->acl); json_object_add_value_int(root, "aerl", ctrl->aerl); json_object_add_value_int(root, "frmw", ctrl->frmw); json_object_add_value_int(root, "lpa", ctrl->lpa); json_object_add_value_int(root, "elpe", ctrl->elpe); json_object_add_value_int(root, "npss", ctrl->npss); json_object_add_value_int(root, "avscc", ctrl->avscc); json_object_add_value_int(root, "apsta", ctrl->apsta); json_object_add_value_int(root, "wctemp", le16_to_cpu(ctrl->wctemp)); json_object_add_value_int(root, "cctemp", le16_to_cpu(ctrl->cctemp)); json_object_add_value_int(root, "mtfa", le16_to_cpu(ctrl->mtfa)); json_object_add_value_int(root, "hmpre", le32_to_cpu(ctrl->hmpre)); json_object_add_value_int(root, "hmmin", le32_to_cpu(ctrl->hmmin)); json_object_add_value_float(root, "tnvmcap", tnvmcap); json_object_add_value_float(root, "unvmcap", unvmcap); json_object_add_value_int(root, "rpmbs", le32_to_cpu(ctrl->rpmbs)); json_object_add_value_int(root, "edstt", le16_to_cpu(ctrl->edstt)); json_object_add_value_int(root, "dsto", ctrl->dsto); json_object_add_value_int(root, "fwug", ctrl->fwug); json_object_add_value_int(root, "kas", le16_to_cpu(ctrl->kas)); json_object_add_value_int(root, "hctma", le16_to_cpu(ctrl->hctma)); json_object_add_value_int(root, "mntmt", le16_to_cpu(ctrl->mntmt)); json_object_add_value_int(root, "mxtmt", le16_to_cpu(ctrl->mxtmt)); json_object_add_value_int(root, "sanicap", le32_to_cpu(ctrl->sanicap)); json_object_add_value_int(root, "sqes", ctrl->sqes); json_object_add_value_int(root, "cqes", ctrl->cqes); json_object_add_value_int(root, "maxcmd", le16_to_cpu(ctrl->maxcmd)); json_object_add_value_int(root, "nn", le32_to_cpu(ctrl->nn)); json_object_add_value_int(root, "oncs", le16_to_cpu(ctrl->oncs)); json_object_add_value_int(root, "fuses", le16_to_cpu(ctrl->fuses)); json_object_add_value_int(root, "fna", ctrl->fna); json_object_add_value_int(root, "vwc", ctrl->vwc); json_object_add_value_int(root, "awun", le16_to_cpu(ctrl->awun)); json_object_add_value_int(root, "awupf", le16_to_cpu(ctrl->awupf)); json_object_add_value_int(root, "nvscc", ctrl->nvscc); json_object_add_value_int(root, "acwu", le16_to_cpu(ctrl->acwu)); json_object_add_value_int(root, "sgls", le32_to_cpu(ctrl->sgls)); if (strlen(subnqn)) json_object_add_value_string(root, "subnqn", subnqn); json_object_add_value_int(root, "ioccsz", le32_to_cpu(ctrl->ioccsz)); json_object_add_value_int(root, "iorcsz", le32_to_cpu(ctrl->iorcsz)); json_object_add_value_int(root, "icdoff", le16_to_cpu(ctrl->icdoff)); json_object_add_value_int(root, "ctrattr", ctrl->ctrattr); json_object_add_value_int(root, "msdbd", ctrl->msdbd); psds = json_create_array(); json_object_add_value_array(root, "psds", psds); for (i = 0; i <= ctrl->npss; i++) { struct json_object *psd = json_create_object(); json_object_add_value_int(psd, "max_power", le16_to_cpu(ctrl->psd[i].max_power)); json_object_add_value_int(psd, "flags", ctrl->psd[i].flags); json_object_add_value_int(psd, "entry_lat", le32_to_cpu(ctrl->psd[i].entry_lat)); json_object_add_value_int(psd, "exit_lat", le32_to_cpu(ctrl->psd[i].exit_lat)); json_object_add_value_int(psd, "read_tput", ctrl->psd[i].read_tput); json_object_add_value_int(psd, "read_lat", ctrl->psd[i].read_lat); json_object_add_value_int(psd, "write_tput", ctrl->psd[i].write_tput); json_object_add_value_int(psd, "write_lat", ctrl->psd[i].write_lat); json_object_add_value_int(psd, "idle_power", le16_to_cpu(ctrl->psd[i].idle_power)); json_object_add_value_int(psd, "idle_scale", ctrl->psd[i].idle_scale); json_object_add_value_int(psd, "active_power", le16_to_cpu(ctrl->psd[i].active_power)); json_object_add_value_int(psd, "active_work_scale", ctrl->psd[i].active_work_scale); json_array_add_value_object(psds, psd); } if(vs) vs(ctrl->vs, root); json_print_object(root, NULL); printf("\n"); json_free_object(root); } void json_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname) { struct json_object *root; struct json_array *errors; int i; root = json_create_object(); errors = json_create_array(); json_object_add_value_array(root, "errors", errors); for (i = 0; i < entries; i++) { struct json_object *error = json_create_object(); json_object_add_value_int(error, "error_count", err_log[i].error_count); json_object_add_value_int(error, "sqid", err_log[i].sqid); json_object_add_value_int(error, "cmdid", err_log[i].cmdid); json_object_add_value_int(error, "status_field", err_log[i].status_field); json_object_add_value_int(error, "parm_error_location", err_log[i].parm_error_location); json_object_add_value_int(error, "lba", err_log[i].lba); json_object_add_value_int(error, "nsid", err_log[i].nsid); json_object_add_value_int(error, "vs", err_log[i].vs); json_array_add_value_object(errors, error); } json_print_object(root, NULL); printf("\n"); json_free_object(root); } void json_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11) { struct json_object *root; struct json_array *rcs; int i, j, regctl, entries; regctl = status->regctl[0] | (status->regctl[1] << 8); root = json_create_object(); json_object_add_value_int(root, "gen", le32_to_cpu(status->gen)); json_object_add_value_int(root, "rtype", status->rtype); json_object_add_value_int(root, "regctl", regctl); json_object_add_value_int(root, "ptpls", status->ptpls); rcs = json_create_array(); /* check Extended Data Structure bit */ if ((cdw11 & 0x1) == 0) { /* if status buffer was too small, don't loop past the end of the buffer */ entries = (bytes - 24) / 24; if (entries < regctl) regctl = entries; json_object_add_value_array(root, "regctls", rcs); for (i = 0; i < regctl; i++) { struct json_object *rc = json_create_object(); json_object_add_value_int(rc, "cntlid", le16_to_cpu(status->regctl_ds[i].cntlid)); json_object_add_value_int(rc, "rcsts", status->regctl_ds[i].rcsts); json_object_add_value_int(rc, "hostid", (uint64_t)le64_to_cpu(status->regctl_ds[i].hostid)); json_object_add_value_int(rc, "rkey", (uint64_t)le64_to_cpu(status->regctl_ds[i].rkey)); json_array_add_value_object(rcs, rc); } } else { struct nvme_reservation_status_ext *ext_status = (struct nvme_reservation_status_ext *)status; char hostid[33]; /* if status buffer was too small, don't loop past the end of the buffer */ entries = (bytes - 64) / 64; if (entries < regctl) regctl = entries; json_object_add_value_array(root, "regctlext", rcs); for (i = 0; i < regctl; i++) { struct json_object *rc = json_create_object(); json_object_add_value_int(rc, "cntlid", le16_to_cpu(ext_status->regctl_eds[i].cntlid)); json_object_add_value_int(rc, "rcsts", ext_status->regctl_eds[i].rcsts); json_object_add_value_int(rc, "rkey", (uint64_t)le64_to_cpu(ext_status->regctl_eds[i].rkey)); for (j = 0; j < 16; j++) sprintf(hostid + j * 2, "%02x", ext_status->regctl_eds[i].hostid[j]); json_object_add_value_string(rc, "hostid", hostid); json_array_add_value_object(rcs, rc); } } json_print_object(root, NULL); printf("\n"); json_free_object(root); } void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname) { struct json_object *root; struct json_object *fwsi; char fmt[21]; char str[32]; int i; root = json_create_object(); fwsi = json_create_object(); json_object_add_value_int(fwsi, "Active Firmware Slot (afi)", fw_log->afi); for (i = 0; i < 7; i++) { snprintf(fmt, sizeof(fmt), "Firmware Rev Slot %d", i); snprintf(str, sizeof(str), "%"PRIu64" (%s)", (uint64_t)fw_log->frs[i], fw_to_string(fw_log->frs[i])); json_object_add_value_string(fwsi, fmt, str); } json_object_add_value_object(root, devname, fwsi); json_print_object(root, NULL); printf("\n"); json_free_object(root); } void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname) { struct json_object *root; int c; char key[21]; unsigned int temperature = ((smart->temperature[1] << 8) | smart->temperature[0]); long double data_units_read = int128_to_double(smart->data_units_read); long double data_units_written = int128_to_double(smart->data_units_written); long double host_read_commands = int128_to_double(smart->host_reads); long double host_write_commands = int128_to_double(smart->host_writes); long double controller_busy_time = int128_to_double(smart->ctrl_busy_time); long double power_cycles = int128_to_double(smart->power_cycles); long double power_on_hours = int128_to_double(smart->power_on_hours); long double unsafe_shutdowns = int128_to_double(smart->unsafe_shutdowns); long double media_errors = int128_to_double(smart->media_errors); long double num_err_log_entries = int128_to_double(smart->num_err_log_entries); root = json_create_object(); json_object_add_value_int(root, "critical_warning", smart->critical_warning); json_object_add_value_int(root, "temperature", temperature); json_object_add_value_int(root, "avail_spare", smart->avail_spare); json_object_add_value_int(root, "spare_thresh", smart->spare_thresh); json_object_add_value_int(root, "percent_used", smart->percent_used); json_object_add_value_float(root, "data_units_read", data_units_read); json_object_add_value_float(root, "data_units_written", data_units_written); json_object_add_value_float(root, "host_read_commands", host_read_commands); json_object_add_value_float(root, "host_write_commands", host_write_commands); json_object_add_value_float(root, "controller_busy_time", controller_busy_time); json_object_add_value_float(root, "power_cycles", power_cycles); json_object_add_value_float(root, "power_on_hours", power_on_hours); json_object_add_value_float(root, "unsafe_shutdowns", unsafe_shutdowns); json_object_add_value_float(root, "media_errors", media_errors); json_object_add_value_float(root, "num_err_log_entries", num_err_log_entries); json_object_add_value_int(root, "warning_temp_time", le32_to_cpu(smart->warning_temp_time)); json_object_add_value_int(root, "critical_comp_time", le32_to_cpu(smart->critical_comp_time)); for (c=0; c < 8; c++) { __s32 temp = le16_to_cpu(smart->temp_sensor[c]); if (temp == 0) continue; sprintf(key, "temperature_sensor_%d",c+1); json_object_add_value_int(root, key, temp); } json_object_add_value_int(root, "thm_temp1_trans_count", le32_to_cpu(smart->thm_temp1_trans_count)); json_object_add_value_int(root, "thm_temp2_trans_count", le32_to_cpu(smart->thm_temp2_trans_count)); json_object_add_value_int(root, "thm_temp1_total_time", le32_to_cpu(smart->thm_temp1_total_time)); json_object_add_value_int(root, "thm_temp2_total_time", le32_to_cpu(smart->thm_temp2_total_time)); json_print_object(root, NULL); printf("\n"); json_free_object(root); } void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n) { struct json_object *root; struct json_array *subsystems; struct json_object *subsystem_attrs; struct json_array *paths; struct json_object *path_attrs; struct json_object *path_object; int i, j; root = json_create_object(); subsystems = json_create_array(); for (i = 0; i < n; i++) { subsystem_attrs = json_create_object(); json_object_add_value_string(subsystem_attrs, "Name", slist[i].name); json_object_add_value_string(subsystem_attrs, "NQN", slist[i].subsysnqn); json_array_add_value_object(subsystems, subsystem_attrs); paths = json_create_array(); path_object = json_create_object(); for (j = 0; j < slist[i].nctrls; j++) { path_attrs = json_create_object(); json_object_add_value_string(path_attrs, "Name", slist[i].ctrls[j].name); json_object_add_value_string(path_attrs, "Transport", slist[i].ctrls[j].transport); json_object_add_value_string(path_attrs, "Address", slist[i].ctrls[j].address); json_array_add_value_object(paths, path_attrs); } if (j) { json_object_add_value_array(path_object, "Paths", paths); json_array_add_value_object(subsystems, path_object); } } if (i) json_object_add_value_array(root, "Subsystems", subsystems); json_print_object(root, NULL); } void show_registers_cap(struct nvme_bar_cap *cap) { printf("\tMemory Page Size Maximum (MPSMAX): %u bytes\n", 1 << (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4))); printf("\tMemory Page Size Minimum (MPSMIN): %u bytes\n", 1 << (12 + (cap->mpsmax_mpsmin & 0x0f))); printf("\tCommand Sets Supported (CSS): NVM command set is %s\n", (cap->css_nssrs_dstrd & 0x0020) ? "supported":"not supported"); printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n", (cap->css_nssrs_dstrd & 0x0010) ? "Yes":"No"); printf("\tDoorbell Stride (DSTRD): %u bytes\n", 1 << (2 + (cap->css_nssrs_dstrd & 0x000f))); printf("\tTimeout (TO): %u ms\n", cap->to * 500); printf("\tArbitration Mechanism Supported (AMS): Weighted Round Robin with Urgent Priority Class is %s\n", (cap->ams_cqr & 0x02) ? "supported":"not supported"); printf("\tContiguous Queues Required (CQR): %s\n", (cap->ams_cqr & 0x01) ? "Yes":"No"); printf("\tMaximum Queue Entries Supported (MQES): %u\n\n", cap->mqes + 1); } static void show_registers_version(__u32 vs) { printf("\tNVMe specification %d.%d\n\n", (vs & 0xffff0000) >> 16, (vs & 0x0000ff00) >> 8); } static void show_registers_cc_ams (__u8 ams) { printf("\tArbitration Mechanism Selected (AMS): "); switch (ams) { case 0: printf("Round Robin\n"); break; case 1: printf("Weighted Round Robin with Urgent Priority Class\n"); break; case 7: printf("Vendor Specific\n"); break; default: printf("Reserved\n"); } } static void show_registers_cc_shn (__u8 shn) { printf("\tShutdown Notification (SHN): "); switch (shn) { case 0: printf("No notification; no effect\n"); break; case 1: printf("Normal shutdown notification\n"); break; case 2: printf("Abrupt shutdown notification\n"); break; default: printf("Reserved\n"); } } static void show_registers_cc(__u32 cc) { printf("\tI/O Completion Queue Entry Size (IOCQES): %u bytes\n", 1 << ((cc & 0x00f00000) >> NVME_CC_IOCQES_SHIFT)); printf("\tI/O Submission Queue Entry Size (IOSQES): %u bytes\n", 1 << ((cc & 0x000f0000) >> NVME_CC_IOSQES_SHIFT)); show_registers_cc_shn((cc & 0x0000c000) >> NVME_CC_SHN_SHIFT); show_registers_cc_ams((cc & 0x00003800) >> NVME_CC_AMS_SHIFT); printf("\tMemory Page Size (MPS): %u bytes\n", 1 << (12 + ((cc & 0x00000780) >> NVME_CC_MPS_SHIFT))); printf("\tI/O Command Sets Selected (CSS): %s\n", (cc & 0x00000070) ? "Reserved":"NVM Command Set"); printf("\tEnable (EN): %s\n\n", (cc & 0x00000001) ? "Yes":"No"); } static void show_registers_csts_shst(__u8 shst) { printf("\tShutdown Status (SHST): "); switch (shst) { case 0: printf("Normal operation (no shutdown has been requested)\n"); break; case 1: printf("Shutdown processing occurring\n"); break; case 2: printf("Shutdown processing complete\n"); break; default: printf("Reserved\n"); } } static void show_registers_csts(__u32 csts) { printf("\tProcessing Paused (PP): %s\n", (csts & 0x00000020) ? "Yes":"No"); printf("\tNVM Subsystem Reset Occurred (NSSRO): %s\n", (csts & 0x00000010) ? "Yes":"No"); show_registers_csts_shst((csts & 0x0000000c) >> 2); printf("\tController Fatal Status (CFS): %s\n", (csts & 0x00000002) ? "True":"False"); printf("\tReady (RDY): %s\n\n", (csts & 0x00000001) ? "Yes":"No"); } static void show_registers_aqa(__u32 aqa) { printf("\tAdmin Completion Queue Size (ACQS): %u\n", ((aqa & 0x0fff0000) >> 16)+1); printf("\tAdmin Submission Queue Size (ASQS): %u\n\n", (aqa & 0x00000fff)+1); } static void show_registers_cmbloc(__u32 cmbloc, __u32 cmbsz) { if (cmbsz == 0) { printf("\tController Memory Buffer feature is not supported\n\n"); } else { printf("\tOffset (OFST): %x (See cmbsz.szu for granularity)\n", (cmbloc & 0xfffff000) >> 12); printf("\tBase Indicator Register (BIR): %x\n\n", cmbloc & 0x00000007 ); } } static char *nvme_register_szu_to_string(__u8 szu) { switch (szu) { case 0: return "4 KB"; case 1: return "64 KB"; case 2: return "1 MB"; case 3: return "16 MB"; case 4: return "256 MB"; case 5: return "4 GB"; case 6: return "64 GB"; default: return "Reserved"; } } static void show_registers_cmbsz(__u32 cmbsz) { if (cmbsz == 0) { printf("\tController Memory Buffer feature is not supported\n\n"); return; } printf("\tSize (SZ): %u\n", (cmbsz & 0xfffff000) >> 12); printf("\tSize Units (SZU): %s\n", nvme_register_szu_to_string((cmbsz & 0x00000f00) >> 8)); printf("\tWrite Data Support (WDS): Write Data and metadata transfer in Controller Memory Buffer is %s\n", (cmbsz & 0x00000010) ? "Supported":"Not supported"); printf("\tRead Data Support (RDS): Read Data and metadata transfer in Controller Memory Buffer is %s\n", (cmbsz & 0x00000008) ? "Supported":"Not supported"); printf("\tPRP SGL List Support (LISTS): PRP/SG Lists in Controller Memory Buffer is %s\n", (cmbsz & 0x00000004) ? "Supported":"Not supported"); printf("\tCompletion Queue Support (CQS): Admin and I/O Completion Queues in Controller Memory Buffer is %s\n", (cmbsz & 0x00000002) ? "Supported":"Not supported"); printf("\tSubmission Queue Support (SQS): Admin and I/O Submission Queues in Controller Memory Buffer is %s\n\n", (cmbsz & 0x00000001) ? "Supported":"Not supported"); } static void show_registers_bpinfo_brs(__u8 brs) { printf("\tBoot Read Status (BRS): "); switch (brs) { case 0: printf("No Boot Partition read operation requested\n"); break; case 1: printf("Boot Partition read in progres\n"); break; case 2: printf("Boot Partition read completed successfully\n"); break; case 3: printf("Error completing Boot Partition read\n"); break; default: printf("Invalid\n"); } } static void show_registers_bpinfo(__u32 bpinfo) { if (bpinfo == 0) { printf("\tBoot Partition feature is not supported\n\n"); return; } printf("\tActive Boot Partition ID (ABPID): %u\n", (bpinfo & 0x80000000) >> 31); show_registers_bpinfo_brs((bpinfo & 0x03000000) >> 24); printf("\tBoot Partition Size (BPSZ): %u\n", bpinfo & 0x00007fff); } static void show_registers_bprsel(__u32 bprsel) { if (bprsel == 0) { printf("\tBoot Partition feature is not supported\n\n"); return; } printf("\tBoot Partition Identifier (BPID): %u\n", (bprsel & 0x80000000) >> 31); printf("\tBoot Partition Read Offset (BPROF): %x\n", (bprsel & 0x3ffffc00) >> 10); printf("\tBoot Partition Read Size (BPRSZ): %x\n", bprsel & 0x000003ff); } static void show_registers_bpmbl(uint64_t bpmbl) { if (bpmbl == 0) { printf("\tBoot Partition feature is not supported\n\n"); return; } printf("\tBoot Partition Memory Buffer Base Address (BMBBA): %"PRIx64"\n", bpmbl); } static inline uint32_t mmio_read32(void *addr) { __le32 *p = addr; return le32_to_cpu(*p); } /* Access 64-bit registers as 2 32-bit; Some devices fail 64-bit MMIO. */ static inline __u64 mmio_read64(void *addr) { __le32 *p = addr; return le32_to_cpu(*p) | ((uint64_t)le32_to_cpu(*(p + 1)) << 32); } void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics) { uint64_t cap, asq, acq, bpmbl; uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc, bpinfo, bprsel; int human = mode & HUMAN; cap = mmio_read64(bar + NVME_REG_CAP); vs = mmio_read32(bar + NVME_REG_VS); intms = mmio_read32(bar + NVME_REG_INTMS); intmc = mmio_read32(bar + NVME_REG_INTMC); cc = mmio_read32(bar + NVME_REG_CC); csts = mmio_read32(bar + NVME_REG_CSTS); nssr = mmio_read32(bar + NVME_REG_NSSR); aqa = mmio_read32(bar + NVME_REG_AQA); asq = mmio_read64(bar + NVME_REG_ASQ); acq = mmio_read64(bar + NVME_REG_ACQ); cmbloc = mmio_read32(bar + NVME_REG_CMBLOC); cmbsz = mmio_read32(bar + NVME_REG_CMBSZ); bpinfo = mmio_read32(bar + NVME_REG_BPINFO); bprsel = mmio_read32(bar + NVME_REG_BPRSEL); bpmbl = mmio_read64(bar + NVME_REG_BPMBL); if (human) { if (cap != 0xffffffff) { printf("cap : %"PRIx64"\n", cap); show_registers_cap((struct nvme_bar_cap *)&cap); } if (vs != 0xffffffff) { printf("version : %x\n", vs); show_registers_version(vs); } if (cc != 0xffffffff) { printf("cc : %x\n", cc); show_registers_cc(cc); } if (csts != 0xffffffff) { printf("csts : %x\n", csts); show_registers_csts(csts); } if (nssr != 0xffffffff) { printf("nssr : %x\n", nssr); printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", nssr); } if (!fabrics) { printf("intms : %x\n", intms); printf("\tInterrupt Vector Mask Set (IVMS): %x\n\n", intms); printf("intmc : %x\n", intmc); printf("\tInterrupt Vector Mask Clear (IVMC): %x\n\n", intmc); printf("aqa : %x\n", aqa); show_registers_aqa(aqa); printf("asq : %"PRIx64"\n", asq); printf("\tAdmin Submission Queue Base (ASQB): %"PRIx64"\n\n", asq); printf("acq : %"PRIx64"\n", acq); printf("\tAdmin Completion Queue Base (ACQB): %"PRIx64"\n\n", acq); printf("cmbloc : %x\n", cmbloc); show_registers_cmbloc(cmbloc, cmbsz); printf("cmbsz : %x\n", cmbsz); show_registers_cmbsz(cmbsz); printf("bpinfo : %x\n", bpinfo); show_registers_bpinfo(bpinfo); printf("bprsel : %x\n", bprsel); show_registers_bprsel(bprsel); printf("bpmbl : %"PRIx64"\n", bpmbl); show_registers_bpmbl(bpmbl); } } else { if (cap != 0xffffffff) printf("cap : %"PRIx64"\n", cap); if (vs != 0xffffffff) printf("version : %x\n", vs); if (cc != 0xffffffff) printf("cc : %x\n", cc); if (csts != 0xffffffff) printf("csts : %x\n", csts); if (nssr != 0xffffffff) printf("nssr : %x\n", nssr); if (!fabrics) { printf("intms : %x\n", intms); printf("intmc : %x\n", intmc); printf("aqa : %x\n", aqa); printf("asq : %"PRIx64"\n", asq); printf("acq : %"PRIx64"\n", acq); printf("cmbloc : %x\n", cmbloc); printf("cmbsz : %x\n", cmbsz); printf("bpinfo : %x\n", bpinfo); printf("bprsel : %x\n", bprsel); printf("bpmbl : %"PRIx64"\n", bpmbl); } } } nvme-cli-1.5/nvme-print.h000066400000000000000000000045231322317423600153500ustar00rootroot00000000000000#ifndef NVME_PRINT_H #define NVME_PRINT_H #include "nvme.h" #include "json.h" #include enum { TERSE = 0x1u, // only show a few useful fields HUMAN = 0x2u, // interpret some values for humans VS = 0x4u, // print vendor specific data area RAW = 0x8u, // just dump raw bytes }; void d(unsigned char *buf, int len, int width, int group); void d_raw(unsigned char *buf, unsigned len); uint64_t int48_to_long(__u8 *data); void __show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root)); void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode); void show_nvme_id_ns(struct nvme_id_ns *ns, unsigned int flags); void show_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11); void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges); void show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname); void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname); void show_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname); void show_effects_log(struct nvme_effects_log_page *effects); void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics); void show_nvme_id_ns_descs(void *data); void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf); void nvme_directive_show_fields(__u8 dtype, __u8 doper, unsigned int result, unsigned char *buf); char *nvme_status_to_string(__u32 status); char *nvme_select_to_string(int sel); char *nvme_feature_to_string(int feature); char *nvme_register_to_string(int reg); void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root)); void json_nvme_id_ns(struct nvme_id_ns *ns, unsigned int flags); void json_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11); void json_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname); void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname); void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname); void json_print_list_items(struct list_item *items, unsigned amnt); void json_nvme_id_ns_descs(void *data); void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n); #endif nvme-cli-1.5/nvme.c000066400000000000000000003407101322317423600142120ustar00rootroot00000000000000/* * nvme.c -- NVM-Express command line utility. * * Copyright (c) 2014-2015, Intel Corporation. * * Written by Keith Busch * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * This program uses NVMe IOCTLs to run native nvme commands to a device. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nvme-print.h" #include "nvme-ioctl.h" #include "nvme-lightnvm.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" #include "fabrics.h" #define array_len(x) ((size_t)(sizeof(x) / sizeof(x[0]))) #define min(x, y) ((x) > (y) ? (y) : (x)) #define max(x, y) ((x) > (y) ? (x) : (y)) static struct stat nvme_stat; const char *devicename; static const char nvme_version_string[] = NVME_VERSION; #define CREATE_CMD #include "nvme-builtin.h" static struct plugin builtin = { .commands = commands, .name = NULL, .desc = NULL, .next = NULL, .tail = &builtin, }; static struct program nvme = { .name = "nvme", .version = nvme_version_string, .usage = " [] []", .desc = "The '' may be either an NVMe character "\ "device (ex: /dev/nvme0) or an nvme block device "\ "(ex: /dev/nvme0n1).", .extensions = &builtin, }; static unsigned long long elapsed_utime(struct timeval start_time, struct timeval end_time) { unsigned long long ret = (end_time.tv_sec - start_time.tv_sec) * 1000000 + (end_time.tv_usec - start_time.tv_usec); return ret; } static int open_dev(const char *dev) { int err, fd; devicename = basename(dev); err = open(dev, O_RDONLY); if (err < 0) goto perror; fd = err; err = fstat(fd, &nvme_stat); if (err < 0) goto perror; if (!S_ISCHR(nvme_stat.st_mode) && !S_ISBLK(nvme_stat.st_mode)) { fprintf(stderr, "%s is not a block or character device\n", dev); return -ENODEV; } return fd; perror: perror(dev); return err; } static int check_arg_dev(int argc, char **argv) { if (optind >= argc) { errno = EINVAL; perror(argv[0]); return -EINVAL; } return 0; } static int get_dev(int argc, char **argv) { int ret; ret = check_arg_dev(argc, argv); if (ret) return ret; return open_dev((const char *)argv[optind]); } int parse_and_open(int argc, char **argv, const char *desc, const struct argconfig_commandline_options *clo, void *cfg, size_t size) { int ret; ret = argconfig_parse(argc, argv, desc, clo, cfg, size); if (ret) return ret; ret = get_dev(argc, argv); if (ret < 0) argconfig_print_help(desc, clo); return ret; } static const char *output_format = "Output format: normal|json|binary"; int validate_output_format(char *format) { if (!format) return -EINVAL; if (!strcmp(format, "normal")) return NORMAL; if (!strcmp(format, "json")) return JSON; if (!strcmp(format, "binary")) return BINARY; return -EINVAL; } static int get_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_smart_log smart_log; const char *desc = "Retrieve SMART log for the given device "\ "(or optionally a namespace) in either decoded format "\ "(default) or binary."; const char *namespace = "(optional) desired namespace"; const char *raw = "output in binary format"; int err, fmt, fd; struct config { __u32 namespace_id; int raw_binary; char *output_format; }; struct config cfg = { .namespace_id = NVME_NSID_ALL, .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; if (cfg.raw_binary) fmt = BINARY; err = nvme_smart_log(fd, cfg.namespace_id, &smart_log); if (!err) { if (fmt == BINARY) d_raw((unsigned char *)&smart_log, sizeof(smart_log)); else if (fmt == JSON) json_smart_log(&smart_log, cfg.namespace_id, devicename); else show_smart_log(&smart_log, cfg.namespace_id, devicename); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("smart log"); return err; } static int get_effects_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve command effects log page and print the table."; struct nvme_effects_log_page effects; int err, fd; struct config { }; struct config cfg = { }; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; err = nvme_get_log(fd, NVME_NSID_ALL, 5, 4096, &effects); if (!err) show_effects_log(&effects); else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("effects log page"); return err; } static int get_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve specified number of "\ "error log entries from a given device (or "\ "namespace) in either decoded format (default) or binary."; const char *namespace_id = "desired namespace"; const char *log_entries = "number of entries to retrieve"; const char *raw_binary = "dump in binary format"; struct nvme_id_ctrl ctrl; int err, fmt, fd; struct config { __u32 namespace_id; __u32 log_entries; int raw_binary; char *output_format; }; struct config cfg = { .namespace_id = NVME_NSID_ALL, .log_entries = 64, .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"log-entries", 'e', "NUM", CFG_POSITIVE, &cfg.log_entries, required_argument, log_entries}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; if (cfg.raw_binary) fmt = BINARY; if (!cfg.log_entries) { fprintf(stderr, "non-zero log-entries is required param\n"); return EINVAL; } err = nvme_identify_ctrl(fd, &ctrl); if (err < 0) perror("identify controller"); else if (err) { fprintf(stderr, "could not identify controller\n"); err = ENODEV; } else { struct nvme_error_log_page *err_log; cfg.log_entries = min(cfg.log_entries, ctrl.elpe + 1); err_log = calloc(cfg.log_entries, sizeof(struct nvme_error_log_page)); if (!err_log) { fprintf(stderr, "could not alloc buffer for error log\n"); return ENOMEM; } err = nvme_error_log(fd, cfg.namespace_id, cfg.log_entries, err_log); if (!err) { if (fmt == BINARY) d_raw((unsigned char *)err_log, sizeof(err_log)); else if (fmt == JSON) json_error_log(err_log, cfg.log_entries, devicename); else show_error_log(err_log, cfg.log_entries, devicename); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("error log"); free(err_log); } return err; } static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve the firmware log for the "\ "specified device in either decoded format (default) or binary."; const char *raw_binary = "use binary output"; int err, fmt, fd; struct nvme_firmware_log_page fw_log; struct config { int raw_binary; char *output_format; }; struct config cfg = { .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; if (cfg.raw_binary) fmt = BINARY; err = nvme_fw_log(fd, &fw_log); if (!err) { if (fmt == BINARY) d_raw((unsigned char *)&fw_log, sizeof(fw_log)); else if (fmt == JSON) json_fw_log(&fw_log, devicename); else show_fw_log(&fw_log, devicename); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("fw log"); return err; } static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve desired number of bytes "\ "from a given log on a specified device in either "\ "hex-dump (default) or binary format"; const char *namespace_id = "desired namespace"; const char *log_id = "identifier of log to retrieve"; const char *log_len = "how many bytes to retrieve"; const char *aen = "result of the aen, use to override log id"; const char *raw_binary = "output in raw format"; int err, fd; struct config { __u32 namespace_id; __u32 log_id; __u32 log_len; __u32 aen; int raw_binary; }; struct config cfg = { .namespace_id = NVME_NSID_ALL, .log_id = 0, .log_len = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"log-id", 'i', "NUM", CFG_POSITIVE, &cfg.log_id, required_argument, log_id}, {"log-len", 'l', "NUM", CFG_POSITIVE, &cfg.log_len, required_argument, log_len}, {"aen", 'a', "NUM", CFG_POSITIVE, &cfg.aen, required_argument, aen}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.aen) { cfg.log_len = 4096; cfg.log_id = (cfg.aen >> 16) & 0xff; } if (!cfg.log_len) { fprintf(stderr, "non-zero log-len is required param\n"); return EINVAL; } else { unsigned char *log; log = malloc(cfg.log_len); if (!log) { fprintf(stderr, "could not alloc buffer for log\n"); return EINVAL; } err = nvme_get_log(fd, cfg.namespace_id, cfg.log_id, cfg.log_len, log); if (!err) { if (!cfg.raw_binary) { printf("Device:%s log-id:%d namespace-id:%#x\n", devicename, cfg.log_id, cfg.namespace_id); d(log, cfg.log_len, 16, 1); } else d_raw((unsigned char *)log, cfg.log_len); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("log page"); free(log); return err; } } static const char * sanitize_mon_status_to_string(__u16 status) { const char * str; switch (status & NVME_SANITIZE_LOG_STATUS_MASK) { case NVME_SANITIZE_LOG_NEVER_SANITIZED: str = "NVM Subsystem has never been sanitized."; break; case NVME_SANITIZE_LOG_COMPLETED_SUCCESS: str = "Most Recent Sanitize Command Completed Successfully."; break; case NVME_SANITIZE_LOG_IN_PROGESS: str = "Sanitize in Progress."; break; case NVME_SANITIZE_LOG_COMPLETED_FAILED: str = "Most Recent Sanitize Command Failed."; break; default: str = "Unknown."; } return str; } static int sanitize_log(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Retrieve sanitize log and show it."; int fd; int ret; __u8 output[NVME_SANITIZE_LOG_DATA_LEN] = {0}; struct nvme_sanitize_log_page *slp; double progress_percent; const struct argconfig_commandline_options command_line_options[] = { { NULL, '\0', NULL, CFG_NONE, NULL, no_argument, desc}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; ret = nvme_get_log(fd, 0x01, NVME_LOG_SANITIZE, NVME_SANITIZE_LOG_DATA_LEN, output); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); if (ret != 0) return ret; slp = (struct nvme_sanitize_log_page *) output; printf("Sanitize status = 0x%0x\n", slp->status); printf("%s\n", sanitize_mon_status_to_string(slp->status)); if ((slp->status & NVME_SANITIZE_LOG_STATUS_MASK) == NVME_SANITIZE_LOG_IN_PROGESS) { progress_percent = (((double)le32_to_cpu(slp->progress) * 100) / 0x10000); printf("Sanitize Progress (percentage) = %f%%\n", progress_percent); } else { if (slp->status & NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED) printf("Global Data Erased Set\n"); else printf("Global Data Erased Cleared\n"); } return ret; } static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Show controller list information for the subsystem the "\ "given device is part of, or optionally controllers attached to a specific namespace."; const char *controller = "controller to display"; const char *namespace_id = "optional namespace attached to controller"; int err, i, fd; struct nvme_controller_list *cntlist; struct config { __u16 cntid; __u32 namespace_id; }; struct config cfg = { .cntid = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"cntid", 'c', "NUM", CFG_SHORT, &cfg.cntid, required_argument, controller}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (posix_memalign((void *)&cntlist, getpagesize(), 0x1000)) { fprintf(stderr, "can not allocate controller list payload\n"); return ENOMEM; } err = nvme_identify_ctrl_list(fd, cfg.namespace_id, cfg.cntid, cntlist); if (!err) { __u16 num = le16_to_cpu(cntlist->num); for (i = 0; i < (min(num, 2048)); i++) printf("[%4u]:%#x\n", i, le16_to_cpu(cntlist->identifier[i])); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) cntid:%d\n", nvme_status_to_string(err), err, cfg.cntid); else perror("id controller list"); return err; } static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "For the specified device, show the "\ "namespace list in a NVMe subsystem, optionally starting with a given namespace"; const char *namespace_id = "namespace number returned list should to start after"; const char *all = "show all namespaces in the subsystem, whether attached or inactive"; int err, i, fd; __u32 ns_list[1024]; struct config { __u32 namespace_id; int all; }; struct config cfg = { .namespace_id = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"all", 'a', "", CFG_NONE, &cfg.all, no_argument, all}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; err = nvme_identify_ns_list(fd, cfg.namespace_id, !!cfg.all, ns_list); if (!err) { for (i = 0; i < 1024; i++) if (ns_list[i]) printf("[%4u]:%#x\n", i, ns_list[i]); } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", nvme_status_to_string(err), err, cfg.namespace_id); else perror("id namespace list"); return err; } static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Delete the given namespace by "\ "sending a namespace management command to "\ "the provided device. All controllers should be detached from "\ "the namespace prior to namespace deletion. A namespace ID "\ "becomes inactive when that namespace is detached or, if "\ "the namespace is not already inactive, once deleted."; const char *namespace_id = "namespace to delete"; int err, fd; struct config { __u32 namespace_id; }; struct config cfg = { .namespace_id = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (!cfg.namespace_id) { fprintf(stderr, "%s: namespace-id parameter required\n", cmd->name); return EINVAL; } err = nvme_ns_delete(fd, cfg.namespace_id); if (!err) printf("%s: Success, deleted nsid:%d\n", cmd->name, cfg.namespace_id); else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("delete namespace"); return err; } static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd) { int err, num, i, fd, list[2048]; __u16 ctrlist[2048]; const char *namespace_id = "namespace to attach"; const char *cont = "optional comma-sep controllers list"; struct config { char *cntlist; __u32 namespace_id; }; struct config cfg = { .cntlist = "", .namespace_id = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"controllers", 'c', "LIST", CFG_STRING, &cfg.cntlist, required_argument, cont}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (!cfg.namespace_id) { fprintf(stderr, "%s: namespace-id parameter required\n", cmd->name); return EINVAL; } num = argconfig_parse_comma_sep_array(cfg.cntlist, list, 2047); for (i = 0; i < num; i++) ctrlist[i] = (uint16_t)list[i]; if (attach) err = nvme_ns_attach_ctrls(fd, cfg.namespace_id, num, ctrlist); else err = nvme_ns_detach_ctrls(fd, cfg.namespace_id, num, ctrlist); if (!err) printf("%s: Success, nsid:%d\n", cmd->name, cfg.namespace_id); else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror(attach ? "attach namespace" : "detach namespace"); return err; } static int attach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Attach the given namespace to the "\ "given controller or comma-sep list of controllers. ID of the "\ "given namespace becomes active upon attachment to a "\ "controller. A namespace must be attached to a controller "\ "before IO commands may be directed to that namespace."; return nvme_attach_ns(argc, argv, 1, desc, cmd); } static int detach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Detach the given namespace from the "\ "given controller; de-activates the given namespace's ID. A "\ "namespace must be attached to a controller before IO "\ "commands may be directed to that namespace."; return nvme_attach_ns(argc, argv, 0, desc, cmd); } static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send a namespace management command "\ "to the specified device to create a namespace with the given "\ "parameters. The next available namespace ID is used for the "\ "create operation. Note that create-ns does not attach the "\ "namespace to a controller, the attach-ns command is needed."; const char *nsze = "size of ns"; const char *ncap = "capacity of ns"; const char *flbas = "FLBA size"; const char *dps = "data protection capabilities"; const char *nmic = "multipath and sharing capabilities"; int err = 0, fd; __u32 nsid; struct config { __u64 nsze; __u64 ncap; __u8 flbas; __u8 dps; __u8 nmic; }; struct config cfg = { }; const struct argconfig_commandline_options command_line_options[] = { {"nsze", 's', "NUM", CFG_LONG_SUFFIX, &cfg.nsze, required_argument, nsze}, {"ncap", 'c', "NUM", CFG_LONG_SUFFIX, &cfg.ncap, required_argument, ncap}, {"flbas", 'f', "NUM", CFG_BYTE, &cfg.flbas, required_argument, flbas}, {"dps", 'd', "NUM", CFG_BYTE, &cfg.dps, required_argument, dps}, {"nmic", 'm', "NUM", CFG_BYTE, &cfg.nmic, required_argument, nmic}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; err = nvme_ns_create(fd, cfg.nsze, cfg.ncap, cfg.flbas, cfg.dps, cfg.nmic, &nsid); if (!err) printf("%s: Success, created nsid:%d\n", cmd->name, nsid); else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("create namespace"); return err; } static char *nvme_char_from_block(char *block) { char slen[16]; unsigned len; if (strncmp("nvme", block, 4)) { fprintf(stderr, "Device %s is not a nvme device.", block); return NULL; } sscanf(block, "nvme%d", &len); sprintf(slen, "%d", len); block[4 + strlen(slen)] = 0; return block; } static void *get_registers(void) { int fd; char *base, path[512]; void *membase; base = nvme_char_from_block((char *)devicename); sprintf(path, "/sys/class/nvme/%s/device/resource0", base); fd = open(path, O_RDONLY); if (fd < 0) { sprintf(path, "/sys/class/misc/%s/device/resource0", base); fd = open(path, O_RDONLY); } if (fd < 0) { fprintf(stderr, "%s did not find a pci resource\n", base); return NULL; } membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0); if (membase == MAP_FAILED) { fprintf(stderr, "%s failed to map\n", base); return NULL; } return membase; } static const char *subsys_dir = "/sys/class/nvme-subsystem/"; static char *get_nvme_subsnqn(char *path) { char sspath[319]; char *subsysnqn; int fd; int ret; snprintf(sspath, sizeof(sspath), "%s/subsysnqn", path); fd = open(sspath, O_RDONLY); if (fd < 0) return NULL; subsysnqn = calloc(1, 256); if (!subsysnqn) goto close_fd; ret = read(fd, subsysnqn, 256); if (ret < 0) { free(subsysnqn); subsysnqn = NULL; } if (subsysnqn[strlen(subsysnqn) - 1] == '\n') subsysnqn[strlen(subsysnqn) - 1] = '\0'; close_fd: close(fd); return subsysnqn; } static char *get_nvme_ctrl_transport(char *path) { char *trpath; char *transport; int fd; ssize_t ret; ret = asprintf(&trpath, "%s/transport", path); if (ret < 0) return NULL; transport = calloc(1, 1024); if (!transport) goto err_free_trpath; fd = open(trpath, O_RDONLY); if (fd < 0) goto err_free_tr; ret = read(fd, transport, 1024); if (ret < 0) goto err_close_fd; if (transport[strlen(transport) - 1] == '\n') transport[strlen(transport) - 1] = '\0'; close(fd); free(trpath); return transport; err_close_fd: close(fd); err_free_tr: free(transport); err_free_trpath: free(trpath); return NULL; } static char *get_nvme_ctrl_address(char *path) { char *addrpath; char *address; int fd; ssize_t ret; int i; ret = asprintf(&addrpath, "%s/address", path); if (ret < 0) return NULL; address = calloc(1, 1024); if (!address) goto err_free_addrpath; fd = open(addrpath, O_RDONLY); if (fd < 0) goto err_free_addr; ret = read(fd, address, 1024); if (ret < 0) goto err_close_fd; if (address[strlen(address) - 1] == '\n') address[strlen(address) - 1] = '\0'; for (i = 0; i < strlen(address); i++) { if (address[i] == ',' ) address[i] = ' '; } close(fd); free(addrpath); return address; err_close_fd: close(fd); err_free_addr: free(address); err_free_addrpath: free(addrpath); return NULL; } static int scan_ctrls_filter(const struct dirent *d) { int id, nsid; if (d->d_name[0] == '.') return 0; if (strstr(d->d_name, "nvme")) { if (sscanf(d->d_name, "nvme%dn%d", &id, &nsid) == 2) return 0; return 1; } return 0; } void print_nvme_subsystem(struct subsys_list_item *item) { int i; printf("%s - NQN=%s\n", item->name, item->subsysnqn); printf("\\\n"); for (i = 0; i < item->nctrls; i++) { printf(" +- %s %s %s\n", item->ctrls[i].name, item->ctrls[i].transport, item->ctrls[i].address); } } void print_nvme_subsystem_list(struct subsys_list_item *slist, int n) { int i; for (i = 0; i < n; i++) print_nvme_subsystem(&slist[i]); } int get_nvme_subsystem_info(char *name, char *path, struct subsys_list_item *item) { char ctrl_path[512]; struct dirent **ctrls; int n, i; item->subsysnqn = get_nvme_subsnqn(path); if (!item->subsysnqn) return 1; item->name = strdup(name); n = scandir(path, &ctrls, scan_ctrls_filter, alphasort); if (n < 0) goto free_subysynqn; item->ctrls = calloc(n, sizeof(struct ctrl_list_item)); if (!item->ctrls) goto free_ctrls; item->nctrls = n; for (i = 0; i < n; i++) { item->ctrls[i].name = strdup(ctrls[i]->d_name); snprintf(ctrl_path, sizeof(ctrl_path), "%s/%s", path, item->ctrls[i].name); item->ctrls[i].address = get_nvme_ctrl_address(ctrl_path); if (!item->ctrls[i].address) { free(item->ctrls[i].name); goto free_ctrl_list; } item->ctrls[i].transport = get_nvme_ctrl_transport(ctrl_path); if (!item->ctrls[i].transport) { free(item->ctrls[i].name); free(item->ctrls[i].address); goto free_ctrl_list; } } for (i = 0; i < n; i++) free(ctrls[i]); free(ctrls); return 0; free_ctrl_list: free(item->ctrls); free_ctrls: for (i = 0; i < n; i++) free(ctrls[i]); free(ctrls); free_subysynqn: free(item->subsysnqn); free(item->name); return 1; } static int scan_subsys_filter(const struct dirent *d) { char path[310]; struct stat ss; int id; int tmp; if (d->d_name[0] == '.') return 0; /* sanity checking, probably unneeded */ if (strstr(d->d_name, "nvme-subsys")) { snprintf(path, sizeof(path), "%s%s", subsys_dir, d->d_name); if (stat(path, &ss)) return 0; if (!S_ISDIR(ss.st_mode)) return 0; tmp = sscanf(d->d_name, "nvme-subsys%d", &id); if (tmp != 1) return 0; return 1; } return 0; } static void free_subsys_list_item(struct subsys_list_item *item) { int i; for (i = 0; i < item->nctrls; i++) { free(item->ctrls[i].name); free(item->ctrls[i].transport); free(item->ctrls[i].address); } free(item->ctrls); free(item->subsysnqn); free(item->name); } static void free_subsys_list(struct subsys_list_item *slist, int n) { int i; for (i = 0; i < n; i++) free_subsys_list_item(&slist[i]); free(slist); } static int list_subsys(int argc, char **argv, struct command *cmd, struct plugin *plugin) { char path[310]; struct dirent **subsys; struct subsys_list_item *slist; int fmt, n, i, ret = 0; const char *desc = "Retrieve information for subsystems"; struct config { char *output_format; }; struct config cfg = { .output_format = "normal", }; const struct argconfig_commandline_options opts[] = { {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, "Output Format: normal|json"}, {NULL} }; ret = argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg)); if (ret < 0) return ret; fmt = validate_output_format(cfg.output_format); if (fmt != JSON && fmt != NORMAL) return -EINVAL; n = scandir(subsys_dir, &subsys, scan_subsys_filter, alphasort); if (n < 0) { fprintf(stderr, "no NVMe subsystem(s) detected.\n"); return n; } slist = calloc(n, sizeof(struct subsys_list_item)); if (!slist) { ret = ENOMEM; goto free_subsys; } for (i = 0; i < n; i++) { snprintf(path, sizeof(path), "%s%s", subsys_dir, subsys[i]->d_name); ret = get_nvme_subsystem_info(subsys[i]->d_name, path, &slist[i]); if (ret) goto free_subsys; } if (fmt == JSON) json_print_nvme_subsystem_list(slist, n); else print_nvme_subsystem_list(slist, n); free_subsys: free_subsys_list(slist, n); for (i = 0; i < n; i++) free(subsys[i]); free(subsys); return ret; } static void print_list_item(struct list_item list_item) { long long int lba = 1 << list_item.ns.lbaf[(list_item.ns.flbas & 0x0f)].ds; double nsze = le64_to_cpu(list_item.ns.nsze) * lba; double nuse = le64_to_cpu(list_item.ns.nuse) * lba; const char *s_suffix = suffix_si_get(&nsze); const char *u_suffix = suffix_si_get(&nuse); const char *l_suffix = suffix_binary_get(&lba); char usage[128]; char format[128]; sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix); sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix, list_item.ns.lbaf[(list_item.ns.flbas & 0x0f)].ms); printf("%-16s %-*.*s %-*.*s %-9d %-26s %-16s %-.*s\n", list_item.node, (int)sizeof(list_item.ctrl.sn), (int)sizeof(list_item.ctrl.sn), list_item.ctrl.sn, (int)sizeof(list_item.ctrl.mn), (int)sizeof(list_item.ctrl.mn), list_item.ctrl.mn, list_item.nsid, usage, format, (int)sizeof(list_item.ctrl.fr), list_item.ctrl.fr); } static void print_list_items(struct list_item *list_items, unsigned len) { unsigned i; printf("%-16s %-20s %-40s %-9s %-26s %-16s %-8s\n", "Node", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev"); printf("%-16s %-20s %-40s %-9s %-26s %-16s %-8s\n", "----------------", "--------------------", "----------------------------------------", "---------", "--------------------------", "----------------", "--------"); for (i = 0 ; i < len ; i++) print_list_item(list_items[i]); } static int get_nvme_info(int fd, struct list_item *item, const char *node) { int err; err = nvme_identify_ctrl(fd, &item->ctrl); if (err) return err; item->nsid = nvme_get_nsid(fd); err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); if (err) return err; strcpy(item->node, node); item->block = S_ISBLK(nvme_stat.st_mode); return 0; } static const char *dev = "/dev/"; /* Assume every block device starting with /dev/nvme is an nvme namespace */ static int scan_dev_filter(const struct dirent *d) { char path[264]; struct stat bd; int ctrl, ns, part; if (d->d_name[0] == '.') return 0; if (strstr(d->d_name, "nvme")) { snprintf(path, sizeof(path), "%s%s", dev, d->d_name); if (stat(path, &bd)) return 0; if (!S_ISBLK(bd.st_mode)) return 0; if (sscanf(d->d_name, "nvme%dn%dp%d", &ctrl, &ns, &part) == 3) return 0; return 1; } return 0; } static int list(int argc, char **argv, struct command *cmd, struct plugin *plugin) { char path[264]; struct dirent **devices; struct list_item *list_items; unsigned int i, n; int fmt, ret, fd; const char *desc = "Retrieve basic information for the given device"; struct config { char *output_format; }; struct config cfg = { .output_format = "normal", }; const struct argconfig_commandline_options opts[] = { {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, "Output Format: normal|json"}, {NULL} }; ret = argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg)); if (ret < 0) return ret; fmt = validate_output_format(cfg.output_format); if (fmt != JSON && fmt != NORMAL) return -EINVAL; n = scandir(dev, &devices, scan_dev_filter, alphasort); if (n < 0) { fprintf(stderr, "no NVMe device(s) detected.\n"); return n; } list_items = calloc(n, sizeof(*list_items)); if (!list_items) { fprintf(stderr, "can not allocate controller list payload\n"); return ENOMEM; } for (i = 0; i < n; i++) { snprintf(path, sizeof(path), "%s%s", dev, devices[i]->d_name); fd = open(path, O_RDONLY); if (fd < 0) { fprintf(stderr, "can not open %s: %s\n", path, strerror(errno)); return errno; } ret = get_nvme_info(fd, &list_items[i], path); close(fd); if (ret) return ret; } if (fmt == JSON) json_print_list_items(list_items, n); else print_list_items(list_items, n); for (i = 0; i < n; i++) free(devices[i]); free(devices); free(list_items); return 0; } static int get_nsid(int fd) { int nsid = nvme_get_nsid(fd); if (nsid <= 0) { fprintf(stderr, "%s: failed to return namespace id\n", devicename); return errno; } return nsid; } int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, void (*vs)(__u8 *vs, struct json_object *root)) { const char *desc = "Send an Identify Controller command to "\ "the given device and report information about the specified "\ "controller in human-readable or "\ "binary format. May also return vendor-specific "\ "controller attributes in hex-dump if requested."; const char *vendor_specific = "dump binary vendor infos"; const char *raw_binary = "show infos in binary format"; const char *human_readable = "show infos in readable format"; int err, fmt, fd; unsigned int flags = 0; struct nvme_id_ctrl ctrl; struct config { int vendor_specific; int raw_binary; int human_readable; char *output_format; }; struct config cfg = { .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"vendor-specific", 'v', "", CFG_NONE, &cfg.vendor_specific, no_argument, vendor_specific}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"human-readable", 'H', "", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; if (cfg.raw_binary) { fprintf(stderr, "binary output\n"); fmt = BINARY; } if (cfg.vendor_specific) flags |= VS; if (cfg.human_readable) flags |= HUMAN; err = nvme_identify_ctrl(fd, &ctrl); if (!err) { if (fmt == BINARY) d_raw((unsigned char *)&ctrl, sizeof(ctrl)); else if (fmt == JSON) json_nvme_id_ctrl(&ctrl, flags, vs); else { printf("NVME Identify Controller:\n"); __show_nvme_id_ctrl(&ctrl, flags, vs); } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); else perror("identify controller"); return err; } static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return __id_ctrl(argc, argv, cmd, plugin, NULL); } static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send Namespace Identification Descriptors command to the "\ "given device, returns the namespace identifcation descriptors "\ "of the specific namespace in either human-readable or binary format."; const char *raw_binary = "show infos in binary format"; const char *namespace_id = "identifier of desired namespace"; int err, fmt, fd; char *nsdescs[0x1000] = { }; struct config { __u32 namespace_id; int raw_binary; char *output_format; }; struct config cfg = { .namespace_id = 0, .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, {NULL} }; if (posix_memalign((void *)&nsdescs, getpagesize(), 0x1000)) { fprintf(stderr, "can not allocate controller list payload\n"); return ENOMEM; } fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; if (cfg.raw_binary) fmt = BINARY; if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); err = nvme_identify_ns_descs(fd, cfg.namespace_id, &nsdescs); if (!err) { if (fmt == BINARY) d_raw((unsigned char *)&nsdescs, 0x1000); else if (fmt == JSON) json_nvme_id_ns_descs(&nsdescs); else { printf("NVME Namespace Identification Descriptors NS %d:\n", cfg.namespace_id); show_nvme_id_ns_descs(&nsdescs); } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", nvme_status_to_string(err), err, cfg.namespace_id); else perror("identify namespace"); return err; } static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send an Identify Namespace command to the "\ "given device, returns properties of the specified namespace "\ "in either human-readable or binary format. Can also return "\ "binary vendor-specific namespace attributes."; const char *force = "Return this namespace, even if not attaced (1.2 devices only)"; const char *vendor_specific = "dump binary vendor infos"; const char *raw_binary = "show infos in binary format"; const char *human_readable = "show infos in readable format"; const char *namespace_id = "identifier of desired namespace"; struct nvme_id_ns ns; int err, fmt, fd; unsigned int flags = 0; struct config { __u32 namespace_id; int vendor_specific; int raw_binary; int human_readable; int force; char *output_format; }; struct config cfg = { .namespace_id = 0, .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"force", 'f', "", CFG_NONE, &cfg.force, no_argument, force}, {"vendor-specific", 'v', "", CFG_NONE, &cfg.vendor_specific, no_argument, vendor_specific}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"human-readable", 'H', "", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; if (cfg.raw_binary) fmt = BINARY; if (cfg.vendor_specific) flags |= VS; if (cfg.human_readable) flags |= HUMAN; if (!cfg.namespace_id && S_ISBLK(nvme_stat.st_mode)) cfg.namespace_id = get_nsid(fd); else if(!cfg.namespace_id) fprintf(stderr, "Error: requesting namespace-id from non-block device\n"); err = nvme_identify_ns(fd, cfg.namespace_id, cfg.force, &ns); if (!err) { if (fmt == BINARY) d_raw((unsigned char *)&ns, sizeof(ns)); else if (fmt == JSON) json_nvme_id_ns(&ns, flags); else { printf("NVME Identify Namespace %d:\n", cfg.namespace_id); show_nvme_id_ns(&ns, flags); } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", nvme_status_to_string(err), err, cfg.namespace_id); else perror("identify namespace"); return err; } static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int nsid, fd; const char *desc = "Get namespce ID of a the block device."; const struct argconfig_commandline_options command_line_options[] = { {NULL}, }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; nsid = nvme_get_nsid(fd); if (nsid <= 0) { perror(devicename); return errno; } printf("%s: namespace-id:%d\n", devicename, nsid); return 0; } static int get_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Read operating parameters of the "\ "specified controller. Operating parameters are grouped "\ "and identified by Feature Identifiers; each Feature "\ "Identifier contains one or more attributes that may affect "\ "behaviour of the feature. Each Feature has three possible "\ "settings: default, saveable, and current. If a Feature is "\ "saveable, it may be modified by set-feature. Default values "\ "are vendor-specific and not changeable. Use set-feature to "\ "change saveable Features."; const char *raw_binary = "show infos in binary format"; const char *namespace_id = "identifier of desired namespace"; const char *feature_id = "hexadecimal feature name"; const char *sel = "[0-3]: current/default/saved/supported"; const char *data_len = "buffer len if data is returned through host memory buffer"; const char *cdw11 = "dword 11 for interrupt vector config"; const char *human_readable = "show infos in readable format"; int err, fd; __u32 result; void *buf = NULL; struct config { __u32 namespace_id; __u32 feature_id; __u8 sel; __u32 cdw11; __u32 data_len; int raw_binary; int human_readable; }; struct config cfg = { .namespace_id = 1, .feature_id = 0, .sel = 0, .cdw11 = 0, .data_len = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"feature-id", 'f', "NUM", CFG_POSITIVE, &cfg.feature_id, required_argument, feature_id}, {"sel", 's', "NUM", CFG_BYTE, &cfg.sel, required_argument, sel}, {"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"cdw11", 'c', "NUM", CFG_POSITIVE, &cfg.cdw11, required_argument, cdw11}, {"human-readable", 'H', "", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.sel > 7) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); return EINVAL; } if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); return EINVAL; } switch (cfg.feature_id) { case NVME_FEAT_LBA_RANGE: cfg.data_len = 4096; break; case NVME_FEAT_AUTO_PST: cfg.data_len = 256; break; case NVME_FEAT_HOST_MEM_BUF: cfg.data_len = 4096; break; case NVME_FEAT_HOST_ID: cfg.data_len = 8; /* check for Extended Host Identifier */ if (cfg.cdw11 & 0x1) cfg.data_len = 16; break; } if (cfg.sel == 3) cfg.data_len = 0; if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); return ENOMEM; } memset(buf, 0, cfg.data_len); } err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11, cfg.data_len, buf, &result); if (!err) { if (!cfg.raw_binary || !buf) { printf("get-feature:%#02x (%s), %s value:%#08x\n", cfg.feature_id, nvme_feature_to_string(cfg.feature_id), nvme_select_to_string(cfg.sel), result); if (cfg.human_readable) nvme_feature_show_fields(cfg.feature_id, result, buf); if (buf) d(buf, cfg.data_len, 16, 1); } else if (buf) d_raw(buf, cfg.data_len); } else if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); } else perror("get-feature"); if (buf) free(buf); return err; } static int fw_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Copy all or part of a firmware image to "\ "a controller for future update. Optionally, specify how "\ "many KiB of the firmware to transfer at once. The offset will "\ "start at 0 and automatically adjust based on xfer size "\ "unless fw is split across multiple files. May be submitted "\ "while outstanding commands exist on the Admin and IO "\ "Submission Queues. Activate downloaded firmware with "\ "fw-activate, and then reset the device to apply the downloaded firmware."; const char *fw = "firmware file (required)"; const char *xfer = "transfer chunksize limit"; const char *offset = "starting dword offset, default 0"; int err, fd, fw_fd = -1; unsigned int fw_size; struct stat sb; void *fw_buf; struct config { char *fw; __u32 xfer; __u32 offset; }; struct config cfg = { .fw = "", .xfer = 4096, .offset = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"fw", 'f', "FILE", CFG_STRING, &cfg.fw, required_argument, fw}, {"xfer", 'x', "NUM", CFG_POSITIVE, &cfg.xfer, required_argument, xfer}, {"offset", 'o', "NUM", CFG_POSITIVE, &cfg.offset, required_argument, offset}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fw_fd = open(cfg.fw, O_RDONLY); cfg.offset <<= 2; if (fw_fd < 0) { fprintf(stderr, "no firmware file provided\n"); return EINVAL; } err = fstat(fw_fd, &sb); if (err < 0) { perror("fstat"); return errno; } fw_size = sb.st_size; if (fw_size & 0x3) { fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size); return EINVAL; } if (posix_memalign(&fw_buf, getpagesize(), fw_size)) { fprintf(stderr, "No memory for f/w size:%d\n", fw_size); return ENOMEM; } if (cfg.xfer == 0 || cfg.xfer % 4096) cfg.xfer = 4096; if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size))) return EIO; while (fw_size > 0) { cfg.xfer = min(cfg.xfer, fw_size); err = nvme_fw_download(fd, cfg.offset, cfg.xfer, fw_buf); if (err < 0) { perror("fw-download"); break; } else if (err != 0) { fprintf(stderr, "NVME Admin command error:%s(%x)\n", nvme_status_to_string(err), err); break; } fw_buf += cfg.xfer; fw_size -= cfg.xfer; cfg.offset += cfg.xfer; } if (!err) printf("Firmware download success\n"); return err; } static char *nvme_fw_status_reset_type(__u32 status) { switch (status & 0x3ff) { case NVME_SC_FW_NEEDS_CONV_RESET: return "conventional"; case NVME_SC_FW_NEEDS_SUBSYS_RESET: return "subsystem"; case NVME_SC_FW_NEEDS_RESET: return "any controller"; default: return "unknown"; } } static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Verify downloaded firmware image and "\ "commit to specific firmware slot. Device is not automatically "\ "reset following firmware activation. A reset may be issued "\ "with an 'echo 1 > /sys/class/nvme/nvmeX/reset_controller'. "\ "Ensure nvmeX is the device you just activated before reset."; const char *slot = "[0-7]: firmware slot for commit action"; const char *action = "[0-7]: commit action"; const char *bpid = "[0,1]: boot partition identifier, if applicable (default: 0)"; int err, fd; struct config { __u8 slot; __u8 action; __u8 bpid; }; struct config cfg = { .slot = 0, .action = 0, .bpid = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"slot", 's', "NUM", CFG_BYTE, &cfg.slot, required_argument, slot}, {"action", 'a', "NUM", CFG_BYTE, &cfg.action, required_argument, action}, {"bpid", 'b', "NUM", CFG_BYTE, &cfg.bpid, required_argument, bpid}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.slot > 7) { fprintf(stderr, "invalid slot:%d\n", cfg.slot); return EINVAL; } if (cfg.action > 7 || cfg.action == 4 || cfg.action == 5) { fprintf(stderr, "invalid action:%d\n", cfg.action); return EINVAL; } if (cfg.bpid > 1) { fprintf(stderr, "invalid boot partition id:%d\n", cfg.bpid); return EINVAL; } err = nvme_fw_commit(fd, cfg.slot, cfg.action, cfg.bpid); if (err < 0) perror("fw-commit"); else if (err != 0) switch (err & 0x3ff) { case NVME_SC_FW_NEEDS_CONV_RESET: case NVME_SC_FW_NEEDS_SUBSYS_RESET: case NVME_SC_FW_NEEDS_RESET: printf("Success activating firmware action:%d slot:%d", cfg.action, cfg.slot); if (cfg.action == 6 || cfg.action == 7) printf(" bpid:%d", cfg.bpid); printf(", but firmware requires %s reset\n", nvme_fw_status_reset_type(err)); break; default: fprintf(stderr, "NVME Admin command error:%s(%x)\n", nvme_status_to_string(err), err); break; } else { printf("Success committing firmware action:%d slot:%d", cfg.action, cfg.slot); if (cfg.action == 6 || cfg.action == 7) printf(" bpid:%d", cfg.bpid); printf("\n"); } return err; } static int subsystem_reset(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Resets the NVMe subsystem\n"; int err, fd; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; err = nvme_subsystem_reset(fd); if (err < 0) { perror("Subsystem-reset"); return errno; } return err; } static int reset(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Resets the NVMe controller\n"; int err, fd; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; err = nvme_reset_controller(fd); if (err < 0) { perror("Reset"); return errno; } return err; } static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Rescans the NVMe namespaces\n"; int err, fd; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; err = nvme_ns_rescan(fd); if (err < 0) { perror("Namespace Rescan"); return errno; } return err; } static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *plugin) { char *desc = "Send a sanitize command."; char *no_dealloc_desc = "No deallocate after sanitize."; char *oipbp_desc = "Overwrite invert pattern between passes."; char *owpass_desc = "Overwrite pass count."; char *ause_desc = "Allow unrestricted sanitize exit."; char *sanact_desc = "Sanitize action."; char *ovrpat_desc = "Overwrite pattern."; int fd; int ret; __u32 sanitize_cdw10 = 0; __u32 sanitize_cdw11 = 0; struct nvme_passthru_cmd admin_cmd; struct config { int no_dealloc; int oipbp; __u8 owpass; int ause; __u8 sanact; __u32 ovrpat; }; struct config cfg = { .no_dealloc = 0, .oipbp = 0, .owpass = 1, .ause = 0, .sanact = 0, .ovrpat = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"no-dealloc", 'd', "", CFG_NONE, &cfg.no_dealloc, no_argument, no_dealloc_desc}, {"oipbp", 'i', "", CFG_NONE, &cfg.oipbp, no_argument, oipbp_desc}, {"owpass", 'n', "NUM", CFG_BYTE, &cfg.owpass, required_argument, owpass_desc}, {"ause", 'u', "", CFG_NONE, &cfg.ause, no_argument, ause_desc}, {"sanact", 'a', "NUM", CFG_BYTE, &cfg.sanact, required_argument, sanact_desc}, {"ovrpat", 'p', "NUM", CFG_POSITIVE, &cfg.ovrpat, required_argument, ovrpat_desc}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; switch (cfg.sanact) { case NVME_SANITIZE_ACT_CRYPTO_ERASE: case NVME_SANITIZE_ACT_BLOCK_ERASE: case NVME_SANITIZE_ACT_EXIT: sanitize_cdw10 = cfg.sanact; break; case NVME_SANITIZE_ACT_OVERWRITE: sanitize_cdw10 = cfg.sanact; sanitize_cdw11 = cfg.ovrpat; break; default: fprintf(stderr, "Invalid Sanitize Action\n"); return -1; } if (cfg.sanact != NVME_SANITIZE_ACT_EXIT && cfg.ause) sanitize_cdw10 |= NVME_SANITIZE_AUSE; if (cfg.sanact == NVME_SANITIZE_ACT_OVERWRITE) { if (cfg.owpass >= 0 && cfg.owpass <= 16) { sanitize_cdw10 |= (cfg.owpass << NVME_SANITIZE_OWPASS_SHIFT); } else { fprintf(stderr, "owpass out of range [0-16] or sanitize action is not set to overwrite\n"); return -1; } if (cfg.oipbp) sanitize_cdw10 |= NVME_SANITIZE_OIPBP; } if (cfg.sanact != NVME_SANITIZE_ACT_EXIT && cfg.no_dealloc) sanitize_cdw10 |= NVME_SANITIZE_NO_DEALLOC; memset(&admin_cmd, 0, sizeof (admin_cmd)); admin_cmd.opcode = nvme_admin_sanitize_nvm; admin_cmd.cdw10 = sanitize_cdw10; admin_cmd.cdw11 = sanitize_cdw11; ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; } static int show_registers(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Reads and shows the defined NVMe controller registers "\ "in binary or human-readable format"; const char *human_readable = "show info in readable format"; void *bar; int fd, err; bool fabrics = true; struct config { int human_readable; }; struct config cfg = { .human_readable = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"human-readable", 'H', "", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; err = nvme_get_properties(fd, &bar); if (err) { bar = get_registers(); fabrics = false; } if (!bar) return ENODEV; show_ctrl_registers(bar, cfg.human_readable ? HUMAN : 0, fabrics); if (fabrics) free(bar); return 0; } static int set_property(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Writes and shows the defined NVMe controller property "\ "for NVMe ove Fabric"; const char *offset = "the offset of the property"; const char *value = "the value of the property to be set"; int fd, err; struct config { int offset; int value; }; struct config cfg = { .offset = -1, .value = -1, }; const struct argconfig_commandline_options command_line_options[] = { {"offset", 'o', "NUM", CFG_POSITIVE, &cfg.offset, required_argument, offset}, {"value", 'v', "NUM", CFG_POSITIVE, &cfg.value, required_argument, value}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.offset == -1) { fprintf(stderr, "offset required param"); return EINVAL; } if (cfg.value == -1) { fprintf(stderr, "value required param"); return EINVAL; } err = nvme_set_property(fd, cfg.offset, cfg.value); if (err < 0) { perror("set-property"); return errno; } else if (!err) { printf("set-property: %02x (%s), value: %#08x\n", cfg.offset, nvme_register_to_string(cfg.offset), cfg.value); } else if (err > 0) { fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err), err); } return err; } static int format(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Re-format a specified namespace on the "\ "given device. Can erase all data in namespace (user "\ "data erase) or delete data encryption key if specified. "\ "Can also be used to change LBAF to change the namespaces reported physical block format."; const char *namespace_id = "identifier of desired namespace"; const char *lbaf = "LBA format to apply (required)"; const char *ses = "[0-2]: secure erase"; const char *pil = "[0-1]: protection info location last/first 8 bytes of metadata"; const char *pi = "[0-3]: protection info off/Type 1/Type 2/Type 3"; const char *ms = "[0-1]: extended format off/on"; const char *reset = "Automatically reset the controller after successful format"; const char *timeout = "timeout value, in milliseconds"; struct nvme_id_ns ns; int err, fd; __u8 prev_lbaf = 0; struct config { __u32 namespace_id; __u32 timeout; __u8 lbaf; __u8 ses; __u8 pi; __u8 pil; __u8 ms; int reset; }; struct config cfg = { .namespace_id = NVME_NSID_ALL, .timeout = 600000, .lbaf = 0xff, .ses = 0, .pi = 0, .reset = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"timeout", 't', "NUM", CFG_POSITIVE, &cfg.timeout, required_argument, timeout}, {"lbaf", 'l', "NUM", CFG_BYTE, &cfg.lbaf, required_argument, lbaf}, {"ses", 's', "NUM", CFG_BYTE, &cfg.ses, required_argument, ses}, {"pi", 'i', "NUM", CFG_BYTE, &cfg.pi, required_argument, pi}, {"pil", 'p', "NUM", CFG_BYTE, &cfg.pil, required_argument, pil}, {"ms", 'm', "NUM", CFG_BYTE, &cfg.ms, required_argument, ms}, {"reset", 'r', "", CFG_NONE, &cfg.reset, no_argument, reset}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (S_ISBLK(nvme_stat.st_mode)) cfg.namespace_id = get_nsid(fd); if (cfg.namespace_id != NVME_NSID_ALL) { err = nvme_identify_ns(fd, cfg.namespace_id, 0, &ns); if (err) { if (err < 0) perror("identify-namespace"); else fprintf(stderr, "NVME Admin command error:%s(%x)\n", nvme_status_to_string(err), err); return err; } prev_lbaf = ns.flbas & 0xf; } if (cfg.lbaf == 0xff) cfg.lbaf = prev_lbaf; /* ses & pi checks set to 7 for forward-compatibility */ if (cfg.ses > 7) { fprintf(stderr, "invalid secure erase settings:%d\n", cfg.ses); return EINVAL; } if (cfg.lbaf > 15) { fprintf(stderr, "invalid lbaf:%d\n", cfg.lbaf); return EINVAL; } if (cfg.pi > 7) { fprintf(stderr, "invalid pi:%d\n", cfg.pi); return EINVAL; } if (cfg.pil > 1) { fprintf(stderr, "invalid pil:%d\n", cfg.pil); return EINVAL; } if (cfg.ms > 1) { fprintf(stderr, "invalid ms:%d\n", cfg.ms); return EINVAL; } err = nvme_format(fd, cfg.namespace_id, cfg.lbaf, cfg.ses, cfg.pi, cfg.pil, cfg.ms, cfg.timeout); if (err < 0) perror("format"); else if (err != 0) fprintf(stderr, "NVME Admin command error:%s(%x)\n", nvme_status_to_string(err), err); else { printf("Success formatting namespace:%x\n", cfg.namespace_id); ioctl(fd, BLKRRPART); if (cfg.reset && S_ISCHR(nvme_stat.st_mode)) nvme_reset_controller(fd); } return err; } static int set_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Modify the saveable or changeable "\ "current operating parameters of the controller. Operating "\ "parameters are grouped and identified by Feature "\ "Identifiers. Feature settings can be applied to the entire "\ "controller and all associated namespaces, or to only a few "\ "namespace(s) associated with the controller. Default values "\ "for each Feature are vendor-specific and may not be modified."\ "Use get-feature to determine which Features are supported by "\ "the controller and are saveable/changeable."; const char *namespace_id = "desired namespace"; const char *feature_id = "hex feature name (required)"; const char *data_len = "buffer length if data required"; const char *data = "optional file for feature data (default stdin)"; const char *value = "new value of feature (required)"; const char *save = "specifies that the controller shall save the attribute"; int err; __u32 result; void *buf = NULL; int fd, ffd = STDIN_FILENO; struct config { char *file; __u32 namespace_id; __u32 feature_id; __u32 value; __u32 data_len; int save; }; struct config cfg = { .file = "", .namespace_id = 0, .feature_id = 0, .value = 0, .data_len = 0, .save = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"feature-id", 'f', "NUM", CFG_POSITIVE, &cfg.feature_id, required_argument, feature_id}, {"value", 'v', "NUM", CFG_POSITIVE, &cfg.value, required_argument, value}, {"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len}, {"data", 'd', "FILE", CFG_STRING, &cfg.file, required_argument, data}, {"save", 's', "", CFG_NONE, &cfg.save, no_argument, save}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); return EINVAL; } if (cfg.feature_id == NVME_FEAT_LBA_RANGE) cfg.data_len = 4096; if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); return ENOMEM; } memset(buf, 0, cfg.data_len); } if (buf) { if (strlen(cfg.file)) { ffd = open(cfg.file, O_RDONLY); if (ffd <= 0) { fprintf(stderr, "no firmware file provided\n"); return -EINVAL; } } if (read(ffd, (void *)buf, cfg.data_len) < 0) { fprintf(stderr, "failed to read data buffer from input file\n"); return EINVAL; } } err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, cfg.save, cfg.data_len, buf, &result); if (err < 0) { perror("set-feature"); return errno; } else if (!err) { printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, nvme_feature_to_string(cfg.feature_id), cfg.value); if (buf) { if (cfg.feature_id == NVME_FEAT_LBA_RANGE) show_lba_range((struct nvme_lba_range_type *)buf, result); else d(buf, cfg.data_len, 16, 1); } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); if (buf) free(buf); return err; } static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct stat sb; const char *desc = "Transfer security protocol data to "\ "a controller. Security Receives for the same protocol should be "\ "performed after Security Sends. The security protocol field "\ "associates Security Sends (security-send) and Security Receives "\ "(security-recv)."; const char *file = "transfer payload"; const char *secp = "security protocol (cf. SPC-4)"; const char *spsp = "security-protocol-specific (cf. SPC-4)"; const char *tl = "transfer length (cf. SPC-4)"; const char *namespace_id = "desired namespace"; const char *nssf = "NVMe Security Specific Field"; int err, fd, sec_fd = -1; void *sec_buf; unsigned int sec_size; __u32 result; struct config { __u32 namespace_id; char *file; __u8 nssf; __u8 secp; __u16 spsp; __u32 tl; }; struct config cfg = { .file = "", .secp = 0, .spsp = 0, .tl = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"file", 'f', "FILE", CFG_STRING, &cfg.file, required_argument, file}, {"nssf", 'N', "NUM", CFG_BYTE, &cfg.nssf, required_argument, nssf}, {"secp", 'p', "NUM", CFG_BYTE, &cfg.secp, required_argument, secp}, {"spsp", 's', "NUM", CFG_SHORT, &cfg.spsp, required_argument, spsp}, {"tl", 't', "NUM", CFG_POSITIVE, &cfg.tl, required_argument, tl}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; sec_fd = open(cfg.file, O_RDONLY); if (sec_fd < 0) { fprintf(stderr, "no firmware file provided\n"); return EINVAL; } err = fstat(sec_fd, &sb); if (err < 0) { perror("fstat"); return errno; } sec_size = sb.st_size; if (posix_memalign(&sec_buf, getpagesize(), sec_size)) { fprintf(stderr, "No memory for security size:%d\n", sec_size); return ENOMEM; } if (read(sec_fd, sec_buf, sec_size) < 0) { fprintf(stderr, "Failed to read data from security file with %s\n", strerror(errno)); return EINVAL; } err = nvme_sec_send(fd, cfg.namespace_id, cfg.nssf, cfg.spsp, cfg.secp, cfg.tl, sec_size, sec_buf, &result); if (err < 0) perror("security-send"); else if (err != 0) fprintf(stderr, "NVME Security Send Command Error:%d\n", err); else printf("NVME Security Send Command Success:%d\n", result); return err; } static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Set directive parameters of the "\ "specified directive type."; const char *raw_binary = "show infos in binary format"; const char *namespace_id = "identifier of desired namespace"; const char *data_len = "buffer len (if) data is returned"; const char *dtype = "directive type"; const char *dspec = "directive specification associated with directive type"; const char *doper = "directive operation"; const char *endir = "directive enable"; const char *ttype = "target directive type to be enabled/disabled"; const char *human_readable = "show infos in readable format"; int err, fd; __u32 result; __u32 dw12 = 0; void *buf = NULL; int ffd = STDIN_FILENO; struct config { char *file; __u32 namespace_id; __u32 data_len; __u16 dspec; __u8 dtype; __u8 doper; __u16 endir; __u8 ttype; int raw_binary; int human_readable; }; struct config cfg = { .file = "", .namespace_id = 1, .data_len = 0, .dspec = 0, .dtype = 0, .ttype = 0, .doper = 0, .endir = 1, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len}, {"raw-binary", 'b', "FLAG",CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"dir-type", 'D', "NUM", CFG_BYTE, &cfg.dtype, required_argument, dtype}, {"target-dir", 'T', "NUM", CFG_BYTE, &cfg.ttype, required_argument, ttype}, {"dir-spec", 'S', "NUM", CFG_SHORT, &cfg.dspec, required_argument, dspec}, {"dir-oper", 'O', "NUM", CFG_BYTE, &cfg.doper, required_argument, doper}, {"endir", 'e', "NUM", CFG_SHORT, &cfg.endir, required_argument, endir}, {"human-readable", 'H', "FLAG",CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; switch (cfg.dtype) { case NVME_DIR_IDENTIFY: switch (cfg.doper) { case NVME_DIR_SND_ID_OP_ENABLE: if (!cfg.ttype) { fprintf(stderr, "target-dir required param\n"); return EINVAL; } dw12 = cfg.ttype << 8 | cfg.endir; break; default: fprintf(stderr, "invalid directive operations for Identify Directives\n"); return EINVAL; } break; case NVME_DIR_STREAMS: switch (cfg.doper) { case NVME_DIR_SND_ST_OP_REL_ID: case NVME_DIR_SND_ST_OP_REL_RSC: break; default: fprintf(stderr, "invalid directive operations for Streams Directives\n"); return EINVAL; } break; default: fprintf(stderr, "invalid directive type\n"); return EINVAL; break; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) exit(ENOMEM); memset(buf, 0, cfg.data_len); } if (buf) { if (strlen(cfg.file)) { ffd = open(cfg.file, O_RDONLY); if (ffd <= 0) { fprintf(stderr, "no firmware file provided\n"); return -EINVAL; } } if (read(ffd, (void *)buf, cfg.data_len) < 0) { fprintf(stderr, "failed to read data buffer from input file\n"); return EINVAL; } } err = nvme_dir_send(fd, cfg.namespace_id, cfg.dspec, cfg.dtype, cfg.doper, cfg.data_len, dw12, buf, &result); if (err < 0) { perror("dir-send"); return errno; } if (!err) { printf("dir-send: type %#x, operation %#x, spec_val %#x, nsid %#x, result %#x \n", cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, result); if (buf) { if (!cfg.raw_binary) d(buf, cfg.data_len, 16, 1); else d_raw(buf, cfg.data_len); } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); if (buf) free(buf); return err; } static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int err, fd; const char *desc = "The Write Uncorrectable command is used to set a "\ "range of logical blocks to invalid."; const char *namespace_id = "desired namespace"; const char *start_block = "64-bit LBA of first block to access"; const char *block_count = "number of blocks (zeroes based) on device to access"; struct config { __u64 start_block; __u32 namespace_id; __u16 block_count; }; struct config cfg = { .start_block = 0, .namespace_id = 0, .block_count = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"start-block", 's', "NUM", CFG_LONG_SUFFIX, &cfg.start_block, required_argument, start_block}, {"block-count", 'c', "NUM", CFG_SHORT, &cfg.block_count, required_argument, block_count}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); err = nvme_write_uncorrectable(fd, cfg.namespace_id, cfg.start_block, cfg.block_count); if (err < 0) perror("write uncorrectable"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else printf("NVME Write Uncorrectable Success\n"); return err; } static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int err, fd; __u16 control = 0; const char *desc = "The Write Zeroes command is used to set a "\ "range of logical blocks to zero."; const char *namespace_id = "desired namespace"; const char *start_block = "64-bit LBA of first block to access"; const char *block_count = "number of blocks (zeroes based) on device to access"; const char *limited_retry = "limit media access attempts"; const char *force = "force device to commit data before command completes"; const char *prinfo = "PI and check field"; const char *ref_tag = "reference tag (for end to end PI)"; const char *app_tag_mask = "app tag mask (for end to end PI)"; const char *app_tag = "app tag (for end to end PI)"; const char *deac = "Set DEAC bit, requesting controller to deallocate specified logical blocks"; struct config { __u64 start_block; __u32 namespace_id; __u32 ref_tag; __u16 app_tag; __u16 app_tag_mask; __u16 block_count; __u8 prinfo; int deac; int limited_retry; int force_unit_access; }; struct config cfg = { .start_block = 0, .block_count = 0, .prinfo = 0, .ref_tag = 0, .app_tag_mask = 0, .app_tag = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"start-block", 's', "NUM", CFG_LONG_SUFFIX, &cfg.start_block, required_argument, start_block}, {"block-count", 'c', "NUM", CFG_SHORT, &cfg.block_count, required_argument, block_count}, {"deac", 'd', "", CFG_NONE, &cfg.deac, no_argument, deac}, {"limited-retry", 'l', "", CFG_NONE, &cfg.limited_retry, no_argument, limited_retry}, {"force-unit-access", 'f', "", CFG_NONE, &cfg.force_unit_access, no_argument, force}, {"prinfo", 'p', "NUM", CFG_BYTE, &cfg.prinfo, required_argument, prinfo}, {"ref-tag", 'r', "NUM", CFG_POSITIVE, &cfg.ref_tag, required_argument, ref_tag}, {"app-tag-mask", 'm', "NUM", CFG_SHORT, &cfg.app_tag_mask, required_argument, app_tag_mask}, {"app-tag", 'a', "NUM", CFG_SHORT, &cfg.app_tag, required_argument, app_tag}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.prinfo > 0xf) return EINVAL; control |= (cfg.prinfo << 10); if (cfg.limited_retry) control |= NVME_RW_LR; if (cfg.force_unit_access) control |= NVME_RW_FUA; if (cfg.deac) control |= NVME_RW_DEAC; if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); err = nvme_write_zeros(fd, cfg.namespace_id, cfg.start_block, cfg.block_count, control, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask); if (err < 0) perror("write-zeroes"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else printf("NVME Write Zeroes Success\n"); return err; } static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "The Dataset Management command is used by the host to "\ "indicate attributes for ranges of logical blocks. This includes attributes "\ "for discarding unused blocks, data read and write frequency, access size, and other "\ "information that may be used to optimize performance and reliability."; const char *namespace_id = "identifier of desired namespace"; const char *blocks = "Comma separated list of the number of blocks in each range"; const char *starting_blocks = "Comma separated list of the starting block in each range"; const char *context_attrs = "Comma separated list of the context attributes in each range"; const char *ad = "Attribute Deallocate"; const char *idw = "Attribute Integral Dataset for Write"; const char *idr = "Attribute Integral Dataset for Read"; const char *cdw11 = "All the command DWORD 11 attributes. Use instead of specifying individual attributes"; int err, fd; uint16_t nr, nc, nb, ns; int ctx_attrs[256] = {0,}; int nlbs[256] = {0,}; unsigned long long slbas[256] = {0,}; struct nvme_dsm_range *dsm; struct config { char *ctx_attrs; char *blocks; char *slbas; int ad; int idw; int idr; __u32 cdw11; __u32 namespace_id; }; struct config cfg = { .ctx_attrs = "", .blocks = "", .slbas = "", .namespace_id = 0, .ad = 0, .idw = 0, .idr = 0, .cdw11 = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"ctx-attrs", 'a', "LIST", CFG_STRING, &cfg.ctx_attrs, required_argument, context_attrs}, {"blocks", 'b', "LIST", CFG_STRING, &cfg.blocks, required_argument, blocks}, {"slbs", 's', "LIST", CFG_STRING, &cfg.slbas, required_argument, starting_blocks}, {"ad", 'd', "", CFG_NONE, &cfg.ad, no_argument, ad}, {"idw", 'w', "", CFG_NONE, &cfg.idw, no_argument, idw}, {"idr", 'r', "", CFG_NONE, &cfg.idr, no_argument, idr}, {"cdw11", 'c', "NUM", CFG_POSITIVE, &cfg.cdw11, required_argument, cdw11}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, ctx_attrs, array_len(ctx_attrs)); nb = argconfig_parse_comma_sep_array(cfg.blocks, nlbs, array_len(nlbs)); ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, array_len(slbas)); nr = max(nc, max(nb, ns)); if (!nr || nr > 256) { fprintf(stderr, "No range definition provided\n"); return EINVAL; } if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); if (!cfg.cdw11) cfg.cdw11 = (cfg.ad << 2) | (cfg.idw << 1) | (cfg.idr << 0); dsm = nvme_setup_dsm_range((__u32 *)ctx_attrs, (__u32 *)nlbs, (__u64 *)slbas, nr); if (!dsm) { fprintf(stderr, "failed to allocate data set payload\n"); return ENOMEM; } err = nvme_dsm(fd, cfg.namespace_id, cfg.cdw11, dsm, nr); if (err < 0) perror("data-set management"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else printf("NVMe DSM: success\n"); return err; } static int flush(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Commit data and metadata associated with "\ "given namespaces to nonvolatile media. Applies to all commands "\ "finished before the flush was submitted. Additional data may also be "\ "flushed by the controller, from any namespace, depending on controller and "\ "associated namespace status."; const char *namespace_id = "identifier of desired namespace"; int err, fd; struct config { __u32 namespace_id; }; struct config cfg = { .namespace_id = NVME_NSID_ALL, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; err = nvme_flush(fd, cfg.namespace_id); if (err < 0) perror("flush"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else printf("NVMe Flush: success\n"); close(fd); return err; } static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Obtain a reservation on a given "\ "namespace. Only one reservation is allowed at a time on a "\ "given namespace, though multiple controllers may register "\ "with that namespace. Namespace reservation will abort with "\ "status Reservation Conflict if the given namespace is "\ "already reserved."; const char *namespace_id = "identifier of desired namespace"; const char *crkey = "current reservation key"; const char *prkey = "pre-empt reservation key"; const char *rtype = "hex reservation type"; const char *racqa = "reservation acquiry action"; const char *iekey = "ignore existing res. key"; int err, fd; struct config { __u32 namespace_id; __u64 crkey; __u64 prkey; __u8 rtype; __u8 racqa; int iekey; }; struct config cfg = { .namespace_id = 0, .crkey = 0, .prkey = 0, .rtype = 0, .racqa = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"crkey", 'c', "NUM", CFG_LONG_SUFFIX, &cfg.crkey, required_argument, crkey}, {"prkey", 'p', "NUM", CFG_LONG_SUFFIX, &cfg.prkey, required_argument, prkey}, {"rtype", 't', "NUM", CFG_BYTE, &cfg.rtype, required_argument, rtype}, {"racqa", 'a', "NUM", CFG_BYTE, &cfg.racqa, required_argument, racqa}, {"iekey", 'i', "", CFG_NONE, &cfg.iekey, no_argument, iekey}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); if (cfg.racqa > 7) { fprintf(stderr, "invalid racqa:%d\n", cfg.racqa); return EINVAL; } err = nvme_resv_acquire(fd, cfg.namespace_id, cfg.rtype, cfg.racqa, !!cfg.iekey, cfg.crkey, cfg.prkey); if (err < 0) perror("reservation acquire"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else printf("NVME Reservation Acquire success\n"); return err; } static int resv_register(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Register, de-register, or "\ "replace a controller's reservation on a given namespace. "\ "Only one reservation at a time is allowed on any namespace."; const char *namespace_id = "identifier of desired namespace"; const char *crkey = "current reservation key"; const char *iekey = "ignore existing res. key"; const char *nrkey = "new reservation key"; const char *rrega = "reservation registration action"; const char *cptpl = "change persistence through power loss setting"; int err, fd; struct config { __u32 namespace_id; __u64 crkey; __u64 nrkey; __u8 rrega; __u8 cptpl; int iekey; }; struct config cfg = { .namespace_id = 0, .crkey = 0, .nrkey = 0, .rrega = 0, .cptpl = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"crkey", 'c', "NUM", CFG_LONG_SUFFIX, &cfg.crkey, required_argument, crkey}, {"nrkey", 'k', "NUM", CFG_LONG_SUFFIX, &cfg.nrkey, required_argument, nrkey}, {"rrega", 'r', "NUM", CFG_BYTE, &cfg.rrega, required_argument, rrega}, {"cptpl", 'p', "NUM", CFG_BYTE, &cfg.cptpl, required_argument, cptpl}, {"iekey", 'i', "", CFG_NONE, &cfg.iekey, no_argument, iekey}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); if (cfg.cptpl > 3) { fprintf(stderr, "invalid cptpl:%d\n", cfg.cptpl); return EINVAL; } err = nvme_resv_register(fd, cfg.namespace_id, cfg.rrega, cfg.cptpl, !!cfg.iekey, cfg.crkey, cfg.nrkey); if (err < 0) perror("reservation register"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else printf("NVME Reservation success\n"); return err; } static int resv_release(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Releases reservation held on a "\ "namespace by the given controller. If rtype != current reservation"\ "type, release will fails. If the given controller holds no "\ "reservation on the namespace or is not the namespace's current "\ "reservation holder, the release command completes with no "\ "effect. If the reservation type is not Write Exclusive or "\ "Exclusive Access, all registrants on the namespace except "\ "the issuing controller are notified."; const char *namespace_id = "desired namespace"; const char *crkey = "current reservation key"; const char *iekey = "ignore existing res. key"; const char *rtype = "hex reservation type"; const char *rrela = "reservation release action"; int err, fd; struct config { __u32 namespace_id; __u64 crkey; __u8 rtype; __u8 rrela; __u8 iekey; }; struct config cfg = { .namespace_id = 0, .crkey = 0, .rtype = 0, .rrela = 0, .iekey = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"crkey", 'c', "NUM", CFG_LONG_SUFFIX, &cfg.crkey, required_argument, crkey}, {"rtype", 't', "NUM", CFG_BYTE, &cfg.rtype, required_argument, rtype}, {"rrela", 'a', "NUM", CFG_BYTE, &cfg.rrela, required_argument, rrela}, {"iekey", 'i', "NUM", CFG_BYTE, &cfg.iekey, required_argument, iekey}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); if (cfg.iekey > 1) { fprintf(stderr, "invalid iekey:%d\n", cfg.iekey); return EINVAL; } if (cfg.rrela > 7) { fprintf(stderr, "invalid rrela:%d\n", cfg.rrela); return EINVAL; } err = nvme_resv_release(fd, cfg.namespace_id, cfg.rtype, cfg.rrela, !!cfg.iekey, cfg.crkey); if (err < 0) perror("reservation release"); else if (err != 0) fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err); else printf("NVME Reservation Release success\n"); return err; } static int resv_report(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Returns Reservation Status data "\ "structure describing any existing reservations on and the "\ "status of a given namespace. Namespace Reservation Status "\ "depends on the number of controllers registered for that "\ "namespace."; const char *namespace_id = "identifier of desired namespace"; const char *numd = "number of dwords to transfer"; const char *cdw11 = "command dword 11 value"; const char *raw_binary = "dump output in binary format"; int err, fmt, fd; struct nvme_reservation_status *status; struct config { __u32 namespace_id; __u32 numd; __u32 cdw11; int raw_binary; char *output_format; }; struct config cfg = { .namespace_id = 0, .numd = 0, .cdw11 = 0, .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"numd", 'd', "NUM", CFG_POSITIVE, &cfg.numd, required_argument, numd}, {"cdw11", 'c', "NUM", CFG_POSITIVE, &cfg.cdw11, required_argument, cdw11}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; fmt = validate_output_format(cfg.output_format); if (fmt < 0) return fmt; if (cfg.raw_binary) fmt = BINARY; if (!cfg.namespace_id) cfg.namespace_id = get_nsid(fd); if (!cfg.numd || cfg.numd > (0x1000 >> 2)) cfg.numd = 0x1000 >> 2; if (cfg.numd < 3) cfg.numd = 3; /* get the header fields at least */ if (posix_memalign((void **)&status, getpagesize(), cfg.numd << 2)) { fprintf(stderr, "No memory for resv report:%d\n", cfg.numd << 2); return ENOMEM; } memset(status, 0, cfg.numd << 2); err = nvme_resv_report(fd, cfg.namespace_id, cfg.numd, cfg.cdw11, status); if (err < 0) perror("reservation report"); else if (err != 0) fprintf(stderr, "NVME IO command error:%04x\n", err); else { if (fmt == BINARY) d_raw((unsigned char *)status, cfg.numd << 2); else if (fmt == JSON) json_nvme_resv_report(status, cfg.numd << 2, cfg.cdw11); else { printf("NVME Reservation Report success\n"); show_nvme_resv_report(status, cfg.numd << 2, cfg.cdw11); } } free(status); return err; } static int submit_io(int opcode, char *command, const char *desc, int argc, char **argv) { struct timeval start_time, end_time; void *buffer, *mbuffer = NULL; int err = 0; int dfd, mfd, fd; int flags = opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT; int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; __u16 control = 0; __u32 dsmgmt = 0; int phys_sector_size = 0; long long buffer_size = 0; const char *start_block = "64-bit addr of first block to access"; const char *block_count = "number of blocks (zeroes based) on device to access"; const char *data_size = "size of data in bytes"; const char *metadata_size = "size of metadata in bytes"; const char *ref_tag = "reference tag (for end to end PI)"; const char *data = "data file"; const char *metadata = "metadata file"; const char *prinfo = "PI and check field"; const char *app_tag_mask = "app tag mask (for end to end PI)"; const char *app_tag = "app tag (for end to end PI)"; const char *limited_retry = "limit num. media access attempts"; const char *latency = "output latency statistics"; const char *force = "force device to commit data before command completes"; const char *show = "show command before sending"; const char *dry = "show command instead of sending"; const char *dtype = "directive type (for write-only)"; const char *dspec = "directive specific (for write-only)"; const char *dsm = "dataset management attributes (lower 16 bits)"; struct config { __u64 start_block; __u16 block_count; __u64 data_size; __u64 metadata_size; __u32 ref_tag; char *data; char *metadata; __u8 prinfo; __u8 dtype; __u16 dspec; __u16 dsmgmt; __u16 app_tag_mask; __u16 app_tag; int limited_retry; int force_unit_access; int show; int dry_run; int latency; }; struct config cfg = { .start_block = 0, .block_count = 0, .data_size = 0, .metadata_size = 0, .ref_tag = 0, .data = "", .metadata = "", .prinfo = 0, .app_tag_mask = 0, .app_tag = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"start-block", 's', "NUM", CFG_LONG_SUFFIX, &cfg.start_block, required_argument, start_block}, {"block-count", 'c', "NUM", CFG_SHORT, &cfg.block_count, required_argument, block_count}, {"data-size", 'z', "NUM", CFG_LONG_SUFFIX, &cfg.data_size, required_argument, data_size}, {"metadata-size", 'y', "NUM", CFG_LONG_SUFFIX, &cfg.metadata_size, required_argument, metadata_size}, {"ref-tag", 'r', "NUM", CFG_POSITIVE, &cfg.ref_tag, required_argument, ref_tag}, {"data", 'd', "FILE", CFG_STRING, &cfg.data, required_argument, data}, {"metadata", 'M', "FILE", CFG_STRING, &cfg.metadata, required_argument, metadata}, {"prinfo", 'p', "NUM", CFG_BYTE, &cfg.prinfo, required_argument, prinfo}, {"app-tag-mask", 'm', "NUM", CFG_SHORT, &cfg.app_tag_mask, required_argument, app_tag_mask}, {"app-tag", 'a', "NUM", CFG_SHORT, &cfg.app_tag, required_argument, app_tag}, {"limited-retry", 'l', "", CFG_NONE, &cfg.limited_retry, no_argument, limited_retry}, {"force-unit-access", 'f', "", CFG_NONE, &cfg.force_unit_access, no_argument, force}, {"dir-type", 'T', "NUM", CFG_BYTE, &cfg.dtype, required_argument, dtype}, {"dir-spec", 'S', "NUM", CFG_SHORT, &cfg.dspec, required_argument, dspec}, {"dsm", 'D', "NUM", CFG_SHORT, &cfg.dsmgmt, required_argument, dsm}, {"show-command", 'v', "", CFG_NONE, &cfg.show, no_argument, show}, {"dry-run", 'w', "", CFG_NONE, &cfg.dry_run, no_argument, dry}, {"latency", 't', "", CFG_NONE, &cfg.latency, no_argument, latency}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; dfd = mfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO; if (cfg.prinfo > 0xf) return EINVAL; dsmgmt = cfg.dsmgmt; control |= (cfg.prinfo << 10); if (cfg.limited_retry) control |= NVME_RW_LR; if (cfg.force_unit_access) control |= NVME_RW_FUA; if (cfg.dtype) { if (cfg.dtype > 0xf) { fprintf(stderr, "Invalid directive type, %x\n", cfg.dtype); return EINVAL; } control |= cfg.dtype << 4; dsmgmt |= ((__u32)cfg.dspec) << 16; } if (strlen(cfg.data)){ dfd = open(cfg.data, flags, mode); if (dfd < 0) { perror(cfg.data); return EINVAL; } mfd = dfd; } if (strlen(cfg.metadata)){ mfd = open(cfg.metadata, flags, mode); if (mfd < 0) { perror(cfg.metadata); return EINVAL; } } if (!cfg.data_size) { fprintf(stderr, "data size not provided\n"); return EINVAL; } if (ioctl(fd, BLKPBSZGET, &phys_sector_size) < 0) return errno; buffer_size = (cfg.block_count + 1) * phys_sector_size; if (cfg.data_size < buffer_size) { fprintf(stderr, "Rounding data size to fit block count (%lld bytes)\n", buffer_size); } else { buffer_size = cfg.data_size; } if (posix_memalign(&buffer, getpagesize(), buffer_size)) { fprintf(stderr, "can not allocate io payload\n"); return ENOMEM; } memset(buffer, 0, cfg.data_size); if (cfg.metadata_size) { mbuffer = malloc(cfg.metadata_size); if (!mbuffer) { free(buffer); fprintf(stderr, "can not allocate io metadata payload\n"); return ENOMEM; } } if ((opcode & 1) && read(dfd, (void *)buffer, cfg.data_size) < 0) { fprintf(stderr, "failed to read data buffer from input file\n"); err = EINVAL; goto free_and_return; } if ((opcode & 1) && cfg.metadata_size && read(mfd, (void *)mbuffer, cfg.metadata_size) < 0) { fprintf(stderr, "failed to read meta-data buffer from input file\n"); err = EINVAL; goto free_and_return; } if (cfg.show) { printf("opcode : %02x\n", opcode); printf("flags : %02x\n", 0); printf("control : %04x\n", control); printf("nblocks : %04x\n", cfg.block_count); printf("rsvd : %04x\n", 0); printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mbuffer); printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer); printf("sbla : %"PRIx64"\n", (uint64_t)cfg.start_block); printf("dsmgmt : %08x\n", dsmgmt); printf("reftag : %08x\n", cfg.ref_tag); printf("apptag : %04x\n", cfg.app_tag); printf("appmask : %04x\n", cfg.app_tag_mask); if (cfg.dry_run) goto free_and_return; } gettimeofday(&start_time, NULL); err = nvme_io(fd, opcode, cfg.start_block, cfg.block_count, control, dsmgmt, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask, buffer, mbuffer); gettimeofday(&end_time, NULL); if (cfg.latency) printf(" latency: %s: %llu us\n", command, elapsed_utime(start_time, end_time)); if (err < 0) perror("submit-io"); else if (err) printf("%s:%s(%04x)\n", command, nvme_status_to_string(err), err); else { if (!(opcode & 1) && write(dfd, (void *)buffer, cfg.data_size) < 0) { fprintf(stderr, "failed to write buffer to output file\n"); err = EINVAL; goto free_and_return; } else if (!(opcode & 1) && cfg.metadata_size && write(mfd, (void *)mbuffer, cfg.metadata_size) < 0) { fprintf(stderr, "failed to write meta-data buffer to output file\n"); err = EINVAL; goto free_and_return; } else fprintf(stderr, "%s: Success\n", command); } free_and_return: free(buffer); if (cfg.metadata_size) free(mbuffer); return err; } static int compare(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Compare specified logical blocks on "\ "device with specified data buffer; return failure if buffer "\ "and block(s) are dissimilar"; return submit_io(nvme_cmd_compare, "compare", desc, argc, argv); } static int read_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Copy specified logical blocks on the given "\ "device to specified data buffer (default buffer is stdout)."; return submit_io(nvme_cmd_read, "read", desc, argc, argv); } static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Copy from provided data buffer (default "\ "buffer is stdin) to specified logical blocks on the given "\ "device."; return submit_io(nvme_cmd_write, "write", desc, argc, argv); } static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Obtain results of one or more "\ "previously submitted security-sends. Results, and association "\ "between Security Send and Receive, depend on the security "\ "protocol field as they are defined by the security protocol "\ "used. A Security Receive must follow a Security Send made with "\ "the same security protocol."; const char *size = "size of buffer (prints to stdout on success)"; const char *secp = "security protocol (cf. SPC-4)"; const char *spsp = "security-protocol-specific (cf. SPC-4)"; const char *al = "allocation length (cf. SPC-4)"; const char *raw_binary = "dump output in binary format"; const char *namespace_id = "desired namespace"; const char *nssf = "NVMe Security Specific Field"; int err, fd; void *sec_buf = NULL; __u32 result; struct config { __u32 namespace_id; __u32 size; __u8 secp; __u8 nssf; __u16 spsp; __u32 al; int raw_binary; }; struct config cfg = { .size = 0, .secp = 0, .spsp = 0, .al = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"size", 'x', "NUM", CFG_POSITIVE, &cfg.size, required_argument, size}, {"nssf", 'N', "NUM", CFG_BYTE, &cfg.nssf, required_argument, nssf}, {"secp", 'p', "NUM", CFG_BYTE, &cfg.secp, required_argument, secp}, {"spsp", 's', "NUM", CFG_SHORT, &cfg.spsp, required_argument, spsp}, {"al", 't', "NUM", CFG_POSITIVE, &cfg.al, required_argument, al}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.size) { if (posix_memalign(&sec_buf, getpagesize(), cfg.size)) { fprintf(stderr, "No memory for security size:%d\n", cfg.size); return ENOMEM; } } err = nvme_sec_recv(fd, cfg.namespace_id, cfg.nssf, cfg.spsp, cfg.secp, cfg.al, cfg.size, sec_buf, &result); if (err < 0) perror("security receive"); else if (err != 0) fprintf(stderr, "NVME Security Receive Command Error:%d\n", err); else { if (!cfg.raw_binary) { printf("NVME Security Receive Command Success:%d\n", result); d(sec_buf, cfg.size, 16, 1); } else if (cfg.size) d_raw((unsigned char *)sec_buf, cfg.size); } return err; } static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Read directive parameters of the "\ "specified directive type."; const char *raw_binary = "show infos in binary format"; const char *namespace_id = "identifier of desired namespace"; const char *data_len = "buffer len (if) data is returned"; const char *dtype = "directive type"; const char *dspec = "directive specification associated with directive type"; const char *doper = "directive operation"; const char *nsr = "namespace stream requested"; const char *human_readable = "show infos in readable format"; int err, fd; __u32 result; __u32 dw12 = 0; void *buf = NULL; struct config { __u32 namespace_id; __u32 data_len; __u16 dspec; __u8 dtype; __u8 doper; __u16 nsr; /* dw12 for NVME_DIR_ST_RCVOP_STATUS */ int raw_binary; int human_readable; }; struct config cfg = { .namespace_id = 1, .data_len = 0, .dspec = 0, .dtype = 0, .doper = 0, .nsr = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len}, {"raw-binary", 'b', "FLAG",CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"dir-type", 'D', "NUM", CFG_BYTE, &cfg.dtype, required_argument, dtype}, {"dir-spec", 'S', "NUM", CFG_SHORT, &cfg.dspec, required_argument, dspec}, {"dir-oper", 'O', "NUM", CFG_BYTE, &cfg.doper, required_argument, doper}, {"req-resource", 'r', "NUM", CFG_SHORT, &cfg.nsr, required_argument, nsr}, {"human-readable", 'H', "FLAG",CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; switch (cfg.dtype) { case NVME_DIR_IDENTIFY: switch (cfg.doper) { case NVME_DIR_RCV_ID_OP_PARAM: if (!cfg.data_len) cfg.data_len = 4096; break; default: fprintf(stderr, "invalid directive operations for Identify Directives\n"); return EINVAL; } break; case NVME_DIR_STREAMS: switch (cfg.doper) { case NVME_DIR_RCV_ST_OP_PARAM: if (!cfg.data_len) cfg.data_len = 32; break; case NVME_DIR_RCV_ST_OP_STATUS: if (!cfg.data_len) cfg.data_len = 128 * 1024; break; case NVME_DIR_RCV_ST_OP_RESOURCE: dw12 = cfg.nsr; break; default: fprintf(stderr, "invalid directive operations for Streams Directives\n"); return EINVAL; } break; default: fprintf(stderr, "invalid directive type\n"); return EINVAL; break; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) exit(ENOMEM); memset(buf, 0, cfg.data_len); } err = nvme_dir_recv(fd, cfg.namespace_id, cfg.dspec, cfg.dtype, cfg.doper, cfg.data_len, dw12, buf, &result); if (err < 0) { perror("dir-receive"); return errno; } if (!err) { printf("dir-receive: type %#x, operation %#x, spec %#x, nsid %#x, result %#x \n", cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, result); if (cfg.human_readable) nvme_directive_show_fields(cfg.dtype, cfg.doper, result, buf); else { if (buf) { if (!cfg.raw_binary) d(buf, cfg.data_len, 16, 1); else d_raw(buf, cfg.data_len); } } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); if (buf) free(buf); return err; } static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, struct command *cmd) { void *data = NULL, *metadata = NULL; int err = 0, wfd = STDIN_FILENO, fd; __u32 result; struct config { __u8 opcode; __u8 flags; __u16 rsvd; __u32 namespace_id; __u32 data_len; __u32 metadata_len; __u32 timeout; __u32 cdw2; __u32 cdw3; __u32 cdw10; __u32 cdw11; __u32 cdw12; __u32 cdw13; __u32 cdw14; __u32 cdw15; char *input_file; int raw_binary; int show_command; int dry_run; int read; int write; __u8 prefill; }; struct config cfg = { .opcode = 0, .flags = 0, .rsvd = 0, .namespace_id = 0, .data_len = 0, .metadata_len = 0, .timeout = 0, .cdw2 = 0, .cdw3 = 0, .cdw10 = 0, .cdw11 = 0, .cdw12 = 0, .cdw13 = 0, .cdw14 = 0, .cdw15 = 0, .input_file = "", .prefill = 0, }; const char *opcode = "hex opcode (required)"; const char *flags = "command flags"; const char *rsvd = "value for reserved field"; const char *namespace_id = "desired namespace"; const char *data_len = "data I/O length (bytes)"; const char *metadata_len = "metadata seg. length (bytes)"; const char *timeout = "timeout value, in milliseconds"; const char *cdw2 = "command dword 2 value"; const char *cdw3 = "command dword 3 value"; const char *cdw10 = "command dword 10 value"; const char *cdw11 = "command dword 11 value"; const char *cdw12 = "command dword 12 value"; const char *cdw13 = "command dword 13 value"; const char *cdw14 = "command dword 14 value"; const char *cdw15 = "command dword 15 value"; const char *input = "write/send file (default stdin)"; const char *raw_binary = "dump output in binary format"; const char *show = "print command before sending"; const char *dry = "show command instead of sending"; const char *re = "set dataflow direction to receive"; const char *wr = "set dataflow direction to send"; const char *prefill = "prefill buffer with known byte-value, default 0"; const struct argconfig_commandline_options command_line_options[] = { {"opcode", 'o', "NUM", CFG_BYTE, &cfg.opcode, required_argument, opcode}, {"flags", 'f', "NUM", CFG_BYTE, &cfg.flags, required_argument, flags}, {"prefill", 'p', "NUM", CFG_BYTE, &cfg.prefill, required_argument, prefill}, {"rsvd", 'R', "NUM", CFG_SHORT, &cfg.rsvd, required_argument, rsvd}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len}, {"metadata-len", 'm', "NUM", CFG_POSITIVE, &cfg.metadata_len, required_argument, metadata_len}, {"timeout", 't', "NUM", CFG_POSITIVE, &cfg.timeout, required_argument, timeout}, {"cdw2", '2', "NUM", CFG_POSITIVE, &cfg.cdw2, required_argument, cdw2}, {"cdw3", '3', "NUM", CFG_POSITIVE, &cfg.cdw3, required_argument, cdw3}, {"cdw10", '4', "NUM", CFG_POSITIVE, &cfg.cdw10, required_argument, cdw10}, {"cdw11", '5', "NUM", CFG_POSITIVE, &cfg.cdw11, required_argument, cdw11}, {"cdw12", '6', "NUM", CFG_POSITIVE, &cfg.cdw12, required_argument, cdw12}, {"cdw13", '7', "NUM", CFG_POSITIVE, &cfg.cdw13, required_argument, cdw13}, {"cdw14", '8', "NUM", CFG_POSITIVE, &cfg.cdw14, required_argument, cdw14}, {"cdw15", '9', "NUM", CFG_POSITIVE, &cfg.cdw15, required_argument, cdw15}, {"input-file", 'i', "FILE", CFG_STRING, &cfg.input_file, required_argument, input}, {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"show-command", 's', "", CFG_NONE, &cfg.show_command, no_argument, show}, {"dry-run", 'd', "", CFG_NONE, &cfg.dry_run, no_argument, dry}, {"read", 'r', "", CFG_NONE, &cfg.read, no_argument, re}, {"write", 'w', "", CFG_NONE, &cfg.write, no_argument, wr}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (strlen(cfg.input_file)){ wfd = open(cfg.input_file, O_RDONLY, S_IRUSR | S_IRGRP | S_IROTH); if (wfd < 0) { perror(cfg.input_file); return EINVAL; } } if (cfg.metadata_len) metadata = malloc(cfg.metadata_len); if (cfg.data_len) { if (posix_memalign(&data, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate data payload\n"); return ENOMEM; } memset(data, cfg.prefill, cfg.data_len); if (!cfg.read && !cfg.write) { fprintf(stderr, "data direction not given\n"); err = EINVAL; goto free_and_return; } else if (cfg.write) { if (read(wfd, data, cfg.data_len) < 0) { fprintf(stderr, "failed to read write buffer\n"); err = EINVAL; goto free_and_return; } } } if (cfg.show_command) { printf("opcode : %02x\n", cfg.opcode); printf("flags : %02x\n", cfg.flags); printf("rsvd1 : %04x\n", cfg.rsvd); printf("nsid : %08x\n", cfg.namespace_id); printf("cdw2 : %08x\n", cfg.cdw2); printf("cdw3 : %08x\n", cfg.cdw3); printf("data_len : %08x\n", cfg.data_len); printf("metadata_len : %08x\n", cfg.metadata_len); printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)data); printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)metadata); printf("cdw10 : %08x\n", cfg.cdw10); printf("cdw11 : %08x\n", cfg.cdw11); printf("cdw12 : %08x\n", cfg.cdw12); printf("cdw13 : %08x\n", cfg.cdw13); printf("cdw14 : %08x\n", cfg.cdw14); printf("cdw15 : %08x\n", cfg.cdw15); printf("timeout_ms : %08x\n", cfg.timeout); if (cfg.dry_run) goto free_and_return; } err = nvme_passthru(fd, ioctl_cmd, cfg.opcode, cfg.flags, cfg.rsvd, cfg.namespace_id, cfg.cdw2, cfg.cdw3, cfg.cdw10, cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, cfg.cdw15, cfg.data_len, data, cfg.metadata_len, metadata, cfg.timeout, &result); if (err < 0) perror("passthru"); else if (err) fprintf(stderr, "NVMe Status:%s(%x) Command Result:%08x\n", nvme_status_to_string(err), err, result); else { if (!cfg.raw_binary) { fprintf(stderr, "NVMe command result:%08x\n", result); if (data && cfg.read && !err) d((unsigned char *)data, cfg.data_len, 16, 1); } else if (data && cfg.read) d_raw((unsigned char *)data, cfg.data_len); } free_and_return: free(data); free(metadata); return err; } static int io_passthru(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send a user-defined IO command to the specified "\ "device via IOCTL passthrough, return results."; return passthru(argc, argv, NVME_IOCTL_IO_CMD, desc, cmd); } static int admin_passthru(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send a user-defined Admin command to the specified "\ "device via IOCTL passthrough, return results."; return passthru(argc, argv, NVME_IOCTL_ADMIN_CMD, desc, cmd); } #ifdef LIBUUID static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { uuid_t uuid; char uuid_str[37]; /* e.g. 1b4e28ba-2fa1-11d2-883f-0016d3cca427 + \0 */ uuid_generate_random(uuid); uuid_unparse_lower(uuid, uuid_str); printf("nqn.2014-08.org.nvmexpress:uuid:%s\n", uuid_str); return 0; } #else static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { fprintf(stderr, "\"%s\" not supported. Install lib uuid and rebuild.\n", command->name); return -ENOTSUP; } #endif static int discover_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send Get Log Page request to Discovery Controller."; return discover(desc, argc, argv, false); } static int connect_all_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Discover NVMeoF subsystems and connect to them"; return discover(desc, argc, argv, true); } static int connect_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Connect to NVMeoF subsystem"; return connect(desc, argc, argv); } static int disconnect_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Disconnect from NVMeoF subsystem"; return disconnect(desc, argc, argv); } void register_extension(struct plugin *plugin) { plugin->parent = &nvme; nvme.extensions->tail->next = plugin; nvme.extensions->tail = plugin; } int main(int argc, char **argv) { int ret; nvme.extensions->parent = &nvme; if (argc < 2) { general_help(&builtin); return 0; } setlocale(LC_ALL, ""); ret = handle_plugin(argc - 1, &argv[1], nvme.extensions); if (ret == -ENOTTY) general_help(&builtin); return ret; } nvme-cli-1.5/nvme.control.in000066400000000000000000000003471322317423600160540ustar00rootroot00000000000000Package: nvme Version: @@VERSION@@ Section: base Priority: optional Architecture: amd64 Depends: @@DEPENDS@@ Maintainer: Keith Busch Description: NVM-Express Command Line Interface The nvme management tool nvme-cli-1.5/nvme.h000066400000000000000000000055671322317423600142270ustar00rootroot00000000000000/* * Definitions for the NVM Express interface * Copyright (c) 2011-2014, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ #ifndef _NVME_H #define _NVME_H #include #include #include #include "plugin.h" #include "json.h" #define unlikely(x) x #ifdef LIBUUID #include #else typedef struct { uint8_t b[16]; } uuid_t; #endif #include "linux/nvme.h" struct nvme_effects_log_page { __le32 acs[256]; __le32 iocs[256]; __u8 resv[2048]; }; struct nvme_error_log_page { __u64 error_count; __u16 sqid; __u16 cmdid; __u16 status_field; __u16 parm_error_location; __u64 lba; __u32 nsid; __u8 vs; __u8 resv[35]; }; struct nvme_firmware_log_page { __u8 afi; __u8 resv[7]; __u64 frs[7]; __u8 resv2[448]; }; /* idle and active power scales occupy the last 2 bits of the field */ #define POWER_SCALE(s) ((s) >> 6) struct nvme_host_mem_buffer { __u32 hsize; __u32 hmdlal; __u32 hmdlau; __u32 hmdlec; __u8 rsvd16[4080]; }; struct nvme_auto_pst { __u32 data; __u32 rsvd32; }; struct nvme_controller_list { __le16 num; __le16 identifier[]; }; struct nvme_bar_cap { __u16 mqes; __u8 ams_cqr; __u8 to; __u16 css_nssrs_dstrd; __u8 mpsmax_mpsmin; __u8 reserved; }; #ifdef __CHECKER__ #define __force __attribute__((force)) #else #define __force #endif #define cpu_to_le16(x) \ ((__force __le16)htole16(x)) #define cpu_to_le32(x) \ ((__force __le32)htole32(x)) #define cpu_to_le64(x) \ ((__force __le64)htole64(x)) #define le16_to_cpu(x) \ le16toh((__force __u16)(x)) #define le32_to_cpu(x) \ le32toh((__force __u32)(x)) #define le64_to_cpu(x) \ le64toh((__force __u64)(x)) #define MAX_LIST_ITEMS 256 struct list_item { char node[1024]; struct nvme_id_ctrl ctrl; int nsid; struct nvme_id_ns ns; unsigned block; }; struct ctrl_list_item { char *name; char *address; char *transport; }; struct subsys_list_item { char *name; char *subsysnqn; int nctrls; struct ctrl_list_item *ctrls; }; enum { NORMAL, JSON, BINARY, }; void register_extension(struct plugin *plugin); #include "argconfig.h" int parse_and_open(int argc, char **argv, const char *desc, const struct argconfig_commandline_options *clo, void *cfg, size_t size); extern const char *devicename; int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, void (*vs)(__u8 *vs, struct json_object *root)); int validate_output_format(char *format); #endif /* _NVME_H */ nvme-cli-1.5/nvme.spec.in000066400000000000000000000023741322317423600153300ustar00rootroot00000000000000Name: nvme Version: @@VERSION@@ Release: 1%{?dist} Summary: Core nvme tools License: GPL Group: Development/Tools URL: https://github.com/linux-nvme/nvme-cli/ Source: nvme-@@VERSION@@.tar.gz Provides: nvme Requires(post): uuidgen BuildRoot: %{_tmppath}/%{name}-%{version}-root %description NVMe is a fast, scalable, direct attached storage interface. The nvme cli rpm installs core management tools with minimal dependencies. %prep %setup %build make %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=%{buildroot} PREFIX=/usr %files %defattr(-,root,root) %doc Documentation/nvme*.1 %{_sbindir}/nvme %{_mandir}/man1/nvme*.1* %{_datadir}/bash_completion.d/nvme %clean rm -rf $RPM_BUILD_ROOT %post if [ $1 = 1 ]; then # 1 : This package is being installed for the first time if [ ! -f /etc/nvme/hostnqn ]; then install -D /dev/null /etc/nvme/hostnqn echo $(nvme gen-hostnqn) > /etc/nvme/hostnqn fi if [ ! -f /etc/nvme/hostid ]; then uuidgen > /etc/nvme/hostid fi fi %preun if [ "$1" = "remove" ]; then if [ -d /etc/nvme ]; then rm -f /etc/nvme/hostnqn if [ ! -n "`ls -A /etc/nvme`" ]; then rm -rf /etc/nvme fi fi fi %changelog * Thu Oct 15 2015 Keith Busch - Initial RPM spec nvme-cli-1.5/parser.c000066400000000000000000000155561322317423600145500ustar00rootroot00000000000000/* * lib/parser.c - simple parser for mount, etc. options. * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ #include #include #include #include #include #include #include #include "parser.h" /** * match_one: - Determines if a string matches a simple pattern * @s: the string to examine for presence of the pattern * @p: the string containing the pattern * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match * locations. * * Description: Determines if the pattern @p is present in string @s. Can only * match extremely simple token=arg style patterns. If the pattern is found, * the location(s) of the arguments will be returned in the @args array. */ static int match_one(char *s, const char *p, substring_t args[]) { char *meta; int argc = 0; if (!p) return 1; while(1) { int len = -1; meta = strchr(p, '%'); if (!meta) return strcmp(p, s) == 0; if (strncmp(p, s, meta-p)) return 0; s += meta - p; p = meta + 1; if (isdigit(*p)) len = strtoul(p, (char **) &p, 10); else if (*p == '%') { if (*s++ != '%') return 0; p++; continue; } if (argc >= MAX_OPT_ARGS) return 0; args[argc].from = s; switch (*p++) { case 's': { size_t str_len = strlen(s); if (str_len == 0) return 0; if (len == -1 || len > str_len) len = str_len; args[argc].to = s + len; break; } case 'd': strtol(s, &args[argc].to, 0); goto num; case 'u': strtoul(s, &args[argc].to, 0); goto num; case 'o': strtoul(s, &args[argc].to, 8); goto num; case 'x': strtoul(s, &args[argc].to, 16); num: if (args[argc].to == args[argc].from) return 0; break; default: return 0; } s = args[argc].to; argc++; } } /** * match_token: - Find a token (and optional args) in a string * @s: the string to examine for token/argument pairs * @table: match_table_t describing the set of allowed option tokens and the * arguments that may be associated with them. Must be terminated with a * &struct match_token whose pattern is set to the NULL pointer. * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match * locations. * * Description: Detects which if any of a set of token strings has been passed * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style * format identifiers which will be taken into account when matching the * tokens, and whose locations will be returned in the @args array. */ int match_token(char *s, const match_table_t table, substring_t args[]) { const struct match_token *p; for (p = table; !match_one(s, p->pattern, args) ; p++) ; return p->token; } /** * match_number: scan a number in the given base from a substring_t * @s: substring to be scanned * @result: resulting integer on success * @base: base to use when converting string * * Description: Given a &substring_t and a base, attempts to parse the substring * as a number in that base. On success, sets @result to the integer represented * by the string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. */ static int match_number(substring_t *s, int *result, int base) { char *endp; char *buf; int ret; long val; size_t len = s->to - s->from; buf = malloc(len + 1); if (!buf) return -ENOMEM; memcpy(buf, s->from, len); buf[len] = '\0'; ret = 0; val = strtol(buf, &endp, base); if (endp == buf) ret = -EINVAL; else if (val < (long)INT_MIN || val > (long)INT_MAX) ret = -ERANGE; else *result = (int) val; free(buf); return ret; } /** * match_int: - scan a decimal representation of an integer from a substring_t * @s: substring_t to be scanned * @result: resulting integer on success * * Description: Attempts to parse the &substring_t @s as a decimal integer. On * success, sets @result to the integer represented by the string and returns 0. * Returns -ENOMEM, -EINVAL, or -ERANGE on failure. */ int match_int(substring_t *s, int *result) { return match_number(s, result, 0); } /** * match_octal: - scan an octal representation of an integer from a substring_t * @s: substring_t to be scanned * @result: resulting integer on success * * Description: Attempts to parse the &substring_t @s as an octal integer. On * success, sets @result to the integer represented by the string and returns * 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. */ int match_octal(substring_t *s, int *result) { return match_number(s, result, 8); } /** * match_hex: - scan a hex representation of an integer from a substring_t * @s: substring_t to be scanned * @result: resulting integer on success * * Description: Attempts to parse the &substring_t @s as a hexadecimal integer. * On success, sets @result to the integer represented by the string and * returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. */ int match_hex(substring_t *s, int *result) { return match_number(s, result, 16); } /** * match_wildcard: - parse if a string matches given wildcard pattern * @pattern: wildcard pattern * @str: the string to be parsed * * Description: Parse the string @str to check if matches wildcard * pattern @pattern. The pattern may contain two type wildcardes: * '*' - matches zero or more characters * '?' - matches one character * If it's matched, return true, else return false. */ bool match_wildcard(const char *pattern, const char *str) { const char *s = str; const char *p = pattern; bool star = false; while (*s) { switch (*p) { case '?': s++; p++; break; case '*': star = true; str = s; if (!*++p) return true; pattern = p; break; default: if (*s == *p) { s++; p++; } else { if (!star) return false; str++; s = str; p = pattern; } break; } } if (*p == '*') ++p; return !*p; } /** * match_strlcpy: - Copy the characters from a substring_t to a sized buffer * @dest: where to copy to * @src: &substring_t to copy * @size: size of destination buffer * * Description: Copy the characters in &substring_t @src to the * c-style string @dest. Copy no more than @size - 1 characters, plus * the terminating NUL. Return length of @src. */ size_t match_strlcpy(char *dest, const substring_t *src, size_t size) { size_t ret = src->to - src->from; if (size) { size_t len = ret >= size ? size - 1 : ret; memcpy(dest, src->from, len); dest[len] = '\0'; } return ret; } /** * match_strdup: - allocate a new string with the contents of a substring_t * @s: &substring_t to copy * * Description: Allocates and returns a string filled with the contents of * the &substring_t @s. The caller is responsible for freeing the returned * string with free(). */ char *match_strdup(const substring_t *s) { size_t sz = s->to - s->from + 1; char *p = malloc(sz); if (p) match_strlcpy(p, s, sz); return p; } nvme-cli-1.5/parser.h000066400000000000000000000017261322317423600145470ustar00rootroot00000000000000/* * linux/include/linux/parser.h * * Header for lib/parser.c * Intended use of these functions is parsing filesystem argument lists, * but could potentially be used anywhere else that simple option=arg * parsing is required. */ /* associates an integer enumerator with a pattern string. */ struct match_token { int token; const char *pattern; }; typedef struct match_token match_table_t[]; /* Maximum number of arguments that match_token will find in a pattern */ enum {MAX_OPT_ARGS = 3}; /* Describe the location within a string of a substring */ typedef struct { char *from; char *to; } substring_t; int match_token(char *, const match_table_t table, substring_t args[]); int match_int(substring_t *, int *result); int match_octal(substring_t *, int *result); int match_hex(substring_t *, int *result); bool match_wildcard(const char *pattern, const char *str); size_t match_strlcpy(char *, const substring_t *, size_t); char *match_strdup(const substring_t *); nvme-cli-1.5/plugin.c000066400000000000000000000103341322317423600145370ustar00rootroot00000000000000#include #include #include #include #include "plugin.h" #include "argconfig.h" static int version(struct plugin *plugin) { struct program *prog = plugin->parent; if (plugin->name) printf("%s %s version %s\n", prog->name, plugin->name, prog->version); else printf("%s version %s\n", prog->name, prog->version); return 0; } static int help(int argc, char **argv, struct plugin *plugin) { char man[0x100]; struct program *prog = plugin->parent; char *str = argv[1]; int i; if (argc == 1) { general_help(plugin); return 0; } for (i = 0; plugin->commands[i]; i++) { struct command *cmd = plugin->commands[i]; if (strcmp(str, cmd->name)) if (!cmd->alias || (cmd->alias && strcmp(str, cmd->alias))) continue; if (plugin->name) sprintf(man, "%s-%s-%s", prog->name, plugin->name, cmd->name); else sprintf(man, "%s-%s", prog->name, cmd->name); if (execlp("man", "man", man, (char *)NULL)) perror(argv[1]); } return 0; } void usage(struct plugin *plugin) { struct program *prog = plugin->parent; if (plugin->name) printf("usage: %s %s %s\n", prog->name, plugin->name, prog->usage); else printf("usage: %s %s\n", prog->name, prog->usage); } void general_help(struct plugin *plugin) { struct program *prog = plugin->parent; struct plugin *extension; unsigned i = 0; printf("%s-%s\n", prog->name, prog->version); usage(plugin); printf("\n"); print_word_wrapped(prog->desc, 0, 0); printf("\n"); if (plugin->desc) { printf("\n"); print_word_wrapped(plugin->desc, 0, 0); printf("\n"); } printf("\nThe following are all implemented sub-commands:\n"); for (; plugin->commands[i]; i++) printf(" %-*s %s\n", 15, plugin->commands[i]->name, plugin->commands[i]->help); printf(" %-*s %s\n", 15, "version", "Shows the program version"); printf(" %-*s %s\n", 15, "help", "Display this help"); printf("\n"); if (plugin->name) printf("See '%s %s help ' for more information on a specific command\n", prog->name, plugin->name); else printf("See '%s help ' for more information on a specific command\n", prog->name); /* The first plugin is the built-in. If we're not showing help for the * built-in, don't show the program's other extensions */ if (plugin->name) return; extension = prog->extensions->next; if (!extension) return; printf("\nThe following are all installed plugin extensions:\n"); while (extension) { printf(" %-*s %s\n", 15, extension->name, extension->desc); extension = extension->next; } printf("\nSee '%s help' for more information on a plugin\n", prog->name); } int handle_plugin(int argc, char **argv, struct plugin *plugin) { unsigned i = 0; char *str = argv[0]; char use[0x100]; struct plugin *extension; struct program *prog = plugin->parent; if (!argc) { general_help(plugin); return 0; } if (!plugin->name) sprintf(use, "%s %s [OPTIONS]", prog->name, str); else sprintf(use, "%s %s %s [OPTIONS]", prog->name, plugin->name, str); argconfig_append_usage(use); /* translate --help and --version into commands */ while (*str == '-') str++; if (!strcmp(str, "help")) return help(argc, argv, plugin); if (!strcmp(str, "version")) return version(plugin); for (; plugin->commands[i]; i++) { struct command *cmd = plugin->commands[i]; if (strcmp(str, cmd->name)) if (!cmd->alias || (cmd->alias && strcmp(str, cmd->alias))) continue; return (cmd->fn(argc, argv, cmd, plugin)); } /* Check extensions only if this is running the built-in plugin */ if (plugin->name) { printf("ERROR: Invalid sub-command '%s' for plugin %s\n", str, plugin->name); return -ENOTTY; } extension = plugin->next; while (extension) { if (!strcmp(str, extension->name)) return handle_plugin(argc - 1, &argv[1], extension); /* If the command is executed with the extension name and * command together ("plugin-command"), run the plug in */ if (!strncmp(str, extension->name, strlen(extension->name))) { argv[0] += strlen(extension->name); while (*argv[0] == '-') argv[0]++; return handle_plugin(argc, &argv[0], extension); } extension = extension->next; } printf("ERROR: Invalid sub-command '%s'\n", str); return -ENOTTY; } nvme-cli-1.5/plugin.h000066400000000000000000000012521322317423600145430ustar00rootroot00000000000000#ifndef PLUGIN_H #define PLUGIN_H #include struct program { const char *name; const char *version; const char *usage; const char *desc; const char *more; struct command **commands; struct plugin *extensions; }; struct plugin { const char *name; const char *desc; struct command **commands; struct program *parent; struct plugin *next; struct plugin *tail; }; struct command { char *name; char *help; int (*fn)(int argc, char **argv, struct command *command, struct plugin *plugin); char *alias; }; void usage(struct plugin *plugin); void general_help(struct plugin *plugin); int handle_plugin(int argc, char **argv, struct plugin *plugin); #endif nvme-cli-1.5/regress000077500000000000000000000055371322317423600145060ustar00rootroot00000000000000#!/bin/bash # # Copyright 2015 PMC-Sierra, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Stephen Bates # # Description: # Regression test-suite for the NVM Express CLI. # DEVICE= WRITE=false LIST=false RAND_BASE=temp.rand RAND_WFILE=${RAND_BASE}.write RAND_RFILE=${RAND_BASE}.read RAND_SIZE=4k green=$(tput bold)$(tput setaf 2) red=$(tput bold)$(tput setaf 1) rst=$(tput sgr0) while getopts ":d:wl" opt; do case $opt in d) DEVICE=${OPTARG} ;; w) echo "WARNING: Write mode enabled, this might trash your drive!" WRITE=true ;; l) LIST=true ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done if [ -z "$DEVICE" ]; then echo "regress: You must specify a NVMe device using -d" exit 1 fi function print_pass_fail { $* > /dev/null 2>&1 if (( $? )); then echo ${red}"FAILED!"${rst} echo "Failed running command: " echo " $*" exit 1 else echo ${green}"PASSED!"${rst} fi } function run_test { LINE="$*" printf " %-3s %-68s : " "RUN" "${LINE::67}" print_pass_fail $* } make clean > /dev/null || exit -1 make install > /dev/null || exit -1 if $LIST ; then run_test nvme list fi run_test nvme id-ctrl ${DEVICE} run_test nvme id-ns -raw-binary ${DEVICE} run_test nvme list-ns -n 1 ${DEVICE} run_test nvme get-ns-id ${DEVICE} run_test nvme get-log ${DEVICE} --log-id=2 --log-len=512 run_test nvme fw-log ${DEVICE} run_test nvme fw-log ${DEVICE} -b run_test nvme smart-log ${DEVICE} run_test nvme error-log ${DEVICE} run_test nvme get-feature ${DEVICE} -f 7 run_test nvme flush ${DEVICE} if $WRITE ; then run_test dd if=/dev/urandom of=${RAND_WFILE} bs=${RAND_SIZE} count=1 run_test nvme write ${DEVICE} --start-block=0 --block-count=0 --data-size=${RAND_SIZE} --data ${RAND_WFILE} fi run_test nvme read ${DEVICE} --start-block=0 --block-count=0 --data-size=${RAND_SIZE} --data ${RAND_RFILE} --latency if $WRITE ; then run_test diff ${RAND_RFILE} ${RAND_WFILE} rm ${RAND_WFILE} > /dev/null fi rm ${RAND_RFILE} > /dev/null nvme-cli-1.5/scripts/000077500000000000000000000000001322317423600145635ustar00rootroot00000000000000nvme-cli-1.5/scripts/latency000077500000000000000000000057001322317423600161520ustar00rootroot00000000000000#!/bin/bash # # Copyright 2015 PMC-Sierra, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Stephen Bates # # Description: # A shell script that calls the NVMe CLI multiple times to gather # latency data. Consider this a poor man's iometer or fio for QD=1 # analysis. Of course this is below the file-system and block # layer so is a best case measurement. # DEVICE= WRITE=false COUNT=10 DATA_SIZE=4096 METADATA_SIZE=64 RAND_BASE=temp.rand RAND_WFILE=${RAND_BASE}.write RAND_RFILE=${RAND_BASE}.read OUTPUT=latency.dat green=$(tput bold)$(tput setaf 2) red=$(tput bold)$(tput setaf 1) rst=$(tput sgr0) while getopts ":d:n:w" opt; do case $opt in d) DEVICE=${OPTARG} ;; n) COUNT=${OPTARG} ;; w) echo "WARNING: Write mode enabled, this might trash your drive!" WRITE=true ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done if [ "$COUNT" == "0" ]; then echo "Count can not be 0" exit 1 fi if [ -z "$DEVICE" ]; then echo "regress: You must specify a NVMe device using -d" exit 1 fi function run_test { $* | grep -i latency >> ${OUTPUT} 2>&1 if (( $? )); then echo ${red}"FAILED!"${rst} echo "Failed running command: " echo " $*" exit 1 fi } rm -f ${OUTPUT} > /dev/null || exit -1 make clean > /dev/null || exit -1 make install > /dev/null || exit -1 for i in `seq 1 ${COUNT}`; do if $WRITE ; then dd if=/dev/urandom of=${RAND_WFILE} bs=${DATA_SIZE} count=1 run_test nvme write ${DEVICE} --start-block=0 --block-count=0 \ --metadata-size=${METADATA_SIZE} --data-size=${DATA_SIZE} \ --data ${RAND_WFILE} --latency rm ${RAND_WFILE} > /dev/null else run_test nvme read ${DEVICE} --start-block=0 --block-count=0 \ --metadata-size=${METADATA_SIZE} --data-size=${DATA_SIZE} \ --data ${RAND_RFILE} --latency rm ${RAND_RFILE} > /dev/null fi done # Calculate average latency SUM=0 for i in `cat ${OUTPUT} | awk '{print $3}' | xargs` do SUM=$(($SUM + $i)) done AVERAGE=$(echo "scale=2; $SUM/$COUNT" | bc -l) echo "Average Latency: $AVERAGE us" nvme-cli-1.5/suffix.c000066400000000000000000000054241322317423600145510ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////// // // Copyright 2014 PMC-Sierra, Inc. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // // Author: Logan Gunthorpe // // Date: Oct 23 2014 // // Description: // Functions for dealing with number suffixes // //////////////////////////////////////////////////////////////////////// #include "suffix.h" #include #include #include #include static struct si_suffix { double magnitude; const char *suffix; } si_suffixes[] = { {1e15, "P"}, {1e12, "T"}, {1e9, "G"}, {1e6, "M"}, {1e3, "k"}, {1e0, ""}, {1e-3, "m"}, {1e-6, "u"}, {1e-9, "n"}, {1e-12, "p"}, {1e-15, "f"}, {0} }; const char *suffix_si_get(double *value) { struct si_suffix *s; for (s = si_suffixes; s->magnitude != 0; s++) { if (*value >= s->magnitude) { *value /= s->magnitude; return s->suffix; } } return ""; } static struct binary_suffix { int shift; const char *suffix; } binary_suffixes[] = { {50, "Pi"}, {40, "Ti"}, {30, "Gi"}, {20, "Mi"}, {10, "Ki"}, {0, ""} }; const char *suffix_binary_get(long long *value) { struct binary_suffix *s; for (s = binary_suffixes; s->shift != 0; s++) { if (llabs(*value) >= (1LL << s->shift)) { *value = (*value + (1LL << (s->shift - 1))) / (1LL << s->shift); return s->suffix; } } return ""; } const char *suffix_dbinary_get(double *value) { struct binary_suffix *s; for (s = binary_suffixes; s->shift != 0; s++) { if (fabs(*value) >= (1LL << s->shift)) { *value = *value / (1LL << s->shift); return s->suffix; } } return ""; } long long suffix_binary_parse(const char *value) { char *suffix; errno = 0; long long ret = strtoll(value, &suffix, 0); if (errno) return 0; struct binary_suffix *s; for (s = binary_suffixes; s->shift != 0; s++) { if (tolower(suffix[0]) == tolower(s->suffix[0])) { ret <<= s->shift; return ret; } } if (suffix[0] != '\0') errno = EINVAL; return ret; } nvme-cli-1.5/suffix.h000066400000000000000000000026131322317423600145530ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////// // // Copyright 2014 PMC-Sierra, Inc. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // // Author: Logan Gunthorpe // // Date: Oct 23 2014 // // Description: // Functions for dealing with number suffixes // //////////////////////////////////////////////////////////////////////// #ifndef __ARGCONFIG_SUFFIX_H__ const char *suffix_si_get(double *value); const char *suffix_binary_get(long long *value); const char *suffix_dbinary_get(double *value); long long suffix_binary_parse(const char *value); #endif nvme-cli-1.5/tests/000077500000000000000000000000001322317423600142365ustar00rootroot00000000000000nvme-cli-1.5/tests/Makefile000066400000000000000000000022071322317423600156770ustar00rootroot00000000000000############################################################################### # # Makefile : Allows user to run testcases, generate documentation, and # perform static code analysis. # ############################################################################### NOSE2_OPTIONS="--verbose" help: all all: @echo "Usage:" @echo @echo " make run - Run all testcases." @echo " make doc - Generate Documentation." @echo " make cleanall - removes *pyc, documentation." @echo " make static_check- runs pep8, flake8, pylint on code." doc: @epydoc -v --output=Documentation *.py run: @for i in `ls *.py`; \ do \ echo "Running $${i}"; \ TESTCASE_NAME=`echo $${i} | cut -f 1 -d '.'`; \ nose2 ${NOSE2_OPTIONS} $${TESTCASE_NAME}; \ done static_check: @for i in `ls *.py`; \ do \ echo "Pylint :- " ; \ printf "%10s " $${i}; \ pylint $${i} 2>&1 | grep "^Your code" | awk '{print $$7}';\ echo "--------------------------------------------";\ pep8 $${i}; \ echo "pep8 :- "; \ echo "flake8 :- "; \ flake8 $${i}; \ done cleanall: clean @rm -fr *.pyc Documentation clean: @rm -fr *.pyc nvme-cli-1.5/tests/README000066400000000000000000000073111322317423600151200ustar00rootroot00000000000000nvmetests ========= This contains NVMe unit tests framework. The purpose of this framework to use nvme cli and test various supported commands and scenarios for NVMe device. In current implementation this framework uses nvme cli to interact with underlying controller/namespace. 1. Common Package Dependencies ------------------------------ 1. Python(>= 2.7.5 or >= 3.3) 2. nose(http://nose.readthedocs.io/en/latest/) 3. nose2(Installation guide http://nose2.readthedocs.io/) 4. pep8(https://pypi.python.org/pypi/setuptools-pep8) 5. flake8(https://pypi.python.org/pypi/flake8) 6. pylint(https://www.pylint.org/) 7. Epydoc(http://epydoc.sourceforge.net/) 8. nvme-cli(https://github.com/linux-nvme/nvme-cli.git) Python package management system pip can be used to install most of the listed packages(https://pip.pypa.io/en/stable/installing/) :- $ pip install nose nose2 pep8 flake8 pylint epydoc 2. Overview ----------- This framework follows simple class hierarchy. Each test file contains one test. Each test is direct subclass or indirect subclass of TestNVMe class which represents one testcase. To write a new testcase one can copy existing template "nvme_simple_template_test.py" and start adding new testcase specific functionality. For detailed information please look into section 3. For more information about tests, class hierarchy and code please refer :- 1. Documentation :- html/ 2. Class Index :- html/index.html 3. Class Hierarchy :- html/class-tree.html For each testcase it will create log directory mentioned in configuration file. This directory will be used for a temporary files and storing execution logs of each testcases. Current implementation stores stdout and stderr for each testcase under log directory, e.g. :- $ tree nvmetests/ nvmetests/ ├── TestNVMeAttachDetachNSCmd │   ├── stderr.log │   └── stdout.log ├── TestNVMeFlushCmd │   ├── stderr.log │   └── stdout.log └── TestNVMeFormatCmd ├── stderr.log └── stdout.log . . . 3. Walk-Through Example for writing a new testcase -------------------------------------------------- 1. Copy simple test template file from current directory with appropriate name, replace "simple_template" with testcase name in new file name. Update config.json if necessary. 2. Write a testcase main function, make sure its name is starting with test_*. 3. Based on the requirement one can inherit TestNVMe or TestNVMeIO class. 4. Write test precondition code into __init__. Make sure you are calling super class __init__. 5. Write test post condition code into __del__. Make sure you are calling super class __del__. 6. Before writing a new function have a look into TestNVMe to see if it can be reused. 7. Once testcase is ready make sure :- a. Run pep8, flake8, pylint on the testcase and fix errors/warnings. -Example "$ make static_check" will run pep8, flake8 and pylint on all the python files in current directory. b. Execute make doc to generate the documentation. -Example "$ make doc" will create and update existing documentation. 4. Running testcases with framework ----------------------------------- 1. Running single testcase with nose2 :- $ nose2 --verbose nvme_writezeros_test $ nose2 --verbose nvme_read_write_test 2. Running all the testcases with Makefile :- $ make run nvme-cli-1.5/tests/TODO000066400000000000000000000011511322317423600147240ustar00rootroot00000000000000nvmetests TODO List =================== Feature list (with priority):- ------------------------------ 1. PRE and POST section improvements :- a. Add functionality to load and unload driver. b. Make sure default namespace is present, if not create one before any test begins. Read the default namespace size from config file. 2. Add system statistics collection in PRE and POST section of testcase. 3. Create execution summary file under log directory at the end of each run. 4. Add tracing functionality to track overall and current progress of the testcase. nvme-cli-1.5/tests/config.json000066400000000000000000000001321322317423600163720ustar00rootroot00000000000000{ "controller" : "/dev/nvme0", "ns1": "/dev/nvme0n1", "log_dir": "nvmetests/" } nvme-cli-1.5/tests/nvme_attach_detach_ns_test.py000066400000000000000000000061401322317423600221510ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Namespace Management Testcase:- 1. Create Namespace and validate. 2. Attach Namespace to controller. 3. Run IOs on Namespace under test. 4. Detach Namespace from controller. 5. Delete Namespace. """ import time from nose.tools import assert_equal from nvme_test import TestNVMe class TestNVMeAttachDetachNSCmd(TestNVMe): """ Represents Attach, Detach namespace testcase. - Attributes: - dps : data protection information. - flabs : LBA format information. - nsze : namespace size. - ncap : namespace capacity. - ctrl_id : controller id. """ def __init__(self): """ Pre Section for TestNVMeAttachDetachNSCmd """ TestNVMe.__init__(self) self.dps = 0 self.flbas = 0 self.nsze = 0x1400000 self.ncap = 0x1400000 self.setup_log_dir(self.__class__.__name__) self.ctrl_id = self.get_ctrl_id() self.delete_all_ns() time.sleep(1) def __del__(self): """ Post Section for TestNVMeAttachDetachNSCmd - Create primary namespace. - Atttach it to controller. - Call super class's destructor. """ assert_equal(self.create_and_validate_ns(self.default_nsid, self.nsze, self.ncap, self.flbas, self.dps), 0) self.attach_ns(self.ctrl_id, self.default_nsid) TestNVMe.__del__(self) def test_attach_detach_ns(self): """ Testcase main """ err = self.create_and_validate_ns(self.default_nsid, self.nsze, self.ncap, self.flbas, self.dps) assert_equal(err, 0) assert_equal(self.attach_ns(self.ctrl_id, self.default_nsid), 0) self.run_ns_io(self.default_nsid, 0) assert_equal(self.detach_ns(self.ctrl_id, self.default_nsid), 0) assert_equal(self.delete_and_validate_ns(self.default_nsid), 0) self.nvme_reset_ctrl() nvme-cli-1.5/tests/nvme_compare_test.py000066400000000000000000000060431322317423600203250ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Compare Command Testcase:- 1. Create a data file 1 with pattern 1515 to write. 2. Create a data file 2 with pattern 2525 to compare with. 3. Write a block of data pattern using data file1. 4. Compare written block to data file 2's pattern; shall fail. 5. Compare written block to data file1's pattern; shall pass. """ from nose.tools import assert_equal, assert_not_equal from nvme_test_io import TestNVMeIO class TestNVMeCompareCmd(TestNVMeIO): """ Represents Compare Testcase. Inherits TestNVMeIO class. - Attributes: - data_size : data size to perform IO. - start_block : starting block of to perform IO. - compare_file : data file to use in nvme comapre commmand. - test_log_dir : directory for logs, temp files. """ def __init__(self): """ Pre Section for TestNVMeCompareCmd """ TestNVMeIO.__init__(self) self.data_size = 1024 self.start_block = 1023 self.setup_log_dir(self.__class__.__name__) self.compare_file = self.test_log_dir + "/" + "compare_file.txt" self.write_file = self.test_log_dir + "/" + self.write_file self.create_data_file(self.write_file, self.data_size, "15") self.create_data_file(self.compare_file, self.data_size, "25") def __del__(self): """ Post Section for TestNVMeCompareCmd """ TestNVMeIO.__del__(self) def nvme_compare(self, cmp_file): """ Wrapper for nvme compare command. - Args: - cmp_file : data file used in nvme compare command. - Returns: - return code of the nvme compare command. """ compare_cmd = "nvme compare " + self.ns1 + " --start-block=" + \ str(self.start_block) + " --block-count=" + \ str(self.block_count) + " --data-size=" + \ str(self.data_size) + " --data=" + cmp_file return self.exec_cmd(compare_cmd) def test_nvme_compare(self): """ Testcase main """ assert_equal(self.nvme_write(), 0) assert_not_equal(self.nvme_compare(self.compare_file), 0) assert_equal(self.nvme_compare(self.write_file), 0) nvme-cli-1.5/tests/nvme_create_max_ns_test.py000066400000000000000000000067451322317423600215200ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Namespace Management Testcase:- 1. Create Maximum number of Namespaces and validate. 2. Attach all Namespaces to controller. 3. Run IOs on Namespace under test. 4. Detach Maximum number of Namespaces from controller. 5. Delete all Namespaces. """ import time from nose.tools import assert_equal from nvme_test import TestNVMe class TestNVMeCreateMaxNS(TestNVMe): """ Represents Attach, Detach namespace testcase. - Attributes: - dps : data protection information. - flbas : LBA format information. - nsze : namespace size. - ncap : namespace capacity. - ctrl_id : controller id. """ def __init__(self): """ Pre Section for TestNVMeAttachDetachNSCmd """ TestNVMe.__init__(self) self.dps = 0 self.flbas = 0 self.nsze = 0x1400000 self.ncap = 0x1400000 self.setup_log_dir(self.__class__.__name__) self.max_ns = self.get_max_ns() self.ctrl_id = self.get_ctrl_id() self.delete_all_ns() time.sleep(1) def __del__(self): """ Post Section for TestNVMeAttachDetachNSCmd - Create primary namespace. - Atttach it to controller. - Call super class's destructor. """ assert_equal(self.create_and_validate_ns(self.default_nsid, self.nsze, self.ncap, self.flbas, self.dps), 0) self.attach_ns(self.ctrl_id, self.default_nsid) TestNVMe.__del__(self) def test_attach_detach_ns(self): """ Testcase main """ for nsid in range(1, self.max_ns): print "##### Creating " + str(nsid) err = self.create_and_validate_ns(nsid, self.nsze, self.ncap, self.flbas, self.dps) assert_equal(err, 0) print "##### Attaching " + str(nsid) assert_equal(self.attach_ns(self.ctrl_id, nsid), 0) print "##### Running IOs in " + str(nsid) self.run_ns_io(nsid, 0) for nsid in range(1, self.max_ns): print "##### Detaching " + str(nsid) assert_equal(self.detach_ns(self.ctrl_id, nsid), 0) print "#### Deleting " + str(nsid) assert_equal(self.delete_and_validate_ns(nsid), 0) self.nvme_reset_ctrl() nvme-cli-1.5/tests/nvme_error_log_test.py000066400000000000000000000051341322317423600206710ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Smart Log Verification Testcase:- 1. Execute error-log on controller. 2. Execute error-log on each available namespace. """ from nose.tools import assert_equal from nvme_test import TestNVMe class TestNVMeErrorLogCmd(TestNVMe): """ Represents Smart Log testcae. - Attributes: """ def __init__(self): """ Pre Section for TestNVMeErrorLogCmd """ TestNVMe.__init__(self) self.setup_log_dir(self.__class__.__name__) def __del__(self): """ Post Section for TestNVMeErrorLogCmd - Call super class's destructor. """ TestNVMe.__del__(self) def get_error_log_ctrl(self): """ Wrapper for executing error-log on controller. - Args: - None: - Returns: - 0 on success, error code on failure. """ return self.get_error_log("0xFFFFFFFF") def get_error_log_ns(self, nsid): """ Wrapper for executing error-log on a namespace. - Args: - nsid: namespace id to be used in error-log command. - Returns: - 0 on success, error code on failure. """ return self.get_error_log(nsid) def get_error_log_all_ns(self): """ Wrapper for executing error-log on all the namespaces. - Args: - None: - Returns: - 0 on success, error code on failure. """ ns_list = self.get_ns_list() for nsid in range(0, len(ns_list)): self.get_error_log_ns(ns_list[nsid]) return 0 def test_get_error_log(self): """ Testcase main """ assert_equal(self.get_error_log_ctrl(), 0) assert_equal(self.get_error_log_all_ns(), 0) nvme-cli-1.5/tests/nvme_flush_test.py000066400000000000000000000034211322317423600200150ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Flush Command Testcase:- 1. Execute nvme flush on controller. """ from nose.tools import assert_equal from nvme_test import TestNVMe class TestNVMeFlushCmd(TestNVMe): """ Represents Flush Testcase. Inherits TestNVMe class. - Attributes: """ def __init__(self): """ Pre Section for TestNVMeFlushCmd """ TestNVMe.__init__(self) self.setup_log_dir(self.__class__.__name__) def __del__(self): """ Post Section for TestNVMeFlushCmd """ TestNVMe.__del__(self) def nvme_flush(self): """ Wrapper for nvme flush command. - Args: - None - Returns: - None """ flush_cmd = "nvme flush " + self.ctrl + " -n " + str(self.default_nsid) print flush_cmd return self.exec_cmd(flush_cmd) def test_nvme_flush(self): """ Testcase main """ assert_equal(self.nvme_flush(), 0) nvme-cli-1.5/tests/nvme_format_test.py000066400000000000000000000143761322317423600201770ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ Namespace Format testcase :- 1. Create, attach, detach, delete primary namespace and extract the supported format information from default namespace:- - List of the supported format. - List of Metadata Size per format. Based on this we calculate data protection parameter at the time of namespace. - List of LBA Data Size per format. 2. Use the collected information and iterate through each supported format:- - Create namespace. - Attach namespace. - Run IOs on the namespace under test. - Detach namespace - Delete Namespace. """ import time import subprocess from nose.tools import assert_equal from nvme_test import TestNVMe class TestNVMeFormatCmd(TestNVMe): """ Represents Format testcase. - Attributes: - dps : data protection information. - flabs : LBA format information. - nsze : namespace size. - ncap : namespace capacity. - ctrl_id : controller id. - lba_format_list : lis of supported format. - ms_list : list of metadat size per format. - lbads_list : list of LBA data size per format. - test_log_dir : directory for logs, temp files. """ def __init__(self): """ Pre Section for TestNVMeFormatCmd """ TestNVMe.__init__(self) self.dps = 0 # ns data protection settings self.flbas = 0 # ns formattes logical block settings self.nsze = 0x1400000 # ns size self.ncap = 0x1400000 # ns capacity self.ctrl_id = self.get_ctrl_id() self.lba_format_list = [] self.ms_list = [] self.lbads_list = [] self.test_log_dir = self.log_dir + "/" + self.__class__.__name__ self.setup_log_dir(self.__class__.__name__) self.delete_all_ns() time.sleep(1) def __del__(self): """ Post Section for TestNVMeFormatCmd - Create primary namespace. - Atttach it to controller. - Call super class's destructor. """ assert_equal(self.create_and_validate_ns(self.default_nsid, self.nsze, self.ncap, self.flbas, self.dps), 0) self.attach_ns(self.ctrl_id, self.default_nsid) TestNVMe.__del__(self) def attach_detach_primary_ns(self): """ Extract supported format information using default namespace """ assert_equal(self.create_and_validate_ns(self.default_nsid, self.nsze, self.ncap, self.flbas, self.dps), 0) assert_equal(self.attach_ns(self.ctrl_id, self.default_nsid), 0) # read lbaf information id_ns = "nvme id-ns " + self.ctrl + \ " -n1 | grep ^lbaf | awk '{print $2}' | tr -s \"\\n\" \" \"" proc = subprocess.Popen(id_ns, shell=True, stdout=subprocess.PIPE) self.lba_format_list = proc.stdout.read().strip().split(" ") if proc.wait() == 0: # read lbads information id_ns = "nvme id-ns " + self.ctrl + \ " -n1 | grep ^lbaf | awk '{print $5}'" + \ " | cut -f 2 -d ':' | tr -s \"\\n\" \" \"" proc = subprocess.Popen(id_ns, shell=True, stdout=subprocess.PIPE) self.lbads_list = proc.stdout.read().strip().split(" ") # read metadata information id_ns = "nvme id-ns " + self.ctrl + \ " -n1 | grep ^lbaf | awk '{print $4}'" + \ " | cut -f 2 -d ':' | tr -s \"\\n\" \" \"" proc = subprocess.Popen(id_ns, shell=True, stdout=subprocess.PIPE) self.ms_list = proc.stdout.read().strip().split(" ") assert_equal(self.detach_ns(self.ctrl_id, self.default_nsid), 0) assert_equal(self.delete_and_validate_ns(self.default_nsid), 0) self.nvme_reset_ctrl() def test_format_ns(self): """ Testcase main """ # extract the supported format information. self.attach_detach_primary_ns() # iterate through all supported format for i in range(0, len(self.lba_format_list)): print "\nlba format " + str(self.lba_format_list[i]) + \ " lbad " + str(self.lbads_list[i]) + \ " ms " + str(self.ms_list[i]) metadata_size = 1 if self.ms_list[i] == '8' else 0 err = self.create_and_validate_ns(self.default_nsid, self.nsze, self.ncap, self.lba_format_list[i], metadata_size) assert_equal(err, 0) assert_equal(self.attach_ns(self.ctrl_id, self.default_nsid), 0) self.run_ns_io(self.default_nsid, self.lbads_list[i]) time.sleep(5) assert_equal(self.detach_ns(self.ctrl_id, self.default_nsid), 0) assert_equal(self.delete_and_validate_ns(self.default_nsid), 0) self.nvme_reset_ctrl() nvme-cli-1.5/tests/nvme_get_features_test.py000066400000000000000000000076061322317423600213620ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ Get Features Testcase:- Test the Mandetory features with get features command:- 1. 01h rbitration. 2. 02h M Power Management. 3. 04h M Temperature Threshold. 4. 05h M Error Recovery. 5. 07h M Number of Queues. 6. 08h M Interrupt Coalescing. 7. 09h M Interrupt Vector Configuration. 8. 0Ah M Write Atomicity Normal. 9. 0Bh M Asynchronous Event Configuration. """ import subprocess from nose.tools import assert_equal from nvme_test import TestNVMe class TestNVMeGetMandetoryFeatures(TestNVMe): """ Represents Get Features testcase. - Attributes: - feature_id_list : list of the mandetory features. - get_vector_list_cmd : vector list collection for 09h. - vector_list : vector list to hold the interrupt vectors. """ def __init__(self): """ Pre Section for TestNVMeGetMandetoryFeatures """ TestNVMe.__init__(self) self.setup_log_dir(self.__class__.__name__) self.feature_id_list = ["0x01", "0x02", "0x04", "0x05", "0x07", "0x08", "0x09", "0x0A", "0x0B"] get_vector_list_cmd = "cat /proc/interrupts | grep nvme |" \ " cut -d : -f 1 | tr -d ' ' | tr '\n' ' '" proc = subprocess.Popen(get_vector_list_cmd, shell=True, stdout=subprocess.PIPE) self.vector_list = [] self.vector_list = proc.stdout.read().strip().split(" ") def __del__(self): """ Post Section for TestNVMeGetMandetoryFeatures Call super class's destructor. """ TestNVMe.__del__(self) def get_mandetory_features(self, feature_id): """ Wrapper for NVMe get features command - Args: - feature_id : feature id to be used with get feature command. - Returns: - None """ if str(feature_id) == "0x09": for vector in self.vector_list: get_feat_cmd = "nvme get-feature " + self.ctrl + \ " --feature-id=" + str(feature_id) + \ " --cdw11=" + str(vector) proc = subprocess.Popen(get_feat_cmd, shell=True, stdout=subprocess.PIPE) feature_output = proc.communicate()[0] print feature_output assert_equal(proc.wait(), 0) else: get_feat_cmd = "nvme get-feature " + self.ctrl + \ " --feature-id=" + str(feature_id) proc = subprocess.Popen(get_feat_cmd, shell=True, stdout=subprocess.PIPE) feature_output = proc.communicate()[0] print feature_output assert_equal(proc.wait(), 0) def test_get_mandetory_features(self): """ Testcase main """ for feature_id in self.feature_id_list: self.get_mandetory_features(feature_id) nvme-cli-1.5/tests/nvme_read_write_test.py000066400000000000000000000051041322317423600210210ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Read/Write Testcae:- 1. Create data file with specific pattern outside of the device under test. 2. Write data file on the namespace under test. 3. Read the data from the namespace under test into different file. 4. Compare file in #1 and #3. """ import filecmp from nose.tools import assert_equal from nvme_test_io import TestNVMeIO class TestNVMeReadWriteTest(TestNVMeIO): """ Represents NVMe read, write testcase. - Attributes: - start_block : starting block of to perform IO. - compare_file : data file to use in nvme comapre commmand. - test_log_dir : directory for logs, temp files. """ def __init__(self): """ Pre Section for TestNVMeReadWriteTest """ TestNVMeIO.__init__(self) self.start_block = 1023 self.test_log_dir = self.log_dir + "/" + self.__class__.__name__ self.setup_log_dir(self.__class__.__name__) self.write_file = self.test_log_dir + "/" + self.write_file self.read_file = self.test_log_dir + "/" + self.read_file self.create_data_file(self.write_file, self.data_size, "15") open(self.read_file, 'a').close() def __del__(self): """ Post Section for TestNVMeReadWriteTest """ TestNVMeIO.__del__(self) def read_validate(self): """ Validate the data file read - Args: - None - Returns: - returns 0 on success, 1 on failure. """ return 0 if filecmp.cmp(self.read_file, self.write_file) else 1 def test_nvme_write(self): """ Testcaes main """ assert_equal(self.nvme_write(), 0) assert_equal(self.nvme_read(), 0) assert_equal(self.read_validate(), 0) nvme-cli-1.5/tests/nvme_simple_template_test.py000066400000000000000000000033341322317423600220630ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ Simple Template test example :- """ from nvme_test import TestNVMe class TestNVMeSimpleTestTemplate(TestNVMe): """ Represents Simple NVMe test """ def __init__(self): """ Pre Section for TestNVMeSimpleTestTemplate. """ TestNVMe.__init__(self) self.setup_log_dir(self.__class__.__name__) # Add this test specific variables here def __del__(self): """ Post Section for TestNVMeSimpleTestTemplate Call super class's destructor. """ # Add this test specific cleanup code here TestNVMe.__del__(self) def simple_template_test(self): """ Wrapper for this test specific functions - Args: - None - Returns: - None """ pass def test_get_mandetory_features(self): """ Testcase main """ self.simple_template_test() nvme-cli-1.5/tests/nvme_smart_log_test.py000066400000000000000000000051271322317423600206700ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Smart Log Verification Testcase:- 1. Execute smat-log on controller. 2. Execute smart-log on each available namespace. """ from nose.tools import assert_equal from nvme_test import TestNVMe class TestNVMeSmartLogCmd(TestNVMe): """ Represents Smart Log testcae. - Attributes: """ def __init__(self): """ Pre Section for TestNVMeSmartLogCmd """ TestNVMe.__init__(self) self.setup_log_dir(self.__class__.__name__) def __del__(self): """ Post Section for TestNVMeSmartLogCmd - Call super class's destructor. """ TestNVMe.__del__(self) def get_smart_log_ctrl(self): """ Wrapper for executing smart-log on controller. - Args: - None: - Returns: - 0 on success, error code on failure. """ return self.get_smart_log("0xFFFFFFFF") def get_smart_log_ns(self, nsid): """ Wrapper for executing smart-log on a namespace. - Args: - nsid: namespace id to be used in smart-log command. - Returns: - 0 on success, error code on failure. """ return self.get_smart_log(nsid) def get_smart_log_all_ns(self): """ Wrapper for executing smart-log on all the namespaces. - Args: - None: - Returns: - 0 on success, error code on failure. """ ns_list = self.get_ns_list() for nsid in range(0, len(ns_list)): self.get_smart_log_ns(ns_list[nsid]) return 0 def test_smart_log(self): """ Testcase main """ assert_equal(self.get_smart_log_ctrl(), 0) assert_equal(self.get_smart_log_all_ns(), 0) nvme-cli-1.5/tests/nvme_test.py000066400000000000000000000344721322317423600166260ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ Base class for all the testcases """ import re import os import sys import json import mmap import stat import time import shutil import string import subprocess from nose import tools from nose.tools import assert_equal from nvme_test_logger import TestNVMeLogger class TestNVMe(object): """ Represents a testcase, each testcase shuold inherit this class or appropriate subclass which is a child of this class. Common utility functions used in various testcases. - Attributes: - ctrl : NVMe Controller. - ns1 : default namespace. - default_nsid : default namespace id. - config_file : configuration file. - clear_log_dir : default log directory. """ def __init__(self): """ Pre Section for TestNVMe. """ # common code used in various testcases. self.ctrl = "XXX" self.ns1 = "XXX" self.test_log_dir = "XXX" self.default_nsid = 0x1 self.config_file = 'config.json' self.load_config() self.validate_pci_device() def __del__(self): """ Post Section for TestNVMe. """ if self.clear_log_dir is True: shutil.rmtree(self.log_dir, ignore_errors=True) @tools.nottest def validate_pci_device(self): """ Validate underlaying device belogs to pci subsystem. - Args: - None - Returns: - None """ cmd = cmd = "find /sys/devices -name \\*nvme0 | grep -i pci" err = subprocess.call(cmd, shell=True) assert_equal(err, 0, "ERROR : Only NVMe PCI subsystem is supported") @tools.nottest def load_config(self): """ Load Basic test configuration. - Args: - None - Returns: - None """ with open(self.config_file) as data_file: config = json.load(data_file) self.ctrl = config['controller'] self.ns1 = config['ns1'] self.log_dir = config['log_dir'] self.clear_log_dir = False if self.clear_log_dir is True: shutil.rmtree(self.log_dir, ignore_errors=True) if not os.path.exists(self.log_dir): os.makedirs(self.log_dir) @tools.nottest def setup_log_dir(self, test_name): """ Set up the log directory for a testcase Args: - test_name : name of the testcase. Returns: - None """ self.test_log_dir = self.log_dir + "/" + test_name if not os.path.exists(self.test_log_dir): os.makedirs(self.test_log_dir) sys.stdout = TestNVMeLogger(self.test_log_dir + "/" + "stdout.log") sys.stderr = TestNVMeLogger(self.test_log_dir + "/" + "stderr.log") @tools.nottest def exec_cmd(self, cmd): """ Wrapper for executing a shell command and return the result. """ proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) return proc.wait() @tools.nottest def nvme_reset_ctrl(self): """ Wrapper for nvme reset command. - Args: - None: - Returns: - None """ nvme_reset_cmd = "nvme reset " + self.ctrl err = subprocess.call(nvme_reset_cmd, shell=True, stdout=subprocess.PIPE) assert_equal(err, 0, "ERROR : nvme reset failed") time.sleep(5) rescan_cmd = "echo 1 > /sys/bus/pci/rescan" proc = subprocess.Popen(rescan_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) time.sleep(5) assert_equal(proc.wait(), 0, "ERROR : pci rescan failed") @tools.nottest def get_ctrl_id(self): """ Wrapper for extracting the controller id. - Args: - None - Returns: - controller id. """ get_ctrl_id = "nvme list-ctrl " + self.ctrl proc = subprocess.Popen(get_ctrl_id, shell=True, stdout=subprocess.PIPE) err = proc.wait() assert_equal(err, 0, "ERROR : nvme list-ctrl failed") line = proc.stdout.readline() ctrl_id = line.split(":")[1].strip() return ctrl_id @tools.nottest def get_ns_list(self): """ Wrapper for extrating the namespace list. - Args: - None - Returns: - List of the namespaces. """ ns_list = [] ns_list_cmd = "nvme list-ns " + self.ctrl proc = subprocess.Popen(ns_list_cmd, shell=True, stdout=subprocess.PIPE) assert_equal(proc.wait(), 0, "ERROR : nvme list namespace failed") for line in proc.stdout: ns_list.append(string.replace(line.split(":")[1], '\n', '')) return ns_list @tools.nottest def get_max_ns(self): """ Wrapper for extracting maximum number of namspaces supported. - Args: - None - Returns: - maximum number of namespaces supported. """ pattern = re.compile("^nn[ ]+: [0-9]", re.IGNORECASE) max_ns = -1 max_ns_cmd = "nvme id-ctrl " + self.ctrl proc = subprocess.Popen(max_ns_cmd, shell=True, stdout=subprocess.PIPE) err = proc.wait() assert_equal(err, 0, "ERROR : reading maximum namespace count failed") for line in proc.stdout: if pattern.match(line): max_ns = line.split(":")[1].strip() break print max_ns return int(max_ns) @tools.nottest def delete_all_ns(self): """ Wrapper for deleting all the namespaces. - Args: - None - Returns: - None """ delete_ns_cmd = "nvme delete-ns " + self.ctrl + " -n 0xFFFFFFFF" assert_equal(self.exec_cmd(delete_ns_cmd), 0) list_ns_cmd = "nvme list-ns " + self.ctrl + " --all | wc -l" proc = subprocess.Popen(list_ns_cmd, shell=True, stdout=subprocess.PIPE) output = proc.stdout.read().strip() assert_equal(output, '0', "ERROR : deleting all namespace failed") @tools.nottest def create_ns(self, nsze, ncap, flbas, dps): """ Wrapper for creating a namespace. - Args: - nsze : new namespace size. - ncap : new namespace capacity. - flbas : new namespace format. - dps : new namespace data protection information. - Returns: - return code of the nvme create namespace command. """ create_ns_cmd = "nvme create-ns " + self.ctrl + " --nsze=" + \ str(nsze) + " --ncap=" + str(ncap) + \ " --flbas=" + str(flbas) + " --dps=" + str(dps) return self.exec_cmd(create_ns_cmd) @tools.nottest def create_and_validate_ns(self, nsid, nsze, ncap, flbas, dps): """ Wrapper for creating and validating a namespace. - Args: - nsid : new namespace id. - nsze : new namespace size. - ncap : new namespace capacity. - flbas : new namespace format. - dps : new namespace data protection information. - Returns: - return 0 on success, error code on failure. """ err = self.create_ns(nsze, ncap, flbas, dps) if err == 0: time.sleep(2) id_ns_cmd = "nvme id-ns " + self.ctrl + " -n " + str(nsid) err = subprocess.call(id_ns_cmd, shell=True, stdout=subprocess.PIPE) return err @tools.nottest def attach_ns(self, ctrl_id, ns_id): """ Wrapper for attaching the namespace. - Args: - ctrl_id : controller id to which namespace to be attched. - nsid : new namespace id. - Returns: - 0 on success, error code on failure. """ attach_ns_cmd = "nvme attach-ns " + self.ctrl + \ " --namespace-id=" + str(ns_id) + \ " --controllers=" + ctrl_id err = subprocess.call(attach_ns_cmd, shell=True, stdout=subprocess.PIPE) time.sleep(5) if err == 0: # enumerate new namespace block device self.nvme_reset_ctrl() time.sleep(5) # check if new namespace block device exists err = 0 if stat.S_ISBLK(os.stat(self.ns1).st_mode) else 1 return err @tools.nottest def detach_ns(self, ctrl_id, nsid): """ Wrapper for detaching the namespace. - Args: - ctrl_id : controller id to which namespace to be attched. - nsid : new namespace id. - Returns: - 0 on success, error code on failure. """ detach_ns_cmd = "nvme detach-ns " + self.ctrl + \ " --namespace-id=" + str(nsid) + \ " --controllers=" + ctrl_id return subprocess.call(detach_ns_cmd, shell=True, stdout=subprocess.PIPE) @tools.nottest def delete_and_validate_ns(self, nsid): """ Wrapper for deleting and validating that namespace is deleted. - Args: - nsid : new namespace id. - Returns: - 0 on success, 1 on failure. """ # delete the namespace delete_ns_cmd = "nvme delete-ns " + self.ctrl + " -n " + str(nsid) err = subprocess.call(delete_ns_cmd, shell=True, stdout=subprocess.PIPE) assert_equal(err, 0, "ERROR : delete namespace failed") return err def get_smart_log(self, nsid): """ Wrapper for nvme smart-log command. - Args: - nsid : namespace id to get smart log from. - Returns: - 0 on success, error code on failure. """ smart_log_cmd = "nvme smart-log " + self.ctrl + " -n " + str(nsid) print smart_log_cmd proc = subprocess.Popen(smart_log_cmd, shell=True, stdout=subprocess.PIPE) err = proc.wait() assert_equal(err, 0, "ERROR : nvme smart log failed") for line in proc.stdout: if "data_units_read" in line: data_units_read = \ string.replace(line.split(":")[1].strip(), ",", "") if "data_units_written" in line: data_units_written = \ string.replace(line.split(":")[1].strip(), ",", "") if "host_read_commands" in line: host_read_commands = \ string.replace(line.split(":")[1].strip(), ",", "") if "host_write_commands" in line: host_write_commands = \ string.replace(line.split(":")[1].strip(), ",", "") print "data_units_read " + data_units_read print "data_units_written " + data_units_written print "host_read_commands " + host_read_commands print "host_write_commands " + host_write_commands return err def get_error_log(self, nsid): """ Wrapper for nvme error-log command. - Args: - nsid : namespace id to get error log from. - Returns: - 0 on success, error code on failure. """ pattern = re.compile("^ Entry\[[ ]*[0-9]+\]") error_log_cmd = "nvme error-log " + self.ctrl + " -n " + str(nsid) proc = subprocess.Popen(error_log_cmd, shell=True, stdout=subprocess.PIPE) err = proc.wait() assert_equal(err, 0, "ERROR : nvme error log failed") line = proc.stdout.readline() err_log_entry_count = int(line.split(" ")[5].strip().split(":")[1]) entry_count = 0 for line in proc.stdout: if pattern.match(line): entry_count += 1 return 0 if err_log_entry_count == entry_count else 1 def run_ns_io(self, nsid, lbads): """ Wrapper to run ios on namespace under test. - Args: - lbads : LBA Data size supported in power of 2 format. - Returns: - None """ block_size = mmap.PAGESIZE if lbads < 9 else 2 ** int(lbads) ns_path = self.ctrl + "n" + str(nsid) io_cmd = "dd if=" + ns_path + " of=/dev/null" + " bs=" + \ str(block_size) + " count=10 > /dev/null 2>&1" print io_cmd run_io = subprocess.Popen(io_cmd, shell=True, stdout=subprocess.PIPE) run_io_result = run_io.communicate()[1] assert_equal(run_io_result, None) io_cmd = "dd if=/dev/zero of=" + ns_path + " bs=" + \ str(block_size) + " count=10 > /dev/null 2>&1" print io_cmd run_io = subprocess.Popen(io_cmd, shell=True, stdout=subprocess.PIPE) run_io_result = run_io.communicate()[1] assert_equal(run_io_result, None) nvme-cli-1.5/tests/nvme_test_io.py000066400000000000000000000067211322317423600173110ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ Inherit TestNVMeIO for nvme read/write operations """ import os from nose import tools from nvme_test import TestNVMe class TestNVMeIO(TestNVMe): """ Variable and Methods required to perform nvme read/write. - Attributes: - data_size : data size to perform IO. - start_block : starting block of to perform IO. - block_count : Number of blocks to use in IO. - write_file : data file to use in nvme write command. - read_file : data file to use in nvme read command. """ def __init__(self): """ Pre Section for TestNVMeIO """ TestNVMe.__init__(self) # common code used in various testcases. self.data_size = 512 self.start_block = 0 self.block_count = 0 self.write_file = "write_file.txt" self.read_file = "read_file.txt" def __del__(self): """ Post Section for TestNVMeIO """ TestNVMe.__del__(self) @tools.nottest def create_data_file(self, pathname, data_size, pattern): """ Creates data file with specific pattern - Args: - pathname : data file path name. - data_size : total size of the data. - pattern : data pattern to create file. - Returns: None """ pattern_len = len(pattern) data_file = open(pathname, "w") for i in range(0, data_size): data_file.write(pattern[i % pattern_len]) data_file.flush() os.fsync(data_file.fileno()) data_file.close() @tools.nottest def nvme_write(self): """ Wrapper for nvme write operation - Args: - None - Returns: - return code for nvme write command. """ write_cmd = "nvme write " + self.ns1 + " --start-block=" + \ str(self.start_block) + " --block-count=" + \ str(self.block_count) + " --data-size=" + \ str(self.data_size) + " --data=" + self.write_file return self.exec_cmd(write_cmd) @tools.nottest def nvme_read(self): """ Wrapper for nvme read operation - Args: - None - Returns: - return code for nvme read command. """ read_cmd = "nvme read " + self.ns1 + " --start-block=" + \ str(self.start_block) + " --block-count=" + \ str(self.block_count) + " --data-size=" + \ str(self.data_size) + " --data=" + self.read_file print read_cmd return self.exec_cmd(read_cmd) nvme-cli-1.5/tests/nvme_test_logger.py000066400000000000000000000033051322317423600201540ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ Logger for NVMe Test Framwwork:- """ import sys class TestNVMeLogger(object): """ Represents Logger for NVMe Testframework. """ def __init__(self, log_file_path): """ Logger setup - Args: log_file_path : path to store the log. """ self.terminal = sys.stdout self.log = open(log_file_path, "w") def write(self, log_message): """ Logger setup - Args: log_message: string to write in the log file. - Returns: None """ self.terminal.write(log_message) self.log.write(log_message) def flush(self): """ This flush method is needed for python 3 compatibility. this handles the flush command by doing nothing. you might want to specify some extra behavior here. """ pass nvme-cli-1.5/tests/nvme_writeuncor_test.py000066400000000000000000000053001322317423600210730ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Write Compare Testcae:- 1. Read block of data successfully. 2. Issue write uncorrectable to block of data. 3. Attempt to read from same block; shall fail. 4. Issue a write command to first block of data. 5. Read from the same block; shall pass. """ from nose.tools import assert_equal, assert_not_equal from nvme_test_io import TestNVMeIO class TestNVMeUncor(TestNVMeIO): """ Represents NVMe Write Uncorrecatble testcase. - Attributes: - start_block : starting block of to perform IO. - test_log_dir : directory for logs, temp files. """ def __init__(self): """ Constructor TestNVMeUncor """ TestNVMeIO.__init__(self) self.start_block = 1023 self.setup_log_dir(self.__class__.__name__) self.write_file = self.test_log_dir + "/" + self.write_file self.read_file = self.test_log_dir + "/" + self.read_file self.create_data_file(self.write_file, self.data_size, "15") open(self.read_file, 'a').close() def __del__(self): """ Post Section for TestNVMeUncor """ TestNVMeIO.__del__(self) def write_uncor(self): """ Wrapper for nvme write uncorrectable - Args: - None - Returns: - return code of nvme write uncorrectable command. """ write_uncor_cmd = "nvme write-uncor " + self.ns1 + \ " --start-block=" + str(self.start_block) + \ " --block-count=" + str(self.block_count) return self.exec_cmd(write_uncor_cmd) def test_write_uncor(self): """ Testcase main """ assert_equal(self.nvme_read(), 0) assert_equal(self.write_uncor(), 0) assert_not_equal(self.nvme_read(), 0) assert_equal(self.nvme_write(), 0) assert_equal(self.nvme_read(), 0) nvme-cli-1.5/tests/nvme_writezeros_test.py000066400000000000000000000071751322317423600211230ustar00rootroot00000000000000# Copyright (c) 2015-2016 Western Digital Corporation or its affiliates. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # Author: Chaitanya Kulkarni # """ NVMe Write Zeros:- 1. Issue a write command to block of data. 2. Read from same block to verify data pattern. 3. Issue write zeros to the block of data. 4. Read from same block, should be all zeroes. """ import filecmp from nose.tools import assert_equal from nvme_test_io import TestNVMeIO class TestNVMeWriteZeros(TestNVMeIO): """ Represents NVMe Write Zero Testcase. - Attributes: - zero_file : file with all '\0' to compare the zero data. - data_size : data size to perform IO. - start_block : starting block of to perform IO. - block_count: Number of blocks to use in IO. - test_log_dir : directory for logs, temp files. """ def __init__(self): """ Pre Section for TestNVMeWriteZeros """ TestNVMeIO.__init__(self) self.start_block = 1023 self.block_count = 0 self.setup_log_dir(self.__class__.__name__) self.write_file = self.test_log_dir + "/" + self.write_file self.read_file = self.test_log_dir + "/" + self.read_file self.zero_file = self.test_log_dir + "/" + "zero_file.txt" self.create_data_file(self.write_file, self.data_size, "15") self.create_data_file(self.zero_file, self.data_size, '\0') open(self.read_file, 'a').close() def __del__(self): """ Post Section for TestNVMeWriteZeros """ TestNVMeIO.__del__(self) def write_zeroes(self): """ Wrapper for nvme write-zeroe - Args: - None - Returns: - return code for nvme write command. """ write_zeroes_cmd = "nvme write-zeroes " + self.ns1 + \ " --start-block=" + str(self.start_block) + \ " --block-count=" + str(self.block_count) return self.exec_cmd(write_zeroes_cmd) def validate_write_read(self): """ Validate the file which had been read from the device - Args: - None - Returns: - 0 on success, 1 on failure """ return 0 if filecmp.cmp(self.write_file, self.read_file) is True else 1 def validate_zeroes(self): """ Validate the data which is zeroed out via write-zeroes - Args: - None - Returns: - 0 on success, 1 on failure """ return 0 if filecmp.cmp(self.zero_file, self.read_file) is True else 1 def test_write_zeros(self): """ Testcae main """ assert_equal(self.nvme_write(), 0) assert_equal(self.nvme_read(), 0) assert_equal(self.validate_write_read(), 0) assert_equal(self.write_zeroes(), 0) assert_equal(self.nvme_read(), 0) assert_equal(self.validate_zeroes(), 0) nvme-cli-1.5/wdc-nvme.c000066400000000000000000001234751322317423600147740ustar00rootroot00000000000000/* * Copyright (c) 2015-2017 Western Digital Corporation or its affiliates. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * Author: Chaitanya Kulkarni , * Dong Ho */ #include #include #include #include #include #include #include #include #include "linux/nvme_ioctl.h" #include "nvme.h" #include "nvme-print.h" #include "nvme-ioctl.h" #include "plugin.h" #include "json.h" #include "argconfig.h" #include "suffix.h" #include #define CREATE_CMD #include "wdc-nvme.h" #define WRITE_SIZE (sizeof(__u8) * 4096) #define WDC_NVME_SUBCMD_SHIFT 8 #define WDC_NVME_LOG_SIZE_DATA_LEN 0x08 /* Device Config */ #define WDC_NVME_VID 0x1c58 #define WDC_NVME_SN100_CNTL_ID 0x0003 #define WDC_NVME_SN200_CNTL_ID 0x0023 /* Capture Diagnostics */ #define WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE WDC_NVME_LOG_SIZE_DATA_LEN #define WDC_NVME_CAP_DIAG_OPCODE 0xE6 #define WDC_NVME_CAP_DIAG_CMD_OPCODE 0xC6 #define WDC_NVME_CAP_DIAG_SUBCMD 0x00 #define WDC_NVME_CAP_DIAG_CMD 0x00 /* Crash dump */ #define WDC_NVME_CRASH_DUMP_SIZE_OPCODE WDC_NVME_CAP_DIAG_CMD_OPCODE #define WDC_NVME_CRASH_DUMP_SIZE_DATA_LEN WDC_NVME_LOG_SIZE_DATA_LEN #define WDC_NVME_CRASH_DUMP_SIZE_NDT 0x02 #define WDC_NVME_CRASH_DUMP_SIZE_CMD 0x20 #define WDC_NVME_CRASH_DUMP_SIZE_SUBCMD 0x03 #define WDC_NVME_CRASH_DUMP_OPCODE WDC_NVME_CAP_DIAG_CMD_OPCODE #define WDC_NVME_CRASH_DUMP_CMD 0x20 #define WDC_NVME_CRASH_DUMP_SUBCMD 0x04 /* Drive Log */ #define WDC_NVME_DRIVE_LOG_SIZE_OPCODE WDC_NVME_CAP_DIAG_CMD_OPCODE #define WDC_NVME_DRIVE_LOG_SIZE_DATA_LEN WDC_NVME_LOG_SIZE_DATA_LEN #define WDC_NVME_DRIVE_LOG_SIZE_NDT 0x02 #define WDC_NVME_DRIVE_LOG_SIZE_CMD 0x20 #define WDC_NVME_DRIVE_LOG_SIZE_SUBCMD 0x01 #define WDC_NVME_DRIVE_LOG_OPCODE WDC_NVME_CAP_DIAG_CMD_OPCODE #define WDC_NVME_DRIVE_LOG_CMD WDC_NVME_LOG_SIZE_DATA_LEN #define WDC_NVME_DRIVE_LOG_SUBCMD 0x00 /* Purge and Purge Monitor */ #define WDC_NVME_PURGE_CMD_OPCODE 0xDD #define WDC_NVME_PURGE_MONITOR_OPCODE 0xDE #define WDC_NVME_PURGE_MONITOR_DATA_LEN 0x2F #define WDC_NVME_PURGE_MONITOR_CMD_CDW10 0x0000000C #define WDC_NVME_PURGE_MONITOR_TIMEOUT 0x7530 #define WDC_NVME_PURGE_CMD_SEQ_ERR 0x0C #define WDC_NVME_PURGE_INT_DEV_ERR 0x06 #define WDC_NVME_PURGE_STATE_IDLE 0x00 #define WDC_NVME_PURGE_STATE_DONE 0x01 #define WDC_NVME_PURGE_STATE_BUSY 0x02 #define WDC_NVME_PURGE_STATE_REQ_PWR_CYC 0x03 #define WDC_NVME_PURGE_STATE_PWR_CYC_PURGE 0x04 /* Clear dumps */ #define WDC_NVME_CLEAR_DUMP_OPCODE 0xFF #define WDC_NVME_CLEAR_CRASH_DUMP_CMD 0x03 #define WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD 0x05 /* Additional Smart Log */ #define WDC_ADD_LOG_BUF_LEN 0x4000 #define WDC_NVME_ADD_LOG_OPCODE 0xC1 #define WDC_GET_LOG_PAGE_SSD_PERFORMANCE 0x37 #define WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME 0x0F /* C2 Log Page */ #define WDC_NVME_GET_AVAILABLE_LOG_PAGES_OPCODE 0xC2 #define WDC_C2_LOG_BUF_LEN 0x1000 #define WDC_C2_LOG_PAGES_SUPPORTED_ID 0x08 /* CA Log Page */ #define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE 0xCA #define WDC_CA_LOG_BUF_LEN 0x80 static int wdc_get_serial_name(int fd, char *file, size_t len, char *suffix); static int wdc_create_log_file(char *file, __u8 *drive_log_data, __u32 drive_log_length); static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12); static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, __u32 cdw10, __u32 cdw12, __u32 dump_length, char *file); static int wdc_do_crash_dump(int fd, char *file); static int wdc_crash_dump(int fd, char *file); static int wdc_get_crash_dump(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_do_drive_log(int fd, char *file); static int wdc_drive_log(int argc, char **argv, struct command *command, struct plugin *plugin); static const char* wdc_purge_mon_status_to_string(__u32 status); static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_purge_monitor(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_nvme_check_supported_log_page(int fd, __u8 log_id); /* Drive log data size */ struct wdc_log_size { __le32 log_size; }; /* Purge monitor response */ struct wdc_nvme_purge_monitor_data { __le16 rsvd1; __le16 rsvd2; __le16 first_erase_failure_cnt; __le16 second_erase_failure_cnt; __le16 rsvd3; __le16 programm_failure_cnt; __le32 rsvd4; __le32 rsvd5; __le32 entire_progress_total; __le32 entire_progress_current; __u8 rsvd6[14]; }; /* Additional Smart Log */ struct wdc_log_page_header { uint8_t num_subpages; uint8_t reserved; __le16 total_log_size; }; struct wdc_log_page_subpage_header { uint8_t spcode; uint8_t pcset; __le16 subpage_length; }; struct wdc_ssd_perf_stats { __le64 hr_cmds; /* Host Read Commands */ __le64 hr_blks; /* Host Read Blocks */ __le64 hr_ch_cmds; /* Host Read Cache Hit Commands */ __le64 hr_ch_blks; /* Host Read Cache Hit Blocks */ __le64 hr_st_cmds; /* Host Read Stalled Commands */ __le64 hw_cmds; /* Host Write Commands */ __le64 hw_blks; /* Host Write Blocks */ __le64 hw_os_cmds; /* Host Write Odd Start Commands */ __le64 hw_oe_cmds; /* Host Write Odd End Commands */ __le64 hw_st_cmds; /* Host Write Commands Stalled */ __le64 nr_cmds; /* NAND Read Commands */ __le64 nr_blks; /* NAND Read Blocks */ __le64 nw_cmds; /* NAND Write Commands */ __le64 nw_blks; /* NAND Write Blocks */ __le64 nrbw; /* NAND Read Before Write */ }; /* Additional C2 Log Page */ struct wdc_c2_log_page_header { __le32 length; __le32 version; }; struct wdc_c2_log_subpage_header { __le32 length; __le32 entry_id; __le32 data; }; struct wdc_c2_cbs_data { __le32 length; __u8 data[]; }; struct __attribute__((__packed__)) wdc_ssd_ca_perf_stats { __le64 nand_bytes_wr_lo; /* 0x00 - NAND Bytes Written lo */ __le64 nand_bytes_wr_hi; /* 0x08 - NAND Bytes Written hi */ __le64 nand_bytes_rd_lo; /* 0x10 - NAND Bytes Read lo */ __le64 nand_bytes_rd_hi; /* 0x18 - NAND Bytes Read hi */ __le64 nand_bad_block; /* 0x20 - NAND Bad Block Count */ __le64 uncorr_read_count; /* 0x28 - Uncorrectable Read Count */ __le64 ecc_error_count; /* 0x30 - Soft ECC Error Count */ __le32 ssd_detect_count; /* 0x38 - SSD End to End Detection Count */ __le32 ssd_correct_count; /* 0x3C - SSD End to End Correction Count */ __le32 data_percent_used; /* 0x40 - System Data Percent Used */ __le32 data_erase_max; /* 0x44 - User Data Erase Counts */ __le32 data_erase_min; /* 0x48 - User Data Erase Counts */ __le64 refresh_count; /* 0x4c - Refresh Count */ __le64 program_fail; /* 0x54 - Program Fail Count */ __le64 user_erase_fail; /* 0x5C - User Data Erase Fail Count */ __le64 system_erase_fail; /* 0x64 - System Area Erase Fail Count */ __le16 thermal_throttle_status; /* 0x6C - Thermal Throttling Status */ __le16 thermal_throttle_count; /* 0x6E - Thermal Throttling Count */ __le64 pcie_corr_error; /* 0x70 - pcie Correctable Error Count */ __le32 rsvd1; /* 0x78 - Reserved */ __le32 rsvd2; /* 0x7C - Reserved */ }; static double safe_div_fp(double numerator, double denominator) { return denominator ? numerator / denominator : 0; } static double calc_percent(uint64_t numerator, uint64_t denominator) { return denominator ? (uint64_t)(((double)numerator / (double)denominator) * 100) : 0; } static int wdc_check_device(int fd) { int ret; struct nvme_id_ctrl ctrl; memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); ret = nvme_identify_ctrl(fd, &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); return -1; } ret = -1; /* WDC : ctrl->cntlid == PCI Device ID, use that with VID to identify WDC Devices */ if ((le32_to_cpu(ctrl.vid) == WDC_NVME_VID) && ((le32_to_cpu(ctrl.cntlid) == WDC_NVME_SN100_CNTL_ID) || (le32_to_cpu(ctrl.cntlid) == WDC_NVME_SN200_CNTL_ID))) ret = 0; else fprintf(stderr, "WARNING : WDC : Device not supported\n"); return ret; } static bool wdc_check_device_sn100(int fd) { bool ret; struct nvme_id_ctrl ctrl; memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); ret = nvme_identify_ctrl(fd, &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); return false; } /* WDC : ctrl->cntlid == PCI Device ID, use that with VID to identify WDC Devices */ if ((le32_to_cpu(ctrl.vid) == WDC_NVME_VID) && (le32_to_cpu(ctrl.cntlid) == WDC_NVME_SN100_CNTL_ID)) ret = true; else ret = false; return ret; } static bool wdc_check_device_sn200(int fd) { bool ret; struct nvme_id_ctrl ctrl; memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); ret = nvme_identify_ctrl(fd, &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); return false; } /* WDC : ctrl->cntlid == PCI Device ID, use that with VID to identify WDC Devices */ if ((le32_to_cpu(ctrl.vid) == WDC_NVME_VID) && (le32_to_cpu(ctrl.cntlid) == WDC_NVME_SN200_CNTL_ID)) ret = true; else ret = false; return ret; } static int wdc_get_serial_name(int fd, char *file, size_t len, char *suffix) { int i; int ret; char orig[PATH_MAX] = {0}; struct nvme_id_ctrl ctrl; i = sizeof (ctrl.sn) - 1; strncpy(orig, file, PATH_MAX); memset(file, 0, len); memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); ret = nvme_identify_ctrl(fd, &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); return -1; } /* Remove trailing spaces from the name */ while (i && ctrl.sn[i] == ' ') { ctrl.sn[i] = '\0'; i--; } snprintf(file, len, "%s%s%s.bin", orig, ctrl.sn, suffix); return 0; } static int wdc_create_log_file(char *file, __u8 *drive_log_data, __u32 drive_log_length) { int fd; int ret; if (drive_log_length == 0) { fprintf(stderr, "ERROR : WDC: invalid log file length\n"); return -1; } fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { fprintf(stderr, "ERROR : WDC: open : %s\n", strerror(errno)); return -1; } while (drive_log_length > WRITE_SIZE) { ret = write(fd, drive_log_data, WRITE_SIZE); if (ret < 0) { fprintf (stderr, "ERROR : WDC: write : %s\n", strerror(errno)); return -1; } drive_log_data += WRITE_SIZE; drive_log_length -= WRITE_SIZE; } ret = write(fd, drive_log_data, drive_log_length); if (ret < 0) { fprintf(stderr, "ERROR : WDC : write : %s\n", strerror(errno)); return -1; } if (fsync(fd) < 0) { fprintf(stderr, "ERROR : WDC : fsync : %s\n", strerror(errno)); return -1; } close(fd); return 0; } static int wdc_nvme_check_supported_log_page(int fd, __u8 log_id) { int i; int ret = -1; int found = 0; __u8* data; __u32 length = 0; struct wdc_c2_cbs_data *cbs_data; struct wdc_c2_log_page_header *hdr_ptr; struct wdc_c2_log_subpage_header *sph; if ((data = (__u8*) malloc(sizeof (__u8) * WDC_C2_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return ret; } memset(data, 0, sizeof (__u8) * WDC_C2_LOG_BUF_LEN); /* get the log page length */ ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_AVAILABLE_LOG_PAGES_OPCODE, WDC_C2_LOG_BUF_LEN, data); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to get C2 Log Page length, ret = %d\n", ret); goto out; } hdr_ptr = (struct wdc_c2_log_page_header *)data; if (hdr_ptr->length > WDC_C2_LOG_BUF_LEN) { fprintf(stderr, "ERROR : WDC : data length > buffer size : 0x%x\n", hdr_ptr->length); goto out; } ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_AVAILABLE_LOG_PAGES_OPCODE, hdr_ptr->length, data); /* parse the data until the List of log page ID's is found */ if (ret) { fprintf(stderr, "ERROR : WDC : Unable to read C2 Log Page data, ret = %d\n", ret); goto out; } length = sizeof(struct wdc_c2_log_page_header); while (length < hdr_ptr->length) { sph = (struct wdc_c2_log_subpage_header *)(data + length); if (sph->entry_id == WDC_C2_LOG_PAGES_SUPPORTED_ID) { cbs_data = (struct wdc_c2_cbs_data *)&sph->data; for (i = 0; i < cbs_data->length; i++) { if (log_id == cbs_data->data[i]) { found = 1; ret = 0; break; } } if (!found) { fprintf(stderr, "ERROR : WDC : Log Page 0x%x not supported\n", log_id); fprintf(stderr, "WDC : Supported Log Pages:\n"); /* print the supported pages */ d((__u8 *)&sph->data + 4, sph->length - 12, 16, 1); ret = -1; } break; } length += le32_to_cpu(sph->length); } out: free(data); return ret; } static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12) { int ret; struct nvme_admin_cmd admin_cmd; memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); admin_cmd.opcode = opcode; admin_cmd.cdw12 = cdw12; ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); if (ret != 0) { fprintf(stdout, "ERROR : WDC : Crash dump erase failed\n"); } fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; } static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length) { int ret; __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN] = {0}; struct wdc_log_size *l; struct nvme_admin_cmd admin_cmd; l = (struct wdc_log_size *) buf; memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); admin_cmd.opcode = opcode; admin_cmd.addr = (__u64)(uintptr_t)buf; admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN; admin_cmd.cdw10 = cdw10; admin_cmd.cdw12 = cdw12; ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); if (ret != 0) { l->log_size = 0; ret = -1; fprintf(stderr, "ERROR : WDC : reading dump length failed\n"); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; } if (opcode == WDC_NVME_CAP_DIAG_OPCODE) *dump_length = buf[0x04] << 24 | buf[0x05] << 16 | buf[0x06] << 8 | buf[0x07]; else *dump_length = le32_to_cpu(l->log_size); return ret; } static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, __u32 cdw10, __u32 cdw12, __u32 dump_length, char *file) { int ret; __u8 *dump_data; struct nvme_admin_cmd admin_cmd; dump_data = (__u8 *) malloc(sizeof (__u8) * dump_length); if (dump_data == NULL) { fprintf(stderr, "ERROR : malloc : %s\n", strerror(errno)); return -1; } memset(dump_data, 0, sizeof (__u8) * dump_length); memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); admin_cmd.opcode = opcode; admin_cmd.addr = (__u64)(uintptr_t)dump_data; admin_cmd.data_len = data_len; admin_cmd.cdw10 = cdw10; admin_cmd.cdw12 = cdw12; ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); if (ret == 0) { ret = wdc_create_log_file(file, dump_data, dump_length); } free(dump_data); return ret; } static int wdc_do_cap_diag(int fd, char *file) { int ret; __u32 cap_diag_length; ret = wdc_dump_length(fd, WDC_NVME_CAP_DIAG_OPCODE, WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE, 0x00, &cap_diag_length); if (ret == -1) { return -1; } if (cap_diag_length == 0) { fprintf(stderr, "INFO : WDC : Capture Dignostics log is empty\n"); } else { ret = wdc_do_dump(fd, WDC_NVME_CAP_DIAG_OPCODE, cap_diag_length, cap_diag_length, (WDC_NVME_CAP_DIAG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CAP_DIAG_CMD, cap_diag_length, file); } return ret; } static int wdc_cap_diag(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Capture Diagnostics Log."; char *file = "Output file pathname."; char f[PATH_MAX] = {0}; int fd; struct config { char *file; }; struct config cfg = { .file = NULL }; const struct argconfig_commandline_options command_line_options[] = { {"output-file", 'o', "FILE", CFG_STRING, &cfg.file, required_argument, file}, { NULL, '\0', NULL, CFG_NONE, NULL, no_argument, desc}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; wdc_check_device(fd); if (cfg.file != NULL) { strncpy(f, cfg.file, PATH_MAX); } if (wdc_get_serial_name(fd, f, PATH_MAX, "cap_diag") == -1) { fprintf(stderr, "ERROR : WDC: failed to generate file name\n"); return -1; } return wdc_do_cap_diag(fd, f); } static int wdc_do_crash_dump(int fd, char *file) { int ret; __u32 crash_dump_length; __u8 opcode = WDC_NVME_CLEAR_DUMP_OPCODE; __u32 cdw12 = ((WDC_NVME_CLEAR_CRASH_DUMP_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_CRASH_DUMP_CMD); ret = wdc_dump_length(fd, WDC_NVME_CRASH_DUMP_SIZE_OPCODE, WDC_NVME_CRASH_DUMP_SIZE_NDT, ((WDC_NVME_CRASH_DUMP_SIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CRASH_DUMP_SIZE_CMD), &crash_dump_length); if (ret == -1) { return -1; } if (crash_dump_length == 0) { fprintf(stderr, "INFO : WDC: Crash dump is empty\n"); } else { ret = wdc_do_dump(fd, WDC_NVME_CRASH_DUMP_OPCODE, crash_dump_length, crash_dump_length, (WDC_NVME_CRASH_DUMP_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CRASH_DUMP_CMD, crash_dump_length, file); if (ret == 0) ret = wdc_do_clear_dump(fd, opcode, cdw12); } return ret; } static int wdc_crash_dump(int fd, char *file) { char f[PATH_MAX] = {0}; if (file != NULL) { strncpy(f, file, PATH_MAX); } if (wdc_get_serial_name(fd, f, PATH_MAX, "crash_dump") == -1) { fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); return -1; } return wdc_do_crash_dump(fd, f); } static int wdc_do_drive_log(int fd, char *file) { int ret; __u8 *drive_log_data; __u32 drive_log_length; struct nvme_admin_cmd admin_cmd; ret = wdc_dump_length(fd, WDC_NVME_DRIVE_LOG_SIZE_OPCODE, WDC_NVME_DRIVE_LOG_SIZE_NDT, (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT | WDC_NVME_DRIVE_LOG_SIZE_CMD), &drive_log_length); if (ret == -1) { return -1; } drive_log_data = (__u8 *) malloc(sizeof (__u8) * drive_log_length); if (drive_log_data == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return -1; } memset(drive_log_data, 0, sizeof (__u8) * drive_log_length); memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)drive_log_data; admin_cmd.data_len = drive_log_length; admin_cmd.cdw10 = drive_log_length; admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_LOG_SIZE_CMD); ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); if (ret == 0) { ret = wdc_create_log_file(file, drive_log_data, drive_log_length); } free(drive_log_data); return ret; } static int wdc_drive_log(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Capture Drive Log."; char *file = "Output file pathname."; char f[PATH_MAX] = {0}; int fd; struct config { char *file; }; struct config cfg = { .file = NULL }; const struct argconfig_commandline_options command_line_options[] = { {"output-file", 'o', "FILE", CFG_STRING, &cfg.file, required_argument, file}, { NULL, '\0', NULL, CFG_NONE, NULL, no_argument, desc}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; wdc_check_device(fd); if (cfg.file != NULL) { strncpy(f, cfg.file, PATH_MAX); } if (wdc_get_serial_name(fd, f, PATH_MAX, "drive_log") == -1) { fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); return -1; } return wdc_do_drive_log(fd, f); } static int wdc_get_crash_dump(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Get Crash Dump."; char *file = "Output file pathname."; int fd; int ret; struct config { char *file; }; struct config cfg = { .file = NULL, }; const struct argconfig_commandline_options command_line_options[] = { {"output-file", 'o', "FILE", CFG_STRING, &cfg.file, required_argument, file}, { NULL, '\0', NULL, CFG_NONE, NULL, no_argument, desc}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; wdc_check_device(fd); ret = wdc_crash_dump(fd, cfg.file); if (ret != 0) { fprintf(stderr, "ERROR : WDC : failed to read crash dump\n"); } return ret; } static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root) { char vsn[24] = {0}; int base = 3072; int vsn_start = 3081; memcpy(vsn, &vs[vsn_start - base], sizeof(vsn)); if (root) json_object_add_value_string(root, "wdc vsn", strlen(vsn) > 1 ? vsn : "NULL"); else printf("wdc vsn : %s\n", strlen(vsn) > 1 ? vsn : "NULL"); } static int wdc_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return __id_ctrl(argc, argv, cmd, plugin, wdc_do_id_ctrl); } static const char* wdc_purge_mon_status_to_string(__u32 status) { const char *str; switch (status) { case WDC_NVME_PURGE_STATE_IDLE: str = "Purge State Idle."; break; case WDC_NVME_PURGE_STATE_DONE: str = "Purge State Done."; break; case WDC_NVME_PURGE_STATE_BUSY: str = "Purge State Busy."; break; case WDC_NVME_PURGE_STATE_REQ_PWR_CYC: str = "Purge Operation resulted in an error that requires " "power cycle."; break; case WDC_NVME_PURGE_STATE_PWR_CYC_PURGE: str = "The previous purge operation was interrupted by a power " "cycle\nor reset interruption. Other commands may be " "rejected until\nPurge Execute is issued and " "completed."; break; default: str = "Unknown."; } return str; } static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Send a Purge command."; char *err_str; int fd; int ret; struct nvme_passthru_cmd admin_cmd; const struct argconfig_commandline_options command_line_options[] = { { NULL, '\0', NULL, CFG_NONE, NULL, no_argument, desc }, {NULL} }; err_str = ""; memset(&admin_cmd, 0, sizeof (admin_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; wdc_check_device(fd); ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); if (ret > 0) { switch (ret) { case WDC_NVME_PURGE_CMD_SEQ_ERR: err_str = "ERROR : WDC : Cannot execute purge, " "Purge operation is in progress.\n"; break; case WDC_NVME_PURGE_INT_DEV_ERR: err_str = "ERROR : WDC : Internal Device Error.\n"; break; default: err_str = "ERROR : WDC\n"; } } fprintf(stderr, "%s", err_str); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; } static int wdc_purge_monitor(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Send a Purge Monitor command."; int fd; int ret; __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN]; double progress_percent; struct nvme_passthru_cmd admin_cmd; struct wdc_nvme_purge_monitor_data *mon; const struct argconfig_commandline_options command_line_options[] = { { NULL, '\0', NULL, CFG_NONE, NULL, no_argument, desc }, {NULL} }; memset(output, 0, sizeof (output)); memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)output; admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN; admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW10; admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; wdc_check_device(fd); ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); if (ret == 0) { mon = (struct wdc_nvme_purge_monitor_data *) output; printf("Purge state = 0x%0x\n", admin_cmd.result); printf("%s\n", wdc_purge_mon_status_to_string(admin_cmd.result)); if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY) { progress_percent = ((double)le32_to_cpu(mon->entire_progress_current) * 100) / le32_to_cpu(mon->entire_progress_total); printf("Purge Progress = %f%%\n", progress_percent); } } fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; } static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf) { printf(" C1 Log Page Performance Statistics :- \n"); printf(" Host Read Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hr_cmds)); printf(" Host Read Blocks %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hr_blks)); printf(" Average Read Size %20lf\n", safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds)))); printf(" Host Read Cache Hit Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hr_ch_cmds)); printf(" Host Read Cache Hit_Percentage %20"PRIu64"%%\n", (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds))); printf(" Host Read Cache Hit Blocks %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hr_ch_blks)); printf(" Average Read Cache Hit Size %20f\n", safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds)))); printf(" Host Read Commands Stalled %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hr_st_cmds)); printf(" Host Read Commands Stalled Percentage %20"PRIu64"%%\n", (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds))); printf(" Host Write Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hw_cmds)); printf(" Host Write Blocks %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hw_blks)); printf(" Average Write Size %20f\n", safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds)))); printf(" Host Write Odd Start Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hw_os_cmds)); printf(" Host Write Odd Start Commands Percentage %20"PRIu64"%%\n", (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds)))); printf(" Host Write Odd End Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hw_oe_cmds)); printf(" Host Write Odd End Commands Percentage %20"PRIu64"%%\n", (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds))))); printf(" Host Write Commands Stalled %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hw_st_cmds)); printf(" Host Write Commands Stalled Percentage %20"PRIu64"%%\n", (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds)))); printf(" NAND Read Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nr_cmds)); printf(" NAND Read Blocks Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nr_blks)); printf(" Average NAND Read Size %20f\n", safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds))))); printf(" Host Write Odd Start Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->hw_os_cmds)); printf(" Nand Write Commands %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nw_cmds)); printf(" NAND Write Blocks %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nw_blks)); printf(" Average NAND Write Size %20f\n", safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds)))); printf(" NAND Read Before Write %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nrbw)); } static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf) { struct json_object *root; root = json_create_object(); json_object_add_value_int(root, "Host Read Commands", le64_to_cpu(perf->hr_cmds)); json_object_add_value_int(root, "Host Read Blocks", le64_to_cpu(perf->hr_blks)); json_object_add_value_int(root, "Average Read Size", safe_div_fp((le64_to_cpu(perf->hr_blks)), (le64_to_cpu(perf->hr_cmds)))); json_object_add_value_int(root, "Host Read Cache Hit Commands", (uint64_t)le64_to_cpu(perf->hr_ch_cmds)); json_object_add_value_int(root, "Host Read Cache Hit Percentage", (uint64_t) calc_percent(le64_to_cpu(perf->hr_ch_cmds), le64_to_cpu(perf->hr_cmds))); json_object_add_value_int(root, "Host Read Cache Hit Blocks", (uint64_t)le64_to_cpu(perf->hr_ch_blks)); json_object_add_value_int(root, "Average Read Cache Hit Size", safe_div_fp((le64_to_cpu(perf->hr_ch_blks)), (le64_to_cpu(perf->hr_ch_cmds)))); json_object_add_value_int(root, "Host Read Commands Stalled", (uint64_t)le64_to_cpu(perf->hr_st_cmds)); json_object_add_value_int(root, "Host Read Commands Stalled Percentage", (uint64_t)calc_percent((le64_to_cpu(perf->hr_st_cmds)), le64_to_cpu(perf->hr_cmds))); json_object_add_value_int(root, "Host Write Commands", (uint64_t)le64_to_cpu(perf->hw_cmds)); json_object_add_value_int(root, "Host Write Blocks", (uint64_t)le64_to_cpu(perf->hw_blks)); json_object_add_value_int(root, "Average Write Size", safe_div_fp((le64_to_cpu(perf->hw_blks)), (le64_to_cpu(perf->hw_cmds)))); json_object_add_value_int(root, "Host Write Odd Start Commands", (uint64_t)le64_to_cpu(perf->hw_os_cmds)); json_object_add_value_int(root, "Host Write Odd Start Commands Percentage", (uint64_t)calc_percent((le64_to_cpu(perf->hw_os_cmds)), (le64_to_cpu(perf->hw_cmds)))); json_object_add_value_int(root, "Host Write Odd End Commands", (uint64_t)le64_to_cpu(perf->hw_oe_cmds)); json_object_add_value_int(root, "Host Write Odd End Commands Percentage", (uint64_t)calc_percent((le64_to_cpu(perf->hw_oe_cmds)), (le64_to_cpu((perf->hw_cmds))))); json_object_add_value_int(root, "Host Write Commands Stalled", (uint64_t)le64_to_cpu(perf->hw_st_cmds)); json_object_add_value_int(root, "Host Write Commands Stalled Percentage", (uint64_t)calc_percent((le64_to_cpu(perf->hw_st_cmds)), (le64_to_cpu(perf->hw_cmds)))); json_object_add_value_int(root, "NAND Read Commands", (uint64_t)le64_to_cpu(perf->nr_cmds)); json_object_add_value_int(root, "NAND Read Blocks Commands", (uint64_t)le64_to_cpu(perf->nr_blks)); json_object_add_value_int(root, "Average NAND Read Size", safe_div_fp((le64_to_cpu(perf->nr_blks)), (le64_to_cpu((perf->nr_cmds))))); json_object_add_value_int(root, "Host Write Odd Start Commands", (uint64_t)le64_to_cpu(perf->hw_os_cmds)); json_object_add_value_int(root, "Nand Write Commands", (uint64_t)le64_to_cpu(perf->nw_cmds)); json_object_add_value_int(root, "NAND Write Blocks", (uint64_t)le64_to_cpu(perf->nw_blks)); json_object_add_value_int(root, "Average NAND Write Size", safe_div_fp((le64_to_cpu(perf->nw_blks)), (le64_to_cpu(perf->nw_cmds)))); json_object_add_value_int(root, "NAND Read Before Written", (uint64_t)le64_to_cpu(perf->nrbw)); json_print_object(root, NULL); printf("\n"); json_free_object(root); } static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt) { if (!perf) { fprintf(stderr, "ERROR : WDC : Invalid buffer to read perf stats\n"); return -1; } switch (fmt) { case NORMAL: wdc_print_log_normal(perf); break; case JSON: wdc_print_log_json(perf); break; } return 0; } static void wdc_print_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf) { printf(" CA Log Page Performance Statistics :- \n"); printf(" NAND Bytes Written %20"PRIu64 "%20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nand_bytes_wr_hi), (uint64_t)le64_to_cpu(perf->nand_bytes_wr_lo)); printf(" NAND Bytes Read %20"PRIu64 "%20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nand_bytes_rd_hi), (uint64_t)le64_to_cpu(perf->nand_bytes_rd_lo)); printf(" NAND Bad Block Count (Normalized) %20"PRIu16"\n", (uint16_t)le16_to_cpu(perf->nand_bad_block & 0x000000000000FFFF)); printf(" NAND Bad Block Count (Raw) %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->nand_bad_block & 0xFFFFFFFFFFFF0000)>>16); printf(" Uncorrectable Read Count %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->uncorr_read_count)); printf(" Soft ECC Error Count %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->ecc_error_count)); printf(" SSD End to End Detected Correction Count %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->ssd_detect_count)); printf(" SSD End to End Corrected Correction Count %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->ssd_correct_count)); printf(" System Data Percent Used %20"PRIu32"%%\n", (uint32_t)le32_to_cpu(perf->data_percent_used)); printf(" User Data Erase Counts Max %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->data_erase_max)); printf(" User Data Erase Counts Min %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->data_erase_min)); printf(" Refresh Count %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->refresh_count)); printf(" Program Fail Count (Normalized) %20"PRIu16"\n", (uint16_t)le16_to_cpu(perf->program_fail & 0x000000000000FFFF)); printf(" Program Fail Count (Raw) %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->program_fail & 0xFFFFFFFFFFFF0000)>>16); printf(" User Data Erase Fail Count (Normalized) %20"PRIu16"\n", (uint16_t)le16_to_cpu(perf->user_erase_fail & 0x000000000000FFFF)); printf(" User Data Erase Fail Count (Raw) %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->user_erase_fail & 0xFFFFFFFFFFFF0000)>>16); printf(" System Area Erase Fail Count (Normalized) %20"PRIu16"\n", (uint16_t)le16_to_cpu(perf->system_erase_fail & 0x000000000000FFFF)); printf(" System Area Erase Fail Count (Raw) %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->system_erase_fail & 0xFFFFFFFFFFFF0000)>>16); printf(" Thermal Throttling Status %20"PRIu16"\n", (uint16_t)le16_to_cpu(perf->thermal_throttle_status)); printf(" Thermal Throttling Count %20"PRIu16"\n", (uint16_t)le16_to_cpu(perf->thermal_throttle_count)); printf(" PCIe Correctable Error Count %20"PRIu64"\n", (uint64_t)le64_to_cpu(perf->pcie_corr_error)); } static void wdc_print_ca_log_json(struct wdc_ssd_ca_perf_stats *perf) { struct json_object *root; root = json_create_object(); json_object_add_value_int(root, "NAND Bytes Written Hi", le64_to_cpu(perf->nand_bytes_wr_hi)); json_object_add_value_int(root, "NAND Bytes Written Lo", le64_to_cpu(perf->nand_bytes_wr_lo)); json_object_add_value_int(root, "NAND Bytes Read Hi", le64_to_cpu(perf->nand_bytes_rd_hi)); json_object_add_value_int(root, "NAND Bytes Read Lo", le64_to_cpu(perf->nand_bytes_rd_lo)); json_object_add_value_int(root, "NAND Bad Block Count (Normalized)", le16_to_cpu(perf->nand_bad_block & 0x000000000000FFFF)); json_object_add_value_int(root, "NAND Bad Block Count (Raw)", le64_to_cpu(perf->nand_bad_block & 0xFFFFFFFFFFFF0000)>>16); json_object_add_value_int(root, "Uncorrectable Read Count", le64_to_cpu(perf->uncorr_read_count)); json_object_add_value_int(root, "Soft ECC Error Count", le64_to_cpu(perf->ecc_error_count)); json_object_add_value_int(root, "SSD End to End Detected Correction Count", le32_to_cpu(perf->ssd_detect_count)); json_object_add_value_int(root, "SSD End to End Corrected Correction Count", le32_to_cpu(perf->ssd_correct_count)); json_object_add_value_int(root, "System Data Percent Used", le32_to_cpu(perf->data_percent_used)); json_object_add_value_int(root, "User Data Erase Counts Max", le32_to_cpu(perf->data_erase_max)); json_object_add_value_int(root, "User Data Erase Counts Min", le32_to_cpu(perf->data_erase_min)); json_object_add_value_int(root, "Refresh Count", le64_to_cpu(perf->refresh_count)); json_object_add_value_int(root, "Program Fail Count (Normalized)", le16_to_cpu(perf->program_fail & 0x000000000000FFFF)); json_object_add_value_int(root, "Program Fail Count (Raw)", le64_to_cpu(perf->program_fail & 0xFFFFFFFFFFFF0000)>>16); json_object_add_value_int(root, "User Data Erase Fail Count (Normalized)", le16_to_cpu(perf->user_erase_fail & 0x000000000000FFFF)); json_object_add_value_int(root, "User Data Erase Fail Count (Raw)", le64_to_cpu(perf->user_erase_fail & 0xFFFFFFFFFFFF0000)>>16); json_object_add_value_int(root, "System Area Erase Fail Count (Normalized)", le16_to_cpu(perf->system_erase_fail & 0x000000000000FFFF)); json_object_add_value_int(root, "System Area Erase Fail Count (Raw)", le64_to_cpu(perf->system_erase_fail & 0xFFFFFFFFFFFF0000)>>16); json_object_add_value_int(root, "Thermal Throttling Status", le16_to_cpu(perf->thermal_throttle_status)); json_object_add_value_int(root, "Thermal Throttling Count", le16_to_cpu(perf->thermal_throttle_count)); json_object_add_value_int(root, "PCIe Correctable Error", le64_to_cpu(perf->pcie_corr_error)); json_print_object(root, NULL); printf("\n"); json_free_object(root); } static int wdc_print_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt) { if (!perf) { fprintf(stderr, "ERROR : WDC : Invalid buffer to read perf stats\n"); return -1; } switch (fmt) { case NORMAL: wdc_print_ca_log_normal(perf); break; case JSON: wdc_print_ca_log_json(perf); break; } return 0; } static int wdc_get_ca_log_page(int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; struct wdc_ssd_ca_perf_stats *perf; wdc_check_device(fd); fmt = validate_output_format(format); if (fmt < 0) { fprintf(stderr, "ERROR : WDC : invalid output format\n"); return fmt; } /* verify the 0xCA log page is supported */ if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE)) { fprintf(stderr, "ERROR : WDC : 0xCA Log Page not supported\n"); return -1; } if ((data = (__u8*) malloc(sizeof (__u8) * WDC_CA_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return -1; } memset(data, 0, sizeof (__u8) * WDC_CA_LOG_BUF_LEN); ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, WDC_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); if (ret == 0) { /* parse the data */ perf = (struct wdc_ssd_ca_perf_stats *)(data); ret = wdc_print_ca_log(perf, fmt); } else { fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data\n"); ret = -1; } free(data); return ret; } static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) { int ret = 0; int fmt = -1; __u8 *data; __u8 *p; int i; int skip_cnt = 4; int total_subpages; struct wdc_log_page_header *l; struct wdc_log_page_subpage_header *sph; struct wdc_ssd_perf_stats *perf; wdc_check_device(fd); fmt = validate_output_format(format); if (fmt < 0) { fprintf(stderr, "ERROR : WDC : invalid output format\n"); return fmt; } if (interval < 1 || interval > 15) { fprintf(stderr, "ERROR : WDC : interval out of range [1-15]\n"); return -1; } if ((data = (__u8*) malloc(sizeof (__u8) * WDC_ADD_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return -1; } memset(data, 0, sizeof (__u8) * WDC_ADD_LOG_BUF_LEN); ret = nvme_get_log(fd, 0x01, WDC_NVME_ADD_LOG_OPCODE, WDC_ADD_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); if (ret == 0) { l = (struct wdc_log_page_header*)data; total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME - 1; for (i = 0, p = data + skip_cnt; i < total_subpages; i++, p += skip_cnt) { sph = (struct wdc_log_page_subpage_header *) p; if (sph->spcode == WDC_GET_LOG_PAGE_SSD_PERFORMANCE) { if (sph->pcset == interval) { perf = (struct wdc_ssd_perf_stats *) (p + 4); ret = wdc_print_log(perf, fmt); break; } } skip_cnt = le32_to_cpu(sph->subpage_length) + 4; } if (ret) { fprintf(stderr, "ERROR : WDC : Unable to read data from buffer\n"); } } free(data); return ret; } static int wdc_smart_add_log(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Retrieve additional performance statistics."; char *interval = "Interval to read the statistics from [1, 15]."; int fd; int ret; struct config { uint8_t interval; int vendor_specific; char *output_format; }; struct config cfg = { .interval = 14, .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"interval", 'i', "NUM", CFG_POSITIVE, &cfg.interval, required_argument, interval}, {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, "Output Format: normal|json" }, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); if (fd < 0) return fd; if (wdc_check_device_sn100(fd)) { // Get the C1 Log Page ret = wdc_get_c1_log_page(fd, cfg.output_format, cfg.interval); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to read C1 Log Page data from buffer\n"); return ret; } } else if (wdc_check_device_sn200(fd)) { // Get the CA and C1 Log Page ret = wdc_get_ca_log_page(fd, cfg.output_format); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data from buffer\n"); return ret; } ret = wdc_get_c1_log_page(fd, cfg.output_format, cfg.interval); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to read C1 Log Page data from buffer\n"); return ret; } } else { fprintf(stderr, "INFO : WDC : Command not supported in this devicer\n"); } return 0; } nvme-cli-1.5/wdc-nvme.h000066400000000000000000000012471322317423600147710ustar00rootroot00000000000000#undef CMD_INC_FILE #define CMD_INC_FILE wdc-nvme #if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ) #define WDC_NVME #include "cmd.h" PLUGIN(NAME("wdc", "Western Digital vendor specific extensions"), COMMAND_LIST( ENTRY("cap-diag", "WDC Capture-Diagnostics", wdc_cap_diag) ENTRY("drive-log", "WDC Drive Log", wdc_drive_log) ENTRY("get-crash-dump", "WDC Crash Dump", wdc_get_crash_dump) ENTRY("id-ctrl", "WDC identify controller", wdc_id_ctrl) ENTRY("purge", "WDC Purge", wdc_purge) ENTRY("purge-monitor", "WDC Purge Monitor", wdc_purge_monitor) ENTRY("smart-add-log", "WDC Additional Smart Log", wdc_smart_add_log) ) ); #endif #include "define_cmd.h"