diff options
512 files changed, 28024 insertions, 17444 deletions
diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml deleted file mode 100644 index 03471d7..0000000 --- a/.github/workflows/c-cpp.yml +++ /dev/null @@ -1,18 +0,0 @@ -gname: C/C++ CI - -on: - push: - branches: [ master nvme-cli-monolithic ] - pull_request: - branches: [ master nvme-cli-monolithic ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: make - run: sudo apt-get install gcc-10-powerpc* && make clean && make && make clean && make LD=powerpc64le-linux-gnu-ld CC=powerpc64le-linux-gnu-gcc-10 CFLAGS='-O2 -g -Wall -Wformat-security -Werror -m64 -mcpu=power8 -mtune=power8 -I -I/usr/powerpc64-linux-gnu/include/' - diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml new file mode 100644 index 0000000..0d6350f --- /dev/null +++ b/.github/workflows/meson.yml @@ -0,0 +1,27 @@ +name: nvme-cli meson CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + + workflow_dispatch: + +jobs: + meson-build: + runs-on: ubuntu-latest + + steps: + - name: install libraries + run: sudo apt-get install libjson-c-dev libhugetlbfs-dev + - uses: actions/checkout@v2 + - uses: actions/setup-python@v1 + # - name: install python dependencies + # run: | + # python -m pip install --upgrade pip + # pip install nose nose2 + - uses: BSFishy/meson-build@v1.0.3 + with: + setup-options: --werror + action: build @@ -4,18 +4,15 @@ a.out *.o *~ *.swp -NVME-VERSION-FILE -nvme.spec nvme-*.tar.gz -version -cscope.* +subprojects/* +!subprojects/*.wrap -/debian/files -/debian/nvme-cli.debhelper.log -/debian/nvme-cli.substvars -/debian/nvme-cli +cscope.* tests/__pycache__ tests/nvmetests tests/*.pyc + +.build
\ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.gitmodules diff --git a/Documentation/Makefile b/Documentation/Makefile deleted file mode 100644 index 9edae99..0000000 --- a/Documentation/Makefile +++ /dev/null @@ -1,265 +0,0 @@ -# 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) - -ifneq ($(findstring $(MAKEFLAGS),s),s) -ifndef V - QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@; - QUIET_XMLTO = @echo ' ' XMLTO $@; - QUIET_DB2TEXI = @echo ' ' DB2TEXI $@; - QUIET_MAKEINFO = @echo ' ' MAKEINFO $@; - QUIET_DBLATEX = @echo ' ' DBLATEX $@; - QUIET_XSLTPROC = @echo ' ' XSLTPROC $@; - QUIET_GEN = @echo ' ' GEN $@; - QUIET_LINT = @echo ' ' LINT $@; - QUIET_STDERR = 2> /dev/null - QUIET_SUBDIR0 = +@subdir= - QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ - $(MAKE) $(PRINT_DIR) -C $$subdir - export V -endif -endif - -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 = --skip-validation -INSTALL ?= install -RM ?= rm -f -MAN_REPO = ../../nvme-manpages - -ASCIIDOC_HTML = xhtml11 -ASCIIDOC_CONF = -f asciidoc.conf - -ifdef USE_ASCIIDOCTOR -ASCIIDOC = asciidoctor -ASCIIDOC_CONF = -ASCIIDOC_HTML = xhtml5 -ASCIIDOC_DOCBOOK = docbook5 -ASCIIDOC_EXTRA += -acompat-mode -ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions -ASCIIDOC_EXTRA += -alitdd='&\#x2d;&\#x2d;' -ASCIIDOC_EXTRA += -amansource='NVMe' -ASCIIDOC_EXTRA += -amanmanual='NVMe Manual' -endif - -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 diff --git a/Documentation/cmd-plugins.txt b/Documentation/cmd-plugins.txt new file mode 100644 index 0000000..4e66cf1 --- /dev/null +++ b/Documentation/cmd-plugins.txt @@ -0,0 +1,200 @@ +linknvme:nvme-intel-id-ctrl[1]:: + Intel - NVMe Identify Controller + +linknvme:nvme-intel-internal-log[1]:: + Retrieve Intel device's internal log and save to file + +linknvme:nvme-intel-lat-stats[1]:: + Retrieve NVMe Identify Controller, return result and structure + +linknvme:nvme-intel-market-name[1]:: + Intel vendor specific marketing name log page + +linknvme:nvme-intel-smart-log-add[1]:: + NVMe Intel Additional SMART log page + +linknvme:nvme-intel-temp-stats[1]:: + NVMe Intel Additional SMART log page for temp stats + +linknvme:nvme-huawei-id-ctrl[1]:: + NVMe huawei Identify Controller + +linknvme:nvme-huawei-list[1]:: + List all recognized Huawei NVMe devices + +linknvme:nvme-dera-stat[1]:: + NVMe Dera Device status and Additional SMART log page request + +linknvme:nvme-micron-clear-pcie-errors[1]:: + Clears correctable PCIe correctable errors of given Micron device + +linknvme:nvme-micron-internal-log[1]:: + Retrieve Micron device's internal logs and save to given zip file + +linknvme:nvme-micron-nand-stats[1]:: + Retrieves NAND statistics of given micron device + +linknvme:nvme-micron-pcie-stats[1]:: + Retrieves pcie error statistics for given micron device + +linknvme:nvme-micron-selective-download[1]:: + Performs selective firmware download + +linknvme:nvme-micron-smart-add-log[1]:: + Retrieves NAND statistics + +linknvme:nvme-micron-temperature-stats[1]:: + Retrieves temperature information of given micron device + +linknvme:nvme-netapp-ontapdevices[1]:: + Display information about ONTAP devices + +linknvme:nvme-netapp-smdevices[1]:: + Display information for each NVMe path to an E-Series volume + +linknvme:nvme-toshiba-clear-pcie-correctable-errors[1]:: + Reset the PCIe correctable errors count to zero + +linknvme:nvme-toshiba-vs-internal-log[1]:: + Retrieve a Toshiba device's vendor specific internal log + +linknvme:nvme-toshiba-vs-smart-add-log[1]:: + Retrieve a Toshiba device's vendor specific extended SMART log page + +linknvme:nvme-transcend-badblock[1]:: + Retrieve Transcend NVMe device's bad blocks + +linknvme:nvme-transcend-healthvalue[1]:: + Use NVMe SMART table to analyse the health value of Transcend device + +linknvme:nvme-virtium-show-identify[1]:: + Show a complete detail of identify device information in json format + +linknvme:nvme-virtium-save-smart-to-vtview-log[1]:: + Periodically save smart attributes into a log file + +linknvme:nvme-wdc-cap-diag[1]:: + Retrieve WDC device's diagnostic log and save to file + +linknvme:nvme-wdc-capabilities[1]:: + Display WDC plugin command capabilities + +linknvme:nvme-wdc-clear-assert-dump[1]:: + Clears the assert dump (if present) + +linknvme:nvme-wdc-clear-fw-activate-history[1]:: + Clears the firmware activate history table + +linknvme:nvme-wdc-clear-pcie-corr[1]:: + Clears the pcie correctable errors field + +linknvme:nvme-wdc-clear-pcie-correctable-errors[1]:: + Clears the pcie correctable errors returned in the smart-log-add command + +linknvme:nvme-wdc-cloud-SSD-plugin-version[1]:: + Display WDC plugin Cloud SSD Plugin Version + +linknvme:nvme-wdc-drive-essentials[1]:: + Retrieve WDC device's drive essentials bin files + +linknvme:nvme-wdc-drive-log[1]:: + Retrieve WDC device's drive log and save to file + +linknvme:nvme-wdc-drive-resize[1]:: + Send NVMe WDC Resize Vendor Unique Command + +linknvme:nvme-wdc-enc-get-log[1]:: + Send NVMe WDC enc-get-log Vendor Unique Command + +linknvme:nvme-wdc-get-crash-dump[1]:: + Retrieve WDC device's crash dump + +linknvme:nvme-wdc-get-drive-status[1]:: + Send the NVMe WDC get-drive-status command + +linknvme:nvme-wdc-get-latency-monitor-log[1]:: + Display latency monitor log page data in human readable format + +linknvme:nvme-wdc-get-pfail-dump[1]:: + Retrieve WDC device's pfail crash dump + +linknvme:nvme-wdc-id-ctrl[1]:: + Send NVMe Identify Controller, return result and structure + +linknvme:nvme-wdc-log-page-directory[1]:: + Retrieves the list of Log IDs supported by the drive + +linknvme:nvme-wdc-namespace-resize[1]:: + Resizes the device's namespace + +linknvme:nvme-wdc-purge-monitor[1]:: + Send NVMe WDC Purge-Monitor Vendor Unique Command + +linknvme:nvme-wdc-purge[1]:: + Send NVMe WDC Purge Vendor Unique Command + +linknvme:nvme-wdc-smart-add-log[1]:: + Send NVMe WDC smart add log Vendor Unique Command + +linknvme:nvme-wdc-vs-drive-info[1]:: + Send the NVMe WDC vs-drive-info command + +linknvme:nvme-wdc-vs-error-reason-identifier[1]:: + Retrieve WDC device's telemetry log error reason identifier field + +linknvme:nvme-wdc-vs-fw-activate-history[1]:: + Execute NVMe WDC vs-fw-activate-history Vendor Unique Command + +linknvme:nvme-wdc-vs-internal-log[1]:: + Retrieve WDC device's internal firmware log and save to file + +linknvme:nvme-wdc-vs-nand-stats[1]:: + Send NVMe WDC vs-nand-stats Vendor Unique Command + +linknvme:nvme-wdc-vs-telemetry-controller-option[1]:: + Disable/Enable the controller initiated option of the telemetry log page + +linknvme:nvme-wdc-vs-temperature-stats[1]:: + Display temperature-related statistics + +linknvme:nvme-zns-changed-zone-list[1]:: + Retrieve Changed Zone log for the given device + +linknvme:nvme-zns-close-zone[1]:: + Closes one or all zones + +linknvme:nvme-zns-finish-zone[1]:: + Finishes one or all zones + +linknvme:nvme-zns-id-ctrl[1]:: + Send NVMe Zoned Command Set Identify Controller + +linknvme:nvme-zns-id-ns[1]:: + Send NVMe Zoned Command Set Identify Namespace + +linknvme:nvme-zns-offline-zone[1]:: + Offlines one or all zones + +linknvme:nvme-zns-open-zone[1]:: + Opens one or all zones + +linknvme:nvme-zns-report-zones[1]:: + Retrieve and display the Report Zones data structure + +linknvme:nvme-zns-reset-zone[1]:: + Resets one or all zones + +linknvme:nvme-zns-set-zone-desc[1]:: + Set extended descriptor data for a zone + +linknvme:nvme-zns-zone-append[1]:: + Send an NVMe write command, provide results + +linknvme:nvme-zns-zone-mgmt-recv[1]:: + Zone Management Receive command + +linknvme:nvme-zns-zone-mgmt-send[1]:: + Zone Management Send command + +linknvme:nvme-zns-zrwa-flush-zone[1]:: + Flush LBAs associated with a ZRWA to a zone diff --git a/Documentation/cmds-main.txt b/Documentation/cmds-main.txt index 46df03d..ab8ee3b 100644 --- a/Documentation/cmds-main.txt +++ b/Documentation/cmds-main.txt @@ -10,7 +10,7 @@ linknvme:nvme-error-log[1]:: linknvme:nvme-flush[1]:: Submit flush -linknvme:nvme-dms[1]:: +linknvme:nvme-dsm[1]:: Submit Data Set Management linknvme:nvme-format[1]:: @@ -160,6 +160,9 @@ linknvme:nvme-connect-all[1]:: linknvme:nvme-connect[1]:: Connect to an NVMe-over-Fabrics subsystem +linknvme:nvme-dim[1]:: + Send Discovery Information Management command to a Discovery Controller + linknvme:nvme-disconnect[1]:: Disconnect from an NVMe-over-Fabrics subsystem @@ -168,3 +171,102 @@ linknvme:nvme-disconnect-all[1]:: linknvme:nvme-get-property[1]:: Reads and shows NVMe-over-Fabrics controller property + +linknvme:nvme-media-unit-stat-log[1]:: + Retrieve and show the configuration and wear of media units + +linknvme:nvme-supported-cap-config-log[1]:: + Retrieve and show the list of Supported Capacity Configuration Descriptors + +linknvme:nvme-boot-part-log[1]:: + Retrieve Boot Partition Log + +linknvme:nvme-capacity-mgmt[1]:: + Capacity Management Command + +linknvme:nvme-check-dhchap-key[1]:: + Generate NVMeoF DH-HMAC-CHAP host key + +linknvme:nvme-check-tls-key[1]:: + Validate NVMeoF TLS PSK + +linknvme:nvme-cmdset-ind-id-ns[1]:: + I/O Command Set Independent Identify Namespace + +linknvme:nvme-endurance-event-agg-log[1]:: + Retrieve Endurance Group Event Aggregate Log + +linknvme:nvme-fid-support-effects-log[1]:: + Retrieve FID Support and Effects log + +linknvme:nvme-gen-dhchap-key[1]:: + Generate NVMeoF DH-HMAC-CHAP host key + +linknvme:nvme-gen-hostnqn[1]:: + Generate NVMeoF host NQN + +linknvme:nvme-gen-tls-key[1]:: + Generate NVMeoF TLS PSK + +linknvme:nvme-get-lba-status[1]:: + Get LBA Status command + +linknvme:nvme-id-domain[1]:: + NVMe Identify Domain List + +linknvme:nvme-id-ns-lba-format[1]:: + NVMe Identify Namespace for the specified LBA Format index + +linknvme:nvme-lba-status-log[1]:: + Retrieve LBA Status Information Log + +linknvme:nvme-list-endgrp[1]:: + NVMe Identify Endurance Group List + +linknvme:nvme-ns-rescan[1]:: + Rescans the NVME namespaces + +linknvme:nvme-nvm-id-ctrl[1]:: + NVMe Identify Controller NVM Command Set + +linknvme:nvme-nvm-id-ns[1]:: + NVMe Identify Namespace NVM Command Set + +linknvme:nvme-nvm-id-ns-lba-format[1]:: + NVMe Identify Namespace NVM Command Set for the specified LBA Format index + +linknvme:nvme-persistent-event-log[1]:: + Retrieve Presistent Event Log + +linknvme:nvme-predictable-lat-log[1]:: + Retrieve Predictable Latency per Nvmset Log + +linknvme:nvme-pred-lat-event-agg-log[1]:: + Retrieve Predictable Latency Event Aggregate Log + +linknvme:nvme-primary-ctrl-caps[1]:: + NVMe Identify Primary Controller Capabilities + +linknvme:nvme-reset[1]:: + Resets the controller + +linknvme:nvme-rpmb[1]:: + Replay Protection Memory Block commands + +linknvme:nvme-sanitize-log[1]:: + Retrieve sanitize log + +linknvme:nvme-set-property[1]:: + Set a property and show the resulting value + +linknvme:nvme-show-hostnqn[1]:: + Show NVMeoF host NQN + +linknvme:nvme-subsystem-reset[1]:: + Resets the subsystem + +linknvme:nvme-supported-log-pages[1]:: + Retrieve the Supported Log pages details + +linknvme:nvme-verify[1]:: + verify command diff --git a/Documentation/meson.build b/Documentation/meson.build new file mode 100644 index 0000000..a12eec4 --- /dev/null +++ b/Documentation/meson.build @@ -0,0 +1,257 @@ +adoc_sources = [ + 'nvme', + 'nvme-admin-passthru', + 'nvme-ana-log', + 'nvme-attach-ns', + 'nvme-boot-part-log', + 'nvme-capacity-mgmt', + 'nvme-changed-ns-list-log', + 'nvme-cmdset-ind-id-ns', + 'nvme-compare', + 'nvme-connect', + 'nvme-connect-all', + 'nvme-copy', + 'nvme-create-ns', + 'nvme-delete-ns', + 'nvme-dera-stat', + 'nvme-detach-ns', + 'nvme-device-self-test', + 'nvme-dim', + 'nvme-dir-receive', + 'nvme-dir-send', + 'nvme-disconnect', + 'nvme-disconnect-all', + 'nvme-discover', + 'nvme-dsm', + 'nvme-effects-log', + 'nvme-endurance-event-agg-log', + 'nvme-endurance-log', + 'nvme-error-log', + 'nvme-fid-support-effects-log', + 'nvme-mi-cmd-support-effects-log', + 'nvme-flush', + 'nvme-format', + 'nvme-fw-commit', + 'nvme-fw-download', + 'nvme-fw-log', + 'nvme-gen-hostnqn', + 'nvme-get-feature', + 'nvme-get-lba-status', + 'nvme-get-log', + 'nvme-get-ns-id', + 'nvme-get-property', + 'nvme-help', + 'nvme-huawei-id-ctrl', + 'nvme-huawei-list', + 'nvme-id-ctrl', + 'nvme-id-domain', + 'nvme-id-iocs', + 'nvme-id-ns', + 'nvme-id-nvmset', + 'nvme-intel-id-ctrl', + 'nvme-intel-internal-log', + 'nvme-intel-lat-stats', + 'nvme-intel-market-name', + 'nvme-intel-smart-log-add', + 'nvme-intel-temp-stats', + 'nvme-io-passthru', + 'nvme-lba-status-log', + 'nvme-list', + 'nvme-list-ctrl', + 'nvme-list-endgrp', + 'nvme-list-ns', + 'nvme-list-subsys', + 'nvme-lockdown', + 'nvme-micron-clear-pcie-errors', + 'nvme-micron-internal-log', + 'nvme-micron-nand-stats', + 'nvme-micron-pcie-stats', + 'nvme-micron-selective-download', + 'nvme-micron-smart-add-log', + 'nvme-micron-temperature-stats', + 'nvme-netapp-ontapdevices', + 'nvme-netapp-smdevices', + 'nvme-ns-descs', + 'nvme-ns-rescan', + 'nvme-nvm-id-ctrl', + 'nvme-ocp-latency-monitor-log', + 'nvme-ocp-smart-add-log', + 'nvme-persistent-event-log', + 'nvme-pred-lat-event-agg-log', + 'nvme-predictable-lat-log', + 'nvme-primary-ctrl-caps', + 'nvme-read', + 'nvme-reset', + 'nvme-resv-acquire', + 'nvme-resv-notif-log', + 'nvme-resv-register', + 'nvme-resv-release', + 'nvme-resv-report', + 'nvme-rpmb', + 'nvme-sanitize', + 'nvme-sanitize-log', + 'nvme-security-recv', + 'nvme-security-send', + 'nvme-self-test-log', + 'nvme-set-feature', + 'nvme-set-property', + 'nvme-show-hostnqn', + 'nvme-show-regs', + 'nvme-smart-log', + 'nvme-subsystem-reset', + 'nvme-supported-log-pages', + 'nvme-telemetry-log', + 'nvme-toshiba-clear-pcie-correctable-errors', + 'nvme-toshiba-vs-internal-log', + 'nvme-toshiba-vs-smart-add-log', + 'nvme-transcend-badblock', + 'nvme-transcend-healthvalue', + 'nvme-verify', + 'nvme-virtium-save-smart-to-vtview-log', + 'nvme-virtium-show-identify', + 'nvme-wdc-cap-diag', + 'nvme-wdc-capabilities', + 'nvme-wdc-clear-assert-dump', + 'nvme-wdc-clear-fw-activate-history', + 'nvme-wdc-clear-pcie-correctable-errors', + 'nvme-wdc-cloud-SSD-plugin-version', + 'nvme-wdc-drive-essentials', + 'nvme-wdc-drive-log', + 'nvme-wdc-drive-resize', + 'nvme-wdc-enc-get-log', + 'nvme-wdc-get-crash-dump', + 'nvme-wdc-get-dev-capabilities-log', + 'nvme-wdc-get-drive-status', + 'nvme-wdc-get-error-recovery-log', + 'nvme-wdc-get-latency-monitor-log', + 'nvme-wdc-get-pfail-dump', + 'nvme-wdc-get-unsupported-reqs-log', + 'nvme-wdc-id-ctrl', + 'nvme-wdc-log-page-directory', + 'nvme-wdc-namespace-resize', + 'nvme-wdc-purge', + 'nvme-wdc-purge-monitor', + 'nvme-wdc-vs-drive-info', + 'nvme-wdc-vs-error-reason-identifier', + 'nvme-wdc-vs-fw-activate-history', + 'nvme-wdc-vs-internal-log', + 'nvme-wdc-vs-nand-stats', + 'nvme-wdc-vs-smart-add-log', + 'nvme-wdc-vs-telemetry-controller-option', + 'nvme-wdc-vs-temperature-stats', + 'nvme-write', + 'nvme-write-uncor', + 'nvme-write-zeroes', + 'nvme-zns-changed-zone-list', + 'nvme-zns-close-zone', + 'nvme-zns-finish-zone', + 'nvme-zns-id-ctrl', + 'nvme-zns-id-ns', + 'nvme-zns-offline-zone', + 'nvme-zns-open-zone', + 'nvme-zns-report-zones', + 'nvme-zns-reset-zone', + 'nvme-zns-set-zone-desc', + 'nvme-zns-zone-append', + 'nvme-zns-zone-mgmt-recv', + 'nvme-zns-zone-mgmt-send', +] + +adoc_includes = [ + 'cmd-plugins.txt', + 'cmds-main.txt', +] + +want_docs = get_option('docs') +want_docs_build = get_option('docs-build') +if want_docs != 'false' + mandir = join_paths(get_option('mandir'), 'man1') + htmldir = join_paths(get_option('htmldir'), 'nvme') + + asciidoctor = find_program('asciidoc', required : false) + if want_docs_build and asciidoctor.found() + # Build documentation before installing + + foreach file : adoc_includes + configure_file( + input: file, + output: file, + copy: true) + endforeach + + # man pages + if want_docs == 'all' or want_docs == 'man' + xmlto = find_program('xmlto', required: false) + if xmlto.found() + foreach adoc : adoc_sources + input = adoc + '.txt' + subst = configure_file( + input: adoc + '.txt', + output: adoc + '.msubst', + configuration: substs) + xml = custom_target( + adoc.underscorify() + '_xml', + input: subst, + output: '@BASENAME@.xml', + command: [asciidoctor, + '-f', files('asciidoc.conf'), + '-b', 'docbook', + '-d', 'manpage', + '-o', '@OUTPUT@', + '@INPUT@'], + ) + custom_target( + adoc.underscorify() + '_man', + input: xml, + output: '@BASENAME@.1', + command: [xmlto, + '-m', files('manpage-normal.xsl'), + '-o', '@OUTDIR@', + '--skip-validation', + 'man', + '@INPUT@'], + install: true, + install_dir: mandir) + endforeach + endif + endif + + # html + if want_docs == 'all' or want_docs == 'html' + foreach adoc : adoc_sources + input = adoc + '.txt' + subst = configure_file( + input: adoc + '.txt', + output: adoc + '.hsubst', + configuration: substs) + custom_target( + adoc.underscorify() + '_html', + input: subst, + output: '@BASENAME@.html', + command: [asciidoctor, + '-f', files('asciidoc.conf'), + '-b', 'xhtml11', + '-d', 'manpage', + '-o', '@OUTPUT@', + '@INPUT@'], + install: true, + install_dir: htmldir) + endforeach + endif + + else + # asciidoctor not found, install pre compiled documetationx + + foreach adoc : adoc_sources + if want_docs == 'all' or want_docs == 'man' + man = files(adoc + '.1') + install_data(man, install_dir: mandir) + endif + if want_docs == 'all' or want_docs == 'html' + html = files(adoc + '.html') + install_data(html, install_dir: htmldir) + endif + endforeach + + endif +endif diff --git a/Documentation/nvme-admin-passthru.1 b/Documentation/nvme-admin-passthru.1 index fecabb4..1beb822 100644 --- a/Documentation/nvme-admin-passthru.1 +++ b/Documentation/nvme-admin-passthru.1 @@ -2,12 +2,12 @@ .\" Title: nvme-admin-passthru .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ADMIN\-PASSTHR" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ADMIN\-PASSTHR" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-admin-passthru.html b/Documentation/nvme-admin-passthru.html index 064f852..b6b7675 100644 --- a/Documentation/nvme-admin-passthru.html +++ b/Documentation/nvme-admin-passthru.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-admin-passthru(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -998,7 +998,7 @@ Or if you want to save that structure to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-ana-log.1 b/Documentation/nvme-ana-log.1 index 70d8f4d..9e726a5 100644 --- a/Documentation/nvme-ana-log.1 +++ b/Documentation/nvme-ana-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-ana-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ANA\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ANA\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-ana-log.html b/Documentation/nvme-ana-log.html index 6a96f5f..09fe690 100644 --- a/Documentation/nvme-ana-log.html +++ b/Documentation/nvme-ana-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-ana-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -812,7 +812,7 @@ Print the ANA log page in a human readable format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-attach-ns.1 b/Documentation/nvme-attach-ns.1 index fb81080..224bafe 100644 --- a/Documentation/nvme-attach-ns.1 +++ b/Documentation/nvme-attach-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-attach-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ATTACH\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ATTACH\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-attach-ns.html b/Documentation/nvme-attach-ns.html index 1bfe53f..d4247ce 100644 --- a/Documentation/nvme-attach-ns.html +++ b/Documentation/nvme-attach-ns.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-attach-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -817,7 +817,7 @@ controller identifiers.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-boot-part-log.1 b/Documentation/nvme-boot-part-log.1 index d618825..79a6802 100644 --- a/Documentation/nvme-boot-part-log.1 +++ b/Documentation/nvme-boot-part-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-boot-part-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-BOOT\-PART\-LO" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-BOOT\-PART\-LO" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-boot-part-log.html b/Documentation/nvme-boot-part-log.html index 7c93c53..aed6df2 100644 --- a/Documentation/nvme-boot-part-log.html +++ b/Documentation/nvme-boot-part-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-boot-part-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -835,7 +835,7 @@ Retrieve Boot Partition data to boot_part_log.bin <div id="footer">
<div id="footer-text">
Last updated
- 2021-08-11 09:38:58 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-capacity-mgmt.1 b/Documentation/nvme-capacity-mgmt.1 index 9c63545..951ed58 100644 --- a/Documentation/nvme-capacity-mgmt.1 +++ b/Documentation/nvme-capacity-mgmt.1 @@ -2,12 +2,12 @@ .\" Title: nvme-capacity-mgmt .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-CAPACITY\-MGMT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-CAPACITY\-MGMT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-capacity-mgmt.html b/Documentation/nvme-capacity-mgmt.html index aeb0fbc..7e6ed4c 100644 --- a/Documentation/nvme-capacity-mgmt.html +++ b/Documentation/nvme-capacity-mgmt.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-capacity-mgmt(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -760,10 +760,11 @@ nvme-capacity-mgmt(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>For the NVMe device given, sends a capacity management command to configure/create/delete
-the Endurance Groups or NVM Sets with the requested operation and element_id. On success,
-if the Operation is Create Endurance group or NVM Set, CQE CDW0 contains Created element
-identifier else CQE CDW0 is reserved.</p></div>
+<div class="paragraph"><p>For the NVMe device given, sends a capacity management command to
+configure/create/delete the Endurance Groups or NVM Sets with the requested
+operation and element_id. On success, if the Operation is Create Endurance
+group or NVM Set, CQE CDW0 contains Created element identifier else CQE CDW0 is
+reserved.</p></div>
<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>
</div>
@@ -838,7 +839,7 @@ device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></di <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-02 09:55:05 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-changed-ns-list-log.1 b/Documentation/nvme-changed-ns-list-log.1 index 98486f2..05adedd 100644 --- a/Documentation/nvme-changed-ns-list-log.1 +++ b/Documentation/nvme-changed-ns-list-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-changed-ns-list-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-CHANGED\-NS\-L" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-CHANGED\-NS\-L" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-changed-ns-list-log.html b/Documentation/nvme-changed-ns-list-log.html index 08fba6e..02ef9e9 100644 --- a/Documentation/nvme-changed-ns-list-log.html +++ b/Documentation/nvme-changed-ns-list-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-changed-ns-list-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -835,7 +835,7 @@ Print the raw Changed Namespace List log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-lnvm-info.1 b/Documentation/nvme-check-dhchap-key.1 index 80a0288..df8df21 100644 --- a/Documentation/nvme-lnvm-info.1 +++ b/Documentation/nvme-check-dhchap-key.1 @@ -1,13 +1,13 @@ '\" t -.\" Title: nvme-lnvm-info -.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Title: nvme-check-dhchap-key +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> +.\" Date: 11/25/2021 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LNVM\-INFO" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-CHECK\-DHCHAP\" "1" "11/25/2021" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,21 +28,24 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -nvme-lnvm-info \- Show general information and registered target types with LightNVM +nvme-check-dhchap-key \- Check a generated host DH\-HMAC\-CHAP key .SH "SYNOPSIS" .sp .nf -\fInvme lnvm\-info\fR +\fInvme check\-dhchap\-key\fR [\-\-key=<key> ] .fi .SH "DESCRIPTION" .sp -Show general information and registered target types with LightNVM\&. +Checks if the key is a valid DH\-HMAC\-CHAP host key of the form: DHHC\-1:00:ia6zGodOr4SEG0Zzaw398rpY0wqipUWj4jWjUh4HWUz6aQ2n: and prints it to stdout\&. .SH "OPTIONS" -.sp -No options yet\&. +.PP +\-k <key>, \-\-key=<key> +.RS 4 +Key to be checked\&. +.RE .SH "EXAMPLES" .sp -No examples yet\&. +No Examples .SH "NVME" .sp Part of the nvme\-user suite diff --git a/Documentation/nvme-lnvm-info.html b/Documentation/nvme-check-dhchap-key.html index 1cee911..927ed7e 100644 --- a/Documentation/nvme-lnvm-info.html +++ b/Documentation/nvme-check-dhchap-key.html @@ -1,11 +1,10 @@ -<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-info(1)</title>
+<meta name="generator" content="AsciiDoc 8.6.8" />
+<title>nvme-check-dhchap-key(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -95,9 +94,7 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-pre {
- white-space: pre-wrap;
-}
+
#author {
color: #527bbd;
@@ -226,7 +223,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; vertical-align: text-bottom; }
+span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
@@ -735,12 +732,12 @@ asciidoc.install(); <body class="manpage">
<div id="header">
<h1>
-nvme-lnvm-info(1) Manual Page
+nvme-check-dhchap-key(1) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>nvme-lnvm-info -
- Show general information and registered target types with LightNVM
+<p>nvme-check-dhchap-key -
+ Check a generated host DH-HMAC-CHAP key
</p>
</div>
</div>
@@ -749,7 +746,7 @@ nvme-lnvm-info(1) Manual Page <h2 id="_synopsis">SYNOPSIS</h2>
<div class="sectionbody">
<div class="verseblock">
-<pre class="content"><em>nvme lnvm-info</em></pre>
+<pre class="content"><em>nvme check-dhchap-key</em> [--key=<key> ]</pre>
<div class="attribution">
</div></div>
</div>
@@ -757,19 +754,33 @@ nvme-lnvm-info(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Show general information and registered target types with LightNVM.</p></div>
+<div class="paragraph"><p>Checks if the key is a valid DH-HMAC-CHAP host key of the form:
+DHHC-1:00:ia6zGodOr4SEG0Zzaw398rpY0wqipUWj4jWjUh4HWUz6aQ2n:
+and prints it to stdout.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_options">OPTIONS</h2>
<div class="sectionbody">
-<div class="paragraph"><p>No options yet.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-k <key>
+</dt>
+<dt class="hdlist1">
+--key=<key>
+</dt>
+<dd>
+<p>
+ Key to be checked.
+</p>
+</dd>
+</dl></div>
</div>
</div>
<div class="sect1">
<h2 id="_examples">EXAMPLES</h2>
<div class="sectionbody">
-<div class="paragraph"><p>No examples yet.</p></div>
+<div class="paragraph"><p>No Examples</p></div>
</div>
</div>
<div class="sect1">
@@ -782,8 +793,7 @@ nvme-lnvm-info(1) Manual Page <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated
- 2021-07-19 10:10:19 PDT
+Last updated 2021-11-25 14:13:07 KST
</div>
</div>
</body>
diff --git a/Documentation/nvme-check-dhchap-key.txt b/Documentation/nvme-check-dhchap-key.txt new file mode 100644 index 0000000..9cfa1f7 --- /dev/null +++ b/Documentation/nvme-check-dhchap-key.txt @@ -0,0 +1,31 @@ +nvme-check-dhchap-key(1) +======================== + +NAME +---- +nvme-check-dhchap-key - Check a generated host DH-HMAC-CHAP key + +SYNOPSIS +-------- +[verse] +'nvme check-dhchap-key' [--key=<key> ] + +DESCRIPTION +----------- +Checks if the key is a valid DH-HMAC-CHAP host key of the form: +DHHC-1:00:ia6zGodOr4SEG0Zzaw398rpY0wqipUWj4jWjUh4HWUz6aQ2n: +and prints it to stdout. + +OPTIONS +------- +-k <key>:: +--key=<key>:: + Key to be checked. + +EXAMPLES +-------- +No Examples + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-check-tls-key.txt b/Documentation/nvme-check-tls-key.txt new file mode 100644 index 0000000..9ef6679 --- /dev/null +++ b/Documentation/nvme-check-tls-key.txt @@ -0,0 +1,31 @@ +nvme-check-tls-key(1) +======================== + +NAME +---- +nvme-check-tls-key - Check a generated NVMe TLS PSK + +SYNOPSIS +-------- +[verse] +'nvme check-tls-key' [--key=<key> ] + +DESCRIPTION +----------- +Checks if the key is a valid NVMe TLS PSK in the PSK interchange format +NVMeTLSkey-1:01:VRLbtnN9AQb2WXW3c9+wEf/DRLz0QuLdbYvEhwtdWwNf9LrZ: + + +OPTIONS +------- +-k <key>:: +--key=<key>:: + Key to be checked. + +EXAMPLES +-------- +No Examples + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-cmdset-ind-id-ns.1 b/Documentation/nvme-cmdset-ind-id-ns.1 index 95f110b..fa6ce8d 100644 --- a/Documentation/nvme-cmdset-ind-id-ns.1 +++ b/Documentation/nvme-cmdset-ind-id-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-cmdset-ind-id-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-CMDSET\-IND\-I" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-CMDSET\-IND\-I" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-cmdset-ind-id-ns.html b/Documentation/nvme-cmdset-ind-id-ns.html index 55c5bfc..b3e3ee2 100644 --- a/Documentation/nvme-cmdset-ind-id-ns.html +++ b/Documentation/nvme-cmdset-ind-id-ns.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-cmdset-ind-id-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -875,7 +878,8 @@ Have the program return the raw structure in binary: <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-25 18:30:10 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-compare.1 b/Documentation/nvme-compare.1 index 49b2c6a..af11284 100644 --- a/Documentation/nvme-compare.1 +++ b/Documentation/nvme-compare.1 @@ -2,12 +2,12 @@ .\" Title: nvme-compare .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-COMPARE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-COMPARE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -51,6 +51,7 @@ nvme-compare \- Send an NVMe Compare command, provide results [\-\-dry\-run | \-w] [\-\-latency | \-t] [\-\-storage\-tag\-check<storage\-tag\-check> | \-C <storage\-tag\-check>] + [\-\-force] .fi .SH "DESCRIPTION" .sp @@ -183,7 +184,7 @@ Optional field for directive specifics\&. When used with write streams, this val .PP \-D <dsm>, \-\-dsm=<dsm> .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\&. +The optional data set management attributes for this command\&. The argument for this is the least significant 8 bits of the DSM field in a write command; the most significant 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 \-v, \-\-show\-cmd @@ -208,6 +209,11 @@ Print out the latency the IOCTL took (in us)\&. .RS 4 This bit specifies the Storage Tag field shall be checked as part of end\-to\-end data protection processing\&. .RE +.PP +\-\-force +.RS 4 +Ignore namespace is currently busy and perfome the operation even though\&. +.RE .SH "EXAMPLES" .sp No examples yet\&. diff --git a/Documentation/nvme-compare.html b/Documentation/nvme-compare.html index 0c13e32..8143c7b 100644 --- a/Documentation/nvme-compare.html +++ b/Documentation/nvme-compare.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-compare(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -767,7 +767,8 @@ nvme-compare(1) Manual Page [--show-command | -v]
[--dry-run | -w]
[--latency | -t]
- [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]</pre>
+ [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]
+ [--force]</pre>
<div class="attribution">
</div></div>
</div>
@@ -996,9 +997,9 @@ metadata is passes.</p></td> </dt>
<dd>
<p>
- 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
+ The optional data set management attributes for this command. The argument
+ for this is the least significant 8 bits of the DSM field in a write
+ command; the most significant 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
@@ -1053,6 +1054,15 @@ metadata is passes.</p></td> data protection processing.
</p>
</dd>
+<dt class="hdlist1">
+--force
+</dt>
+<dd>
+<p>
+ Ignore namespace is currently busy and perfome the operation
+ even though.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -1073,7 +1083,7 @@ metadata is passes.</p></td> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-09 14:16:50 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-compare.txt b/Documentation/nvme-compare.txt index b6f8863..f082a33 100644 --- a/Documentation/nvme-compare.txt +++ b/Documentation/nvme-compare.txt @@ -27,6 +27,7 @@ SYNOPSIS [--dry-run | -w] [--latency | -t] [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>] + [--force] DESCRIPTION ----------- @@ -117,15 +118,14 @@ metadata is passes. -D <dsm>:: --dsm=<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 + The optional data set management attributes for this command. The argument + for this is the least significant 8 bits of the DSM field in a write + command; the most significant 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. - -v:: --show-cmd:: Print out the command to be sent. @@ -145,6 +145,10 @@ metadata is passes. This bit specifies the Storage Tag field shall be checked as part of end-to-end data protection processing. +--force:: + Ignore namespace is currently busy and perfome the operation + even though. + EXAMPLES -------- No examples yet. diff --git a/Documentation/nvme-config.txt b/Documentation/nvme-config.txt new file mode 100644 index 0000000..5b76925 --- /dev/null +++ b/Documentation/nvme-config.txt @@ -0,0 +1,210 @@ +nvme-config(1) +=============== + +NAME +---- +nvme-config - NVMe-over-Fabrics configuration. + +SYNOPSIS +-------- +[verse] +'nvme config' + [--scan | -R] + [--modify | -M] + [--update | -U] + [--dump | -O] + [--config=<cfg> | -J <cfg> ] + [--transport=<trtype> | -t <trtype>] + [--nqn=<subnqn> | -n <subnqn>] + [--traddr=<traddr> | -a <traddr>] + [--trsvcid=<trsvcid> | -s <trsvcid>] + [--host-traddr=<traddr> | -w <traddr>] + [--host-iface=<iface> | -f <iface>] + [--hostnqn=<hostnqn> | -q <hostnqn>] + [--hostid=<hostid> | -I <hostid>] + [--dhchap-secret=<secret> | -S <secret>] + [--dhchap-ctrl-secret=<secret> | -C <secret>] + [--nr-io-queues=<#> | -i <#>] + [--nr-write-queues=<#> | -W <#>] + [--nr-poll-queues=<#> | -P <#>] + [--queue-size=<#> | -Q <#>] + [--keep-alive-tmo=<#> | -k <#>] + [--reconnect-delay=<#> | -c <#>] + [--ctrl-loss-tmo=<#> | -l <#>] + [--duplicate-connect | -D] + [--disable-sqflow | -d] + [--hdr-digest | -g] + [--data-digest | -G] + +DESCRIPTION +----------- +Read in the NVMe over Fabrics configuration from the specified JSON +configuration file and allow to update or modify the contents. +The JSON configuration file format is documented in +https://github.com/linux-nvme/libnvme/doc/config-schema.json + +OPTIONS +------- +-R:: +--scan:: + Additionally read the current configuration from sysfs. + +-M:: +--modify:: + Add or modify entries in the configuration based on the values from + the commandline. + +-U:: +--update:: + Write updated configuration into the JSON configuration file. + +-O:: +--dump:: + Print out resulting JSON configuration file to stdout. + +-J <cfg>:: +--config=<cfg>:: + Use the specified JSON configuration file instead of the + default @SYSCONFDIR@/nvme/config.json file or 'none' to not read in + an existing configuration file. + +-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 |The network fabric is a Fibre Channel network. +|tcp |The network fabric is a TCP/IP 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. For TCP, this sets the source address on the socket. + +-f <iface>:: +--host-iface=<iface>:: + This field specifies the network interface used on the host to connect + to the Controller (e.g. IP eth1, enp2s0, enx78e7d1ea46da). This forces + the connection to be made on a specific interface instead of letting + the system decide. + +-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 + @SYSCONFDIR@/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 <hostid>:: +--hostid=<hostid>:: + UUID(Universally Unique Identifier) to be discovered which should be + formatted. + +-S <secret>:: +--dhchap-secret=<secret>:: + NVMe In-band authentication secret; needs to be in ASCII format as + specified in NVMe 2.0 section 8.13.5.8 'Secret representation'. + If this option is not specified, the default is read from + @SYSCONFDIR@/nvme/hostkey. If that does not exist no in-band authentication + is attempted. + +-C <secret>:: +--dhchap-ctrl-secret=<secret>:: + NVMe In-band authentication controller secret for bi-directional + authentication; needs to be in ASCII format as + specified in NVMe 2.0 section 8.13.5.8 'Secret representation'. + If not present bi-directional authentication is not attempted. + +-i <#>:: +--nr-io-queues=<#>:: + Overrides the default number of I/O queues create by the driver. + +-W <#>:: +--nr-write-queues=<#>:: + Adds additional queues that will be used for write I/O. + +-P <#>:: +--nr-poll-queues=<#>:: + Adds additional queues that will be used for polling latency sensitive I/O. + +-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. + +-l <#>:: +--ctrl-loss-tmo=<#>:: + Overrides the default controller loss timeout period (in seconds). + +-D:: +--duplicate-connect:: + Allows duplicated connections between same transport host and subsystem + port. + +-d:: +--disable-sqflow:: + Disables SQ flow control to omit head doorbell update for submission + queues when sending nvme completions. + +-g:: +--hdr-digest:: + Generates/verifies header digest (TCP). + +-G:: +--data-digest:: + Generates/verifies data digest (TCP). + +EXAMPLES +-------- +* Read the current system configuration and write the contents to /tmp/config.json: ++ +------------ +# nvme config --config /tmp/config.json --scan --update +------------ + +SEE ALSO +-------- +nvme-discover(1) +nvme-connect(1) +https://github.com/linux-nvme/libnvme/doc/config-schema.json + + +AUTHORS +------- +This was written by mailto:hare@suse.com[Hannes Reinecke] + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-connect-all.1 b/Documentation/nvme-connect-all.1 index 028b6e3..683eaf4 100644 --- a/Documentation/nvme-connect-all.1 +++ b/Documentation/nvme-connect-all.1 @@ -2,12 +2,12 @@ .\" Title: nvme-connect-all .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-CONNECT\-ALL" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-CONNECT\-ALL" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -34,6 +34,7 @@ nvme-connect-all \- Discover and Connect to Fabrics controllers\&. .nf \fInvme connect\-all\fR [\-\-transport=<trtype> | \-t <trtype>] + [\-\-nqn=<subnqn> | \-n <subnqn>] [\-\-traddr=<traddr> | \-a <traddr>] [\-\-trsvcid=<trsvcid> | \-s <trsvcid>] [\-\-host\-traddr=<traddr> | \-w <traddr>] @@ -41,6 +42,7 @@ nvme-connect-all \- Discover and Connect to Fabrics controllers\&. [\-\-hostnqn=<hostnqn> | \-q <hostnqn>] [\-\-hostid=<hostid> | \-I <hostid>] [\-\-raw=<filename> | \-r <filename>] + [\-\-cfg\-file=<cfg> | \-C <cfg>] [\-\-keep\-alive\-tmo=<#> | \-k <#>] [\-\-reconnect\-delay=<#> | \-c <#>] [\-\-ctrl\-loss\-tmo=<#> | \-l <#>] @@ -50,9 +52,9 @@ nvme-connect-all \- Discover and Connect to Fabrics controllers\&. [\-\-nr\-write\-queues=<#> | \-W <#>] [\-\-nr\-poll\-queues=<#> | \-P <#>] [\-\-queue\-size=<#> | \-Q <#>] - [\-\-matching | \-m] [\-\-persistent | \-p] [\-\-quiet | \-S] + [\-\-dump\-config | \-O] .fi .SH "DESCRIPTION" .sp @@ -105,6 +107,11 @@ T} .sp 1 .RE .PP +\-n <subnqn>, \-\-nqn <subnqn> +.RS 4 +This field specifies the name for the NVMe subsystem to connect to\&. +.RE +.PP \-a <traddr>, \-\-traddr=<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)\&. @@ -144,6 +151,14 @@ command and dump it to a raw binary file\&. By default will dump the output to stdout\&. .RE .PP +\-C <cfg>, \-\-config\-file=<cfg> +.RS 4 +Use the specified JSON configuration file instead of the default /etc/nvme/config\&.json file or +\fInone\fR +to not read in an existing configuration file\&. The JSON configuration file format is documented in +\m[blue]\fBhttps://github\&.com/linux\-nvme/libnvme/doc/config\-schema\&.json\fR\m[] +.RE +.PP \-k <#>, \-\-keep\-alive\-tmo=<#> .RS 4 Overrides the default keep alive timeout (in seconds)\&. This option will be ignored for discovery, but will be passed on to the subsequent connect call\&. @@ -189,11 +204,6 @@ Adds additional queues that will be used for polling latency sensitive I/O\&. Overrides the default number of elements in the I/O queues created by the driver\&. This option will be ignored for discovery, but will be passed on to the subsequent connect call\&. .RE .PP -\-m, \-\-matching -.RS 4 -If a traddr was specified on the command line or in the configuration file, only create controllers for discovery records that match the given traddr, rather than for all entries in the discovery log page\&. -.RE -.PP \-p, \-\-persistent .RS 4 Don\(cqt remove the discovery controller after retrieving the discovery log page\&. @@ -203,6 +213,11 @@ Don\(cqt remove the discovery controller after retrieving the discovery log page .RS 4 Suppress error messages\&. .RE +.PP +\-O, \-\-dump\-config +.RS 4 +Print out resulting JSON configuration file to stdout\&. +.RE .SH "EXAMPLES" .sp .RS 4 diff --git a/Documentation/nvme-connect-all.html b/Documentation/nvme-connect-all.html index 91bd91a..39d5732 100644 --- a/Documentation/nvme-connect-all.html +++ b/Documentation/nvme-connect-all.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-connect-all(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -751,6 +751,7 @@ nvme-connect-all(1) Manual Page <div class="verseblock">
<pre class="content"><em>nvme connect-all</em>
[--transport=<trtype> | -t <trtype>]
+ [--nqn=<subnqn> | -n <subnqn>]
[--traddr=<traddr> | -a <traddr>]
[--trsvcid=<trsvcid> | -s <trsvcid>]
[--host-traddr=<traddr> | -w <traddr>]
@@ -758,6 +759,7 @@ nvme-connect-all(1) Manual Page [--hostnqn=<hostnqn> | -q <hostnqn>]
[--hostid=<hostid> | -I <hostid>]
[--raw=<filename> | -r <filename>]
+ [--cfg-file=<cfg> | -C <cfg>]
[--keep-alive-tmo=<#> | -k <#>]
[--reconnect-delay=<#> | -c <#>]
[--ctrl-loss-tmo=<#> | -l <#>]
@@ -767,9 +769,9 @@ nvme-connect-all(1) Manual Page [--nr-write-queues=<#> | -W <#>]
[--nr-poll-queues=<#> | -P <#>]
[--queue-size=<#> | -Q <#>]
- [--matching | -m]
[--persistent | -p]
- [--quiet | -S]</pre>
+ [--quiet | -S]
+ [--dump-config | -O]</pre>
<div class="attribution">
</div></div>
</div>
@@ -781,8 +783,8 @@ nvme-connect-all(1) Manual Page Controller, and create controllers for the returned discovery records.</p></div>
<div class="paragraph"><p>If no parameters are given, then <em>nvme connect-all</em> 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.</p></div>
+connect-all commands to run. If no /etc/nvme/discovery.conf file
+exists, the command will quit with an error.</p></div>
<div class="paragraph"><p>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.</p></div>
@@ -838,6 +840,17 @@ cellspacing="0" cellpadding="4"> </div>
</dd>
<dt class="hdlist1">
+-n <subnqn>
+</dt>
+<dt class="hdlist1">
+--nqn <subnqn>
+</dt>
+<dd>
+<p>
+ This field specifies the name for the NVMe subsystem to connect to.
+</p>
+</dd>
+<dt class="hdlist1">
-a <traddr>
</dt>
<dt class="hdlist1">
@@ -899,8 +912,8 @@ cellspacing="0" cellpadding="4"> <p>
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.
+ /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.
@@ -932,6 +945,21 @@ cellspacing="0" cellpadding="4"> </p>
</dd>
<dt class="hdlist1">
+-C <cfg>
+</dt>
+<dt class="hdlist1">
+--config-file=<cfg>
+</dt>
+<dd>
+<p>
+ Use the specified JSON configuration file instead of the
+ default /etc/nvme/config.json file or <em>none</em> to not read in
+ an existing configuration file. The JSON configuration file
+ format is documented in
+ <a href="https://github.com/linux-nvme/libnvme/doc/config-schema.json">https://github.com/linux-nvme/libnvme/doc/config-schema.json</a>
+</p>
+</dd>
+<dt class="hdlist1">
-k <#>
</dt>
<dt class="hdlist1">
@@ -1038,39 +1066,37 @@ cellspacing="0" cellpadding="4"> </p>
</dd>
<dt class="hdlist1">
--m
+-p
</dt>
<dt class="hdlist1">
---matching
+--persistent
</dt>
<dd>
<p>
- If a traddr was specified on the command line or in the configuration
- file, only create controllers for discovery records that match the
- given traddr, rather than for all entries in the discovery log page.
+ Don’t remove the discovery controller after retrieving the discovery
+ log page.
</p>
</dd>
<dt class="hdlist1">
--p
+-S
</dt>
<dt class="hdlist1">
---persistent
+--quiet
</dt>
<dd>
<p>
- Don’t remove the discovery controller after retrieving the discovery
- log page.
+ Suppress error messages.
</p>
</dd>
<dt class="hdlist1">
--S
+-O
</dt>
<dt class="hdlist1">
---quiet
+--dump-config
</dt>
<dd>
<p>
- Suppress error messages.
+ Print out resulting JSON configuration file to stdout.
</p>
</dd>
</dl></div>
@@ -1130,7 +1156,7 @@ nvme-connect(1)</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-connect-all.txt b/Documentation/nvme-connect-all.txt index 1cb7822..605d245 100644 --- a/Documentation/nvme-connect-all.txt +++ b/Documentation/nvme-connect-all.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'nvme connect-all' [--transport=<trtype> | -t <trtype>] + [--nqn=<subnqn> | -n <subnqn>] [--traddr=<traddr> | -a <traddr>] [--trsvcid=<trsvcid> | -s <trsvcid>] [--host-traddr=<traddr> | -w <traddr>] @@ -17,6 +18,7 @@ SYNOPSIS [--hostnqn=<hostnqn> | -q <hostnqn>] [--hostid=<hostid> | -I <hostid>] [--raw=<filename> | -r <filename>] + [--cfg-file=<cfg> | -C <cfg>] [--keep-alive-tmo=<#> | -k <#>] [--reconnect-delay=<#> | -c <#>] [--ctrl-loss-tmo=<#> | -l <#>] @@ -26,9 +28,9 @@ SYNOPSIS [--nr-write-queues=<#> | -W <#>] [--nr-poll-queues=<#> | -P <#>] [--queue-size=<#> | -Q <#>] - [--matching | -m] [--persistent | -p] [--quiet | -S] + [--dump-config | -O] DESCRIPTION ----------- @@ -36,9 +38,9 @@ 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. +find a @SYSCONFDIR@/nvme/discovery.conf file to use to supply a list of +connect-all commands to run. If no @SYSCONFDIR@/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 @@ -63,6 +65,10 @@ OPTIONS |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 Discovery Controller. @@ -91,8 +97,8 @@ OPTIONS --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. + @SYSCONFDIR@/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. @@ -108,6 +114,14 @@ OPTIONS and dump it to a raw binary file. By default 'nvme connect-all' will dump the output to stdout. +-C <cfg>:: +--config-file=<cfg>:: + Use the specified JSON configuration file instead of the + default @SYSCONFDIR@/nvme/config.json file or 'none' to not read in + an existing configuration file. The JSON configuration file + format is documented in + https://github.com/linux-nvme/libnvme/doc/config-schema.json + -k <#>:: --keep-alive-tmo=<#>:: Overrides the default keep alive timeout (in seconds). This @@ -151,12 +165,6 @@ OPTIONS by the driver. This option will be ignored for discovery, but will be passed on to the subsequent connect call. --m:: ---matching:: - If a traddr was specified on the command line or in the configuration - file, only create controllers for discovery records that match the - given traddr, rather than for all entries in the discovery log page. - -p:: --persistent:: Don't remove the discovery controller after retrieving the discovery @@ -166,6 +174,10 @@ OPTIONS --quiet:: Suppress error messages. +-O:: +--dump-config:: + Print out resulting JSON configuration file to stdout. + EXAMPLES -------- @@ -178,7 +190,7 @@ the RDMA network. Port 4420 is used by default: --hostnqn=host1-rogue-nqn ------------ + -* Issue a 'nvme connect-all' command using a /etc/nvme/discovery.conf file: +* Issue a 'nvme connect-all' command using a @SYSCONFDIR@/nvme/discovery.conf file: + ----------- # Machine default 'nvme discover' commands. Query the diff --git a/Documentation/nvme-connect.1 b/Documentation/nvme-connect.1 index 55ff773..8139ecd 100644 --- a/Documentation/nvme-connect.1 +++ b/Documentation/nvme-connect.1 @@ -2,12 +2,12 @@ .\" Title: nvme-connect .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-CONNECT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-CONNECT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -41,6 +41,9 @@ nvme-connect \- Connect to a Fabrics controller\&. [\-\-host\-iface=<iface> | \-f <iface>] [\-\-hostnqn=<hostnqn> | \-q <hostnqn>] [\-\-hostid=<hostid> | \-I <hostid>] + [\-\-config\-file=<cfg> | \-J <cfg> ] + [\-\-dhchap\-secret=<secret> | \-S <secret>] + [\-\-dhchap\-ctrl\-secret=<secret> | \-C <secret>] [\-\-nr\-io\-queues=<#> | \-i <#>] [\-\-nr\-write\-queues=<#> | \-W <#>] [\-\-nr\-poll\-queues=<#> | \-P <#>] @@ -52,6 +55,7 @@ nvme-connect \- Connect to a Fabrics controller\&. [\-\-disable\-sqflow | \-d] [\-\-hdr\-digest | \-g] [\-\-data\-digest | \-G] + [\-\-dump\-config | \-O] [\-\-output\-format=<fmt> | \-o <fmt>] .fi .SH "DESCRIPTION" @@ -134,6 +138,26 @@ Overrides the default Host NQN that identifies the NVMe Host\&. If this option i UUID(Universally Unique Identifier) to be discovered which should be formatted\&. .RE .PP +\-J <cfg>, \-\-config\-file=<cfg> +.RS 4 +Use the specified JSON configuration file instead of the default /etc/nvme/config\&.json file or +\fInone\fR +to not read in an existing configuration file\&. The JSON configuration file format is documented in +\m[blue]\fBhttps://github\&.com/linux\-nvme/libnvme/doc/config\-schema\&.json\fR\m[] +.RE +.PP +\-S <secret>, \-\-dhchap\-secret=<secret> +.RS 4 +NVMe In\-band authentication secret; needs to be in ASCII format as specified in NVMe 2\&.0 section 8\&.13\&.5\&.8 +\fISecret representation\fR\&. If this option is not specified, the default is read from /etc/nvme/hostkey\&. If that does not exist no in\-band authentication is attempted\&. +.RE +.PP +\-C <secret>, \-\-dhchap\-ctrl\-secret=<secret> +.RS 4 +NVMe In\-band authentication controller secret for bi\-directional authentication; needs to be in ASCII format as specified in NVMe 2\&.0 section 8\&.13\&.5\&.8 +\fISecret representation\fR\&. If not present bi\-directional authentication is not attempted\&. +.RE +.PP \-i <#>, \-\-nr\-io\-queues=<#> .RS 4 Overrides the default number of I/O queues create by the driver\&. @@ -171,7 +195,7 @@ Overrides the default controller loss timeout period (in seconds)\&. .PP \-D, \-\-duplicate\-connect .RS 4 -Allows duplicated connections between same trnsport host and subsystem port\&. +Allows duplicated connections between same transport host and subsystem port\&. .RE .PP \-d, \-\-disable\-sqflow @@ -189,6 +213,11 @@ Generates/verifies header digest (TCP)\&. Generates/verifies data digest (TCP)\&. .RE .PP +\-O, \-\-dump\-config +.RS 4 +Print out resulting JSON configuration file to stdout\&. +.RE +.PP \-o <format>, \-\-output\-format=<format> .RS 4 Set the reporting format to diff --git a/Documentation/nvme-connect.html b/Documentation/nvme-connect.html index 1f523dc..c0f1eca 100644 --- a/Documentation/nvme-connect.html +++ b/Documentation/nvme-connect.html @@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -755,8 +755,12 @@ nvme-connect(1) Manual Page [--traddr=<traddr> | -a <traddr>]
[--trsvcid=<trsvcid> | -s <trsvcid>]
[--host-traddr=<traddr> | -w <traddr>]
+ [--host-iface=<iface> | -f <iface>]
[--hostnqn=<hostnqn> | -q <hostnqn>]
[--hostid=<hostid> | -I <hostid>]
+ [--config-file=<cfg> | -J <cfg> ]
+ [--dhchap-secret=<secret> | -S <secret>]
+ [--dhchap-ctrl-secret=<secret> | -C <secret>]
[--nr-io-queues=<#> | -i <#>]
[--nr-write-queues=<#> | -W <#>]
[--nr-poll-queues=<#> | -P <#>]
@@ -767,7 +771,9 @@ nvme-connect(1) Manual Page [--duplicate-connect | -D]
[--disable-sqflow | -d]
[--hdr-digest | -g]
- [--data-digest | -G]</pre>
+ [--data-digest | -G]
+ [--dump-config | -O]
+ [--output-format=<fmt> | -o <fmt>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -873,7 +879,21 @@ cellspacing="0" cellpadding="4"> <dd>
<p>
This field specifies the network address used on the host to connect
- to the Controller.
+ to the Controller. For TCP, this sets the source address on the socket.
+</p>
+</dd>
+<dt class="hdlist1">
+-f <iface>
+</dt>
+<dt class="hdlist1">
+--host-iface=<iface>
+</dt>
+<dd>
+<p>
+ This field specifies the network interface used on the host to connect
+ to the Controller (e.g. IP eth1, enp2s0, enx78e7d1ea46da). This forces
+ the connection to be made on a specific interface instead of letting
+ the system decide.
</p>
</dd>
<dt class="hdlist1">
@@ -904,6 +924,50 @@ cellspacing="0" cellpadding="4"> </p>
</dd>
<dt class="hdlist1">
+-J <cfg>
+</dt>
+<dt class="hdlist1">
+--config-file=<cfg>
+</dt>
+<dd>
+<p>
+ Use the specified JSON configuration file instead of the
+ default /etc/nvme/config.json file or <em>none</em> to not read in
+ an existing configuration file. The JSON configuration file
+ format is documented in
+ <a href="https://github.com/linux-nvme/libnvme/doc/config-schema.json">https://github.com/linux-nvme/libnvme/doc/config-schema.json</a>
+</p>
+</dd>
+<dt class="hdlist1">
+-S <secret>
+</dt>
+<dt class="hdlist1">
+--dhchap-secret=<secret>
+</dt>
+<dd>
+<p>
+ NVMe In-band authentication secret; needs to be in ASCII format as
+ specified in NVMe 2.0 section 8.13.5.8 <em>Secret representation</em>.
+ If this option is not specified, the default is read from
+ /etc/nvme/hostkey. If that does not exist no in-band authentication
+ is attempted.
+</p>
+</dd>
+<dt class="hdlist1">
+-C <secret>
+</dt>
+<dt class="hdlist1">
+--dhchap-ctrl-secret=<secret>
+</dt>
+<dd>
+<p>
+ NVMe In-band authentication controller secret for bi-directional
+ authentication; needs to be in ASCII format as
+ specified in NVMe 2.0 section 8.13.5.8 <em>Secret representation</em>.
+ If not present bi-directional authentication is not attempted.
+</p>
+</dd>
+<dt class="hdlist1">
-i <#>
</dt>
<dt class="hdlist1">
@@ -990,7 +1054,7 @@ cellspacing="0" cellpadding="4"> </dt>
<dd>
<p>
- Allows duplicated connections between same trnsport host and subsystem
+ Allows duplicated connections between same transport host and subsystem
port.
</p>
</dd>
@@ -1028,6 +1092,30 @@ cellspacing="0" cellpadding="4"> Generates/verifies data digest (TCP).
</p>
</dd>
+<dt class="hdlist1">
+-O
+</dt>
+<dt class="hdlist1">
+--dump-config
+</dt>
+<dd>
+<p>
+ Print out resulting JSON configuration file to stdout.
+</p>
+</dd>
+<dt class="hdlist1">
+-o <format>
+</dt>
+<dt class="hdlist1">
+--output-format=<format>
+</dt>
+<dd>
+<p>
+ Set the reporting format to <em>normal</em> or <em>json</em>. Only one output format can
+ be used at a time. When this option is specified, the device associated with
+ the connection will be printed. Nothing is printed otherwise.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -1074,7 +1162,7 @@ and <a href="mailto:hch@lst.de">Christoph Hellwig</a></p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2020-07-14 17:50:40 -03
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-connect.txt b/Documentation/nvme-connect.txt index dd31cd3..f57b34d 100644 --- a/Documentation/nvme-connect.txt +++ b/Documentation/nvme-connect.txt @@ -17,6 +17,9 @@ SYNOPSIS [--host-iface=<iface> | -f <iface>] [--hostnqn=<hostnqn> | -q <hostnqn>] [--hostid=<hostid> | -I <hostid>] + [--config-file=<cfg> | -J <cfg> ] + [--dhchap-secret=<secret> | -S <secret>] + [--dhchap-ctrl-secret=<secret> | -C <secret>] [--nr-io-queues=<#> | -i <#>] [--nr-write-queues=<#> | -W <#>] [--nr-poll-queues=<#> | -P <#>] @@ -28,6 +31,7 @@ SYNOPSIS [--disable-sqflow | -d] [--hdr-digest | -g] [--data-digest | -G] + [--dump-config | -O] [--output-format=<fmt> | -o <fmt>] DESCRIPTION @@ -84,7 +88,7 @@ OPTIONS --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 + @SYSCONFDIR@/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. @@ -93,6 +97,29 @@ OPTIONS UUID(Universally Unique Identifier) to be discovered which should be formatted. +-J <cfg>:: +--config-file=<cfg>:: + Use the specified JSON configuration file instead of the + default @SYSCONFDIR@/nvme/config.json file or 'none' to not read in + an existing configuration file. The JSON configuration file + format is documented in + https://github.com/linux-nvme/libnvme/doc/config-schema.json + +-S <secret>:: +--dhchap-secret=<secret>:: + NVMe In-band authentication secret; needs to be in ASCII format as + specified in NVMe 2.0 section 8.13.5.8 'Secret representation'. + If this option is not specified, the default is read from + @SYSCONFDIR@/nvme/hostkey. If that does not exist no in-band authentication + is attempted. + +-C <secret>:: +--dhchap-ctrl-secret=<secret>:: + NVMe In-band authentication controller secret for bi-directional + authentication; needs to be in ASCII format as + specified in NVMe 2.0 section 8.13.5.8 'Secret representation'. + If not present bi-directional authentication is not attempted. + -i <#>:: --nr-io-queues=<#>:: Overrides the default number of I/O queues create by the driver. @@ -125,7 +152,7 @@ OPTIONS -D:: --duplicate-connect:: - Allows duplicated connections between same trnsport host and subsystem + Allows duplicated connections between same transport host and subsystem port. -d:: @@ -141,6 +168,10 @@ OPTIONS --data-digest:: Generates/verifies data digest (TCP). +-O:: +--dump-config:: + Print out resulting JSON configuration file to stdout. + -o <format>:: --output-format=<format>:: Set the reporting format to 'normal' or 'json'. Only one output format can diff --git a/Documentation/nvme-copy.1 b/Documentation/nvme-copy.1 index f215724..d5683e3 100644 --- a/Documentation/nvme-copy.1 +++ b/Documentation/nvme-copy.1 @@ -2,12 +2,12 @@ .\" Title: nvme-copy .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-COPY" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-COPY" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-copy.html b/Documentation/nvme-copy.html index 38867b0..5d9e575 100644 --- a/Documentation/nvme-copy.html +++ b/Documentation/nvme-copy.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-copy(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -982,7 +982,7 @@ logical block ranges to a single consecutive destination logical block range.</p <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-create-ns.1 b/Documentation/nvme-create-ns.1 index 3931bf9..4ba894c 100644 --- a/Documentation/nvme-create-ns.1 +++ b/Documentation/nvme-create-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-create-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-CREATE\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-CREATE\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -40,6 +40,7 @@ nvme-create-ns \- Send NVMe Namespace management command to create namespace, re [\-\-anagrp\-id=<anagrpid> | \-a <anagrpid>] [\-\-nvmset\-id=<nvmsetid> | \-i <nvmsetid>] [\-\-csi=<command_set_identifier> | \-y <command_set_identifier>] + [\-\-lbstm=<lbstm> | \-l <lbstm>] [\-\-block\-size=<block\-size> | \-b <block\-size>] [\-\-timeout=<timeout> | \-t <timeout>] DESCRIPTION @@ -96,6 +97,11 @@ This field specifies the identifier of the NVM Set\&. This field specifies the identifier of command set\&. if not issued, NVM Command Set will be selected\&. .RE .PP +\-l <lbstm>, \-\-lbstm=<lbstm> +.RS 4 +Logical Block Storage Tag Mask for end\-to\-end protection\&. +.RE +.PP \-b, \-\-block\-size .RS 4 Target block size the new namespace should be formatted as\&. Potential FLBAS values will be values will be scanned and the lowest numbered will be selected for the create\-ns operation\&. Conflicts with \-\-flbas argument\&. diff --git a/Documentation/nvme-create-ns.html b/Documentation/nvme-create-ns.html index dcbb74d..5da96ab 100644 --- a/Documentation/nvme-create-ns.html +++ b/Documentation/nvme-create-ns.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-create-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -757,6 +757,7 @@ nvme-create-ns(1) Manual Page [--anagrp-id=<anagrpid> | -a <anagrpid>]
[--nvmset-id=<nvmsetid> | -i <nvmsetid>]
[--csi=<command_set_identifier> | -y <command_set_identifier>]
+ [--lbstm=<lbstm> | -l <lbstm>]
[--block-size=<block-size> | -b <block-size>]
[--timeout=<timeout> | -t <timeout>]
DESCRIPTION</pre>
@@ -866,6 +867,17 @@ OPTIONS</code></pre> </p>
</dd>
<dt class="hdlist1">
+-l <lbstm>
+</dt>
+<dt class="hdlist1">
+--lbstm=<lbstm>
+</dt>
+<dd>
+<p>
+ Logical Block Storage Tag Mask for end-to-end protection.
+</p>
+</dd>
+<dt class="hdlist1">
-b
</dt>
<dt class="hdlist1">
@@ -898,7 +910,7 @@ OPTIONS</code></pre> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-create-ns.txt b/Documentation/nvme-create-ns.txt index 09c0c78..7fd64f4 100644 --- a/Documentation/nvme-create-ns.txt +++ b/Documentation/nvme-create-ns.txt @@ -16,6 +16,7 @@ SYNOPSIS [--anagrp-id=<anagrpid> | -a <anagrpid>] [--nvmset-id=<nvmsetid> | -i <nvmsetid>] [--csi=<command_set_identifier> | -y <command_set_identifier>] + [--lbstm=<lbstm> | -l <lbstm>] [--block-size=<block-size> | -b <block-size>] [--timeout=<timeout> | -t <timeout>] DESCRIPTION @@ -64,6 +65,10 @@ OPTIONS This field specifies the identifier of command set. if not issued, NVM Command Set will be selected. +-l <lbstm>:: +--lbstm=<lbstm>:: + Logical Block Storage Tag Mask for end-to-end protection. + -b:: --block-size:: Target block size the new namespace should be formatted as. Potential FLBAS diff --git a/Documentation/nvme-delete-ns.1 b/Documentation/nvme-delete-ns.1 index 5cebcf0..0fe6f4b 100644 --- a/Documentation/nvme-delete-ns.1 +++ b/Documentation/nvme-delete-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-delete-ns.html b/Documentation/nvme-delete-ns.html index 2a0351b..ea7a316 100644 --- a/Documentation/nvme-delete-ns.html +++ b/Documentation/nvme-delete-ns.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -799,7 +799,7 @@ The <code>'--namespace-id'</code> option is mandatory.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-dera-stat.1 b/Documentation/nvme-dera-stat.1 index ca4d5c4..b17bff4 100644 --- a/Documentation/nvme-dera-stat.1 +++ b/Documentation/nvme-dera-stat.1 @@ -2,12 +2,12 @@ .\" Title: nvme-dera-stat .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DERA\-STAT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DERA\-STAT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-dera-stat.html b/Documentation/nvme-dera-stat.html index 47be552..686ec98 100644 --- a/Documentation/nvme-dera-stat.html +++ b/Documentation/nvme-dera-stat.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-dera-stat(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -797,7 +797,7 @@ Print the Dera Device status and Additional SMART log page in a human readable f <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-detach-ns.1 b/Documentation/nvme-detach-ns.1 index 7bb5a8b..8b794d4 100644 --- a/Documentation/nvme-detach-ns.1 +++ b/Documentation/nvme-detach-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-detach-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DETACH\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DETACH\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-detach-ns.html b/Documentation/nvme-detach-ns.html index ddf7824..59b13f8 100644 --- a/Documentation/nvme-detach-ns.html +++ b/Documentation/nvme-detach-ns.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-detach-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -810,7 +810,7 @@ controller identifiers.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-device-self-test.1 b/Documentation/nvme-device-self-test.1 index 4e4ac30..df9df60 100644 --- a/Documentation/nvme-device-self-test.1 +++ b/Documentation/nvme-device-self-test.1 @@ -2,12 +2,12 @@ .\" Title: nvme-device-self-test .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DEVICE\-SELF\-" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DEVICE\-SELF\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-device-self-test.html b/Documentation/nvme-device-self-test.html index 0c7ae22..86413fc 100644 --- a/Documentation/nvme-device-self-test.html +++ b/Documentation/nvme-device-self-test.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-device-self-test(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -833,7 +833,7 @@ Abort the device self-test operation in the namespace-id 1: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-dim.1 b/Documentation/nvme-dim.1 new file mode 100644 index 0000000..908eec8 --- /dev/null +++ b/Documentation/nvme-dim.1 @@ -0,0 +1,113 @@ +'\" t +.\" Title: nvme-dim +.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] +.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> +.\" Date: 04/08/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-DIM" "1" "04/08/2022" "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-dim \- Send Discovery Information Management command to one or more Discovery Controllers\&. +.SH "SYNOPSIS" +.sp +.nf +\fInvme dim\fR + [\-\-task=<task> | \-t <task>] + [\-\-nqn=<nqn> | \-n <nqn>] + [\-\-device=<device> | \-d <device>] +.fi +.SH "DESCRIPTION" +.sp +Send Discovery Information Management (DIM) command to one or more Discovery Controllers\&. The DIM command allows performing two types of tasks: register or deregister\&. +.sp +The DIM command is used to explicitly register with Discovery Controllers (DC), especially with Central Discovery Controllers (CDC)\&. CDCs maintain a database (DB) of all the Hosts and Storage Susbsystems in a network\&. The register task is used to add a host to the CDC\(cqs DB\&. The deregister task is used to remove a host from the CDC\(cqs DB\&. +.sp +During a register operation the host will send mandatory information such as the Host\(cqs NQN and ID, as well as the Host\(cqs hostname and the Operating System\(cqs version that it is running on\&. There is also an optional Host Symbolic Name that can be registered with the CDC\&. +.sp +This command can only be applied to existing DC connections previously created with the nvme\-discover(1) command using the \-\-persistent option\&. +.SH "OPTIONS" +.PP +\-t <task>, \-\-task <task> +.RS 4 +The task to perform: "register" or "deregister"\&. +.RE +.PP +\-n <subnqn>, \-\-nqn <nqn> +.RS 4 +The DIM command will be sent to the Discovery Controller (DC) matching this NQN\&. A list of comma\-separated NQNs can be supplied to apply the command to more than one DC\&. +.RE +.PP +\-d <device>, \-\-device <device> +.RS 4 +The DIM command will be sent to the Discovery Controllers (DC) associated with this NVMe device handle\&. A list of comma\-separated device handles can be supplied to apply the command to more than one DC\&. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Register with the Central Discovery Controller (CDC) named nqn\&.1988\-11\&.com\&.dell:SFSS:1:20220118125153e8: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme dim \-\-task=register \-\-nqn=nqn\&.1988\-11\&.com\&.dell:SFSS:1:20220118125153e8 +.fi +.if n \{\ +.RE +.\} +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Deregister from Central Discovery Controller (CDC) associated with nvme4 +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme dim \-\-task=deregister \-\-device=nvme4 +.fi +.if n \{\ +.RE +.\} +.RE +.SH "SEE ALSO" +.sp +nvme\-discover(1) +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-lnvm-diag-set-bbtbl.html b/Documentation/nvme-dim.html index b8e5943..875689d 100644 --- a/Documentation/nvme-lnvm-diag-set-bbtbl.html +++ b/Documentation/nvme-dim.html @@ -4,8 +4,8 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-diag-set-bbtbl(1)</title>
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-dim(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -735,12 +735,12 @@ asciidoc.install(); <body class="manpage">
<div id="header">
<h1>
-nvme-lnvm-diag-set-bbtbl(1) Manual Page
+nvme-dim(1) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>nvme-lnvm-diag-set-bbtbl -
- Set a block state in the bad block table
+<p>nvme-dim -
+ Send Discovery Information Management command to one or more Discovery Controllers.
</p>
</div>
</div>
@@ -749,12 +749,10 @@ nvme-lnvm-diag-set-bbtbl(1) Manual Page <h2 id="_synopsis">SYNOPSIS</h2>
<div class="sectionbody">
<div class="verseblock">
-<pre class="content"><em>nvme lnvm-diag-set-bbtbl</em> [--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>]</pre>
+<pre class="content"><em>nvme dim</em>
+ [--task=<task> | -t <task>]
+ [--nqn=<nqn> | -n <nqn>]
+ [--device=<device> | -d <device>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -762,14 +760,20 @@ nvme-lnvm-diag-set-bbtbl(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Set the bad block table for a given channel, lun, plane and block with value v.</p></div>
-<div class="paragraph"><p>For each block available, the status byte is read as follows:</p></div>
-<div class="paragraph"><p>0: Good block
-1: Bad block
-2: Grown bad block
-4: Device reserved block
-8: Host-side reserved block
-16: Media managed reserved block</p></div>
+<div class="paragraph"><p>Send Discovery Information Management (DIM) command to one or more Discovery
+Controllers. The DIM command allows performing two types of tasks: register or
+deregister.</p></div>
+<div class="paragraph"><p>The DIM command is used to explicitly register with Discovery Controllers (DC),
+especially with Central Discovery Controllers (CDC). CDCs maintain a database (DB)
+of all the Hosts and Storage Susbsystems in a network. The register task is used
+to add a host to the CDC’s DB. The deregister task is used to remove a host from
+the CDC’s DB.</p></div>
+<div class="paragraph"><p>During a register operation the host will send mandatory information such as the
+Host’s NQN and ID, as well as the Host’s hostname and the Operating System’s
+version that it is running on. There is also an optional Host Symbolic Name
+that can be registered with the CDC.</p></div>
+<div class="paragraph"><p>This command can only be applied to existing DC connections previously created
+with the nvme-discover(1) command using the --persistent option.</p></div>
</div>
</div>
<div class="sect1">
@@ -777,58 +781,40 @@ nvme-lnvm-diag-set-bbtbl(1) Manual Page <div class="sectionbody">
<div class="dlist"><dl>
<dt class="hdlist1">
---namespace-id=<NUM>
+-t <task>
</dt>
<dt class="hdlist1">
--n <NUM>
+--task <task>
</dt>
<dd>
<p>
- Namespace id to use
+ The task to perform: "register" or "deregister".
</p>
</dd>
<dt class="hdlist1">
---channel-id
+-n <subnqn>
</dt>
<dt class="hdlist1">
--c
+--nqn <nqn>
</dt>
<dd>
<p>
- Channel id
+ The DIM command will be sent to the Discovery Controller (DC) matching this
+ NQN. A list of comma-separated NQNs can be supplied to apply the command to
+ more than one DC.
</p>
</dd>
<dt class="hdlist1">
---lun-id
+-d <device>
</dt>
<dt class="hdlist1">
--l
+--device <device>
</dt>
<dd>
<p>
- LUN id
-</p>
-</dd>
-<dt class="hdlist1">
---plane-id
-</dt>
-<dt class="hdlist1">
--p
-</dt>
-<dd>
-<p>
- Plane id
-</p>
-</dd>
-<dt class="hdlist1">
---block-id
-</dt>
-<dt class="hdlist1">
--b
-</dt>
-<dd>
-<p>
- Block id
+ The DIM command will be sent to the Discovery Controllers (DC) associated
+ with this NVMe device handle. A list of comma-separated device handles can
+ be supplied to apply the command to more than one DC.
</p>
</dd>
</dl></div>
@@ -840,15 +826,30 @@ nvme-lnvm-diag-set-bbtbl(1) Manual Page <div class="ulist"><ul>
<li>
<p>
-Set channel 0, lun 0, plane 0, block 10 to bad block value 2 (grown bad)
- on physical device /dev/nvme0
+Register with the Central Discovery Controller (CDC) named
+nqn.1988-11.com.dell:SFSS:1:20220118125153e8:
</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme dim --task=register --nqn=nqn.1988-11.com.dell:SFSS:1:20220118125153e8</code></pre>
+</div></div>
</li>
-</ul></div>
+<li>
+<p>
+Deregister from Central Discovery Controller (CDC) associated with nvme4
+</p>
<div class="listingblock">
<div class="content">
-<pre><code># nvme lnvm-diag-set-bbtbl /dev/nvme0 -c 0 -l 0 -p 0 -b 10 -v 2</code></pre>
+<pre><code># nvme dim --task=deregister --device=nvme4</code></pre>
</div></div>
+</li>
+</ul></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_see_also">SEE ALSO</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>nvme-discover(1)</p></div>
</div>
</div>
<div class="sect1">
@@ -862,7 +863,7 @@ Set channel 0, lun 0, plane 0, block 10 to bad block value 2 (grown bad) <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-dim.txt b/Documentation/nvme-dim.txt new file mode 100644 index 0000000..805c7ff --- /dev/null +++ b/Documentation/nvme-dim.txt @@ -0,0 +1,75 @@ +nvme-dim(1) +=========== + +NAME +---- +nvme-dim - Send Discovery Information Management command to one or more Discovery Controllers. + +SYNOPSIS +-------- +[verse] +'nvme dim' + [--task=<task> | -t <task>] + [--nqn=<nqn> | -n <nqn>] + [--device=<device> | -d <device>] + +DESCRIPTION +----------- +Send Discovery Information Management (DIM) command to one or more Discovery +Controllers. The DIM command allows performing two types of tasks: register or +deregister. + +The DIM command is used to explicitly register with Discovery Controllers (DC), +especially with Central Discovery Controllers (CDC). CDCs maintain a database (DB) +of all the Hosts and Storage Susbsystems in a network. The register task is used +to add a host to the CDC's DB. The deregister task is used to remove a host from +the CDC's DB. + +During a register operation the host will send mandatory information such as the +Host's NQN and ID, as well as the Host's hostname and the Operating System's +version that it is running on. There is also an optional Host Symbolic Name +that can be registered with the CDC. + +This command can only be applied to existing DC connections previously created +with the nvme-discover(1) command using the --persistent option. + +OPTIONS +------- +-t <task>:: +--task <task>:: + The task to perform: "register" or "deregister". + +-n <subnqn>:: +--nqn <nqn>:: + The DIM command will be sent to the Discovery Controller (DC) matching this + NQN. A list of comma-separated NQNs can be supplied to apply the command to + more than one DC. + +-d <device>:: +--device <device>:: + The DIM command will be sent to the Discovery Controllers (DC) associated + with this NVMe device handle. A list of comma-separated device handles can + be supplied to apply the command to more than one DC. + +EXAMPLES +-------- +* Register with the Central Discovery Controller (CDC) named +nqn.1988-11.com.dell:SFSS:1:20220118125153e8: ++ +------------ +# nvme dim --task=register --nqn=nqn.1988-11.com.dell:SFSS:1:20220118125153e8 +------------ + +* Deregister from Central Discovery Controller (CDC) associated with nvme4 ++ +------------ +# nvme dim --task=deregister --device=nvme4 +------------ + +SEE ALSO +-------- +nvme-discover(1) + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-dir-receive.1 b/Documentation/nvme-dir-receive.1 index e6ce68c..b8a1af4 100644 --- a/Documentation/nvme-dir-receive.1 +++ b/Documentation/nvme-dir-receive.1 @@ -2,12 +2,12 @@ .\" Title: nvme-dir-receive .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DIR\-RECEIVE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DIR\-RECEIVE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-dir-receive.html b/Documentation/nvme-dir-receive.html index a84c72d..c978644 100644 --- a/Documentation/nvme-dir-receive.html +++ b/Documentation/nvme-dir-receive.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-dir-receive(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -969,7 +969,7 @@ Get streams directive status : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-dir-send.1 b/Documentation/nvme-dir-send.1 index fbc9a48..5744105 100644 --- a/Documentation/nvme-dir-send.1 +++ b/Documentation/nvme-dir-send.1 @@ -2,12 +2,12 @@ .\" Title: nvme-dir-send .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DIR\-SEND" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DIR\-SEND" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-dir-send.html b/Documentation/nvme-dir-send.html index 301be97..a6f774c 100644 --- a/Documentation/nvme-dir-send.html +++ b/Documentation/nvme-dir-send.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-dir-send(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -982,7 +982,7 @@ Release stream ID 3 : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-disconnect-all.1 b/Documentation/nvme-disconnect-all.1 index d76a9d0..dfae0c0 100644 --- a/Documentation/nvme-disconnect-all.1 +++ b/Documentation/nvme-disconnect-all.1 @@ -2,12 +2,12 @@ .\" Title: nvme-disconnect-all .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DISCONNECT\-AL" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DISCONNECT\-AL" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-disconnect-all.html b/Documentation/nvme-disconnect-all.html index 88fbf61..5049ed5 100644 --- a/Documentation/nvme-disconnect-all.html +++ b/Documentation/nvme-disconnect-all.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-disconnect-all(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -795,7 +795,7 @@ Disconnect all existing nvme controllers: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-disconnect.1 b/Documentation/nvme-disconnect.1 index 5ed7ef8..1ecc26e 100644 --- a/Documentation/nvme-disconnect.1 +++ b/Documentation/nvme-disconnect.1 @@ -2,12 +2,12 @@ .\" Title: nvme-disconnect .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DISCONNECT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DISCONNECT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-disconnect.html b/Documentation/nvme-disconnect.html index 3aac5c1..20d0109 100644 --- a/Documentation/nvme-disconnect.html +++ b/Documentation/nvme-disconnect.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-disconnect(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -839,7 +839,7 @@ Disconnect the controller nvme4 <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-discover.1 b/Documentation/nvme-discover.1 index aa6edf4..cbc7766 100644 --- a/Documentation/nvme-discover.1 +++ b/Documentation/nvme-discover.1 @@ -2,12 +2,12 @@ .\" Title: nvme-discover .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DISCOVER" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DISCOVER" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -34,6 +34,7 @@ nvme-discover \- Send Get Log Page request to Discovery Controller\&. .nf \fInvme discover\fR [\-\-transport=<trtype> | \-t <trtype>] + [\-\-nqn=<subnqn> | \-n <subnqn>] [\-\-traddr=<traddr> | \-a <traddr>] [\-\-trsvcid=<trsvcid> | \-s <trsvcid>] [\-\-host\-traddr=<traddr> | \-w <traddr>] @@ -42,6 +43,7 @@ nvme-discover \- Send Get Log Page request to Discovery Controller\&. [\-\-hostid=<hostid> | \-I <hostid>] [\-\-raw=<filename> | \-r <filename>] [\-\-device=<device> | \-d <device>] + [\-\-cfg\-file=<cfg> | \-C <cfg> ] [\-\-keep\-alive\-tmo=<sec> | \-k <sec>] [\-\-reconnect\-delay=<#> | \-c <#>] [\-\-ctrl\-loss\-tmo=<#> | \-l <#>] @@ -53,7 +55,9 @@ nvme-discover \- Send Get Log Page request to Discovery Controller\&. [\-\-queue\-size=<#> | \-Q <#>] [\-\-persistent | \-p] [\-\-quiet | \-S] + [\-\-dump\-config | \-O] [\-\-output\-format=<fmt> | \-o <fmt>] + [\-\-force] .fi .SH "DESCRIPTION" .sp @@ -111,6 +115,11 @@ T} .sp 1 .RE .PP +\-n <subnqn>, \-\-nqn <subnqn> +.RS 4 +This field specifies the name for the NVMe subsystem to connect to\&. +.RE +.PP \-a <traddr>, \-\-traddr=<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\&. @@ -155,6 +164,14 @@ will dump the output to stdout\&. This field takes a device as input\&. Device is in the format of nvme*, eg\&. nvme0, nvme1 .RE .PP +\-C <cfg>, \-\-config\-file=<cfg> +.RS 4 +Use the specified JSON configuration file instead of the default /etc/nvme/config\&.json file or +\fInone\fR +to not read in an existing configuration file\&. The JSON configuration file format is documented in +\m[blue]\fBhttps://github\&.com/linux\-nvme/libnvme/doc/config\-schema\&.json\fR\m[] +.RE +.PP \-k <#>, \-\-keep\-alive\-tmo=<#> .RS 4 Overrides the default dealy (in seconds) for keep alive\&. This option will be ignored for the discovery, and it is only implemented for completeness\&. @@ -210,6 +227,11 @@ Persistent discovery connection\&. Suppress already connected errors\&. .RE .PP +\-O, \-\-dump\-config +.RS 4 +Print out resulting JSON configuration file to stdout\&. +.RE +.PP \-o <format>, \-\-output\-format=<format> .RS 4 Set the reporting format to @@ -217,6 +239,11 @@ Set the reporting format to \fIjson\fR, or \fIbinary\fR\&. Only one output format can be used at a time\&. .RE +.PP +\-\-force +.RS 4 +Disable the built\-in persitent discover connection rules\&. Combined with \-\-persistent flag, always create new persistent discovery connection\&. +.RE .SH "EXAMPLES" .sp .RS 4 diff --git a/Documentation/nvme-discover.html b/Documentation/nvme-discover.html index 2a4493f..9dd5e22 100644 --- a/Documentation/nvme-discover.html +++ b/Documentation/nvme-discover.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-discover(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -751,6 +751,7 @@ nvme-discover(1) Manual Page <div class="verseblock">
<pre class="content"><em>nvme discover</em>
[--transport=<trtype> | -t <trtype>]
+ [--nqn=<subnqn> | -n <subnqn>]
[--traddr=<traddr> | -a <traddr>]
[--trsvcid=<trsvcid> | -s <trsvcid>]
[--host-traddr=<traddr> | -w <traddr>]
@@ -759,6 +760,7 @@ nvme-discover(1) Manual Page [--hostid=<hostid> | -I <hostid>]
[--raw=<filename> | -r <filename>]
[--device=<device> | -d <device>]
+ [--cfg-file=<cfg> | -C <cfg> ]
[--keep-alive-tmo=<sec> | -k <sec>]
[--reconnect-delay=<#> | -c <#>]
[--ctrl-loss-tmo=<#> | -l <#>]
@@ -770,7 +772,9 @@ nvme-discover(1) Manual Page [--queue-size=<#> | -Q <#>]
[--persistent | -p]
[--quiet | -S]
- [--output-format=<fmt> | -o <fmt>]</pre>
+ [--dump-config | -O]
+ [--output-format=<fmt> | -o <fmt>]
+ [--force]</pre>
<div class="attribution">
</div></div>
</div>
@@ -861,6 +865,17 @@ cellspacing="0" cellpadding="4"> </div>
</dd>
<dt class="hdlist1">
+-n <subnqn>
+</dt>
+<dt class="hdlist1">
+--nqn <subnqn>
+</dt>
+<dd>
+<p>
+ This field specifies the name for the NVMe subsystem to connect to.
+</p>
+</dd>
+<dt class="hdlist1">
-a <traddr>
</dt>
<dt class="hdlist1">
@@ -922,8 +937,8 @@ cellspacing="0" cellpadding="4"> <p>
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.
+ /etc/nvme/hostnqn first. If that does not exist, the
+ autogenerated NQN value from the NVMe Host kernel module is used next.
</p>
</dd>
<dt class="hdlist1">
@@ -964,6 +979,21 @@ cellspacing="0" cellpadding="4"> </p>
</dd>
<dt class="hdlist1">
+-C <cfg>
+</dt>
+<dt class="hdlist1">
+--config-file=<cfg>
+</dt>
+<dd>
+<p>
+ Use the specified JSON configuration file instead of the
+ default /etc/nvme/config.json file or <em>none</em> to not read in
+ an existing configuration file. The JSON configuration file
+ format is documented in
+ <a href="https://github.com/linux-nvme/libnvme/doc/config-schema.json">https://github.com/linux-nvme/libnvme/doc/config-schema.json</a>
+</p>
+</dd>
+<dt class="hdlist1">
-k <#>
</dt>
<dt class="hdlist1">
@@ -1093,6 +1123,17 @@ cellspacing="0" cellpadding="4"> </p>
</dd>
<dt class="hdlist1">
+-O
+</dt>
+<dt class="hdlist1">
+--dump-config
+</dt>
+<dd>
+<p>
+ Print out resulting JSON configuration file to stdout.
+</p>
+</dd>
+<dt class="hdlist1">
-o <format>
</dt>
<dt class="hdlist1">
@@ -1104,6 +1145,16 @@ cellspacing="0" cellpadding="4"> <em>binary</em>. Only one output format can be used at a time.
</p>
</dd>
+<dt class="hdlist1">
+--force
+</dt>
+<dd>
+<p>
+ Disable the built-in persitent discover connection rules.
+ Combined with --persistent flag, always create new
+ persistent discovery connection.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -1167,7 +1218,7 @@ nvme-connect-all(1)</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-discover.txt b/Documentation/nvme-discover.txt index d0a281a..e27949b 100644 --- a/Documentation/nvme-discover.txt +++ b/Documentation/nvme-discover.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'nvme discover' [--transport=<trtype> | -t <trtype>] + [--nqn=<subnqn> | -n <subnqn>] [--traddr=<traddr> | -a <traddr>] [--trsvcid=<trsvcid> | -s <trsvcid>] [--host-traddr=<traddr> | -w <traddr>] @@ -18,6 +19,7 @@ SYNOPSIS [--hostid=<hostid> | -I <hostid>] [--raw=<filename> | -r <filename>] [--device=<device> | -d <device>] + [--cfg-file=<cfg> | -C <cfg> ] [--keep-alive-tmo=<sec> | -k <sec>] [--reconnect-delay=<#> | -c <#>] [--ctrl-loss-tmo=<#> | -l <#>] @@ -29,7 +31,9 @@ SYNOPSIS [--queue-size=<#> | -Q <#>] [--persistent | -p] [--quiet | -S] + [--dump-config | -O] [--output-format=<fmt> | -o <fmt>] + [--force] DESCRIPTION ----------- @@ -37,8 +41,8 @@ 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 +find a @SYSCONFDIR@/nvme/discovery.conf file to use to supply a list of +Discovery commands to run. If no @SYSCONFDIR@/nvme/discovery.conf file exists, the command will quit with an error. Otherwise, a specific Discovery Controller should be specified using the @@ -85,6 +89,10 @@ OPTIONS |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 Discovery Controller. @@ -113,8 +121,8 @@ OPTIONS --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. + @SYSCONFDIR@/nvme/hostnqn first. If that does not exist, the + autogenerated NQN value from the NVMe Host kernel module is used next. -I <hostid>:: --hostid=<hostid>:: @@ -132,6 +140,14 @@ OPTIONS This field takes a device as input. Device is in the format of nvme*, eg. nvme0, nvme1 +-C <cfg>:: +--config-file=<cfg>:: + Use the specified JSON configuration file instead of the + default @SYSCONFDIR@/nvme/config.json file or 'none' to not read in + an existing configuration file. The JSON configuration file + format is documented in + https://github.com/linux-nvme/libnvme/doc/config-schema.json + -k <#>:: --keep-alive-tmo=<#>:: Overrides the default dealy (in seconds) for keep alive. @@ -184,11 +200,20 @@ OPTIONS --quiet:: Suppress already connected errors. +-O:: +--dump-config:: + Print out resulting JSON configuration file 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. +--force:: + Disable the built-in persitent discover connection rules. + Combined with --persistent flag, always create new + persistent discovery connection. + EXAMPLES -------- * Query the Discover Controller with IP4 address 192.168.1.3 for all @@ -200,7 +225,7 @@ Port 4420 is used by default: --hostnqn=host1-rogue-nqn ------------ + -* Issue a 'nvme discover' command using a /etc/nvme/discovery.conf file: +* Issue a 'nvme discover' command using a @SYSCONFDIR@/nvme/discovery.conf file: + ----------- # Machine default 'nvme discover' commands. Query the diff --git a/Documentation/nvme-dsm.1 b/Documentation/nvme-dsm.1 index 89d7cc4..05f7288 100644 --- a/Documentation/nvme-dsm.1 +++ b/Documentation/nvme-dsm.1 @@ -2,12 +2,12 @@ .\" Title: nvme-dsm .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-DSM" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-DSM" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-dsm.html b/Documentation/nvme-dsm.html index aa05411..73abce7 100644 --- a/Documentation/nvme-dsm.html +++ b/Documentation/nvme-dsm.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-dsm(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -893,7 +893,7 @@ any settings from the flags may have provided.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-effects-log.1 b/Documentation/nvme-effects-log.1 index 8017853..a7951f5 100644 --- a/Documentation/nvme-effects-log.1 +++ b/Documentation/nvme-effects-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-effects-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-EFFECTS\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-EFFECTS\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-effects-log.html b/Documentation/nvme-effects-log.html index e29e61e..14154a1 100644 --- a/Documentation/nvme-effects-log.html +++ b/Documentation/nvme-effects-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-effects-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -847,7 +847,7 @@ Have the program return the raw structure in binary: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-endurance-event-agg-log.1 b/Documentation/nvme-endurance-event-agg-log.1 index 1444bcf..94fd72c 100644 --- a/Documentation/nvme-endurance-event-agg-log.1 +++ b/Documentation/nvme-endurance-event-agg-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-endurance-event-agg-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ENDURANCE\-EVE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ENDURANCE\-EVE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-endurance-event-agg-log.html b/Documentation/nvme-endurance-event-agg-log.html index 17f5dcd..24f116e 100644 --- a/Documentation/nvme-endurance-event-agg-log.html +++ b/Documentation/nvme-endurance-event-agg-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-endurance-event-agg-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -851,7 +851,7 @@ Print the raw Endurance log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-endurance-log.1 b/Documentation/nvme-endurance-log.1 index 1035279..574b1f9 100644 --- a/Documentation/nvme-endurance-log.1 +++ b/Documentation/nvme-endurance-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-endurance-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ENDURANCE\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ENDURANCE\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-endurance-log.html b/Documentation/nvme-endurance-log.html index d023752..59ce97d 100644 --- a/Documentation/nvme-endurance-log.html +++ b/Documentation/nvme-endurance-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-endurance-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -834,7 +834,7 @@ Print the raw Endurance log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-error-log.1 b/Documentation/nvme-error-log.1 index 318b31c..218abae 100644 --- a/Documentation/nvme-error-log.1 +++ b/Documentation/nvme-error-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-error-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ERROR\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ERROR\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-error-log.html b/Documentation/nvme-error-log.html index d5032ce..78ab884 100644 --- a/Documentation/nvme-error-log.html +++ b/Documentation/nvme-error-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-error-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -849,7 +849,7 @@ Print the raw output to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-fid-support-effects-log.1 b/Documentation/nvme-fid-support-effects-log.1 index b6b6fa6..d064a1e 100644 --- a/Documentation/nvme-fid-support-effects-log.1 +++ b/Documentation/nvme-fid-support-effects-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-fid-support-effects-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-FID\-SUPPORT\-" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-FID\-SUPPORT\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-fid-support-effects-log.html b/Documentation/nvme-fid-support-effects-log.html index b617100..1d00b70 100644 --- a/Documentation/nvme-fid-support-effects-log.html +++ b/Documentation/nvme-fid-support-effects-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-fid-support-effects-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -814,7 +814,7 @@ raw buffer may be printed to stdout.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-08-26 10:36:30 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-flush.1 b/Documentation/nvme-flush.1 index 1af9c6c..adeb7ff 100644 --- a/Documentation/nvme-flush.1 +++ b/Documentation/nvme-flush.1 @@ -2,12 +2,12 @@ .\" Title: nvme-flush .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-FLUSH" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-FLUSH" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-flush.html b/Documentation/nvme-flush.html index 9c659dc..05bb4f9 100644 --- a/Documentation/nvme-flush.html +++ b/Documentation/nvme-flush.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-flush(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -800,7 +800,7 @@ any namespace.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-format.1 b/Documentation/nvme-format.1 index bda93e7..bec8bf3 100644 --- a/Documentation/nvme-format.1 +++ b/Documentation/nvme-format.1 @@ -2,12 +2,12 @@ .\" Title: nvme-format .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-FORMAT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-FORMAT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -40,7 +40,7 @@ nvme-format \- Format an NVMe device [\-\-pi=<pi> | \-i <pi>] [\-\-ms=<ms> | \-m <ms>] [\-\-reset | \-r ] - [\-\-force | \-f ] + [\-\-force ] [\-\-timeout=<timeout> | \-t <timeout> ] .fi .SH "DESCRIPTION" @@ -168,7 +168,7 @@ Metadata Settings: This field is set to \(oq1\(cq if the metadata is transferred Issue a reset after successful format\&. Must use the character device for this\&. .RE .PP -\-f, \-\-force +\-\-force .RS 4 Just send the command immediately without warning of the implications\&. .RE diff --git a/Documentation/nvme-format.html b/Documentation/nvme-format.html index 39c4827..7312ddd 100644 --- a/Documentation/nvme-format.html +++ b/Documentation/nvme-format.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-format(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -757,7 +757,7 @@ nvme-format(1) Manual Page [--pi=<pi> | -i <pi>]
[--ms=<ms> | -m <ms>]
[--reset | -r ]
- [--force | -f ]
+ [--force ]
[--timeout=<timeout> | -t <timeout> ]</pre>
<div class="attribution">
</div></div>
@@ -977,9 +977,6 @@ cellspacing="0" cellpadding="4"> </p>
</dd>
<dt class="hdlist1">
--f
-</dt>
-<dt class="hdlist1">
--force
</dt>
<dd>
@@ -1038,7 +1035,7 @@ information: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-format.txt b/Documentation/nvme-format.txt index 9ef788a..cbadd1d 100644 --- a/Documentation/nvme-format.txt +++ b/Documentation/nvme-format.txt @@ -16,7 +16,7 @@ SYNOPSIS [--pi=<pi> | -i <pi>] [--ms=<ms> | -m <ms>] [--reset | -r ] - [--force | -f ] + [--force ] [--timeout=<timeout> | -t <timeout> ] DESCRIPTION @@ -128,7 +128,6 @@ cryptographically. This is accomplished by deleting the encryption key. Issue a reset after successful format. Must use the character device for this. --f:: --force:: Just send the command immediately without warning of the implications. diff --git a/Documentation/nvme-fw-commit.1 b/Documentation/nvme-fw-commit.1 index e5d8886..629d4c0 100644 --- a/Documentation/nvme-fw-commit.1 +++ b/Documentation/nvme-fw-commit.1 @@ -2,12 +2,12 @@ .\" Title: nvme-fw-commit .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-FW\-COMMIT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-FW\-COMMIT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-fw-commit.html b/Documentation/nvme-fw-commit.html index c2f09d6..5354ef2 100644 --- a/Documentation/nvme-fw-commit.html +++ b/Documentation/nvme-fw-commit.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-fw-commit(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -905,7 +905,7 @@ commit the last downloaded fw to slot 1. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-fw-download.1 b/Documentation/nvme-fw-download.1 index 5026876..c446817 100644 --- a/Documentation/nvme-fw-download.1 +++ b/Documentation/nvme-fw-download.1 @@ -2,12 +2,12 @@ .\" Title: nvme-fw-download .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-FW\-DOWNLOAD" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-FW\-DOWNLOAD" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-fw-download.html b/Documentation/nvme-fw-download.html index 6767fab..fb65c62 100644 --- a/Documentation/nvme-fw-download.html +++ b/Documentation/nvme-fw-download.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-fw-download(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -852,7 +852,7 @@ Transfer a firmware size 128KiB at a time: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-fw-log.1 b/Documentation/nvme-fw-log.1 index 7502b84..87fea02 100644 --- a/Documentation/nvme-fw-log.1 +++ b/Documentation/nvme-fw-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-fw-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-FW\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-FW\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-fw-log.html b/Documentation/nvme-fw-log.html index b3fbec0..372ecca 100644 --- a/Documentation/nvme-fw-log.html +++ b/Documentation/nvme-fw-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-fw-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -835,7 +835,7 @@ Print the log firmware to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-gen-dhchap-key.1 b/Documentation/nvme-gen-dhchap-key.1 new file mode 100644 index 0000000..ad54b1f --- /dev/null +++ b/Documentation/nvme-gen-dhchap-key.1 @@ -0,0 +1,69 @@ +'\" t +.\" Title: nvme-gen-dhchap-key +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> +.\" Date: 11/25/2021 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-GEN\-DHCHAP\-K" "1" "11/25/2021" "NVMe" "NVMe Manual" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +nvme-gen-dhchap-key \- Generate a host DH\-HMAC\-CHAP key +.SH "SYNOPSIS" +.sp +.nf +\fInvme gen\-dhchap\-key\fR [\-\-hmac=<hmac\-id> | \-h <hmac\-id>] + [\-\-secret=<secret> | \-s <secret> ] + [\-\-key\-length=<len> | \-l <len> ] + [\-\-nqn=<host\-nqn> | \-n <host\-nqn> ] +.fi +.SH "DESCRIPTION" +.sp +Generate a base64\-encoded DH\-HMAC\-CHAP host key in the form: DHHC\-1:00:ia6zGodOr4SEG0Zzaw398rpY0wqipUWj4jWjUh4HWUz6aQ2n: and prints it to stdout\&. +.SH "OPTIONS" +.PP +\-h <hmac\-id>, \-\-hmac=<hmac\-id> +.RS 4 +Select a HMAC algorithm to use\&. Possible values are: 0 \- No HMAC algorithm 1 \- SHA\-256 2 \- SHA\-384 3 \- SHA\-512 +.RE +.PP +\-s <secret>, \-\-secret=<secret> +.RS 4 +Secret value (in hexadecimal) to be used for the key\&. If none are provided a random value is used\&. +.RE +.PP +\-l <len>, \-\-key\-length=<len> +.RS 4 +Length of the resulting key\&. Possible values are 32, 48, or 64\&. +.RE +.PP +\-n <hostnqn>, \-\-nqn=<hostnqn> +.RS 4 +Host\-NQN to be used for the transformation\&. This parameter is only valid if a non\-zero HMAC function has been specified\&. +.RE +.SH "EXAMPLES" +.sp +No Examples +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-gen-dhchap-key.html b/Documentation/nvme-gen-dhchap-key.html new file mode 100644 index 0000000..224e773 --- /dev/null +++ b/Documentation/nvme-gen-dhchap-key.html @@ -0,0 +1,842 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.6.8" />
+<title>nvme-gen-dhchap-key(1)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+nvme-gen-dhchap-key(1) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>nvme-gen-dhchap-key -
+ Generate a host DH-HMAC-CHAP key
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="verseblock">
+<pre class="content"><em>nvme gen-dhchap-key</em> [--hmac=<hmac-id> | -h <hmac-id>]
+ [--secret=<secret> | -s <secret> ]
+ [--key-length=<len> | -l <len> ]
+ [--nqn=<host-nqn> | -n <host-nqn> ]</pre>
+<div class="attribution">
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_description">DESCRIPTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Generate a base64-encoded DH-HMAC-CHAP host key in the form:
+DHHC-1:00:ia6zGodOr4SEG0Zzaw398rpY0wqipUWj4jWjUh4HWUz6aQ2n:
+and prints it to stdout.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_options">OPTIONS</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-h <hmac-id>
+</dt>
+<dt class="hdlist1">
+--hmac=<hmac-id>
+</dt>
+<dd>
+<p>
+ Select a HMAC algorithm to use. Possible values are:
+ 0 - No HMAC algorithm
+ 1 - SHA-256
+ 2 - SHA-384
+ 3 - SHA-512
+</p>
+</dd>
+<dt class="hdlist1">
+-s <secret>
+</dt>
+<dt class="hdlist1">
+--secret=<secret>
+</dt>
+<dd>
+<p>
+ Secret value (in hexadecimal) to be used for the key. If none are
+ provided a random value is used.
+</p>
+</dd>
+<dt class="hdlist1">
+-l <len>
+</dt>
+<dt class="hdlist1">
+--key-length=<len>
+</dt>
+<dd>
+<p>
+ Length of the resulting key. Possible values are 32, 48, or 64.
+</p>
+</dd>
+<dt class="hdlist1">
+-n <hostnqn>
+</dt>
+<dt class="hdlist1">
+--nqn=<hostnqn>
+</dt>
+<dd>
+<p>
+ Host-NQN to be used for the transformation. This parameter is only
+ valid if a non-zero HMAC function has been specified.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">EXAMPLES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>No Examples</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_nvme">NVME</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2021-11-25 14:12:38 KST
+</div>
+</div>
+</body>
+</html>
diff --git a/Documentation/nvme-gen-dhchap-key.txt b/Documentation/nvme-gen-dhchap-key.txt new file mode 100644 index 0000000..79e8ed5 --- /dev/null +++ b/Documentation/nvme-gen-dhchap-key.txt @@ -0,0 +1,52 @@ +nvme-gen-dhchap-key(1) +====================== + +NAME +---- +nvme-gen-dhchap-key - Generate a host DH-HMAC-CHAP key + +SYNOPSIS +-------- +[verse] +'nvme gen-dhchap-key' [--hmac=<hmac-id> | -h <hmac-id>] + [--secret=<secret> | -s <secret> ] + [--key-length=<len> | -l <len> ] + [--nqn=<host-nqn> | -n <host-nqn> ] + +DESCRIPTION +----------- +Generate a base64-encoded DH-HMAC-CHAP host key in the form: +DHHC-1:00:ia6zGodOr4SEG0Zzaw398rpY0wqipUWj4jWjUh4HWUz6aQ2n: +and prints it to stdout. + +OPTIONS +------- +-h <hmac-id>:: +--hmac=<hmac-id>:: + Select a HMAC algorithm to use. Possible values are: + 0 - No HMAC algorithm + 1 - SHA-256 + 2 - SHA-384 + 3 - SHA-512 + +-s <secret>:: +--secret=<secret>:: + Secret value (in hexadecimal) to be used for the key. If none are + provided a random value is used. + +-l <len>:: +--key-length=<len>:: + Length of the resulting key. Possible values are 32, 48, or 64. + +-n <hostnqn>:: +--nqn=<hostnqn>:: + Host-NQN to be used for the transformation. This parameter is only + valid if a non-zero HMAC function has been specified. + +EXAMPLES +-------- +No Examples + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-gen-hostnqn.1 b/Documentation/nvme-gen-hostnqn.1 index 9aee601..79a586f 100644 --- a/Documentation/nvme-gen-hostnqn.1 +++ b/Documentation/nvme-gen-hostnqn.1 @@ -2,12 +2,12 @@ .\" Title: nvme-gen-hostnqn .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-GEN\-HOSTNQN" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-GEN\-HOSTNQN" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-gen-hostnqn.html b/Documentation/nvme-gen-hostnqn.html index 2b43185..1e06595 100644 --- a/Documentation/nvme-gen-hostnqn.html +++ b/Documentation/nvme-gen-hostnqn.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-gen-hostnqn(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -785,7 +785,7 @@ and prints it to stdout.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-gen-tls-key.txt b/Documentation/nvme-gen-tls-key.txt new file mode 100644 index 0000000..cfa8614 --- /dev/null +++ b/Documentation/nvme-gen-tls-key.txt @@ -0,0 +1,40 @@ +nvme-gen-tls-key(1) +====================== + +NAME +---- +nvme-gen-tls-key - Generate a NVMe TLS PSK + +SYNOPSIS +-------- +[verse] +'nvme gen-tls-key' [--hmac=<hmac-id> | -h <hmac-id>] + [--secret=<secret> | -s <secret> ] + +DESCRIPTION +----------- +Generate a base64-encoded NVMe TLS pre-shared key (PSK) in +the PSK interchange format +NVMeTLSkey-1:01:VRLbtnN9AQb2WXW3c9+wEf/DRLz0QuLdbYvEhwtdWwNf9LrZ: +and prints it to stdout. + +OPTIONS +------- +-h <hmac-id>:: +--hmac=<hmac-id>:: + Select a HMAC algorithm to use. Possible values are: + 1 - SHA-256 (default) + 2 - SHA-384 + +-s <secret>:: +--secret=<secret>:: + Secret value (in hexadecimal) to be used for the key. If none are + provided a random value is used. + +EXAMPLES +-------- +No Examples + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-get-feature.1 b/Documentation/nvme-get-feature.1 index 08808aa..dc9d0e7 100644 --- a/Documentation/nvme-get-feature.1 +++ b/Documentation/nvme-get-feature.1 @@ -2,12 +2,12 @@ .\" Title: nvme-get-feature .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-GET\-FEATURE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-GET\-FEATURE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-get-feature.html b/Documentation/nvme-get-feature.html index 699941f..dd602c4 100644 --- a/Documentation/nvme-get-feature.html +++ b/Documentation/nvme-get-feature.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-get-feature(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -977,7 +977,7 @@ format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-get-lba-status.1 b/Documentation/nvme-get-lba-status.1 index b541658..5d5e40d 100644 --- a/Documentation/nvme-get-lba-status.1 +++ b/Documentation/nvme-get-lba-status.1 @@ -2,12 +2,12 @@ .\" Title: nvme-get-lba-status .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-GET\-LBA\-STAT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-GET\-LBA\-STAT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-get-lba-status.html b/Documentation/nvme-get-lba-status.html index 0c9fb80..2936aa0 100644 --- a/Documentation/nvme-get-lba-status.html +++ b/Documentation/nvme-get-lba-status.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-get-lba-status(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -896,7 +896,7 @@ Get LBA Status of the namespace 1 from SLBA 10 for the max Dwords of 0x1000 <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-get-log.1 b/Documentation/nvme-get-log.1 index e253760..8598804 100644 --- a/Documentation/nvme-get-log.1 +++ b/Documentation/nvme-get-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-get-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-GET\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-GET\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -33,16 +33,16 @@ nvme-get-log \- Retrieves a log page from an NVMe device .sp .nf \fInvme get\-log\fR <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] - [\-\-lpo=<offset> | \-o <offset>] - [\-\-lsp=<field> | \-s <field>] - [\-\-lsi=<field> | \-S <field>] - [\-\-rae | \-r] - [\-\-csi=<command_set_identifier> | \-y <command_set_identifier>] - [\-\-ot | \-O] + [\-\-log\-len=<log\-len> | \-l <log\-len>] + [\-\-aen=<aen> | \-a <aen>] + [\-\-namespace\-id=<nsid> | \-n <nsid>] + [\-\-raw\-binary | \-b] + [\-\-lpo=<offset> | \-o <offset>] + [\-\-lsp=<field> | \-s <field>] + [\-\-lsi=<field> | \-S <field>] + [\-\-rae | \-r] + [\-\-csi=<command_set_identifier> | \-y <command_set_identifier>] + [\-\-ot=<offset_type> | \-O <offset_type>] .fi .SH "DESCRIPTION" .sp @@ -105,7 +105,7 @@ This field specifies the identifier of command set\&. if not issued, NVM Command .PP \-O, \-\-ot .RS 4 -Offset Type +This field specifies the offset type\&. If set to false, the Log Page Offset Lower field and the Log Page Offset Upper field specify the byte offset into the log page to be returned\&. If set to true, the Log Page Offset Lower field and the Log Page Offset Upper field specify the index into the list of data structures in the log page to be returned\&. The default is byte offset\&. If the option is specified the index mode is used\&. .RE .SH "EXAMPLES" .sp diff --git a/Documentation/nvme-get-log.html b/Documentation/nvme-get-log.html index 53af505..5692f60 100644 --- a/Documentation/nvme-get-log.html +++ b/Documentation/nvme-get-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-get-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -750,16 +750,16 @@ nvme-get-log(1) Manual Page <div class="sectionbody">
<div class="verseblock">
<pre class="content"><em>nvme get-log</em> <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]
- [--lpo=<offset> | -o <offset>]
- [--lsp=<field> | -s <field>]
- [--lsi=<field> | -S <field>]
- [--rae | -r]
- [--csi=<command_set_identifier> | -y <command_set_identifier>]
- [--ot | -O]</pre>
+ [--log-len=<log-len> | -l <log-len>]
+ [--aen=<aen> | -a <aen>]
+ [--namespace-id=<nsid> | -n <nsid>]
+ [--raw-binary | -b]
+ [--lpo=<offset> | -o <offset>]
+ [--lsp=<field> | -s <field>]
+ [--lsi=<field> | -S <field>]
+ [--rae | -r]
+ [--csi=<command_set_identifier> | -y <command_set_identifier>]
+ [--ot=<offset_type> | -O <offset_type>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -908,7 +908,14 @@ program to parse.</p></div> </dt>
<dd>
<p>
- Offset Type
+ This field specifies the offset type. If set to false, the
+ Log Page Offset Lower field and the Log Page Offset Upper
+ field specify the byte offset into the log page to be returned.
+ If set to true, the Log Page Offset Lower field and the Log
+ Page Offset Upper field specify the index into the list of
+ data structures in the log page to be returned.
+ The default is byte offset. If the option is specified
+ the index mode is used.
</p>
</dd>
</dl></div>
@@ -955,7 +962,7 @@ Have the program return the raw log page in binary: <div id="footer">
<div id="footer-text">
Last updated
- 2021-06-12 14:47:50 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-get-log.txt b/Documentation/nvme-get-log.txt index d371f5d..a92ab6a 100644 --- a/Documentation/nvme-get-log.txt +++ b/Documentation/nvme-get-log.txt @@ -9,16 +9,16 @@ SYNOPSIS -------- [verse] '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] - [--lpo=<offset> | -o <offset>] - [--lsp=<field> | -s <field>] - [--lsi=<field> | -S <field>] - [--rae | -r] - [--csi=<command_set_identifier> | -y <command_set_identifier>] - [--ot | -O] + [--log-len=<log-len> | -l <log-len>] + [--aen=<aen> | -a <aen>] + [--namespace-id=<nsid> | -n <nsid>] + [--raw-binary | -b] + [--lpo=<offset> | -o <offset>] + [--lsp=<field> | -s <field>] + [--lsi=<field> | -S <field>] + [--rae | -r] + [--csi=<command_set_identifier> | -y <command_set_identifier>] + [--ot=<offset_type> | -O <offset_type>] DESCRIPTION ----------- @@ -86,7 +86,14 @@ OPTIONS -O:: --ot:: - Offset Type + This field specifies the offset type. If set to false, the + Log Page Offset Lower field and the Log Page Offset Upper + field specify the byte offset into the log page to be returned. + If set to true, the Log Page Offset Lower field and the Log + Page Offset Upper field specify the index into the list of + data structures in the log page to be returned. + The default is byte offset. If the option is specified + the index mode is used. EXAMPLES -------- diff --git a/Documentation/nvme-get-ns-id.1 b/Documentation/nvme-get-ns-id.1 index 43ef4d4..10e400e 100644 --- a/Documentation/nvme-get-ns-id.1 +++ b/Documentation/nvme-get-ns-id.1 @@ -2,12 +2,12 @@ .\" Title: nvme-get-ns-id .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-GET\-NS\-ID" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-GET\-NS\-ID" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-get-ns-id.html b/Documentation/nvme-get-ns-id.html index db76ae5..9dab1bf 100644 --- a/Documentation/nvme-get-ns-id.html +++ b/Documentation/nvme-get-ns-id.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-get-ns-id(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -794,7 +794,7 @@ Shows the namespace id for the given block device: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-get-property.1 b/Documentation/nvme-get-property.1 index 1aad427..fcd7223 100644 --- a/Documentation/nvme-get-property.1 +++ b/Documentation/nvme-get-property.1 @@ -2,12 +2,12 @@ .\" Title: nvme-get-property .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-GET\-PROPERTY" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-GET\-PROPERTY" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-get-property.html b/Documentation/nvme-get-property.html index 98e4294..184b281 100644 --- a/Documentation/nvme-get-property.html +++ b/Documentation/nvme-get-property.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-get-property(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -843,7 +843,7 @@ Then look for NVMe Fabrics command (0x7f) at trace <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-help.1 b/Documentation/nvme-help.1 index b2688c3..8de6378 100644 --- a/Documentation/nvme-help.1 +++ b/Documentation/nvme-help.1 @@ -2,12 +2,12 @@ .\" Title: nvme-help .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-HELP" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-HELP" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-help.html b/Documentation/nvme-help.html index 0b0a669..ab6a9aa 100644 --- a/Documentation/nvme-help.html +++ b/Documentation/nvme-help.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-help(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -794,7 +794,7 @@ Show help for nvme smart log: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-huawei-id-ctrl.1 b/Documentation/nvme-huawei-id-ctrl.1 index 1ee1893..bf65b61 100644 --- a/Documentation/nvme-huawei-id-ctrl.1 +++ b/Documentation/nvme-huawei-id-ctrl.1 @@ -2,12 +2,12 @@ .\" Title: nvme-huawei-id-ctrl .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-HUAWEI\-ID\-CT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-HUAWEI\-ID\-CT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-huawei-id-ctrl.html b/Documentation/nvme-huawei-id-ctrl.html index e49362e..0f9a7c1 100644 --- a/Documentation/nvme-huawei-id-ctrl.html +++ b/Documentation/nvme-huawei-id-ctrl.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-huawei-id-ctrl(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -855,7 +855,7 @@ fields in a human readable format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-huawei-list.1 b/Documentation/nvme-huawei-list.1 index 4cd039b..ca9d1e0 100644 --- a/Documentation/nvme-huawei-list.1 +++ b/Documentation/nvme-huawei-list.1 @@ -2,12 +2,12 @@ .\" Title: nvme-list .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LIST" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-LIST" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-huawei-list.html b/Documentation/nvme-huawei-list.html index c79d3f0..ce2178a 100644 --- a/Documentation/nvme-huawei-list.html +++ b/Documentation/nvme-huawei-list.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-list(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -797,7 +797,7 @@ for those Huawei devices as well as some pertinent information about them.</p></ <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-id-ctrl.1 b/Documentation/nvme-id-ctrl.1 index f5656b9..206a728 100644 --- a/Documentation/nvme-id-ctrl.1 +++ b/Documentation/nvme-id-ctrl.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-ctrl .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-CTRL" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-CTRL" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-id-ctrl.html b/Documentation/nvme-id-ctrl.html index 1c1d3ad..0e7f00f 100644 --- a/Documentation/nvme-id-ctrl.html +++ b/Documentation/nvme-id-ctrl.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-ctrl(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -910,7 +910,7 @@ int main(int argc, char **argv) <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-id-domain.1 b/Documentation/nvme-id-domain.1 index 94fdf58..b98a6f3 100644 --- a/Documentation/nvme-id-domain.1 +++ b/Documentation/nvme-id-domain.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-domain .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-DOMAIN" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-DOMAIN" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-id-domain.html b/Documentation/nvme-id-domain.html index 067cef0..480c2df 100644 --- a/Documentation/nvme-id-domain.html +++ b/Documentation/nvme-id-domain.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-domain(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -812,7 +812,7 @@ device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></di <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-20 12:04:44 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-id-iocs.1 b/Documentation/nvme-id-iocs.1 index 27106b2..7563836 100644 --- a/Documentation/nvme-id-iocs.1 +++ b/Documentation/nvme-id-iocs.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-iocs .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-IOCS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-IOCS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-id-iocs.html b/Documentation/nvme-id-iocs.html index 07c0d9e..445c128 100644 --- a/Documentation/nvme-id-iocs.html +++ b/Documentation/nvme-id-iocs.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-iocs(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -844,7 +844,7 @@ show the fields in human readable format <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-id-ns-lba-format.1 b/Documentation/nvme-id-ns-lba-format.1 new file mode 100644 index 0000000..cb6c2a9 --- /dev/null +++ b/Documentation/nvme-id-ns-lba-format.1 @@ -0,0 +1,172 @@ +'\" t +.\" Title: nvme-id-ns-lba-format +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> +.\" Date: 01/07/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-ID\-NS\-LBA\-F" "1" "01/07/2022" "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-lba-format \- Send NVMe Identify Namespace for the specified LBA Format index, display structure +.SH "SYNOPSIS" +.sp +.nf +\fInvme id\-ns\fR <device> [\-\-uuid\-index=<uuid\-index> | \-U <uuid_index>] + [\-\-lba\-format\-index=<lba_format_index> | \-i <lba_format_index>] + [\-v | \-\-verbose] + [\-\-output\-format=<fmt> | \-o <fmt>] +.fi +.SH "DESCRIPTION" +.sp +For the NVMe device given, sends an identify namespace for the specified LBA Format index command and provides the result that is include capability field only and returned structure\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. +.sp +On success, the 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 +\-U <uuid\-index>, \-\-uuid\-index=<uuid\-index> +.RS 4 +UUID Index of the feature +.RE +.PP +\-i <lba_format_index>, \-\-lba\-format\-index=<lba_format_index> +.RS 4 +This field specifies the index into the LBA Format list identifying the LBA Format capabilities that are to be returned +.RE +.PP +\-v, \-\-verbose +.RS 4 +Increase the information detail in the output\&. +.RE +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, +\fIjson\fR, or +\fIbinary\fR\&. Only one output format can be used at a time\&. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +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\-lba\-format /dev/nvme0n1 \-i 0 +.fi +.if n \{\ +.RE +.\} +.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\-lba\-format /dev/nvme0n1 \-i 0 \-o binary > id_ns\&.raw +# nvme id\-ns\-lba\-format /dev/nvme0n1 \-i 0 \-\-output\-format=binary > 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\-lba\-format /dev/nvme0n1 \-i 0 \-\-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_lba_format\&.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\en", ns\->nlbaf); + printf("ncap : %#llx\en", ns\->mc); + return 0; +} +.fi +.if n \{\ +.RE +.\} +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-id-ns-lba-format.html b/Documentation/nvme-id-ns-lba-format.html new file mode 100644 index 0000000..1a4b83f --- /dev/null +++ b/Documentation/nvme-id-ns-lba-format.html @@ -0,0 +1,901 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.6.8" />
+<title>nvme-id-ns-lba-format(1)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overridden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+nvme-id-ns-lba-format(1) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>nvme-id-ns-lba-format -
+ Send NVMe Identify Namespace for the specified LBA Format index, display structure
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="verseblock">
+<pre class="content"><em>nvme id-ns</em> <device> [--uuid-index=<uuid-index> | -U <uuid_index>]
+ [--lba-format-index=<lba_format_index> | -i <lba_format_index>]
+ [-v | --verbose]
+ [--output-format=<fmt> | -o <fmt>]</pre>
+<div class="attribution">
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_description">DESCRIPTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>For the NVMe device given, sends an identify namespace for
+the specified LBA Format index command and provides the result
+that is include capability field only and returned structure.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>
+<div class="paragraph"><p>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.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_options">OPTIONS</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-U <uuid-index>
+</dt>
+<dt class="hdlist1">
+--uuid-index=<uuid-index>
+</dt>
+<dd>
+<p>
+ UUID Index of the feature
+</p>
+</dd>
+<dt class="hdlist1">
+-i <lba_format_index>
+</dt>
+<dt class="hdlist1">
+--lba-format-index=<lba_format_index>
+</dt>
+<dd>
+<p>
+ This field specifies the index into the LBA Format list identifying
+ the LBA Format capabilities that are to be returned
+</p>
+</dd>
+<dt class="hdlist1">
+-v
+</dt>
+<dt class="hdlist1">
+--verbose
+</dt>
+<dd>
+<p>
+ Increase the information detail in the output.
+</p>
+</dd>
+<dt class="hdlist1">
+-o <format>
+</dt>
+<dt class="hdlist1">
+--output-format=<format>
+</dt>
+<dd>
+<p>
+ Set the reporting format to <em>normal</em>, <em>json</em>, or
+ <em>binary</em>. Only one output format can be used at a time.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">EXAMPLES</h2>
+<div class="sectionbody">
+<div class="ulist"><ul>
+<li>
+<p>
+Has the program interpret the returned buffer and display the known
+fields in a human readable format:
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme id-ns-lba-format /dev/nvme0n1 -i 0</code></pre>
+</div></div>
+</li>
+<li>
+<p>
+Have the program return the raw structure in binary:
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme id-ns-lba-format /dev/nvme0n1 -i 0 -o binary > id_ns.raw
+# nvme id-ns-lba-format /dev/nvme0n1 -i 0 --output-format=binary > id_ns.raw</code></pre>
+</div></div>
+<div class="paragraph"><p>It is probably a bad idea to not redirect stdout when using this mode.</p></div>
+</li>
+<li>
+<p>
+Alternatively you may want to send the data to another program that
+can parse the raw buffer.
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme id-ns-lba-format /dev/nvme0n1 -i 0 --raw-binary | nvme_parse_id_ns</code></pre>
+</div></div>
+<div class="paragraph"><p>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, <code>'|'</code>,
+as shown in the above example, or you can <code>'cat'</code> a saved output buffer
+to it.</p></div>
+</li>
+</ul></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>/* File: nvme_parse_id_ns_lba_format.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->nlbaf);
+ printf("ncap : %#llx\n", ns->mc);
+ return 0;
+}</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_nvme">NVME</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2022-01-07 13:48:12 KST
+</div>
+</div>
+</body>
+</html>
diff --git a/Documentation/nvme-id-ns-lba-format.txt b/Documentation/nvme-id-ns-lba-format.txt new file mode 100644 index 0000000..32df2f6 --- /dev/null +++ b/Documentation/nvme-id-ns-lba-format.txt @@ -0,0 +1,102 @@ +nvme-id-ns-lba-format(1) +======================== + +NAME +---- +nvme-id-ns-lba-format - Send NVMe Identify Namespace for the specified LBA Format index, display structure + +SYNOPSIS +-------- +[verse] +'nvme id-ns' <device> [--uuid-index=<uuid-index> | -U <uuid_index>] + [--lba-format-index=<lba_format_index> | -i <lba_format_index>] + [-v | --verbose] + [--output-format=<fmt> | -o <fmt>] + +DESCRIPTION +----------- +For the NVMe device given, sends an identify namespace for +the specified LBA Format index command and provides the result +that is include capability field only 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 +------- +-U <uuid-index>:: +--uuid-index=<uuid-index>:: + UUID Index of the feature + +-i <lba_format_index>:: +--lba-format-index=<lba_format_index>:: + This field specifies the index into the LBA Format list identifying + the LBA Format capabilities that are to be returned + +-v:: +--verbose:: + Increase the information detail in the output. + +-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-lba-format /dev/nvme0n1 -i 0 +------------ ++ +* Have the program return the raw structure in binary: ++ +------------ +# nvme id-ns-lba-format /dev/nvme0n1 -i 0 -o binary > id_ns.raw +# nvme id-ns-lba-format /dev/nvme0n1 -i 0 --output-format=binary > 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-lba-format /dev/nvme0n1 -i 0 --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_lba_format.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->nlbaf); + printf("ncap : %#llx\n", ns->mc); + return 0; +} +------------ + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-id-ns.1 b/Documentation/nvme-id-ns.1 index 3104be3..97e8962 100644 --- a/Documentation/nvme-id-ns.1 +++ b/Documentation/nvme-id-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -33,7 +33,7 @@ nvme-id-ns \- Send NVMe Identify Namespace, return result and structure .sp .nf \fInvme id\-ns\fR <device> [\-v | \-\-vendor\-specific] [\-b | \-\-raw\-binary] - [\-\-namespace\-id=<nsid> | \-n <nsid>] [\-f | \-\-force] + [\-\-namespace\-id=<nsid> | \-n <nsid>] [\-\-force] [\-\-human\-readable | \-H] [\-\-output\-format=<fmt> | \-o <fmt>] .fi @@ -51,7 +51,7 @@ On success, the structure may be returned in one of several ways depending on th 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 +\-\-force .RS 4 Request controller return the identify 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 diff --git a/Documentation/nvme-id-ns.html b/Documentation/nvme-id-ns.html index 8213e5e..55ce45a 100644 --- a/Documentation/nvme-id-ns.html +++ b/Documentation/nvme-id-ns.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -750,7 +750,7 @@ nvme-id-ns(1) Manual Page <div class="sectionbody">
<div class="verseblock">
<pre class="content"><em>nvme id-ns</em> <device> [-v | --vendor-specific] [-b | --raw-binary]
- [--namespace-id=<nsid> | -n <nsid>] [-f | --force]
+ [--namespace-id=<nsid> | -n <nsid>] [--force]
[--human-readable | -H]
[--output-format=<fmt> | -o <fmt>]</pre>
<div class="attribution">
@@ -791,9 +791,6 @@ raw buffer may be printed to stdout.</p></div> </p>
</dd>
<dt class="hdlist1">
--f
-</dt>
-<dt class="hdlist1">
--force
</dt>
<dd>
@@ -955,7 +952,7 @@ int main(int argc, char **argv) <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-id-ns.txt b/Documentation/nvme-id-ns.txt index 4b3c258..d12b157 100644 --- a/Documentation/nvme-id-ns.txt +++ b/Documentation/nvme-id-ns.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'nvme id-ns' <device> [-v | --vendor-specific] [-b | --raw-binary] - [--namespace-id=<nsid> | -n <nsid>] [-f | --force] + [--namespace-id=<nsid> | -n <nsid>] [--force] [--human-readable | -H] [--output-format=<fmt> | -o <fmt>] @@ -37,7 +37,6 @@ OPTIONS is required for the character devices, or overrides the block nsid if given. --f:: --force:: Request controller return the identify namespace structure even if the namespace is not attached to the controller. This is valid diff --git a/Documentation/nvme-id-nvmset.1 b/Documentation/nvme-id-nvmset.1 index 1a26386..e2504c2 100644 --- a/Documentation/nvme-id-nvmset.1 +++ b/Documentation/nvme-id-nvmset.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-nvmset .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-NVMSET" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-NVMSET" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-id-nvmset.html b/Documentation/nvme-id-nvmset.html index c93e344..c6596e3 100644 --- a/Documentation/nvme-id-nvmset.html +++ b/Documentation/nvme-id-nvmset.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-nvmset(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -851,7 +851,7 @@ as shown in the above example, or you can <code>'cat'</code> a saved output buff <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-intel-id-ctrl.1 b/Documentation/nvme-intel-id-ctrl.1 index e2b228c..c64210a 100644 --- a/Documentation/nvme-intel-id-ctrl.1 +++ b/Documentation/nvme-intel-id-ctrl.1 @@ -2,12 +2,12 @@ .\" Title: nvme-intel-id-ctrl .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-INTEL\-ID\-CTR" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-INTEL\-ID\-CTR" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-intel-id-ctrl.html b/Documentation/nvme-intel-id-ctrl.html index 2accabd..e9e3ac4 100644 --- a/Documentation/nvme-intel-id-ctrl.html +++ b/Documentation/nvme-intel-id-ctrl.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-intel-id-ctrl(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -853,7 +853,7 @@ fields in a human readable format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-intel-internal-log.1 b/Documentation/nvme-intel-internal-log.1 index 91d2670..c77c013 100644 --- a/Documentation/nvme-intel-internal-log.1 +++ b/Documentation/nvme-intel-internal-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-intel-internal-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-INTEL\-INTERNA" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-INTEL\-INTERNA" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-intel-internal-log.html b/Documentation/nvme-intel-internal-log.html index 06db8b8..c66cbfb 100644 --- a/Documentation/nvme-intel-internal-log.html +++ b/Documentation/nvme-intel-internal-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-intel-internal-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -873,7 +873,7 @@ Gets the event log from the device and saves to defined file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-intel-lat-stats.1 b/Documentation/nvme-intel-lat-stats.1 index d2bece4..f7c8276 100644 --- a/Documentation/nvme-intel-lat-stats.1 +++ b/Documentation/nvme-intel-lat-stats.1 @@ -2,12 +2,12 @@ .\" Title: nvme-intel-lat-stats .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-INTEL\-LAT\-ST" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-INTEL\-LAT\-ST" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-intel-lat-stats.html b/Documentation/nvme-intel-lat-stats.html index 52501c6..6f1c8c8 100644 --- a/Documentation/nvme-intel-lat-stats.html +++ b/Documentation/nvme-intel-lat-stats.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-intel-lat-stats(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -832,7 +832,7 @@ Get the write statistics <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-intel-market-name.1 b/Documentation/nvme-intel-market-name.1 index 0e9eec2..841a0e0 100644 --- a/Documentation/nvme-intel-market-name.1 +++ b/Documentation/nvme-intel-market-name.1 @@ -2,12 +2,12 @@ .\" Title: nvme-intel-market-name .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-INTEL\-MARKET\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-INTEL\-MARKET\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-intel-market-name.html b/Documentation/nvme-intel-market-name.html index 77f8d66..2feee12 100644 --- a/Documentation/nvme-intel-market-name.html +++ b/Documentation/nvme-intel-market-name.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-intel-market-name(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -813,7 +813,7 @@ Get the marketing name <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-intel-smart-log-add.1 b/Documentation/nvme-intel-smart-log-add.1 index b487922..9b631a6 100644 --- a/Documentation/nvme-intel-smart-log-add.1 +++ b/Documentation/nvme-intel-smart-log-add.1 @@ -2,12 +2,12 @@ .\" Title: nvme-intel-smart-log-add .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-INTEL\-SMART\-" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-INTEL\-SMART\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-intel-smart-log-add.html b/Documentation/nvme-intel-smart-log-add.html index 7f368fa..6177e03 100644 --- a/Documentation/nvme-intel-smart-log-add.html +++ b/Documentation/nvme-intel-smart-log-add.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-intel-smart-log-add(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -850,7 +850,7 @@ Print the raw Intel Additional SMART log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-intel-temp-stats.1 b/Documentation/nvme-intel-temp-stats.1 index c45d164..61a0c43 100644 --- a/Documentation/nvme-intel-temp-stats.1 +++ b/Documentation/nvme-intel-temp-stats.1 @@ -2,12 +2,12 @@ .\" Title: nvme-intel-temp-stats .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-INTEL\-TEMP\-S" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-INTEL\-TEMP\-S" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-intel-temp-stats.html b/Documentation/nvme-intel-temp-stats.html index 1aa2f98..a9eff36 100644 --- a/Documentation/nvme-intel-temp-stats.html +++ b/Documentation/nvme-intel-temp-stats.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-intel-temp-stats(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -822,7 +822,7 @@ Print the raw SMART log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-io-passthru.1 b/Documentation/nvme-io-passthru.1 index 8fc87c8..98a4858 100644 --- a/Documentation/nvme-io-passthru.1 +++ b/Documentation/nvme-io-passthru.1 @@ -2,12 +2,12 @@ .\" Title: nvme-io-passthru .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-IO\-PASSTHRU" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-IO\-PASSTHRU" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -42,6 +42,7 @@ nvme-io-passthru \- Submit an arbitrary io command, return results [\-\-metadata\-len=<len> | \-m <len>] [\-\-read | \-r ] [\-\-write | \-w] [\-\-input\-file=<file> | \-i <file>] + [\-\-metadata=<file> | \-M <file>] [\-\-timeout=<to> | \-t <to>] [\-\-show\-command | \-s] [\-\-dry\-run | \-d] @@ -91,7 +92,12 @@ Used for the data\-direction for the command and required for commands sending/r .PP \-i <file>, \-\-input\-file=<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\&. +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\&. If the command is a data\-in (read) command, the data returned from the device will be saved here\&. +.RE +.PP +\-M <file>, \-\-metadata=<file> +.RS 4 +If the command is a data\-out (write) command, use this file to fill the metadata buffer sent to the device\&. If no file is given, assumed to use STDIN\&. If the command is a data\-in (read) command, the metadata returned from the device will be saved here\&. .RE .PP \-l <data\-len>, \-\-data\-len=<data\-len> diff --git a/Documentation/nvme-io-passthru.html b/Documentation/nvme-io-passthru.html index a802604..c88ff8b 100644 --- a/Documentation/nvme-io-passthru.html +++ b/Documentation/nvme-io-passthru.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-io-passthru(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -759,6 +759,7 @@ nvme-io-passthru(1) Manual Page [--metadata-len=<len> | -m <len>]
[--read | -r ] [--write | -w]
[--input-file=<file> | -i <file>]
+ [--metadata=<file> | -M <file>]
[--timeout=<to> | -t <to>]
[--show-command | -s]
[--dry-run | -d]
@@ -869,8 +870,23 @@ printed to stdout for another program to parse.</p></div> <dd>
<p>
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.
+ to fill the buffer sent to the device. If no file is given, assumed to
+ use STDIN. If the command is a data-in (read) command, the data
+ returned from the device will be saved here.
+</p>
+</dd>
+<dt class="hdlist1">
+-M <file>
+</dt>
+<dt class="hdlist1">
+--metadata=<file>
+</dt>
+<dd>
+<p>
+ If the command is a data-out (write) command, use this file
+ to fill the metadata buffer sent to the device. If no file is given,
+ assumed to use STDIN. If the command is a data-in (read) command, the
+ metadata returned from the device will be saved here.
</p>
</dd>
<dt class="hdlist1">
@@ -977,7 +993,7 @@ printed to stdout for another program to parse.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-io-passthru.txt b/Documentation/nvme-io-passthru.txt index 5a16698..ba0904c 100644 --- a/Documentation/nvme-io-passthru.txt +++ b/Documentation/nvme-io-passthru.txt @@ -18,6 +18,7 @@ SYNOPSIS [--metadata-len=<len> | -m <len>] [--read | -r ] [--write | -w] [--input-file=<file> | -i <file>] + [--metadata=<file> | -M <file>] [--timeout=<to> | -t <to>] [--show-command | -s] [--dry-run | -d] @@ -73,8 +74,16 @@ OPTIONS -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. + to fill the buffer sent to the device. If no file is given, assumed to + use STDIN. If the command is a data-in (read) command, the data + returned from the device will be saved here. + +-M <file>:: +--metadata=<file>:: + If the command is a data-out (write) command, use this file + to fill the metadata buffer sent to the device. If no file is given, + assumed to use STDIN. If the command is a data-in (read) command, the + metadata returned from the device will be saved here. -l <data-len>:: --data-len=<data-len>:: diff --git a/Documentation/nvme-lba-status-log.1 b/Documentation/nvme-lba-status-log.1 index 5bd142f..c5f0266 100644 --- a/Documentation/nvme-lba-status-log.1 +++ b/Documentation/nvme-lba-status-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-lba-status-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LBA\-STATUS\-L" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-LBA\-STATUS\-L" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-lba-status-log.html b/Documentation/nvme-lba-status-log.html index 5cfbfdf..158fa4b 100644 --- a/Documentation/nvme-lba-status-log.html +++ b/Documentation/nvme-lba-status-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-lba-status-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -831,7 +831,7 @@ NVME</code></pre> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-list-ctrl.1 b/Documentation/nvme-list-ctrl.1 index 56cdf01..f7672d4 100644 --- a/Documentation/nvme-list-ctrl.1 +++ b/Documentation/nvme-list-ctrl.1 @@ -2,12 +2,12 @@ .\" Title: nvme-list-ctrl .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LIST\-CTRL" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-LIST\-CTRL" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-list-ctrl.html b/Documentation/nvme-list-ctrl.html index e8898cb..307120e 100644 --- a/Documentation/nvme-list-ctrl.html +++ b/Documentation/nvme-list-ctrl.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-list-ctrl(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -828,7 +828,7 @@ OPTIONS</code></pre> <div id="footer">
<div id="footer-text">
Last updated
- 2021-09-08 14:24:09 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-list-endgrp.1 b/Documentation/nvme-list-endgrp.1 index 59e27a8..b98b1ac 100644 --- a/Documentation/nvme-list-endgrp.1 +++ b/Documentation/nvme-list-endgrp.1 @@ -2,12 +2,12 @@ .\" Title: nvme-list-endgrp .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LIST\-ENDGRP" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-LIST\-ENDGRP" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-list-endgrp.html b/Documentation/nvme-list-endgrp.html index 33ba4d1..1eeb6b4 100644 --- a/Documentation/nvme-list-endgrp.html +++ b/Documentation/nvme-list-endgrp.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-list-endgrp(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -815,7 +815,7 @@ than or equal to the value specified in the CDW11.ENDGID field.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-09-08 14:12:47 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-list-ns.1 b/Documentation/nvme-list-ns.1 index 848bc70..b966c1d 100644 --- a/Documentation/nvme-list-ns.1 +++ b/Documentation/nvme-list-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-list-ns.html b/Documentation/nvme-list-ns.html index a14d67a..1815d85 100644 --- a/Documentation/nvme-list-ns.html +++ b/Documentation/nvme-list-ns.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -859,7 +859,7 @@ Print the namespaces present for NVM Command Set in normal format <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-list-subsys.1 b/Documentation/nvme-list-subsys.1 index f930bcb..b65e9ba 100644 --- a/Documentation/nvme-list-subsys.1 +++ b/Documentation/nvme-list-subsys.1 @@ -2,12 +2,12 @@ .\" Title: nvme-list-subsys .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LIST\-SUBSYS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-LIST\-SUBSYS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-list-subsys.html b/Documentation/nvme-list-subsys.html index f7a6f89..d653eeb 100644 --- a/Documentation/nvme-list-subsys.html +++ b/Documentation/nvme-list-subsys.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-list-subsys(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -854,7 +854,7 @@ nvme-subsys1 - NQN=nvmf-test2 <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-list.1 b/Documentation/nvme-list.1 index ca0672e..75960b7 100644 --- a/Documentation/nvme-list.1 +++ b/Documentation/nvme-list.1 @@ -2,12 +2,12 @@ .\" Title: nvme-list .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LIST" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-LIST" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-list.html b/Documentation/nvme-list.html index 0e68360..d476ae2 100644 --- a/Documentation/nvme-list.html +++ b/Documentation/nvme-list.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-list(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -816,7 +816,7 @@ for those devices as well as some pertinent information about them.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-lnvm-create.1 b/Documentation/nvme-lnvm-create.1 deleted file mode 100644 index 4c2e8d8..0000000 --- a/Documentation/nvme-lnvm-create.1 +++ /dev/null @@ -1,100 +0,0 @@ -'\" t -.\" Title: nvme-lnvm-create -.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 -.\" Manual: NVMe Manual -.\" Source: NVMe -.\" Language: English -.\" -.TH "NVME\-LNVM\-CREATE" "1" "11/11/2021" "NVMe" "NVMe Manual" -.\" ----------------------------------------------------------------- -.\" * Define some portability stuff -.\" ----------------------------------------------------------------- -.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.\" http://bugs.debian.org/507673 -.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html -.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" ----------------------------------------------------------------- -.\" * set default formatting -.\" ----------------------------------------------------------------- -.\" disable hyphenation -.nh -.\" disable justification (adjust text to left margin only) -.ad l -.\" ----------------------------------------------------------------- -.\" * MAIN CONTENT STARTS HERE * -.\" ----------------------------------------------------------------- -.SH "NAME" -nvme-lnvm-create \- Instantiate a target on top of a LightNVM enabled device -.SH "SYNOPSIS" -.sp -.nf -\fInvme lnvm\-create\fR [\-\-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>] -.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/<targetname> -.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=<DEVICE>, \-d <DEVICE> -.RS 4 -Device name to initialize\&. -.RE -.PP -\-\-target\-name=<TARGET>, \-n <TARGET> -.RS 4 -Target name of the device to initialize\&. For example: target0\&. -.RE -.PP -\-\-target\-type=<TARGETTYPE>, \-t <TARGETTYPE> -.RS 4 -Target type of the device to use\&. For example: pblk -.RE -.PP -\-\-lun\-begin <NUM>, \-b <NUM> -.RS 4 -Begin LUN id offset to use for target -.RE -.PP -\-\-lun\-end <NUM>, \-e <NUM> -.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 diff --git a/Documentation/nvme-lnvm-create.txt b/Documentation/nvme-lnvm-create.txt deleted file mode 100644 index 3c9109d..0000000 --- a/Documentation/nvme-lnvm-create.txt +++ /dev/null @@ -1,60 +0,0 @@ -nvme-lnvm-create(1) -=================== - -NAME ----- -nvme-lnvm-create - Instantiate a target on top of a LightNVM enabled device - -SYNOPSIS --------- -[verse] -'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 diff --git a/Documentation/nvme-lnvm-diag-bbtbl.1 b/Documentation/nvme-lnvm-diag-bbtbl.1 deleted file mode 100644 index 4afe42f..0000000 --- a/Documentation/nvme-lnvm-diag-bbtbl.1 +++ /dev/null @@ -1,117 +0,0 @@ -'\" t -.\" Title: nvme-lnvm-diag-bbtbl -.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 -.\" Manual: NVMe Manual -.\" Source: NVMe -.\" Language: English -.\" -.TH "NVME\-LNVM\-DIAG\-BB" "1" "11/11/2021" "NVMe" "NVMe Manual" -.\" ----------------------------------------------------------------- -.\" * Define some portability stuff -.\" ----------------------------------------------------------------- -.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.\" http://bugs.debian.org/507673 -.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html -.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" ----------------------------------------------------------------- -.\" * set default formatting -.\" ----------------------------------------------------------------- -.\" disable hyphenation -.nh -.\" disable justification (adjust text to left margin only) -.ad l -.\" ----------------------------------------------------------------- -.\" * MAIN CONTENT STARTS HERE * -.\" ----------------------------------------------------------------- -.SH "NAME" -nvme-lnvm-diag-bbtbl \- Diagnose the bad block table -.SH "SYNOPSIS" -.sp -.nf -\fInvme lnvm\-diag\-bbtbl\fR [\-\-namespace\-id=<NUM> | \-n <NUM>] - [\-\-channel\-id=<CHID> | \-c <CHID>] - [\-\-lun\-id=<LUNID> | \-l <LUNID>] - [\-\-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=<NUM>, \-n <NUM> -.RS 4 -Namespace id to use -.RE -.PP -\-\-channel\-id=<NUM>, \-c -.RS 4 -Channel id -.RE -.PP -\-\-lun\-id=<NUM>, \-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 diff --git a/Documentation/nvme-lnvm-diag-bbtbl.txt b/Documentation/nvme-lnvm-diag-bbtbl.txt deleted file mode 100644 index 7324807..0000000 --- a/Documentation/nvme-lnvm-diag-bbtbl.txt +++ /dev/null @@ -1,65 +0,0 @@ -nvme-lnvm-diag-bbtbl(1) -======================= - -NAME ----- -nvme-lnvm-diag-bbtbl - Diagnose the bad block table - -SYNOPSIS --------- -[verse] -'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 diff --git a/Documentation/nvme-lnvm-diag-set-bbtbl.txt b/Documentation/nvme-lnvm-diag-set-bbtbl.txt deleted file mode 100644 index f5dd004..0000000 --- a/Documentation/nvme-lnvm-diag-set-bbtbl.txt +++ /dev/null @@ -1,63 +0,0 @@ -nvme-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=<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 diff --git a/Documentation/nvme-lnvm-factory.txt b/Documentation/nvme-lnvm-factory.txt deleted file mode 100644 index baa7a69..0000000 --- a/Documentation/nvme-lnvm-factory.txt +++ /dev/null @@ -1,54 +0,0 @@ -nvme-lnvm-factory(1) -==================== - -NAME ----- -nvme-lnvm-factory - Factory reset a LightNVM device - -SYNOPSIS --------- -[verse] -'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 diff --git a/Documentation/nvme-lnvm-id-ns.txt b/Documentation/nvme-lnvm-id-ns.txt deleted file mode 100644 index 1a3565f..0000000 --- a/Documentation/nvme-lnvm-id-ns.txt +++ /dev/null @@ -1,49 +0,0 @@ -nvme-lnvm-id-ns(1) -================== - -NAME ----- -nvme-lnvm-id-ns - Identify Geometry for LightNVM NVMe device - -SYNOPSIS --------- -[verse] -'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 diff --git a/Documentation/nvme-lnvm-info.txt b/Documentation/nvme-lnvm-info.txt deleted file mode 100644 index e755c9c..0000000 --- a/Documentation/nvme-lnvm-info.txt +++ /dev/null @@ -1,27 +0,0 @@ -nvme-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 diff --git a/Documentation/nvme-lnvm-init.txt b/Documentation/nvme-lnvm-init.txt deleted file mode 100644 index 0d922a9..0000000 --- a/Documentation/nvme-lnvm-init.txt +++ /dev/null @@ -1,44 +0,0 @@ -nvme-lnvm-init(1) -================= - -NAME ----- -nvme-lnvm-init - Initialize LightNVM device with media manager - -SYNOPSIS --------- -[verse] -'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 diff --git a/Documentation/nvme-lnvm-list.1 b/Documentation/nvme-lnvm-list.1 deleted file mode 100644 index 33eaa44..0000000 --- a/Documentation/nvme-lnvm-list.1 +++ /dev/null @@ -1,48 +0,0 @@ -'\" t -.\" Title: nvme-lnvm-list -.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 -.\" Manual: NVMe Manual -.\" Source: NVMe -.\" Language: English -.\" -.TH "NVME\-LNVM\-LIST" "1" "11/11/2021" "NVMe" "NVMe Manual" -.\" ----------------------------------------------------------------- -.\" * Define some portability stuff -.\" ----------------------------------------------------------------- -.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.\" http://bugs.debian.org/507673 -.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html -.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" ----------------------------------------------------------------- -.\" * set default formatting -.\" ----------------------------------------------------------------- -.\" disable hyphenation -.nh -.\" disable justification (adjust text to left margin only) -.ad l -.\" ----------------------------------------------------------------- -.\" * MAIN CONTENT STARTS HERE * -.\" ----------------------------------------------------------------- -.SH "NAME" -nvme-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 diff --git a/Documentation/nvme-lnvm-list.txt b/Documentation/nvme-lnvm-list.txt deleted file mode 100644 index 959f6b9..0000000 --- a/Documentation/nvme-lnvm-list.txt +++ /dev/null @@ -1,27 +0,0 @@ -nvme-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 diff --git a/Documentation/nvme-lnvm-remove.txt b/Documentation/nvme-lnvm-remove.txt deleted file mode 100644 index f5cdd6e..0000000 --- a/Documentation/nvme-lnvm-remove.txt +++ /dev/null @@ -1,32 +0,0 @@ -nvme-lnvm-remove(1) -=================== - -NAME ----- -nvme-lnvm-remove - Remove an initialized LightNVM target. - -SYNOPSIS --------- -[verse] -'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 diff --git a/Documentation/nvme-lockdown.1 b/Documentation/nvme-lockdown.1 index dcf7c22..79754d0 100644 --- a/Documentation/nvme-lockdown.1 +++ b/Documentation/nvme-lockdown.1 @@ -2,12 +2,12 @@ .\" Title: nvme-lockdown .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LOCKDOWN" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-LOCKDOWN" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-lockdown.html b/Documentation/nvme-lockdown.html index cb2e86c..7fd48c1 100644 --- a/Documentation/nvme-lockdown.html +++ b/Documentation/nvme-lockdown.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-lockdown(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -850,7 +850,7 @@ Identifier.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-09-09 14:46:45 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-media-unit-stat-log.1 b/Documentation/nvme-media-unit-stat-log.1 new file mode 100644 index 0000000..21d49d8 --- /dev/null +++ b/Documentation/nvme-media-unit-stat-log.1 @@ -0,0 +1,67 @@ +'\" t +.\" Title: nvme-media-unit-stat-log +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 11/11/2021 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-MEDIA\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +nvme-media-unit-stat-log \- Send NVMe Media unit status log pages request, returns result and log +.SH "SYNOPSIS" +.sp +.nf +\fInvme media\-log\-pages\fR <device> [\-d | \-\-dom\-id] + [\-\-output\-format=<fmt> | \-o <fmt>] + [\-\-raw\-binary | \-b] +.fi +.SH "DESCRIPTION" +.sp +Retrieves the NVMe Media unit status log pages details from an NVMe device and provides the returned structure\&. +.sp +The <device> parameter is mandatory and should be the NVMe character device (ex: /dev/nvme0)\&. +.sp +On success, the returned Media unit status log pages log structure will be printed \&. +.SH "OPTIONS" +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +This option will set the reporting format to normal, json, or binary\&. Only one output format can be used at a time\&. +.RE +.PP +\-d, \-\-dom\-id +.RS 4 +This option is to get the domain ID\&. +.RE +.PP +\-b, \-\-raw\-binary +.RS 4 +This option is to get raw binary data\&. +.RE +.SH "EXAMPLES" +.sp +No examples provided yet\&. +.SH "NVME" +.sp +Part of the nvme\-user suite
\ No newline at end of file diff --git a/Documentation/nvme-lnvm-remove.html b/Documentation/nvme-media-unit-stat-log.html index ac8530e..5042ba9 100644 --- a/Documentation/nvme-lnvm-remove.html +++ b/Documentation/nvme-media-unit-stat-log.html @@ -1,804 +1,831 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
- "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-remove(1)</title>
-<style type="text/css">
-/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
-
-/* Default font. */
-body {
- font-family: Georgia,serif;
-}
-
-/* Title font. */
-h1, h2, h3, h4, h5, h6,
-div.title, caption.title,
-thead, p.table.header,
-#toctitle,
-#author, #revnumber, #revdate, #revremark,
-#footer {
- font-family: Arial,Helvetica,sans-serif;
-}
-
-body {
- margin: 1em 5% 1em 5%;
-}
-
-a {
- color: blue;
- text-decoration: underline;
-}
-a:visited {
- color: fuchsia;
-}
-
-em {
- font-style: italic;
- color: navy;
-}
-
-strong {
- font-weight: bold;
- color: #083194;
-}
-
-h1, h2, h3, h4, h5, h6 {
- color: #527bbd;
- margin-top: 1.2em;
- margin-bottom: 0.5em;
- line-height: 1.3;
-}
-
-h1, h2, h3 {
- border-bottom: 2px solid silver;
-}
-h2 {
- padding-top: 0.5em;
-}
-h3 {
- float: left;
-}
-h3 + * {
- clear: left;
-}
-h5 {
- font-size: 1.0em;
-}
-
-div.sectionbody {
- margin-left: 0;
-}
-
-hr {
- border: 1px solid silver;
-}
-
-p {
- margin-top: 0.5em;
- margin-bottom: 0.5em;
-}
-
-ul, ol, li > p {
- margin-top: 0;
-}
-ul > li { color: #aaa; }
-ul > li > * { color: black; }
-
-.monospaced, code, pre {
- font-family: "Courier New", Courier, monospace;
- font-size: inherit;
- color: navy;
- padding: 0;
- margin: 0;
-}
-pre {
- white-space: pre-wrap;
-}
-
-#author {
- color: #527bbd;
- font-weight: bold;
- font-size: 1.1em;
-}
-#email {
-}
-#revnumber, #revdate, #revremark {
-}
-
-#footer {
- font-size: small;
- border-top: 2px solid silver;
- padding-top: 0.5em;
- margin-top: 4.0em;
-}
-#footer-text {
- float: left;
- padding-bottom: 0.5em;
-}
-#footer-badges {
- float: right;
- padding-bottom: 0.5em;
-}
-
-#preamble {
- margin-top: 1.5em;
- margin-bottom: 1.5em;
-}
-div.imageblock, div.exampleblock, div.verseblock,
-div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
-div.admonitionblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-div.admonitionblock {
- margin-top: 2.0em;
- margin-bottom: 2.0em;
- margin-right: 10%;
- color: #606060;
-}
-
-div.content { /* Block element content. */
- padding: 0;
-}
-
-/* Block element titles. */
-div.title, caption.title {
- color: #527bbd;
- font-weight: bold;
- text-align: left;
- margin-top: 1.0em;
- margin-bottom: 0.5em;
-}
-div.title + * {
- margin-top: 0;
-}
-
-td div.title:first-child {
- margin-top: 0.0em;
-}
-div.content div.title:first-child {
- margin-top: 0.0em;
-}
-div.content + div.title {
- margin-top: 0.0em;
-}
-
-div.sidebarblock > div.content {
- background: #ffffee;
- border: 1px solid #dddddd;
- border-left: 4px solid #f0f0f0;
- padding: 0.5em;
-}
-
-div.listingblock > div.content {
- border: 1px solid #dddddd;
- border-left: 5px solid #f0f0f0;
- background: #f8f8f8;
- padding: 0.5em;
-}
-
-div.quoteblock, div.verseblock {
- padding-left: 1.0em;
- margin-left: 1.0em;
- margin-right: 10%;
- border-left: 5px solid #f0f0f0;
- color: #888;
-}
-
-div.quoteblock > div.attribution {
- padding-top: 0.5em;
- text-align: right;
-}
-
-div.verseblock > pre.content {
- font-family: inherit;
- font-size: inherit;
-}
-div.verseblock > div.attribution {
- padding-top: 0.75em;
- text-align: left;
-}
-/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
-div.verseblock + div.attribution {
- text-align: left;
-}
-
-div.admonitionblock .icon {
- vertical-align: top;
- font-size: 1.1em;
- font-weight: bold;
- text-decoration: underline;
- color: #527bbd;
- padding-right: 0.5em;
-}
-div.admonitionblock td.content {
- padding-left: 0.5em;
- border-left: 3px solid #dddddd;
-}
-
-div.exampleblock > div.content {
- border-left: 3px solid #dddddd;
- padding-left: 0.5em;
-}
-
-div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; vertical-align: text-bottom; }
-a.image:visited { color: white; }
-
-dl {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-dt {
- margin-top: 0.5em;
- margin-bottom: 0;
- font-style: normal;
- color: navy;
-}
-dd > *:first-child {
- margin-top: 0.1em;
-}
-
-ul, ol {
- list-style-position: outside;
-}
-ol.arabic {
- list-style-type: decimal;
-}
-ol.loweralpha {
- list-style-type: lower-alpha;
-}
-ol.upperalpha {
- list-style-type: upper-alpha;
-}
-ol.lowerroman {
- list-style-type: lower-roman;
-}
-ol.upperroman {
- list-style-type: upper-roman;
-}
-
-div.compact ul, div.compact ol,
-div.compact p, div.compact p,
-div.compact div, div.compact div {
- margin-top: 0.1em;
- margin-bottom: 0.1em;
-}
-
-tfoot {
- font-weight: bold;
-}
-td > div.verse {
- white-space: pre;
-}
-
-div.hdlist {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-div.hdlist tr {
- padding-bottom: 15px;
-}
-dt.hdlist1.strong, td.hdlist1.strong {
- font-weight: bold;
-}
-td.hdlist1 {
- vertical-align: top;
- font-style: normal;
- padding-right: 0.8em;
- color: navy;
-}
-td.hdlist2 {
- vertical-align: top;
-}
-div.hdlist.compact tr {
- margin: 0;
- padding-bottom: 0;
-}
-
-.comment {
- background: yellow;
-}
-
-.footnote, .footnoteref {
- font-size: 0.8em;
-}
-
-span.footnote, span.footnoteref {
- vertical-align: super;
-}
-
-#footnotes {
- margin: 20px 0 20px 0;
- padding: 7px 0 0 0;
-}
-
-#footnotes div.footnote {
- margin: 0 0 5px 0;
-}
-
-#footnotes hr {
- border: none;
- border-top: 1px solid silver;
- height: 1px;
- text-align: left;
- margin-left: 0;
- width: 20%;
- min-width: 100px;
-}
-
-div.colist td {
- padding-right: 0.5em;
- padding-bottom: 0.3em;
- vertical-align: top;
-}
-div.colist td img {
- margin-top: 0.3em;
-}
-
-@media print {
- #footer-badges { display: none; }
-}
-
-#toc {
- margin-bottom: 2.5em;
-}
-
-#toctitle {
- color: #527bbd;
- font-size: 1.1em;
- font-weight: bold;
- margin-top: 1.0em;
- margin-bottom: 0.1em;
-}
-
-div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
- margin-top: 0;
- margin-bottom: 0;
-}
-div.toclevel2 {
- margin-left: 2em;
- font-size: 0.9em;
-}
-div.toclevel3 {
- margin-left: 4em;
- font-size: 0.9em;
-}
-div.toclevel4 {
- margin-left: 6em;
- font-size: 0.9em;
-}
-
-span.aqua { color: aqua; }
-span.black { color: black; }
-span.blue { color: blue; }
-span.fuchsia { color: fuchsia; }
-span.gray { color: gray; }
-span.green { color: green; }
-span.lime { color: lime; }
-span.maroon { color: maroon; }
-span.navy { color: navy; }
-span.olive { color: olive; }
-span.purple { color: purple; }
-span.red { color: red; }
-span.silver { color: silver; }
-span.teal { color: teal; }
-span.white { color: white; }
-span.yellow { color: yellow; }
-
-span.aqua-background { background: aqua; }
-span.black-background { background: black; }
-span.blue-background { background: blue; }
-span.fuchsia-background { background: fuchsia; }
-span.gray-background { background: gray; }
-span.green-background { background: green; }
-span.lime-background { background: lime; }
-span.maroon-background { background: maroon; }
-span.navy-background { background: navy; }
-span.olive-background { background: olive; }
-span.purple-background { background: purple; }
-span.red-background { background: red; }
-span.silver-background { background: silver; }
-span.teal-background { background: teal; }
-span.white-background { background: white; }
-span.yellow-background { background: yellow; }
-
-span.big { font-size: 2em; }
-span.small { font-size: 0.6em; }
-
-span.underline { text-decoration: underline; }
-span.overline { text-decoration: overline; }
-span.line-through { text-decoration: line-through; }
-
-div.unbreakable { page-break-inside: avoid; }
-
-
-/*
- * xhtml11 specific
- *
- * */
-
-div.tableblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-div.tableblock > table {
- border: 3px solid #527bbd;
-}
-thead, p.table.header {
- font-weight: bold;
- color: #527bbd;
-}
-p.table {
- margin-top: 0;
-}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
-div.tableblock > table[frame="void"] {
- border-style: none;
-}
-div.tableblock > table[frame="hsides"] {
- border-left-style: none;
- border-right-style: none;
-}
-div.tableblock > table[frame="vsides"] {
- border-top-style: none;
- border-bottom-style: none;
-}
-
-
-/*
- * html5 specific
- *
- * */
-
-table.tableblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-thead, p.tableblock.header {
- font-weight: bold;
- color: #527bbd;
-}
-p.tableblock {
- margin-top: 0;
-}
-table.tableblock {
- border-width: 3px;
- border-spacing: 0px;
- border-style: solid;
- border-color: #527bbd;
- border-collapse: collapse;
-}
-th.tableblock, td.tableblock {
- border-width: 1px;
- padding: 4px;
- border-style: solid;
- border-color: #527bbd;
-}
-
-table.tableblock.frame-topbot {
- border-left-style: hidden;
- border-right-style: hidden;
-}
-table.tableblock.frame-sides {
- border-top-style: hidden;
- border-bottom-style: hidden;
-}
-table.tableblock.frame-none {
- border-style: hidden;
-}
-
-th.tableblock.halign-left, td.tableblock.halign-left {
- text-align: left;
-}
-th.tableblock.halign-center, td.tableblock.halign-center {
- text-align: center;
-}
-th.tableblock.halign-right, td.tableblock.halign-right {
- text-align: right;
-}
-
-th.tableblock.valign-top, td.tableblock.valign-top {
- vertical-align: top;
-}
-th.tableblock.valign-middle, td.tableblock.valign-middle {
- vertical-align: middle;
-}
-th.tableblock.valign-bottom, td.tableblock.valign-bottom {
- vertical-align: bottom;
-}
-
-
-/*
- * manpage specific
- *
- * */
-
-body.manpage h1 {
- padding-top: 0.5em;
- padding-bottom: 0.5em;
- border-top: 2px solid silver;
- border-bottom: 2px solid silver;
-}
-body.manpage h2 {
- border-style: none;
-}
-body.manpage div.sectionbody {
- margin-left: 3em;
-}
-
-@media print {
- body.manpage div#toc { display: none; }
-}
-
-
-</style>
-<script type="text/javascript">
-/*<![CDATA[*/
-var asciidoc = { // Namespace.
-
-/////////////////////////////////////////////////////////////////////
-// Table Of Contents generator
-/////////////////////////////////////////////////////////////////////
-
-/* Author: Mihai Bazon, September 2002
- * http://students.infoiasi.ro/~mishoo
- *
- * Table Of Content generator
- * Version: 0.4
- *
- * Feel free to use this script under the terms of the GNU General Public
- * License, as long as you do not remove or alter this notice.
- */
-
- /* modified by Troy D. Hanson, September 2006. License: GPL */
- /* modified by Stuart Rackham, 2006, 2009. License: GPL */
-
-// toclevels = 1..4.
-toc: function (toclevels) {
-
- function getText(el) {
- var text = "";
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
- text += i.data;
- else if (i.firstChild != null)
- text += getText(i);
- }
- return text;
- }
-
- function TocEntry(el, text, toclevel) {
- this.element = el;
- this.text = text;
- this.toclevel = toclevel;
- }
-
- function tocEntries(el, toclevels) {
- var result = new Array;
- var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
- // Function that scans the DOM tree for header elements (the DOM2
- // nodeIterator API would be a better technique but not supported by all
- // browsers).
- var iterate = function (el) {
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
- var mo = re.exec(i.tagName);
- if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
- result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
- }
- iterate(i);
- }
- }
- }
- iterate(el);
- return result;
- }
-
- var toc = document.getElementById("toc");
- if (!toc) {
- return;
- }
-
- // Delete existing TOC entries in case we're reloading the TOC.
- var tocEntriesToRemove = [];
- var i;
- for (i = 0; i < toc.childNodes.length; i++) {
- var entry = toc.childNodes[i];
- if (entry.nodeName.toLowerCase() == 'div'
- && entry.getAttribute("class")
- && entry.getAttribute("class").match(/^toclevel/))
- tocEntriesToRemove.push(entry);
- }
- for (i = 0; i < tocEntriesToRemove.length; i++) {
- toc.removeChild(tocEntriesToRemove[i]);
- }
-
- // Rebuild TOC entries.
- var entries = tocEntries(document.getElementById("content"), toclevels);
- for (var i = 0; i < entries.length; ++i) {
- var entry = entries[i];
- if (entry.element.id == "")
- entry.element.id = "_toc_" + i;
- var a = document.createElement("a");
- a.href = "#" + entry.element.id;
- a.appendChild(document.createTextNode(entry.text));
- var div = document.createElement("div");
- div.appendChild(a);
- div.className = "toclevel" + entry.toclevel;
- toc.appendChild(div);
- }
- if (entries.length == 0)
- toc.parentNode.removeChild(toc);
-},
-
-
-/////////////////////////////////////////////////////////////////////
-// Footnotes generator
-/////////////////////////////////////////////////////////////////////
-
-/* Based on footnote generation code from:
- * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
- */
-
-footnotes: function () {
- // Delete existing footnote entries in case we're reloading the footnodes.
- var i;
- var noteholder = document.getElementById("footnotes");
- if (!noteholder) {
- return;
- }
- var entriesToRemove = [];
- for (i = 0; i < noteholder.childNodes.length; i++) {
- var entry = noteholder.childNodes[i];
- if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
- entriesToRemove.push(entry);
- }
- for (i = 0; i < entriesToRemove.length; i++) {
- noteholder.removeChild(entriesToRemove[i]);
- }
-
- // Rebuild footnote entries.
- var cont = document.getElementById("content");
- var spans = cont.getElementsByTagName("span");
- var refs = {};
- var n = 0;
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnote") {
- n++;
- var note = spans[i].getAttribute("data-note");
- if (!note) {
- // Use [\s\S] in place of . so multi-line matches work.
- // Because JavaScript has no s (dotall) regex flag.
- note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
- spans[i].innerHTML =
- "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- spans[i].setAttribute("data-note", note);
- }
- noteholder.innerHTML +=
- "<div class='footnote' id='_footnote_" + n + "'>" +
- "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
- n + "</a>. " + note + "</div>";
- var id =spans[i].getAttribute("id");
- if (id != null) refs["#"+id] = n;
- }
- }
- if (n == 0)
- noteholder.parentNode.removeChild(noteholder);
- else {
- // Process footnoterefs.
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnoteref") {
- var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
- href = href.match(/#.*/)[0]; // Because IE return full URL.
- n = refs[href];
- spans[i].innerHTML =
- "[<a href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- }
- }
- }
-},
-
-install: function(toclevels) {
- var timerId;
-
- function reinstall() {
- asciidoc.footnotes();
- if (toclevels) {
- asciidoc.toc(toclevels);
- }
- }
-
- function reinstallAndRemoveTimer() {
- clearInterval(timerId);
- reinstall();
- }
-
- timerId = setInterval(reinstall, 500);
- if (document.addEventListener)
- document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
- else
- window.onload = reinstallAndRemoveTimer;
-}
-
-}
-asciidoc.install();
-/*]]>*/
-</script>
-</head>
-<body class="manpage">
-<div id="header">
-<h1>
-nvme-lnvm-remove(1) Manual Page
-</h1>
-<h2>NAME</h2>
-<div class="sectionbody">
-<p>nvme-lnvm-remove -
- Remove an initialized LightNVM target.
-</p>
-</div>
-</div>
-<div id="content">
-<div class="sect1">
-<h2 id="_synopsis">SYNOPSIS</h2>
-<div class="sectionbody">
-<div class="verseblock">
-<pre class="content"><em>nvme lnvm-remove</em> [--target-name=<TARGET> | -n <TARGET>]</pre>
-<div class="attribution">
-</div></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_description">DESCRIPTION</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Remove an initialized target.</p></div>
-<div class="paragraph"><p>The target name is the name of which the media is exposed as in
-/dev/<TARGET></p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_options">OPTIONS</h2>
-<div class="sectionbody">
-<div class="dlist"><dl>
-<dt class="hdlist1">
---target-name=<TARGET>
-</dt>
-<dt class="hdlist1">
--n <TARGET>
-</dt>
-<dd>
-<p>
- Target name of the device to initialize. For example: target0.
-</p>
-</dd>
-</dl></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_examples">EXAMPLES</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>None yet</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_nvme">NVME</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Part of the nvme-user suite</p></div>
-</div>
-</div>
-</div>
-<div id="footnotes"><hr /></div>
-<div id="footer">
-<div id="footer-text">
-Last updated
- 2021-07-19 10:10:19 PDT
-</div>
-</div>
-</body>
-</html>
+<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> +<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> +<meta name="generator" content="AsciiDoc 8.6.10" /> +<title>nvme-media-unit-stat-log(1)</title> +<style type="text/css"> +/* Shared CSS for AsciiDoc xhtml11 and html5 backends */ + +/* Default font. */ +body { + font-family: Georgia,serif; +} + +/* Title font. */ +h1, h2, h3, h4, h5, h6, +div.title, caption.title, +thead, p.table.header, +#toctitle, +#author, #revnumber, #revdate, #revremark, +#footer { + font-family: Arial,Helvetica,sans-serif; +} + +body { + margin: 1em 5% 1em 5%; +} + +a { + color: blue; + text-decoration: underline; +} +a:visited { + color: fuchsia; +} + +em { + font-style: italic; + color: navy; +} + +strong { + font-weight: bold; + color: #083194; +} + +h1, h2, h3, h4, h5, h6 { + color: #527bbd; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; +} + +h1, h2, h3 { + border-bottom: 2px solid silver; +} +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} +h5 { + font-size: 1.0em; +} + +div.sectionbody { + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} +ul > li { color: #aaa; } +ul > li > * { color: black; } + +.monospaced, code, pre { + font-family: "Courier New", Courier, monospace; + font-size: inherit; + color: navy; + padding: 0; + margin: 0; +} +pre { + white-space: pre-wrap; +} + +#author { + color: #527bbd; + font-weight: bold; + font-size: 1.1em; +} +#email { +} +#revnumber, #revdate, #revremark { +} + +#footer { + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +#footer-text { + float: left; + padding-bottom: 0.5em; +} +#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + color: #606060; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #527bbd; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid #dddddd; + border-left: 4px solid #f0f0f0; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid #dddddd; + border-left: 5px solid #f0f0f0; + background: #f8f8f8; + padding: 0.5em; +} + +div.quoteblock, div.verseblock { + padding-left: 1.0em; + margin-left: 1.0em; + margin-right: 10%; + border-left: 5px solid #f0f0f0; + color: #888; +} + +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock > pre.content { + font-family: inherit; + font-size: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #527bbd; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 3px solid #dddddd; +} + +div.exampleblock > div.content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; vertical-align: text-bottom; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: navy; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +.footnote, .footnoteref { + font-size: 0.8em; +} + +span.footnote, span.footnoteref { + vertical-align: super; +} + +#footnotes { + margin: 20px 0 20px 0; + padding: 7px 0 0 0; +} + +#footnotes div.footnote { + margin: 0 0 5px 0; +} + +#footnotes hr { + border: none; + border-top: 1px solid silver; + height: 1px; + text-align: left; + margin-left: 0; + width: 20%; + min-width: 100px; +} + +div.colist td { + padding-right: 0.5em; + padding-bottom: 0.3em; + vertical-align: top; +} +div.colist td img { + margin-top: 0.3em; +} + +@media print { + #footer-badges { display: none; } +} + +#toc { + margin-bottom: 2.5em; +} + +#toctitle { + color: #527bbd; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} + +span.aqua { color: aqua; } +span.black { color: black; } +span.blue { color: blue; } +span.fuchsia { color: fuchsia; } +span.gray { color: gray; } +span.green { color: green; } +span.lime { color: lime; } +span.maroon { color: maroon; } +span.navy { color: navy; } +span.olive { color: olive; } +span.purple { color: purple; } +span.red { color: red; } +span.silver { color: silver; } +span.teal { color: teal; } +span.white { color: white; } +span.yellow { color: yellow; } + +span.aqua-background { background: aqua; } +span.black-background { background: black; } +span.blue-background { background: blue; } +span.fuchsia-background { background: fuchsia; } +span.gray-background { background: gray; } +span.green-background { background: green; } +span.lime-background { background: lime; } +span.maroon-background { background: maroon; } +span.navy-background { background: navy; } +span.olive-background { background: olive; } +span.purple-background { background: purple; } +span.red-background { background: red; } +span.silver-background { background: silver; } +span.teal-background { background: teal; } +span.white-background { background: white; } +span.yellow-background { background: yellow; } + +span.big { font-size: 2em; } +span.small { font-size: 0.6em; } + +span.underline { text-decoration: underline; } +span.overline { text-decoration: overline; } +span.line-through { text-decoration: line-through; } + +div.unbreakable { page-break-inside: avoid; } + + +/* + * xhtml11 specific + * + * */ + +div.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.tableblock > table { + border: 3px solid #527bbd; +} +thead, p.table.header { + font-weight: bold; + color: #527bbd; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +/* + * html5 specific + * + * */ + +table.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +thead, p.tableblock.header { + font-weight: bold; + color: #527bbd; +} +p.tableblock { + margin-top: 0; +} +table.tableblock { + border-width: 3px; + border-spacing: 0px; + border-style: solid; + border-color: #527bbd; + border-collapse: collapse; +} +th.tableblock, td.tableblock { + border-width: 1px; + padding: 4px; + border-style: solid; + border-color: #527bbd; +} + +table.tableblock.frame-topbot { + border-left-style: hidden; + border-right-style: hidden; +} +table.tableblock.frame-sides { + border-top-style: hidden; + border-bottom-style: hidden; +} +table.tableblock.frame-none { + border-style: hidden; +} + +th.tableblock.halign-left, td.tableblock.halign-left { + text-align: left; +} +th.tableblock.halign-center, td.tableblock.halign-center { + text-align: center; +} +th.tableblock.halign-right, td.tableblock.halign-right { + text-align: right; +} + +th.tableblock.valign-top, td.tableblock.valign-top { + vertical-align: top; +} +th.tableblock.valign-middle, td.tableblock.valign-middle { + vertical-align: middle; +} +th.tableblock.valign-bottom, td.tableblock.valign-bottom { + vertical-align: bottom; +} + + +/* + * manpage specific + * + * */ + +body.manpage h1 { + padding-top: 0.5em; + padding-bottom: 0.5em; + border-top: 2px solid silver; + border-bottom: 2px solid silver; +} +body.manpage h2 { + border-style: none; +} +body.manpage div.sectionbody { + margin-left: 3em; +} + +@media print { + body.manpage div#toc { display: none; } +} + + +</style> +<script type="text/javascript"> +/*<![CDATA[*/ +var asciidoc = { // Namespace. + +///////////////////////////////////////////////////////////////////// +// Table Of Contents generator +///////////////////////////////////////////////////////////////////// + +/* Author: Mihai Bazon, September 2002 + * http://students.infoiasi.ro/~mishoo + * + * Table Of Content generator + * Version: 0.4 + * + * Feel free to use this script under the terms of the GNU General Public + * License, as long as you do not remove or alter this notice. + */ + + /* modified by Troy D. Hanson, September 2006. License: GPL */ + /* modified by Stuart Rackham, 2006, 2009. License: GPL */ + +// toclevels = 1..4. +toc: function (toclevels) { + + function getText(el) { + var text = ""; + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants. + text += i.data; + else if (i.firstChild != null) + text += getText(i); + } + return text; + } + + function TocEntry(el, text, toclevel) { + this.element = el; + this.text = text; + this.toclevel = toclevel; + } + + function tocEntries(el, toclevels) { + var result = new Array; + var re = new RegExp('[hH]([1-'+(toclevels+1)+'])'); + // Function that scans the DOM tree for header elements (the DOM2 + // nodeIterator API would be a better technique but not supported by all + // browsers). + var iterate = function (el) { + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 1 /* Node.ELEMENT_NODE */) { + var mo = re.exec(i.tagName); + if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") { + result[result.length] = new TocEntry(i, getText(i), mo[1]-1); + } + iterate(i); + } + } + } + iterate(el); + return result; + } + + var toc = document.getElementById("toc"); + if (!toc) { + return; + } + + // Delete existing TOC entries in case we're reloading the TOC. + var tocEntriesToRemove = []; + var i; + for (i = 0; i < toc.childNodes.length; i++) { + var entry = toc.childNodes[i]; + if (entry.nodeName.toLowerCase() == 'div' + && entry.getAttribute("class") + && entry.getAttribute("class").match(/^toclevel/)) + tocEntriesToRemove.push(entry); + } + for (i = 0; i < tocEntriesToRemove.length; i++) { + toc.removeChild(tocEntriesToRemove[i]); + } + + // Rebuild TOC entries. + var entries = tocEntries(document.getElementById("content"), toclevels); + for (var i = 0; i < entries.length; ++i) { + var entry = entries[i]; + if (entry.element.id == "") + entry.element.id = "_toc_" + i; + var a = document.createElement("a"); + a.href = "#" + entry.element.id; + a.appendChild(document.createTextNode(entry.text)); + var div = document.createElement("div"); + div.appendChild(a); + div.className = "toclevel" + entry.toclevel; + toc.appendChild(div); + } + if (entries.length == 0) + toc.parentNode.removeChild(toc); +}, + + +///////////////////////////////////////////////////////////////////// +// Footnotes generator +///////////////////////////////////////////////////////////////////// + +/* Based on footnote generation code from: + * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html + */ + +footnotes: function () { + // Delete existing footnote entries in case we're reloading the footnodes. + var i; + var noteholder = document.getElementById("footnotes"); + if (!noteholder) { + return; + } + var entriesToRemove = []; + for (i = 0; i < noteholder.childNodes.length; i++) { + var entry = noteholder.childNodes[i]; + if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote") + entriesToRemove.push(entry); + } + for (i = 0; i < entriesToRemove.length; i++) { + noteholder.removeChild(entriesToRemove[i]); + } + + // Rebuild footnote entries. + var cont = document.getElementById("content"); + var spans = cont.getElementsByTagName("span"); + var refs = {}; + var n = 0; + for (i=0; i<spans.length; i++) { + if (spans[i].className == "footnote") { + n++; + var note = spans[i].getAttribute("data-note"); + if (!note) { + // Use [\s\S] in place of . so multi-line matches work. + // Because JavaScript has no s (dotall) regex flag. + note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1]; + spans[i].innerHTML = + "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n + + "' title='View footnote' class='footnote'>" + n + "</a>]"; + spans[i].setAttribute("data-note", note); + } + noteholder.innerHTML += + "<div class='footnote' id='_footnote_" + n + "'>" + + "<a href='#_footnoteref_" + n + "' title='Return to text'>" + + n + "</a>. " + note + "</div>"; + var id =spans[i].getAttribute("id"); + if (id != null) refs["#"+id] = n; + } + } + if (n == 0) + noteholder.parentNode.removeChild(noteholder); + else { + // Process footnoterefs. + for (i=0; i<spans.length; i++) { + if (spans[i].className == "footnoteref") { + var href = spans[i].getElementsByTagName("a")[0].getAttribute("href"); + href = href.match(/#.*/)[0]; // Because IE return full URL. + n = refs[href]; + spans[i].innerHTML = + "[<a href='#_footnote_" + n + + "' title='View footnote' class='footnote'>" + n + "</a>]"; + } + } + } +}, + +install: function(toclevels) { + var timerId; + + function reinstall() { + asciidoc.footnotes(); + if (toclevels) { + asciidoc.toc(toclevels); + } + } + + function reinstallAndRemoveTimer() { + clearInterval(timerId); + reinstall(); + } + + timerId = setInterval(reinstall, 500); + if (document.addEventListener) + document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false); + else + window.onload = reinstallAndRemoveTimer; +} + +} +asciidoc.install(); +/*]]>*/ +</script> +</head> +<body class="manpage"> +<div id="header"> +<h1> +nvme-media-unit-stat-log(1) Manual Page +</h1> +<h2>NAME</h2> +<div class="sectionbody"> +<p>nvme-media-unit-stat-log - + Send NVMe Supported Log pages request, returns result and log +</p> +</div> +</div> +<div id="content"> +<div class="sect1"> +<h2 id="_synopsis">SYNOPSIS</h2> +<div class="sectionbody"> +<div class="verseblock"> +<pre class="content"><em>nvme supported-log-pages</em> <device> [--output-format=<fmt> | -o <fmt>] + [-b | --raw-binary]</pre> +<div class="attribution"> +</div></div> +</div> +</div> +<div class="sect1"> +<h2 id="_description">DESCRIPTION</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Retrieves the NVMe supportd log pages details from an NVMe device and provides +the returned structure.</p></div> +<div class="paragraph"><p>The <device> parameter is mandatory and should be the NVMe character +device (ex: /dev/nvme0).</p></div> +<div class="paragraph"><p>On success, the returned supportd log pages log structure will be printed +for each command that is supported.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_options">OPTIONS</h2> +<div class="sectionbody"> +<div class="dlist"><dl> +<dt class="hdlist1"> +-o <format> +</dt> +<dt class="hdlist1"> +--output-format=<format> +</dt> +<dd> +<p> + This option will set the reporting format to normal, json, or binary. + Only one output format can be used at a time. +</p> +</dd> +<dt class="hdlist1"> + -b + </dt> + <dt class="hdlist1"> + --raw-binary + </dt> + <dd> + <p> + This option will get the data in raw binary format. + </p> + </dd> +<dt class="hdlist1"> + -d + </dt> + <dt class="hdlist1"> + --dom-id + </dt> + <dd> + <p> + This option is to get the domain ID. + </p> + </dd> +</dl></div> +</div> +</div> +<div class="sect1"> +<h2 id="_examples">EXAMPLES</h2> +<div class="sectionbody"> +<div class="paragraph"><p>No examples provided yet.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_nvme">NVME</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Part of the nvme-user suite</p></div> +</div> +</div> +</div> +<div id="footnotes"><hr /></div> +<div id="footer"> +<div id="footer-text"> +Last updated + 2021-08-13 22:37:48 IST +</div> +</div> +</body> +</html>
\ No newline at end of file diff --git a/Documentation/nvme-media-unit-stat-log.txt b/Documentation/nvme-media-unit-stat-log.txt new file mode 100644 index 0000000..427b77c --- /dev/null +++ b/Documentation/nvme-media-unit-stat-log.txt @@ -0,0 +1,47 @@ +nvme-media-unit-stat-log(1) +=========================== + +NAME +---- +nvme-media-unit-stat-log - Send NVMe Media unit status Log pages +request, returns result and log. + +SYNOPSIS +-------- +[verse] +'nvme media-unit-stat-log' <device> [--dom-id | -d ] + [--output-format=<fmt> | -o <fmt>] + [--raw-binary | -b] + +DESCRIPTION +----------- +Retrieves the NVMe Media unit status log pages details from +an NVMe device and provides the returned structure. + +The <device> parameter is mandatory and should be the NVMe character +device (ex: /dev/nvme0). + +On success, the returned Media unit status log pages log structure will be printed. + +OPTIONS +------- + +-o <format>:: +--output-format=<format>:: + This option will set the reporting format to normal, json, or binary. + Only one output format can be used at a time. + +-d:: +--dom-id:: + To get the domain ID. +-b:: +--raw-binary:: + To show raw binary data. + +EXAMPLES +-------- +No examples provided yet. + +NVME +---- +Part of the nvme-user suite
\ No newline at end of file diff --git a/Documentation/nvme-lnvm-remove.1 b/Documentation/nvme-mi-cmd-support-effects-log.1 index 8b6bb76..c15184d 100644 --- a/Documentation/nvme-lnvm-remove.1 +++ b/Documentation/nvme-mi-cmd-support-effects-log.1 @@ -1,13 +1,13 @@ '\" t -.\" Title: nvme-lnvm-remove +.\" Title: nvme-mi-cmd-support-effects-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LNVM\-REMOVE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MI\-CMD\-SUPPO" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,26 +28,37 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -nvme-lnvm-remove \- Remove an initialized LightNVM target\&. +nvme-mi-cmd-support-effects-log \- Send NVMe MI Command Support and Effects log, returns results and structure .SH "SYNOPSIS" .sp .nf -\fInvme lnvm\-remove\fR [\-\-target\-name=<TARGET> | \-n <TARGET>] +\fInvme\-mi\-cmd\-support\-effects\-log\fR <device> [\-o <fmt> | \-\-output\-format=<fmt>] + [\-H | \-\-human\-readable] .fi .SH "DESCRIPTION" .sp -Remove an initialized target\&. +For the NVMe device given, sends an MI Command Support and Effects log (id 13h) and provides the result and returned log structure\&. .sp -The target name is the name of which the media is exposed as in /dev/<TARGET> +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. +.sp +On success, the 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 -\-\-target\-name=<TARGET>, \-n <TARGET> +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, +\fIjson\fR, or +\fIbinary\fR\&. Only one output format can be used at a time\&. +.RE +.PP +\-H, \-\-human\-readable .RS 4 -Target name of the device to initialize\&. For example: target0\&. +This option will parse and format many of the bit fields into human\-readable formats\&. .RE .SH "EXAMPLES" .sp -None yet +nvme mi\-cmd\-support\-effects\-log /dev/nvme0 \-H .SH "NVME" .sp Part of the nvme\-user suite diff --git a/Documentation/nvme-mi-cmd-support-effects-log.html b/Documentation/nvme-mi-cmd-support-effects-log.html new file mode 100644 index 0000000..1afb0c0 --- /dev/null +++ b/Documentation/nvme-mi-cmd-support-effects-log.html @@ -0,0 +1,822 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-mi-cmd-support-effects-log(1)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+pre {
+ white-space: pre-wrap;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overridden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+nvme-mi-cmd-support-effects-log(1) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>nvme-mi-cmd-support-effects-log -
+ Send NVMe MI Command Support and Effects log, returns results and structure
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="verseblock">
+<pre class="content"><em>nvme-mi-cmd-support-effects-log</em> <device> [-o <fmt> | --output-format=<fmt>]
+ [-H | --human-readable]</pre>
+<div class="attribution">
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_description">DESCRIPTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>For the NVMe device given, sends an MI Command Support and Effects log (id 13h)
+and provides the result and returned log structure.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>
+<div class="paragraph"><p>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.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_options">OPTIONS</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-o <format>
+</dt>
+<dt class="hdlist1">
+--output-format=<format>
+</dt>
+<dd>
+<p>
+ Set the reporting format to <em>normal</em>, <em>json</em>, or
+ <em>binary</em>. Only one output format can be used at a time.
+</p>
+</dd>
+<dt class="hdlist1">
+-H
+</dt>
+<dt class="hdlist1">
+--human-readable
+</dt>
+<dd>
+<p>
+ This option will parse and format many of the bit fields
+ into human-readable formats.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">EXAMPLES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>nvme mi-cmd-support-effects-log /dev/nvme0 -H</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_nvme">NVME</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated
+ 2022-04-08 18:46:59 CEST
+</div>
+</div>
+</body>
+</html>
diff --git a/Documentation/nvme-mi-cmd-support-effects-log.txt b/Documentation/nvme-mi-cmd-support-effects-log.txt new file mode 100644 index 0000000..67b8355 --- /dev/null +++ b/Documentation/nvme-mi-cmd-support-effects-log.txt @@ -0,0 +1,45 @@ +nvme-mi-cmd-support-effects-log(1) +================================== + +NAME +---- +nvme-mi-cmd-support-effects-log - Send NVMe MI Command Support and Effects log, + returns results and structure + +SYNOPSIS +-------- +[verse] +'nvme-mi-cmd-support-effects-log' <device> [-o <fmt> | --output-format=<fmt>] + [-H | --human-readable] + +DESCRIPTION +----------- +For the NVMe device given, sends an MI Command Support and Effects log (id 13h) +and provides the result and returned log 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 +------- +-o <format>:: +--output-format=<format>:: + Set the reporting format to 'normal', 'json', or + 'binary'. Only one output format can be used at a time. + +-H:: +--human-readable:: + This option will parse and format many of the bit fields + into human-readable formats. + +EXAMPLES +-------- +nvme mi-cmd-support-effects-log /dev/nvme0 -H + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-micron-clear-pcie-errors.1 b/Documentation/nvme-micron-clear-pcie-errors.1 index 7da8234..b99290e 100644 --- a/Documentation/nvme-micron-clear-pcie-errors.1 +++ b/Documentation/nvme-micron-clear-pcie-errors.1 @@ -2,12 +2,12 @@ .\" Title: nvme-micron-clear-pcie-errors .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-MICRON\-CLEAR\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MICRON\-CLEAR\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-micron-clear-pcie-errors.html b/Documentation/nvme-micron-clear-pcie-errors.html index 3f958f4..be146ad 100644 --- a/Documentation/nvme-micron-clear-pcie-errors.html +++ b/Documentation/nvme-micron-clear-pcie-errors.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-micron-clear-pcie-errors(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -798,7 +798,7 @@ Retrieve NAND statistics information <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-micron-internal-log.1 b/Documentation/nvme-micron-internal-log.1 index e72f88f..6baecf9 100644 --- a/Documentation/nvme-micron-internal-log.1 +++ b/Documentation/nvme-micron-internal-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-micron-internal-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-MICRON\-INTERN" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MICRON\-INTERN" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-micron-internal-log.html b/Documentation/nvme-micron-internal-log.html index 9d3efff..922de52 100644 --- a/Documentation/nvme-micron-internal-log.html +++ b/Documentation/nvme-micron-internal-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-micron-internal-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -813,7 +813,7 @@ Gets the logs from the device and saves to micron_logs.zip file <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-micron-nand-stats.1 b/Documentation/nvme-micron-nand-stats.1 index 149c7a4..6605d24 100644 --- a/Documentation/nvme-micron-nand-stats.1 +++ b/Documentation/nvme-micron-nand-stats.1 @@ -2,12 +2,12 @@ .\" Title: nvme-micron-nand-stats .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-MICRON\-NAND\-" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MICRON\-NAND\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-micron-nand-stats.html b/Documentation/nvme-micron-nand-stats.html index 10c2923..7f41a9a 100644 --- a/Documentation/nvme-micron-nand-stats.html +++ b/Documentation/nvme-micron-nand-stats.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-micron-nand-stats(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -799,7 +799,7 @@ Retrieve NAND statistics information <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-micron-pcie-stats.1 b/Documentation/nvme-micron-pcie-stats.1 index 7297b0f..8ed93c0 100644 --- a/Documentation/nvme-micron-pcie-stats.1 +++ b/Documentation/nvme-micron-pcie-stats.1 @@ -2,12 +2,12 @@ .\" Title: nvme-micron-pcie-stats .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-MICRON\-PCIE\-" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MICRON\-PCIE\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-micron-pcie-stats.html b/Documentation/nvme-micron-pcie-stats.html index 3c6c2e8..7d06af5 100644 --- a/Documentation/nvme-micron-pcie-stats.html +++ b/Documentation/nvme-micron-pcie-stats.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-micron-pcie-stats(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -799,7 +799,7 @@ Retrieve PCIe error information <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-micron-selective-download.1 b/Documentation/nvme-micron-selective-download.1 index 65959ba..9c4d1ce 100644 --- a/Documentation/nvme-micron-selective-download.1 +++ b/Documentation/nvme-micron-selective-download.1 @@ -2,12 +2,12 @@ .\" Title: nvme-micron-selective-download .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-MICRON\-SELECT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MICRON\-SELECT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-micron-selective-download.html b/Documentation/nvme-micron-selective-download.html index 88ea82e..68ce5cc 100644 --- a/Documentation/nvme-micron-selective-download.html +++ b/Documentation/nvme-micron-selective-download.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-micron-selective-download(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -867,7 +867,7 @@ Update eeprom, OOB and main firmware <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-micron-smart-add-log.1 b/Documentation/nvme-micron-smart-add-log.1 index 1ffbdc8..5f68604 100644 --- a/Documentation/nvme-micron-smart-add-log.1 +++ b/Documentation/nvme-micron-smart-add-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-micron-smart-add-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-MICRON\-SMART\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MICRON\-SMART\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-micron-smart-add-log.html b/Documentation/nvme-micron-smart-add-log.html index 406ddf9..bc75dfa 100644 --- a/Documentation/nvme-micron-smart-add-log.html +++ b/Documentation/nvme-micron-smart-add-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-micron-smart-add-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -808,7 +808,7 @@ Retrieve NAND/extended SMART data and display in json format <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-micron-temperature-stats.1 b/Documentation/nvme-micron-temperature-stats.1 index 95f798e..770ed1b 100644 --- a/Documentation/nvme-micron-temperature-stats.1 +++ b/Documentation/nvme-micron-temperature-stats.1 @@ -2,12 +2,12 @@ .\" Title: nvme-micron-temperarature-stats .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-MICRON\-TEMPER" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-MICRON\-TEMPER" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-micron-temperature-stats.html b/Documentation/nvme-micron-temperature-stats.html index 0703737..da7a53f 100644 --- a/Documentation/nvme-micron-temperature-stats.html +++ b/Documentation/nvme-micron-temperature-stats.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-micron-temperarature-stats(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -799,7 +799,7 @@ Retrieve temperature information <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-netapp-ontapdevices.1 b/Documentation/nvme-netapp-ontapdevices.1 index c95830e..3deca2f 100644 --- a/Documentation/nvme-netapp-ontapdevices.1 +++ b/Documentation/nvme-netapp-ontapdevices.1 @@ -2,12 +2,12 @@ .\" Title: nvme-netapp-ontapdevices .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-NETAPP\-ONTAPD" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-NETAPP\-ONTAPD" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-netapp-ontapdevices.html b/Documentation/nvme-netapp-ontapdevices.html index 3714ad9..1b39256 100644 --- a/Documentation/nvme-netapp-ontapdevices.html +++ b/Documentation/nvme-netapp-ontapdevices.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-netapp-ontapdevices(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -807,7 +807,7 @@ Display information, in a column-based format, for ONTAP devices. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-netapp-smdevices.1 b/Documentation/nvme-netapp-smdevices.1 index af6433e..9cde647 100644 --- a/Documentation/nvme-netapp-smdevices.1 +++ b/Documentation/nvme-netapp-smdevices.1 @@ -2,12 +2,12 @@ .\" Title: nvme-netapp-smdevices .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-NETAPP\-SMDEVI" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-NETAPP\-SMDEVI" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-netapp-smdevices.html b/Documentation/nvme-netapp-smdevices.html index 0ec37eb..76b38ba 100644 --- a/Documentation/nvme-netapp-smdevices.html +++ b/Documentation/nvme-netapp-smdevices.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-netapp-smdevices(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -809,7 +809,7 @@ namespace. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-ns-descs.1 b/Documentation/nvme-ns-descs.1 index f13de91..4f58333 100644 --- a/Documentation/nvme-ns-descs.1 +++ b/Documentation/nvme-ns-descs.1 @@ -2,12 +2,12 @@ .\" Title: nvme-ns-descs .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-NS\-DESCS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-NS\-DESCS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-ns-descs.html b/Documentation/nvme-ns-descs.html index ca4dae9..f8b00f1 100644 --- a/Documentation/nvme-ns-descs.html +++ b/Documentation/nvme-ns-descs.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-ns-descs(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -857,7 +857,7 @@ Have the program return the raw structure in binary: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-ns-rescan.1 b/Documentation/nvme-ns-rescan.1 index 3473023..700993f 100644 --- a/Documentation/nvme-ns-rescan.1 +++ b/Documentation/nvme-ns-rescan.1 @@ -2,12 +2,12 @@ .\" Title: nvme-ns-rescan .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-NS\-RESCAN" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-NS\-RESCAN" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-ns-rescan.html b/Documentation/nvme-ns-rescan.html index b7d6d3c..a544f94 100644 --- a/Documentation/nvme-ns-rescan.html +++ b/Documentation/nvme-ns-rescan.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-ns-rescan(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -794,7 +794,7 @@ Rescans the nvme namespaces. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-nvm-id-ctrl.1 b/Documentation/nvme-nvm-id-ctrl.1 index c25ca19..6495c60 100644 --- a/Documentation/nvme-nvm-id-ctrl.1 +++ b/Documentation/nvme-nvm-id-ctrl.1 @@ -2,12 +2,12 @@ .\" Title: nvme-nvm-id-ctrl .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-NVM\-ID\-CTRL" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-NVM\-ID\-CTRL" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-nvm-id-ctrl.html b/Documentation/nvme-nvm-id-ctrl.html index a4910c2..a72fce9 100644 --- a/Documentation/nvme-nvm-id-ctrl.html +++ b/Documentation/nvme-nvm-id-ctrl.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-nvm-id-ctrl(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -821,7 +821,7 @@ Show the output in json format <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-nvm-id-ns-lba-format.1 b/Documentation/nvme-nvm-id-ns-lba-format.1 new file mode 100644 index 0000000..86723f0 --- /dev/null +++ b/Documentation/nvme-nvm-id-ns-lba-format.1 @@ -0,0 +1,117 @@ +'\" t +.\" Title: nvme-nvm-id-ns-lba-format +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> +.\" Date: 01/07/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-NVM\-ID\-NS\-L" "1" "01/07/2022" "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-nvm-id-ns-lba-format \- Send NVMe Identify NVM Command Set specific Namespace data structure for specified LBA format, display structure +.SH "SYNOPSIS" +.sp +.nf +\fInvme nvm\-id\-ns\-lba\-format\fR <device> [\-\-uuid\-index=<uuid\-index> | \-U <uuid_index>] + [\-\-lba\-format\-index=<lba_format_index> | \-i <lba_format_index>] + [\-v | \-\-verbose] + [\-\-output\-format=<fmt> | \-o <fmt>] +.fi +.SH "DESCRIPTION" +.sp +Identify NVM Command Set specific Namespace data structure for the specified LBA format index for the NVM Command Set specified in the CSI field\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. +.sp +On success, the 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 +\-U <uuid\-index>, \-\-uuid\-index=<uuid\-index> +.RS 4 +UUID Index of the feature +.RE +.PP +\-i <lba_format_index>, \-\-lba\-format\-index=<lba_format_index> +.RS 4 +This field specifies the index into the LBA Format list identifying the LBA Format capabilities that are to be returned +.RE +.PP +\-v, \-\-verbose +.RS 4 +Increase the information detail in the output\&. +.RE +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, +\fIjson\fR, or +\fIbinary\fR\&. Only one output format can be used at a time\&. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Has the program interpret the returned buffer and display the known fields in a human readable format: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme nvm\-id\-ns\-lba\-format /dev/nvme0n1 \-i 0 +.fi +.if n \{\ +.RE +.\} +.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 nvm\-id\-ns\-lba\-format /dev/nvme0 \-i 0 \-o binary > nvm_id_ns\&.raw +# nvme nvm\-id\-ns\-lba\-format /dev/nvme0n1 \-i 0 \-\-output\-format=binary > nvm_id_ns\&.raw +.fi +.if n \{\ +.RE +.\} +.RE +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-lnvm-diag-bbtbl.html b/Documentation/nvme-nvm-id-ns-lba-format.html index be2f05a..09ac1c4 100644 --- a/Documentation/nvme-lnvm-diag-bbtbl.html +++ b/Documentation/nvme-nvm-id-ns-lba-format.html @@ -1,11 +1,10 @@ -<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-diag-bbtbl(1)</title>
+<meta name="generator" content="AsciiDoc 8.6.8" />
+<title>nvme-nvm-id-ns-lba-format(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -95,9 +94,7 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-pre {
- white-space: pre-wrap;
-}
+
#author {
color: #527bbd;
@@ -226,7 +223,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; vertical-align: text-bottom; }
+span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
@@ -436,7 +433,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -735,12 +732,12 @@ asciidoc.install(); <body class="manpage">
<div id="header">
<h1>
-nvme-lnvm-diag-bbtbl(1) Manual Page
+nvme-nvm-id-ns-lba-format(1) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>nvme-lnvm-diag-bbtbl -
- Diagnose the bad block table
+<p>nvme-nvm-id-ns-lba-format -
+ Send NVMe Identify NVM Command Set specific Namespace data structure for specified LBA format, display structure
</p>
</div>
</div>
@@ -749,10 +746,10 @@ nvme-lnvm-diag-bbtbl(1) Manual Page <h2 id="_synopsis">SYNOPSIS</h2>
<div class="sectionbody">
<div class="verseblock">
-<pre class="content"><em>nvme lnvm-diag-bbtbl</em> [--namespace-id=<NUM> | -n <NUM>]
- [--channel-id=<CHID> | -c <CHID>]
- [--lun-id=<LUNID> | -l <LUNID>]
- [--raw-binary | -b]</pre>
+<pre class="content"><em>nvme nvm-id-ns-lba-format</em> <device> [--uuid-index=<uuid-index> | -U <uuid_index>]
+ [--lba-format-index=<lba_format_index> | -i <lba_format_index>]
+ [-v | --verbose]
+ [--output-format=<fmt> | -o <fmt>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -760,15 +757,13 @@ nvme-lnvm-diag-bbtbl(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Retrieve the bad block table for a given channel and lun.</p></div>
-<div class="paragraph"><p>The statistics will be shown in the default case, and the actual output bad
-block information can be retrieved when --raw-binary is passed.</p></div>
-<div class="paragraph"><p>The raw binary output follows this format:</p></div>
-<div class="paragraph"><p>Channel 0, LUN0 (Dual plane flash)</p></div>
-<div class="paragraph"><p>Byte 0 → Plane 0, Block 0
-Byte 1 → Plane 1, Block 0
-Byte 2 → Plane 0, Block 1
-…</p></div>
+<div class="paragraph"><p>Identify NVM Command Set specific Namespace data structure for the specified
+LBA format index for the NVM Command Set specified in the CSI field.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>
+<div class="paragraph"><p>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.</p></div>
</div>
</div>
<div class="sect1">
@@ -776,47 +771,49 @@ Byte 2 → Plane 0, Block 1 <div class="sectionbody">
<div class="dlist"><dl>
<dt class="hdlist1">
---namespace-id=<NUM>
+-U <uuid-index>
</dt>
<dt class="hdlist1">
--n <NUM>
+--uuid-index=<uuid-index>
</dt>
<dd>
<p>
- Namespace id to use
+ UUID Index of the feature
</p>
</dd>
<dt class="hdlist1">
---channel-id=<NUM>
+-i <lba_format_index>
</dt>
<dt class="hdlist1">
--c
+--lba-format-index=<lba_format_index>
</dt>
<dd>
<p>
- Channel id
+ This field specifies the index into the LBA Format list identifying
+ the LBA Format capabilities that are to be returned
</p>
</dd>
<dt class="hdlist1">
---lun-id=<NUM>
+-v
</dt>
<dt class="hdlist1">
--l
+--verbose
</dt>
<dd>
<p>
- LUN id
+ Increase the information detail in the output.
</p>
</dd>
<dt class="hdlist1">
---raw-binary
+-o <format>
</dt>
<dt class="hdlist1">
--b
+--output-format=<format>
</dt>
<dd>
<p>
- Returns the bad block table in binary form without statistics.
+ Set the reporting format to <em>normal</em>, <em>json</em>, or
+ <em>binary</em>. Only one output format can be used at a time.
</p>
</dd>
</dl></div>
@@ -828,26 +825,25 @@ Byte 2 → Plane 0, Block 1 <div class="ulist"><ul>
<li>
<p>
-Retrieve bad block table statistics for physical device nvme0, channel 0, and
-lun 0:
+Has the program interpret the returned buffer and display the known
+fields in a human readable format:
</p>
-</li>
-</ul></div>
<div class="listingblock">
<div class="content">
-<pre><code># nvme lnvm-diag-bbtbl /dev/nvme0 -c 0 -n 0</code></pre>
+<pre><code># nvme nvm-id-ns-lba-format /dev/nvme0n1 -i 0</code></pre>
</div></div>
-<div class="ulist"><ul>
+</li>
<li>
<p>
-Display the bad block table in raw form without statistics for same query:
+Have the program return the raw structure in binary:
</p>
-</li>
-</ul></div>
<div class="listingblock">
<div class="content">
-<pre><code># nvme lnvm-diag-bbtbl /dev/nvme0 -c 0 -n 0 -b | hexdump</code></pre>
+<pre><code># nvme nvm-id-ns-lba-format /dev/nvme0 -i 0 -o binary > nvm_id_ns.raw
+# nvme nvm-id-ns-lba-format /dev/nvme0n1 -i 0 --output-format=binary > nvm_id_ns.raw</code></pre>
</div></div>
+</li>
+</ul></div>
</div>
</div>
<div class="sect1">
@@ -860,8 +856,7 @@ Display the bad block table in raw form without statistics for same query: <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated
- 2021-07-19 10:10:19 PDT
+Last updated 2022-01-07 19:00:31 KST
</div>
</div>
</body>
diff --git a/Documentation/nvme-nvm-id-ns-lba-format.txt b/Documentation/nvme-nvm-id-ns-lba-format.txt new file mode 100644 index 0000000..638e2fb --- /dev/null +++ b/Documentation/nvme-nvm-id-ns-lba-format.txt @@ -0,0 +1,67 @@ +nvme-nvm-id-ns-lba-format(1) +============================ + +NAME +---- +nvme-nvm-id-ns-lba-format - Send NVMe Identify NVM Command Set specific +Namespace data structure for specified LBA format, display structure + +SYNOPSIS +-------- +[verse] +'nvme nvm-id-ns-lba-format' <device> [--uuid-index=<uuid-index> | -U <uuid_index>] + [--lba-format-index=<lba_format_index> | -i <lba_format_index>] + [-v | --verbose] + [--output-format=<fmt> | -o <fmt>] + +DESCRIPTION +----------- +Identify NVM Command Set specific Namespace data structure for the specified +LBA format index for the NVM Command Set specified in the CSI field. + +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 +------- +-U <uuid-index>:: +--uuid-index=<uuid-index>:: + UUID Index of the feature + +-i <lba_format_index>:: +--lba-format-index=<lba_format_index>:: + This field specifies the index into the LBA Format list identifying + the LBA Format capabilities that are to be returned + +-v:: +--verbose:: + Increase the information detail in the output. + +-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 nvm-id-ns-lba-format /dev/nvme0n1 -i 0 +------------ ++ +* Have the program return the raw structure in binary: ++ +------------ +# nvme nvm-id-ns-lba-format /dev/nvme0 -i 0 -o binary > nvm_id_ns.raw +# nvme nvm-id-ns-lba-format /dev/nvme0n1 -i 0 --output-format=binary > nvm_id_ns.raw +------------ + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-nvm-id-ns.1 b/Documentation/nvme-nvm-id-ns.1 new file mode 100644 index 0000000..fde30b7 --- /dev/null +++ b/Documentation/nvme-nvm-id-ns.1 @@ -0,0 +1,162 @@ +'\" t +.\" Title: nvme-nvm-id-ns +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> +.\" Date: 01/07/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-NVM\-ID\-NS" "1" "01/07/2022" "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-nvm-id-ns \- Send NVMe Identify NVM Command Set specific Namespace data structure, display structure +.SH "SYNOPSIS" +.sp +.nf +\fInvme nvm\-id\-ns\fR <device> [\-\-uuid\-index=<uuid\-index> | \-U <uuid_index>] + [\-\-namespace\-id=<NUM> | \-n <NUM>] + [\-v | \-\-verbose] + [\-\-output\-format=<fmt> | \-o <fmt>] +.fi +.SH "DESCRIPTION" +.sp +Identify NVM Command Set specific Namespace data structure for the specified NSID for the NVM Command Set specified in the CSI field\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. +.sp +On success, the 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 <NUM>, \-\-namespace\-id=<NUM> +.RS 4 +Use the provided namespace id for the command\&. If not provided, the namespace id of the block device will be used\&. If the command is issued to a non\-block device, the parameter is required\&. +.RE +.PP +\-U <uuid\-index>, \-\-uuid\-index=<uuid\-index> +.RS 4 +UUID Index of the feature +.RE +.PP +\-v, \-\-verbose +.RS 4 +Increase the information detail in the output\&. +.RE +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, +\fIjson\fR, or +\fIbinary\fR\&. Only one output format can be used at a time\&. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Has the program interpret the returned buffer and display the known fields in a human readable format: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme nvm\-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 nvm\-id\-ns /dev/nvme0 \-n 1 +# nvme nvm\-id\-ns /dev/nvme0n1 \-n 1 +# nvme nvm\-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 +.\} +Have the program return the raw structure in binary: +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme nvm\-id\-ns /dev/nvme0n1 \-o binary > id_ns\&.raw +# nvme nvm\-id\-ns /dev/nvme0n1 \-\-output\-format=binary > 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 +.fi +.if n \{\ +.RE +.\} +.RE +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-lnvm-create.html b/Documentation/nvme-nvm-id-ns.html index f1472f1..82645dc 100644 --- a/Documentation/nvme-lnvm-create.html +++ b/Documentation/nvme-nvm-id-ns.html @@ -1,11 +1,10 @@ -<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-create(1)</title>
+<meta name="generator" content="AsciiDoc 8.6.8" />
+<title>nvme-nvm-id-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -95,9 +94,7 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-pre {
- white-space: pre-wrap;
-}
+
#author {
color: #527bbd;
@@ -226,7 +223,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; vertical-align: text-bottom; }
+span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
@@ -436,7 +433,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -735,12 +732,12 @@ asciidoc.install(); <body class="manpage">
<div id="header">
<h1>
-nvme-lnvm-create(1) Manual Page
+nvme-nvm-id-ns(1) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>nvme-lnvm-create -
- Instantiate a target on top of a LightNVM enabled device
+<p>nvme-nvm-id-ns -
+ Send NVMe Identify NVM Command Set specific Namespace data structure, display structure
</p>
</div>
</div>
@@ -749,11 +746,10 @@ nvme-lnvm-create(1) Manual Page <h2 id="_synopsis">SYNOPSIS</h2>
<div class="sectionbody">
<div class="verseblock">
-<pre class="content"><em>nvme lnvm-create</em> [--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>]</pre>
+<pre class="content"><em>nvme nvm-id-ns</em> <device> [--uuid-index=<uuid-index> | -U <uuid_index>]
+ [--namespace-id=<NUM> | -n <NUM>]
+ [-v | --verbose]
+ [--output-format=<fmt> | -o <fmt>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -761,12 +757,13 @@ nvme-lnvm-create(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Instantiate a target on top of a LightNVM enabled device. This exposes the
-physical for the user to use.</p></div>
-<div class="paragraph"><p>The target name is the name of which the media is exposed as in
-/dev/<targetname></p></div>
-<div class="paragraph"><p>The target type is the target to be instantiated. Typically pblk or rrpc.</p></div>
-<div class="paragraph"><p>LUN begin and end defines the range of LUNs to use for a target instantiation.</p></div>
+<div class="paragraph"><p>Identify NVM Command Set specific Namespace data structure for the specified
+NSID for the NVM Command Set specified in the CSI field.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>
+<div class="paragraph"><p>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.</p></div>
</div>
</div>
<div class="sect1">
@@ -774,58 +771,50 @@ physical for the user to use.</p></div> <div class="sectionbody">
<div class="dlist"><dl>
<dt class="hdlist1">
---device-name=<DEVICE>
-</dt>
-<dt class="hdlist1">
--d <DEVICE>
-</dt>
-<dd>
-<p>
- Device name to initialize.
-</p>
-</dd>
-<dt class="hdlist1">
---target-name=<TARGET>
+-n <NUM>
</dt>
<dt class="hdlist1">
--n <TARGET>
+--namespace-id=<NUM>
</dt>
<dd>
<p>
- Target name of the device to initialize. For example: target0.
+ Use the provided namespace id for the command. If not provided, the
+ namespace id of the block device will be used. If the command is issued
+ to a non-block device, the parameter is required.
</p>
</dd>
<dt class="hdlist1">
---target-type=<TARGETTYPE>
+-U <uuid-index>
</dt>
<dt class="hdlist1">
--t <TARGETTYPE>
+--uuid-index=<uuid-index>
</dt>
<dd>
<p>
- Target type of the device to use. For example: pblk
+ UUID Index of the feature
</p>
</dd>
<dt class="hdlist1">
---lun-begin <NUM>
+-v
</dt>
<dt class="hdlist1">
--b <NUM>
+--verbose
</dt>
<dd>
<p>
- Begin LUN id offset to use for target
+ Increase the information detail in the output.
</p>
</dd>
<dt class="hdlist1">
---lun-end <NUM>
+-o <format>
</dt>
<dt class="hdlist1">
--e <NUM>
+--output-format=<format>
</dt>
<dd>
<p>
- End LUN id offset to use for target
+ Set the reporting format to <em>normal</em>, <em>json</em>, or
+ <em>binary</em>. Only one output format can be used at a time.
</p>
</dd>
</dl></div>
@@ -837,19 +826,47 @@ physical for the user to use.</p></div> <div class="ulist"><ul>
<li>
<p>
-Initialize nvme0n1 with pblk target with 64 LUNs.
+Has the program interpret the returned buffer and display the known
+fields in a human readable format:
</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme nvm-id-ns /dev/nvme0n1</code></pre>
+</div></div>
</li>
-</ul></div>
+<li>
+<p>
+If using the character device or overriding namespace id:
+</p>
<div class="listingblock">
<div class="content">
-<pre><code># nvme lnvm-create -d nvme0n1 -t pblk -n target0 -b 0 -e 63</code></pre>
+<pre><code># nvme nvm-id-ns /dev/nvme0 -n 1
+# nvme nvm-id-ns /dev/nvme0n1 -n 1
+# nvme nvm-id-ns /dev/nvme0 --namespace-id=1</code></pre>
</div></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_nvme">NVME</h2>
-<div class="sectionbody">
+</li>
+<li>
+<p>
+Have the program return the raw structure in binary:
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme nvm-id-ns /dev/nvme0n1 -o binary > id_ns.raw
+# nvme nvm-id-ns /dev/nvme0n1 --output-format=binary > id_ns.raw</code></pre>
+</div></div>
+<div class="paragraph"><p>It is probably a bad idea to not redirect stdout when using this mode.</p></div>
+</li>
+<li>
+<p>
+Alternatively you may want to send the data to another program that
+can parse the raw buffer.
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code>NVME</code></pre>
+</div></div>
+</li>
+</ul></div>
<div class="paragraph"><p>Part of the nvme-user suite</p></div>
</div>
</div>
@@ -857,8 +874,7 @@ Initialize nvme0n1 with pblk target with 64 LUNs. <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated
- 2021-07-19 10:10:19 PDT
+Last updated 2022-01-07 14:55:44 KST
</div>
</div>
</body>
diff --git a/Documentation/nvme-nvm-id-ns.txt b/Documentation/nvme-nvm-id-ns.txt new file mode 100644 index 0000000..dfbbfaa --- /dev/null +++ b/Documentation/nvme-nvm-id-ns.txt @@ -0,0 +1,83 @@ +nvme-nvm-id-ns(1) +================= + +NAME +---- +nvme-nvm-id-ns - Send NVMe Identify NVM Command Set specific Namespace data structure, display structure + +SYNOPSIS +-------- +[verse] +'nvme nvm-id-ns' <device> [--uuid-index=<uuid-index> | -U <uuid_index>] + [--namespace-id=<NUM> | -n <NUM>] + [-v | --verbose] + [--output-format=<fmt> | -o <fmt>] + +DESCRIPTION +----------- +Identify NVM Command Set specific Namespace data structure for the specified +NSID for the NVM Command Set specified in the CSI field. + +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 +------- +-n <NUM>:: +--namespace-id=<NUM>:: + Use the provided namespace id for the command. If not provided, the + namespace id of the block device will be used. If the command is issued + to a non-block device, the parameter is required. + +-U <uuid-index>:: +--uuid-index=<uuid-index>:: + UUID Index of the feature + +-v:: +--verbose:: + Increase the information detail in the output. + +-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 nvm-id-ns /dev/nvme0n1 +------------ ++ + +* If using the character device or overriding namespace id: ++ +------------ +# nvme nvm-id-ns /dev/nvme0 -n 1 +# nvme nvm-id-ns /dev/nvme0n1 -n 1 +# nvme nvm-id-ns /dev/nvme0 --namespace-id=1 +------------ ++ +* Have the program return the raw structure in binary: ++ +------------ +# nvme nvm-id-ns /dev/nvme0n1 -o binary > id_ns.raw +# nvme nvm-id-ns /dev/nvme0n1 --output-format=binary > 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 +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-lnvm-init.1 b/Documentation/nvme-ocp-latency-monitor-log.1 index a6eff88..9c38abd 100644 --- a/Documentation/nvme-lnvm-init.1 +++ b/Documentation/nvme-ocp-latency-monitor-log.1 @@ -1,13 +1,13 @@ '\" t -.\" Title: nvme-lnvm-init +.\" Title: nvme-ocp-latency-monitor-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LNVM\-INIT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-OCP\-LATENCY\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,26 +28,29 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -nvme-lnvm-init \- Initialize LightNVM device with media manager +nvme-ocp-latency-monitor-log \- Display latency monitor log page data in human readable format .SH "SYNOPSIS" .sp .nf -\fInvme lnvm\-init\fR [\-\-device\-name=<DEVICE> | \-d <DEVICE>] - [\-\-mediamgr\-name | \-m] +\fInvme ocp latency\-monitor\-log\fR <device> [\-\-output\-format=<fmt> | \-o <fmt>] .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\&. +For the NVMe device given, latency monitor log page data\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1)\&. +.sp +This will only work on OCP compliant devices supporting this log page\&. Results for any other device are undefined\&. +.sp +On success it returns 0, error code otherwise\&. .SH "OPTIONS" .PP -\-\-device\-name=<DEVICE>, \-d <DEVICE> +\-o <format>, \-\-output\-format=<format> .RS 4 -Device name to initialize\&. -.RE -.PP -\-\-mediamgr\-name=<MediaMgr>, \-m <MediaMgr> -.RS 4 -Media Manager name to use for initialization\&. +Set the reporting format to +\fInormal\fR +or +\fIjson\fR\&. Only one output format can be used at a time\&. The default is normal\&. .RE .SH "EXAMPLES" .sp @@ -59,39 +62,18 @@ Media Manager name to use for initialization\&. .sp -1 .IP \(bu 2.3 .\} -Initialize nvme0n1 -.RE +Displays the get latency monitor log for the device: .sp .if n \{\ .RS 4 .\} .nf -# nvme lnvm\-init \-d nvme0n1 +# nvme ocp latency\-monitor\-log /dev/nvme0 .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 +Part of the nvme\-user suite\&. diff --git a/Documentation/nvme-lnvm-init.html b/Documentation/nvme-ocp-latency-monitor-log.html index d1bee83..b3c21d7 100644 --- a/Documentation/nvme-lnvm-init.html +++ b/Documentation/nvme-ocp-latency-monitor-log.html @@ -4,8 +4,8 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-init(1)</title>
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-ocp-latency-monitor-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -735,12 +735,12 @@ asciidoc.install(); <body class="manpage">
<div id="header">
<h1>
-nvme-lnvm-init(1) Manual Page
+nvme-ocp-latency-monitor-log(1) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>nvme-lnvm-init -
- Initialize LightNVM device with media manager
+<p>nvme-ocp-latency-monitor-log -
+ Display latency monitor log page data in human readable format
</p>
</div>
</div>
@@ -749,8 +749,7 @@ nvme-lnvm-init(1) Manual Page <h2 id="_synopsis">SYNOPSIS</h2>
<div class="sectionbody">
<div class="verseblock">
-<pre class="content"><em>nvme lnvm-init</em> [--device-name=<DEVICE> | -d <DEVICE>]
- [--mediamgr-name | -m]</pre>
+<pre class="content"><em>nvme ocp latency-monitor-log</em> <device> [--output-format=<fmt> | -o <fmt>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -758,9 +757,12 @@ nvme-lnvm-init(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>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.</p></div>
+<div class="paragraph"><p>For the NVMe device given, latency monitor log page data.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1).</p></div>
+<div class="paragraph"><p>This will only work on OCP compliant devices supporting this log page.
+Results for any other device are undefined.</p></div>
+<div class="paragraph"><p>On success it returns 0, error code otherwise.</p></div>
</div>
</div>
<div class="sect1">
@@ -768,25 +770,15 @@ initialize the general media manager on top of the device.</p></div> <div class="sectionbody">
<div class="dlist"><dl>
<dt class="hdlist1">
---device-name=<DEVICE>
+-o <format>
</dt>
<dt class="hdlist1">
--d <DEVICE>
+--output-format=<format>
</dt>
<dd>
<p>
- Device name to initialize.
-</p>
-</dd>
-<dt class="hdlist1">
---mediamgr-name=<MediaMgr>
-</dt>
-<dt class="hdlist1">
--m <MediaMgr>
-</dt>
-<dd>
-<p>
- Media Manager name to use for initialization.
+ Set the reporting format to <em>normal</em> or <em>json</em>. Only one output format
+ can be used at a time. The default is normal.
</p>
</dd>
</dl></div>
@@ -798,31 +790,20 @@ initialize the general media manager on top of the device.</p></div> <div class="ulist"><ul>
<li>
<p>
-Initialize nvme0n1
+Displays the get latency monitor log for the device:
</p>
-</li>
-</ul></div>
<div class="listingblock">
<div class="content">
-<pre><code># nvme lnvm-init -d nvme0n1</code></pre>
+<pre><code># nvme ocp latency-monitor-log /dev/nvme0</code></pre>
</div></div>
-<div class="ulist"><ul>
-<li>
-<p>
-Initialize nvme0n1 with gennvm media manager (default media manager)
-</p>
</li>
</ul></div>
-<div class="listingblock">
-<div class="content">
-<pre><code># nvme lnvm-init -d nvme0n1 -m gennvm</code></pre>
-</div></div>
</div>
</div>
<div class="sect1">
<h2 id="_nvme">NVME</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Part of the nvme-user suite</p></div>
+<div class="paragraph"><p>Part of the nvme-user suite.</p></div>
</div>
</div>
</div>
@@ -830,7 +811,7 @@ Initialize nvme0n1 with gennvm media manager (default media manager) <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-ocp-latency-monitor-log.txt b/Documentation/nvme-ocp-latency-monitor-log.txt new file mode 100644 index 0000000..66f760c --- /dev/null +++ b/Documentation/nvme-ocp-latency-monitor-log.txt @@ -0,0 +1,44 @@ +nvme-ocp-latency-monitor-log(1) +=============================== + +NAME +---- +nvme-ocp-latency-monitor-log - Display latency monitor log page data in human +readable format + +SYNOPSIS +-------- +[verse] +'nvme ocp latency-monitor-log' <device> [--output-format=<fmt> | -o <fmt>] + +DESCRIPTION +----------- + +For the NVMe device given, latency monitor log page data. + +The <device> parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1). + +This will only work on OCP compliant devices supporting this log page. +Results for any other device are undefined. + +On success it returns 0, error code otherwise. + +OPTIONS +------- +-o <format>:: +--output-format=<format>:: + Set the reporting format to 'normal' or 'json'. Only one output format + can be used at a time. The default is normal. + +EXAMPLES +-------- +* Displays the get latency monitor log for the device: ++ +------------ +# nvme ocp latency-monitor-log /dev/nvme0 +------------ + +NVME +---- +Part of the nvme-user suite. diff --git a/Documentation/nvme-lnvm-diag-set-bbtbl.1 b/Documentation/nvme-ocp-smart-add-log.1 index d46ee65..3127edc 100644 --- a/Documentation/nvme-lnvm-diag-set-bbtbl.1 +++ b/Documentation/nvme-ocp-smart-add-log.1 @@ -1,13 +1,13 @@ '\" t -.\" Title: nvme-lnvm-diag-set-bbtbl +.\" Title: nvme-ocp-smart-add-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LNVM\-DIAG\-SE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-OCP\-SMART\-AD" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,49 +28,29 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -nvme-lnvm-diag-set-bbtbl \- Set a block state in the bad block table +nvme-ocp-smart-add-log \- Retrieves Extended SMART information of given OCP compliant device .SH "SYNOPSIS" .sp .nf -\fInvme lnvm\-diag\-set\-bbtbl\fR [\-\-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>] +\fInvme ocp smart\-add\-log\fR <device> [\-\-output\-format=<fmt> | \-o <fmt>] .fi .SH "DESCRIPTION" .sp -Set the bad block table for a given channel, lun, plane and block with value v\&. +For the NVMe device given, send a smart\-add\-log command and provide the additional smart log\&. .sp -For each block available, the status byte is read as follows: +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1)\&. .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 +This will only work on OCP compliant devices supporting this feature\&. Results for any other device are undefined\&. +.sp +On success it returns 0, error code otherwise\&. .SH "OPTIONS" .PP -\-\-namespace\-id=<NUM>, \-n <NUM> -.RS 4 -Namespace id to use -.RE -.PP -\-\-channel\-id, \-c +\-o <format>, \-\-output\-format=<format> .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 +Set the reporting format to +\fInormal\fR +or +\fIjson\fR\&. Only one output format can be used at a time\&. The default is normal\&. .RE .SH "EXAMPLES" .sp @@ -82,18 +62,18 @@ Block id .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 +Has the program issue a smart\-add\-log command to retrieve the 0xC0 log page\&. .sp .if n \{\ .RS 4 .\} .nf -# nvme lnvm\-diag\-set\-bbtbl /dev/nvme0 \-c 0 \-l 0 \-p 0 \-b 10 \-v 2 +# nvme ocp smart\-add\-log /dev/nvme0 .fi .if n \{\ .RE .\} +.RE .SH "NVME" .sp -Part of the nvme\-user suite +Part of the nvme\-user suite\&. diff --git a/Documentation/nvme-lnvm-id-ns.html b/Documentation/nvme-ocp-smart-add-log.html index b8898b6..baba251 100644 --- a/Documentation/nvme-lnvm-id-ns.html +++ b/Documentation/nvme-ocp-smart-add-log.html @@ -4,8 +4,8 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-id-ns(1)</title>
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-ocp-smart-add-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -735,12 +735,12 @@ asciidoc.install(); <body class="manpage">
<div id="header">
<h1>
-nvme-lnvm-id-ns(1) Manual Page
+nvme-ocp-smart-add-log(1) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>nvme-lnvm-id-ns -
- Identify Geometry for LightNVM NVMe device
+<p>nvme-ocp-smart-add-log -
+ Retrieves Extended SMART information of given OCP compliant device
</p>
</div>
</div>
@@ -749,10 +749,7 @@ nvme-lnvm-id-ns(1) Manual Page <h2 id="_synopsis">SYNOPSIS</h2>
<div class="sectionbody">
<div class="verseblock">
-<pre class="content"><em>nvme lnvm-id-ns</em> <device> [--namespace-id=<nsid> | -n <nsid>]
- [--force | -f]
- [--raw-binary | -b]
- [--human-readable | -H]</pre>
+<pre class="content"><em>nvme ocp smart-add-log</em> <device> [--output-format=<fmt> | -o <fmt>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -760,9 +757,13 @@ nvme-lnvm-id-ns(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Send an Identify Geometry command to the given LightNVM device, returns
-properties of the specified namespace in either human-readable or binary
-format.</p></div>
+<div class="paragraph"><p>For the NVMe device given, send a smart-add-log command and
+provide the additional smart log.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1).</p></div>
+<div class="paragraph"><p>This will only work on OCP compliant devices supporting this feature.
+Results for any other device are undefined.</p></div>
+<div class="paragraph"><p>On success it returns 0, error code otherwise.</p></div>
</div>
</div>
<div class="sect1">
@@ -770,47 +771,15 @@ format.</p></div> <div class="sectionbody">
<div class="dlist"><dl>
<dt class="hdlist1">
---namespace-id=<nsid>
+-o <format>
</dt>
<dt class="hdlist1">
--n <nsid>
+--output-format=<format>
</dt>
<dd>
<p>
- Retrieve the geometry from the selected namespace.
-</p>
-</dd>
-<dt class="hdlist1">
---force
-</dt>
-<dt class="hdlist1">
--f
-</dt>
-<dd>
-<p>
- Try to read the data and assume it is a LightNVM device
-</p>
-</dd>
-<dt class="hdlist1">
---raw-binary
-</dt>
-<dt class="hdlist1">
--b
-</dt>
-<dd>
-<p>
- Output the raw output
-</p>
-</dd>
-<dt class="hdlist1">
---human-readable
-</dt>
-<dt class="hdlist1">
--H
-</dt>
-<dd>
-<p>
- Output the status in human readable format
+ Set the reporting format to <em>normal</em> or <em>json</em>. Only one output format
+ can be used at a time. The default is normal.
</p>
</dd>
</dl></div>
@@ -822,20 +791,20 @@ format.</p></div> <div class="ulist"><ul>
<li>
<p>
-Retrieve the geometry from nvme0
+Has the program issue a smart-add-log command to retrieve the 0xC0 log page.
</p>
-</li>
-</ul></div>
<div class="listingblock">
<div class="content">
-<pre><code># nvme lnvm-id-ns /dev/nvme0 -n 1</code></pre>
+<pre><code># nvme ocp smart-add-log /dev/nvme0</code></pre>
</div></div>
+</li>
+</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_nvme">NVME</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Part of the nvme-user suite</p></div>
+<div class="paragraph"><p>Part of the nvme-user suite.</p></div>
</div>
</div>
</div>
@@ -843,7 +812,7 @@ Retrieve the geometry from nvme0 <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-ocp-smart-add-log.txt b/Documentation/nvme-ocp-smart-add-log.txt new file mode 100644 index 0000000..3a25822 --- /dev/null +++ b/Documentation/nvme-ocp-smart-add-log.txt @@ -0,0 +1,44 @@ +nvme-ocp-smart-add-log(1) +========================= + +NAME +---- +nvme-ocp-smart-add-log - Retrieves Extended SMART information of given OCP +compliant device + +SYNOPSIS +-------- +[verse] +'nvme ocp smart-add-log' <device> [--output-format=<fmt> | -o <fmt>] + +DESCRIPTION +----------- +For the NVMe device given, send a smart-add-log command and +provide the additional smart log. + +The <device> parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1). + +This will only work on OCP compliant devices supporting this feature. +Results for any other device are undefined. + +On success it returns 0, error code otherwise. + +OPTIONS +------- +-o <format>:: +--output-format=<format>:: + Set the reporting format to 'normal' or 'json'. Only one output format + can be used at a time. The default is normal. + +EXAMPLES +-------- +* Has the program issue a smart-add-log command to retrieve the 0xC0 log page. ++ +------------ +# nvme ocp smart-add-log /dev/nvme0 +------------ + +NVME +---- +Part of the nvme-user suite. diff --git a/Documentation/nvme-persistent-event-log.1 b/Documentation/nvme-persistent-event-log.1 index 653b657..de68633 100644 --- a/Documentation/nvme-persistent-event-log.1 +++ b/Documentation/nvme-persistent-event-log.1 @@ -2,12 +2,12 @@ .\" Title: persistent-event-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "PERSISTENT\-EVENT\-L" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "PERSISTENT\-EVENT\-L" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-persistent-event-log.html b/Documentation/nvme-persistent-event-log.html index 3f89c8e..cf519c5 100644 --- a/Documentation/nvme-persistent-event-log.html +++ b/Documentation/nvme-persistent-event-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>persistent-event-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -867,7 +867,7 @@ Print the raw persistent event log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-pred-lat-event-agg-log.1 b/Documentation/nvme-pred-lat-event-agg-log.1 index 1eab15e..5909b42 100644 --- a/Documentation/nvme-pred-lat-event-agg-log.1 +++ b/Documentation/nvme-pred-lat-event-agg-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-pred-lat-event-agg-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-PRED\-LAT\-EVE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-PRED\-LAT\-EVE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-pred-lat-event-agg-log.html b/Documentation/nvme-pred-lat-event-agg-log.html index d80a495..4b48e0f 100644 --- a/Documentation/nvme-pred-lat-event-agg-log.html +++ b/Documentation/nvme-pred-lat-event-agg-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-pred-lat-event-agg-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -863,7 +863,7 @@ Print the raw Predectible Latency Event Aggregate log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-predictable-lat-log.1 b/Documentation/nvme-predictable-lat-log.1 index 08b1f5c..1ea9159 100644 --- a/Documentation/nvme-predictable-lat-log.1 +++ b/Documentation/nvme-predictable-lat-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-predictable-lat-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-PREDICTABLE\-L" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-PREDICTABLE\-L" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-predictable-lat-log.html b/Documentation/nvme-predictable-lat-log.html index 08543d6..39f2dd6 100644 --- a/Documentation/nvme-predictable-lat-log.html +++ b/Documentation/nvme-predictable-lat-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-predictable-lat-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -850,7 +850,7 @@ Print the raw Predectible latency per NVM set log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-primary-ctrl-caps.1 b/Documentation/nvme-primary-ctrl-caps.1 index fe2593f..fc00e12 100644 --- a/Documentation/nvme-primary-ctrl-caps.1 +++ b/Documentation/nvme-primary-ctrl-caps.1 @@ -2,12 +2,12 @@ .\" Title: nvme-primary-ctrl-caps .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-PRIMARY\-CTRL\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-PRIMARY\-CTRL\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-primary-ctrl-caps.html b/Documentation/nvme-primary-ctrl-caps.html index b450507..e2a9270 100644 --- a/Documentation/nvme-primary-ctrl-caps.html +++ b/Documentation/nvme-primary-ctrl-caps.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-primary-ctrl-caps(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -835,7 +835,7 @@ fields in a human readable format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-read.1 b/Documentation/nvme-read.1 index ce21322..e490fce 100644 --- a/Documentation/nvme-read.1 +++ b/Documentation/nvme-read.1 @@ -2,12 +2,12 @@ .\" Title: nvme-read .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-READ" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-READ" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -51,6 +51,7 @@ nvme-read \- Send an NVMe Read command, provide results [\-\-dry\-run | \-w] [\-\-latency | \-t] [\-\-storage\-tag\-check<storage\-tag\-check> | \-C <storage\-tag\-check>] + [\-\-force] .fi .SH "DESCRIPTION" .sp @@ -159,7 +160,7 @@ Optional field for directive specifics\&. When used with write streams, this val .PP \-D <dsm>, \-\-dsm=<dsm> .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\&. +The optional data set management attributes for this command\&. The argument for this is the least significant 8 bits of the DSM field in a write command; the most significant 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 \-v, \-\-show\-cmd @@ -184,6 +185,11 @@ Print out the latency the IOCTL took (in us)\&. .RS 4 This bit specifies the Storage Tag field shall be checked as part of end\-to\-end data protection processing\&. .RE +.PP +\-\-force +.RS 4 +Ignore namespace is currently busy and perfome the operation even though\&. +.RE .SH "EXAMPLES" .sp No examples yet\&. diff --git a/Documentation/nvme-read.html b/Documentation/nvme-read.html index d61580c..f566ec4 100644 --- a/Documentation/nvme-read.html +++ b/Documentation/nvme-read.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-read(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -767,7 +767,8 @@ nvme-read(1) Manual Page [--show-command | -v]
[--dry-run | -w]
[--latency | -t]
- [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]</pre>
+ [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]
+ [--force]</pre>
<div class="attribution">
</div></div>
</div>
@@ -969,9 +970,9 @@ metadata is passes.</p></td> </dt>
<dd>
<p>
- 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
+ The optional data set management attributes for this command. The argument
+ for this is the least significant 8 bits of the DSM field in a write
+ command; the most significant 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
@@ -1026,6 +1027,15 @@ metadata is passes.</p></td> data protection processing.
</p>
</dd>
+<dt class="hdlist1">
+--force
+</dt>
+<dd>
+<p>
+ Ignore namespace is currently busy and perfome the operation
+ even though.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -1046,7 +1056,7 @@ metadata is passes.</p></td> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-09 14:16:42 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-read.txt b/Documentation/nvme-read.txt index 58902e7..8565431 100644 --- a/Documentation/nvme-read.txt +++ b/Documentation/nvme-read.txt @@ -27,6 +27,7 @@ SYNOPSIS [--dry-run | -w] [--latency | -t] [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>] + [--force] DESCRIPTION ----------- @@ -106,9 +107,9 @@ metadata is passes. -D <dsm>:: --dsm=<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 + The optional data set management attributes for this command. The argument + for this is the least significant 8 bits of the DSM field in a write + command; the most significant 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 @@ -134,6 +135,10 @@ metadata is passes. This bit specifies the Storage Tag field shall be checked as part of end-to-end data protection processing. +--force:: + Ignore namespace is currently busy and perfome the operation + even though. + EXAMPLES -------- No examples yet. diff --git a/Documentation/nvme-reset.1 b/Documentation/nvme-reset.1 index ee853c3..4736b90 100644 --- a/Documentation/nvme-reset.1 +++ b/Documentation/nvme-reset.1 @@ -2,12 +2,12 @@ .\" Title: nvme-reset .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-RESET" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-RESET" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-reset.html b/Documentation/nvme-reset.html index 66cd027..6169b9b 100644 --- a/Documentation/nvme-reset.html +++ b/Documentation/nvme-reset.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-reset(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -794,7 +794,7 @@ Resets the controller. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-resv-acquire.1 b/Documentation/nvme-resv-acquire.1 index 685ed66..bc8bb57 100644 --- a/Documentation/nvme-resv-acquire.1 +++ b/Documentation/nvme-resv-acquire.1 @@ -2,12 +2,12 @@ .\" Title: nvme-resv-acquire .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-RESV\-ACQUIRE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-RESV\-ACQUIRE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-resv-acquire.html b/Documentation/nvme-resv-acquire.html index 22b5ae8..59db28e 100644 --- a/Documentation/nvme-resv-acquire.html +++ b/Documentation/nvme-resv-acquire.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-resv-acquire(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -948,7 +948,7 @@ cellspacing="0" cellpadding="4"> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-resv-notif-log.1 b/Documentation/nvme-resv-notif-log.1 index a891af1..f877de2 100644 --- a/Documentation/nvme-resv-notif-log.1 +++ b/Documentation/nvme-resv-notif-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-resv-notif-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-RESV\-NOTIF\-L" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-RESV\-NOTIF\-L" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-resv-notif-log.html b/Documentation/nvme-resv-notif-log.html index 1a5ebb9..11e4c2b 100644 --- a/Documentation/nvme-resv-notif-log.html +++ b/Documentation/nvme-resv-notif-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-resv-notif-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -822,7 +822,7 @@ Print the output in json format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-resv-register.1 b/Documentation/nvme-resv-register.1 index 958f6d7..a41155c 100644 --- a/Documentation/nvme-resv-register.1 +++ b/Documentation/nvme-resv-register.1 @@ -2,12 +2,12 @@ .\" Title: nvme-resv-register .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-RESV\-REGISTER" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-RESV\-REGISTER" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-resv-register.html b/Documentation/nvme-resv-register.html index c18b2fa..4272b9a 100644 --- a/Documentation/nvme-resv-register.html +++ b/Documentation/nvme-resv-register.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-resv-register(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -937,7 +937,7 @@ cellspacing="0" cellpadding="4"> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-resv-release.1 b/Documentation/nvme-resv-release.1 index c7fa980..0079f31 100644 --- a/Documentation/nvme-resv-release.1 +++ b/Documentation/nvme-resv-release.1 @@ -2,12 +2,12 @@ .\" Title: nvme-resv-release .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-RESV\-RELEASE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-RESV\-RELEASE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-resv-release.html b/Documentation/nvme-resv-release.html index 31c4171..821f709 100644 --- a/Documentation/nvme-resv-release.html +++ b/Documentation/nvme-resv-release.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-resv-release(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -930,7 +930,7 @@ cellspacing="0" cellpadding="4"> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-resv-report.1 b/Documentation/nvme-resv-report.1 index c9f7ff9..c197522 100644 --- a/Documentation/nvme-resv-report.1 +++ b/Documentation/nvme-resv-report.1 @@ -2,12 +2,12 @@ .\" Title: nvme-resv-report .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-RESV\-REPORT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-RESV\-REPORT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -34,7 +34,7 @@ nvme-resv-report \- Send NVMe Reservation Report, parse the result .nf \fInvme resv\-report\fR <device> [\-\-namespace\-id=<nsid> | \-n <nsid>] [\-\-numd=<num\-dwords> | \-d <num\-dwords>] - [\-\-cdw11=<cdw11> | \-c <cdw11>] + [\-\-eds | \-e] [\-\-raw\-binary | \-b] [\-\-output\-format=<fmt> | \-o <fmt>] .fi @@ -55,9 +55,10 @@ Retrieve the reservation report structure for the given nsid\&. This is required Specify the number of Dwords of the Reservation Status structure to transfer\&. Defaults to 4k\&. .RE .PP -\-c <cdw11>, \-\-cdw11=<cdw11> +\-e, \-\-eds .RS 4 -The value for command dword 11\&. Setting bit 0 specifies that the controller returns the Extended Data Structure\&. +Request extended Data Structure: If this bit is set to a +\fI1\fR, then the controller returns the Extended Data Structure\&. .RE .PP \-b, \-\-raw\-binary diff --git a/Documentation/nvme-resv-report.html b/Documentation/nvme-resv-report.html index 83655ae..5d31be9 100644 --- a/Documentation/nvme-resv-report.html +++ b/Documentation/nvme-resv-report.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-resv-report(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -751,7 +751,7 @@ nvme-resv-report(1) Manual Page <div class="verseblock">
<pre class="content"><em>nvme resv-report</em> <device> [--namespace-id=<nsid> | -n <nsid>]
[--numd=<num-dwords> | -d <num-dwords>]
- [--cdw11=<cdw11> | -c <cdw11>]
+ [--eds | -e]
[--raw-binary | -b]
[--output-format=<fmt> | -o <fmt>]</pre>
<div class="attribution">
@@ -800,14 +800,14 @@ Controller data structure for each such controller).</p></div> </p>
</dd>
<dt class="hdlist1">
--c <cdw11>
+-e
</dt>
<dt class="hdlist1">
---cdw11=<cdw11>
+--eds
</dt>
<dd>
<p>
- The value for command dword 11. Setting bit 0 specifies that the
+ Request extended Data Structure: If this bit is set to a <em>1</em>, then the
controller returns the Extended Data Structure.
</p>
</dd>
@@ -855,7 +855,7 @@ Controller data structure for each such controller).</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2020-06-08 08:31:26 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-resv-report.txt b/Documentation/nvme-resv-report.txt index b53c141..32012fe 100644 --- a/Documentation/nvme-resv-report.txt +++ b/Documentation/nvme-resv-report.txt @@ -10,7 +10,7 @@ SYNOPSIS [verse] 'nvme resv-report' <device> [--namespace-id=<nsid> | -n <nsid>] [--numd=<num-dwords> | -d <num-dwords>] - [--cdw11=<cdw11> | -c <cdw11>] + [--eds | -e] [--raw-binary | -b] [--output-format=<fmt> | -o <fmt>] @@ -38,9 +38,9 @@ OPTIONS 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 +-e:: +--eds:: + Request extended Data Structure: If this bit is set to a '1', then the controller returns the Extended Data Structure. -b:: diff --git a/Documentation/nvme-rpmb.1 b/Documentation/nvme-rpmb.1 index bde629b..f34805e 100644 --- a/Documentation/nvme-rpmb.1 +++ b/Documentation/nvme-rpmb.1 @@ -2,12 +2,12 @@ .\" Title: nvme-rpmb .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-RPMB" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-RPMB" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-rpmb.html b/Documentation/nvme-rpmb.html index 612a60e..c63a1e7 100644 --- a/Documentation/nvme-rpmb.html +++ b/Documentation/nvme-rpmb.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-rpmb(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -1001,7 +1001,7 @@ data onto output.bin <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-sanitize-log.1 b/Documentation/nvme-sanitize-log.1 index cb5788d..f83eecc 100644 --- a/Documentation/nvme-sanitize-log.1 +++ b/Documentation/nvme-sanitize-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-sanitize-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SANITIZE\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SANITIZE\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-sanitize-log.html b/Documentation/nvme-sanitize-log.html index bf04741..c000a71 100644 --- a/Documentation/nvme-sanitize-log.html +++ b/Documentation/nvme-sanitize-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-sanitize-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -892,7 +892,7 @@ Has the program issue Sanitize-log Command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-sanitize.1 b/Documentation/nvme-sanitize.1 index 2953af7..55d225a 100644 --- a/Documentation/nvme-sanitize.1 +++ b/Documentation/nvme-sanitize.1 @@ -2,12 +2,12 @@ .\" Title: nvme-sanitize .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SANITIZE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SANITIZE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -38,6 +38,7 @@ nvme-sanitize \- Send NVMe Sanitize Command, return result [\-\-ause | \-u] [\-\-sanact=<action> | \-a <action>] [\-\-ovrpat=<overwrite\-pattern> | \-p <overwrite\-pattern>] + [\-\-force] .fi .SH "DESCRIPTION" .sp @@ -77,6 +78,11 @@ Sanitize Action: 000b \- Reserved 001b \- Exit Failure Mode 010b \- Start a Bloc .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 +.PP +\-\-force +.RS 4 +Ignore namespace is currently busy and perfome the operation even though\&. +.RE .SH "EXAMPLES" .sp .RS 4 diff --git a/Documentation/nvme-sanitize.html b/Documentation/nvme-sanitize.html index 325fdf7..a865b1b 100644 --- a/Documentation/nvme-sanitize.html +++ b/Documentation/nvme-sanitize.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-sanitize(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -754,7 +754,8 @@ nvme-sanitize(1) Manual Page [--owpass=<overwrite-pass-count> | -n <overwrite-pass-count>]
[--ause | -u]
[--sanact=<action> | -a <action>]
- [--ovrpat=<overwrite-pattern> | -p <overwrite-pattern>]</pre>
+ [--ovrpat=<overwrite-pattern> | -p <overwrite-pattern>]
+ [--force]</pre>
<div class="attribution">
</div></div>
</div>
@@ -866,6 +867,15 @@ provides the result.</p></div> sanitize operation.
</p>
</dd>
+<dt class="hdlist1">
+--force
+</dt>
+<dd>
+<p>
+ Ignore namespace is currently busy and perfome the operation
+ even though.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -897,7 +907,7 @@ Has the program issue Sanitize Command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-sanitize.txt b/Documentation/nvme-sanitize.txt index b1d9a0e..be489d3 100644 --- a/Documentation/nvme-sanitize.txt +++ b/Documentation/nvme-sanitize.txt @@ -14,6 +14,7 @@ SYNOPSIS [--ause | -u] [--sanact=<action> | -a <action>] [--ovrpat=<overwrite-pattern> | -p <overwrite-pattern>] + [--force] DESCRIPTION ----------- @@ -78,6 +79,10 @@ OPTIONS specifies a 32-bit pattern that is used for the Overwrite sanitize operation. +--force:: + Ignore namespace is currently busy and perfome the operation + even though. + EXAMPLES -------- * Has the program issue Sanitize Command : diff --git a/Documentation/nvme-security-recv.1 b/Documentation/nvme-security-recv.1 index 3c17f75..7ac143d 100644 --- a/Documentation/nvme-security-recv.1 +++ b/Documentation/nvme-security-recv.1 @@ -2,12 +2,12 @@ .\" Title: nvme-security-recv .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SECURITY\-RECV" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SECURITY\-RECV" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-security-recv.html b/Documentation/nvme-security-recv.html index 1614c8f..a575aa0 100644 --- a/Documentation/nvme-security-recv.html +++ b/Documentation/nvme-security-recv.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-security-recv(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -886,7 +886,7 @@ controller reset occurs.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-security-send.1 b/Documentation/nvme-security-send.1 index 5ee8dba..8f9c2ee 100644 --- a/Documentation/nvme-security-send.1 +++ b/Documentation/nvme-security-send.1 @@ -2,12 +2,12 @@ .\" Title: nvme-security-send .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SECURITY\-SEND" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SECURITY\-SEND" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-security-send.html b/Documentation/nvme-security-send.html index 6df7879..9b050ec 100644 --- a/Documentation/nvme-security-send.html +++ b/Documentation/nvme-security-send.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-security-send(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -872,7 +872,7 @@ Receive command is Security Protocol field dependent as defined in SPC-4.</p></d <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-self-test-log.1 b/Documentation/nvme-self-test-log.1 index 8296aad..b077943 100644 --- a/Documentation/nvme-self-test-log.1 +++ b/Documentation/nvme-self-test-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-self-test-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SELF\-TEST\-LO" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SELF\-TEST\-LO" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-self-test-log.html b/Documentation/nvme-self-test-log.html index f90c8ee..f45495e 100644 --- a/Documentation/nvme-self-test-log.html +++ b/Documentation/nvme-self-test-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-self-test-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -847,7 +847,7 @@ Get the self-test-log and print it in a json format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-set-feature.1 b/Documentation/nvme-set-feature.1 index f37ef0b..c589ee2 100644 --- a/Documentation/nvme-set-feature.1 +++ b/Documentation/nvme-set-feature.1 @@ -2,12 +2,12 @@ .\" Title: nvme-set-feature .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SET\-FEATURE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SET\-FEATURE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-set-feature.html b/Documentation/nvme-set-feature.html index 56c31f1..a2ae2ec 100644 --- a/Documentation/nvme-set-feature.html +++ b/Documentation/nvme-set-feature.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-set-feature(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -899,7 +899,7 @@ Sets the host id to the ascii string. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-set-property.1 b/Documentation/nvme-set-property.1 index 83fb20a..ec7c48f 100644 --- a/Documentation/nvme-set-property.1 +++ b/Documentation/nvme-set-property.1 @@ -2,12 +2,12 @@ .\" Title: nvme-set-property .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SET\-PROPERTY" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SET\-PROPERTY" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-set-property.html b/Documentation/nvme-set-property.html index 5da9a9e..973d9c3 100644 --- a/Documentation/nvme-set-property.html +++ b/Documentation/nvme-set-property.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-set-property(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -805,7 +805,7 @@ nvme-set-property(1) Manual Page <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-show-hostnqn.1 b/Documentation/nvme-show-hostnqn.1 index c9ad4fd..0b0b8eb 100644 --- a/Documentation/nvme-show-hostnqn.1 +++ b/Documentation/nvme-show-hostnqn.1 @@ -2,12 +2,12 @@ .\" Title: nvme-show-hostnqn .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SHOW\-HOSTNQN" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SHOW\-HOSTNQN" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-show-hostnqn.html b/Documentation/nvme-show-hostnqn.html index 49ccd32..3169bf3 100644 --- a/Documentation/nvme-show-hostnqn.html +++ b/Documentation/nvme-show-hostnqn.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-show-hostnqn(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -785,7 +785,7 @@ this will show the systemd-generated host NQN for the system.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-show-hostnqn.txt b/Documentation/nvme-show-hostnqn.txt index 044346c..58263d8 100644 --- a/Documentation/nvme-show-hostnqn.txt +++ b/Documentation/nvme-show-hostnqn.txt @@ -12,7 +12,7 @@ SYNOPSIS DESCRIPTION ----------- -Show the host NQN configured for the system. If /etc/nvme/hostnqn is +Show the host NQN configured for the system. If @SYSCONFDIR@/nvme/hostnqn is not present and systemd application-specific machine IDs are available, this will show the systemd-generated host NQN for the system. diff --git a/Documentation/nvme-show-regs.1 b/Documentation/nvme-show-regs.1 index 02e571f..ba4ac20 100644 --- a/Documentation/nvme-show-regs.1 +++ b/Documentation/nvme-show-regs.1 @@ -2,12 +2,12 @@ .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ID\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ID\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-show-regs.html b/Documentation/nvme-show-regs.html index 74f43fb..c3cc58c 100644 --- a/Documentation/nvme-show-regs.html +++ b/Documentation/nvme-show-regs.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-id-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -848,7 +848,7 @@ in a json format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-smart-log.1 b/Documentation/nvme-smart-log.1 index 4b2a3e3..20fe8d3 100644 --- a/Documentation/nvme-smart-log.1 +++ b/Documentation/nvme-smart-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-smart-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SMART\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SMART\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-smart-log.html b/Documentation/nvme-smart-log.html index f105d5b..f188a08 100644 --- a/Documentation/nvme-smart-log.html +++ b/Documentation/nvme-smart-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-smart-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -850,7 +850,7 @@ Print the raw SMART log to a file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-subsystem-reset.1 b/Documentation/nvme-subsystem-reset.1 index 544f467..929b87b 100644 --- a/Documentation/nvme-subsystem-reset.1 +++ b/Documentation/nvme-subsystem-reset.1 @@ -2,12 +2,12 @@ .\" Title: nvme-subsystem-reset .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SUBSYSTEM\-RES" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SUBSYSTEM\-RES" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-subsystem-reset.html b/Documentation/nvme-subsystem-reset.html index facfcb6..0d59265 100644 --- a/Documentation/nvme-subsystem-reset.html +++ b/Documentation/nvme-subsystem-reset.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-subsystem-reset(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -794,7 +794,7 @@ Resets the subsystem. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-supported-cap-config-log.txt b/Documentation/nvme-supported-cap-config-log.txt new file mode 100644 index 0000000..0050634 --- /dev/null +++ b/Documentation/nvme-supported-cap-config-log.txt @@ -0,0 +1,49 @@ +nvme-supported-cap-config-log(1) +================================ + +NAME +---- +nvme-supported-cap-config-log - Send NVMe Supported Capacity +Configuration List Log pages request, returns result and log. + +SYNOPSIS +-------- +[verse] +'nvme supported-cap-config-log' <device> [--dom-id | -d ] + [--output-format=<fmt> | -o <fmt>] + [--raw-binary | -b] + +DESCRIPTION +----------- +Retrieves the list of Supported Capacity Configuration List +log pages details from an NVMe device and provides +the returned structure. + +The <device> parameter is mandatory and should be the NVMe character +device (ex: /dev/nvme0). + +On success, the returned Supported Capacity Configuration List log +pages log structure will be printed. + +OPTIONS +------- + +-o <format>:: +--output-format=<format>:: + This option will set the reporting format to normal, json, or binary. + Only one output format can be used at a time. + +-d:: +--dom-id:: + To get the domain ID. +-b:: +--raw-binary:: + To show raw binary data. + +EXAMPLES +-------- +No examples provided yet. + +NVME +---- +Part of the nvme-user suite
\ No newline at end of file diff --git a/Documentation/nvme-supported-log-pages.1 b/Documentation/nvme-supported-log-pages.1 index 812891c..e20ddcd 100644 --- a/Documentation/nvme-supported-log-pages.1 +++ b/Documentation/nvme-supported-log-pages.1 @@ -2,12 +2,12 @@ .\" Title: nvme-supported-log-pages .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-SUPPORTED\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-SUPPORTED\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-supported-log-pages.html b/Documentation/nvme-supported-log-pages.html index b64a635..1a3e835 100644 --- a/Documentation/nvme-supported-log-pages.html +++ b/Documentation/nvme-supported-log-pages.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-supported-log-pages(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -814,7 +814,7 @@ for each command that is supported.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-08-13 22:37:48 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-telemetry-log.1 b/Documentation/nvme-telemetry-log.1 index 6260023..61fb031 100644 --- a/Documentation/nvme-telemetry-log.1 +++ b/Documentation/nvme-telemetry-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-telemetry-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-TELEMETRY\-LOG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-TELEMETRY\-LOG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-telemetry-log.html b/Documentation/nvme-telemetry-log.html index 4242a98..e1ed7bf 100644 --- a/Documentation/nvme-telemetry-log.html +++ b/Documentation/nvme-telemetry-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-telemetry-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -838,7 +838,7 @@ Retrieve Telemetry Host-Initiated data to telemetry_log.bin <div id="footer">
<div id="footer-text">
Last updated
- 2021-11-11 13:06:55 PST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-toshiba-clear-pcie-correctable-errors.1 b/Documentation/nvme-toshiba-clear-pcie-correctable-errors.1 index a9c0f1a..2ba9696 100644 --- a/Documentation/nvme-toshiba-clear-pcie-correctable-errors.1 +++ b/Documentation/nvme-toshiba-clear-pcie-correctable-errors.1 @@ -2,12 +2,12 @@ .\" Title: nvme-toshiba-clear-pcie-correctable-errors .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-TOSHIBA\-CLEAR" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-TOSHIBA\-CLEAR" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-toshiba-clear-pcie-correctable-errors.html b/Documentation/nvme-toshiba-clear-pcie-correctable-errors.html index a712b3c..95f86a2 100644 --- a/Documentation/nvme-toshiba-clear-pcie-correctable-errors.html +++ b/Documentation/nvme-toshiba-clear-pcie-correctable-errors.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-toshiba-clear-pcie-correctable-errors(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -791,7 +791,7 @@ Clear the PCIe correctable errors count: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-toshiba-vs-internal-log.1 b/Documentation/nvme-toshiba-vs-internal-log.1 index 045d45a..5f05051 100644 --- a/Documentation/nvme-toshiba-vs-internal-log.1 +++ b/Documentation/nvme-toshiba-vs-internal-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-toshiba-vs-internal-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-TOSHIBA\-VS\-I" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-TOSHIBA\-VS\-I" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-toshiba-vs-internal-log.html b/Documentation/nvme-toshiba-vs-internal-log.html index 87da386..0d5057f 100644 --- a/Documentation/nvme-toshiba-vs-internal-log.html +++ b/Documentation/nvme-toshiba-vs-internal-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-toshiba-vs-internal-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -837,7 +837,7 @@ Get the previous log from the device and save to a binary file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-toshiba-vs-smart-add-log.1 b/Documentation/nvme-toshiba-vs-smart-add-log.1 index 3926292..af72552 100644 --- a/Documentation/nvme-toshiba-vs-smart-add-log.1 +++ b/Documentation/nvme-toshiba-vs-smart-add-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-toshiba-vs-smart-add-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-TOSHIBA\-VS\-S" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-TOSHIBA\-VS\-S" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-toshiba-vs-smart-add-log.html b/Documentation/nvme-toshiba-vs-smart-add-log.html index 3fd4c48..60acc5b 100644 --- a/Documentation/nvme-toshiba-vs-smart-add-log.html +++ b/Documentation/nvme-toshiba-vs-smart-add-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-toshiba-vs-smart-add-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -840,7 +840,7 @@ Get the contents of log page 0xC0 from the device and save to a binary file: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-transcend-badblock.1 b/Documentation/nvme-transcend-badblock.1 index ac89e68..9999285 100644 --- a/Documentation/nvme-transcend-badblock.1 +++ b/Documentation/nvme-transcend-badblock.1 @@ -2,12 +2,12 @@ .\" Title: nvme-transcend-badblock .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-TRANSCEND\-BAD" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-TRANSCEND\-BAD" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-transcend-badblock.html b/Documentation/nvme-transcend-badblock.html index df693ed..df647c9 100644 --- a/Documentation/nvme-transcend-badblock.html +++ b/Documentation/nvme-transcend-badblock.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-transcend-badblock(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -796,7 +796,7 @@ Print the Transcend device’s bad blocks in a human readable format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-transcend-healthvalue.1 b/Documentation/nvme-transcend-healthvalue.1 index 1af5eaa..6079016 100644 --- a/Documentation/nvme-transcend-healthvalue.1 +++ b/Documentation/nvme-transcend-healthvalue.1 @@ -2,12 +2,12 @@ .\" Title: nvme-transcend-healthvalue .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-TRANSCEND\-HEA" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-TRANSCEND\-HEA" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-transcend-healthvalue.html b/Documentation/nvme-transcend-healthvalue.html index f2841c2..07f1df2 100644 --- a/Documentation/nvme-transcend-healthvalue.html +++ b/Documentation/nvme-transcend-healthvalue.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-transcend-healthvalue(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -796,7 +796,7 @@ Print the Transcend Device health value in a human readable format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-verify.1 b/Documentation/nvme-verify.1 index 6a6d0f7..be3caf1 100644 --- a/Documentation/nvme-verify.1 +++ b/Documentation/nvme-verify.1 @@ -2,12 +2,12 @@ .\" Title: nvme-verify .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-VERIFY" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-VERIFY" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-verify.html b/Documentation/nvme-verify.html index 3567ec4..634b44e 100644 --- a/Documentation/nvme-verify.html +++ b/Documentation/nvme-verify.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-verify(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -954,7 +954,7 @@ metadata is passes.</p></td> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-09 13:43:04 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-virtium-save-smart-to-vtview-log.1 b/Documentation/nvme-virtium-save-smart-to-vtview-log.1 index e4025d8..f3f61dd 100644 --- a/Documentation/nvme-virtium-save-smart-to-vtview-log.1 +++ b/Documentation/nvme-virtium-save-smart-to-vtview-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-virtium-save-smart-to-vtview-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-VIRTIUM\-SAVE\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-VIRTIUM\-SAVE\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-virtium-save-smart-to-vtview-log.html b/Documentation/nvme-virtium-save-smart-to-vtview-log.html index 7447c38..d6b24dd 100644 --- a/Documentation/nvme-virtium-save-smart-to-vtview-log.html +++ b/Documentation/nvme-virtium-save-smart-to-vtview-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-virtium-save-smart-to-vtview-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -876,7 +876,7 @@ Just logging: Default logging is run for 20 hours and log every 10 hours. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-virtium-show-identify.1 b/Documentation/nvme-virtium-show-identify.1 index d9ae5c4..9fc5b43 100644 --- a/Documentation/nvme-virtium-show-identify.1 +++ b/Documentation/nvme-virtium-show-identify.1 @@ -2,12 +2,12 @@ .\" Title: nvme-virtium-show-identify .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-VIRTIUM\-SHOW\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-VIRTIUM\-SHOW\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-virtium-show-identify.html b/Documentation/nvme-virtium-show-identify.html index 9204010..519dcd3 100644 --- a/Documentation/nvme-virtium-show-identify.html +++ b/Documentation/nvme-virtium-show-identify.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-virtium-show-identify(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -798,7 +798,7 @@ Show Identify Device: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-cap-diag.1 b/Documentation/nvme-wdc-cap-diag.1 index c7b27bd..1fbd6da 100644 --- a/Documentation/nvme-wdc-cap-diag.1 +++ b/Documentation/nvme-wdc-cap-diag.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-cap-diag .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-CAP\-DIAG" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-CAP\-DIAG" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-cap-diag.html b/Documentation/nvme-wdc-cap-diag.html index 11d85b3..e34dbd4 100644 --- a/Documentation/nvme-wdc-cap-diag.html +++ b/Documentation/nvme-wdc-cap-diag.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-cap-diag(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -856,7 +856,7 @@ Gets the capture diagnostics log from the device transferring the data in 16k ch <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-capabilities.1 b/Documentation/nvme-wdc-capabilities.1 index d24593b..a32938b 100644 --- a/Documentation/nvme-wdc-capabilities.1 +++ b/Documentation/nvme-wdc-capabilities.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-capabilities .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-CAPABILIT" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-CAPABILIT" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-capabilities.html b/Documentation/nvme-wdc-capabilities.html index 8588ab6..549b752 100644 --- a/Documentation/nvme-wdc-capabilities.html +++ b/Documentation/nvme-wdc-capabilities.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-capabilities(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -789,7 +789,7 @@ Displays the capabilities for the device: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-clear-assert-dump.1 b/Documentation/nvme-wdc-clear-assert-dump.1 index 9ede44a..2b03142 100644 --- a/Documentation/nvme-wdc-clear-assert-dump.1 +++ b/Documentation/nvme-wdc-clear-assert-dump.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-clear-assert-dump .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-CLEAR\-AS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-CLEAR\-AS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-clear-assert-dump.html b/Documentation/nvme-wdc-clear-assert-dump.html index df642bf..5325d97 100644 --- a/Documentation/nvme-wdc-clear-assert-dump.html +++ b/Documentation/nvme-wdc-clear-assert-dump.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-clear-assert-dump(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -798,7 +798,7 @@ Clears the assert dump (if present): <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-clear-fw-activate-history.1 b/Documentation/nvme-wdc-clear-fw-activate-history.1 index 9808756..43b8a62 100644 --- a/Documentation/nvme-wdc-clear-fw-activate-history.1 +++ b/Documentation/nvme-wdc-clear-fw-activate-history.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-clear-fw-activate-history .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-CLEAR\-FW" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-CLEAR\-FW" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-clear-fw-activate-history.html b/Documentation/nvme-wdc-clear-fw-activate-history.html index 47f9bd6..eec9b96 100644 --- a/Documentation/nvme-wdc-clear-fw-activate-history.html +++ b/Documentation/nvme-wdc-clear-fw-activate-history.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-clear-fw-activate-history(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -797,7 +797,7 @@ Clears the firmware activate history table: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-lnvm-id-ns.1 b/Documentation/nvme-wdc-clear-pcie-corr.1 index 32e7029..6e5989d 100644 --- a/Documentation/nvme-lnvm-id-ns.1 +++ b/Documentation/nvme-wdc-clear-pcie-corr.1 @@ -1,13 +1,13 @@ '\" t -.\" Title: nvme-lnvm-id-ns +.\" Title: nvme-wdc-clear-pcie-corr .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 01/08/2019 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LNVM\-ID\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-CLEAR\-PC" "1" "01/08/2019" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,39 +28,22 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -nvme-lnvm-id-ns \- Identify Geometry for LightNVM NVMe device +nvme-wdc-clear-pcie-corr \- Clears the pcie correctable errors field returned in the smart\-log\-add command\&. .SH "SYNOPSIS" .sp .nf -\fInvme lnvm\-id\-ns\fR <device> [\-\-namespace\-id=<nsid> | \-n <nsid>] - [\-\-force | \-f] - [\-\-raw\-binary | \-b] - [\-\-human\-readable | \-H] +\fInvme wdc clear\-pcie\-corr\fR <device> .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\&. +For the NVMe device given, sends the wdc vendor unique clear pcie correctable errors command\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. +.sp +This will only work on WDC devices supporting this feature\&. Results for any other device are undefined\&. .SH "OPTIONS" -.PP -\-\-namespace\-id=<nsid>, \-n <nsid> -.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 +.sp +None .SH "EXAMPLES" .sp .RS 4 @@ -71,18 +54,18 @@ Output the status in human readable format .sp -1 .IP \(bu 2.3 .\} -Retrieve the geometry from nvme0 -.RE +Clears the PCIe Correctable Error Count field returned in the smart\-log\-add command: .sp .if n \{\ .RS 4 .\} .nf -# nvme lnvm\-id\-ns /dev/nvme0 \-n 1 +# nvme wdc clear\-pcie\-corr /dev/nvme0 .fi .if n \{\ .RE .\} +.RE .SH "NVME" .sp Part of the nvme\-user suite diff --git a/Documentation/nvme-lnvm-list.html b/Documentation/nvme-wdc-clear-pcie-corr.html index 3126af7..3e8a4a9 100644 --- a/Documentation/nvme-lnvm-list.html +++ b/Documentation/nvme-wdc-clear-pcie-corr.html @@ -1,790 +1,806 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
- "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-list(1)</title>
-<style type="text/css">
-/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
-
-/* Default font. */
-body {
- font-family: Georgia,serif;
-}
-
-/* Title font. */
-h1, h2, h3, h4, h5, h6,
-div.title, caption.title,
-thead, p.table.header,
-#toctitle,
-#author, #revnumber, #revdate, #revremark,
-#footer {
- font-family: Arial,Helvetica,sans-serif;
-}
-
-body {
- margin: 1em 5% 1em 5%;
-}
-
-a {
- color: blue;
- text-decoration: underline;
-}
-a:visited {
- color: fuchsia;
-}
-
-em {
- font-style: italic;
- color: navy;
-}
-
-strong {
- font-weight: bold;
- color: #083194;
-}
-
-h1, h2, h3, h4, h5, h6 {
- color: #527bbd;
- margin-top: 1.2em;
- margin-bottom: 0.5em;
- line-height: 1.3;
-}
-
-h1, h2, h3 {
- border-bottom: 2px solid silver;
-}
-h2 {
- padding-top: 0.5em;
-}
-h3 {
- float: left;
-}
-h3 + * {
- clear: left;
-}
-h5 {
- font-size: 1.0em;
-}
-
-div.sectionbody {
- margin-left: 0;
-}
-
-hr {
- border: 1px solid silver;
-}
-
-p {
- margin-top: 0.5em;
- margin-bottom: 0.5em;
-}
-
-ul, ol, li > p {
- margin-top: 0;
-}
-ul > li { color: #aaa; }
-ul > li > * { color: black; }
-
-.monospaced, code, pre {
- font-family: "Courier New", Courier, monospace;
- font-size: inherit;
- color: navy;
- padding: 0;
- margin: 0;
-}
-pre {
- white-space: pre-wrap;
-}
-
-#author {
- color: #527bbd;
- font-weight: bold;
- font-size: 1.1em;
-}
-#email {
-}
-#revnumber, #revdate, #revremark {
-}
-
-#footer {
- font-size: small;
- border-top: 2px solid silver;
- padding-top: 0.5em;
- margin-top: 4.0em;
-}
-#footer-text {
- float: left;
- padding-bottom: 0.5em;
-}
-#footer-badges {
- float: right;
- padding-bottom: 0.5em;
-}
-
-#preamble {
- margin-top: 1.5em;
- margin-bottom: 1.5em;
-}
-div.imageblock, div.exampleblock, div.verseblock,
-div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
-div.admonitionblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-div.admonitionblock {
- margin-top: 2.0em;
- margin-bottom: 2.0em;
- margin-right: 10%;
- color: #606060;
-}
-
-div.content { /* Block element content. */
- padding: 0;
-}
-
-/* Block element titles. */
-div.title, caption.title {
- color: #527bbd;
- font-weight: bold;
- text-align: left;
- margin-top: 1.0em;
- margin-bottom: 0.5em;
-}
-div.title + * {
- margin-top: 0;
-}
-
-td div.title:first-child {
- margin-top: 0.0em;
-}
-div.content div.title:first-child {
- margin-top: 0.0em;
-}
-div.content + div.title {
- margin-top: 0.0em;
-}
-
-div.sidebarblock > div.content {
- background: #ffffee;
- border: 1px solid #dddddd;
- border-left: 4px solid #f0f0f0;
- padding: 0.5em;
-}
-
-div.listingblock > div.content {
- border: 1px solid #dddddd;
- border-left: 5px solid #f0f0f0;
- background: #f8f8f8;
- padding: 0.5em;
-}
-
-div.quoteblock, div.verseblock {
- padding-left: 1.0em;
- margin-left: 1.0em;
- margin-right: 10%;
- border-left: 5px solid #f0f0f0;
- color: #888;
-}
-
-div.quoteblock > div.attribution {
- padding-top: 0.5em;
- text-align: right;
-}
-
-div.verseblock > pre.content {
- font-family: inherit;
- font-size: inherit;
-}
-div.verseblock > div.attribution {
- padding-top: 0.75em;
- text-align: left;
-}
-/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
-div.verseblock + div.attribution {
- text-align: left;
-}
-
-div.admonitionblock .icon {
- vertical-align: top;
- font-size: 1.1em;
- font-weight: bold;
- text-decoration: underline;
- color: #527bbd;
- padding-right: 0.5em;
-}
-div.admonitionblock td.content {
- padding-left: 0.5em;
- border-left: 3px solid #dddddd;
-}
-
-div.exampleblock > div.content {
- border-left: 3px solid #dddddd;
- padding-left: 0.5em;
-}
-
-div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; vertical-align: text-bottom; }
-a.image:visited { color: white; }
-
-dl {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-dt {
- margin-top: 0.5em;
- margin-bottom: 0;
- font-style: normal;
- color: navy;
-}
-dd > *:first-child {
- margin-top: 0.1em;
-}
-
-ul, ol {
- list-style-position: outside;
-}
-ol.arabic {
- list-style-type: decimal;
-}
-ol.loweralpha {
- list-style-type: lower-alpha;
-}
-ol.upperalpha {
- list-style-type: upper-alpha;
-}
-ol.lowerroman {
- list-style-type: lower-roman;
-}
-ol.upperroman {
- list-style-type: upper-roman;
-}
-
-div.compact ul, div.compact ol,
-div.compact p, div.compact p,
-div.compact div, div.compact div {
- margin-top: 0.1em;
- margin-bottom: 0.1em;
-}
-
-tfoot {
- font-weight: bold;
-}
-td > div.verse {
- white-space: pre;
-}
-
-div.hdlist {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-div.hdlist tr {
- padding-bottom: 15px;
-}
-dt.hdlist1.strong, td.hdlist1.strong {
- font-weight: bold;
-}
-td.hdlist1 {
- vertical-align: top;
- font-style: normal;
- padding-right: 0.8em;
- color: navy;
-}
-td.hdlist2 {
- vertical-align: top;
-}
-div.hdlist.compact tr {
- margin: 0;
- padding-bottom: 0;
-}
-
-.comment {
- background: yellow;
-}
-
-.footnote, .footnoteref {
- font-size: 0.8em;
-}
-
-span.footnote, span.footnoteref {
- vertical-align: super;
-}
-
-#footnotes {
- margin: 20px 0 20px 0;
- padding: 7px 0 0 0;
-}
-
-#footnotes div.footnote {
- margin: 0 0 5px 0;
-}
-
-#footnotes hr {
- border: none;
- border-top: 1px solid silver;
- height: 1px;
- text-align: left;
- margin-left: 0;
- width: 20%;
- min-width: 100px;
-}
-
-div.colist td {
- padding-right: 0.5em;
- padding-bottom: 0.3em;
- vertical-align: top;
-}
-div.colist td img {
- margin-top: 0.3em;
-}
-
-@media print {
- #footer-badges { display: none; }
-}
-
-#toc {
- margin-bottom: 2.5em;
-}
-
-#toctitle {
- color: #527bbd;
- font-size: 1.1em;
- font-weight: bold;
- margin-top: 1.0em;
- margin-bottom: 0.1em;
-}
-
-div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
- margin-top: 0;
- margin-bottom: 0;
-}
-div.toclevel2 {
- margin-left: 2em;
- font-size: 0.9em;
-}
-div.toclevel3 {
- margin-left: 4em;
- font-size: 0.9em;
-}
-div.toclevel4 {
- margin-left: 6em;
- font-size: 0.9em;
-}
-
-span.aqua { color: aqua; }
-span.black { color: black; }
-span.blue { color: blue; }
-span.fuchsia { color: fuchsia; }
-span.gray { color: gray; }
-span.green { color: green; }
-span.lime { color: lime; }
-span.maroon { color: maroon; }
-span.navy { color: navy; }
-span.olive { color: olive; }
-span.purple { color: purple; }
-span.red { color: red; }
-span.silver { color: silver; }
-span.teal { color: teal; }
-span.white { color: white; }
-span.yellow { color: yellow; }
-
-span.aqua-background { background: aqua; }
-span.black-background { background: black; }
-span.blue-background { background: blue; }
-span.fuchsia-background { background: fuchsia; }
-span.gray-background { background: gray; }
-span.green-background { background: green; }
-span.lime-background { background: lime; }
-span.maroon-background { background: maroon; }
-span.navy-background { background: navy; }
-span.olive-background { background: olive; }
-span.purple-background { background: purple; }
-span.red-background { background: red; }
-span.silver-background { background: silver; }
-span.teal-background { background: teal; }
-span.white-background { background: white; }
-span.yellow-background { background: yellow; }
-
-span.big { font-size: 2em; }
-span.small { font-size: 0.6em; }
-
-span.underline { text-decoration: underline; }
-span.overline { text-decoration: overline; }
-span.line-through { text-decoration: line-through; }
-
-div.unbreakable { page-break-inside: avoid; }
-
-
-/*
- * xhtml11 specific
- *
- * */
-
-div.tableblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-div.tableblock > table {
- border: 3px solid #527bbd;
-}
-thead, p.table.header {
- font-weight: bold;
- color: #527bbd;
-}
-p.table {
- margin-top: 0;
-}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
-div.tableblock > table[frame="void"] {
- border-style: none;
-}
-div.tableblock > table[frame="hsides"] {
- border-left-style: none;
- border-right-style: none;
-}
-div.tableblock > table[frame="vsides"] {
- border-top-style: none;
- border-bottom-style: none;
-}
-
-
-/*
- * html5 specific
- *
- * */
-
-table.tableblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-thead, p.tableblock.header {
- font-weight: bold;
- color: #527bbd;
-}
-p.tableblock {
- margin-top: 0;
-}
-table.tableblock {
- border-width: 3px;
- border-spacing: 0px;
- border-style: solid;
- border-color: #527bbd;
- border-collapse: collapse;
-}
-th.tableblock, td.tableblock {
- border-width: 1px;
- padding: 4px;
- border-style: solid;
- border-color: #527bbd;
-}
-
-table.tableblock.frame-topbot {
- border-left-style: hidden;
- border-right-style: hidden;
-}
-table.tableblock.frame-sides {
- border-top-style: hidden;
- border-bottom-style: hidden;
-}
-table.tableblock.frame-none {
- border-style: hidden;
-}
-
-th.tableblock.halign-left, td.tableblock.halign-left {
- text-align: left;
-}
-th.tableblock.halign-center, td.tableblock.halign-center {
- text-align: center;
-}
-th.tableblock.halign-right, td.tableblock.halign-right {
- text-align: right;
-}
-
-th.tableblock.valign-top, td.tableblock.valign-top {
- vertical-align: top;
-}
-th.tableblock.valign-middle, td.tableblock.valign-middle {
- vertical-align: middle;
-}
-th.tableblock.valign-bottom, td.tableblock.valign-bottom {
- vertical-align: bottom;
-}
-
-
-/*
- * manpage specific
- *
- * */
-
-body.manpage h1 {
- padding-top: 0.5em;
- padding-bottom: 0.5em;
- border-top: 2px solid silver;
- border-bottom: 2px solid silver;
-}
-body.manpage h2 {
- border-style: none;
-}
-body.manpage div.sectionbody {
- margin-left: 3em;
-}
-
-@media print {
- body.manpage div#toc { display: none; }
-}
-
-
-</style>
-<script type="text/javascript">
-/*<![CDATA[*/
-var asciidoc = { // Namespace.
-
-/////////////////////////////////////////////////////////////////////
-// Table Of Contents generator
-/////////////////////////////////////////////////////////////////////
-
-/* Author: Mihai Bazon, September 2002
- * http://students.infoiasi.ro/~mishoo
- *
- * Table Of Content generator
- * Version: 0.4
- *
- * Feel free to use this script under the terms of the GNU General Public
- * License, as long as you do not remove or alter this notice.
- */
-
- /* modified by Troy D. Hanson, September 2006. License: GPL */
- /* modified by Stuart Rackham, 2006, 2009. License: GPL */
-
-// toclevels = 1..4.
-toc: function (toclevels) {
-
- function getText(el) {
- var text = "";
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
- text += i.data;
- else if (i.firstChild != null)
- text += getText(i);
- }
- return text;
- }
-
- function TocEntry(el, text, toclevel) {
- this.element = el;
- this.text = text;
- this.toclevel = toclevel;
- }
-
- function tocEntries(el, toclevels) {
- var result = new Array;
- var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
- // Function that scans the DOM tree for header elements (the DOM2
- // nodeIterator API would be a better technique but not supported by all
- // browsers).
- var iterate = function (el) {
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
- var mo = re.exec(i.tagName);
- if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
- result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
- }
- iterate(i);
- }
- }
- }
- iterate(el);
- return result;
- }
-
- var toc = document.getElementById("toc");
- if (!toc) {
- return;
- }
-
- // Delete existing TOC entries in case we're reloading the TOC.
- var tocEntriesToRemove = [];
- var i;
- for (i = 0; i < toc.childNodes.length; i++) {
- var entry = toc.childNodes[i];
- if (entry.nodeName.toLowerCase() == 'div'
- && entry.getAttribute("class")
- && entry.getAttribute("class").match(/^toclevel/))
- tocEntriesToRemove.push(entry);
- }
- for (i = 0; i < tocEntriesToRemove.length; i++) {
- toc.removeChild(tocEntriesToRemove[i]);
- }
-
- // Rebuild TOC entries.
- var entries = tocEntries(document.getElementById("content"), toclevels);
- for (var i = 0; i < entries.length; ++i) {
- var entry = entries[i];
- if (entry.element.id == "")
- entry.element.id = "_toc_" + i;
- var a = document.createElement("a");
- a.href = "#" + entry.element.id;
- a.appendChild(document.createTextNode(entry.text));
- var div = document.createElement("div");
- div.appendChild(a);
- div.className = "toclevel" + entry.toclevel;
- toc.appendChild(div);
- }
- if (entries.length == 0)
- toc.parentNode.removeChild(toc);
-},
-
-
-/////////////////////////////////////////////////////////////////////
-// Footnotes generator
-/////////////////////////////////////////////////////////////////////
-
-/* Based on footnote generation code from:
- * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
- */
-
-footnotes: function () {
- // Delete existing footnote entries in case we're reloading the footnodes.
- var i;
- var noteholder = document.getElementById("footnotes");
- if (!noteholder) {
- return;
- }
- var entriesToRemove = [];
- for (i = 0; i < noteholder.childNodes.length; i++) {
- var entry = noteholder.childNodes[i];
- if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
- entriesToRemove.push(entry);
- }
- for (i = 0; i < entriesToRemove.length; i++) {
- noteholder.removeChild(entriesToRemove[i]);
- }
-
- // Rebuild footnote entries.
- var cont = document.getElementById("content");
- var spans = cont.getElementsByTagName("span");
- var refs = {};
- var n = 0;
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnote") {
- n++;
- var note = spans[i].getAttribute("data-note");
- if (!note) {
- // Use [\s\S] in place of . so multi-line matches work.
- // Because JavaScript has no s (dotall) regex flag.
- note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
- spans[i].innerHTML =
- "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- spans[i].setAttribute("data-note", note);
- }
- noteholder.innerHTML +=
- "<div class='footnote' id='_footnote_" + n + "'>" +
- "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
- n + "</a>. " + note + "</div>";
- var id =spans[i].getAttribute("id");
- if (id != null) refs["#"+id] = n;
- }
- }
- if (n == 0)
- noteholder.parentNode.removeChild(noteholder);
- else {
- // Process footnoterefs.
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnoteref") {
- var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
- href = href.match(/#.*/)[0]; // Because IE return full URL.
- n = refs[href];
- spans[i].innerHTML =
- "[<a href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- }
- }
- }
-},
-
-install: function(toclevels) {
- var timerId;
-
- function reinstall() {
- asciidoc.footnotes();
- if (toclevels) {
- asciidoc.toc(toclevels);
- }
- }
-
- function reinstallAndRemoveTimer() {
- clearInterval(timerId);
- reinstall();
- }
-
- timerId = setInterval(reinstall, 500);
- if (document.addEventListener)
- document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
- else
- window.onload = reinstallAndRemoveTimer;
-}
-
-}
-asciidoc.install();
-/*]]>*/
-</script>
-</head>
-<body class="manpage">
-<div id="header">
-<h1>
-nvme-lnvm-list(1) Manual Page
-</h1>
-<h2>NAME</h2>
-<div class="sectionbody">
-<p>nvme-lnvm-list -
- List all recognized LightNVM NVMe devices
-</p>
-</div>
-</div>
-<div id="content">
-<div class="sect1">
-<h2 id="_synopsis">SYNOPSIS</h2>
-<div class="sectionbody">
-<div class="verseblock">
-<pre class="content"><em>nvme lnvm-list</em></pre>
-<div class="attribution">
-</div></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_description">DESCRIPTION</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>List all registered LightNVM devices.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_options">OPTIONS</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>No options yet.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_examples">EXAMPLES</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>No examples yet.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_nvme">NVME</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Part of the nvme-user suite</p></div>
-</div>
-</div>
-</div>
-<div id="footnotes"><hr /></div>
-<div id="footer">
-<div id="footer-text">
-Last updated
- 2021-07-19 10:10:19 PDT
-</div>
-</div>
-</body>
-</html>
+<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> +<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> +<meta name="generator" content="AsciiDoc 8.6.10" /> +<title>nvme-wdc-clear-pcie-corr(1)</title> +<style type="text/css"> +/* Shared CSS for AsciiDoc xhtml11 and html5 backends */ + +/* Default font. */ +body { + font-family: Georgia,serif; +} + +/* Title font. */ +h1, h2, h3, h4, h5, h6, +div.title, caption.title, +thead, p.table.header, +#toctitle, +#author, #revnumber, #revdate, #revremark, +#footer { + font-family: Arial,Helvetica,sans-serif; +} + +body { + margin: 1em 5% 1em 5%; +} + +a { + color: blue; + text-decoration: underline; +} +a:visited { + color: fuchsia; +} + +em { + font-style: italic; + color: navy; +} + +strong { + font-weight: bold; + color: #083194; +} + +h1, h2, h3, h4, h5, h6 { + color: #527bbd; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; +} + +h1, h2, h3 { + border-bottom: 2px solid silver; +} +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} +h5 { + font-size: 1.0em; +} + +div.sectionbody { + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} +ul > li { color: #aaa; } +ul > li > * { color: black; } + +.monospaced, code, pre { + font-family: "Courier New", Courier, monospace; + font-size: inherit; + color: navy; + padding: 0; + margin: 0; +} +pre { + white-space: pre-wrap; +} + +#author { + color: #527bbd; + font-weight: bold; + font-size: 1.1em; +} +#email { +} +#revnumber, #revdate, #revremark { +} + +#footer { + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +#footer-text { + float: left; + padding-bottom: 0.5em; +} +#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + color: #606060; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #527bbd; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid #dddddd; + border-left: 4px solid #f0f0f0; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid #dddddd; + border-left: 5px solid #f0f0f0; + background: #f8f8f8; + padding: 0.5em; +} + +div.quoteblock, div.verseblock { + padding-left: 1.0em; + margin-left: 1.0em; + margin-right: 10%; + border-left: 5px solid #f0f0f0; + color: #888; +} + +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock > pre.content { + font-family: inherit; + font-size: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #527bbd; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 3px solid #dddddd; +} + +div.exampleblock > div.content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; vertical-align: text-bottom; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: navy; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +.footnote, .footnoteref { + font-size: 0.8em; +} + +span.footnote, span.footnoteref { + vertical-align: super; +} + +#footnotes { + margin: 20px 0 20px 0; + padding: 7px 0 0 0; +} + +#footnotes div.footnote { + margin: 0 0 5px 0; +} + +#footnotes hr { + border: none; + border-top: 1px solid silver; + height: 1px; + text-align: left; + margin-left: 0; + width: 20%; + min-width: 100px; +} + +div.colist td { + padding-right: 0.5em; + padding-bottom: 0.3em; + vertical-align: top; +} +div.colist td img { + margin-top: 0.3em; +} + +@media print { + #footer-badges { display: none; } +} + +#toc { + margin-bottom: 2.5em; +} + +#toctitle { + color: #527bbd; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} + +span.aqua { color: aqua; } +span.black { color: black; } +span.blue { color: blue; } +span.fuchsia { color: fuchsia; } +span.gray { color: gray; } +span.green { color: green; } +span.lime { color: lime; } +span.maroon { color: maroon; } +span.navy { color: navy; } +span.olive { color: olive; } +span.purple { color: purple; } +span.red { color: red; } +span.silver { color: silver; } +span.teal { color: teal; } +span.white { color: white; } +span.yellow { color: yellow; } + +span.aqua-background { background: aqua; } +span.black-background { background: black; } +span.blue-background { background: blue; } +span.fuchsia-background { background: fuchsia; } +span.gray-background { background: gray; } +span.green-background { background: green; } +span.lime-background { background: lime; } +span.maroon-background { background: maroon; } +span.navy-background { background: navy; } +span.olive-background { background: olive; } +span.purple-background { background: purple; } +span.red-background { background: red; } +span.silver-background { background: silver; } +span.teal-background { background: teal; } +span.white-background { background: white; } +span.yellow-background { background: yellow; } + +span.big { font-size: 2em; } +span.small { font-size: 0.6em; } + +span.underline { text-decoration: underline; } +span.overline { text-decoration: overline; } +span.line-through { text-decoration: line-through; } + +div.unbreakable { page-break-inside: avoid; } + + +/* + * xhtml11 specific + * + * */ + +div.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.tableblock > table { + border: 3px solid #527bbd; +} +thead, p.table.header { + font-weight: bold; + color: #527bbd; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overridden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +/* + * html5 specific + * + * */ + +table.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +thead, p.tableblock.header { + font-weight: bold; + color: #527bbd; +} +p.tableblock { + margin-top: 0; +} +table.tableblock { + border-width: 3px; + border-spacing: 0px; + border-style: solid; + border-color: #527bbd; + border-collapse: collapse; +} +th.tableblock, td.tableblock { + border-width: 1px; + padding: 4px; + border-style: solid; + border-color: #527bbd; +} + +table.tableblock.frame-topbot { + border-left-style: hidden; + border-right-style: hidden; +} +table.tableblock.frame-sides { + border-top-style: hidden; + border-bottom-style: hidden; +} +table.tableblock.frame-none { + border-style: hidden; +} + +th.tableblock.halign-left, td.tableblock.halign-left { + text-align: left; +} +th.tableblock.halign-center, td.tableblock.halign-center { + text-align: center; +} +th.tableblock.halign-right, td.tableblock.halign-right { + text-align: right; +} + +th.tableblock.valign-top, td.tableblock.valign-top { + vertical-align: top; +} +th.tableblock.valign-middle, td.tableblock.valign-middle { + vertical-align: middle; +} +th.tableblock.valign-bottom, td.tableblock.valign-bottom { + vertical-align: bottom; +} + + +/* + * manpage specific + * + * */ + +body.manpage h1 { + padding-top: 0.5em; + padding-bottom: 0.5em; + border-top: 2px solid silver; + border-bottom: 2px solid silver; +} +body.manpage h2 { + border-style: none; +} +body.manpage div.sectionbody { + margin-left: 3em; +} + +@media print { + body.manpage div#toc { display: none; } +} + + +</style> +<script type="text/javascript"> +/*<![CDATA[*/ +var asciidoc = { // Namespace. + +///////////////////////////////////////////////////////////////////// +// Table Of Contents generator +///////////////////////////////////////////////////////////////////// + +/* Author: Mihai Bazon, September 2002 + * http://students.infoiasi.ro/~mishoo + * + * Table Of Content generator + * Version: 0.4 + * + * Feel free to use this script under the terms of the GNU General Public + * License, as long as you do not remove or alter this notice. + */ + + /* modified by Troy D. Hanson, September 2006. License: GPL */ + /* modified by Stuart Rackham, 2006, 2009. License: GPL */ + +// toclevels = 1..4. +toc: function (toclevels) { + + function getText(el) { + var text = ""; + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants. + text += i.data; + else if (i.firstChild != null) + text += getText(i); + } + return text; + } + + function TocEntry(el, text, toclevel) { + this.element = el; + this.text = text; + this.toclevel = toclevel; + } + + function tocEntries(el, toclevels) { + var result = new Array; + var re = new RegExp('[hH]([1-'+(toclevels+1)+'])'); + // Function that scans the DOM tree for header elements (the DOM2 + // nodeIterator API would be a better technique but not supported by all + // browsers). + var iterate = function (el) { + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 1 /* Node.ELEMENT_NODE */) { + var mo = re.exec(i.tagName); + if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") { + result[result.length] = new TocEntry(i, getText(i), mo[1]-1); + } + iterate(i); + } + } + } + iterate(el); + return result; + } + + var toc = document.getElementById("toc"); + if (!toc) { + return; + } + + // Delete existing TOC entries in case we're reloading the TOC. + var tocEntriesToRemove = []; + var i; + for (i = 0; i < toc.childNodes.length; i++) { + var entry = toc.childNodes[i]; + if (entry.nodeName.toLowerCase() == 'div' + && entry.getAttribute("class") + && entry.getAttribute("class").match(/^toclevel/)) + tocEntriesToRemove.push(entry); + } + for (i = 0; i < tocEntriesToRemove.length; i++) { + toc.removeChild(tocEntriesToRemove[i]); + } + + // Rebuild TOC entries. + var entries = tocEntries(document.getElementById("content"), toclevels); + for (var i = 0; i < entries.length; ++i) { + var entry = entries[i]; + if (entry.element.id == "") + entry.element.id = "_toc_" + i; + var a = document.createElement("a"); + a.href = "#" + entry.element.id; + a.appendChild(document.createTextNode(entry.text)); + var div = document.createElement("div"); + div.appendChild(a); + div.className = "toclevel" + entry.toclevel; + toc.appendChild(div); + } + if (entries.length == 0) + toc.parentNode.removeChild(toc); +}, + + +///////////////////////////////////////////////////////////////////// +// Footnotes generator +///////////////////////////////////////////////////////////////////// + +/* Based on footnote generation code from: + * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html + */ + +footnotes: function () { + // Delete existing footnote entries in case we're reloading the footnodes. + var i; + var noteholder = document.getElementById("footnotes"); + if (!noteholder) { + return; + } + var entriesToRemove = []; + for (i = 0; i < noteholder.childNodes.length; i++) { + var entry = noteholder.childNodes[i]; + if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote") + entriesToRemove.push(entry); + } + for (i = 0; i < entriesToRemove.length; i++) { + noteholder.removeChild(entriesToRemove[i]); + } + + // Rebuild footnote entries. + var cont = document.getElementById("content"); + var spans = cont.getElementsByTagName("span"); + var refs = {}; + var n = 0; + for (i=0; i<spans.length; i++) { + if (spans[i].className == "footnote") { + n++; + var note = spans[i].getAttribute("data-note"); + if (!note) { + // Use [\s\S] in place of . so multi-line matches work. + // Because JavaScript has no s (dotall) regex flag. + note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1]; + spans[i].innerHTML = + "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n + + "' title='View footnote' class='footnote'>" + n + "</a>]"; + spans[i].setAttribute("data-note", note); + } + noteholder.innerHTML += + "<div class='footnote' id='_footnote_" + n + "'>" + + "<a href='#_footnoteref_" + n + "' title='Return to text'>" + + n + "</a>. " + note + "</div>"; + var id =spans[i].getAttribute("id"); + if (id != null) refs["#"+id] = n; + } + } + if (n == 0) + noteholder.parentNode.removeChild(noteholder); + else { + // Process footnoterefs. + for (i=0; i<spans.length; i++) { + if (spans[i].className == "footnoteref") { + var href = spans[i].getElementsByTagName("a")[0].getAttribute("href"); + href = href.match(/#.*/)[0]; // Because IE return full URL. + n = refs[href]; + spans[i].innerHTML = + "[<a href='#_footnote_" + n + + "' title='View footnote' class='footnote'>" + n + "</a>]"; + } + } + } +}, + +install: function(toclevels) { + var timerId; + + function reinstall() { + asciidoc.footnotes(); + if (toclevels) { + asciidoc.toc(toclevels); + } + } + + function reinstallAndRemoveTimer() { + clearInterval(timerId); + reinstall(); + } + + timerId = setInterval(reinstall, 500); + if (document.addEventListener) + document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false); + else + window.onload = reinstallAndRemoveTimer; +} + +} +asciidoc.install(); +/*]]>*/ +</script> +</head> +<body class="manpage"> +<div id="header"> +<h1> +nvme-wdc-clear-pcie-corr(1) Manual Page +</h1> +<h2>NAME</h2> +<div class="sectionbody"> +<p>nvme-wdc-clear-pcie-corr - + Clears the pcie correctable errors field returned in the smart-log-add command. +</p> +</div> +</div> +<div id="content"> +<div class="sect1"> +<h2 id="_synopsis">SYNOPSIS</h2> +<div class="sectionbody"> +<div class="verseblock"> +<pre class="content"><em>nvme wdc clear-pcie-corr</em> <device></pre> +<div class="attribution"> +</div></div> +</div> +</div> +<div class="sect1"> +<h2 id="_description">DESCRIPTION</h2> +<div class="sectionbody"> +<div class="paragraph"><p>For the NVMe device given, sends the wdc vendor unique clear pcie +correctable errors command.</p></div> +<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe +character device (ex: /dev/nvme0), or a namespace block device (ex: +/dev/nvme0n1).</p></div> +<div class="paragraph"><p>This will only work on WDC devices supporting this feature. +Results for any other device are undefined.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_options">OPTIONS</h2> +<div class="sectionbody"> +<div class="paragraph"><p>None</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_examples">EXAMPLES</h2> +<div class="sectionbody"> +<div class="ulist"><ul> +<li> +<p> +Clears the PCIe Correctable Error Count field returned in the smart-log-add command: +</p> +<div class="listingblock"> +<div class="content"> +<pre><code># nvme wdc clear-pcie-corr /dev/nvme0</code></pre> +</div></div> +</li> +</ul></div> +</div> +</div> +<div class="sect1"> +<h2 id="_nvme">NVME</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Part of the nvme-user suite</p></div> +</div> +</div> +</div> +<div id="footnotes"><hr /></div> +<div id="footer"> +<div id="footer-text"> +Last updated + 2018-01-18 13:54:43 CST +</div> +</div> +</body> +</html> diff --git a/Documentation/nvme-wdc-clear-pcie-correctable-errors.1 b/Documentation/nvme-wdc-clear-pcie-correctable-errors.1 index 7d3e090..50225e9 100644 --- a/Documentation/nvme-wdc-clear-pcie-correctable-errors.1 +++ b/Documentation/nvme-wdc-clear-pcie-correctable-errors.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-clear-pcie-correctable-errors .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-CLEAR\-PC" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-CLEAR\-PC" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-clear-pcie-correctable-errors.html b/Documentation/nvme-wdc-clear-pcie-correctable-errors.html index 2b4b49c..4aa66ab 100644 --- a/Documentation/nvme-wdc-clear-pcie-correctable-errors.html +++ b/Documentation/nvme-wdc-clear-pcie-correctable-errors.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-clear-pcie-correctable-errors(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -799,7 +799,7 @@ Clears the PCIe Correctable Error Count field returned in the smart-log-add comm <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-cloud-SSD-plugin-version.1 b/Documentation/nvme-wdc-cloud-SSD-plugin-version.1 index c5672e3..8467b6f 100644 --- a/Documentation/nvme-wdc-cloud-SSD-plugin-version.1 +++ b/Documentation/nvme-wdc-cloud-SSD-plugin-version.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-cloud-SSD-plugin-version .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-CLOUD\-SS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-CLOUD\-SS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-cloud-SSD-plugin-version.html b/Documentation/nvme-wdc-cloud-SSD-plugin-version.html index 3461c7f..60b60ef 100644 --- a/Documentation/nvme-wdc-cloud-SSD-plugin-version.html +++ b/Documentation/nvme-wdc-cloud-SSD-plugin-version.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-cloud-SSD-plugin-version(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -790,7 +790,7 @@ Displays the cloud ssd plugin version for the device: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-drive-essentials.1 b/Documentation/nvme-wdc-drive-essentials.1 index d2e2fc6..e481ec2 100644 --- a/Documentation/nvme-wdc-drive-essentials.1 +++ b/Documentation/nvme-wdc-drive-essentials.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-drive-essentials .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-DRIVE\-ES" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-DRIVE\-ES" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-drive-essentials.html b/Documentation/nvme-wdc-drive-essentials.html index e3ed5aa..d760965 100644 --- a/Documentation/nvme-wdc-drive-essentials.html +++ b/Documentation/nvme-wdc-drive-essentials.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-drive-essentials(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -821,7 +821,7 @@ Gets the drive essentials data files from the device and saves the tar file to s <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-drive-log.1 b/Documentation/nvme-wdc-drive-log.1 index 1d3a353..637dd40 100644 --- a/Documentation/nvme-wdc-drive-log.1 +++ b/Documentation/nvme-wdc-drive-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-drive-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-DRIVE\-LO" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-DRIVE\-LO" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-drive-log.html b/Documentation/nvme-wdc-drive-log.html index 8b3c9a4..7a680c1 100644 --- a/Documentation/nvme-wdc-drive-log.html +++ b/Documentation/nvme-wdc-drive-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-drive-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -829,7 +829,7 @@ Gets the drive log from the device and saves to defined file with pathname (e.g. <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-drive-resize.1 b/Documentation/nvme-wdc-drive-resize.1 index b46cffc..0ddf4b2 100644 --- a/Documentation/nvme-wdc-drive-resize.1 +++ b/Documentation/nvme-wdc-drive-resize.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-drive-resize .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-DRIVE\-RE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-DRIVE\-RE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-drive-resize.html b/Documentation/nvme-wdc-drive-resize.html index fcb7efd..a09fb97 100644 --- a/Documentation/nvme-wdc-drive-resize.html +++ b/Documentation/nvme-wdc-drive-resize.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-drive-resize(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -810,7 +810,7 @@ Has the program issue WDC Resize Vendor Unique Command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-enc-get-log.1 b/Documentation/nvme-wdc-enc-get-log.1 index 11ec7b8..f6c92f8 100644 --- a/Documentation/nvme-wdc-enc-get-log.1 +++ b/Documentation/nvme-wdc-enc-get-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-enc-get-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-ENC\-GET\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-ENC\-GET\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-enc-get-log.html b/Documentation/nvme-wdc-enc-get-log.html index 25cf0cd..5876c3c 100644 --- a/Documentation/nvme-wdc-enc-get-log.html +++ b/Documentation/nvme-wdc-enc-get-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-enc-get-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -832,7 +832,7 @@ Gets the enclosure log from the device based on the log id(0xd2) with default tr <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-get-crash-dump.1 b/Documentation/nvme-wdc-get-crash-dump.1 index 81589e3..30af088 100644 --- a/Documentation/nvme-wdc-get-crash-dump.1 +++ b/Documentation/nvme-wdc-get-crash-dump.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-get-crash-dump .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-GET\-CRAS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-GET\-CRAS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-get-crash-dump.html b/Documentation/nvme-wdc-get-crash-dump.html index 7cb4eb5..bed7610 100644 --- a/Documentation/nvme-wdc-get-crash-dump.html +++ b/Documentation/nvme-wdc-get-crash-dump.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-get-crash-dump(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -830,7 +830,7 @@ Gets the crash dump from the device and saves to defined file with pathname (e.g <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-get-dev-capabilities-log.1 b/Documentation/nvme-wdc-get-dev-capabilities-log.1 new file mode 100644 index 0000000..211c71d --- /dev/null +++ b/Documentation/nvme-wdc-get-dev-capabilities-log.1 @@ -0,0 +1,79 @@ +'\" t +.\" Title: nvme-wdc-get-dev-capabilities-log +.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] +.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> +.\" Date: 04/08/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-WDC\-GET\-DEV\" "1" "04/08/2022" "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-dev-capabilities-log \- Send NVMe WDC get\-dev\-capabilities\-log plugin command, return parsed log output +.SH "SYNOPSIS" +.sp +.nf +\fInvme wdc get\-dev\-capabilities\-log\fR <device> [\-\-output\-format=<normal|json> +\-o <normal|json>] +.fi +.SH "DESCRIPTION" +.sp +For the NVMe device given, send a WDC plugin get\-dev\-capabilities\-log command and output the device capabilities log data\&. The \-\-output\-format option will format the output as specified\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0)\&. +.sp +This will only work on WDC devices supporting this log page\&. Results for any other device are undefined\&. +.sp +On success it returns the parsed device capabilities log page data, error code otherwise\&. +.SH "OPTIONS" +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, or +\fIjson\fR\&. Only one output format can be used at a time\&. Default is normal\&. +.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 WDC get\-dev\-capabilities\-log plugin command : +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme wdc get\-dev\-capabilities\-log /dev/nvme0 +.fi +.if n \{\ +.RE +.\} +.RE +.SH "NVME" +.sp +Part of the nvme\-user suite\&. diff --git a/Documentation/nvme-wdc-get-dev-capabilities-log.html b/Documentation/nvme-wdc-get-dev-capabilities-log.html new file mode 100644 index 0000000..1b90878 --- /dev/null +++ b/Documentation/nvme-wdc-get-dev-capabilities-log.html @@ -0,0 +1,823 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-wdc-get-dev-capabilities-log(1)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+pre {
+ white-space: pre-wrap;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overridden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+nvme-wdc-get-dev-capabilities-log(1) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>nvme-wdc-get-dev-capabilities-log -
+ Send NVMe WDC get-dev-capabilities-log plugin command, return parsed log output
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="verseblock">
+<pre class="content"><em>nvme wdc get-dev-capabilities-log</em> <device> [--output-format=<normal|json>
+-o <normal|json>]</pre>
+<div class="attribution">
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_description">DESCRIPTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>For the NVMe device given, send a WDC plugin get-dev-capabilities-log command
+and output the device capabilities log data. The --output-format option will
+format the output as specified.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0).</p></div>
+<div class="paragraph"><p>This will only work on WDC devices supporting this log page.
+Results for any other device are undefined.</p></div>
+<div class="paragraph"><p>On success it returns the parsed device capabilities log page data, error
+code otherwise.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_options">OPTIONS</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-o <format>
+</dt>
+<dt class="hdlist1">
+--output-format=<format>
+</dt>
+<dd>
+<p>
+ Set the reporting format to <em>normal</em>, or
+ <em>json</em>. Only one output format can be used at a time.
+ Default is normal.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">EXAMPLES</h2>
+<div class="sectionbody">
+<div class="ulist"><ul>
+<li>
+<p>
+Has the program issue WDC get-dev-capabilities-log plugin command :
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme wdc get-dev-capabilities-log /dev/nvme0</code></pre>
+</div></div>
+</li>
+</ul></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_nvme">NVME</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Part of the nvme-user suite.</p></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated
+ 2022-04-08 18:46:59 CEST
+</div>
+</div>
+</body>
+</html>
diff --git a/Documentation/nvme-wdc-get-dev-capabilities-log.txt b/Documentation/nvme-wdc-get-dev-capabilities-log.txt new file mode 100644 index 0000000..0621881 --- /dev/null +++ b/Documentation/nvme-wdc-get-dev-capabilities-log.txt @@ -0,0 +1,48 @@ +nvme-wdc-get-dev-capabilities-log(1) +==================================== + +NAME +---- +nvme-wdc-get-dev-capabilities-log - Send NVMe WDC get-dev-capabilities-log + plugin command, return parsed log output + +SYNOPSIS +-------- +[verse] +'nvme wdc get-dev-capabilities-log' <device> [--output-format=<normal|json> +-o <normal|json>] + +DESCRIPTION +----------- +For the NVMe device given, send a WDC plugin get-dev-capabilities-log command +and output the device capabilities log data. The --output-format option will +format the output as specified. + +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 log page. +Results for any other device are undefined. + +On success it returns the parsed device capabilities log page data, error +code otherwise. + +OPTIONS +------- +-o <format>:: +--output-format=<format>:: + Set the reporting format to 'normal', or + 'json'. Only one output format can be used at a time. + Default is normal. + +EXAMPLES +-------- +* Has the program issue WDC get-dev-capabilities-log plugin command : ++ +------------ +# nvme wdc get-dev-capabilities-log /dev/nvme0 +------------ + +NVME +---- +Part of the nvme-user suite. diff --git a/Documentation/nvme-wdc-get-drive-status.1 b/Documentation/nvme-wdc-get-drive-status.1 index 0ce71ba..3c64d66 100644 --- a/Documentation/nvme-wdc-get-drive-status.1 +++ b/Documentation/nvme-wdc-get-drive-status.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-get-drive-status .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-GET\-DRIV" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-GET\-DRIV" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-get-drive-status.html b/Documentation/nvme-wdc-get-drive-status.html index ee340f2..041aade 100644 --- a/Documentation/nvme-wdc-get-drive-status.html +++ b/Documentation/nvme-wdc-get-drive-status.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-get-drive-status(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -836,7 +836,7 @@ Has the program issue WDC get-drive-status command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-get-error-recovery-log.1 b/Documentation/nvme-wdc-get-error-recovery-log.1 new file mode 100644 index 0000000..b3301ac --- /dev/null +++ b/Documentation/nvme-wdc-get-error-recovery-log.1 @@ -0,0 +1,79 @@ +'\" t +.\" Title: nvme-wdc-get-error-recovery-log +.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] +.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> +.\" Date: 04/08/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-WDC\-GET\-ERRO" "1" "04/08/2022" "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-error-recovery-log \- Send NVMe WDC get\-error\-recovery\-log plugin command, return parsed log output +.SH "SYNOPSIS" +.sp +.nf +\fInvme wdc get\-error\-recovery\-log\fR <device> [\-\-output\-format=<normal|json> +\-o <normal|json>] +.fi +.SH "DESCRIPTION" +.sp +For the NVMe device given, send a WDC plugin get\-error\-recovery\-log command and output the error recovery log data\&. The \-\-output\-format option will format the output as specified\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0)\&. +.sp +This will only work on WDC devices supporting this log page\&. Results for any other device are undefined\&. +.sp +On success it returns the parsed error recovery log page data, error code otherwise\&. +.SH "OPTIONS" +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, or +\fIjson\fR\&. Only one output format can be used at a time\&. Default is normal\&. +.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 WDC get\-error\-recovery\-log plugin command : +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme wdc get\-error\-recovery\-log /dev/nvme0 +.fi +.if n \{\ +.RE +.\} +.RE +.SH "NVME" +.sp +Part of the nvme\-user suite\&. diff --git a/Documentation/nvme-wdc-get-error-recovery-log.html b/Documentation/nvme-wdc-get-error-recovery-log.html new file mode 100644 index 0000000..bb2f750 --- /dev/null +++ b/Documentation/nvme-wdc-get-error-recovery-log.html @@ -0,0 +1,823 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-wdc-get-error-recovery-log(1)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+pre {
+ white-space: pre-wrap;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overridden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+nvme-wdc-get-error-recovery-log(1) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>nvme-wdc-get-error-recovery-log -
+ Send NVMe WDC get-error-recovery-log plugin command, return parsed log output
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="verseblock">
+<pre class="content"><em>nvme wdc get-error-recovery-log</em> <device> [--output-format=<normal|json>
+-o <normal|json>]</pre>
+<div class="attribution">
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_description">DESCRIPTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>For the NVMe device given, send a WDC plugin get-error-recovery-log command
+and output the error recovery log data. The --output-format option will format
+the output as specified.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0).</p></div>
+<div class="paragraph"><p>This will only work on WDC devices supporting this log page.
+Results for any other device are undefined.</p></div>
+<div class="paragraph"><p>On success it returns the parsed error recovery log page data, error
+code otherwise.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_options">OPTIONS</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-o <format>
+</dt>
+<dt class="hdlist1">
+--output-format=<format>
+</dt>
+<dd>
+<p>
+ Set the reporting format to <em>normal</em>, or
+ <em>json</em>. Only one output format can be used at a time.
+ Default is normal.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">EXAMPLES</h2>
+<div class="sectionbody">
+<div class="ulist"><ul>
+<li>
+<p>
+Has the program issue WDC get-error-recovery-log plugin command :
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme wdc get-error-recovery-log /dev/nvme0</code></pre>
+</div></div>
+</li>
+</ul></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_nvme">NVME</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Part of the nvme-user suite.</p></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated
+ 2022-04-08 18:46:59 CEST
+</div>
+</div>
+</body>
+</html>
diff --git a/Documentation/nvme-wdc-get-error-recovery-log.txt b/Documentation/nvme-wdc-get-error-recovery-log.txt new file mode 100644 index 0000000..2ad3605 --- /dev/null +++ b/Documentation/nvme-wdc-get-error-recovery-log.txt @@ -0,0 +1,48 @@ +nvme-wdc-get-error-recovery-log(1) +================================== + +NAME +---- +nvme-wdc-get-error-recovery-log - Send NVMe WDC get-error-recovery-log plugin + command, return parsed log output + +SYNOPSIS +-------- +[verse] +'nvme wdc get-error-recovery-log' <device> [--output-format=<normal|json> +-o <normal|json>] + +DESCRIPTION +----------- +For the NVMe device given, send a WDC plugin get-error-recovery-log command +and output the error recovery log data. The --output-format option will format +the output as specified. + +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 log page. +Results for any other device are undefined. + +On success it returns the parsed error recovery log page data, error +code otherwise. + +OPTIONS +------- +-o <format>:: +--output-format=<format>:: + Set the reporting format to 'normal', or + 'json'. Only one output format can be used at a time. + Default is normal. + +EXAMPLES +-------- +* Has the program issue WDC get-error-recovery-log plugin command : ++ +------------ +# nvme wdc get-error-recovery-log /dev/nvme0 +------------ + +NVME +---- +Part of the nvme-user suite. diff --git a/Documentation/nvme-wdc-get-latency-monitor-log.1 b/Documentation/nvme-wdc-get-latency-monitor-log.1 index 24903c5..4853add 100644 --- a/Documentation/nvme-wdc-get-latency-monitor-log.1 +++ b/Documentation/nvme-wdc-get-latency-monitor-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-get-latency-monitor-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-GET\-LATE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-GET\-LATE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-get-latency-monitor-log.html b/Documentation/nvme-wdc-get-latency-monitor-log.html index 0c86989..fa91b8f 100644 --- a/Documentation/nvme-wdc-get-latency-monitor-log.html +++ b/Documentation/nvme-wdc-get-latency-monitor-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-get-latency-monitor-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -810,7 +810,7 @@ Displays the get latency monitor log for the device: <div id="footer">
<div id="footer-text">
Last updated
- 2021-10-22 16:48:14 CDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-get-pfail-dump.1 b/Documentation/nvme-wdc-get-pfail-dump.1 index 6066a82..1c436f1 100644 --- a/Documentation/nvme-wdc-get-pfail-dump.1 +++ b/Documentation/nvme-wdc-get-pfail-dump.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-get-pfail-dump .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-GET\-PFAI" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-GET\-PFAI" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-get-pfail-dump.html b/Documentation/nvme-wdc-get-pfail-dump.html index 8e6ec97..5df8939 100644 --- a/Documentation/nvme-wdc-get-pfail-dump.html +++ b/Documentation/nvme-wdc-get-pfail-dump.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-get-pfail-dump(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -832,7 +832,7 @@ Gets the pfail crash dump from the device and saves to defined file with pathnam <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-get-unsupported-reqs-log.1 b/Documentation/nvme-wdc-get-unsupported-reqs-log.1 new file mode 100644 index 0000000..1adbed0 --- /dev/null +++ b/Documentation/nvme-wdc-get-unsupported-reqs-log.1 @@ -0,0 +1,79 @@ +'\" t +.\" Title: nvme-wdc-get-unsupported-reqs-log +.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] +.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> +.\" Date: 04/08/2022 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-WDC\-GET\-UNSU" "1" "04/08/2022" "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-unsupported-reqs-log \- Send NVMe WDC get\-unsupported\-reqs\-log plugin command, return parsed log output +.SH "SYNOPSIS" +.sp +.nf +\fInvme wdc get\-unsupported\-reqs\-log\fR <device> [\-\-output\-format=<normal|json> +\-o <normal|json>] +.fi +.SH "DESCRIPTION" +.sp +For the NVMe device given, send a WDC plugin get\-unsupported\-reqs\-log command and output the unsupported requirements log data\&. The \-\-output\-format option will format the output as specified\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0)\&. +.sp +This will only work on WDC devices supporting this log page\&. Results for any other device are undefined\&. +.sp +On success it returns the parsed unsupported requirements log page data, error code otherwise\&. +.SH "OPTIONS" +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, or +\fIjson\fR\&. Only one output format can be used at a time\&. Default is normal\&. +.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 WDC get\-unsupported\-reqs\-log plugin command : +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme wdc get\-unsupported\-reqs\-log /dev/nvme0 +.fi +.if n \{\ +.RE +.\} +.RE +.SH "NVME" +.sp +Part of the nvme\-user suite\&. diff --git a/Documentation/nvme-wdc-get-unsupported-reqs-log.html b/Documentation/nvme-wdc-get-unsupported-reqs-log.html new file mode 100644 index 0000000..e1ae5d7 --- /dev/null +++ b/Documentation/nvme-wdc-get-unsupported-reqs-log.html @@ -0,0 +1,823 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-wdc-get-unsupported-reqs-log(1)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+pre {
+ white-space: pre-wrap;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overridden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+nvme-wdc-get-unsupported-reqs-log(1) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>nvme-wdc-get-unsupported-reqs-log -
+ Send NVMe WDC get-unsupported-reqs-log plugin command, return parsed log output
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="verseblock">
+<pre class="content"><em>nvme wdc get-unsupported-reqs-log</em> <device> [--output-format=<normal|json>
+-o <normal|json>]</pre>
+<div class="attribution">
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_description">DESCRIPTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>For the NVMe device given, send a WDC plugin get-unsupported-reqs-log command
+and output the unsupported requirements log data. The --output-format option
+will format the output as specified.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0).</p></div>
+<div class="paragraph"><p>This will only work on WDC devices supporting this log page.
+Results for any other device are undefined.</p></div>
+<div class="paragraph"><p>On success it returns the parsed unsupported requirements log page data, error
+code otherwise.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_options">OPTIONS</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-o <format>
+</dt>
+<dt class="hdlist1">
+--output-format=<format>
+</dt>
+<dd>
+<p>
+ Set the reporting format to <em>normal</em>, or
+ <em>json</em>. Only one output format can be used at a time.
+ Default is normal.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">EXAMPLES</h2>
+<div class="sectionbody">
+<div class="ulist"><ul>
+<li>
+<p>
+Has the program issue WDC get-unsupported-reqs-log plugin command :
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme wdc get-unsupported-reqs-log /dev/nvme0</code></pre>
+</div></div>
+</li>
+</ul></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_nvme">NVME</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Part of the nvme-user suite.</p></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated
+ 2022-04-08 18:46:59 CEST
+</div>
+</div>
+</body>
+</html>
diff --git a/Documentation/nvme-wdc-get-unsupported-reqs-log.txt b/Documentation/nvme-wdc-get-unsupported-reqs-log.txt new file mode 100644 index 0000000..f028665 --- /dev/null +++ b/Documentation/nvme-wdc-get-unsupported-reqs-log.txt @@ -0,0 +1,48 @@ +nvme-wdc-get-unsupported-reqs-log(1) +==================================== + +NAME +---- +nvme-wdc-get-unsupported-reqs-log - Send NVMe WDC get-unsupported-reqs-log + plugin command, return parsed log output + +SYNOPSIS +-------- +[verse] +'nvme wdc get-unsupported-reqs-log' <device> [--output-format=<normal|json> +-o <normal|json>] + +DESCRIPTION +----------- +For the NVMe device given, send a WDC plugin get-unsupported-reqs-log command +and output the unsupported requirements log data. The --output-format option +will format the output as specified. + +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 log page. +Results for any other device are undefined. + +On success it returns the parsed unsupported requirements log page data, error +code otherwise. + +OPTIONS +------- +-o <format>:: +--output-format=<format>:: + Set the reporting format to 'normal', or + 'json'. Only one output format can be used at a time. + Default is normal. + +EXAMPLES +-------- +* Has the program issue WDC get-unsupported-reqs-log plugin command : ++ +------------ +# nvme wdc get-unsupported-reqs-log /dev/nvme0 +------------ + +NVME +---- +Part of the nvme-user suite. diff --git a/Documentation/nvme-wdc-id-ctrl.1 b/Documentation/nvme-wdc-id-ctrl.1 index 7c176a7..bdb99e3 100644 --- a/Documentation/nvme-wdc-id-ctrl.1 +++ b/Documentation/nvme-wdc-id-ctrl.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-id-ctrl .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-ID\-CTRL" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-ID\-CTRL" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-id-ctrl.html b/Documentation/nvme-wdc-id-ctrl.html index 3acde0a..f0ef3e8 100644 --- a/Documentation/nvme-wdc-id-ctrl.html +++ b/Documentation/nvme-wdc-id-ctrl.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-id-ctrl(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -856,7 +856,7 @@ fields in a human readable format: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-log-page-directory.1 b/Documentation/nvme-wdc-log-page-directory.1 index fd283a9..5c4a79e 100644 --- a/Documentation/nvme-wdc-log-page-directory.1 +++ b/Documentation/nvme-wdc-log-page-directory.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-log-page-directory .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-LOG\-PAGE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-LOG\-PAGE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-log-page-directory.html b/Documentation/nvme-wdc-log-page-directory.html index e5af0da..d76b29c 100644 --- a/Documentation/nvme-wdc-log-page-directory.html +++ b/Documentation/nvme-wdc-log-page-directory.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-log-page-directory(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -812,7 +812,7 @@ WDC log-page-directory example command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-namespace-resize.1 b/Documentation/nvme-wdc-namespace-resize.1 index 1d60adb..c46c8c3 100644 --- a/Documentation/nvme-wdc-namespace-resize.1 +++ b/Documentation/nvme-wdc-namespace-resize.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-namespace-resize .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-NAMESPACE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-NAMESPACE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-namespace-resize.html b/Documentation/nvme-wdc-namespace-resize.html index e20c30d..9bc0c38 100644 --- a/Documentation/nvme-wdc-namespace-resize.html +++ b/Documentation/nvme-wdc-namespace-resize.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-namespace-resize(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -838,7 +838,7 @@ Resizes namespace 2 to 7% of the orginal TNVMCAP reported value: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-purge-monitor.1 b/Documentation/nvme-wdc-purge-monitor.1 index 5fd78eb..ed3ce94 100644 --- a/Documentation/nvme-wdc-purge-monitor.1 +++ b/Documentation/nvme-wdc-purge-monitor.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-purge-monitor .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-PURGE\-MO" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-PURGE\-MO" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-purge-monitor.html b/Documentation/nvme-wdc-purge-monitor.html index c1ac8aa..ac5f005 100644 --- a/Documentation/nvme-wdc-purge-monitor.html +++ b/Documentation/nvme-wdc-purge-monitor.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-purge-monitor(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -837,7 +837,7 @@ Has the program issue WDC Purge-Monitor Vendor Unique Command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-purge.1 b/Documentation/nvme-wdc-purge.1 index 91baa90..02d935e 100644 --- a/Documentation/nvme-wdc-purge.1 +++ b/Documentation/nvme-wdc-purge.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-purge .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-PURGE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-PURGE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-purge.html b/Documentation/nvme-wdc-purge.html index 79616a4..0e6b312 100644 --- a/Documentation/nvme-wdc-purge.html +++ b/Documentation/nvme-wdc-purge.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-purge(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -799,7 +799,7 @@ Has the program issue WDC Purge Vendor Unique Command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-smart-add-log.1 b/Documentation/nvme-wdc-smart-add-log.1 new file mode 100644 index 0000000..fe1d3de --- /dev/null +++ b/Documentation/nvme-wdc-smart-add-log.1 @@ -0,0 +1,496 @@ +'\" t +.\" Title: nvme-wdc-smart-add-log +.\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] +.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> +.\" Date: 01/08/2019 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-WDC\-SMART\-AD" "1" "01/08/2019" "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 <device> [\-\-interval=<NUM>, \-i <NUM>] [\-\-output\-format=<normal|json> \-o <normal|json>] +.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 <device> 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 <NUM>, \-\-interval=<NUM> +.RS 4 +Return the statistics from specific interval, defaults to 14 +.RE +.PP +\-o <format>, \-\-output\-format=<format> +.RS 4 +Set the reporting format to +\fInormal\fR, or +\fIjson\fR\&. Only one output format can be used at a time\&. Default is normal\&. +.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\&. diff --git a/Documentation/nvme-wdc-smart-add-log.html b/Documentation/nvme-wdc-smart-add-log.html new file mode 100644 index 0000000..e7f1d50 --- /dev/null +++ b/Documentation/nvme-wdc-smart-add-log.html @@ -0,0 +1,1139 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.6.9" />
+<title>nvme-wdc-smart-add-log(1)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+pre {
+ white-space: pre-wrap;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overridden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+nvme-wdc-smart-add-log(1) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>nvme-wdc-smart-add-log -
+ Send NVMe WDC smart-add-log Vendor Unique Command, return result
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="verseblock">
+<pre class="content"><em>nvme wdc smart-add-log</em> <device> [--interval=<NUM>, -i <NUM>] [--output-format=<normal|json> -o <normal|json>]</pre>
+<div class="attribution">
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_description">DESCRIPTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>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.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0).</p></div>
+<div class="paragraph"><p>This will only work on WDC devices supporting this feature.
+Results for any other device are undefined.</p></div>
+<div class="paragraph"><p>On success it returns 0, error code otherwise.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_options">OPTIONS</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+-i <NUM>
+</dt>
+<dt class="hdlist1">
+--interval=<NUM>
+</dt>
+<dd>
+<p>
+ Return the statistics from specific interval, defaults to 14
+</p>
+</dd>
+<dt class="hdlist1">
+-o <format>
+</dt>
+<dt class="hdlist1">
+--output-format=<format>
+</dt>
+<dd>
+<p>
+ Set the reporting format to <em>normal</em>, or
+ <em>json</em>. Only one output format can be used at a time.
+ Default is normal.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>Valid Interval values and description :-</p></div>
+<div class="tableblock">
+<table rules="all"
+style="margin-left:auto; margin-right:auto;"
+width="100%"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="50%" />
+<col width="50%" />
+<thead>
+<tr>
+<th align="left" valign="top">Value </th>
+<th align="left" valign="top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>1</strong></p></td>
+<td align="left" valign="top"><p class="table">Most recent five (5) minute accumulated set.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>2-12</strong></p></td>
+<td align="left" valign="top"><p class="table">Previous five (5) minute accumulated sets.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>13</strong></p></td>
+<td align="left" valign="top"><p class="table">The accumulated total of sets 1 through 12 that contain the previous hour of
+accumulated statistics.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>14</strong></p></td>
+<td align="left" valign="top"><p class="table">The statistical set accumulated since power-up.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>15</strong></p></td>
+<td align="left" valign="top"><p class="table">The statistical set accumulated during the entire lifetime of the device.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_ca_log_page_data_output_explanation">CA Log Page Data Output Explanation</h2>
+<div class="sectionbody">
+<div class="tableblock">
+<table rules="all"
+style="margin-left:auto; margin-right:auto;"
+width="100%"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="50%" />
+<col width="50%" />
+<thead>
+<tr>
+<th align="left" valign="top">Field </th>
+<th align="left" valign="top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Physical NAND bytes written.</strong></p></td>
+<td align="left" valign="top"><p class="table">The number of bytes written to NAND. 16 bytes - hi/lo</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Physical NAND bytes read</strong></p></td>
+<td align="left" valign="top"><p class="table">The number of bytes read from NAND. 16 bytes - hi/lo</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Bad NAND Block Count</strong></p></td>
+<td align="left" valign="top"><p class="table">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</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Uncorrectable Read Error Count</strong></p></td>
+<td align="left" valign="top"><p class="table">Total count of NAND reads that were not correctable by read retries, all
+levels of ECC, or XOR (as applicable). 8 bytes</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Soft ECC Error Count</strong></p></td>
+<td align="left" valign="top"><p class="table">Total count of NAND reads that were not correctable by read retries, or
+first-level ECC. 8 bytes</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>SSD End to End Detection Count</strong></p></td>
+<td align="left" valign="top"><p class="table">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</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>SSD End to End Correction Count</strong></p></td>
+<td align="left" valign="top"><p class="table">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</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>System Data % Used</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>User Data Max Erase Count</strong></p></td>
+<td align="left" valign="top"><p class="table">The maximum erase count across all NAND blocks in the drive. 4 bytes</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>User Data Min Erase Count</strong></p></td>
+<td align="left" valign="top"><p class="table">The minimum erase count across all NAND blocks in the drive. 4 bytes</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Refresh Count</strong></p></td>
+<td align="left" valign="top"><p class="table">A count of the number of blocks that have been re-allocated due to
+background operations only. 8 bytes</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Program Fail Count</strong></p></td>
+<td align="left" valign="top"><p class="table">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</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>User Data Erase Fail Count</strong></p></td>
+<td align="left" valign="top"><p class="table">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</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>System Area Erase Fail Count</strong></p></td>
+<td align="left" valign="top"><p class="table">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</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Thermal Throttling Status</strong></p></td>
+<td align="left" valign="top"><p class="table">The current status of thermal throttling (enabled or disabled).
+2 bytes</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Thermal Throttling Count</strong></p></td>
+<td align="left" valign="top"><p class="table">A count of the number of thermal throttling events. 2 bytes</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>PCIe Correctable Error Count</strong></p></td>
+<td align="left" valign="top"><p class="table">Summation counter of all PCIe correctable errors (Bad TLP, Bad
+DLLP, Receiver error, Replay timeouts, Replay rollovers). 8 bytes</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_c1_log_page_data_output_explanation">C1 Log Page Data Output Explanation</h2>
+<div class="sectionbody">
+<div class="tableblock">
+<table rules="all"
+style="margin-left:auto; margin-right:auto;"
+width="100%"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="50%" />
+<col width="50%" />
+<thead>
+<tr>
+<th align="left" valign="top">Field </th>
+<th align="left" valign="top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Read Commands</strong></p></td>
+<td align="left" valign="top"><p class="table">Number of host read commands received during the reporting period.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Read Blocks</strong></p></td>
+<td align="left" valign="top"><p class="table">Number of 512-byte blocks requested during the reporting period.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Average Read Size</strong></p></td>
+<td align="left" valign="top"><p class="table">Average Read size is calculated using (Host Read Blocks/Host Read Commands).</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Read Cache Hit Commands</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Read Cache Hit Percentage</strong></p></td>
+<td align="left" valign="top"><p class="table">Percentage of host read commands satisfied from the cache.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Read Cache Hit Blocks</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Average Read Cache Hit Size</strong></p></td>
+<td align="left" valign="top"><p class="table">Average size of read commands satisfied from the cache.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Read Commands Stalled</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Read Commands Stalled Percentage</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Commands</strong></p></td>
+<td align="left" valign="top"><p class="table">Number of host write commands received during the reporting period.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Blocks</strong></p></td>
+<td align="left" valign="top"><p class="table">Number of 512-byte blocks written during the reporting period.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Average Write Size</strong></p></td>
+<td align="left" valign="top"><p class="table">Average Write size calculated using (Host Write Blocks/Host Write Commands).</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Odd Start Commands</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Odd Start Commands Percentage</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Odd End Commands</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Odd End Commands Percentage</strong></p></td>
+<td align="left" valign="top"><p class="table">Percentage of host write commands that ended on a non-aligned boundary.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Commands Stalled</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Host Write Commands Stalled Percentage</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>NAND Read Commands</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>NAND Read Blocks</strong></p></td>
+<td align="left" valign="top"><p class="table">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</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Average NAND Read Size</strong></p></td>
+<td align="left" valign="top"><p class="table">Average size of NAND read commands.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>NAND Write Commands</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>NAND Write Blocks</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>Average NAND Write Size</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><strong>NAND Read Before Write</strong></p></td>
+<td align="left" valign="top"><p class="table">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.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">EXAMPLES</h2>
+<div class="sectionbody">
+<div class="ulist"><ul>
+<li>
+<p>
+Has the program issue WDC smart-add-log Vendor Unique Command with default interval (14) :
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code># nvme wdc smart-add-log /dev/nvme0</code></pre>
+</div></div>
+</li>
+</ul></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_nvme">NVME</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Part of the nvme-user suite.</p></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated
+ 2018-01-17 20:47:00 KST
+</div>
+</div>
+</body>
+</html>
diff --git a/Documentation/nvme-wdc-vs-drive-info.1 b/Documentation/nvme-wdc-vs-drive-info.1 index 98ef2a8..638188c 100644 --- a/Documentation/nvme-wdc-vs-drive-info.1 +++ b/Documentation/nvme-wdc-vs-drive-info.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-drive-info .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-DRIVE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-DRIVE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-drive-info.html b/Documentation/nvme-wdc-vs-drive-info.html index 9993637..afb487a 100644 --- a/Documentation/nvme-wdc-vs-drive-info.html +++ b/Documentation/nvme-wdc-vs-drive-info.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-drive-info(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -791,7 +791,7 @@ Results for any other device are undefined.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-vs-error-reason-identifier.1 b/Documentation/nvme-wdc-vs-error-reason-identifier.1 index a175664..2565bfe 100644 --- a/Documentation/nvme-wdc-vs-error-reason-identifier.1 +++ b/Documentation/nvme-wdc-vs-error-reason-identifier.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-error-reason-identifier .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-ERROR" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-ERROR" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-error-reason-identifier.html b/Documentation/nvme-wdc-vs-error-reason-identifier.html index ddc6d72..c380034 100644 --- a/Documentation/nvme-wdc-vs-error-reason-identifier.html +++ b/Documentation/nvme-wdc-vs-error-reason-identifier.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-error-reason-identifier(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -836,7 +836,7 @@ Retrieves the controller initiated error reason identifier field and save it in <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-vs-fw-activate-history.1 b/Documentation/nvme-wdc-vs-fw-activate-history.1 index d2d2f78..97ad8ec 100644 --- a/Documentation/nvme-wdc-vs-fw-activate-history.1 +++ b/Documentation/nvme-wdc-vs-fw-activate-history.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-fw-activate-history .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-FW\-A" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-FW\-A" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-fw-activate-history.html b/Documentation/nvme-wdc-vs-fw-activate-history.html index 90ba233..1f41a09 100644 --- a/Documentation/nvme-wdc-vs-fw-activate-history.html +++ b/Documentation/nvme-wdc-vs-fw-activate-history.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-fw-activate-history(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -868,7 +868,7 @@ Has the program issue WDC vs-fw-activate-history Vendor Unique Command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-vs-internal-log.1 b/Documentation/nvme-wdc-vs-internal-log.1 index 923804c..1a557e3 100644 --- a/Documentation/nvme-wdc-vs-internal-log.1 +++ b/Documentation/nvme-wdc-vs-internal-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-internal-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-INTER" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-INTER" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-internal-log.html b/Documentation/nvme-wdc-vs-internal-log.html index 1a47c3d..ef6e70e 100644 --- a/Documentation/nvme-wdc-vs-internal-log.html +++ b/Documentation/nvme-wdc-vs-internal-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-internal-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -950,7 +950,7 @@ Gets the controller telemetry log page to data area 3 from the device and stores <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-vs-nand-stats.1 b/Documentation/nvme-wdc-vs-nand-stats.1 index f41c7b1..b73d266 100644 --- a/Documentation/nvme-wdc-vs-nand-stats.1 +++ b/Documentation/nvme-wdc-vs-nand-stats.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-nand-stats .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-NAND\" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-NAND\" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-nand-stats.html b/Documentation/nvme-wdc-vs-nand-stats.html index 12e8d84..e17954b 100644 --- a/Documentation/nvme-wdc-vs-nand-stats.html +++ b/Documentation/nvme-wdc-vs-nand-stats.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-nand-stats(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -814,7 +814,7 @@ Has the program issue WDC vs-nand-stats Vendor Unique Command : <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-vs-smart-add-log.1 b/Documentation/nvme-wdc-vs-smart-add-log.1 index d4b2336..70dee3e 100644 --- a/Documentation/nvme-wdc-vs-smart-add-log.1 +++ b/Documentation/nvme-wdc-vs-smart-add-log.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-smart-add-log .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-SMART" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-SMART" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-smart-add-log.html b/Documentation/nvme-wdc-vs-smart-add-log.html index b61990a..19a9d33 100644 --- a/Documentation/nvme-wdc-vs-smart-add-log.html +++ b/Documentation/nvme-wdc-vs-smart-add-log.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-smart-add-log(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -927,7 +927,7 @@ Has the program issue WDC vs-smart-add-log Vendor Unique Command for 0xC0 and 0x <div id="footer">
<div id="footer-text">
Last updated
- 2021-10-22 12:29:47 CDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-vs-telemetry-controller-option.1 b/Documentation/nvme-wdc-vs-telemetry-controller-option.1 index 8124598..51389b3 100644 --- a/Documentation/nvme-wdc-vs-telemetry-controller-option.1 +++ b/Documentation/nvme-wdc-vs-telemetry-controller-option.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-telemetry-controller-option .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-TELEM" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-TELEM" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-telemetry-controller-option.html b/Documentation/nvme-wdc-vs-telemetry-controller-option.html index a73fdc7..372af3d 100644 --- a/Documentation/nvme-wdc-vs-telemetry-controller-option.html +++ b/Documentation/nvme-wdc-vs-telemetry-controller-option.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-telemetry-controller-option(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -853,7 +853,7 @@ Gets the current status (enabled or disabled) of the controller initiated option <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-wdc-vs-temperature-stats.1 b/Documentation/nvme-wdc-vs-temperature-stats.1 index dafb229..aa77f0a 100644 --- a/Documentation/nvme-wdc-vs-temperature-stats.1 +++ b/Documentation/nvme-wdc-vs-temperature-stats.1 @@ -2,12 +2,12 @@ .\" Title: nvme-wdc-vs-temperature-stats .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WDC\-VS\-TEMPE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WDC\-VS\-TEMPE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-wdc-vs-temperature-stats.html b/Documentation/nvme-wdc-vs-temperature-stats.html index 82a7255..a3f7b74 100644 --- a/Documentation/nvme-wdc-vs-temperature-stats.html +++ b/Documentation/nvme-wdc-vs-temperature-stats.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-wdc-vs-temperature-stats(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -857,7 +857,7 @@ Displays the temperature stats for the device: <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-write-uncor.1 b/Documentation/nvme-write-uncor.1 index 0a37514..ae057c4 100644 --- a/Documentation/nvme-write-uncor.1 +++ b/Documentation/nvme-write-uncor.1 @@ -2,12 +2,12 @@ .\" Title: nvme-uncor .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-UNCOR" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-UNCOR" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -35,6 +35,7 @@ nvme-write-uncor \- Send an NVMe write uncorrectable command, return results \fInvme\-write\-uncorr\fR <device> [\-\-start\-block=<slba> | \-s <slba>] [\-\-block\-count=<nlb> | \-c <nlb>] [\-\-namespace\-id=<nsid> | \-n <nsid>] + [\-\-force] .fi .SH "DESCRIPTION" .sp @@ -55,6 +56,11 @@ Number of logical blocks to write uncorrectable\&. .RS 4 Namespace ID use in the command\&. .RE +.PP +\-\-force +.RS 4 +Ignore namespace is currently busy and perfome the operation even though\&. +.RE .SH "EXAMPLES" .sp No examples yet\&. diff --git a/Documentation/nvme-write-uncor.html b/Documentation/nvme-write-uncor.html index 4c87d3a..7658f20 100644 --- a/Documentation/nvme-write-uncor.html +++ b/Documentation/nvme-write-uncor.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-uncor(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -751,7 +751,8 @@ nvme-uncor(1) Manual Page <div class="verseblock">
<pre class="content"><em>nvme-write-uncorr</em> <device> [--start-block=<slba> | -s <slba>]
[--block-count=<nlb> | -c <nlb>]
- [--namespace-id=<nsid> | -n <nsid>]</pre>
+ [--namespace-id=<nsid> | -n <nsid>]
+ [--force]</pre>
<div class="attribution">
</div></div>
</div>
@@ -800,6 +801,15 @@ blocks.</p></div> Namespace ID use in the command.
</p>
</dd>
+<dt class="hdlist1">
+--force
+</dt>
+<dd>
+<p>
+ Ignore namespace is currently busy and perfome the operation
+ even though.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -820,7 +830,7 @@ blocks.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-write-uncor.txt b/Documentation/nvme-write-uncor.txt index 0d824d7..41a1d87 100644 --- a/Documentation/nvme-write-uncor.txt +++ b/Documentation/nvme-write-uncor.txt @@ -11,6 +11,7 @@ SYNOPSIS 'nvme-write-uncorr' <device> [--start-block=<slba> | -s <slba>] [--block-count=<nlb> | -c <nlb>] [--namespace-id=<nsid> | -n <nsid>] + [--force] DESCRIPTION ----------- @@ -31,6 +32,10 @@ OPTIONS -n <nsid>:: Namespace ID use in the command. +--force:: + Ignore namespace is currently busy and perfome the operation + even though. + EXAMPLES -------- No examples yet. diff --git a/Documentation/nvme-write-zeroes.1 b/Documentation/nvme-write-zeroes.1 index 2f9dc87..dddd64e 100644 --- a/Documentation/nvme-write-zeroes.1 +++ b/Documentation/nvme-write-zeroes.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zeroes .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZEROES" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZEROES" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -44,6 +44,7 @@ nvme-write-zeroes \- Send an NVMe write zeroes command, return results [\-\-namespace\-id=<nsid> | \-n <nsid>] [\-\-storage\-tag<storage\-tag> | \-S <storage\-tag>] [\-\-storage\-tag\-check<storage\-tag\-check> | \-C <storage\-tag\-check>] + [\-\-force] .fi .SH "DESCRIPTION" .sp @@ -149,6 +150,11 @@ Variable Sized Expected Logical Block Storage Tag(ELBST) and Expected Logical Bl .RS 4 This bit specifies the Storage Tag field shall be checked as part of end\-to\-end data protection processing\&. .RE +.PP +\-\-force +.RS 4 +Ignore namespace is currently busy and perfome the operation even though\&. +.RE .SH "EXAMPLES" .sp No examples yet\&. diff --git a/Documentation/nvme-write-zeroes.html b/Documentation/nvme-write-zeroes.html index 0912800..d48c7c0 100644 --- a/Documentation/nvme-write-zeroes.html +++ b/Documentation/nvme-write-zeroes.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zeroes(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -760,7 +760,8 @@ nvme-zeroes(1) Manual Page [--force-unit-access | -f]
[--namespace-id=<nsid> | -n <nsid>]
[--storage-tag<storage-tag> | -S <storage-tag>]
- [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]</pre>
+ [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]
+ [--force]</pre>
<div class="attribution">
</div></div>
</div>
@@ -946,6 +947,15 @@ metadata is passes.</p></td> data protection processing.
</p>
</dd>
+<dt class="hdlist1">
+--force
+</dt>
+<dd>
+<p>
+ Ignore namespace is currently busy and perfome the operation
+ even though.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -966,7 +976,7 @@ metadata is passes.</p></td> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-09 13:42:09 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-write-zeroes.txt b/Documentation/nvme-write-zeroes.txt index 34fec9d..a644ac7 100644 --- a/Documentation/nvme-write-zeroes.txt +++ b/Documentation/nvme-write-zeroes.txt @@ -20,6 +20,7 @@ SYNOPSIS [--namespace-id=<nsid> | -n <nsid>] [--storage-tag<storage-tag> | -S <storage-tag>] [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>] + [--force] DESCRIPTION ----------- @@ -89,6 +90,10 @@ metadata is passes. This bit specifies the Storage Tag field shall be checked as part of end-to-end data protection processing. +--force:: + Ignore namespace is currently busy and perfome the operation + even though. + EXAMPLES -------- No examples yet. diff --git a/Documentation/nvme-write.1 b/Documentation/nvme-write.1 index 84a42a5..61bef8a 100644 --- a/Documentation/nvme-write.1 +++ b/Documentation/nvme-write.1 @@ -2,12 +2,12 @@ .\" Title: nvme-write .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-WRITE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-WRITE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -51,6 +51,7 @@ nvme-write \- Send an NVMe write command, provide results [\-\-dry\-run | \-w] [\-\-latency | \-t] [\-\-storage\-tag\-check<storage\-tag\-check> | \-C <storage\-tag\-check>] + [\-\-force] .fi .SH "DESCRIPTION" .sp @@ -169,7 +170,7 @@ Optional field for directive specifics\&. When used with write streams, this val .PP \-D <dsm>, \-\-dsm=<dsm> .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\&. +The optional data set management attributes for this command\&. The argument for this is the least significant 8 bits of the DSM field in a write command; the most significant 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 \-v, \-\-show\-cmd @@ -194,6 +195,11 @@ Print out the latency the IOCTL took (in us)\&. .RS 4 This bit specifies the Storage Tag field shall be checked as part of end\-to\-end data protection processing\&. .RE +.PP +\-\-force +.RS 4 +Ignore namespace is currently busy and perfome the operation even though\&. +.RE .SH "EXAMPLES" .sp No examples yet\&. diff --git a/Documentation/nvme-write.html b/Documentation/nvme-write.html index 57dccc3..620e3da 100644 --- a/Documentation/nvme-write.html +++ b/Documentation/nvme-write.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-write(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -767,7 +767,8 @@ nvme-write(1) Manual Page [--show-command | -v]
[--dry-run | -w]
[--latency | -t]
- [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]</pre>
+ [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>]
+ [--force]</pre>
<div class="attribution">
</div></div>
</div>
@@ -991,9 +992,9 @@ metadata is passes.</p></td> </dt>
<dd>
<p>
- 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
+ The optional data set management attributes for this command. The argument
+ for this is the least significant 8 bits of the DSM field in a write
+ command; the most significant 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
@@ -1048,6 +1049,15 @@ metadata is passes.</p></td> data protection processing.
</p>
</dd>
+<dt class="hdlist1">
+--force
+</dt>
+<dd>
+<p>
+ Ignore namespace is currently busy and perfome the operation
+ even though.
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -1068,7 +1078,7 @@ metadata is passes.</p></td> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-09 14:16:34 IST
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-write.txt b/Documentation/nvme-write.txt index c48e6ae..4ac46e0 100644 --- a/Documentation/nvme-write.txt +++ b/Documentation/nvme-write.txt @@ -27,6 +27,7 @@ SYNOPSIS [--dry-run | -w] [--latency | -t] [--storage-tag-check<storage-tag-check> | -C <storage-tag-check>] + [--force] DESCRIPTION ----------- @@ -114,9 +115,9 @@ metadata is passes. -D <dsm>:: --dsm=<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 + The optional data set management attributes for this command. The argument + for this is the least significant 8 bits of the DSM field in a write + command; the most significant 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 @@ -142,6 +143,10 @@ metadata is passes. This bit specifies the Storage Tag field shall be checked as part of end-to-end data protection processing. +--force:: + Ignore namespace is currently busy and perfome the operation + even though. + EXAMPLES -------- No examples yet. diff --git a/Documentation/nvme-zns-changed-zone-list.1 b/Documentation/nvme-zns-changed-zone-list.1 index 6f97254..5b7b590 100644 --- a/Documentation/nvme-zns-changed-zone-list.1 +++ b/Documentation/nvme-zns-changed-zone-list.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-changed-zone-list .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-CHANGED\-" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-CHANGED\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-changed-zone-list.html b/Documentation/nvme-zns-changed-zone-list.html index 1d97c92..c82f18a 100644 --- a/Documentation/nvme-zns-changed-zone-list.html +++ b/Documentation/nvme-zns-changed-zone-list.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-changed-zone-list(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -833,7 +833,7 @@ Show the output in json format <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-close-zone.1 b/Documentation/nvme-zns-close-zone.1 index 08b3a2b..19056da 100644 --- a/Documentation/nvme-zns-close-zone.1 +++ b/Documentation/nvme-zns-close-zone.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-close-zone .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-CLOSE\-ZO" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-CLOSE\-ZO" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-close-zone.html b/Documentation/nvme-zns-close-zone.html index 17795a1..a6bc683 100644 --- a/Documentation/nvme-zns-close-zone.html +++ b/Documentation/nvme-zns-close-zone.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-close-zone(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -842,7 +845,8 @@ Close all zones on namespace 1: <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-26 14:39:37 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-finish-zone.1 b/Documentation/nvme-zns-finish-zone.1 index 2a612a4..7eb59d4 100644 --- a/Documentation/nvme-zns-finish-zone.1 +++ b/Documentation/nvme-zns-finish-zone.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-finish-zone .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-FINISH\-Z" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-FINISH\-Z" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-finish-zone.html b/Documentation/nvme-zns-finish-zone.html index 5a23efc..84d2c2d 100644 --- a/Documentation/nvme-zns-finish-zone.html +++ b/Documentation/nvme-zns-finish-zone.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-finish-zone(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -843,7 +846,8 @@ Finish all zones on namespace 1: <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-26 14:39:40 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-id-ctrl.1 b/Documentation/nvme-zns-id-ctrl.1 index afe8fea..3c6ffa3 100644 --- a/Documentation/nvme-zns-id-ctrl.1 +++ b/Documentation/nvme-zns-id-ctrl.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-id-ctrl .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-ID\-CTRL" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-ID\-CTRL" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-id-ctrl.html b/Documentation/nvme-zns-id-ctrl.html index 990564f..caa9a41 100644 --- a/Documentation/nvme-zns-id-ctrl.html +++ b/Documentation/nvme-zns-id-ctrl.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-id-ctrl(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -821,7 +821,7 @@ Show the output in json format <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-id-ns.1 b/Documentation/nvme-zns-id-ns.1 index 372f761..e9fb1bd 100644 --- a/Documentation/nvme-zns-id-ns.1 +++ b/Documentation/nvme-zns-id-ns.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-id-ns .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-ID\-NS" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-ID\-NS" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,7 +28,7 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -nvme-zns-id-ns \- Send NVMe Zoned Command Set Identify Controller, return result and structure +nvme-zns-id-ns \- Send NVMe Zoned Command Set Identify namespace, return result and structure .SH "SYNOPSIS" .sp .nf diff --git a/Documentation/nvme-zns-id-ns.html b/Documentation/nvme-zns-id-ns.html index c76f9fa..b5bffb3 100644 --- a/Documentation/nvme-zns-id-ns.html +++ b/Documentation/nvme-zns-id-ns.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-id-ns(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -737,7 +740,7 @@ nvme-zns-id-ns(1) Manual Page <h2>NAME</h2>
<div class="sectionbody">
<p>nvme-zns-id-ns -
- Send NVMe Zoned Command Set Identify Controller, return result and structure
+ Send NVMe Zoned Command Set Identify namespace, return result and structure
</p>
</div>
</div>
@@ -843,7 +846,8 @@ Show the output in json format with extra details <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2020-06-28 19:43:32 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-id-ns.txt b/Documentation/nvme-zns-id-ns.txt index a95d975..dccb02c 100644 --- a/Documentation/nvme-zns-id-ns.txt +++ b/Documentation/nvme-zns-id-ns.txt @@ -3,7 +3,7 @@ nvme-zns-id-ns(1) NAME ---- -nvme-zns-id-ns - Send NVMe Zoned Command Set Identify Controller, return +nvme-zns-id-ns - Send NVMe Zoned Command Set Identify namespace, return result and structure SYNOPSIS diff --git a/Documentation/nvme-zns-offline-zone.1 b/Documentation/nvme-zns-offline-zone.1 index a29116f..6570408 100644 --- a/Documentation/nvme-zns-offline-zone.1 +++ b/Documentation/nvme-zns-offline-zone.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-offline-zone .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-OFFLINE\-" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-OFFLINE\-" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-offline-zone.html b/Documentation/nvme-zns-offline-zone.html index 6beef9e..d59c833 100644 --- a/Documentation/nvme-zns-offline-zone.html +++ b/Documentation/nvme-zns-offline-zone.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-offline-zone(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -842,7 +845,8 @@ Offline all zones on namespace 1: <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-26 14:39:22 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-open-zone.1 b/Documentation/nvme-zns-open-zone.1 index 7248547..4695a01 100644 --- a/Documentation/nvme-zns-open-zone.1 +++ b/Documentation/nvme-zns-open-zone.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-open-zone .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-OPEN\-ZON" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-OPEN\-ZON" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -33,9 +33,10 @@ nvme-zns-open-zone \- Opens one or all zones .sp .nf \fInvme zns open\-zone\fR <device> [\-\-namespace\-id=<NUM> | \-n <NUM>] - [\-\-start\-lba=<LBA> | \-s <LBA>] - [\-\-select\-all | \-a] - [\-\-timeout=<timeout> | \-t <timeout>] + [\-\-start\-lba=<LBA> | \-s <LBA>] + [\-\-zrwaa | \-r] + [\-\-select\-all | \-a] + [\-\-timeout=<timeout> | \-t <timeout>] .fi .SH "DESCRIPTION" .sp @@ -54,6 +55,11 @@ Use the provided namespace id for the command\&. If not provided, the namespace The starting LBA of the zone to open\&. .RE .PP +\-r, \-\-zrwaa +.RS 4 +Allocate Zone Random Write Area to zone +.RE +.PP \-a, \-\-select\-all .RS 4 Select all zones for this action diff --git a/Documentation/nvme-zns-open-zone.html b/Documentation/nvme-zns-open-zone.html index 62a7e12..56f6fcf 100644 --- a/Documentation/nvme-zns-open-zone.html +++ b/Documentation/nvme-zns-open-zone.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-open-zone(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -747,9 +750,10 @@ nvme-zns-open-zone(1) Manual Page <div class="sectionbody">
<div class="verseblock">
<pre class="content"><em>nvme zns open-zone</em> <device> [--namespace-id=<NUM> | -n <NUM>]
- [--start-lba=<LBA> | -s <LBA>]
- [--select-all | -a]
- [--timeout=<timeout> | -t <timeout>]</pre>
+ [--start-lba=<LBA> | -s <LBA>]
+ [--zrwaa | -r]
+ [--select-all | -a]
+ [--timeout=<timeout> | -t <timeout>]</pre>
<div class="attribution">
</div></div>
</div>
@@ -792,6 +796,17 @@ device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></di </p>
</dd>
<dt class="hdlist1">
+-r
+</dt>
+<dt class="hdlist1">
+--zrwaa
+</dt>
+<dd>
+<p>
+ Allocate Zone Random Write Area to zone
+</p>
+</dd>
+<dt class="hdlist1">
-a
</dt>
<dt class="hdlist1">
@@ -842,7 +857,8 @@ Open the first zone on namespace 1: <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-26 14:39:34 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-open-zone.txt b/Documentation/nvme-zns-open-zone.txt index bf1c911..0f2cb35 100644 --- a/Documentation/nvme-zns-open-zone.txt +++ b/Documentation/nvme-zns-open-zone.txt @@ -9,9 +9,10 @@ SYNOPSIS -------- [verse] 'nvme zns open-zone' <device> [--namespace-id=<NUM> | -n <NUM>] - [--start-lba=<LBA> | -s <LBA>] - [--select-all | -a] - [--timeout=<timeout> | -t <timeout>] + [--start-lba=<LBA> | -s <LBA>] + [--zrwaa | -r] + [--select-all | -a] + [--timeout=<timeout> | -t <timeout>] DESCRIPTION ----------- @@ -31,7 +32,11 @@ OPTIONS -s <lba>:: --start-lba=<lba>:: - The starting LBA of the zone to open. + The starting LBA of the zone to open. + +-r:: +--zrwaa:: + Allocate Zone Random Write Area to zone -a:: --select-all:: diff --git a/Documentation/nvme-zns-report-zones.1 b/Documentation/nvme-zns-report-zones.1 index 7ecfe39..c92ff88 100644 --- a/Documentation/nvme-zns-report-zones.1 +++ b/Documentation/nvme-zns-report-zones.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-report-zones .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-REPORT\-Z" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-REPORT\-Z" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-report-zones.html b/Documentation/nvme-zns-report-zones.html index ca7a60a..ba66889 100644 --- a/Documentation/nvme-zns-report-zones.html +++ b/Documentation/nvme-zns-report-zones.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-report-zones(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -957,7 +957,7 @@ Show the output in json format with extra details <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-reset-zone.1 b/Documentation/nvme-zns-reset-zone.1 index dd2a2bd..70c2f25 100644 --- a/Documentation/nvme-zns-reset-zone.1 +++ b/Documentation/nvme-zns-reset-zone.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-reset-zone .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-RESET\-ZO" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-RESET\-ZO" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-reset-zone.html b/Documentation/nvme-zns-reset-zone.html index d61e61b..a2356d1 100644 --- a/Documentation/nvme-zns-reset-zone.html +++ b/Documentation/nvme-zns-reset-zone.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-reset-zone(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -843,7 +846,8 @@ Reset the first zone on namespace 1: <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-26 14:44:16 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-set-zone-desc.1 b/Documentation/nvme-zns-set-zone-desc.1 index 1a38132..f774410 100644 --- a/Documentation/nvme-zns-set-zone-desc.1 +++ b/Documentation/nvme-zns-set-zone-desc.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-set-zone-desc .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-SET\-ZONE" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-SET\-ZONE" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -34,6 +34,7 @@ nvme-zns-set-zone-desc \- Set extended descriptor data for a zone .nf \fInvme zns setzone\-desc\fR <device> [\-\-namespace\-id=<NUM> | \-n <NUM>] [\-\-start\-lba=<IONUM>, \-s <IONUM>] + [\-\-zrwaa | \-r] [\-data=<FILE>, \-d <FILE>] [\-\-timeout=<timeout> | \-t <timeout>] .fi @@ -52,6 +53,11 @@ Use the provided namespace id for the command\&. If not provided, the namespace The starting LBA of the zone to manage send\&. .RE .PP +\-r, \-\-zrwaa +.RS 4 +Allocate Zone Random Write Area to zone\&. +.RE +.PP \-d <FILE, \-data=<FILE> .RS 4 Optional file for data (default stdin) diff --git a/Documentation/nvme-zns-set-zone-desc.html b/Documentation/nvme-zns-set-zone-desc.html index 3fe678b..f2f22db 100644 --- a/Documentation/nvme-zns-set-zone-desc.html +++ b/Documentation/nvme-zns-set-zone-desc.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-set-zone-desc(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -748,6 +751,7 @@ nvme-zns-set-zone-desc(1) Manual Page <div class="verseblock">
<pre class="content"><em>nvme zns setzone-desc</em> <device> [--namespace-id=<NUM> | -n <NUM>]
[--start-lba=<IONUM>, -s <IONUM>]
+ [--zrwaa | -r]
[-data=<FILE>, -d <FILE>]
[--timeout=<timeout> | -t <timeout>]</pre>
<div class="attribution">
@@ -792,6 +796,17 @@ length will automatically be calculated from the zns identify namesapce.</p></di </p>
</dd>
<dt class="hdlist1">
+-r
+</dt>
+<dt class="hdlist1">
+--zrwaa
+</dt>
+<dd>
+<p>
+ Allocate Zone Random Write Area to zone.
+</p>
+</dd>
+<dt class="hdlist1">
-d <FILE
</dt>
<dt class="hdlist1">
@@ -843,7 +858,8 @@ Write "hello world" into the zone descriptor for namespace 1’s first zone <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-26 14:39:19 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-set-zone-desc.txt b/Documentation/nvme-zns-set-zone-desc.txt index 880d405..ca598b8 100644 --- a/Documentation/nvme-zns-set-zone-desc.txt +++ b/Documentation/nvme-zns-set-zone-desc.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'nvme zns setzone-desc' <device> [--namespace-id=<NUM> | -n <NUM>] [--start-lba=<IONUM>, -s <IONUM>] + [--zrwaa | -r] [-data=<FILE>, -d <FILE>] [--timeout=<timeout> | -t <timeout>] @@ -32,6 +33,10 @@ OPTIONS --start-lba=<lba>:: The starting LBA of the zone to manage send. +-r:: +--zrwaa:: + Allocate Zone Random Write Area to zone. + -d <FILE:: -data=<FILE>:: Optional file for data (default stdin) diff --git a/Documentation/nvme-zns-zone-append.1 b/Documentation/nvme-zns-zone-append.1 index d342df0..20d3a5e 100644 --- a/Documentation/nvme-zns-zone-append.1 +++ b/Documentation/nvme-zns-zone-append.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-zone-append .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-ZONE\-APP" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-ZONE\-APP" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-zone-append.html b/Documentation/nvme-zns-zone-append.html index 0696078..4233f5a 100644 --- a/Documentation/nvme-zns-zone-append.html +++ b/Documentation/nvme-zns-zone-append.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-zone-append(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -940,7 +940,7 @@ Append the data "hello world" into 4k worth of blocks into the zone starting <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-zone-mgmt-recv.1 b/Documentation/nvme-zns-zone-mgmt-recv.1 index 2c96d12..963f1b4 100644 --- a/Documentation/nvme-zns-zone-mgmt-recv.1 +++ b/Documentation/nvme-zns-zone-mgmt-recv.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-zone-mgmt-recv .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-ZONE\-MGM" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-ZONE\-MGM" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/Documentation/nvme-zns-zone-mgmt-recv.html b/Documentation/nvme-zns-zone-mgmt-recv.html index 82b0d2a..653c1e7 100644 --- a/Documentation/nvme-zns-zone-mgmt-recv.html +++ b/Documentation/nvme-zns-zone-mgmt-recv.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-zone-mgmt-recv(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -882,7 +882,7 @@ Binary dump of a report all zones <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-zone-mgmt-send.1 b/Documentation/nvme-zns-zone-mgmt-send.1 index 73f3ed7..5c14c5e 100644 --- a/Documentation/nvme-zns-zone-mgmt-send.1 +++ b/Documentation/nvme-zns-zone-mgmt-send.1 @@ -2,12 +2,12 @@ .\" Title: nvme-zns-zone-mgmt-send .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-ZNS\-ZONE\-MGM" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-ZONE\-MGM" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -34,10 +34,11 @@ nvme-zns-zone-mgmt-send \- Zone Management Send command .nf \fInvme zns zone\-mgmt\-send\fR <device> [\-\-namespace\-id=<NUM> | \-n <NUM>] [\-\-start\-lba=<IONUM>, \-s <IONUM>] + [\-\-zsaso, \-o] [\-\-select\-all, \-a] [\-\-zsa=<NUM>, \-z <NUM>] [\-\-data\-len=<IONUM>, \-l <IONUM>] - [\-data=<FILE>, \-d <FILE>] + [\-\-data=<FILE>, \-d <FILE>] [\-\-timeout=<timeout> | \-t <timeout>] .fi .SH "DESCRIPTION" @@ -60,6 +61,11 @@ The starting LBA of the zone to manage send\&. Send data buffer length .RE .PP +\-o, \-\-zsaso +.RS 4 +Zone Send Action Specific Option +.RE +.PP \-\-select\-all, \-a .RS 4 Send command to all zones @@ -75,7 +81,7 @@ Zone send action\&. Buffer length if data required .RE .PP -\-d <FILE, \-data=<FILE> +\-d <FILE, \-\-data=<FILE> .RS 4 Optional file for data (default stdin) .RE diff --git a/Documentation/nvme-zns-zone-mgmt-send.html b/Documentation/nvme-zns-zone-mgmt-send.html index d74cc25..9d1cd82 100644 --- a/Documentation/nvme-zns-zone-mgmt-send.html +++ b/Documentation/nvme-zns-zone-mgmt-send.html @@ -1,9 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.8" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme-zns-zone-mgmt-send(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -94,7 +95,9 @@ ul > li > * { color: black; } padding: 0;
margin: 0;
}
-
+pre {
+ white-space: pre-wrap;
+}
#author {
color: #527bbd;
@@ -223,7 +226,7 @@ div.exampleblock > div.content { }
div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
+span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
@@ -433,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -748,10 +751,11 @@ nvme-zns-zone-mgmt-send(1) Manual Page <div class="verseblock">
<pre class="content"><em>nvme zns zone-mgmt-send</em> <device> [--namespace-id=<NUM> | -n <NUM>]
[--start-lba=<IONUM>, -s <IONUM>]
+ [--zsaso, -o]
[--select-all, -a]
[--zsa=<NUM>, -z <NUM>]
[--data-len=<IONUM>, -l <IONUM>]
- [-data=<FILE>, -d <FILE>]
+ [--data=<FILE>, -d <FILE>]
[--timeout=<timeout> | -t <timeout>]</pre>
<div class="attribution">
</div></div>
@@ -806,6 +810,17 @@ Alternatively, the data may come from a file that can be specified.</p></div> </p>
</dd>
<dt class="hdlist1">
+-o
+</dt>
+<dt class="hdlist1">
+--zsaso
+</dt>
+<dd>
+<p>
+ Zone Send Action Specific Option
+</p>
+</dd>
+<dt class="hdlist1">
--select-all
</dt>
<dt class="hdlist1">
@@ -842,7 +857,7 @@ Alternatively, the data may come from a file that can be specified.</p></div> -d <FILE
</dt>
<dt class="hdlist1">
--data=<FILE>
+--data=<FILE>
</dt>
<dd>
<p>
@@ -900,7 +915,8 @@ Write "hello world" into the zone descriptor for namespace 1’s first zone <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2021-08-26 14:39:47 KST
+Last updated
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-zone-mgmt-send.txt b/Documentation/nvme-zns-zone-mgmt-send.txt index bf34d5e..8cbb5c0 100644 --- a/Documentation/nvme-zns-zone-mgmt-send.txt +++ b/Documentation/nvme-zns-zone-mgmt-send.txt @@ -10,10 +10,11 @@ SYNOPSIS [verse] 'nvme zns zone-mgmt-send' <device> [--namespace-id=<NUM> | -n <NUM>] [--start-lba=<IONUM>, -s <IONUM>] + [--zsaso, -o] [--select-all, -a] [--zsa=<NUM>, -z <NUM>] [--data-len=<IONUM>, -l <IONUM>] - [-data=<FILE>, -d <FILE>] + [--data=<FILE>, -d <FILE>] [--timeout=<timeout> | -t <timeout>] DESCRIPTION @@ -39,6 +40,10 @@ OPTIONS --data-len=<NUM>:: Send data buffer length +-o:: +--zsaso:: + Zone Send Action Specific Option + --select-all:: -a:: Send command to all zones @@ -52,7 +57,7 @@ OPTIONS Buffer length if data required -d <FILE:: --data=<FILE>:: +--data=<FILE>:: Optional file for data (default stdin) -t <timeout>:: diff --git a/Documentation/nvme-lnvm-factory.1 b/Documentation/nvme-zns-zrwa-flush-zone.1 index c95396c..fb88210 100644 --- a/Documentation/nvme-lnvm-factory.1 +++ b/Documentation/nvme-zns-zrwa-flush-zone.1 @@ -1,13 +1,13 @@ '\" t -.\" Title: nvme-lnvm-factory +.\" Title: nvme-zns-zrwa-flush-zone .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 12/13/2021 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME\-LNVM\-FACTORY" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME\-ZNS\-ZRWA\-FLU" "1" "12/13/2021" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,38 +28,34 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -nvme-lnvm-factory \- Factory reset a LightNVM device +nvme-zns-zrwa-flush-zone \- Flush LBAs associated with a ZRWA to a zone .SH "SYNOPSIS" .sp .nf -\fInvme lnvm\-factory\fR [\-\-device\-name=<DEVICE> | \-d <DEVICE>] - [\-\-erase\-only\-marked | \-e] - [\-\-clear\-host\-side\-blks | \-s] - [\-\-clear\-bb\-blks | \-b] +\fInvme zns zrwa\-flush\-zone\fR <device> [\-\-namespace\-id=<NUM> | \-n <NUM>] + [\-\-lba=<LBA> | \-l <LBA>] + [\-\-timeout=<timeout> | \-t <timeout> ] .fi .SH "DESCRIPTION" .sp -Instantiate a target on top of a LightNVM enabled device\&. This exposes the physical for the user to use\&. +For the NVMe device given, issues the Zone Management Send command with the "flush Zone" action\&. This will flush the zone that is opened as zone random write area\&. +.sp +The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. .SH "OPTIONS" .PP -\-\-device\-name=<DEVICE>, \-d <DEVICE> -.RS 4 -Device name to factory initialize -.RE -.PP -\-\-erase\-only\-marked, \-e +\-n <NUM>, \-\-namespace\-id=<NUM> .RS 4 -Erases only blocks that are marked in the bad block list +Use the provided namespace id for the command\&. If not provided, the namespace id of the block device will be used\&. If the command is issued to a non\-block device, the parameter is required\&. .RE .PP -\-\-clear\-host\-side\-blks, \-s +\-l <lba>, \-\-lba=<lba> .RS 4 -Remove host\-side bad block marks\&. This clear the media manager registration +The LBA to flush up to\&. .RE .PP -\-\-clear\-bb\-blks, \-b +\-t <timeout>, \-\-timeout=<timeout> .RS 4 -Removes the grown bad block marks\&. Allowing them to be rediscovered\&. +Override default timeout value\&. In milliseconds\&. .RE .SH "EXAMPLES" .sp @@ -71,39 +67,18 @@ Removes the grown bad block marks\&. Allowing them to be rediscovered\&. .sp -1 .IP \(bu 2.3 .\} -Factory reset of device nvme0n1 -.RE +flush the first zwra of first zone for zrwacg(15) on namespace 1: .sp .if n \{\ .RS 4 .\} .nf -# nvme lnvm\-factory \-d nvme0n1 +# nvme zns zrwa\-flush\-zone /dev/nvme0 \-n 1 \-l 15 .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 +Part of nvme\-cli diff --git a/Documentation/nvme-lnvm-factory.html b/Documentation/nvme-zns-zrwa-flush-zone.html index 44a3b1c..38a013f 100644 --- a/Documentation/nvme-lnvm-factory.html +++ b/Documentation/nvme-zns-zrwa-flush-zone.html @@ -4,8 +4,8 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
-<title>nvme-lnvm-factory(1)</title>
+<meta name="generator" content="AsciiDoc" />
+<title>nvme-zns-zrwa-flush-zone(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -735,12 +735,12 @@ asciidoc.install(); <body class="manpage">
<div id="header">
<h1>
-nvme-lnvm-factory(1) Manual Page
+nvme-zns-zrwa-flush-zone(1) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>nvme-lnvm-factory -
- Factory reset a LightNVM device
+<p>nvme-zns-zrwa-flush-zone -
+ Flush LBAs associated with a ZRWA to a zone
</p>
</div>
</div>
@@ -749,10 +749,9 @@ nvme-lnvm-factory(1) Manual Page <h2 id="_synopsis">SYNOPSIS</h2>
<div class="sectionbody">
<div class="verseblock">
-<pre class="content"><em>nvme lnvm-factory</em> [--device-name=<DEVICE> | -d <DEVICE>]
- [--erase-only-marked | -e]
- [--clear-host-side-blks | -s]
- [--clear-bb-blks | -b]</pre>
+<pre class="content"><em>nvme zns zrwa-flush-zone</em> <device> [--namespace-id=<NUM> | -n <NUM>]
+ [--lba=<LBA> | -l <LBA>]
+ [--timeout=<timeout> | -t <timeout> ]</pre>
<div class="attribution">
</div></div>
</div>
@@ -760,8 +759,11 @@ nvme-lnvm-factory(1) Manual Page <div class="sect1">
<h2 id="_description">DESCRIPTION</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Instantiate a target on top of a LightNVM enabled device. This exposes the
-physical for the user to use.</p></div>
+<div class="paragraph"><p>For the NVMe device given, issues the Zone Management Send command with the
+"flush Zone" action. This will flush the zone that is opened as
+zone random write area.</p></div>
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>
</div>
</div>
<div class="sect1">
@@ -769,48 +771,38 @@ physical for the user to use.</p></div> <div class="sectionbody">
<div class="dlist"><dl>
<dt class="hdlist1">
---device-name=<DEVICE>
+-n <NUM>
</dt>
<dt class="hdlist1">
--d <DEVICE>
+--namespace-id=<NUM>
</dt>
<dd>
<p>
- Device name to factory initialize
+ Use the provided namespace id for the command. If not provided, the
+ namespace id of the block device will be used. If the command is issued
+ to a non-block device, the parameter is required.
</p>
</dd>
<dt class="hdlist1">
---erase-only-marked
+-l <lba>
</dt>
<dt class="hdlist1">
--e
+--lba=<lba>
</dt>
<dd>
<p>
- Erases only blocks that are marked in the bad block list
+ The LBA to flush up to.
</p>
</dd>
<dt class="hdlist1">
---clear-host-side-blks
+-t <timeout>
</dt>
<dt class="hdlist1">
--s
+--timeout=<timeout>
</dt>
<dd>
<p>
- Remove host-side bad block marks. This clear the media manager
- registration
-</p>
-</dd>
-<dt class="hdlist1">
---clear-bb-blks
-</dt>
-<dt class="hdlist1">
--b
-</dt>
-<dd>
-<p>
- Removes the grown bad block marks. Allowing them to be rediscovered.
+ Override default timeout value. In milliseconds.
</p>
</dd>
</dl></div>
@@ -822,31 +814,20 @@ physical for the user to use.</p></div> <div class="ulist"><ul>
<li>
<p>
-Factory reset of device nvme0n1
+flush the first zwra of first zone for zrwacg(15) on namespace 1:
</p>
-</li>
-</ul></div>
<div class="listingblock">
<div class="content">
-<pre><code># nvme lnvm-factory -d nvme0n1</code></pre>
+<pre><code># nvme zns zrwa-flush-zone /dev/nvme0 -n 1 -l 15</code></pre>
</div></div>
-<div class="ulist"><ul>
-<li>
-<p>
-Complete factory reset of device nvme0n1
-</p>
</li>
</ul></div>
-<div class="listingblock">
-<div class="content">
-<pre><code># nvme lnvm-factory -d nvme0n1 -s -b</code></pre>
-</div></div>
</div>
</div>
<div class="sect1">
<h2 id="_nvme">NVME</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Part of the nvme-user suite</p></div>
+<div class="paragraph"><p>Part of nvme-cli</p></div>
</div>
</div>
</div>
@@ -854,7 +835,7 @@ Complete factory reset of device nvme0n1 <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2021-12-13 19:30:31 CET
</div>
</div>
</body>
diff --git a/Documentation/nvme-zns-zrwa-flush-zone.txt b/Documentation/nvme-zns-zrwa-flush-zone.txt new file mode 100644 index 0000000..19e7926 --- /dev/null +++ b/Documentation/nvme-zns-zrwa-flush-zone.txt @@ -0,0 +1,50 @@ +nvme-zns-zrwa-flush-zone(1) +=========================== + +NAME +---- +nvme-zns-zrwa-flush-zone - Flush LBAs associated with a ZRWA to a zone + +SYNOPSIS +-------- +[verse] +'nvme zns zrwa-flush-zone' <device> [--namespace-id=<NUM> | -n <NUM>] + [--lba=<LBA> | -l <LBA>] + [--timeout=<timeout> | -t <timeout> ] + +DESCRIPTION +----------- +For the NVMe device given, issues the Zone Management Send command with the +"flush Zone" action. This will flush the zone that is opened as +zone random write area. + +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 +------- +-n <NUM>:: +--namespace-id=<NUM>:: + Use the provided namespace id for the command. If not provided, the + namespace id of the block device will be used. If the command is issued + to a non-block device, the parameter is required. + +-l <lba>:: +--lba=<lba>:: + The LBA to flush up to. + +-t <timeout>:: +--timeout=<timeout>:: + Override default timeout value. In milliseconds. + +EXAMPLES +-------- +* flush the first zwra of first zone for zrwacg(15) on namespace 1: ++ +------------ +# nvme zns zrwa-flush-zone /dev/nvme0 -n 1 -l 15 +------------ + +NVME +---- +Part of nvme-cli diff --git a/Documentation/nvme.1 b/Documentation/nvme.1 index f1593d9..6162752 100644 --- a/Documentation/nvme.1 +++ b/Documentation/nvme.1 @@ -2,12 +2,12 @@ .\" Title: nvme .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 11/11/2021 +.\" Date: 04/08/2022 .\" Manual: NVMe Manual .\" Source: NVMe .\" Language: English .\" -.TH "NVME" "1" "11/11/2021" "NVMe" "NVMe Manual" +.TH "NVME" "1" "04/08/2022" "NVMe" "NVMe Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -73,7 +73,7 @@ Retrieve error logs Submit flush .RE .PP -\fBnvme-dms\fR(1) +\fBnvme-dsm\fR(1) .RS 4 Submit Data Set Management .RE @@ -323,6 +323,11 @@ Discover and connect to all NVMe\-over\-Fabrics subsystems Connect to an NVMe\-over\-Fabrics subsystem .RE .PP +\fBnvme-dim\fR(1) +.RS 4 +Send Discovery Information Management command to a Discovery Controller +.RE +.PP \fBnvme-disconnect\fR(1) .RS 4 Disconnect from an NVMe\-over\-Fabrics subsystem @@ -337,6 +342,507 @@ Disconnect from all NVMe\-over\-Fabrics subsystems .RS 4 Reads and shows NVMe\-over\-Fabrics controller property .RE +.PP +\fBnvme-media-unit-stat-log\fR(1) +.RS 4 +Retrieve and show the configuration and wear of media units +.RE +.PP +\fBnvme-supported-cap-config-log\fR(1) +.RS 4 +Retrieve and show the list of Supported Capacity Configuration Descriptors +.RE +.PP +\fBnvme-boot-part-log\fR(1) +.RS 4 +Retrieve Boot Partition Log +.RE +.PP +\fBnvme-capacity-mgmt\fR(1) +.RS 4 +Capacity Management Command +.RE +.PP +\fBnvme-check-dhchap-key\fR(1) +.RS 4 +Generate NVMeoF DH\-HMAC\-CHAP host key +.RE +.PP +\fBnvme-check-tls-key\fR(1) +.RS 4 +Validate NVMeoF TLS PSK +.RE +.PP +\fBnvme-cmdset-ind-id-ns\fR(1) +.RS 4 +I/O Command Set Independent Identify Namespace +.RE +.PP +\fBnvme-endurance-event-agg-log\fR(1) +.RS 4 +Retrieve Endurance Group Event Aggregate Log +.RE +.PP +\fBnvme-fid-support-effects-log\fR(1) +.RS 4 +Retrieve FID Support and Effects log +.RE +.PP +\fBnvme-gen-dhchap-key\fR(1) +.RS 4 +Generate NVMeoF DH\-HMAC\-CHAP host key +.RE +.PP +\fBnvme-gen-hostnqn\fR(1) +.RS 4 +Generate NVMeoF host NQN +.RE +.PP +\fBnvme-gen-tls-key\fR(1) +.RS 4 +Generate NVMeoF TLS PSK +.RE +.PP +\fBnvme-get-lba-status\fR(1) +.RS 4 +Get LBA Status command +.RE +.PP +\fBnvme-id-domain\fR(1) +.RS 4 +NVMe Identify Domain List +.RE +.PP +\fBnvme-id-ns-lba-format\fR(1) +.RS 4 +NVMe Identify Namespace for the specified LBA Format index +.RE +.PP +\fBnvme-lba-status-log\fR(1) +.RS 4 +Retrieve LBA Status Information Log +.RE +.PP +\fBnvme-list-endgrp\fR(1) +.RS 4 +NVMe Identify Endurance Group List +.RE +.PP +\fBnvme-ns-rescan\fR(1) +.RS 4 +Rescans the NVME namespaces +.RE +.PP +\fBnvme-nvm-id-ctrl\fR(1) +.RS 4 +NVMe Identify Controller NVM Command Set +.RE +.PP +\fBnvme-nvm-id-ns\fR(1) +.RS 4 +NVMe Identify Namespace NVM Command Set +.RE +.PP +\fBnvme-nvm-id-ns-lba-format\fR(1) +.RS 4 +NVMe Identify Namespace NVM Command Set for the specified LBA Format index +.RE +.PP +\fBnvme-persistent-event-log\fR(1) +.RS 4 +Retrieve Presistent Event Log +.RE +.PP +\fBnvme-predictable-lat-log\fR(1) +.RS 4 +Retrieve Predictable Latency per Nvmset Log +.RE +.PP +\fBnvme-pred-lat-event-agg-log\fR(1) +.RS 4 +Retrieve Predictable Latency Event Aggregate Log +.RE +.PP +\fBnvme-primary-ctrl-caps\fR(1) +.RS 4 +NVMe Identify Primary Controller Capabilities +.RE +.PP +\fBnvme-reset\fR(1) +.RS 4 +Resets the controller +.RE +.PP +\fBnvme-rpmb\fR(1) +.RS 4 +Replay Protection Memory Block commands +.RE +.PP +\fBnvme-sanitize-log\fR(1) +.RS 4 +Retrieve sanitize log +.RE +.PP +\fBnvme-set-property\fR(1) +.RS 4 +Set a property and show the resulting value +.RE +.PP +\fBnvme-show-hostnqn\fR(1) +.RS 4 +Show NVMeoF host NQN +.RE +.PP +\fBnvme-subsystem-reset\fR(1) +.RS 4 +Resets the subsystem +.RE +.PP +\fBnvme-supported-log-pages\fR(1) +.RS 4 +Retrieve the Supported Log pages details +.RE +.PP +\fBnvme-verify\fR(1) +.RS 4 +verify command +.RE +.SS "Plugins/Vendor extension commands" +.PP +\fBnvme-intel-id-ctrl\fR(1) +.RS 4 +Intel \- NVMe Identify Controller +.RE +.PP +\fBnvme-intel-internal-log\fR(1) +.RS 4 +Retrieve Intel device\(cqs internal log and save to file +.RE +.PP +\fBnvme-intel-lat-stats\fR(1) +.RS 4 +Retrieve NVMe Identify Controller, return result and structure +.RE +.PP +\fBnvme-intel-market-name\fR(1) +.RS 4 +Intel vendor specific marketing name log page +.RE +.PP +\fBnvme-intel-smart-log-add\fR(1) +.RS 4 +NVMe Intel Additional SMART log page +.RE +.PP +\fBnvme-intel-temp-stats\fR(1) +.RS 4 +NVMe Intel Additional SMART log page for temp stats +.RE +.PP +\fBnvme-huawei-id-ctrl\fR(1) +.RS 4 +NVMe huawei Identify Controller +.RE +.PP +\fBnvme-huawei-list\fR(1) +.RS 4 +List all recognized Huawei NVMe devices +.RE +.PP +\fBnvme-dera-stat\fR(1) +.RS 4 +NVMe Dera Device status and Additional SMART log page request +.RE +.PP +\fBnvme-micron-clear-pcie-errors\fR(1) +.RS 4 +Clears correctable PCIe correctable errors of given Micron device +.RE +.PP +\fBnvme-micron-internal-log\fR(1) +.RS 4 +Retrieve Micron device\(cqs internal logs and save to given zip file +.RE +.PP +\fBnvme-micron-nand-stats\fR(1) +.RS 4 +Retrieves NAND statistics of given micron device +.RE +.PP +\fBnvme-micron-pcie-stats\fR(1) +.RS 4 +Retrieves pcie error statistics for given micron device +.RE +.PP +\fBnvme-micron-selective-download\fR(1) +.RS 4 +Performs selective firmware download +.RE +.PP +\fBnvme-micron-smart-add-log\fR(1) +.RS 4 +Retrieves NAND statistics +.RE +.PP +\fBnvme-micron-temperature-stats\fR(1) +.RS 4 +Retrieves temperature information of given micron device +.RE +.PP +\fBnvme-netapp-ontapdevices\fR(1) +.RS 4 +Display information about ONTAP devices +.RE +.PP +\fBnvme-netapp-smdevices\fR(1) +.RS 4 +Display information for each NVMe path to an E\-Series volume +.RE +.PP +\fBnvme-toshiba-clear-pcie-correctable-errors\fR(1) +.RS 4 +Reset the PCIe correctable errors count to zero +.RE +.PP +\fBnvme-toshiba-vs-internal-log\fR(1) +.RS 4 +Retrieve a Toshiba device\(cqs vendor specific internal log +.RE +.PP +\fBnvme-toshiba-vs-smart-add-log\fR(1) +.RS 4 +Retrieve a Toshiba device\(cqs vendor specific extended SMART log page +.RE +.PP +\fBnvme-transcend-badblock\fR(1) +.RS 4 +Retrieve Transcend NVMe device\(cqs bad blocks +.RE +.PP +\fBnvme-transcend-healthvalue\fR(1) +.RS 4 +Use NVMe SMART table to analyse the health value of Transcend device +.RE +.PP +\fBnvme-virtium-show-identify\fR(1) +.RS 4 +Show a complete detail of identify device information in json format +.RE +.PP +\fBnvme-virtium-save-smart-to-vtview-log\fR(1) +.RS 4 +Periodically save smart attributes into a log file +.RE +.PP +\fBnvme-wdc-cap-diag\fR(1) +.RS 4 +Retrieve WDC device\(cqs diagnostic log and save to file +.RE +.PP +\fBnvme-wdc-capabilities\fR(1) +.RS 4 +Display WDC plugin command capabilities +.RE +.PP +\fBnvme-wdc-clear-assert-dump\fR(1) +.RS 4 +Clears the assert dump (if present) +.RE +.PP +\fBnvme-wdc-clear-fw-activate-history\fR(1) +.RS 4 +Clears the firmware activate history table +.RE +.PP +\fBnvme-wdc-clear-pcie-corr\fR(1) +.RS 4 +Clears the pcie correctable errors field +.RE +.PP +\fBnvme-wdc-clear-pcie-correctable-errors\fR(1) +.RS 4 +Clears the pcie correctable errors returned in the smart\-log\-add command +.RE +.PP +\fBnvme-wdc-cloud-SSD-plugin-version\fR(1) +.RS 4 +Display WDC plugin Cloud SSD Plugin Version +.RE +.PP +\fBnvme-wdc-drive-essentials\fR(1) +.RS 4 +Retrieve WDC device\(cqs drive essentials bin files +.RE +.PP +\fBnvme-wdc-drive-log\fR(1) +.RS 4 +Retrieve WDC device\(cqs drive log and save to file +.RE +.PP +\fBnvme-wdc-drive-resize\fR(1) +.RS 4 +Send NVMe WDC Resize Vendor Unique Command +.RE +.PP +\fBnvme-wdc-enc-get-log\fR(1) +.RS 4 +Send NVMe WDC enc\-get\-log Vendor Unique Command +.RE +.PP +\fBnvme-wdc-get-crash-dump\fR(1) +.RS 4 +Retrieve WDC device\(cqs crash dump +.RE +.PP +\fBnvme-wdc-get-drive-status\fR(1) +.RS 4 +Send the NVMe WDC get\-drive\-status command +.RE +.PP +\fBnvme-wdc-get-latency-monitor-log\fR(1) +.RS 4 +Display latency monitor log page data in human readable format +.RE +.PP +\fBnvme-wdc-get-pfail-dump\fR(1) +.RS 4 +Retrieve WDC device\(cqs pfail crash dump +.RE +.PP +\fBnvme-wdc-id-ctrl\fR(1) +.RS 4 +Send NVMe Identify Controller, return result and structure +.RE +.PP +\fBnvme-wdc-log-page-directory\fR(1) +.RS 4 +Retrieves the list of Log IDs supported by the drive +.RE +.PP +\fBnvme-wdc-namespace-resize\fR(1) +.RS 4 +Resizes the device\(cqs namespace +.RE +.PP +\fBnvme-wdc-purge-monitor\fR(1) +.RS 4 +Send NVMe WDC Purge\-Monitor Vendor Unique Command +.RE +.PP +\fBnvme-wdc-purge\fR(1) +.RS 4 +Send NVMe WDC Purge Vendor Unique Command +.RE +.PP +\fBnvme-wdc-smart-add-log\fR(1) +.RS 4 +Send NVMe WDC smart add log Vendor Unique Command +.RE +.PP +\fBnvme-wdc-vs-drive-info\fR(1) +.RS 4 +Send the NVMe WDC vs\-drive\-info command +.RE +.PP +\fBnvme-wdc-vs-error-reason-identifier\fR(1) +.RS 4 +Retrieve WDC device\(cqs telemetry log error reason identifier field +.RE +.PP +\fBnvme-wdc-vs-fw-activate-history\fR(1) +.RS 4 +Execute NVMe WDC vs\-fw\-activate\-history Vendor Unique Command +.RE +.PP +\fBnvme-wdc-vs-internal-log\fR(1) +.RS 4 +Retrieve WDC device\(cqs internal firmware log and save to file +.RE +.PP +\fBnvme-wdc-vs-nand-stats\fR(1) +.RS 4 +Send NVMe WDC vs\-nand\-stats Vendor Unique Command +.RE +.PP +\fBnvme-wdc-vs-telemetry-controller-option\fR(1) +.RS 4 +Disable/Enable the controller initiated option of the telemetry log page +.RE +.PP +\fBnvme-wdc-vs-temperature-stats\fR(1) +.RS 4 +Display temperature\-related statistics +.RE +.PP +\fBnvme-zns-changed-zone-list\fR(1) +.RS 4 +Retrieve Changed Zone log for the given device +.RE +.PP +\fBnvme-zns-close-zone\fR(1) +.RS 4 +Closes one or all zones +.RE +.PP +\fBnvme-zns-finish-zone\fR(1) +.RS 4 +Finishes one or all zones +.RE +.PP +\fBnvme-zns-id-ctrl\fR(1) +.RS 4 +Send NVMe Zoned Command Set Identify Controller +.RE +.PP +\fBnvme-zns-id-ns\fR(1) +.RS 4 +Send NVMe Zoned Command Set Identify Namespace +.RE +.PP +\fBnvme-zns-offline-zone\fR(1) +.RS 4 +Offlines one or all zones +.RE +.PP +\fBnvme-zns-open-zone\fR(1) +.RS 4 +Opens one or all zones +.RE +.PP +\fBnvme-zns-report-zones\fR(1) +.RS 4 +Retrieve and display the Report Zones data structure +.RE +.PP +\fBnvme-zns-reset-zone\fR(1) +.RS 4 +Resets one or all zones +.RE +.PP +\fBnvme-zns-set-zone-desc\fR(1) +.RS 4 +Set extended descriptor data for a zone +.RE +.PP +\fBnvme-zns-zone-append\fR(1) +.RS 4 +Send an NVMe write command, provide results +.RE +.PP +\fBnvme-zns-zone-mgmt-recv\fR(1) +.RS 4 +Zone Management Receive command +.RE +.PP +\fBnvme-zns-zone-mgmt-send\fR(1) +.RS 4 +Zone Management Send command +.RE +.PP +\fBnvme-zns-zrwa-flush-zone\fR(1) +.RS 4 +Flush LBAs associated with a ZRWA to a zone +.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\&. diff --git a/Documentation/nvme.html b/Documentation/nvme.html index 1d0f2b0..a11eb90 100644 --- a/Documentation/nvme.html +++ b/Documentation/nvme.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.6.10" />
+<meta name="generator" content="AsciiDoc" />
<title>nvme(1)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -436,7 +436,7 @@ thead, p.table.header { p.table {
margin-top: 0;
}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
+/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
@@ -819,7 +819,7 @@ available, run "nvme help".</p></div> </p>
</dd>
<dt class="hdlist1">
-<a href="nvme-dms.html">nvme-dms(1)</a>
+<a href="nvme-dsm.html">nvme-dsm(1)</a>
</dt>
<dd>
<p>
@@ -1219,6 +1219,14 @@ available, run "nvme help".</p></div> </p>
</dd>
<dt class="hdlist1">
+<a href="nvme-dim.html">nvme-dim(1)</a>
+</dt>
+<dd>
+<p>
+ Send Discovery Information Management command to a Discovery Controller
+</p>
+</dd>
+<dt class="hdlist1">
<a href="nvme-disconnect.html">nvme-disconnect(1)</a>
</dt>
<dd>
@@ -1242,6 +1250,811 @@ available, run "nvme help".</p></div> Reads and shows NVMe-over-Fabrics controller property
</p>
</dd>
+<dt class="hdlist1">
+<a href="nvme-media-unit-stat-log.html">nvme-media-unit-stat-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve and show the configuration and wear of media units
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-supported-cap-config-log.html">nvme-supported-cap-config-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve and show the list of Supported Capacity Configuration Descriptors
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-boot-part-log.html">nvme-boot-part-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Boot Partition Log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-capacity-mgmt.html">nvme-capacity-mgmt(1)</a>
+</dt>
+<dd>
+<p>
+ Capacity Management Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-check-dhchap-key.html">nvme-check-dhchap-key(1)</a>
+</dt>
+<dd>
+<p>
+ Generate NVMeoF DH-HMAC-CHAP host key
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-check-tls-key.html">nvme-check-tls-key(1)</a>
+</dt>
+<dd>
+<p>
+ Validate NVMeoF TLS PSK
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-cmdset-ind-id-ns.html">nvme-cmdset-ind-id-ns(1)</a>
+</dt>
+<dd>
+<p>
+ I/O Command Set Independent Identify Namespace
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-endurance-event-agg-log.html">nvme-endurance-event-agg-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Endurance Group Event Aggregate Log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-fid-support-effects-log.html">nvme-fid-support-effects-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve FID Support and Effects log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-gen-dhchap-key.html">nvme-gen-dhchap-key(1)</a>
+</dt>
+<dd>
+<p>
+ Generate NVMeoF DH-HMAC-CHAP host key
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-gen-hostnqn.html">nvme-gen-hostnqn(1)</a>
+</dt>
+<dd>
+<p>
+ Generate NVMeoF host NQN
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-gen-tls-key.html">nvme-gen-tls-key(1)</a>
+</dt>
+<dd>
+<p>
+ Generate NVMeoF TLS PSK
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-get-lba-status.html">nvme-get-lba-status(1)</a>
+</dt>
+<dd>
+<p>
+ Get LBA Status command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-id-domain.html">nvme-id-domain(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Identify Domain List
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-id-ns-lba-format.html">nvme-id-ns-lba-format(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Identify Namespace for the specified LBA Format index
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-lba-status-log.html">nvme-lba-status-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve LBA Status Information Log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-list-endgrp.html">nvme-list-endgrp(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Identify Endurance Group List
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-ns-rescan.html">nvme-ns-rescan(1)</a>
+</dt>
+<dd>
+<p>
+ Rescans the NVME namespaces
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-nvm-id-ctrl.html">nvme-nvm-id-ctrl(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Identify Controller NVM Command Set
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-nvm-id-ns.html">nvme-nvm-id-ns(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Identify Namespace NVM Command Set
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-nvm-id-ns-lba-format.html">nvme-nvm-id-ns-lba-format(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Identify Namespace NVM Command Set for the specified LBA Format index
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-persistent-event-log.html">nvme-persistent-event-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Presistent Event Log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-predictable-lat-log.html">nvme-predictable-lat-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Predictable Latency per Nvmset Log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-pred-lat-event-agg-log.html">nvme-pred-lat-event-agg-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Predictable Latency Event Aggregate Log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-primary-ctrl-caps.html">nvme-primary-ctrl-caps(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Identify Primary Controller Capabilities
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-reset.html">nvme-reset(1)</a>
+</dt>
+<dd>
+<p>
+ Resets the controller
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-rpmb.html">nvme-rpmb(1)</a>
+</dt>
+<dd>
+<p>
+ Replay Protection Memory Block commands
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-sanitize-log.html">nvme-sanitize-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve sanitize log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-set-property.html">nvme-set-property(1)</a>
+</dt>
+<dd>
+<p>
+ Set a property and show the resulting value
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-show-hostnqn.html">nvme-show-hostnqn(1)</a>
+</dt>
+<dd>
+<p>
+ Show NVMeoF host NQN
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-subsystem-reset.html">nvme-subsystem-reset(1)</a>
+</dt>
+<dd>
+<p>
+ Resets the subsystem
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-supported-log-pages.html">nvme-supported-log-pages(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve the Supported Log pages details
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-verify.html">nvme-verify(1)</a>
+</dt>
+<dd>
+<p>
+ verify command
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_plugins_vendor_extension_commands">Plugins/Vendor extension commands</h3>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a href="nvme-intel-id-ctrl.html">nvme-intel-id-ctrl(1)</a>
+</dt>
+<dd>
+<p>
+ Intel - NVMe Identify Controller
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-intel-internal-log.html">nvme-intel-internal-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Intel device’s internal log and save to file
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-intel-lat-stats.html">nvme-intel-lat-stats(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve NVMe Identify Controller, return result and structure
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-intel-market-name.html">nvme-intel-market-name(1)</a>
+</dt>
+<dd>
+<p>
+ Intel vendor specific marketing name log page
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-intel-smart-log-add.html">nvme-intel-smart-log-add(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Intel Additional SMART log page
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-intel-temp-stats.html">nvme-intel-temp-stats(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Intel Additional SMART log page for temp stats
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-huawei-id-ctrl.html">nvme-huawei-id-ctrl(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe huawei Identify Controller
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-huawei-list.html">nvme-huawei-list(1)</a>
+</dt>
+<dd>
+<p>
+ List all recognized Huawei NVMe devices
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-dera-stat.html">nvme-dera-stat(1)</a>
+</dt>
+<dd>
+<p>
+ NVMe Dera Device status and Additional SMART log page request
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-micron-clear-pcie-errors.html">nvme-micron-clear-pcie-errors(1)</a>
+</dt>
+<dd>
+<p>
+ Clears correctable PCIe correctable errors of given Micron device
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-micron-internal-log.html">nvme-micron-internal-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Micron device’s internal logs and save to given zip file
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-micron-nand-stats.html">nvme-micron-nand-stats(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieves NAND statistics of given micron device
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-micron-pcie-stats.html">nvme-micron-pcie-stats(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieves pcie error statistics for given micron device
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-micron-selective-download.html">nvme-micron-selective-download(1)</a>
+</dt>
+<dd>
+<p>
+ Performs selective firmware download
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-micron-smart-add-log.html">nvme-micron-smart-add-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieves NAND statistics
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-micron-temperature-stats.html">nvme-micron-temperature-stats(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieves temperature information of given micron device
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-netapp-ontapdevices.html">nvme-netapp-ontapdevices(1)</a>
+</dt>
+<dd>
+<p>
+ Display information about ONTAP devices
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-netapp-smdevices.html">nvme-netapp-smdevices(1)</a>
+</dt>
+<dd>
+<p>
+ Display information for each NVMe path to an E-Series volume
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-toshiba-clear-pcie-correctable-errors.html">nvme-toshiba-clear-pcie-correctable-errors(1)</a>
+</dt>
+<dd>
+<p>
+ Reset the PCIe correctable errors count to zero
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-toshiba-vs-internal-log.html">nvme-toshiba-vs-internal-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve a Toshiba device’s vendor specific internal log
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-toshiba-vs-smart-add-log.html">nvme-toshiba-vs-smart-add-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve a Toshiba device’s vendor specific extended SMART log page
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-transcend-badblock.html">nvme-transcend-badblock(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Transcend NVMe device’s bad blocks
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-transcend-healthvalue.html">nvme-transcend-healthvalue(1)</a>
+</dt>
+<dd>
+<p>
+ Use NVMe SMART table to analyse the health value of Transcend device
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-virtium-show-identify.html">nvme-virtium-show-identify(1)</a>
+</dt>
+<dd>
+<p>
+ Show a complete detail of identify device information in json format
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-virtium-save-smart-to-vtview-log.html">nvme-virtium-save-smart-to-vtview-log(1)</a>
+</dt>
+<dd>
+<p>
+ Periodically save smart attributes into a log file
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-cap-diag.html">nvme-wdc-cap-diag(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve WDC device’s diagnostic log and save to file
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-capabilities.html">nvme-wdc-capabilities(1)</a>
+</dt>
+<dd>
+<p>
+ Display WDC plugin command capabilities
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-clear-assert-dump.html">nvme-wdc-clear-assert-dump(1)</a>
+</dt>
+<dd>
+<p>
+ Clears the assert dump (if present)
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-clear-fw-activate-history.html">nvme-wdc-clear-fw-activate-history(1)</a>
+</dt>
+<dd>
+<p>
+ Clears the firmware activate history table
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-clear-pcie-corr.html">nvme-wdc-clear-pcie-corr(1)</a>
+</dt>
+<dd>
+<p>
+ Clears the pcie correctable errors field
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-clear-pcie-correctable-errors.html">nvme-wdc-clear-pcie-correctable-errors(1)</a>
+</dt>
+<dd>
+<p>
+ Clears the pcie correctable errors returned in the smart-log-add command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-cloud-SSD-plugin-version.html">nvme-wdc-cloud-SSD-plugin-version(1)</a>
+</dt>
+<dd>
+<p>
+ Display WDC plugin Cloud SSD Plugin Version
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-drive-essentials.html">nvme-wdc-drive-essentials(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve WDC device’s drive essentials bin files
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-drive-log.html">nvme-wdc-drive-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve WDC device’s drive log and save to file
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-drive-resize.html">nvme-wdc-drive-resize(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe WDC Resize Vendor Unique Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-enc-get-log.html">nvme-wdc-enc-get-log(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe WDC enc-get-log Vendor Unique Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-get-crash-dump.html">nvme-wdc-get-crash-dump(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve WDC device’s crash dump
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-get-drive-status.html">nvme-wdc-get-drive-status(1)</a>
+</dt>
+<dd>
+<p>
+ Send the NVMe WDC get-drive-status command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-get-latency-monitor-log.html">nvme-wdc-get-latency-monitor-log(1)</a>
+</dt>
+<dd>
+<p>
+ Display latency monitor log page data in human readable format
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-get-pfail-dump.html">nvme-wdc-get-pfail-dump(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve WDC device’s pfail crash dump
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-id-ctrl.html">nvme-wdc-id-ctrl(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe Identify Controller, return result and structure
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-log-page-directory.html">nvme-wdc-log-page-directory(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieves the list of Log IDs supported by the drive
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-namespace-resize.html">nvme-wdc-namespace-resize(1)</a>
+</dt>
+<dd>
+<p>
+ Resizes the device’s namespace
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-purge-monitor.html">nvme-wdc-purge-monitor(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe WDC Purge-Monitor Vendor Unique Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-purge.html">nvme-wdc-purge(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe WDC Purge Vendor Unique Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-smart-add-log.html">nvme-wdc-smart-add-log(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe WDC smart add log Vendor Unique Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-vs-drive-info.html">nvme-wdc-vs-drive-info(1)</a>
+</dt>
+<dd>
+<p>
+ Send the NVMe WDC vs-drive-info command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-vs-error-reason-identifier.html">nvme-wdc-vs-error-reason-identifier(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve WDC device’s telemetry log error reason identifier field
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-vs-fw-activate-history.html">nvme-wdc-vs-fw-activate-history(1)</a>
+</dt>
+<dd>
+<p>
+ Execute NVMe WDC vs-fw-activate-history Vendor Unique Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-vs-internal-log.html">nvme-wdc-vs-internal-log(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve WDC device’s internal firmware log and save to file
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-vs-nand-stats.html">nvme-wdc-vs-nand-stats(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe WDC vs-nand-stats Vendor Unique Command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-vs-telemetry-controller-option.html">nvme-wdc-vs-telemetry-controller-option(1)</a>
+</dt>
+<dd>
+<p>
+ Disable/Enable the controller initiated option of the telemetry log page
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-wdc-vs-temperature-stats.html">nvme-wdc-vs-temperature-stats(1)</a>
+</dt>
+<dd>
+<p>
+ Display temperature-related statistics
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-changed-zone-list.html">nvme-zns-changed-zone-list(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve Changed Zone log for the given device
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-close-zone.html">nvme-zns-close-zone(1)</a>
+</dt>
+<dd>
+<p>
+ Closes one or all zones
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-finish-zone.html">nvme-zns-finish-zone(1)</a>
+</dt>
+<dd>
+<p>
+ Finishes one or all zones
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-id-ctrl.html">nvme-zns-id-ctrl(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe Zoned Command Set Identify Controller
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-id-ns.html">nvme-zns-id-ns(1)</a>
+</dt>
+<dd>
+<p>
+ Send NVMe Zoned Command Set Identify Namespace
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-offline-zone.html">nvme-zns-offline-zone(1)</a>
+</dt>
+<dd>
+<p>
+ Offlines one or all zones
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-open-zone.html">nvme-zns-open-zone(1)</a>
+</dt>
+<dd>
+<p>
+ Opens one or all zones
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-report-zones.html">nvme-zns-report-zones(1)</a>
+</dt>
+<dd>
+<p>
+ Retrieve and display the Report Zones data structure
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-reset-zone.html">nvme-zns-reset-zone(1)</a>
+</dt>
+<dd>
+<p>
+ Resets one or all zones
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-set-zone-desc.html">nvme-zns-set-zone-desc(1)</a>
+</dt>
+<dd>
+<p>
+ Set extended descriptor data for a zone
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-zone-append.html">nvme-zns-zone-append(1)</a>
+</dt>
+<dd>
+<p>
+ Send an NVMe write command, provide results
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-zone-mgmt-recv.html">nvme-zns-zone-mgmt-recv(1)</a>
+</dt>
+<dd>
+<p>
+ Zone Management Receive command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-zone-mgmt-send.html">nvme-zns-zone-mgmt-send(1)</a>
+</dt>
+<dd>
+<p>
+ Zone Management Send command
+</p>
+</dd>
+<dt class="hdlist1">
+<a href="nvme-zns-zrwa-flush-zone.html">nvme-zns-zrwa-flush-zone(1)</a>
+</dt>
+<dd>
+<p>
+ Flush LBAs associated with a ZRWA to a zone
+</p>
+</dd>
</dl></div>
</div>
</div>
@@ -1278,7 +2091,7 @@ NVM-Express Site</a>.</p></div> <div id="footer">
<div id="footer-text">
Last updated
- 2021-07-19 10:10:19 PDT
+ 2022-04-08 18:46:59 CEST
</div>
</div>
</body>
diff --git a/Documentation/nvme.txt b/Documentation/nvme.txt index b9a1f59..26fcb95 100644 --- a/Documentation/nvme.txt +++ b/Documentation/nvme.txt @@ -40,6 +40,11 @@ Main commands include::cmds-main.txt[] +Plugins/Vendor extension commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +include::cmd-plugins.txt[] + FURTHER DOCUMENTATION --------------------- See the freely available references on the http://nvmexpress.org[Official @@ -1,252 +1,47 @@ -CFLAGS ?= -O2 -g -Wall -Werror -override CFLAGS += -std=gnu99 -I. -override CPPFLAGS += -D_GNU_SOURCE -D__CHECK_ENDIAN__ -LIBUUID = $(shell $(LD) -o /dev/null -luuid >/dev/null 2>&1; echo $$?) -LIBHUGETLBFS = $(shell $(LD) -o /dev/null -lhugetlbfs >/dev/null 2>&1; echo $$?) -HAVE_SYSTEMD = $(shell pkg-config --exists libsystemd --atleast-version=242; echo $$?) -LIBJSONC = $(shell pkg-config --atleast-version=0.14 json-c; echo $$?) -NVME = nvme -INSTALL ?= install -DESTDIR = -DESTDIROLD = /usr/local/sbin -PREFIX ?= /usr -SYSCONFDIR = /etc -SBINDIR = $(PREFIX)/sbin -LIBDIR ?= $(PREFIX)/lib -SYSTEMDDIR ?= $(LIBDIR)/systemd -UDEVDIR ?= $(SYSCONFDIR)/udev -UDEVRULESDIR ?= $(UDEVDIR)/rules.d -DRACUTDIR ?= $(LIBDIR)/dracut -LIB_DEPENDS = - -ifeq ($(LIBUUID),0) - override LDFLAGS += -luuid - override CFLAGS += -DLIBUUID - override LIB_DEPENDS += uuid -endif - -ifeq ($(LIBHUGETLBFS),0) - override LDFLAGS += -lhugetlbfs - override CFLAGS += -DLIBHUGETLBFS - override LIB_DEPENDS += hugetlbfs -endif +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of nvme. +# Copyright (c) 2021 Dell Inc. +# +# Authors: Martin Belanger <Martin.Belanger@dell.com> +# +NAME := nvme +.DEFAULT_GOAL := ${NAME} +BUILD-DIR := .build -INC=-Iutil +${BUILD-DIR}: + meson $@ + @echo "Configuration located in: $@" + @echo "-------------------------------------------------------" -ifeq ($(HAVE_SYSTEMD),0) - override LDFLAGS += -lsystemd - override CFLAGS += -DHAVE_SYSTEMD -endif +.PHONY: ${NAME} +${NAME}: ${BUILD-DIR} + ninja -C ${BUILD-DIR} -ifeq ($(LIBJSONC), 0) - override LDFLAGS += -ljson-c - override CFLAGS += -DLIBJSONC +.PHONY: clean +clean: +ifneq ("$(wildcard ${BUILD-DIR})","") + ninja -C ${BUILD-DIR} -t $@ endif -RPMBUILD = rpmbuild -TAR = tar -RM = rm -f - -AUTHOR=Keith Busch <kbusch@kernel.org> - -ifneq ($(findstring $(MAKEFLAGS),s),s) -ifndef V - QUIET_CC = @echo ' ' CC $@; +.PHONY: purge +purge: +ifneq ("$(wildcard ${BUILD-DIR})","") + rm -rf ${BUILD-DIR} endif -endif - -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 := nvme-print.o nvme-ioctl.o nvme-rpmb.o \ - nvme-lightnvm.o fabrics.o nvme-models.o plugin.o \ - nvme-status.o nvme-filters.o nvme-topology.o - -UTIL_OBJS := util/argconfig.o util/suffix.o util/parser.o \ - util/cleanup.o util/log.o -ifneq ($(LIBJSONC), 0) -override UTIL_OBJS += util/json.o -endif - -PLUGIN_OBJS := \ - plugins/intel/intel-nvme.o \ - plugins/amzn/amzn-nvme.o \ - plugins/lnvm/lnvm-nvme.o \ - plugins/memblaze/memblaze-nvme.o \ - plugins/wdc/wdc-nvme.o \ - plugins/wdc/wdc-utils.o \ - plugins/huawei/huawei-nvme.o \ - plugins/netapp/netapp-nvme.o \ - plugins/toshiba/toshiba-nvme.o \ - plugins/micron/micron-nvme.o \ - plugins/seagate/seagate-nvme.o \ - plugins/virtium/virtium-nvme.o \ - plugins/shannon/shannon-nvme.o \ - plugins/dera/dera-nvme.o \ - plugins/scaleflux/sfx-nvme.o \ - plugins/transcend/transcend-nvme.o \ - plugins/zns/zns.o \ - plugins/nvidia/nvidia-nvme.o \ - plugins/ymtc/ymtc-nvme.o - -nvme: nvme.c nvme.h $(OBJS) $(PLUGIN_OBJS) $(UTIL_OBJS) NVME-VERSION-FILE - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) $< -o $(NVME) $(OBJS) $(PLUGIN_OBJS) $(UTIL_OBJS) $(LDFLAGS) - -verify-no-dep: nvme.c nvme.h $(OBJS) $(UTIL_OBJS) NVME-VERSION-FILE - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) $< -o $@ $(OBJS) $(UTIL_OBJS) $(LDFLAGS) - -nvme.o: nvme.c nvme.h nvme-print.h nvme-ioctl.h util/argconfig.h util/suffix.h nvme-lightnvm.h fabrics.h - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c $< - -%.o: %.c %.h nvme.h linux/nvme.h linux/nvme_ioctl.h nvme-ioctl.h nvme-print.h util/argconfig.h - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -o $@ -c $< - -%.o: %.c nvme.h linux/nvme.h linux/nvme_ioctl.h nvme-ioctl.h nvme-print.h util/argconfig.h - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -o $@ -c $< - -doc: $(NVME) - $(MAKE) -C Documentation - -test: - $(MAKE) -C tests/ run - -all: doc - -clean: - $(RM) $(NVME) $(OBJS) $(PLUGIN_OBJS) $(UTIL_OBJS) *~ a.out NVME-VERSION-FILE *.tar* nvme.spec version control nvme-*.deb 70-nvmf-autoconnect.conf - $(MAKE) -C Documentation clean - $(RM) tests/*.pyc - $(RM) verify-no-dep - -clobber: clean - $(MAKE) -C Documentation clobber - -install-man: - $(MAKE) -C Documentation install-no-build - -install-bin: default - $(RM) $(DESTDIROLD)/nvme - $(INSTALL) -d $(DESTDIR)$(SBINDIR) - $(INSTALL) -m 755 nvme $(DESTDIR)$(SBINDIR) - -install-bash-completion: - $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/bash-completion/completions - $(INSTALL) -m 644 -T ./completions/bash-nvme-completion.sh $(DESTDIR)$(PREFIX)/share/bash-completion/completions/nvme - -install-systemd: - $(INSTALL) -d $(DESTDIR)$(SYSTEMDDIR)/system - $(INSTALL) -m 644 ./nvmf-autoconnect/systemd/* $(DESTDIR)$(SYSTEMDDIR)/system - -install-udev: - $(INSTALL) -d $(DESTDIR)$(UDEVRULESDIR) - $(INSTALL) -m 644 ./nvmf-autoconnect/udev-rules/* $(DESTDIR)$(UDEVRULESDIR) - -install-dracut: 70-nvmf-autoconnect.conf - $(INSTALL) -d $(DESTDIR)$(DRACUTDIR)/dracut.conf.d - $(INSTALL) -m 644 $< $(DESTDIR)$(DRACUTDIR)/dracut.conf.d - -install-zsh-completion: - $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/zsh/site-functions - $(INSTALL) -m 644 -T ./completions/_nvme $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_nvme - -install-hostparams: install-etc - if [ ! -s $(DESTDIR)$(SYSCONFDIR)/nvme/hostnqn ]; then \ - echo `$(DESTDIR)$(SBINDIR)/nvme gen-hostnqn` > $(DESTDIR)$(SYSCONFDIR)/nvme/hostnqn; \ - fi - if [ ! -s $(DESTDIR)$(SYSCONFDIR)/nvme/hostid ]; then \ - uuidgen > $(DESTDIR)$(SYSCONFDIR)/nvme/hostid; \ - fi - -install-etc: - $(INSTALL) -d $(DESTDIR)$(SYSCONFDIR)/nvme - touch $(DESTDIR)$(SYSCONFDIR)/nvme/hostnqn - touch $(DESTDIR)$(SYSCONFDIR)/nvme/hostid - if [ ! -f $(DESTDIR)$(SYSCONFDIR)/nvme/discovery.conf ]; then \ - $(INSTALL) -m 644 -T ./etc/discovery.conf.in $(DESTDIR)$(SYSCONFDIR)/nvme/discovery.conf; \ - fi - -install-spec: install-bin install-man install-bash-completion install-zsh-completion install-etc install-systemd install-udev install-dracut -install: install-spec install-hostparams - -nvme.spec: nvme.spec.in NVME-VERSION-FILE - sed -e 's/@@VERSION@@/$(NVME_VERSION)/g' < $< > $@+ - mv $@+ $@ - -70-nvmf-autoconnect.conf: nvmf-autoconnect/dracut-conf/70-nvmf-autoconnect.conf.in - sed -e 's#@@UDEVRULESDIR@@#$(UDEVRULESDIR)#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 -# ../<name>.changes file to upload onto the relevant PPA. For example: -# -# > make AUTHOR='First Last <first.last@company.com>' \ -# NVME_DPKG_VERSION='0ubuntu1' deb-ppa -# > debsign <name>.changes -# > dput ppa:<lid>/ppa <name>.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) --define '_prefix $(DESTDIR)$(PREFIX)' \ - --define '_libdir $(DESTDIR)${LIBDIR}' \ - --define '_sysconfdir $(DESTDIR)$(SYSCONFDIR)' \ - -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 +.PHONY: install dist +install dist: ${BUILD-DIR} + cd ${BUILD-DIR} && meson $@ + +.PHONY: test +test: ${BUILD-DIR} + ninja -C ${BUILD-DIR} $@ + +.PHONY: rpm +rpm: + meson ${BUILD-DIR} \ + -Dudevrulesdir=$(shell rpm --eval '%{_udevrulesdir}') \ + -Dsystemddir=$(shell rpm --eval '%{_unitdir}') \ + -Ddocs=man + rpmbuild -ba ${BUILD-DIR}/nvme.spec --define "_builddir ${BUILD-DIR}" -v diff --git a/NVME-VERSION-GEN b/NVME-VERSION-GEN deleted file mode 100755 index 4940a68..0000000 --- a/NVME-VERSION-GEN +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -GVF=NVME-VERSION-FILE -DEF_VER=v1.16 - -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 -} - - @@ -1,11 +1,27 @@ # nvme-cli NVM-Express user space tooling for Linux. +nvme-cli uses meson as build system. In order to build nvme-cli +run following commands + + $ meson .build + $ ninja -C .build + +nvme-cli depends on zlib, json-c and libuuid. + To install, run: + # meson install -C .build + +There is a Makefile wrapper for meson for backwards compatiblily + $ make # make install +RPM build support via Makefile that uses meson + + $ make rpm + If not sure how to use, find the top-level documentation with: $ man nvme @@ -80,36 +96,38 @@ $ nix-env -f '<nixpkgs>' -iA nvme-cli ### openSUSE -nvme-cli is available in openSUSE Leap 42.2 or later and Tumbleweed. You can install it using zypper. -For example: +nvme-cli is available in openSUSE Leap 42.2 or later and Tumbleweed. You can +install it using zypper. For example: $ sudo zypper install nvme-cli ### Ubuntu -nvme-cli is supported in the Universe package sources for Xenial for +nvme-cli is supported in the Universe package sources 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 + nvme-cli | 0.5-1 | xenial/universe | source, amd64, arm64, armhf, i386, powerpc, ppc64el, s390x + nvme-cli | 0.5-1ubuntu0.2 | xenial-updates/universe | source, amd64, arm64, armhf, i386, powerpc, ppc64el, s390x + nvme-cli | 1.5-1 | bionic/universe | source, amd64, arm64, armhf, i386, ppc64el, s390x + nvme-cli | 1.5-1ubuntu1.2 | bionic-updates | source, amd64, arm64, armhf, i386, ppc64el, s390x + nvme-cli | 1.9-1 | focal/universe | source, amd64, arm64, armhf, ppc64el, riscv64, s390x + nvme-cli | 1.9-1ubuntu0.1 | focal-updates | source, amd64, arm64, armhf, ppc64el, riscv64, s390x + nvme-cli | 1.14-1 | impish | source, amd64, arm64, armhf, ppc64el, riscv64, s390x + nvme-cli | 1.16-3 | jammy | source, amd64, arm64, armhf, ppc64el, riscv64, 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 +Ubuntu PPA. 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: + 1. Perform an update of your repository list: ``` sudo apt-get update ``` - 3. Get nvme-cli! + 2. Get nvme-cli! ``` sudo apt-get install nvme-cli ``` - 4. Test the code. + 3. Test the code. ``` sudo nvme list ``` @@ -219,4 +237,18 @@ File: foo-plugin.c ``` 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". +ENTRY, then append the object file name to the meson.build "sources". + +## meson tips + +In case meson doesn't find libnvme header files (via pkg-config) it +will fallback using subprojects. meson checks out libnvme in +subprojects directory as git tree once to the commit level specified +in the libnvme.wrap file revision parm. After this initial checkout, +the libnvme code level will not change unless explicitly told. That +means if the current branch is updated via git, the subprojects/libnvme +branch will not updated accordingly. To update it, either use the +normal git operations or the command: + + $ meson subprojects update + diff --git a/ccan/ccan/build_assert/LICENSE b/ccan/ccan/build_assert/LICENSE new file mode 120000 index 0000000..b7951da --- /dev/null +++ b/ccan/ccan/build_assert/LICENSE @@ -0,0 +1 @@ +../../licenses/CC0
\ No newline at end of file diff --git a/ccan/ccan/build_assert/_info b/ccan/ccan/build_assert/_info new file mode 100644 index 0000000..97ebe6c --- /dev/null +++ b/ccan/ccan/build_assert/_info @@ -0,0 +1,49 @@ +#include "config.h" +#include <stdio.h> +#include <string.h> + +/** + * build_assert - routines for build-time assertions + * + * This code provides routines which will cause compilation to fail should some + * assertion be untrue: such failures are preferable to run-time assertions, + * but much more limited since they can only depends on compile-time constants. + * + * These assertions are most useful when two parts of the code must be kept in + * sync: it is better to avoid such cases if possible, but seconds best is to + * detect invalid changes at build time. + * + * For example, a tricky piece of code might rely on a certain element being at + * the start of the structure. To ensure that future changes don't break it, + * you would catch such changes in your code like so: + * + * Example: + * #include <stddef.h> + * #include <ccan/build_assert/build_assert.h> + * + * struct foo { + * char string[5]; + * int x; + * }; + * + * static char *foo_string(struct foo *foo) + * { + * // This trick requires that the string be first in the structure + * BUILD_ASSERT(offsetof(struct foo, string) == 0); + * return (char *)foo; + * } + * + * License: CC0 (Public domain) + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) + /* Nothing. */ + return 0; + + return 1; +} diff --git a/ccan/ccan/build_assert/build_assert.h b/ccan/ccan/build_assert/build_assert.h new file mode 100644 index 0000000..b9ecd84 --- /dev/null +++ b/ccan/ccan/build_assert/build_assert.h @@ -0,0 +1,40 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_BUILD_ASSERT_H +#define CCAN_BUILD_ASSERT_H + +/** + * BUILD_ASSERT - assert a build-time dependency. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can only be used within a function. + * + * Example: + * #include <stddef.h> + * ... + * static char *foo_to_char(struct foo *foo) + * { + * // This code needs string to be at start of foo. + * BUILD_ASSERT(offsetof(struct foo, string) == 0); + * return (char *)foo; + * } + */ +#define BUILD_ASSERT(cond) \ + do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) + +/** + * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can be used in an expression: its value is "0". + * + * Example: + * #define foo_to_char(foo) \ + * ((char *)(foo) \ + * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + */ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#endif /* CCAN_BUILD_ASSERT_H */ diff --git a/ccan/ccan/check_type/LICENSE b/ccan/ccan/check_type/LICENSE new file mode 120000 index 0000000..b7951da --- /dev/null +++ b/ccan/ccan/check_type/LICENSE @@ -0,0 +1 @@ +../../licenses/CC0
\ No newline at end of file diff --git a/ccan/ccan/check_type/_info b/ccan/ccan/check_type/_info new file mode 100644 index 0000000..cc42673 --- /dev/null +++ b/ccan/ccan/check_type/_info @@ -0,0 +1,33 @@ +#include "config.h" +#include <stdio.h> +#include <string.h> + +/** + * check_type - routines for compile time type checking + * + * C has fairly weak typing: ints get automatically converted to longs, signed + * to unsigned, etc. There are some cases where this is best avoided, and + * these macros provide methods for evoking warnings (or build errors) when + * a precise type isn't used. + * + * On compilers which don't support typeof() these routines are less effective, + * since they have to use sizeof() which can only distiguish between types of + * different size. + * + * License: CC0 (Public domain) + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { +#if !HAVE_TYPEOF + printf("ccan/build_assert\n"); +#endif + return 0; + } + + return 1; +} diff --git a/ccan/ccan/check_type/check_type.h b/ccan/ccan/check_type/check_type.h new file mode 100644 index 0000000..837aef7 --- /dev/null +++ b/ccan/ccan/check_type/check_type.h @@ -0,0 +1,64 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_CHECK_TYPE_H +#define CCAN_CHECK_TYPE_H +#include "config.h" + +/** + * check_type - issue a warning or build failure if type is not correct. + * @expr: the expression whose type we should check (not evaluated). + * @type: the exact type we expect the expression to be. + * + * This macro is usually used within other macros to try to ensure that a macro + * argument is of the expected type. No type promotion of the expression is + * done: an unsigned int is not the same as an int! + * + * check_type() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // They should always pass a 64-bit value to _set_some_value! + * #define set_some_value(expr) \ + * _set_some_value((check_type((expr), uint64_t), (expr))) + */ + +/** + * check_types_match - issue a warning or build failure if types are not same. + * @expr1: the first expression (not evaluated). + * @expr2: the second expression (not evaluated). + * + * This macro is usually used within other macros to try to ensure that + * arguments are of identical types. No type promotion of the expressions is + * done: an unsigned int is not the same as an int! + * + * check_types_match() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // Do subtraction to get to enclosing type, but make sure that + * // pointer is of correct type for that member. + * #define container_of(mbr_ptr, encl_type, mbr) \ + * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \ + * ((encl_type *) \ + * ((char *)(mbr_ptr) - offsetof(encl_type, mbr)))) + */ +#if HAVE_TYPEOF +#define check_type(expr, type) \ + ((typeof(expr) *)0 != (type *)0) + +#define check_types_match(expr1, expr2) \ + ((typeof(expr1) *)0 != (typeof(expr2) *)0) +#else +#include <ccan/build_assert/build_assert.h> +/* Without typeof, we can only test the sizes. */ +#define check_type(expr, type) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type)) + +#define check_types_match(expr1, expr2) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2)) +#endif /* HAVE_TYPEOF */ + +#endif /* CCAN_CHECK_TYPE_H */ diff --git a/ccan/ccan/container_of/LICENSE b/ccan/ccan/container_of/LICENSE new file mode 120000 index 0000000..b7951da --- /dev/null +++ b/ccan/ccan/container_of/LICENSE @@ -0,0 +1 @@ +../../licenses/CC0
\ No newline at end of file diff --git a/ccan/ccan/container_of/_info b/ccan/ccan/container_of/_info new file mode 100644 index 0000000..b116052 --- /dev/null +++ b/ccan/ccan/container_of/_info @@ -0,0 +1,65 @@ +#include "config.h" +#include <stdio.h> +#include <string.h> + +/** + * container_of - routine for upcasting + * + * It is often convenient to create code where the caller registers a pointer + * to a generic structure and a callback. The callback might know that the + * pointer points to within a larger structure, and container_of gives a + * convenient and fairly type-safe way of returning to the enclosing structure. + * + * This idiom is an alternative to providing a void * pointer for every + * callback. + * + * Example: + * #include <stdio.h> + * #include <ccan/container_of/container_of.h> + * + * struct timer { + * void *members; + * }; + * + * struct info { + * int my_stuff; + * struct timer timer; + * }; + * + * static void my_timer_callback(struct timer *timer) + * { + * struct info *info = container_of(timer, struct info, timer); + * printf("my_stuff is %u\n", info->my_stuff); + * } + * + * static void register_timer(struct timer *timer) + * { + * (void)timer; + * (void)my_timer_callback; + * //... + * } + * + * int main(void) + * { + * struct info info = { .my_stuff = 1 }; + * + * register_timer(&info.timer); + * // ... + * return 0; + * } + * + * License: CC0 (Public domain) + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + printf("ccan/check_type\n"); + return 0; + } + + return 1; +} diff --git a/ccan/ccan/container_of/container_of.h b/ccan/ccan/container_of/container_of.h new file mode 100644 index 0000000..47a34d8 --- /dev/null +++ b/ccan/ccan/container_of/container_of.h @@ -0,0 +1,145 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_CONTAINER_OF_H +#define CCAN_CONTAINER_OF_H +#include <stddef.h> + +#include "config.h" +#include <ccan/check_type/check_type.h> + +/** + * container_of - get pointer to enclosing structure + * @member_ptr: pointer to the structure member + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info(struct foo *foo) + * { + * return container_of(foo, struct info, my_foo); + * } + */ +#define container_of(member_ptr, containing_type, member) \ + ((containing_type *) \ + ((char *)(member_ptr) \ + - container_off(containing_type, member)) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) + + +/** + * container_of_or_null - get pointer to enclosing structure, or NULL + * @member_ptr: pointer to the structure member + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type, unless it + * is given NULL, in which case it also returns NULL. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info_allowing_null(struct foo *foo) + * { + * return container_of_or_null(foo, struct info, my_foo); + * } + */ +static inline char *container_of_or_null_(void *member_ptr, size_t offset) +{ + return member_ptr ? (char *)member_ptr - offset : NULL; +} +#define container_of_or_null(member_ptr, containing_type, member) \ + ((containing_type *) \ + container_of_or_null_(member_ptr, \ + container_off(containing_type, member)) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) + +/** + * container_off - get offset to enclosing structure + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does + * typechecking and figures out the offset to the enclosing type. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info(struct foo *foo) + * { + * size_t off = container_off(struct info, my_foo); + * return (void *)((char *)foo - off); + * } + */ +#define container_off(containing_type, member) \ + offsetof(containing_type, member) + +/** + * container_of_var - get pointer to enclosing structure using a variable + * @member_ptr: pointer to the structure member + * @container_var: a pointer of same type as this member's container + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type. + * + * Example: + * static struct info *foo_to_i(struct foo *foo) + * { + * struct info *i = container_of_var(foo, i, my_foo); + * return i; + * } + */ +#if HAVE_TYPEOF +#define container_of_var(member_ptr, container_var, member) \ + container_of(member_ptr, typeof(*container_var), member) +#else +#define container_of_var(member_ptr, container_var, member) \ + ((void *)((char *)(member_ptr) - \ + container_off_var(container_var, member))) +#endif + +/** + * container_off_var - get offset of a field in enclosing structure + * @container_var: a pointer to a container structure + * @member: the name of a member within the structure. + * + * Given (any) pointer to a structure and a its member name, this + * macro does pointer subtraction to return offset of member in a + * structure memory layout. + * + */ +#if HAVE_TYPEOF +#define container_off_var(var, member) \ + container_off(typeof(*var), member) +#else +#define container_off_var(var, member) \ + ((const char *)&(var)->member - (const char *)(var)) +#endif + +#endif /* CCAN_CONTAINER_OF_H */ diff --git a/ccan/ccan/endian/LICENSE b/ccan/ccan/endian/LICENSE new file mode 120000 index 0000000..b7951da --- /dev/null +++ b/ccan/ccan/endian/LICENSE @@ -0,0 +1 @@ +../../licenses/CC0
\ No newline at end of file diff --git a/ccan/ccan/endian/_info b/ccan/ccan/endian/_info new file mode 100644 index 0000000..efe5a8b --- /dev/null +++ b/ccan/ccan/endian/_info @@ -0,0 +1,55 @@ +#include "config.h" +#include <stdio.h> +#include <string.h> + +/** + * endian - endian conversion macros for simple types + * + * Portable protocols (such as on-disk formats, or network protocols) + * are often defined to be a particular endian: little-endian (least + * significant bytes first) or big-endian (most significant bytes + * first). + * + * Similarly, some CPUs lay out values in memory in little-endian + * order (most commonly, Intel's 8086 and derivatives), or big-endian + * order (almost everyone else). + * + * This module provides conversion routines, inspired by the linux kernel. + * It also provides leint32_t, beint32_t etc typedefs, which are annotated for + * the sparse checker. + * + * Example: + * #include <stdio.h> + * #include <err.h> + * #include <ccan/endian/endian.h> + * + * // + * int main(int argc, char *argv[]) + * { + * uint32_t value; + * + * if (argc != 2) + * errx(1, "Usage: %s <value>", argv[0]); + * + * value = atoi(argv[1]); + * printf("native: %08x\n", value); + * printf("little-endian: %08x\n", cpu_to_le32(value)); + * printf("big-endian: %08x\n", cpu_to_be32(value)); + * printf("byte-reversed: %08x\n", bswap_32(value)); + * exit(0); + * } + * + * License: License: CC0 (Public domain) + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) + /* Nothing */ + return 0; + + return 1; +} diff --git a/ccan/ccan/endian/endian.h b/ccan/ccan/endian/endian.h new file mode 100644 index 0000000..3753f49 --- /dev/null +++ b/ccan/ccan/endian/endian.h @@ -0,0 +1,363 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_ENDIAN_H +#define CCAN_ENDIAN_H +#include <stdint.h> +#include "config.h" + +/** + * BSWAP_16 - reverse bytes in a constant uint16_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_16(0x1234)]; + * }; + */ +#define BSWAP_16(val) \ + ((((uint16_t)(val) & 0x00ff) << 8) \ + | (((uint16_t)(val) & 0xff00) >> 8)) + +/** + * BSWAP_32 - reverse bytes in a constant uint32_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_32(0xff000000)]; + * }; + */ +#define BSWAP_32(val) \ + ((((uint32_t)(val) & 0x000000ff) << 24) \ + | (((uint32_t)(val) & 0x0000ff00) << 8) \ + | (((uint32_t)(val) & 0x00ff0000) >> 8) \ + | (((uint32_t)(val) & 0xff000000) >> 24)) + +/** + * BSWAP_64 - reverse bytes in a constant uint64_t value. + * @val: constantvalue whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_64(0xff00000000000000ULL)]; + * }; + */ +#define BSWAP_64(val) \ + ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ + | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ + | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ + | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ + | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ + | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ + | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ + | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) + +#if HAVE_BYTESWAP_H +#include <byteswap.h> +#else +/** + * bswap_16 - reverse bytes in a uint16_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 4 as two bytes reversed" + * printf("1024 is %u as two bytes reversed\n", bswap_16(1024)); + */ +static inline uint16_t bswap_16(uint16_t val) +{ + return BSWAP_16(val); +} + +/** + * bswap_32 - reverse bytes in a uint32_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 262144 as four bytes reversed" + * printf("1024 is %u as four bytes reversed\n", bswap_32(1024)); + */ +static inline uint32_t bswap_32(uint32_t val) +{ + return BSWAP_32(val); +} +#endif /* !HAVE_BYTESWAP_H */ + +#if !HAVE_BSWAP_64 +/** + * bswap_64 - reverse bytes in a uint64_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 1125899906842624 as eight bytes reversed" + * printf("1024 is %llu as eight bytes reversed\n", + * (unsigned long long)bswap_64(1024)); + */ +static inline uint64_t bswap_64(uint64_t val) +{ + return BSWAP_64(val); +} +#endif + +/* Needed for Glibc like endiness check */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +/* Sanity check the defines. We don't handle weird endianness. */ +#if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN +#error "Unknown endian" +#elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN +#error "Can't compile for both big and little endian." +#elif HAVE_LITTLE_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __LITTLE_ENDIAN +#elif __BYTE_ORDER != __LITTLE_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" +#endif +#elif HAVE_BIG_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __BIG_ENDIAN +#elif __BYTE_ORDER != __BIG_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" +#endif +#endif + + +#ifdef __CHECKER__ +/* sparse needs forcing to remove bitwise attribute from ccan/short_types */ +#define ENDIAN_CAST __attribute__((force)) +#define ENDIAN_TYPE __attribute__((bitwise)) +#else +#define ENDIAN_CAST +#define ENDIAN_TYPE +#endif + +typedef uint64_t ENDIAN_TYPE leint64_t; +typedef uint64_t ENDIAN_TYPE beint64_t; +typedef uint32_t ENDIAN_TYPE leint32_t; +typedef uint32_t ENDIAN_TYPE beint32_t; +typedef uint16_t ENDIAN_TYPE leint16_t; +typedef uint16_t ENDIAN_TYPE beint16_t; + +#if HAVE_LITTLE_ENDIAN +/** + * CPU_TO_LE64 - convert a constant uint64_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) + +/** + * CPU_TO_LE32 - convert a constant uint32_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) + +/** + * CPU_TO_LE16 - convert a constant uint16_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) + +/** + * LE64_TO_CPU - convert a little-endian uint64_t constant + * @le_val: little-endian constant to convert + */ +#define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * LE32_TO_CPU - convert a little-endian uint32_t constant + * @le_val: little-endian constant to convert + */ +#define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * LE16_TO_CPU - convert a little-endian uint16_t constant + * @le_val: little-endian constant to convert + */ +#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_BIG_ENDIAN */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) +#define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_BIG_ENDIAN */ + +#if HAVE_BIG_ENDIAN +/** + * CPU_TO_BE64 - convert a constant uint64_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) + +/** + * CPU_TO_BE32 - convert a constant uint32_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) + +/** + * CPU_TO_BE16 - convert a constant uint16_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) + +/** + * BE64_TO_CPU - convert a big-endian uint64_t constant + * @le_val: big-endian constant to convert + */ +#define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * BE32_TO_CPU - convert a big-endian uint32_t constant + * @le_val: big-endian constant to convert + */ +#define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * BE16_TO_CPU - convert a big-endian uint16_t constant + * @le_val: big-endian constant to convert + */ +#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_LITTLE_ENDIAN */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) +#define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_LITTE_ENDIAN */ + + +/** + * cpu_to_le64 - convert a uint64_t value to little-endian + * @native: value to convert + */ +static inline leint64_t cpu_to_le64(uint64_t native) +{ + return CPU_TO_LE64(native); +} + +/** + * cpu_to_le32 - convert a uint32_t value to little-endian + * @native: value to convert + */ +static inline leint32_t cpu_to_le32(uint32_t native) +{ + return CPU_TO_LE32(native); +} + +/** + * cpu_to_le16 - convert a uint16_t value to little-endian + * @native: value to convert + */ +static inline leint16_t cpu_to_le16(uint16_t native) +{ + return CPU_TO_LE16(native); +} + +/** + * le64_to_cpu - convert a little-endian uint64_t value + * @le_val: little-endian value to convert + */ +static inline uint64_t le64_to_cpu(leint64_t le_val) +{ + return LE64_TO_CPU(le_val); +} + +/** + * le32_to_cpu - convert a little-endian uint32_t value + * @le_val: little-endian value to convert + */ +static inline uint32_t le32_to_cpu(leint32_t le_val) +{ + return LE32_TO_CPU(le_val); +} + +/** + * le16_to_cpu - convert a little-endian uint16_t value + * @le_val: little-endian value to convert + */ +static inline uint16_t le16_to_cpu(leint16_t le_val) +{ + return LE16_TO_CPU(le_val); +} + +/** + * cpu_to_be64 - convert a uint64_t value to big endian. + * @native: value to convert + */ +static inline beint64_t cpu_to_be64(uint64_t native) +{ + return CPU_TO_BE64(native); +} + +/** + * cpu_to_be32 - convert a uint32_t value to big endian. + * @native: value to convert + */ +static inline beint32_t cpu_to_be32(uint32_t native) +{ + return CPU_TO_BE32(native); +} + +/** + * cpu_to_be16 - convert a uint16_t value to big endian. + * @native: value to convert + */ +static inline beint16_t cpu_to_be16(uint16_t native) +{ + return CPU_TO_BE16(native); +} + +/** + * be64_to_cpu - convert a big-endian uint64_t value + * @be_val: big-endian value to convert + */ +static inline uint64_t be64_to_cpu(beint64_t be_val) +{ + return BE64_TO_CPU(be_val); +} + +/** + * be32_to_cpu - convert a big-endian uint32_t value + * @be_val: big-endian value to convert + */ +static inline uint32_t be32_to_cpu(beint32_t be_val) +{ + return BE32_TO_CPU(be_val); +} + +/** + * be16_to_cpu - convert a big-endian uint16_t value + * @be_val: big-endian value to convert + */ +static inline uint16_t be16_to_cpu(beint16_t be_val) +{ + return BE16_TO_CPU(be_val); +} + +/* Whichever they include first, they get these definitions. */ +#ifdef CCAN_SHORT_TYPES_H +/** + * be64/be32/be16 - 64/32/16 bit big-endian representation. + */ +typedef beint64_t be64; +typedef beint32_t be32; +typedef beint16_t be16; + +/** + * le64/le32/le16 - 64/32/16 bit little-endian representation. + */ +typedef leint64_t le64; +typedef leint32_t le32; +typedef leint16_t le16; +#endif +#endif /* CCAN_ENDIAN_H */ diff --git a/ccan/ccan/list/LICENSE b/ccan/ccan/list/LICENSE new file mode 120000 index 0000000..2354d12 --- /dev/null +++ b/ccan/ccan/list/LICENSE @@ -0,0 +1 @@ +../../licenses/BSD-MIT
\ No newline at end of file diff --git a/ccan/ccan/list/_info b/ccan/ccan/list/_info new file mode 100644 index 0000000..c4f3e2a --- /dev/null +++ b/ccan/ccan/list/_info @@ -0,0 +1,72 @@ +#include "config.h" +#include <stdio.h> +#include <string.h> + +/** + * list - double linked list routines + * + * The list header contains routines for manipulating double linked lists. + * It defines two types: struct list_head used for anchoring lists, and + * struct list_node which is usually embedded in the structure which is placed + * in the list. + * + * Example: + * #include <err.h> + * #include <stdio.h> + * #include <stdlib.h> + * #include <ccan/list/list.h> + * + * struct parent { + * const char *name; + * struct list_head children; + * unsigned int num_children; + * }; + * + * struct child { + * const char *name; + * struct list_node list; + * }; + * + * int main(int argc, char *argv[]) + * { + * struct parent p; + * struct child *c; + * int i; + * + * if (argc < 2) + * errx(1, "Usage: %s parent children...", argv[0]); + * + * p.name = argv[1]; + * list_head_init(&p.children); + * p.num_children = 0; + * for (i = 2; i < argc; i++) { + * c = malloc(sizeof(*c)); + * c->name = argv[i]; + * list_add(&p.children, &c->list); + * p.num_children++; + * } + * + * printf("%s has %u children:", p.name, p.num_children); + * list_for_each(&p.children, c, list) + * printf("%s ", c->name); + * printf("\n"); + * return 0; + * } + * + * License: BSD-MIT + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + printf("ccan/str\n"); + printf("ccan/container_of\n"); + printf("ccan/check_type\n"); + return 0; + } + + return 1; +} diff --git a/ccan/ccan/list/list.c b/ccan/ccan/list/list.c new file mode 100644 index 0000000..2717fa3 --- /dev/null +++ b/ccan/ccan/list/list.c @@ -0,0 +1,43 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#include <stdio.h> +#include <stdlib.h> +#include "list.h" + +static void *corrupt(const char *abortstr, + const struct list_node *head, + const struct list_node *node, + unsigned int count) +{ + if (abortstr) { + fprintf(stderr, + "%s: prev corrupt in node %p (%u) of %p\n", + abortstr, node, count, head); + abort(); + } + return NULL; +} + +struct list_node *list_check_node(const struct list_node *node, + const char *abortstr) +{ + const struct list_node *p, *n; + int count = 0; + + for (p = node, n = node->next; n != node; p = n, n = n->next) { + count++; + if (n->prev != p) + return corrupt(abortstr, node, n, count); + } + /* Check prev on head node. */ + if (node->prev != p) + return corrupt(abortstr, node, node, 0); + + return (struct list_node *)node; +} + +struct list_head *list_check(const struct list_head *h, const char *abortstr) +{ + if (!list_check_node(&h->n, abortstr)) + return NULL; + return (struct list_head *)h; +} diff --git a/ccan/ccan/list/list.h b/ccan/ccan/list/list.h new file mode 100644 index 0000000..a15321c --- /dev/null +++ b/ccan/ccan/list/list.h @@ -0,0 +1,842 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#ifndef CCAN_LIST_H +#define CCAN_LIST_H +//#define CCAN_LIST_DEBUG 1 +#include <stdbool.h> +#include <assert.h> +#include <ccan/str/str.h> +#include <ccan/container_of/container_of.h> +#include <ccan/check_type/check_type.h> + +/** + * struct list_node - an entry in a doubly-linked list + * @next: next entry (self if empty) + * @prev: previous entry (self if empty) + * + * This is used as an entry in a linked list. + * Example: + * struct child { + * const char *name; + * // Linked list of all us children. + * struct list_node list; + * }; + */ +struct list_node +{ + struct list_node *next, *prev; +}; + +/** + * struct list_head - the head of a doubly-linked list + * @h: the list_head (containing next and prev pointers) + * + * This is used as the head of a linked list. + * Example: + * struct parent { + * const char *name; + * struct list_head children; + * unsigned int num_children; + * }; + */ +struct list_head +{ + struct list_node n; +}; + +/** + * list_check - check head of a list for consistency + * @h: the list_head + * @abortstr: the location to print on aborting, or NULL. + * + * Because list_nodes have redundant information, consistency checking between + * the back and forward links can be done. This is useful as a debugging check. + * If @abortstr is non-NULL, that will be printed in a diagnostic if the list + * is inconsistent, and the function will abort. + * + * Returns the list head if the list is consistent, NULL if not (it + * can never return NULL if @abortstr is set). + * + * See also: list_check_node() + * + * Example: + * static void dump_parent(struct parent *p) + * { + * struct child *c; + * + * printf("%s (%u children):\n", p->name, p->num_children); + * list_check(&p->children, "bad child list"); + * list_for_each(&p->children, c, list) + * printf(" -> %s\n", c->name); + * } + */ +struct list_head *list_check(const struct list_head *h, const char *abortstr); + +/** + * list_check_node - check node of a list for consistency + * @n: the list_node + * @abortstr: the location to print on aborting, or NULL. + * + * Check consistency of the list node is in (it must be in one). + * + * See also: list_check() + * + * Example: + * static void dump_child(const struct child *c) + * { + * list_check_node(&c->list, "bad child list"); + * printf("%s\n", c->name); + * } + */ +struct list_node *list_check_node(const struct list_node *n, + const char *abortstr); + +#define LIST_LOC __FILE__ ":" stringify(__LINE__) +#ifdef CCAN_LIST_DEBUG +#define list_debug(h, loc) list_check((h), loc) +#define list_debug_node(n, loc) list_check_node((n), loc) +#else +#define list_debug(h, loc) ((void)loc, h) +#define list_debug_node(n, loc) ((void)loc, n) +#endif + +/** + * LIST_HEAD_INIT - initializer for an empty list_head + * @name: the name of the list. + * + * Explicit initializer for an empty list. + * + * See also: + * LIST_HEAD, list_head_init() + * + * Example: + * static struct list_head my_list = LIST_HEAD_INIT(my_list); + */ +#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } } + +/** + * LIST_HEAD - define and initialize an empty list_head + * @name: the name of the list. + * + * The LIST_HEAD macro defines a list_head and initializes it to an empty + * list. It can be prepended by "static" to define a static list_head. + * + * See also: + * LIST_HEAD_INIT, list_head_init() + * + * Example: + * static LIST_HEAD(my_global_list); + */ +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_head_init - initialize a list_head + * @h: the list_head to set to the empty list + * + * Example: + * ... + * struct parent *parent = malloc(sizeof(*parent)); + * + * list_head_init(&parent->children); + * parent->num_children = 0; + */ +static inline void list_head_init(struct list_head *h) +{ + h->n.next = h->n.prev = &h->n; +} + +/** + * list_node_init - initialize a list_node + * @n: the list_node to link to itself. + * + * You don't need to use this normally! But it lets you list_del(@n) + * safely. + */ +static inline void list_node_init(struct list_node *n) +{ + n->next = n->prev = n; +} + +/** + * list_add_after - add an entry after an existing node in a linked list + * @h: the list_head to add the node to (for debugging) + * @p: the existing list_node to add the node after + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * struct child c1, c2, c3; + * LIST_HEAD(h); + * + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_after(&h, &c1.list, &c2.list); + */ +#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC) +static inline void list_add_after_(struct list_head *h, + struct list_node *p, + struct list_node *n, + const char *abortstr) +{ + n->next = p->next; + n->prev = p; + p->next->prev = n; + p->next = n; + (void)list_debug(h, abortstr); +} + +/** + * list_add - add an entry at the start of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * struct child *child = malloc(sizeof(*child)); + * + * child->name = "marvin"; + * list_add(&parent->children, &child->list); + * parent->num_children++; + */ +#define list_add(h, n) list_add_(h, n, LIST_LOC) +static inline void list_add_(struct list_head *h, + struct list_node *n, + const char *abortstr) +{ + list_add_after_(h, &h->n, n, abortstr); +} + +/** + * list_add_before - add an entry before an existing node in a linked list + * @h: the list_head to add the node to (for debugging) + * @p: the existing list_node to add the node before + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * list_head_init(&h); + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_before(&h, &c3.list, &c2.list); + */ +#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC) +static inline void list_add_before_(struct list_head *h, + struct list_node *p, + struct list_node *n, + const char *abortstr) +{ + n->next = p; + n->prev = p->prev; + p->prev->next = n; + p->prev = n; + (void)list_debug(h, abortstr); +} + +/** + * list_add_tail - add an entry at the end of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * list_add_tail(&parent->children, &child->list); + * parent->num_children++; + */ +#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC) +static inline void list_add_tail_(struct list_head *h, + struct list_node *n, + const char *abortstr) +{ + list_add_before_(h, &h->n, n, abortstr); +} + +/** + * list_empty - is a list empty? + * @h: the list_head + * + * If the list is empty, returns true. + * + * Example: + * assert(list_empty(&parent->children) == (parent->num_children == 0)); + */ +#define list_empty(h) list_empty_(h, LIST_LOC) +static inline bool list_empty_(const struct list_head *h, const char* abortstr) +{ + (void)list_debug(h, abortstr); + return h->n.next == &h->n; +} + +/** + * list_empty_nodebug - is a list empty (and don't perform debug checks)? + * @h: the list_head + * + * If the list is empty, returns true. + * This differs from list_empty() in that if CCAN_LIST_DEBUG is set it + * will NOT perform debug checks. Only use this function if you REALLY + * know what you're doing. + * + * Example: + * assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0)); + */ +#ifndef CCAN_LIST_DEBUG +#define list_empty_nodebug(h) list_empty(h) +#else +static inline bool list_empty_nodebug(const struct list_head *h) +{ + return h->n.next == &h->n; +} +#endif + +/** + * list_empty_nocheck - is a list empty? + * @h: the list_head + * + * If the list is empty, returns true. This doesn't perform any + * debug check for list consistency, so it can be called without + * locks, racing with the list being modified. This is ok for + * checks where an incorrect result is not an issue (optimized + * bail out path for example). + */ +static inline bool list_empty_nocheck(const struct list_head *h) +{ + return h->n.next == &h->n; +} + +/** + * list_del - delete an entry from an (unknown) linked list. + * @n: the list_node to delete from the list. + * + * Note that this leaves @n in an undefined state; it can be added to + * another list, but not deleted again. + * + * See also: + * list_del_from(), list_del_init() + * + * Example: + * list_del(&child->list); + * parent->num_children--; + */ +#define list_del(n) list_del_(n, LIST_LOC) +static inline void list_del_(struct list_node *n, const char* abortstr) +{ + (void)list_debug_node(n, abortstr); + n->next->prev = n->prev; + n->prev->next = n->next; +#ifdef CCAN_LIST_DEBUG + /* Catch use-after-del. */ + n->next = n->prev = NULL; +#endif +} + +/** + * list_del_init - delete a node, and reset it so it can be deleted again. + * @n: the list_node to be deleted. + * + * list_del(@n) or list_del_init() again after this will be safe, + * which can be useful in some cases. + * + * See also: + * list_del_from(), list_del() + * + * Example: + * list_del_init(&child->list); + * parent->num_children--; + */ +#define list_del_init(n) list_del_init_(n, LIST_LOC) +static inline void list_del_init_(struct list_node *n, const char *abortstr) +{ + list_del_(n, abortstr); + list_node_init(n); +} + +/** + * list_del_from - delete an entry from a known linked list. + * @h: the list_head the node is in. + * @n: the list_node to delete from the list. + * + * This explicitly indicates which list a node is expected to be in, + * which is better documentation and can catch more bugs. + * + * See also: list_del() + * + * Example: + * list_del_from(&parent->children, &child->list); + * parent->num_children--; + */ +static inline void list_del_from(struct list_head *h, struct list_node *n) +{ +#ifdef CCAN_LIST_DEBUG + { + /* Thorough check: make sure it was in list! */ + struct list_node *i; + for (i = h->n.next; i != n; i = i->next) + assert(i != &h->n); + } +#endif /* CCAN_LIST_DEBUG */ + + /* Quick test that catches a surprising number of bugs. */ + assert(!list_empty(h)); + list_del(n); +} + +/** + * list_swap - swap out an entry from an (unknown) linked list for a new one. + * @o: the list_node to replace from the list. + * @n: the list_node to insert in place of the old one. + * + * Note that this leaves @o in an undefined state; it can be added to + * another list, but not deleted/swapped again. + * + * See also: + * list_del() + * + * Example: + * struct child x1, x2; + * LIST_HEAD(xh); + * + * list_add(&xh, &x1.list); + * list_swap(&x1.list, &x2.list); + */ +#define list_swap(o, n) list_swap_(o, n, LIST_LOC) +static inline void list_swap_(struct list_node *o, + struct list_node *n, + const char* abortstr) +{ + (void)list_debug_node(o, abortstr); + *n = *o; + n->next->prev = n; + n->prev->next = n; +#ifdef CCAN_LIST_DEBUG + /* Catch use-after-del. */ + o->next = o->prev = NULL; +#endif +} + +/** + * list_entry - convert a list_node back into the structure containing it. + * @n: the list_node + * @type: the type of the entry + * @member: the list_node member of the type + * + * Example: + * // First list entry is children.next; convert back to child. + * child = list_entry(parent->children.n.next, struct child, list); + * + * See Also: + * list_top(), list_for_each() + */ +#define list_entry(n, type, member) container_of(n, type, member) + +/** + * list_top - get the first entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *first; + * first = list_top(&parent->children, struct child, list); + * if (!first) + * printf("Empty list!\n"); + */ +#define list_top(h, type, member) \ + ((type *)list_top_((h), list_off_(type, member))) + +static inline const void *list_top_(const struct list_head *h, size_t off) +{ + if (list_empty(h)) + return NULL; + return (const char *)h->n.next - off; +} + +/** + * list_pop - remove the first entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *one; + * one = list_pop(&parent->children, struct child, list); + * if (!one) + * printf("Empty list!\n"); + */ +#define list_pop(h, type, member) \ + ((type *)list_pop_((h), list_off_(type, member))) + +static inline const void *list_pop_(const struct list_head *h, size_t off) +{ + struct list_node *n; + + if (list_empty(h)) + return NULL; + n = h->n.next; + list_del(n); + return (const char *)n - off; +} + +/** + * list_tail - get the last entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *last; + * last = list_tail(&parent->children, struct child, list); + * if (!last) + * printf("Empty list!\n"); + */ +#define list_tail(h, type, member) \ + ((type *)list_tail_((h), list_off_(type, member))) + +static inline const void *list_tail_(const struct list_head *h, size_t off) +{ + if (list_empty(h)) + return NULL; + return (const char *)h->n.prev - off; +} + +/** + * list_for_each - iterate through a list. + * @h: the list_head (warning: evaluated multiple times!) + * @i: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. + * + * Example: + * list_for_each(&parent->children, child, list) + * printf("Name: %s\n", child->name); + */ +#define list_for_each(h, i, member) \ + list_for_each_off(h, i, list_off_var_(i, member)) + +/** + * list_for_each_rev - iterate through a list backwards. + * @h: the list_head + * @i: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. + * + * Example: + * list_for_each_rev(&parent->children, child, list) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_rev(h, i, member) \ + list_for_each_rev_off(h, i, list_off_var_(i, member)) + +/** + * list_for_each_rev_safe - iterate through a list backwards, + * maybe during deletion + * @h: the list_head + * @i: the structure containing the list_node + * @nxt: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list backwards. + * It's a for loop, so you can break and continue as normal. The extra + * variable * @nxt is used to hold the next element, so you can delete @i + * from the list. + * + * Example: + * struct child *next; + * list_for_each_rev_safe(&parent->children, child, next, list) { + * printf("Name: %s\n", child->name); + * } + */ +#define list_for_each_rev_safe(h, i, nxt, member) \ + list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member)) + +/** + * list_for_each_safe - iterate through a list, maybe during deletion + * @h: the list_head + * @i: the structure containing the list_node + * @nxt: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. The extra variable + * @nxt is used to hold the next element, so you can delete @i from the list. + * + * Example: + * list_for_each_safe(&parent->children, child, next, list) { + * list_del(&child->list); + * parent->num_children--; + * } + */ +#define list_for_each_safe(h, i, nxt, member) \ + list_for_each_safe_off(h, i, nxt, list_off_var_(i, member)) + +/** + * list_next - get the next entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the last entry in the list, returns NULL. + * + * Example: + * struct child *second; + * second = list_next(&parent->children, first, list); + * if (!second) + * printf("No second child!\n"); + */ +#define list_next(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h, \ + __FILE__ ":" stringify(__LINE__)), \ + (i)->member.next, \ + list_off_var_((i), member))) + +/** + * list_prev - get the previous entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the first entry in the list, returns NULL. + * + * Example: + * first = list_prev(&parent->children, second, list); + * if (!first) + * printf("Can't go back to first child?!\n"); + */ +#define list_prev(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h, \ + __FILE__ ":" stringify(__LINE__)), \ + (i)->member.prev, \ + list_off_var_((i), member))) + +/** + * list_append_list - empty one list onto the end of another. + * @to: the list to append into + * @from: the list to empty. + * + * This takes the entire contents of @from and moves it to the end of + * @to. After this @from will be empty. + * + * Example: + * struct list_head adopter; + * + * list_append_list(&adopter, &parent->children); + * assert(list_empty(&parent->children)); + * parent->num_children = 0; + */ +#define list_append_list(t, f) list_append_list_(t, f, \ + __FILE__ ":" stringify(__LINE__)) +static inline void list_append_list_(struct list_head *to, + struct list_head *from, + const char *abortstr) +{ + struct list_node *from_tail = list_debug(from, abortstr)->n.prev; + struct list_node *to_tail = list_debug(to, abortstr)->n.prev; + + /* Sew in head and entire list. */ + to->n.prev = from_tail; + from_tail->next = &to->n; + to_tail->next = &from->n; + from->n.prev = to_tail; + + /* Now remove head. */ + list_del(&from->n); + list_head_init(from); +} + +/** + * list_prepend_list - empty one list into the start of another. + * @to: the list to prepend into + * @from: the list to empty. + * + * This takes the entire contents of @from and moves it to the start + * of @to. After this @from will be empty. + * + * Example: + * list_prepend_list(&adopter, &parent->children); + * assert(list_empty(&parent->children)); + * parent->num_children = 0; + */ +#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC) +static inline void list_prepend_list_(struct list_head *to, + struct list_head *from, + const char *abortstr) +{ + struct list_node *from_tail = list_debug(from, abortstr)->n.prev; + struct list_node *to_head = list_debug(to, abortstr)->n.next; + + /* Sew in head and entire list. */ + to->n.next = &from->n; + from->n.prev = &to->n; + to_head->prev = from_tail; + from_tail->next = to_head; + + /* Now remove head. */ + list_del(&from->n); + list_head_init(from); +} + +/* internal macros, do not use directly */ +#define list_for_each_off_dir_(h, i, off, dir) \ + for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ + (off)); \ + list_node_from_off_((void *)i, (off)) != &(h)->n; \ + i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \ + (off))) + +#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \ + for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ + (off)), \ + nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ + (off)); \ + list_node_from_off_(i, (off)) != &(h)->n; \ + i = nxt, \ + nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ + (off))) + +/** + * list_for_each_off - iterate through a list of memory regions. + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @off: offset(relative to @i) at which list node data resides. + * + * This is a low-level wrapper to iterate @i over the entire list, used to + * implement all oher, more high-level, for-each constructs. It's a for loop, + * so you can break and continue as normal. + * + * WARNING! Being the low-level macro that it is, this wrapper doesn't know + * nor care about the type of @i. The only assumption made is that @i points + * to a chunk of memory that at some @offset, relative to @i, contains a + * properly filled `struct list_node' which in turn contains pointers to + * memory chunks and it's turtles all the way down. With all that in mind + * remember that given the wrong pointer/offset couple this macro will + * happily churn all you memory until SEGFAULT stops it, in other words + * caveat emptor. + * + * It is worth mentioning that one of legitimate use-cases for that wrapper + * is operation on opaque types with known offset for `struct list_node' + * member(preferably 0), because it allows you not to disclose the type of + * @i. + * + * Example: + * list_for_each_off(&parent->children, child, + * offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_off(h, i, off) \ + list_for_each_off_dir_((h),(i),(off),next) + +/** + * list_for_each_rev_off - iterate through a list of memory regions backwards + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @off: offset(relative to @i) at which list node data resides. + * + * See list_for_each_off for details + */ +#define list_for_each_rev_off(h, i, off) \ + list_for_each_off_dir_((h),(i),(off),prev) + +/** + * list_for_each_safe_off - iterate through a list of memory regions, maybe + * during deletion + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @nxt: the structure containing the list_node + * @off: offset(relative to @i) at which list node data resides. + * + * For details see `list_for_each_off' and `list_for_each_safe' + * descriptions. + * + * Example: + * list_for_each_safe_off(&parent->children, child, + * next, offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_safe_off(h, i, nxt, off) \ + list_for_each_safe_off_dir_((h),(i),(nxt),(off),next) + +/** + * list_for_each_rev_safe_off - iterate backwards through a list of + * memory regions, maybe during deletion + * @h: the list_head + * @i: the pointer to a memory region which contains list node data. + * @nxt: the structure containing the list_node + * @off: offset(relative to @i) at which list node data resides. + * + * For details see `list_for_each_rev_off' and `list_for_each_rev_safe' + * descriptions. + * + * Example: + * list_for_each_rev_safe_off(&parent->children, child, + * next, offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_rev_safe_off(h, i, nxt, off) \ + list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev) + +/* Other -off variants. */ +#define list_entry_off(n, type, off) \ + ((type *)list_node_from_off_((n), (off))) + +#define list_head_off(h, type, off) \ + ((type *)list_head_off((h), (off))) + +#define list_tail_off(h, type, off) \ + ((type *)list_tail_((h), (off))) + +#define list_add_off(h, n, off) \ + list_add((h), list_node_from_off_((n), (off))) + +#define list_del_off(n, off) \ + list_del(list_node_from_off_((n), (off))) + +#define list_del_from_off(h, n, off) \ + list_del_from(h, list_node_from_off_((n), (off))) + +/* Offset helper functions so we only single-evaluate. */ +static inline void *list_node_to_off_(struct list_node *node, size_t off) +{ + return (void *)((char *)node - off); +} +static inline struct list_node *list_node_from_off_(void *ptr, size_t off) +{ + return (struct list_node *)((char *)ptr + off); +} + +/* Get the offset of the member, but make sure it's a list_node. */ +#define list_off_(type, member) \ + (container_off(type, member) + \ + check_type(((type *)0)->member, struct list_node)) + +#define list_off_var_(var, member) \ + (container_off_var(var, member) + \ + check_type(var->member, struct list_node)) + +#if HAVE_TYPEOF +#define list_typeof(var) typeof(var) +#else +#define list_typeof(var) void * +#endif + +/* Returns member, or NULL if at end of list. */ +static inline void *list_entry_or_null(const struct list_head *h, + const struct list_node *n, + size_t off) +{ + if (n == &h->n) + return NULL; + return (char *)n - off; +} +#endif /* CCAN_LIST_H */ diff --git a/ccan/ccan/str/LICENSE b/ccan/ccan/str/LICENSE new file mode 120000 index 0000000..b7951da --- /dev/null +++ b/ccan/ccan/str/LICENSE @@ -0,0 +1 @@ +../../licenses/CC0
\ No newline at end of file diff --git a/ccan/ccan/str/_info b/ccan/ccan/str/_info new file mode 100644 index 0000000..b579525 --- /dev/null +++ b/ccan/ccan/str/_info @@ -0,0 +1,52 @@ +#include "config.h" +#include <stdio.h> +#include <string.h> + +/** + * str - string helper routines + * + * This is a grab bag of functions for string operations, designed to enhance + * the standard string.h. + * + * Note that if you define CCAN_STR_DEBUG, you will get extra compile + * checks on common misuses of the following functions (they will now + * be out-of-line, so there is a runtime penalty!). + * + * strstr, strchr, strrchr: + * Return const char * if first argument is const (gcc only). + * + * isalnum, isalpha, isascii, isblank, iscntrl, isdigit, isgraph, + * islower, isprint, ispunct, isspace, isupper, isxdigit: + * Static and runtime check that input is EOF or an *unsigned* + * char, as per C standard (really!). + * + * Example: + * #include <stdio.h> + * #include <ccan/str/str.h> + * + * int main(int argc, char *argv[]) + * { + * if (argc > 1 && streq(argv[1], "--verbose")) + * printf("verbose set\n"); + * if (argc > 1 && strstarts(argv[1], "--")) + * printf("Some option set\n"); + * if (argc > 1 && strends(argv[1], "cow-powers")) + * printf("Magic option set\n"); + * return 0; + * } + * + * License: CC0 (Public domain) + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + printf("ccan/build_assert\n"); + return 0; + } + + return 1; +} diff --git a/ccan/ccan/str/debug.c b/ccan/ccan/str/debug.c new file mode 100644 index 0000000..8c51944 --- /dev/null +++ b/ccan/ccan/str/debug.c @@ -0,0 +1,108 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#include "config.h" +#include <ccan/str/str_debug.h> +#include <assert.h> +#include <ctype.h> +#include <string.h> + +#ifdef CCAN_STR_DEBUG +/* Because we mug the real ones with macros, we need our own wrappers. */ +int str_isalnum(int i) +{ + assert(i >= -1 && i < 256); + return isalnum(i); +} + +int str_isalpha(int i) +{ + assert(i >= -1 && i < 256); + return isalpha(i); +} + +int str_isascii(int i) +{ + assert(i >= -1 && i < 256); + return isascii(i); +} + +#if HAVE_ISBLANK +int str_isblank(int i) +{ + assert(i >= -1 && i < 256); + return isblank(i); +} +#endif + +int str_iscntrl(int i) +{ + assert(i >= -1 && i < 256); + return iscntrl(i); +} + +int str_isdigit(int i) +{ + assert(i >= -1 && i < 256); + return isdigit(i); +} + +int str_isgraph(int i) +{ + assert(i >= -1 && i < 256); + return isgraph(i); +} + +int str_islower(int i) +{ + assert(i >= -1 && i < 256); + return islower(i); +} + +int str_isprint(int i) +{ + assert(i >= -1 && i < 256); + return isprint(i); +} + +int str_ispunct(int i) +{ + assert(i >= -1 && i < 256); + return ispunct(i); +} + +int str_isspace(int i) +{ + assert(i >= -1 && i < 256); + return isspace(i); +} + +int str_isupper(int i) +{ + assert(i >= -1 && i < 256); + return isupper(i); +} + +int str_isxdigit(int i) +{ + assert(i >= -1 && i < 256); + return isxdigit(i); +} + +#undef strstr +#undef strchr +#undef strrchr + +char *str_strstr(const char *haystack, const char *needle) +{ + return strstr(haystack, needle); +} + +char *str_strchr(const char *haystack, int c) +{ + return strchr(haystack, c); +} + +char *str_strrchr(const char *haystack, int c) +{ + return strrchr(haystack, c); +} +#endif diff --git a/ccan/ccan/str/str.c b/ccan/ccan/str/str.c new file mode 100644 index 0000000..a9245c1 --- /dev/null +++ b/ccan/ccan/str/str.c @@ -0,0 +1,13 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#include <ccan/str/str.h> + +size_t strcount(const char *haystack, const char *needle) +{ + size_t i = 0, nlen = strlen(needle); + + while ((haystack = strstr(haystack, needle)) != NULL) { + i++; + haystack += nlen; + } + return i; +} diff --git a/ccan/ccan/str/str.h b/ccan/ccan/str/str.h new file mode 100644 index 0000000..d919b84 --- /dev/null +++ b/ccan/ccan/str/str.h @@ -0,0 +1,228 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_STR_H +#define CCAN_STR_H +#include "config.h" +#include <string.h> +#include <stdbool.h> +#include <limits.h> +#include <ctype.h> + +/** + * streq - Are two strings equal? + * @a: first string + * @b: first string + * + * This macro is arguably more readable than "!strcmp(a, b)". + * + * Example: + * if (streq(somestring, "")) + * printf("String is empty!\n"); + */ +#define streq(a,b) (strcmp((a),(b)) == 0) + +/** + * strstarts - Does this string start with this prefix? + * @str: string to test + * @prefix: prefix to look for at start of str + * + * Example: + * if (strstarts(somestring, "foo")) + * printf("String %s begins with 'foo'!\n", somestring); + */ +#define strstarts(str,prefix) (strncmp((str),(prefix),strlen(prefix)) == 0) + +/** + * strends - Does this string end with this postfix? + * @str: string to test + * @postfix: postfix to look for at end of str + * + * Example: + * if (strends(somestring, "foo")) + * printf("String %s end with 'foo'!\n", somestring); + */ +static inline bool strends(const char *str, const char *postfix) +{ + if (strlen(str) < strlen(postfix)) + return false; + + return streq(str + strlen(str) - strlen(postfix), postfix); +} + +/** + * stringify - Turn expression into a string literal + * @expr: any C expression + * + * Example: + * #define PRINT_COND_IF_FALSE(cond) \ + * ((cond) || printf("%s is false!", stringify(cond))) + */ +#define stringify(expr) stringify_1(expr) +/* Double-indirection required to stringify expansions */ +#define stringify_1(expr) #expr + +/** + * strcount - Count number of (non-overlapping) occurrences of a substring. + * @haystack: a C string + * @needle: a substring + * + * Example: + * assert(strcount("aaa aaa", "a") == 6); + * assert(strcount("aaa aaa", "ab") == 0); + * assert(strcount("aaa aaa", "aa") == 2); + */ +size_t strcount(const char *haystack, const char *needle); + +/** + * STR_MAX_CHARS - Maximum possible size of numeric string for this type. + * @type_or_expr: a pointer or integer type or expression. + * + * This provides enough space for a nul-terminated string which represents the + * largest possible value for the type or expression. + * + * Note: The implementation adds extra space so hex values or negative + * values will fit (eg. sprintf(... "%p"). ) + * + * Example: + * char str[STR_MAX_CHARS(int)]; + * + * sprintf(str, "%i", 7); + */ +#define STR_MAX_CHARS(type_or_expr) \ + ((sizeof(type_or_expr) * CHAR_BIT + 8) / 9 * 3 + 2 \ + + STR_MAX_CHARS_TCHECK_(type_or_expr)) + +#if HAVE_TYPEOF +/* Only a simple type can have 0 assigned, so test that. */ +#define STR_MAX_CHARS_TCHECK_(type_or_expr) \ + (sizeof(({ typeof(type_or_expr) x = 0; x; }))*0) +#else +#define STR_MAX_CHARS_TCHECK_(type_or_expr) 0 +#endif + +/** + * cisalnum - isalnum() which takes a char (and doesn't accept EOF) + * @c: a character + * + * Surprisingly, the standard ctype.h isalnum() takes an int, which + * must have the value of EOF (-1) or an unsigned char. This variant + * takes a real char, and doesn't accept EOF. + */ +static inline bool cisalnum(char c) +{ + return isalnum((unsigned char)c); +} +static inline bool cisalpha(char c) +{ + return isalpha((unsigned char)c); +} +static inline bool cisascii(char c) +{ + return isascii((unsigned char)c); +} +#if HAVE_ISBLANK +static inline bool cisblank(char c) +{ + return isblank((unsigned char)c); +} +#endif +static inline bool ciscntrl(char c) +{ + return iscntrl((unsigned char)c); +} +static inline bool cisdigit(char c) +{ + return isdigit((unsigned char)c); +} +static inline bool cisgraph(char c) +{ + return isgraph((unsigned char)c); +} +static inline bool cislower(char c) +{ + return islower((unsigned char)c); +} +static inline bool cisprint(char c) +{ + return isprint((unsigned char)c); +} +static inline bool cispunct(char c) +{ + return ispunct((unsigned char)c); +} +static inline bool cisspace(char c) +{ + return isspace((unsigned char)c); +} +static inline bool cisupper(char c) +{ + return isupper((unsigned char)c); +} +static inline bool cisxdigit(char c) +{ + return isxdigit((unsigned char)c); +} + +#include <ccan/str/str_debug.h> + +/* These checks force things out of line, hence they are under DEBUG. */ +#ifdef CCAN_STR_DEBUG +#include <ccan/build_assert/build_assert.h> + +/* These are commonly misused: they take -1 or an *unsigned* char value. */ +#undef isalnum +#undef isalpha +#undef isascii +#undef isblank +#undef iscntrl +#undef isdigit +#undef isgraph +#undef islower +#undef isprint +#undef ispunct +#undef isspace +#undef isupper +#undef isxdigit + +/* You can use a char if char is unsigned. */ +#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF +#define str_check_arg_(i) \ + ((i) + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(i), \ + char) \ + || (char)255 > 0)) +#else +#define str_check_arg_(i) (i) +#endif + +#define isalnum(i) str_isalnum(str_check_arg_(i)) +#define isalpha(i) str_isalpha(str_check_arg_(i)) +#define isascii(i) str_isascii(str_check_arg_(i)) +#if HAVE_ISBLANK +#define isblank(i) str_isblank(str_check_arg_(i)) +#endif +#define iscntrl(i) str_iscntrl(str_check_arg_(i)) +#define isdigit(i) str_isdigit(str_check_arg_(i)) +#define isgraph(i) str_isgraph(str_check_arg_(i)) +#define islower(i) str_islower(str_check_arg_(i)) +#define isprint(i) str_isprint(str_check_arg_(i)) +#define ispunct(i) str_ispunct(str_check_arg_(i)) +#define isspace(i) str_isspace(str_check_arg_(i)) +#define isupper(i) str_isupper(str_check_arg_(i)) +#define isxdigit(i) str_isxdigit(str_check_arg_(i)) + +#if HAVE_TYPEOF +/* With GNU magic, we can make const-respecting standard string functions. */ +#undef strstr +#undef strchr +#undef strrchr + +/* + 0 is needed to decay array into pointer. */ +#define strstr(haystack, needle) \ + ((typeof((haystack) + 0))str_strstr((haystack), (needle))) +#define strchr(haystack, c) \ + ((typeof((haystack) + 0))str_strchr((haystack), (c))) +#define strrchr(haystack, c) \ + ((typeof((haystack) + 0))str_strrchr((haystack), (c))) +#endif +#endif /* CCAN_STR_DEBUG */ + +#endif /* CCAN_STR_H */ diff --git a/ccan/ccan/str/str_debug.h b/ccan/ccan/str/str_debug.h new file mode 100644 index 0000000..92c10c4 --- /dev/null +++ b/ccan/ccan/str/str_debug.h @@ -0,0 +1,30 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_STR_DEBUG_H +#define CCAN_STR_DEBUG_H + +/* #define CCAN_STR_DEBUG 1 */ + +#ifdef CCAN_STR_DEBUG +/* Because we mug the real ones with macros, we need our own wrappers. */ +int str_isalnum(int i); +int str_isalpha(int i); +int str_isascii(int i); +#if HAVE_ISBLANK +int str_isblank(int i); +#endif +int str_iscntrl(int i); +int str_isdigit(int i); +int str_isgraph(int i); +int str_islower(int i); +int str_isprint(int i); +int str_ispunct(int i); +int str_isspace(int i); +int str_isupper(int i); +int str_isxdigit(int i); + +char *str_strstr(const char *haystack, const char *needle); +char *str_strchr(const char *s, int c); +char *str_strrchr(const char *s, int c); +#endif /* CCAN_STR_DEBUG */ + +#endif /* CCAN_STR_DEBUG_H */ diff --git a/ccan/licenses/BSD-MIT b/ccan/licenses/BSD-MIT new file mode 100644 index 0000000..89de354 --- /dev/null +++ b/ccan/licenses/BSD-MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/ccan/licenses/CC0 b/ccan/licenses/CC0 new file mode 100644 index 0000000..feb9b11 --- /dev/null +++ b/ccan/licenses/CC0 @@ -0,0 +1,28 @@ +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + + the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + moral rights retained by the original author(s) and/or performer(s); + publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; + rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; + rights protecting the extraction, dissemination, use and reuse of data in a Work; + database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and + other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. + Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. + Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. + Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. diff --git a/ccan/meson.build b/ccan/meson.build new file mode 100644 index 0000000..7573265 --- /dev/null +++ b/ccan/meson.build @@ -0,0 +1,10 @@ +sources += files([ + 'ccan/list/list.c', + 'ccan/str/debug.c', + 'ccan/str/str.c', +]) + +if get_option('buildtype') == 'debug' + add_project_arguments('-DCCAN_LIST_DEBUG=1', language : ['c', 'cpp']) + add_project_arguments('-DCCAN_STR_DEBUG=1', language : ['c', 'cpp']) +endif @@ -1,15 +1,32 @@ #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) +#include <string.h> + +#include "ccan/endian/endian.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define min(x, y) ((x) > (y) ? (y) : (x)) #define max(x, y) ((x) > (y) ? (x) : (y)) -#define __stringify_1(x...) #x -#define __stringify(x...) __stringify_1(x) +static inline uint32_t mmio_read32(void *addr) +{ + leint32_t *p = addr; + + return le32_to_cpu(*p); +} + +/* Access 64-bit registers as 2 32-bit; Some devices fail 64-bit MMIO. */ +static inline uint64_t mmio_read64(void *addr) +{ + const volatile uint32_t *p = addr; + uint32_t low, high; + + low = le32_to_cpu(*p); + high = le32_to_cpu(*(p + 1)); + + return ((uint64_t) high << 32) | low; +} #endif diff --git a/completions/_nvme b/completions/_nvme index 9507cd0..f84ad6c 100644 --- a/completions/_nvme +++ b/completions/_nvme @@ -9,8 +9,9 @@ _nvme () { _cmds=( 'id-ctrl:display information about the controller' 'id-ns:display information about the namespace' + 'id-ns-lba-format:display information about the namespace capability fields for specific LBA format' 'list-ns:identify all namespace(s) attached' - 'cmdset-ind-id-ns':display I/O Command Set Independent information about the namespace' + 'cmdset-ind-id-ns:display I/O Command Set Independent information about the namespace' 'id-iocs:display information about I/O command sets' 'id-domain:display information about domain list' 'create-ns:create a new namespace before attachment' @@ -19,6 +20,8 @@ _nvme () { 'detach-ns:detach namespace from controller' 'list-ctrl:identify all controller(s) attached' 'nvm-id-ctrl:display information about the nvm command set' + 'nvm-id-ns:display information about the namespace of nvm command set' + 'id-ns-lba-format:display information about the namespace of nvm command set capability fields for specific LBA format' 'list-endgrp:display information about nvme endurance group list' 'get-ns-id:get namespace id of opened block device' 'get-log:retrieve any log in raw format' @@ -56,6 +59,8 @@ _nvme () { 'fid-support-effects-log:retrieve fid support and effects log' 'supported-log-pages: retrieve support log pages details' 'lockdown:submit a lockdown command' + 'media-unit-stat-log: retrieve media unit status log pages details' + 'supported-cap-config-log: retrieve support log pages details' 'help:print brief descriptions of all nvme commands' ) @@ -99,6 +104,22 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme id-ns options" _idns ;; + (id-ns-lba-format) + local _idns_lba_format + _idns_lba_format=( + /dev/nvme':supply a device to use (required)' + --lba-format-index=':show infos for lba format index <lba-format-index>' + -i':alias of --lba-format-index' + --uuid-index=':uuid index' + -U':alias for --uuid-index' + --output-format=':Output format: normal|json|binary' + -o':alias for --output-format' + --verbose':show infos verbosely' + -v':alias of --verbose' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme id-ns-lba-format options" _idns_lba_format + ;; (list-ns) local _listns _listns=( @@ -145,7 +166,7 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme id-domain options" _iddomain ;; - nvm-id-ctrl) + (nvm-id-ctrl) local _nvmidctrl _nvmidctrl=( /dev/nvme':supply a device to use (required)' @@ -153,6 +174,38 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme nvm-id-ctrl options" _nvmidctrl ;; + (nvm-id-ns) + local _nvmidns + _nvmidns=( + /dev/nvme':supply a device to use (required)' + --namespace-id=':show infos for namespace <nsid>' + -n':alias of --namespace-id' + --uuid-index=':uuid index' + -U':alias for --uuid-index' + --output-format=':Output format: normal|json|binary' + -o':alias for --output-format' + --verbose':show infos verbosely' + -v':alias of --verbose' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme nvm-id-ns options" _nvmidns + ;; + (id-ns-lba-format) + local _nvm_idns_lba_format + _nvm_idns_lba_format=( + /dev/nvme':supply a device to use (required)' + --lba-format-index=':show infos for lba format index <lba-format-index>' + -i':alias of --lba-format-index' + --uuid-index=':uuid index' + -U':alias for --uuid-index' + --output-format=':Output format: normal|json|binary' + -o':alias for --output-format' + --verbose':show infos verbosely' + -v':alias of --verbose' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme nvm-id-ns-lba-format options" _nvm_idns_lba_format + ;; (list-endgrp) local _listendgrp _listendgrp=( @@ -516,6 +569,30 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme supported-log-pages options" _support ;; + (media-unit-stat-log) + local _medialog + _medialog=( + /dev/nvme':supply a device to use (required)' + --dom-id=':show infos for domain id' + -d':alias of --dom-id' + --raw-binary':dump infos in binary format' + -b':alias of --raw-binary' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme media-unit-stat-log" _medialog + ;; + (supported-cap-config-log) + local _caplog + _caplog=( + /dev/nvme':supply a device to use (required)' + --dom-id=':show infos for domain id' + -d':alias of --dom-id' + --raw-binary':dump infos in binary format' + -b':alias of --raw-binary' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme supported-cap-config-log" _caplog + ;; (admin-passthru) local _admin _admin=( @@ -694,6 +771,8 @@ _nvme () { -n':alias of --namespace-id' --numd=':number of dwords of reservation status to xfer' -d':alias of --numd' + --eds':request extended data structure' + -e':alias of --eds' --raw-binary':dump output in binary format' -b':alias of --raw-binary' ) @@ -899,8 +978,8 @@ _nvme () { resv-report flush compare read write copy show-regs persistent-event-log pred-lat-event-agg-log nvm-id-ctrl endurance-event-agg-log lba-status-log resv-notif-log capacity-mgmt id-domain boot-part-log fid-support-effects-log - supported-log-pages lockdown - supported-log-pages list-endgrp + supported-log-pages lockdown media-unit-stat-log id-ns-lba-format nvm-id-ns + nvm-id-ns-lba-format supported-cap-config-log ) _arguments '*:: :->subcmds' _describe -t commands "help: infos on a specific nvme command, or provide no option to see a synopsis of all nvme commands" _h diff --git a/completions/bash-nvme-completion.sh b/completions/bash-nvme-completion.sh index 41938d7..5e0eb23 100644 --- a/completions/bash-nvme-completion.sh +++ b/completions/bash-nvme-completion.sh @@ -13,8 +13,6 @@ readonly _plugin_subcmds=( set-bucket-thresholds lat-stats-tracking \ market-name smart-log-add temp-stats" [amzn]="id-ctrl" - [lnvm]="list info id-ns chunk-log init create \ - remove factory diag-bbtbl diag-set-bbtbl" [memblaze]="smart-log-add get-pm-status set-pm-status \ select-download lat-stats lat-stats-print lat-log \ lat-log-print clear-error-log" @@ -61,7 +59,6 @@ typeset -A _plugin_funcs readonly _plugin_funcs=( [intel]="plugin_intel_opts" [amzn]="plugin_amzn_opts" - [lnvm]="plugin_lnvm_opts" [memblaze]="plugin_memblaze_opts" [wdc]="plugin_wdc_opts" [huawei]="plugin_huawei_opts" @@ -81,6 +78,7 @@ readonly _plugin_funcs=( # Top level commands _cmds="list list-subsys id-ctrl id-ns \ id-ns-granularity list-ns list-ctrl \ + id-ns-lba-format nvm-id-ns nvm-id-ns-lba-format \ nvm-id-ctrl primary-ctrl-caps list-secondary \ ns-descs id-nvmset id-uuid id-iocs create-ns \ delete-ns get-ns-id get-log telemetry-log \ @@ -101,8 +99,8 @@ _cmds="list list-subsys id-ctrl id-ns \ connect disconnect disconnect-all gen-hostnqn \ show-hostnqn dir-receive dir-send virt-mgmt \ rpmb boot-part-log fid-support-effects-log \ - supported-log-pages lockdown" - supported-log-pages list-endgrp" + supported-log-pages lockdown media-unit-stat-log \ + supported-cap-config-log dim" # Add plugins: for plugin in "${!_plugin_subcmds[@]}"; do @@ -148,6 +146,10 @@ nvme_list_opts () { "id-ns-granularity") opts+=" --output-format= -o" ;; + "id-ns-lba-format") + opts+=" --lba-format-index= -i --uuid-index= -U \ + --verbose -v --output-format= -o" + ;; "list-ns") opts+=" --namespace-id= -n --al -a --csi= -y \ --outputformat= -o" @@ -160,12 +162,17 @@ nvme_list_opts () { opts+=" --namespace-id= -n --raw-binary -b \ --human-readable -H --output-format= -o" ;; - "id-domain") - opts+=" --dom-id= -d --output-format= -o" - ;; "nvm-id-ctrl") opts+=" --output-format= -o" ;; + "nvm-id-ns") + opts+=" --namespace-id= -n --uuid-index= -U\ + --verbose -v --output-format= -o" + ;; + "nvm-id-ns-lba-format") + opts+=" --lba-format-index= -i --uuid-index= -U \ + --verbose -v --output-format= -o" + ;; "primary-ctrl-caps") opts+=" --output-format= -o --human-readable -H" ;; @@ -271,6 +278,14 @@ nvme_list_opts () { opts+=" --lsp -s --output-file= -f \ --output-format= -o" ;; + "media-unit-stat-log") + opts+=" --dom-id= -d --output-format= -o \ + --raw-binary -b" + ;; + "supported-cap-config-log") + opts+=" --dom-id= -d --output-format= -o \ + --raw-binary -b" + ;; "get-feature") opts+=" --namespace-id= -n --feature-id= -f --sel= -s \ --data-len= -l --cdw11= --c -uuid-index= -U --raw-binary -b \ @@ -356,11 +371,11 @@ nvme_list_opts () { --rrela= -a --iekey -i" ;; "resv-report") - opts+=" --namespace-id= -n --numd= -d --cdw11 -c \ - --output-format= -o --raw-binary -b" + opts+=" --namespace-id= -n --numd= -d --eds -e \ + --raw-binary= -b --output-format= -o" ;; "dsm") - opts+=" --namespace-id= -n --ctx-attrs= -a --blocks= -b \ + opts+=" --namespace-id= -n --ctx-attrs= -a --blocks= -b\ --slbs= -s --ad -d --idw -w --idr -r --cdw11= -c" ;; "copy") @@ -442,26 +457,26 @@ nvme_list_opts () { ;; "discover") opts+=" --transport= -t -traddr= -a -trsvcid= -s \ - --host-traddr= -w --hsot-iface= -f \ + --host-traddr= -w --host-iface= -f \ --hostnqn= -q --hostid -I --raw= -r \ --raw= -r --device= -d --keep-alive-tmo= -k \ --ctrl-loss-tmo= -l --fast-io-fail-tmo= -f \ --tos= -T --hdr-digest= -g --data-digest -G \ --nr-io-queues= -i --nr-write-queues= -W \ --nr-poll-queues= -P --queue-size= -Q \ - --persistent -p --quiet -S --matching -m \ + --persistent -p --quiet -S \ --output-format= -o" ;; "connect-all") opts+=" --transport= -t -traddr= -a -trsvcid= -s \ - --host-traddr= -w --hsot-iface= -f \ + --host-traddr= -w --host-iface= -f \ --hostnqn= -q --hostid -I --raw= -r \ --raw= -r --device= -d --keep-alive-tmo= -k \ --ctrl-loss-tmo= -l --fast-io-fail-tmo= -f \ --tos= -T --hdr-digest= -g --data-digest -G \ --nr-io-queues= -i --nr-write-queues= -W \ --nr-poll-queues= -P --queue-size= -Q \ - --persistent -p --quiet -S --matching -m \ + --persistent -p --quiet -S \ --output-format= -o" ;; "connect") @@ -473,6 +488,9 @@ nvme_list_opts () { --tos= -T --duplicate-connect -D --disable-sqflow -d\ --hdr-digest -g --data-digest -G --output-format= -o" ;; + "dim") + opts+=" --task -t --nqn -n --device -d" + ;; "disconnect") opts+=" --nqn -n --device -d" ;; @@ -606,68 +624,6 @@ plugin_amzn_opts () { return 0 } -plugin_lnvm_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 3 ]; then - opts="/dev/nvme* " - fi - - opts+=" " - - case "$1" in - "list") - opts+=$NO_OPTS - ;; - "info") - opts+=$NO_OPTS - ;; - "id-ns") - opts+=" --namespace-id= -n --raw-binary -b --human-readable -H" - ;; - "chunk-log") - opts+=" --output-format= -o --human-readable -H" - ;; - "init") - opts+=" --device-name= -d --mediamgr-name -m" - ;; - "create") - opts+=" --device-name= -d --target-name= -n --target-type= -t \ - --lun-begin= -b --lun-end= -e --over-prov= -o --factory -f" - ;; - "remove") - opts+=" --target-name= -n" - ;; - "factory") - opts+=" --device-name= -d --erase-only-marked -e - --clear-host-side-blks -s --clear-bb-blks -b" - ;; - "diag-bbtbl") - opts+=" --namespace-id= -n --channel-id= -c --lun-id= -l \ - --raw-binary -b" - ;; - "diag-set-bbtbl") - opts+=" --namespace-id= -n --channel-id= -c --lun-id= -l \ - --plane-id= -p --block-id= -b --value= -v" - ;; - "help") - opts+=$NO_OPTS - ;; - esac - - COMPREPLY+=( $( compgen $compargs -W "$opts" -- $cur ) ) - - return 0 -} - plugin_memblaze_opts () { local opts="" local compargs="" @@ -1261,7 +1217,7 @@ plugin_zns_opts () { --data-len= -l" ;; "zone-mgmt-send") - opts+=" --namespace-id= -n --start-lba= -s \ + opts+=" --namespace-id= -n --start-lba= -s --zsaso -o \ --select-all -a --zsa= -z --data-len= -l \ --data= -d --timeout= -t" ;; @@ -1280,7 +1236,7 @@ plugin_zns_opts () { ;; "open-zone") opts+=" --namespace-id= -n --start-lba= -s \ - --select-all -a --timeout= -t" + --select-all -a --timeout= -t --zrwa -r" ;; "reset-zone") opts+=" --namespace-id= -n --start-lba= -s \ @@ -1292,7 +1248,10 @@ plugin_zns_opts () { ;; "set-zone-desc") opts+=" --namespace-id= -n --start-lba= -s \ - --data= -d --timeout= -t" + --data= -d --timeout= -t --zrwa -r" + ;; + "flush-zone") + opts+=" --namespace-id= -n --last-lba= -l --timeout= -t" ;; "zone-append") opts+=" --namespace-id= -n --zslba= -s --data-size= -z \ @@ -27,7 +27,6 @@ #include <stdint.h> #include <unistd.h> #include <dirent.h> -#include <sys/ioctl.h> #include <inttypes.h> #include <libgen.h> #include <sys/stat.h> @@ -36,720 +35,231 @@ #include <time.h> #include <sys/types.h> -#include <arpa/inet.h> -#include <netdb.h> - -#include "util/parser.h" -#include "nvme-ioctl.h" -#include "nvme-status.h" -#include "fabrics.h" +#include <linux/types.h> +#include "common.h" #include "nvme.h" -#include "util/argconfig.h" +#include "libnvme.h" +#include "nvme-print.h" -#include "common.h" -#include "util/log.h" -#include "util/cleanup.h" - -#ifdef HAVE_SYSTEMD -#include <systemd/sd-id128.h> -#define NVME_HOSTNQN_ID SD_ID128_MAKE(c7,f4,61,81,12,be,49,32,8c,83,10,6f,9d,dd,d8,6b) -#endif - -#define NVMF_HOSTID_SIZE 36 - -/* default to 600 seconds of reconnect attempts before giving up */ -#define NVMF_DEF_CTRL_LOSS_TMO 600 - -const char *conarg_nqn = "nqn"; -const char *conarg_transport = "transport"; -const char *conarg_traddr = "traddr"; -const char *conarg_trsvcid = "trsvcid"; -const char *conarg_host_traddr = "host_traddr"; -const char *conarg_host_iface = "host_iface"; - -struct fabrics_config fabrics_cfg = { - .ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO, - .fast_io_fail_tmo = -1, - .output_format = "normal", -}; +#define PATH_NVMF_DISC SYSCONFDIR "/nvme/discovery.conf" +#define PATH_NVMF_CONFIG SYSCONFDIR "/nvme/config.json" +#define MAX_DISC_ARGS 32 +#define MAX_DISC_RETRIES 10 -struct connect_args { +#define NVMF_DEF_DISC_TMO 30 + +/* Name of file to output log pages in their raw format */ +static char *raw; +static bool persistent; +static bool quiet; +static bool dump_config; + +static const char *nvmf_tport = "transport type"; +static const char *nvmf_traddr = "transport address"; +static const char *nvmf_nqn = "subsystem nqn"; +static const char *nvmf_trsvcid = "transport service id (e.g. IP port)"; +static const char *nvmf_htraddr = "host traddr (e.g. FC WWN's)"; +static const char *nvmf_hiface = "host interface (for tcp transport)"; +static const char *nvmf_hostnqn = "user-defined hostnqn"; +static const char *nvmf_hostid = "user-defined hostid (if default not used)"; +static const char *nvmf_hostkey = "user-defined dhchap key (if default not used)"; +static const char *nvmf_ctrlkey = "user-defined dhchap controller key (for bi-directional authentication)"; +static const char *nvmf_nr_io_queues = "number of io queues to use (default is core count)"; +static const char *nvmf_nr_write_queues = "number of write queues to use (default 0)"; +static const char *nvmf_nr_poll_queues = "number of poll queues to use (default 0)"; +static const char *nvmf_queue_size = "number of io queue elements to use (default 128)"; +static const char *nvmf_keep_alive_tmo = "keep alive timeout period in seconds"; +static const char *nvmf_reconnect_delay = "reconnect timeout period in seconds"; +static const char *nvmf_ctrl_loss_tmo = "controller loss timeout period in seconds"; +static const char *nvmf_tos = "type of service"; +static const char *nvmf_dup_connect = "allow duplicate connections between same transport host and subsystem port"; +static const char *nvmf_disable_sqflow = "disable controller sq flow control (default false)"; +static const char *nvmf_hdr_digest = "enable transport protocol header digest (TCP transport)"; +static const char *nvmf_data_digest = "enable transport protocol data digest (TCP transport)"; +static const char *nvmf_config_file = "Use specified JSON configuration file or 'none' to disable"; + +#define NVMF_OPTS(c) \ + OPT_STRING("transport", 't', "STR", &transport, nvmf_tport), \ + OPT_STRING("traddr", 'a', "STR", &traddr, nvmf_traddr), \ + OPT_STRING("trsvcid", 's', "STR", &trsvcid, nvmf_trsvcid), \ + OPT_STRING("host-traddr", 'w', "STR", &c.host_traddr, nvmf_htraddr), \ + OPT_STRING("host-iface", 'f', "STR", &c.host_iface, nvmf_hiface), \ + OPT_STRING("hostnqn", 'q', "STR", &hostnqn, nvmf_hostnqn), \ + OPT_STRING("hostid", 'I', "STR", &hostid, nvmf_hostid), \ + OPT_STRING("nqn", 'n', "STR", &subsysnqn, nvmf_nqn), \ + OPT_STRING("dhchap-secret", 'S', "STR", &hostkey, nvmf_hostkey), \ + OPT_STRING("dhchap-ctrl-secret", 'C', "STR", &ctrlkey, nvmf_ctrlkey), \ + OPT_INT("nr-io-queues", 'i', &c.nr_io_queues, nvmf_nr_io_queues), \ + OPT_INT("nr-write-queues", 'W', &c.nr_write_queues, nvmf_nr_write_queues),\ + OPT_INT("nr-poll-queues", 'P', &c.nr_poll_queues, nvmf_nr_poll_queues), \ + OPT_INT("queue-size", 'Q', &c.queue_size, nvmf_queue_size), \ + OPT_INT("keep-alive-tmo", 'k', &c.keep_alive_tmo, nvmf_keep_alive_tmo), \ + OPT_INT("reconnect-delay", 'c', &c.reconnect_delay, nvmf_reconnect_delay),\ + OPT_INT("ctrl-loss-tmo", 'l', &c.ctrl_loss_tmo, nvmf_ctrl_loss_tmo), \ + OPT_INT("tos", 'T', &c.tos, nvmf_tos), \ + OPT_FLAG("duplicate-connect", 'D', &c.duplicate_connect, nvmf_dup_connect), \ + OPT_FLAG("disable-sqflow", 'd', &c.disable_sqflow, nvmf_disable_sqflow), \ + OPT_FLAG("hdr-digest", 'g', &c.hdr_digest, nvmf_hdr_digest), \ + OPT_FLAG("data-digest", 'G', &c.data_digest, nvmf_data_digest) \ + +struct tr_config { char *subsysnqn; char *transport; char *traddr; - char *trsvcid; char *host_traddr; char *host_iface; - struct connect_args *next; - struct connect_args *tail; -}; - -struct connect_args *tracked_ctrls; - -#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 MAX_DISC_ARGS 10 -#define MAX_DISC_RETRIES 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 }, -}; - -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"; -} - -const char * const trtypes[] = { - [NVMF_TRTYPE_RDMA] = "rdma", - [NVMF_TRTYPE_FC] = "fc", - [NVMF_TRTYPE_TCP] = "tcp", - [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", - [NVMF_ADDR_FAMILY_LOOP] = "loop", -}; - -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", - [NVMF_TREQ_DISABLE_SQFLOW] = "not specified, " - "sq flow control disable supported", -}; - -static inline const char *treq_str(__u8 treq) -{ - return arg_str(treqs, ARRAY_SIZE(treqs), treq); -} - -static const char * const sectypes[] = { - [NVMF_TCP_SECTYPE_NONE] = "none", - [NVMF_TCP_SECTYPE_TLS] = "tls", -}; - -static inline const char *sectype_str(__u8 sectype) -{ - return arg_str(sectypes, ARRAY_SIZE(sectypes), sectype); -} - -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", + char *trsvcid; }; -static const char *cms_str(__u8 cm) +static void space_strip_len(int max, char *str) { - return arg_str(cms, ARRAY_SIZE(cms), cm); -} - -/* - * parse strings with connect arguments to find a particular field. - * If field found, return string containing field value. If field - * not found, return an empty string. - */ -char *parse_conn_arg(const char *conargs, const char delim, const char *field) -{ - char *s, *e; - size_t cnt; - - /* - * There are field name overlaps: traddr and host_traddr. - * By chance, both connect arg strings are set up to - * have traddr field followed by host_traddr field. Thus field - * name matching doesn't overlap in the searches. Technically, - * as is, the loop and delimiter checking isn't necessary. - * However, better to be prepared. - */ - do { - s = strstr(conargs, field); - if (!s) - goto empty_field; - /* validate prior character is delimiter */ - if (s == conargs || *(s - 1) == delim) { - /* match requires next character to be assignment */ - s += strlen(field); - if (*s == '=') - /* match */ - break; - } - /* field overlap: seek to delimiter and keep looking */ - conargs = strchr(s, delim); - if (!conargs) - goto empty_field; - conargs++; /* skip delimiter */ - } while (1); - s++; /* skip assignment character */ - e = strchr(s, delim); - if (e) - cnt = e - s; - else - cnt = strlen(s); - - return strndup(s, cnt); - -empty_field: - return strdup("\0"); -} - -int ctrl_instance(const char *device) -{ - char d[64]; - const char *p; - int ret, instance; - - p = strrchr(device, '/'); - if (p == NULL) - p = device; - else - p++; - ret = sscanf(p, "nvme%d", &instance); - if (ret <= 0) - return -EINVAL; - if (snprintf(d, sizeof(d), "nvme%d", instance) <= 0 || - strcmp(p, d)) - return -EINVAL; - return instance; -} - -/* - * Given a controller name, create a connect_args with its - * attributes and compare the attributes against the connect args - * given. - * Return true/false based on whether it matches - */ -static bool ctrl_matches_connectargs(const char *name, struct connect_args *args) -{ - struct connect_args cargs; - bool found = false; - char *path = NULL, *addr; - int ret; - bool persistent = true; - - ret = asprintf(&path, "%s/%s", SYS_NVME, name); - if (ret < 0) - return found; - - addr = nvme_get_ctrl_attr(path, "address"); - cargs.subsysnqn = nvme_get_ctrl_attr(path, "subsysnqn"); - cargs.transport = nvme_get_ctrl_attr(path, "transport"); - - if (!addr || !cargs.subsysnqn || !cargs.transport) { - fprintf(stderr, "nvme_get_ctrl_attr failed\n"); - goto out; - } + int i; - cargs.traddr = parse_conn_arg(addr, ' ', conarg_traddr); - cargs.trsvcid = parse_conn_arg(addr, ' ', conarg_trsvcid); - cargs.host_traddr = parse_conn_arg(addr, ' ', conarg_host_traddr); - cargs.host_iface = parse_conn_arg(addr, ' ', conarg_host_iface); - - if (!strcmp(cargs.subsysnqn, NVME_DISC_SUBSYS_NAME)) { - char *kato_str = nvme_get_ctrl_attr(path, "kato"), *p; - unsigned int kato = 0; - - /* - * When looking up discovery controllers we have to skip - * any non-persistent controllers (ie those with a zero - * kato value). Otherwise the controller will vanish from - * underneath us as they are owned by another program. - * - * On older kernels, the 'kato' attribute isn't present. - * Assume a persistent controller for these installations. - */ - if (kato_str) { - kato = strtoul(kato_str, &p, 0); - if (p == kato_str) - kato = 0; - free(kato_str); - persistent = (kato != 0); - } + for (i = max - 1; i >= 0; i--) { + if (str[i] != '\0' && str[i] != ' ') + return; + else + str[i] = '\0'; } - - if (persistent && - !strcmp(cargs.subsysnqn, args->subsysnqn) && - !strcmp(cargs.transport, args->transport) && - (!strcmp(cargs.traddr, args->traddr) || - !strcmp(args->traddr, "none")) && - (!strcmp(cargs.trsvcid, args->trsvcid) || - !strcmp(args->trsvcid, "none")) && - (!strcmp(cargs.host_traddr, args->host_traddr) || - !strcmp(args->host_traddr, "none")) && - (!strcmp(cargs.host_iface, args->host_iface) || - !strcmp(args->host_iface, "none"))) - found = true; - - free(cargs.traddr); - free(cargs.trsvcid); - free(cargs.host_traddr); - free(cargs.host_iface); -out: - free(cargs.subsysnqn); - free(cargs.transport); - free(addr); - free(path); - - return found; } -/* - * Look through the system to find an existing controller whose - * attributes match the connect arguments specified - * If found, a string containing the controller name (ex: "nvme?") - * is returned. - * If not found, a NULL is returned. - */ -static char *find_ctrl_with_connectargs(struct connect_args *args) +static int set_discovery_kato(struct nvme_fabrics_config *cfg) { - struct dirent **devices; - char *devname = NULL; - int i, n; - - n = scandir(SYS_NVME, &devices, scan_ctrls_filter, alphasort); - if (n < 0) { - msg(LOG_ERR, "no NVMe controller(s) detected.\n"); - return NULL; - } + int tmo = cfg->keep_alive_tmo; - for (i = 0; i < n; i++) { - if (ctrl_matches_connectargs(devices[i]->d_name, args)) { - devname = strdup(devices[i]->d_name); - if (devname == NULL) - msg(LOG_ERR, "no memory for ctrl name %s\n", - devices[i]->d_name); - goto cleanup_devices; - } - } - -cleanup_devices: - for (i = 0; i < n; i++) - free(devices[i]); - free(devices); + /* Set kato to NVMF_DEF_DISC_TMO for persistent controllers */ + if (persistent && !cfg->keep_alive_tmo) + cfg->keep_alive_tmo = NVMF_DEF_DISC_TMO; + /* Set kato to zero for non-persistent controllers */ + else if (!persistent && (cfg->keep_alive_tmo > 0)) + cfg->keep_alive_tmo = 0; - return devname; + return tmo; } -static struct connect_args *extract_connect_args(char *argstr) +static nvme_ctrl_t __create_discover_ctrl(nvme_root_t r, nvme_host_t h, + struct nvme_fabrics_config *cfg, + struct tr_config *trcfg) { - struct connect_args *cargs; + nvme_ctrl_t c; + int tmo, ret; - cargs = calloc(1, sizeof(*cargs)); - if (!cargs) + c = nvme_create_ctrl(r, trcfg->subsysnqn, trcfg->transport, + trcfg->traddr, trcfg->host_traddr, + trcfg->host_iface, trcfg->trsvcid); + if (!c) return NULL; - cargs->subsysnqn = parse_conn_arg(argstr, ',', conarg_nqn); - cargs->transport = parse_conn_arg(argstr, ',', conarg_transport); - cargs->traddr = parse_conn_arg(argstr, ',', conarg_traddr); - cargs->trsvcid = parse_conn_arg(argstr, ',', conarg_trsvcid); - cargs->host_traddr = parse_conn_arg(argstr, ',', conarg_host_traddr); - cargs->host_iface = parse_conn_arg(argstr, ',', conarg_host_iface); - return cargs; -} - -static void destruct_connect_args(struct connect_args *cargs) -{ - free(cargs->subsysnqn); - free(cargs->transport); - free(cargs->traddr); - free(cargs->trsvcid); - free(cargs->host_traddr); - free(cargs->host_iface); -} - -static void free_connect_args(struct connect_args *cargs) -{ - destruct_connect_args(cargs); - free(cargs); -} - -static void track_ctrl(char *argstr) -{ - struct connect_args *cargs; - - cargs = extract_connect_args(argstr); - if (!cargs) - return; - - if (!tracked_ctrls) - tracked_ctrls = cargs; - else - tracked_ctrls->tail->next = cargs; - tracked_ctrls->tail = cargs; -} - -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) { - msg(LOG_ERR, "Failed to open %s: %s\n", - PATH_NVME_FABRICS, strerror(errno)); - ret = -errno; - goto out; - } - - ret = write(fd, argstr, len); - if (ret != len) { - if (errno != EALREADY) - msg(LOG_NOTICE, "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) { - msg(LOG_ERR, "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; - track_ctrl((char *)argstr); - goto out_close; - default: - /* ignore */ - break; - } - } - -out_fail: - msg(LOG_ERR, "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; - msg(LOG_ERR, "Failed to open %s: %s\n", sysfs_path, - strerror(errno)); - goto out; - } - if (write(fd, "1", 1) != 1) { - ret = -errno; - goto out_close; - } + nvme_ctrl_set_discovery_ctrl(c, true); + tmo = set_discovery_kato(cfg); - ret = 0; -out_close: - close(fd); -out: - return ret; -} + errno = 0; + ret = nvmf_add_ctrl(h, c, cfg); -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; + cfg->keep_alive_tmo = tmo; + if (ret) { + errno = ret; + nvme_free_ctrl(c); + return NULL; } - ret = remove_ctrl_by_path(sysfs_path); - free(sysfs_path); -out: - return ret; + return c; } -enum { - DISC_OK, - DISC_NO_LOG, - DISC_GET_NUMRECS, - DISC_GET_LOG, - DISC_RETRY_EXHAUSTED, - DISC_NOT_EQUAL, -}; - -static int nvmf_get_log_page_discovery(const char *dev_path, - struct nvmf_disc_rsp_page_hdr **logp, int *numrec, int *status) +static nvme_ctrl_t create_discover_ctrl(nvme_root_t r, nvme_host_t h, + struct nvme_fabrics_config *cfg, + struct tr_config *trcfg) { - struct nvmf_disc_rsp_page_hdr *log; - unsigned int hdr_size; - unsigned long genctr; - int error, fd, max_retries = MAX_DISC_RETRIES, retries = 0; - - fd = open(dev_path, O_RDWR); - if (fd < 0) { - error = -errno; - msg(LOG_ERR, "Failed to open %s: %s\n", - dev_path, strerror(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. - */ - hdr_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, hdr_size); - if (!log) { - perror("could not alloc memory for discovery log header"); - error = -ENOMEM; - goto out_close; - } - - error = nvme_discovery_log(fd, log, hdr_size); - if (error) { - error = DISC_GET_NUMRECS; - goto out_free_log; + nvme_ctrl_t c; + + c = __create_discover_ctrl(r, h, cfg, trcfg); + if (!persistent) + return c; + + /* Find out the name of discovery controller */ + struct nvme_id_ctrl id = { 0 }; + if (nvme_ctrl_identify(c, &id)) { + fprintf(stderr, "failed to identify controller, error %s\n", + nvme_strerror(errno)); + nvme_disconnect_ctrl(c); + nvme_free_ctrl(c); + return NULL; } - do { - unsigned int log_size; - - /* 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) { - perror("could not alloc memory for discovery log page"); - 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; - } - - /* - * The above call to nvme_discovery_log() might result - * in several calls (with different offsets), so we need - * to fetch the header again to have the most up-to-date - * value for the generation counter - */ - genctr = le64_to_cpu(log->genctr); - error = nvme_discovery_log(fd, log, hdr_size); - if (error) { - error = DISC_GET_LOG; - goto out_free_log; - } - } while (genctr != le64_to_cpu(log->genctr) && - ++retries < max_retries); + if (!strcmp(id.subnqn, NVME_DISC_SUBSYS_NAME)) + return c; /* - * If genctr is still different with the one in the log entry, it - * means the retires have been exhausted to max_retries. Then it - * should be retried by the caller or the user. + * The subsysnqn is not the well-known name. Prefer the unique + * subsysnqn over the well-known one. */ - if (genctr != le64_to_cpu(log->genctr)) { - error = DISC_RETRY_EXHAUSTED; - goto out_free_log; - } - - if (*numrec != le64_to_cpu(log->numrec)) { - error = DISC_NOT_EQUAL; - goto out_free_log; - } - - /* needs to be freed by the caller */ - *logp = log; - error = DISC_OK; - goto out_close; - -out_free_log: - free(log); -out_close: - close(fd); -out: - *status = nvme_status_to_errno(error, true); - return error; -} + nvme_disconnect_ctrl(c); + nvme_free_ctrl(c); -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; + trcfg->subsysnqn = id.subnqn; + return __create_discover_ctrl(r, h, cfg, trcfg); } -static void print_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, - int instance) +static void print_discovery_log(struct nvmf_discovery_log *log, int numrec) { int i; - printf("\n"); - - if (fabrics_cfg.persistent) - printf("Persistent device: nvme%d\n", instance); - - printf("Discovery Log Number of Records %d, " + printf("\nDiscovery Log Number of Records %d, " "Generation counter %"PRIu64"\n", numrec, le64_to_cpu(log->genctr)); for (i = 0; i < numrec; i++) { - struct nvmf_disc_rsp_page_entry *e = &log->entries[i]; + struct nvmf_disc_log_entry *e = &log->entries[i]; + + space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid); + space_strip_len(NVMF_TRADDR_SIZE, e->traddr); 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("trtype: %s\n", nvmf_trtype_str(e->trtype)); + printf("adrfam: %s\n", + e->traddr && strlen(e->traddr) ? + nvmf_adrfam_str(e->adrfam): ""); + printf("subtype: %s\n", nvmf_subtype_str(e->subtype)); + printf("treq: %s\n", nvmf_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("trsvcid: %s\n", e->trsvcid); printf("subnqn: %s\n", e->subnqn); - printf("traddr: %.*s\n", - space_strip_len(NVMF_TRADDR_SIZE, e->traddr), - e->traddr); + printf("traddr: %s\n", e->traddr); + printf("eflags: %s\n", nvmf_eflags_str(e->eflags)); switch (e->trtype) { case NVMF_TRTYPE_RDMA: printf("rdma_prtype: %s\n", - prtype_str(e->tsas.rdma.prtype)); + nvmf_prtype_str(e->tsas.rdma.prtype)); printf("rdma_qptype: %s\n", - qptype_str(e->tsas.rdma.qptype)); + nvmf_qptype_str(e->tsas.rdma.qptype)); printf("rdma_cms: %s\n", - cms_str(e->tsas.rdma.cms)); + nvmf_cms_str(e->tsas.rdma.cms)); printf("rdma_pkey: 0x%04x\n", le16_to_cpu(e->tsas.rdma.pkey)); break; case NVMF_TRTYPE_TCP: printf("sectype: %s\n", - sectype_str(e->tsas.tcp.sectype)); + nvmf_sectype_str(e->tsas.tcp.sectype)); break; } } } -static void json_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, - int instance) +static void json_discovery_log(struct nvmf_discovery_log *log, int numrec) { struct json_object *root; struct json_object *entries; - char *dev_name = NULL; int i; - if (asprintf(&dev_name, "nvme%d", instance) < 0) - return; - root = json_create_object(); entries = json_create_array(); - json_object_add_value_string(root, "device", dev_name); - json_object_add_value_uint(root, "genctr", le64_to_cpu(log->genctr)); + json_object_add_value_uint64(root, "genctr", le64_to_cpu(log->genctr)); json_object_add_value_array(root, "records", entries); for (i = 0; i < numrec; i++) { - struct nvmf_disc_rsp_page_entry *e = &log->entries[i]; + struct nvmf_disc_log_entry *e = &log->entries[i]; struct json_object *entry = json_create_object(); nvme_strip_spaces(e->trsvcid, NVMF_TRSVCID_SIZE); @@ -757,32 +267,34 @@ static void json_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, nvme_strip_spaces(e->traddr, NVMF_TRADDR_SIZE); json_object_add_value_string(entry, "trtype", - trtype_str(e->trtype)); + nvmf_trtype_str(e->trtype)); json_object_add_value_string(entry, "adrfam", - adrfam_str(e->adrfam)); + nvmf_adrfam_str(e->adrfam)); json_object_add_value_string(entry, "subtype", - subtype_str(e->subtype)); + nvmf_subtype_str(e->subtype)); json_object_add_value_string(entry,"treq", - treq_str(e->treq)); - json_object_add_value_uint(entry, "portid", e->portid); + nvmf_treq_str(e->treq)); + json_object_add_value_uint(entry, "portid", + le16_to_cpu(e->portid)); json_object_add_value_string(entry, "trsvcid", e->trsvcid); json_object_add_value_string(entry, "subnqn", e->subnqn); json_object_add_value_string(entry, "traddr", e->traddr); + json_object_add_value_uint(entry, "eflags", e->eflags); switch (e->trtype) { case NVMF_TRTYPE_RDMA: json_object_add_value_string(entry, "rdma_prtype", - prtype_str(e->tsas.rdma.prtype)); + nvmf_prtype_str(e->tsas.rdma.prtype)); json_object_add_value_string(entry, "rdma_qptype", - qptype_str(e->tsas.rdma.qptype)); + nvmf_qptype_str(e->tsas.rdma.qptype)); json_object_add_value_string(entry, "rdma_cms", - cms_str(e->tsas.rdma.cms)); + nvmf_cms_str(e->tsas.rdma.cms)); json_object_add_value_uint(entry, "rdma_pkey", le16_to_cpu(e->tsas.rdma.pkey)); break; case NVMF_TRTYPE_TCP: json_object_add_value_string(entry, "sectype", - sectype_str(e->tsas.tcp.sectype)); + nvmf_sectype_str(e->tsas.tcp.sectype)); break; } json_array_add_value_object(entries, entry); @@ -790,1158 +302,980 @@ static void json_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, json_print_object(root, NULL); printf("\n"); json_free_object(root); - free(dev_name); } -static void save_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec) +static void save_discovery_log(char *raw, struct nvmf_discovery_log *log) { - int fd; - int len, ret; + uint64_t numrec = le64_to_cpu(log->numrec); + int fd, len, ret; - fd = open(fabrics_cfg.raw, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); + fd = open(raw, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); if (fd < 0) { - msg(LOG_ERR, "failed to open %s: %s\n", - fabrics_cfg.raw, strerror(errno)); + fprintf(stderr, "failed to open %s: %s\n", + raw, strerror(errno)); return; } - len = sizeof(struct nvmf_disc_rsp_page_hdr) + - numrec * sizeof(struct nvmf_disc_rsp_page_entry); + len = sizeof(struct nvmf_discovery_log) + + numrec * sizeof(struct nvmf_disc_log_entry); ret = write(fd, log, len); if (ret < 0) - msg(LOG_ERR, "failed to write to %s: %s\n", - fabrics_cfg.raw, strerror(errno)); + fprintf(stderr, "failed to write to %s: %s\n", + raw, strerror(errno)); else - printf("Discovery log is saved to %s\n", fabrics_cfg.raw); + printf("Discovery log is saved to %s\n", raw); close(fd); } -static void print_connect_msg(int instance) +static void print_connect_msg(nvme_ctrl_t c) { - printf("device: nvme%d\n", instance); + printf("device: %s\n", nvme_ctrl_get_name(c)); } -static void json_connect_msg(int instance) +static void json_connect_msg(nvme_ctrl_t c) { struct json_object *root; - char *dev_name = NULL; - - if (asprintf(&dev_name, "nvme%d", instance) < 0) - return; root = json_create_object(); - json_object_add_value_string(root, "device", dev_name); + json_object_add_value_string(root, "device", nvme_ctrl_get_name(c)); json_print_object(root, NULL); printf("\n"); json_free_object(root); - free(dev_name); } -static char *hostnqn_read_file(void) +static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg, + char *raw, bool connect, bool persistent, + enum nvme_print_flags flags) { - FILE *f; - char hostnqn[NVMF_NQN_SIZE]; - char *ret = NULL; - - f = fopen(PATH_NVMF_HOSTNQN, "r"); - if (f == NULL) - return false; - - if (fgets(hostnqn, sizeof(hostnqn), f) == NULL || - !strlen(hostnqn)) - goto out; + struct nvmf_discovery_log *log = NULL; + nvme_subsystem_t s = nvme_ctrl_get_subsystem(c); + nvme_host_t h = nvme_subsystem_get_host(s); + uint64_t numrec; + int err; - ret = strndup(hostnqn, strcspn(hostnqn, "\n")); -out: - fclose(f); - if (ret && strcmp(ret, "") == 0) { - free(ret); - ret = NULL; + err = nvmf_get_discovery_log(c, &log, MAX_DISC_RETRIES); + if (err) { + if (err > 0) + nvme_show_status(err); + else + fprintf(stderr, "failed to get discovery log: %s\n", + nvme_strerror(errno)); + return err; } - return ret; -} - -static char *hostnqn_generate_systemd(void) -{ -#ifdef HAVE_SYSTEMD - sd_id128_t id; - char *ret; - if (sd_id128_get_machine_app_specific(NVME_HOSTNQN_ID, &id) < 0) - return NULL; - if (asprintf(&ret, "nqn.2014-08.org.nvmexpress:uuid:" SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id)) == -1) - ret = NULL; - - return ret; -#else - return NULL; -#endif -} - -static char *hostnqn_read_dmi(void) -{ - char uuid[16]; - char *ret = NULL; - - if (uuid_from_dmi(uuid) < 0) - return NULL; - if (asprintf(&ret, "nqn.2014-08.org.nvmexpress:uuid:%s", uuid) == -1) - return NULL; - return ret; -} - -/* returns an allocated string or NULL */ -char *hostnqn_read(void) -{ - char *ret; - - ret = hostnqn_read_file(); - if (ret) - return ret; - - ret = hostnqn_read_dmi(); - if (ret) - return ret; - - ret = hostnqn_generate_systemd(); - if (ret) - return ret; - - return NULL; -} - -static int nvmf_hostnqn_file(void) -{ - fabrics_cfg.hostnqn = hostnqn_read(); - - return fabrics_cfg.hostnqn != NULL; -} - -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; - - fabrics_cfg.hostid = strdup(hostid); - if (!fabrics_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; + numrec = le64_to_cpu(log->numrec); + if (raw) + save_discovery_log(raw, log); + else if (!connect) { + if (flags == JSON) + json_discovery_log(log, numrec); + else + print_discovery_log(log, numrec); + } else if (connect) { + int i; + + for (i = 0; i < numrec; i++) { + struct nvmf_disc_log_entry *e = &log->entries[i]; + bool discover = false; + nvme_ctrl_t child; + int tmo = defcfg->keep_alive_tmo; + + if (e->subtype == NVME_NQN_DISC) + set_discovery_kato(defcfg); + + errno = 0; + child = nvmf_connect_disc_entry(h, e, defcfg, + &discover); + + defcfg->keep_alive_tmo = tmo; + + if (child) { + if (discover) + __discover(child, defcfg, raw, + true, persistent, flags); + if (e->subtype != NVME_NQN_NVME && + !persistent) { + nvme_disconnect_ctrl(child); + nvme_free_ctrl(child); + } + } else if (errno == EALREADY && !quiet) { + char *traddr = log->entries[i].traddr; + + space_strip_len(NVMF_TRADDR_SIZE, traddr); + fprintf(stderr, + "traddr=%s is already connected\n", + traddr); + } + } } + free(log); return 0; } -static int -add_int_argument(char **argstr, int *max_len, char *arg_str, int arg, - bool allow_zero) +/* + * Compare two C strings and handle NULL pointers gracefully. + * If either of the two strings is NULL, return 0 + * to let caller ignore the compare. + */ +static inline int strcmp0(const char *s1, const char *s2) { - int len; - - if (arg || allow_zero) { - len = snprintf(*argstr, *max_len, ",%s=%d", arg_str, arg); - if (len < 0) - return -EINVAL; - *argstr += len; - *max_len -= len; - } - - return 0; + if (!s1 || !s2) + return 0; + return strcmp(s1, s2); } -static int -add_argument(char **argstr, int *max_len, char *arg_str, const char *arg) +/* + * Compare two C strings and handle NULL pointers gracefully. + * If either of the two strings is NULL, return 0 + * to let caller ignore the compare. + */ +static inline int strcasecmp0(const char *s1, const char *s2) { - int len; - - if (arg && strcmp(arg, "none")) { - len = snprintf(*argstr, *max_len, ",%s=%s", arg_str, arg); - if (len < 0) - return -EINVAL; - *argstr += len; - *max_len -= len; - } - - return 0; + if (!s1 || !s2) + return 0; + return strcasecmp(s1, s2); } -int build_options(char *argstr, int max_len, bool discover) +static bool ctrl_config_match(nvme_ctrl_t c, struct tr_config *trcfg) { - int len; + if (!strcmp0(nvme_ctrl_get_transport(c), trcfg->transport) && + !strcasecmp0(nvme_ctrl_get_traddr(c), trcfg->traddr) && + !strcmp0(nvme_ctrl_get_trsvcid(c), trcfg->trsvcid) && + !strcmp0(nvme_ctrl_get_host_traddr(c), trcfg->host_traddr) && + !strcmp0(nvme_ctrl_get_host_iface(c), trcfg->host_iface)) + return true; - if (!fabrics_cfg.transport) { - msg(LOG_ERR, "need a transport (-t) argument\n"); - return -EINVAL; - } + return false; +} - if (strncmp(fabrics_cfg.transport, "loop", 4)) { - if (!fabrics_cfg.traddr) { - msg(LOG_ERR, "need a address (-a) argument\n"); - return -EINVAL; +static nvme_ctrl_t lookup_discover_ctrl(nvme_root_t r, struct tr_config *trcfg) +{ + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + if (!nvme_ctrl_is_discovery_ctrl(c)) + continue; + if (ctrl_config_match(c, trcfg)) + return c; + } } } - /* always specify nqn as first arg - this will init the string */ - len = snprintf(argstr, max_len, "nqn=%s", fabrics_cfg.nqn); - if (len < 0) - return -EINVAL; - argstr += len; - max_len -= len; - - if (add_argument(&argstr, &max_len, "transport", fabrics_cfg.transport) || - add_argument(&argstr, &max_len, "traddr", fabrics_cfg.traddr) || - add_argument(&argstr, &max_len, "host_traddr", fabrics_cfg.host_traddr) || - add_argument(&argstr, &max_len, "host_iface", fabrics_cfg.host_iface) || - add_argument(&argstr, &max_len, "trsvcid", fabrics_cfg.trsvcid) || - ((fabrics_cfg.hostnqn || nvmf_hostnqn_file()) && - add_argument(&argstr, &max_len, "hostnqn", fabrics_cfg.hostnqn)) || - ((fabrics_cfg.hostid || nvmf_hostid_file()) && - add_argument(&argstr, &max_len, "hostid", fabrics_cfg.hostid)) || - (!discover && - add_int_argument(&argstr, &max_len, "nr_io_queues", - fabrics_cfg.nr_io_queues, false)) || - add_int_argument(&argstr, &max_len, "nr_write_queues", - fabrics_cfg.nr_write_queues, false) || - add_int_argument(&argstr, &max_len, "nr_poll_queues", - fabrics_cfg.nr_poll_queues, false) || - (!discover && - add_int_argument(&argstr, &max_len, "queue_size", - fabrics_cfg.queue_size, false)) || - add_int_argument(&argstr, &max_len, "keep_alive_tmo", - fabrics_cfg.keep_alive_tmo, false) || - add_int_argument(&argstr, &max_len, "reconnect_delay", - fabrics_cfg.reconnect_delay, false) || - (strncmp(fabrics_cfg.transport, "loop", 4) && - add_int_argument(&argstr, &max_len, "ctrl_loss_tmo", - fabrics_cfg.ctrl_loss_tmo, true)) || - (fabrics_cfg.fast_io_fail_tmo != -1 && - add_int_argument(&argstr, &max_len, "fast_io_fail_tmo", - fabrics_cfg.fast_io_fail_tmo, true)) || - (fabrics_cfg.tos != -1 && - add_int_argument(&argstr, &max_len, "tos", - fabrics_cfg.tos, true)) || - add_bool_argument(&argstr, &max_len, "duplicate_connect", - fabrics_cfg.duplicate_connect) || - add_bool_argument(&argstr, &max_len, "disable_sqflow", - fabrics_cfg.disable_sqflow) || - add_bool_argument(&argstr, &max_len, "hdr_digest", fabrics_cfg.hdr_digest) || - add_bool_argument(&argstr, &max_len, "data_digest", fabrics_cfg.data_digest)) - return -EINVAL; - - return 0; -} - -static void set_discovery_kato(struct fabrics_config *cfg) -{ - /* Set kato to NVMF_DEF_DISC_TMO for persistent controllers */ - if (cfg->persistent && !cfg->keep_alive_tmo) - cfg->keep_alive_tmo = NVMF_DEF_DISC_TMO; - /* Set kato to zero for non-persistent controllers */ - else if (!cfg->persistent && (cfg->keep_alive_tmo > 0)) - cfg->keep_alive_tmo = 0; + return NULL; } -static void discovery_trsvcid(struct fabrics_config *fabrics_cfg, bool discover) +static char *get_default_trsvcid(const char *transport, + bool discovery_ctrl) { - if (!strcmp(fabrics_cfg->transport, "tcp")) { - if (discover) { + if (!strcmp(transport, "tcp")) { + if (discovery_ctrl) { /* Default port for NVMe/TCP discovery controllers */ - fabrics_cfg->trsvcid = __stringify(NVME_DISC_IP_PORT); + return stringify(NVME_DISC_IP_PORT); } else { /* Default port for NVMe/TCP io controllers */ - fabrics_cfg->trsvcid = __stringify(NVME_RDMA_IP_PORT); + return stringify(NVME_RDMA_IP_PORT); } - } else if (!strcmp(fabrics_cfg->transport, "rdma")) { + } else if (!strcmp(transport, "rdma")) { /* Default port for NVMe/RDMA controllers */ - fabrics_cfg->trsvcid = __stringify(NVME_RDMA_IP_PORT); + return stringify(NVME_RDMA_IP_PORT); } -} -static bool traddr_is_hostname(struct fabrics_config *fabrics_cfg) -{ - char addrstr[NVMF_TRADDR_SIZE]; - - if (!fabrics_cfg->traddr || !fabrics_cfg->transport) - return false; - if (strcmp(fabrics_cfg->transport, "tcp") && strcmp(fabrics_cfg->transport, "rdma")) - return false; - if (inet_pton(AF_INET, fabrics_cfg->traddr, addrstr) > 0 || - inet_pton(AF_INET6, fabrics_cfg->traddr, addrstr) > 0) - return false; - return true; + return NULL; } -static int hostname2traddr(struct fabrics_config *fabrics_cfg) +static int discover_from_conf_file(nvme_root_t r, nvme_host_t h, + const char *desc, bool connect, + const struct nvme_fabrics_config *defcfg) { - struct addrinfo *host_info, hints = {.ai_family = AF_UNSPEC}; - char addrstr[NVMF_TRADDR_SIZE]; - const char *p; - int ret; - - ret = getaddrinfo(fabrics_cfg->traddr, NULL, &hints, &host_info); - if (ret) { - msg(LOG_ERR, "failed to resolve host %s info\n", fabrics_cfg->traddr); - return ret; - } - - switch (host_info->ai_family) { - case AF_INET: - p = inet_ntop(host_info->ai_family, - &(((struct sockaddr_in *)host_info->ai_addr)->sin_addr), - addrstr, NVMF_TRADDR_SIZE); - break; - case AF_INET6: - p = inet_ntop(host_info->ai_family, - &(((struct sockaddr_in6 *)host_info->ai_addr)->sin6_addr), - addrstr, NVMF_TRADDR_SIZE); - break; - default: - msg(LOG_ERR, "unrecognized address family (%d) %s\n", - host_info->ai_family, fabrics_cfg->traddr); - ret = -EINVAL; - goto free_addrinfo; - } - - if (!p) { - msg(LOG_ERR, "failed to get traddr for %s\n", fabrics_cfg->traddr); - ret = -errno; - goto free_addrinfo; - } - fabrics_cfg->traddr = strdup(addrstr); - -free_addrinfo: - freeaddrinfo(host_info); - return ret; -} + char *transport = NULL, *traddr = NULL, *trsvcid = NULL; + char *hostnqn = NULL, *hostid = NULL, *hostkey = NULL, *ctrlkey = NULL; + char *subsysnqn = NULL; + char *ptr, **argv, *p, line[4096]; + int argc, ret = 0; + unsigned int verbose = 0; + FILE *f; + enum nvme_print_flags flags; + char *format = "normal"; + struct nvme_fabrics_config cfg; + bool force = false; -static int connect_ctrl(struct nvmf_disc_rsp_page_entry *e) -{ - char argstr[BUF_SIZE], *p; - const char *transport; - bool discover, disable_sqflow = true; - int len, ret; - -retry: - p = argstr; - discover = false; - - switch (e->subtype) { - case NVME_NQN_DISC: - discover = true; - case NVME_NQN_NVME: - break; - default: - msg(LOG_ERR, "skipping unsupported subtype %d\n", - e->subtype); - return -EINVAL; - } + OPT_ARGS(opts) = { + NVMF_OPTS(cfg), + OPT_FMT("output-format", 'o', &format, output_format), + OPT_FILE("raw", 'r', &raw, "save raw output to file"), + OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"), + OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"), + OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"), + OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"), + OPT_END() + }; - len = sprintf(p, "nqn=%s", e->subnqn); - if (len < 0) - return -EINVAL; - p += len; + nvmf_default_config(&cfg); - if (fabrics_cfg.hostnqn && strcmp(fabrics_cfg.hostnqn, "none")) { - len = sprintf(p, ",hostnqn=%s", fabrics_cfg.hostnqn); - if (len < 0) - return -EINVAL; - p += len; - } + ret = flags = validate_output_format(format); + if (ret < 0) + return ret; - if (fabrics_cfg.hostid && strcmp(fabrics_cfg.hostid, "none")) { - len = sprintf(p, ",hostid=%s", fabrics_cfg.hostid); - if (len < 0) - return -EINVAL; - p += len; + f = fopen(PATH_NVMF_DISC, "r"); + if (f == NULL) { + errno = ENOENT; + return -1; } - if (fabrics_cfg.queue_size && !discover) { - len = sprintf(p, ",queue_size=%d", fabrics_cfg.queue_size); - if (len < 0) - return -EINVAL; - p += len; + argv = calloc(MAX_DISC_ARGS, sizeof(char *)); + if (!argv) { + ret = -1; + goto out; } - if (fabrics_cfg.nr_io_queues && !discover) { - len = sprintf(p, ",nr_io_queues=%d", fabrics_cfg.nr_io_queues); - if (len < 0) - return -EINVAL; - p += len; - } + argv[0] = "discover"; + memset(line, 0, sizeof(line)); + while (fgets(line, sizeof(line), f) != NULL) { + nvme_ctrl_t c; - if (fabrics_cfg.nr_write_queues) { - len = sprintf(p, ",nr_write_queues=%d", fabrics_cfg.nr_write_queues); - if (len < 0) - return -EINVAL; - p += len; - } + if (line[0] == '#' || line[0] == '\n') + continue; - if (fabrics_cfg.nr_poll_queues) { - len = sprintf(p, ",nr_poll_queues=%d", fabrics_cfg.nr_poll_queues); - if (len < 0) - return -EINVAL; - p += len; - } + argc = 1; + p = line; + while ((ptr = strsep(&p, " =\n")) != NULL) + argv[argc++] = ptr; + argv[argc] = NULL; - if (fabrics_cfg.host_traddr && strcmp(fabrics_cfg.host_traddr, "none")) { - len = sprintf(p, ",host_traddr=%s", fabrics_cfg.host_traddr); - if (len < 0) - return -EINVAL; - p+= len; - } + memcpy(&cfg, defcfg, sizeof(cfg)); + subsysnqn = NVME_DISC_SUBSYS_NAME; + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + goto next; + if (!transport && !traddr) + goto next; + + if (!trsvcid) + trsvcid = get_default_trsvcid(transport, true); + + struct tr_config trcfg = { + .subsysnqn = subsysnqn, + .transport = transport, + .traddr = traddr, + .host_traddr = cfg.host_traddr, + .host_iface = cfg.host_iface, + .trsvcid = trsvcid, + }; + + if (!force) { + c = lookup_discover_ctrl(r, &trcfg); + if (c) { + __discover(c, &cfg, raw, connect, + true, flags); + goto next; + } + } - if (fabrics_cfg.host_iface && strcmp(fabrics_cfg.host_iface, "none")) { - len = sprintf(p, ",host_iface=%s", fabrics_cfg.host_iface); - if (len < 0) - return -EINVAL; - p+= len; - } + c = create_discover_ctrl(r, h, &cfg, &trcfg); + if (!c) + goto next; - if (fabrics_cfg.reconnect_delay) { - len = sprintf(p, ",reconnect_delay=%d", fabrics_cfg.reconnect_delay); - if (len < 0) - return -EINVAL; - p += len; - } + __discover(c, &cfg, raw, connect, persistent, flags); + if (!persistent) + ret = nvme_disconnect_ctrl(c); + nvme_free_ctrl(c); - if ((e->trtype != NVMF_TRTYPE_LOOP) && (fabrics_cfg.ctrl_loss_tmo >= -1)) { - len = sprintf(p, ",ctrl_loss_tmo=%d", fabrics_cfg.ctrl_loss_tmo); - if (len < 0) - return -EINVAL; - p += len; +next: + memset(&cfg, 0, sizeof(cfg)); } + free(argv); +out: + fclose(f); + return ret; +} - if (fabrics_cfg.fast_io_fail_tmo) { - len = sprintf(p, ",fast_io_fail_tmo=%d", fabrics_cfg.fast_io_fail_tmo); - if (len < 0) - return -EINVAL; - p += len; - } +int nvmf_discover(const char *desc, int argc, char **argv, bool connect) +{ + char *subsysnqn = NVME_DISC_SUBSYS_NAME; + char *hostnqn = NULL, *hostid = NULL, *hostkey = NULL, *ctrlkey = NULL; + char *transport = NULL, *traddr = NULL, *trsvcid = NULL; + char *config_file = PATH_NVMF_CONFIG; + char *hnqn = NULL, *hid = NULL; + enum nvme_print_flags flags; + nvme_root_t r; + nvme_host_t h; + nvme_ctrl_t c = NULL; + unsigned int verbose = 0; + int ret; + char *format = "normal"; + struct nvme_fabrics_config cfg; + char *device = NULL; + bool force = false; - if (fabrics_cfg.tos != -1) { - len = sprintf(p, ",tos=%d", fabrics_cfg.tos); - if (len < 0) - return -EINVAL; - p += len; - } + OPT_ARGS(opts) = { + OPT_STRING("device", 'd', "DEV", &device, "use existing discovery controller device"), + NVMF_OPTS(cfg), + OPT_FMT("output-format", 'o', &format, output_format), + OPT_FILE("raw", 'r', &raw, "save raw output to file"), + OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"), + OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"), + OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file), + OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"), + OPT_FLAG("dump-config", 'O', &dump_config, "Dump configuration file to stdout"), + OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"), + OPT_END() + }; - if (fabrics_cfg.keep_alive_tmo) { - len = sprintf(p, ",keep_alive_tmo=%d", fabrics_cfg.keep_alive_tmo); - if (len < 0) - return -EINVAL; - p += len; - } + nvmf_default_config(&cfg); - transport = trtype_str(e->trtype); - if (!strcmp(transport, "unrecognized")) { - msg(LOG_ERR, "skipping unsupported transport %d\n", - e->trtype); - return -EINVAL; - } + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + return ret; - len = sprintf(p, ",transport=%s", transport); - if (len < 0) - return -EINVAL; - p += len; + ret = flags = validate_output_format(format); + if (ret < 0) + return ret; - if (fabrics_cfg.hdr_digest) { - len = sprintf(p, ",hdr_digest"); - if (len < 0) - return -EINVAL; - p += len; - } + if (!strcmp(config_file, "none")) + config_file = NULL; - if (fabrics_cfg.data_digest) { - len = sprintf(p, ",data_digest"); - if (len < 0) - return -EINVAL; - p += len; + r = nvme_create_root(stderr, map_log_level(verbose, quiet)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); + return -errno; } - - switch (e->trtype) { - case NVMF_TRTYPE_RDMA: - case NVMF_TRTYPE_TCP: - switch (e->adrfam) { - case NVMF_ADDR_FAMILY_IP4: - case NVMF_ADDR_FAMILY_IP6: - /* FALLTHRU */ - 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: - msg(LOG_ERR, "skipping unsupported adrfam\n"); - return -EINVAL; - } - break; - case NVMF_TRTYPE_FC: - switch (e->adrfam) { - case NVMF_ADDR_FAMILY_FC: - len = sprintf(p, ",traddr=%.*s", - space_strip_len(NVMF_TRADDR_SIZE, e->traddr), - e->traddr); - if (len < 0) - return -EINVAL; - p += len; - break; - default: - msg(LOG_ERR, "skipping unsupported adrfam\n"); - return -EINVAL; - } - break; + ret = nvme_scan_topology(r, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Failed to scan topoplogy: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); + return ret; } - if (e->treq & NVMF_TREQ_DISABLE_SQFLOW && disable_sqflow) { - len = sprintf(p, ",disable_sqflow"); - if (len < 0) - return -EINVAL; - p += len; - } + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_from_file(); + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_generate(); + if (!hostid) + hostid = hid = nvmf_hostid_from_file(); + h = nvme_lookup_host(r, hostnqn, hostid); + if (!h) { + ret = ENOMEM; + goto out_free; + } + if (device) { + if (!strcmp(device, "none")) + device = NULL; + else if (!strncmp(device, "/dev/", 5)) + device += 5; + } + if (hostkey) + nvme_host_set_dhchap_key(h, hostkey); + + if (!device && !transport && !traddr) { + ret = discover_from_conf_file(r, h, desc, connect, &cfg); + goto out_free; + } + + if (!trsvcid) + trsvcid = get_default_trsvcid(transport, true); + + struct tr_config trcfg = { + .subsysnqn = subsysnqn, + .transport = transport, + .traddr = traddr, + .host_traddr = cfg.host_traddr, + .host_iface = cfg.host_iface, + .trsvcid = trsvcid, + }; - if (discover) { - enum nvme_print_flags flags; - - flags = validate_output_format(fabrics_cfg.output_format); - if (flags < 0) - flags = NORMAL; - ret = do_discover(argstr, true, flags); - } else - ret = add_ctrl(argstr); - if (ret == -EINVAL && disable_sqflow && - e->treq & NVMF_TREQ_DISABLE_SQFLOW) { - /* disable_sqflow param might not be supported, try without it */ - disable_sqflow = false; - goto retry; + if (device && !force) { + c = nvme_scan_ctrl(r, device); + if (c) { + /* Check if device matches command-line options */ + if (!ctrl_config_match(c, &trcfg)) { + fprintf(stderr, + "ctrl device %s found, ignoring " + "non matching command-line options\n", + device); + } + + if (!nvme_ctrl_is_discovery_ctrl(c)) { + fprintf(stderr, + "ctrl device %s found, ignoring " + "non discovery controller\n", + device); + + nvme_free_ctrl(c); + c = NULL; + persistent = false; + } else { + /* + * If the controller device is found it must + * be persistent, and shouldn't be disconnected + * on exit. + */ + persistent = true; + } + } else { + /* + * No controller found, fall back to create one. + * But that controller cannot be persistent. + */ + fprintf(stderr, + "ctrl device %s not found%s\n", device, + persistent ? ", ignoring --persistent" : ""); + persistent = false; + } } - return ret; -} - -static bool cargs_match_found(struct nvmf_disc_rsp_page_entry *entry) -{ - struct connect_args cargs __cleanup__(destruct_connect_args) = { NULL, }; - struct connect_args *c = tracked_ctrls; - - cargs.traddr = strdup(entry->traddr); - cargs.transport = strdup(trtype_str(entry->trtype)); - cargs.subsysnqn = strdup(entry->subnqn); - cargs.trsvcid = strdup(entry->trsvcid); - cargs.host_traddr = strdup(fabrics_cfg.host_traddr ?: "\0"); - cargs.host_iface = strdup(fabrics_cfg.host_iface ?: "\0"); - - /* check if we have a match in the discovery recursion */ - while (c) { - if (!strcmp(cargs.subsysnqn, c->subsysnqn) && - !strcmp(cargs.transport, c->transport) && - !strcmp(cargs.traddr, c->traddr) && - !strcmp(cargs.trsvcid, c->trsvcid) && - !strcmp(cargs.host_traddr, c->host_traddr) && - !strcmp(cargs.host_iface, c->host_iface)) - return true; - c = c->next; + if (!c && !force) { + c = lookup_discover_ctrl(r, &trcfg); + if (c) + persistent = true; + } + if (!c) { + /* No device or non-matching device, create a new controller */ + c = create_discover_ctrl(r, h, &cfg, &trcfg); + if (!c) { + fprintf(stderr, + "failed to add controller, error %s\n", + nvme_strerror(errno)); + ret = errno; + goto out_free; + } } - /* check if we have a matching existing controller */ - return find_ctrl_with_connectargs(&cargs) != NULL; -} - -static bool should_connect(struct nvmf_disc_rsp_page_entry *entry) -{ - int len; - - if (cargs_match_found(entry)) - return false; + ret = __discover(c, &cfg, raw, connect, + persistent, flags); + if (!persistent) + nvme_disconnect_ctrl(c); + nvme_free_ctrl(c); - /* skip connect if the transport type doesn't match */ - if (strcmp(fabrics_cfg.transport, trtype_str(entry->trtype))) - return false; +out_free: + free(hnqn); + free(hid); + if (dump_config) + nvme_dump_config(r); + nvme_free_tree(r); - if (!fabrics_cfg.matching_only || !fabrics_cfg.traddr) - return true; - - len = space_strip_len(NVMF_TRADDR_SIZE, entry->traddr); - return !strncmp(fabrics_cfg.traddr, entry->traddr, len); + return ret; } -static int connect_ctrls(struct nvmf_disc_rsp_page_hdr *log, int numrec) +int nvmf_connect(const char *desc, int argc, char **argv) { - int i; - int instance; - int ret = 0; - - for (i = 0; i < numrec; i++) { - if (!should_connect(&log->entries[i])) - continue; + char *subsysnqn = NULL; + char *transport = NULL, *traddr = NULL; + char *trsvcid = NULL, *hostnqn = NULL, *hostid = NULL; + char *hostkey = NULL, *ctrlkey = NULL; + char *hnqn = NULL, *hid = NULL; + char *config_file = PATH_NVMF_CONFIG; + unsigned int verbose = 0; + nvme_root_t r; + nvme_host_t h; + nvme_ctrl_t c; + int ret; + struct nvme_fabrics_config cfg; + enum nvme_print_flags flags = -1; + char *format = ""; - instance = connect_ctrl(&log->entries[i]); + OPT_ARGS(opts) = { + NVMF_OPTS(cfg), + OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file), + OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"), + OPT_FLAG("dump-config", 'O', &dump_config, "Dump JSON configuration to stdout"), + OPT_FMT("output-format", 'o', &format, "Output format: normal|json"), + OPT_END() + }; - /* clean success */ - if (instance >= 0) - continue; + nvmf_default_config(&cfg); - /* already connected print message */ - if (instance == -EALREADY) { - const char *traddr = log->entries[i].traddr; + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + return ret; - msg(LOG_NOTICE, "traddr=%.*s is already connected\n", - space_strip_len(NVMF_TRADDR_SIZE, - traddr), - traddr); - continue; - } + if (!strcmp(format, "")) + flags = -1; + else if (!strcmp(format, "normal")) + flags = NORMAL; + else if (!strcmp(format, "json")) + flags = JSON; + else + return EINVAL; - /* - * don't error out. The Discovery Log may contain - * devices that aren't necessarily connectable via - * the system/host transport port. Let those items - * fail and continue on to the next log element. - */ + if (!subsysnqn) { + fprintf(stderr, + "required argument [--nqn | -n] not specified\n"); + return EINVAL; } - return ret; -} - -static void nvmf_get_host_identifiers(int ctrl_instance) -{ - char *path; - - if (asprintf(&path, "%s/nvme%d", SYS_NVME, ctrl_instance) < 0) - return; - fabrics_cfg.hostnqn = nvme_get_ctrl_attr(path, "hostnqn"); - fabrics_cfg.hostid = nvme_get_ctrl_attr(path, "hostid"); -} - -static DEFINE_CLEANUP_FUNC(cleanup_log, struct nvmf_disc_rsp_page_hdr *, free); - -int do_discover(char *argstr, bool connect, enum nvme_print_flags flags) -{ - struct nvmf_disc_rsp_page_hdr *log __cleanup__(cleanup_log) = NULL; - char *dev_name; - int instance, numrec = 0, ret, err; - int status = 0; - struct connect_args *cargs; - - cargs = extract_connect_args(argstr); - if (!cargs) - return -ENOMEM; - - if (fabrics_cfg.device && - !ctrl_matches_connectargs(fabrics_cfg.device, cargs)) { - free(fabrics_cfg.device); - fabrics_cfg.device = NULL; + if (!transport) { + fprintf(stderr, + "required argument [--transport | -t] not specified\n"); + return EINVAL; } - if (!fabrics_cfg.device) - fabrics_cfg.device = find_ctrl_with_connectargs(cargs); - free_connect_args(cargs); - if (!fabrics_cfg.device) { - instance = add_ctrl(argstr); - } else { - instance = ctrl_instance(fabrics_cfg.device); - nvmf_get_host_identifiers(instance); + if (strcmp(transport, "loop")) { + if (!traddr) { + fprintf(stderr, + "required argument [--address | -a] not specified for transport %s\n", + transport); + return EINVAL; + } } - if (instance < 0) - return instance; - if (asprintf(&dev_name, "/dev/nvme%d", instance) < 0) + if (!strcmp(config_file, "none")) + config_file = NULL; + + r = nvme_create_root(stderr, map_log_level(verbose, quiet)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); return -errno; - ret = nvmf_get_log_page_discovery(dev_name, &log, &numrec, &status); - free(dev_name); - if (!fabrics_cfg.device && !fabrics_cfg.persistent) { - err = remove_ctrl(instance); - if (err) - return err; } - - switch (ret) { - case DISC_OK: - if (connect) - ret = connect_ctrls(log, numrec); - else if (fabrics_cfg.raw || flags == BINARY) - save_discovery_log(log, numrec); + ret = nvme_scan_topology(r, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Failed to scan topoplogy: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); + return ret; + } + nvme_read_config(r, config_file); + + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_from_file(); + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_generate(); + if (!hostid) + hostid = hid = nvmf_hostid_from_file(); + h = nvme_lookup_host(r, hostnqn, hostid); + if (!h) { + errno = ENOMEM; + goto out_free; + } + if (hostkey) + nvme_host_set_dhchap_key(h, hostkey); + if (!trsvcid) + trsvcid = get_default_trsvcid(transport, false); + c = nvme_create_ctrl(r, subsysnqn, transport, traddr, + cfg.host_traddr, cfg.host_iface, trsvcid); + if (!c) { + errno = ENOMEM; + goto out_free; + } + if (ctrlkey) + nvme_ctrl_set_dhchap_key(c, ctrlkey); + + errno = 0; + ret = nvmf_add_ctrl(h, c, &cfg); + if (ret) + fprintf(stderr, "no controller found: %s\n", + nvme_strerror(errno)); + else { + errno = 0; + if (flags == NORMAL) + print_connect_msg(c); else if (flags == JSON) - json_discovery_log(log, numrec, instance); - else - print_discovery_log(log, numrec, instance); - break; - case DISC_GET_NUMRECS: - msg(LOG_ERR, - "Get number of discovery log entries failed.\n"); - ret = status; - break; - case DISC_GET_LOG: - msg(LOG_ERR, "Get discovery log entries failed.\n"); - ret = status; - break; - case DISC_NO_LOG: - fprintf(stdout, "No discovery log entries to fetch.\n"); - ret = DISC_OK; - break; - case DISC_RETRY_EXHAUSTED: - fprintf(stdout, "Discovery retries exhausted.\n"); - ret = -EAGAIN; - break; - case DISC_NOT_EQUAL: - msg(LOG_ERR, - "Numrec values of last two get discovery log page not equal\n"); - ret = -EBADSLT; - break; - default: - msg(LOG_ERR, "Get discovery log page failed: %d\n", ret); - break; + json_connect_msg(c); } - return ret; +out_free: + free(hnqn); + free(hid); + if (dump_config) + nvme_dump_config(r); + nvme_free_tree(r); + return errno; } -static int discover_from_conf_file(const char *desc, char *argstr, - const struct argconfig_commandline_options *opts, bool connect) +int nvmf_disconnect(const char *desc, int argc, char **argv) { - FILE *f; - char line[256], *ptr, *all_args, *args, **argv; - int argc, err, ret = 0; - - f = fopen(PATH_NVMF_DISC, "r"); - if (f == NULL) { - msg(LOG_ERR, "No discover params given and no %s\n", - PATH_NVMF_DISC); - return -EINVAL; - } - - while (fgets(line, sizeof(line), f) != NULL) { - enum nvme_print_flags flags; + const char *device = "nvme device handle"; + nvme_root_t r; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + char *p; + int ret; - if (line[0] == '#' || line[0] == '\n') - continue; + struct config { + char *nqn; + char *device; + unsigned int verbose; + }; - args = strdup(line); - if (!args) { - msg(LOG_ERR, "failed to strdup args\n"); - ret = -ENOMEM; - goto out; - } - all_args = args; + struct config cfg = { 0 }; - argv = calloc(MAX_DISC_ARGS, BUF_SIZE); - if (!argv) { - msg(LOG_ERR, "failed to allocate argv vector: %m\n"); - free(args); - ret = -ENOMEM; - goto out; - } + OPT_ARGS(opts) = { + OPT_STRING("nqn", 'n', "NAME", &cfg.nqn, nvmf_nqn), + OPT_STRING("device", 'd', "DEV", &cfg.device, device), + OPT_INCR("verbose", 'v', &cfg.verbose, "Increase logging verbosity"), + OPT_END() + }; - argc = 0; - argv[argc++] = "discover"; - while ((ptr = strsep(&args, " =\n")) != NULL) - argv[argc++] = ptr; + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + return ret; - err = argconfig_parse(argc, argv, desc, opts); - if (err) - goto free_and_continue; + if (!cfg.nqn && !cfg.device) { + fprintf(stderr, + "Neither device name [--device | -d] nor NQN [--nqn | -n] provided\n"); + return EINVAL; + } - if (!fabrics_cfg.transport || !fabrics_cfg.traddr) - goto free_and_continue; + r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); + return -errno; + } + ret = nvme_scan_topology(r, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Failed to scan topoplogy: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); + return ret; + } - err = flags = validate_output_format(fabrics_cfg.output_format); - if (err < 0) - goto free_and_continue; - set_discovery_kato(&fabrics_cfg); + if (cfg.nqn) { + int i = 0; + char *n = cfg.nqn; - if (traddr_is_hostname(&fabrics_cfg)) { - ret = hostname2traddr(&fabrics_cfg); - if (ret) - goto out; + while ((p = strsep(&n, ",")) != NULL) { + if (!strlen(p)) + continue; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + if (strcmp(nvme_subsystem_get_nqn(s), p)) + continue; + nvme_subsystem_for_each_ctrl(s, c) { + if (!nvme_disconnect_ctrl(c)) + i++; + } + } + } } - - if (!fabrics_cfg.trsvcid) - discovery_trsvcid(&fabrics_cfg, true); - - err = build_options(argstr, BUF_SIZE, true); - if (err) { - ret = err; - goto free_and_continue; + printf("NQN:%s disconnected %d controller(s)\n", cfg.nqn, i); + } + + if (cfg.device) { + char *d; + + d = cfg.device; + while ((p = strsep(&d, ",")) != NULL) { + if (!strncmp(p, "/dev/", 5)) + p += 5; + c = nvme_scan_ctrl(r, p); + if (!c) { + fprintf(stderr, + "Did not find device %s: %s\n", + p, nvme_strerror(errno)); + nvme_free_tree(r); + return errno; + } + ret = nvme_disconnect_ctrl(c); + if (ret) + fprintf(stderr, + "Failed to disconnect %s: %s\n", + p, nvme_strerror(errno)); } - - err = do_discover(argstr, connect, flags); - if (err) - ret = err; - -free_and_continue: - free(all_args); - free(argv); - fabrics_cfg.transport = fabrics_cfg.traddr = - fabrics_cfg.trsvcid = fabrics_cfg.host_traddr = - fabrics_cfg.host_iface = NULL; } + nvme_free_tree(r); -out: - fclose(f); - return ret; + return 0; } -int fabrics_discover(const char *desc, int argc, char **argv, bool connect) +int nvmf_disconnect_all(const char *desc, int argc, char **argv) { - char argstr[BUF_SIZE]; + nvme_host_t h; + nvme_subsystem_t s; + nvme_root_t r; + nvme_ctrl_t c; int ret; - enum nvme_print_flags flags; - bool quiet = false; + + struct config { + char *transport; + unsigned int verbose; + }; + + struct config cfg = { 0 }; OPT_ARGS(opts) = { - OPT_LIST("transport", 't', &fabrics_cfg.transport, "transport type"), - OPT_LIST("traddr", 'a', &fabrics_cfg.traddr, "transport address"), - OPT_LIST("trsvcid", 's', &fabrics_cfg.trsvcid, "transport service id (e.g. IP port)"), - OPT_LIST("host-traddr", 'w', &fabrics_cfg.host_traddr, "host traddr (e.g. FC WWN's or IP source address)"), - OPT_LIST("host-iface", 'f', &fabrics_cfg.host_iface, "host transport interface (e.g. IP eth1, enp2s0)"), - OPT_LIST("hostnqn", 'q', &fabrics_cfg.hostnqn, "user-defined hostnqn (if default not used)"), - OPT_LIST("hostid", 'I', &fabrics_cfg.hostid, "user-defined hostid (if default not used)"), - OPT_LIST("raw", 'r', &fabrics_cfg.raw, "raw output file"), - OPT_LIST("device", 'd', &fabrics_cfg.device, "existing discovery controller device"), - OPT_INT("keep-alive-tmo", 'k', &fabrics_cfg.keep_alive_tmo, "keep alive timeout period in seconds"), - OPT_INT("reconnect-delay", 'c', &fabrics_cfg.reconnect_delay, "reconnect timeout period in seconds"), - OPT_INT("ctrl-loss-tmo", 'l', &fabrics_cfg.ctrl_loss_tmo, "controller loss timeout period in seconds"), - OPT_INT("fast_io_fail_tmo",'f',&fabrics_cfg.fast_io_fail_tmo, "fast I/O fail timeout (default off)"), - OPT_INT("tos", 'T', &fabrics_cfg.tos, "type of service"), - OPT_FLAG("hdr_digest", 'g', &fabrics_cfg.hdr_digest, "enable transport protocol header digest (TCP transport)"), - OPT_FLAG("data_digest", 'G', &fabrics_cfg.data_digest, "enable transport protocol data digest (TCP transport)"), - OPT_INT("nr-io-queues", 'i', &fabrics_cfg.nr_io_queues, "number of io queues to use (default is core count)"), - OPT_INT("nr-write-queues", 'W', &fabrics_cfg.nr_write_queues, "number of write queues to use (default 0)"), - OPT_INT("nr-poll-queues", 'P', &fabrics_cfg.nr_poll_queues, "number of poll queues to use (default 0)"), - OPT_INT("queue-size", 'Q', &fabrics_cfg.queue_size, "number of io queue elements to use (default 128)"), - OPT_FLAG("persistent", 'p', &fabrics_cfg.persistent, "persistent discovery connection"), - OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"), - OPT_FLAG("matching", 'm', &fabrics_cfg.matching_only, "connect only records matching the traddr"), - OPT_FMT("output-format", 'o', &fabrics_cfg.output_format, output_format), + OPT_STRING("transport", 'r', "STR", (char *)&cfg.transport, nvmf_tport), + OPT_INCR("verbose", 'v', &cfg.verbose, "Increase logging verbosity"), OPT_END() }; - fabrics_cfg.tos = -1; ret = argconfig_parse(argc, argv, desc, opts); if (ret) - goto out; + return ret; - ret = flags = validate_output_format(fabrics_cfg.output_format); - if (ret < 0) - goto out; - if (fabrics_cfg.device && strcmp(fabrics_cfg.device, "none")) { - fabrics_cfg.device = strdup(fabrics_cfg.device); - if (!fabrics_cfg.device) { - ret = -ENOMEM; - goto out; - } + r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); + return -errno; + } + ret = nvme_scan_topology(r, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Failed to scan topoplogy: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); + return ret; } - if (quiet) - log_level = LOG_WARNING; - - if (fabrics_cfg.device && !strcmp(fabrics_cfg.device, "none")) - fabrics_cfg.device = NULL; - - fabrics_cfg.nqn = NVME_DISC_SUBSYS_NAME; - - if (!fabrics_cfg.transport && !fabrics_cfg.traddr) { - ret = discover_from_conf_file(desc, argstr, opts, connect); - } else { - set_discovery_kato(&fabrics_cfg); - - if (traddr_is_hostname(&fabrics_cfg)) { - ret = hostname2traddr(&fabrics_cfg); - if (ret) - goto out; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + if (cfg.transport && + strcmp(cfg.transport, + nvme_ctrl_get_transport(c))) + continue; + else if (!strcmp(nvme_ctrl_get_transport(c), + "pcie")) + continue; + if (nvme_disconnect_ctrl(c)) + fprintf(stderr, + "failed to disconnect %s\n", + nvme_ctrl_get_name(c)); + } } - - if (!fabrics_cfg.trsvcid) - discovery_trsvcid(&fabrics_cfg, true); - - ret = build_options(argstr, BUF_SIZE, true); - if (ret) - goto out; - - ret = do_discover(argstr, connect, flags); } + nvme_free_tree(r); -out: - return nvme_status_to_errno(ret, true); + return 0; } -int fabrics_connect(const char *desc, int argc, char **argv) +int nvmf_config(const char *desc, int argc, char **argv) { - char argstr[BUF_SIZE]; - int instance, ret; - enum nvme_print_flags flags = -1; + char *subsysnqn = NULL; + char *transport = NULL, *traddr = NULL; + char *trsvcid = NULL, *hostnqn = NULL, *hostid = NULL; + char *hnqn = NULL, *hid = NULL; + char *hostkey = NULL, *ctrlkey = NULL; + char *config_file = PATH_NVMF_CONFIG; + unsigned int verbose = 0; + nvme_root_t r; + int ret; + struct nvme_fabrics_config cfg; + bool scan_tree = false, modify_config = false, update_config = false; OPT_ARGS(opts) = { - OPT_LIST("transport", 't', &fabrics_cfg.transport, "transport type"), - OPT_LIST("nqn", 'n', &fabrics_cfg.nqn, "nqn name"), - OPT_LIST("traddr", 'a', &fabrics_cfg.traddr, "transport address"), - OPT_LIST("trsvcid", 's', &fabrics_cfg.trsvcid, "transport service id (e.g. IP port)"), - OPT_LIST("host-traddr", 'w', &fabrics_cfg.host_traddr, "host traddr (e.g. FC WWN's or IP source address)"), - OPT_LIST("host-iface", 'f', &fabrics_cfg.host_iface, "host transport interface (e.g. IP eth1, enp2s0)"), - OPT_LIST("hostnqn", 'q', &fabrics_cfg.hostnqn, "user-defined hostnqn"), - OPT_LIST("hostid", 'I', &fabrics_cfg.hostid, "user-defined hostid (if default not used)"), - OPT_INT("nr-io-queues", 'i', &fabrics_cfg.nr_io_queues, "number of io queues to use (default is core count)"), - OPT_INT("nr-write-queues", 'W', &fabrics_cfg.nr_write_queues, "number of write queues to use (default 0)"), - OPT_INT("nr-poll-queues", 'P', &fabrics_cfg.nr_poll_queues, "number of poll queues to use (default 0)"), - OPT_INT("queue-size", 'Q', &fabrics_cfg.queue_size, "number of io queue elements to use (default 128)"), - OPT_INT("keep-alive-tmo", 'k', &fabrics_cfg.keep_alive_tmo, "keep alive timeout period in seconds"), - OPT_INT("reconnect-delay", 'c', &fabrics_cfg.reconnect_delay, "reconnect timeout period in seconds"), - OPT_INT("ctrl-loss-tmo", 'l', &fabrics_cfg.ctrl_loss_tmo, "controller loss timeout period in seconds"), - OPT_INT("fast_io_fail_tmo", 'f', &fabrics_cfg.fast_io_fail_tmo, "fast I/O fail timeout (default off)"), - OPT_INT("tos", 'T', &fabrics_cfg.tos, "type of service"), - OPT_FLAG("duplicate-connect", 'D', &fabrics_cfg.duplicate_connect, "allow duplicate connections between same transport host and subsystem port"), - OPT_FLAG("disable-sqflow", 'd', &fabrics_cfg.disable_sqflow, "disable controller sq flow control (default false)"), - OPT_FLAG("hdr-digest", 'g', &fabrics_cfg.hdr_digest, "enable transport protocol header digest (TCP transport)"), - OPT_FLAG("data-digest", 'G', &fabrics_cfg.data_digest, "enable transport protocol data digest (TCP transport)"), - OPT_FMT("output-format", 'o', &fabrics_cfg.output_format, "Output format: normal|json"), + NVMF_OPTS(cfg), + OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file), + OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"), + OPT_FLAG("scan", 'R', &scan_tree, "Scan current NVMeoF topology"), + OPT_FLAG("modify", 'M', &modify_config, "Modify JSON configuration file"), + OPT_FLAG("dump", 'O', &dump_config, "Dump JSON configuration to stdout"), + OPT_FLAG("update", 'U', &update_config, "Update JSON configuration file"), OPT_END() }; - fabrics_cfg.output_format = ""; - fabrics_cfg.tos = -1; + nvmf_default_config(&cfg); + ret = argconfig_parse(argc, argv, desc, opts); if (ret) - goto out; + return ret; - if (!strcmp(fabrics_cfg.output_format, "")) - flags = -1; - else if (!strcmp(fabrics_cfg.output_format, "normal")) - flags = NORMAL; - else if (!strcmp(fabrics_cfg.output_format, "json")) - flags = JSON; - else { - ret = -EINVAL; - goto out; - } + if (!strcmp(config_file, "none")) + config_file = NULL; - if (traddr_is_hostname(&fabrics_cfg)) { - ret = hostname2traddr(&fabrics_cfg); - if (ret) + r = nvme_create_root(stderr, map_log_level(verbose, quiet)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); + return -errno; + } + if (scan_tree) { + ret = nvme_scan_topology(r, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Failed to scan topoplogy: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); + return ret; + } + } + nvme_read_config(r, config_file); + + if (modify_config) { + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_from_file(); + if (!hostid && hnqn) + hostid = hid = nvmf_hostid_from_file(); + h = nvme_lookup_host(r, hostnqn, hostid); + if (!h) { + fprintf(stderr, "Failed to lookup host '%s': %s\n", + hostnqn, nvme_strerror(errno)); + goto out; + } + if (hostkey) + nvme_host_set_dhchap_key(h, hostkey); + s = nvme_lookup_subsystem(h, NULL, subsysnqn); + if (!s) { + fprintf(stderr, "Failed to lookup subsystem '%s': %s\n", + subsysnqn, nvme_strerror(errno)); + goto out; + } + c = nvme_lookup_ctrl(s, transport, traddr, + cfg.host_traddr, cfg.host_iface, + trsvcid, NULL); + if (!c) { + fprintf(stderr, "Failed to lookup controller: %s\n", + nvme_strerror(errno)); goto out; + } + nvmf_update_config(c, &cfg); + if (ctrlkey) + nvme_ctrl_set_dhchap_key(c, ctrlkey); } - if (!fabrics_cfg.trsvcid) - discovery_trsvcid(&fabrics_cfg, false); - - ret = build_options(argstr, BUF_SIZE, false); - if (ret) - goto out; - - if (!fabrics_cfg.nqn) { - msg(LOG_ERR, "need a -n argument\n"); - ret = -EINVAL; - goto out; - } + if (update_config) + nvme_update_config(r); - instance = add_ctrl(argstr); - if (instance < 0) - ret = instance; - else { - if (flags == NORMAL) - print_connect_msg(instance); - else if (flags == JSON) - json_connect_msg(instance); - } + if (dump_config) + nvme_dump_config(r); out: - return nvme_status_to_errno(ret, true); -} - -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; + if (hid) + free(hid); + if (hnqn) + free(hnqn); + nvme_free_tree(r); + return errno; } -/* - * Returns 1 if disconnect occurred, 0 otherwise. - */ -static int disconnect_subsys(const char *nqn, char *ctrl) +static void dim_operation(nvme_ctrl_t c, enum nvmf_dim_tas tas, const char * name) { - 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) { - msg(LOG_ERR, "Failed to open %s: %s\n", - sysfs_nqn_path, strerror(errno)); - goto free; + static const char * const task[] = { + [NVMF_DIM_TAS_REGISTER] = "register", + [NVMF_DIM_TAS_DEREGISTER] = "deregister", + }; + const char * t; + int status; + __u32 result; + + t = (tas > NVMF_DIM_TAS_DEREGISTER || !task[tas]) ? "reserved" : task[tas]; + status = nvmf_register_ctrl(c, tas, &result); + if (status == NVME_SC_SUCCESS) { + printf("%s DIM %s command success\n", name, t); + } else if (status < NVME_SC_SUCCESS) { + fprintf(stderr, "%s DIM %s command error. Status:0x%04x - %s\n", + name, t, status, nvme_status_to_string(status, false)); + } else { + fprintf(stderr, "%s DIM %s command error. Result:0x%04x, Status:0x%04x - %s\n", + name, t, result, status, nvme_status_to_string(status, false)); } - - 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(const 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(const char *device) +int nvmf_dim(const char *desc, int argc, char **argv) { - int instance; - - instance = ctrl_instance(device); - if (instance < 0) - return instance; - return remove_ctrl(instance); -} - -int fabrics_disconnect(const char *desc, int argc, char **argv) -{ - const char *nqn = "nqn name"; - const char *device = "nvme device"; + enum nvmf_dim_tas tas; + nvme_root_t r; + nvme_ctrl_t c; + char *p; int ret; + struct { + char *nqn; + char *device; + char *tas; + unsigned int verbose; + } cfg = { 0 }; + OPT_ARGS(opts) = { - OPT_LIST("nqn", 'n', &fabrics_cfg.nqn, nqn), - OPT_LIST("device", 'd', &fabrics_cfg.device, device), + OPT_STRING("nqn", 'n', "NAME", &cfg.nqn, "Comma-separated list of DC nqn"), + OPT_STRING("device", 'd', "DEV", &cfg.device, "Comma-separated list of DC nvme device handle."), + OPT_STRING("task", 't', "TASK", &cfg.tas, "[register|deregister]"), + OPT_INCR("verbose", 'v', &cfg.verbose, "Increase logging verbosity"), OPT_END() }; ret = argconfig_parse(argc, argv, desc, opts); if (ret) - goto out; + return ret; - if (!fabrics_cfg.nqn && !fabrics_cfg.device) { - msg(LOG_ERR, "need a -n or -d argument\n"); - ret = -EINVAL; - goto out; + if (!cfg.nqn && !cfg.device) { + fprintf(stderr, + "Neither device name [--device | -d] nor NQN [--nqn | -n] provided\n"); + return EINVAL; } - if (fabrics_cfg.nqn) { - ret = disconnect_by_nqn(fabrics_cfg.nqn); - if (ret < 0) - msg(LOG_ERR, "Failed to disconnect by NQN: %s\n", - fabrics_cfg.nqn); - else { - printf("NQN:%s disconnected %d controller(s)\n", fabrics_cfg.nqn, ret); - ret = 0; - } + if (!cfg.tas) { + fprintf(stderr, + "Task [--task | -t] must be specified\n"); + return EINVAL; } - if (fabrics_cfg.device) { - ret = disconnect_by_device(fabrics_cfg.device); - if (ret) - msg(LOG_ERR, - "Failed to disconnect by device name: %s\n", - fabrics_cfg.device); + /* Allow partial name (e.g. "reg" for "register" */ + if (strstarts("register", cfg.tas)) { + tas = NVMF_DIM_TAS_REGISTER; + } else if (strstarts("deregister", cfg.tas)) { + tas = NVMF_DIM_TAS_DEREGISTER; + } else { + fprintf(stderr, "Invalid --task: %s\n", cfg.tas); + return EINVAL; } -out: - return nvme_status_to_errno(ret, true); -} - -int fabrics_disconnect_all(const char *desc, int argc, char **argv) -{ - struct nvme_topology t = { }; - int i, j, err; - - OPT_ARGS(opts) = { - OPT_END() - }; - - err = argconfig_parse(argc, argv, desc, opts); - if (err) - goto out; - - err = scan_subsystems(&t, NULL, 0, 0, NULL); - if (err) { - msg(LOG_ERR, "Failed to scan namespaces\n"); - goto out; + r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); + return -errno; + } + ret = nvme_scan_topology(r, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Failed to scan topoplogy: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); + return ret; } - for (i = 0; i < t.nr_subsystems; i++) { - struct nvme_subsystem *s = &t.subsystems[i]; - - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + if (cfg.nqn) { + nvme_host_t h; + nvme_subsystem_t s; + char *n = cfg.nqn; - if (!c->transport || !strcmp(c->transport, "pcie")) + while ((p = strsep(&n, ",")) != NULL) { + if (!strlen(p)) continue; - err = disconnect_by_device(c->name); - if (err) - goto free; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + if (strcmp(nvme_subsystem_get_nqn(s), p)) + continue; + nvme_subsystem_for_each_ctrl(s, c) { + dim_operation(c, tas, p); + } + } + } } } -free: - free_topology(&t); -out: - return nvme_status_to_errno(err, true); + + if (cfg.device) { + char *d = cfg.device; + + while ((p = strsep(&d, ",")) != NULL) { + if (!strncmp(p, "/dev/", 5)) + p += 5; + c = nvme_scan_ctrl(r, p); + if (!c) { + fprintf(stderr, + "Did not find device %s: %s\n", + p, nvme_strerror(errno)); + nvme_free_tree(r); + return errno; + } + dim_operation(c, tas, p); + } + } + + nvme_free_tree(r); + + return 0; } @@ -1,57 +1,11 @@ -#ifndef _DISCOVER_H -#define _DISCOVER_H - -#define NVMF_DEF_DISC_TMO 30 - -extern char *hostnqn_read(void); - -extern int fabrics_discover(const char *desc, int argc, char **argv, bool connect); -extern int fabrics_connect(const char *desc, int argc, char **argv); -extern int fabrics_disconnect(const char *desc, int argc, char **argv); -extern int fabrics_disconnect_all(const char *desc, int argc, char **argv); - -/* Symbols used by monitor.c */ - -const char *arg_str(const char * const *strings, size_t array_size, size_t idx); - -struct fabrics_config { - const char *nqn; - const char *transport; - const char *traddr; - const char *trsvcid; - const char *host_traddr; - const char *host_iface; - const char *hostnqn; - const char *hostid; - int nr_io_queues; - int nr_write_queues; - int nr_poll_queues; - int queue_size; - int keep_alive_tmo; - int reconnect_delay; - int ctrl_loss_tmo; - int fast_io_fail_tmo; - int tos; - const char *raw; - char *device; - int duplicate_connect; - int disable_sqflow; - int hdr_digest; - int data_digest; - bool persistent; - bool matching_only; - const char *output_format; -}; -extern struct fabrics_config fabrics_cfg; - -extern const char *const trtypes[]; - -#define BUF_SIZE 4096 - -int build_options(char *argstr, int max_len, bool discover); -int do_discover(char *argstr, bool connect, enum nvme_print_flags flags); -int ctrl_instance(const char *device); -char *parse_conn_arg(const char *conargs, const char delim, const char *field); -int remove_ctrl(int instance); +#ifndef _FABRICS_H +#define _FABRICS_H + +extern int nvmf_discover(const char *desc, int argc, char **argv, bool connect); +extern int nvmf_connect(const char *desc, int argc, char **argv); +extern int nvmf_disconnect(const char *desc, int argc, char **argv); +extern int nvmf_disconnect_all(const char *desc, int argc, char **argv); +extern int nvmf_config(const char *desc, int argc, char **argv); +extern int nvmf_dim(const char *desc, int argc, char **argv); #endif diff --git a/linux/lightnvm.h b/linux/lightnvm.h deleted file mode 100644 index f678ffb..0000000 --- a/linux/lightnvm.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 <linux/kernel.h> -#include <linux/ioctl.h> -#else /* __KERNEL__ */ -#include <stdio.h> -#include <sys/ioctl.h> -#define DISK_NAME_LEN 32 -#endif /* __KERNEL__ */ - -#include <linux/types.h> -#include <linux/ioctl.h> - -#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; -}; - -struct nvm_ioctl_create_extended { - __u16 lun_begin; - __u16 lun_end; - __u16 over_prov; - __u16 rsv; -}; - -enum { - NVM_CONFIG_TYPE_SIMPLE = 0, - NVM_CONFIG_TYPE_EXTENDED = 1, -}; - -struct nvm_ioctl_create_conf { - __u32 type; - union { - struct nvm_ioctl_create_simple s; - struct nvm_ioctl_create_extended e; - }; -}; - -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 diff --git a/linux/nvme.h b/linux/nvme.h deleted file mode 100644 index db1e4ac..0000000 --- a/linux/nvme.h +++ /dev/null @@ -1,2013 +0,0 @@ -/* - * 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 <linux/types.h> - -#ifdef LIBUUID -#include <uuid/uuid.h> -#else -typedef struct { - uint8_t b[16]; -} uuid_t; -#endif - -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#else -#define __force -#endif - -static inline __le16 cpu_to_le16(uint16_t x) -{ - return (__force __le16)htole16(x); -} -static inline __le32 cpu_to_le32(uint32_t x) -{ - return (__force __le32)htole32(x); -} -static inline __le64 cpu_to_le64(uint64_t x) -{ - return (__force __le64)htole64(x); -} - -static inline uint16_t le16_to_cpu(__le16 x) -{ - return le16toh((__force __u16)x); -} -static inline uint32_t le32_to_cpu(__le32 x) -{ - return le32toh((__force __u32)x); -} -static inline uint64_t le64_to_cpu(__le64 x) -{ - return le64toh((__force __u64)x); -} - -/* 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_DISC_IP_PORT 8009 - -#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 */ - NVMF_ADDR_FAMILY_LOOP = 254, /* Reserved for host usage */ - NVMF_ADDR_FAMILY_MAX, -}; - -/* Transport Type codes for Discovery Log Page entry TRTYPE field */ -enum { - NVMF_TRTYPE_RDMA = 1, /* RDMA */ - NVMF_TRTYPE_FC = 2, /* Fibre Channel */ - NVMF_TRTYPE_TCP = 3, /* TCP */ - 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 */ - NVMF_TREQ_DISABLE_SQFLOW = (1 << 2), /* SQ flow control disable supported */ -}; - -/* 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 */ -}; - -/* TCP port security type for Discovery Log Page entry TSAS - */ -enum { - NVMF_TCP_SECTYPE_NONE = 0, /* No Security */ - NVMF_TCP_SECTYPE_TLS = 1, /* Transport Layer Security */ -}; - -/* I/O Command Sets - */ -enum { - NVME_IOCS_NVM = 0x00, - NVME_IOCS_ZONED = 0x02, -}; - -#define NVME_NUM_IOCS_COMBINATIONS 512 - -#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_CMBMSC = 0x0050, /* Controller Memory Buffer Memory Space Control */ - NVME_REG_CMBSTS = 0x0058, /* Controller Memory Buffer Status */ - NVME_REG_PMRCAP = 0x0e00, /* Persistent Memory Capabilities */ - NVME_REG_PMRCTL = 0x0e04, /* Persistent Memory Region Control */ - NVME_REG_PMRSTS = 0x0e08, /* Persistent Memory Region Status */ - NVME_REG_PMREBS = 0x0e0c, /* Persistent Memory Region Elasticity Buffer Size */ - NVME_REG_PMRSWTP= 0x0e10, /* Persistent Memory Region Sustained Write Throughput */ - NVME_REG_PMRMSCL= 0x0e14, /* Persistent Memory Region Controller Memory Space Control Lower */ - NVME_REG_PMRMSCU= 0x0e18, /* Persistent Memory Region Controller Memory Space Control Upper*/ - 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]; -}; - -/* idle and active power scales occupy the last 2 bits of the field */ -#define POWER_SCALE(s) ((s) >> 6) - -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; - __le16 rrls; - __u8 rsvd102[9]; - __u8 cntrltype; - char fguid[16]; - __le16 crdt1; - __le16 crdt2; - __le16 crdt3; - __u8 rsvd134[119]; - __u8 nvmsr; - __u8 vwci; - __u8 mec; - __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; - __le16 nsetidmax; - __le16 endgidmax; - __u8 anatt; - __u8 anacap; - __le32 anagrpmax; - __le32 nanagrpid; - __le32 pels; - __le16 domainid; - __u8 rsvd358[10]; - __u8 megcap[16]; - __u8 rsvd384[128]; - __u8 sqes; - __u8 cqes; - __le16 maxcmd; - __le32 nn; - __le16 oncs; - __le16 fuses; - __u8 fna; - __u8 vwc; - __le16 awun; - __le16 awupf; - __u8 icsvscc; - __u8 nwpc; - __le16 acwu; - __le16 ocfs; - __le32 sgls; - __le32 mnan; - __u8 maxdna[16]; - __le32 maxcna; - __u8 rsvd564[204]; - char subnqn[256]; - __u8 rsvd1024[768]; - __le32 ioccsz; - __le32 iorcsz; - __le16 icdoff; - __u8 fcatt; - __u8 msdbd; - __le16 ofcs; - __u8 rsvd1806[242]; - 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, - NVME_CTRL_CTRATT_128_ID = 1 << 0, - NVME_CTRL_CTRATT_NON_OP_PSP = 1 << 1, - NVME_CTRL_CTRATT_NVM_SETS = 1 << 2, - NVME_CTRL_CTRATT_READ_RECV_LVLS = 1 << 3, - NVME_CTRL_CTRATT_ENDURANCE_GROUPS = 1 << 4, - NVME_CTRL_CTRATT_PREDICTABLE_LAT = 1 << 5, - NVME_CTRL_CTRATT_NAMESPACE_GRANULARITY = 1 << 7, - NVME_CTRL_CTRATT_UUID_LIST = 1 << 9, -}; - -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 dlfeat; - __le16 nawun; - __le16 nawupf; - __le16 nacwu; - __le16 nabsn; - __le16 nabo; - __le16 nabspf; - __le16 noiob; - __u8 nvmcap[16]; - __le16 npwg; - __le16 npwa; - __le16 npdg; - __le16 npda; - __le16 nows; - __le16 mssrl; - __le32 mcl; - __u8 msrc; - __u8 rsvd81[11]; - __le32 anagrpid; - __u8 rsvd96[3]; - __u8 nsattr; - __le16 nvmsetid; - __le16 endgid; - __u8 nguid[16]; - __u8 eui64[8]; - struct nvme_lbaf lbaf[64]; - __u8 vs[3712]; -}; - -struct nvme_cmd_set_independent_id_ns { - __u8 nsfeat; - __u8 nmic; - __u8 rescap; - __u8 fpi; - __le32 anagrpid; - __u8 nsattr; - __u8 rsvd9; - __le16 nvmsetid; - __le16 endgid; - __u8 nstat; - __u8 rsvd15[4081]; -}; - -struct nvme_id_iocs { - __le64 iocs[NVME_NUM_IOCS_COMBINATIONS]; -}; - -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_NVMSET_LIST = 0x04, - NVME_ID_CNS_CSI_ID_NS = 0x05, - NVME_ID_CNS_CSI_ID_CTRL = 0x06, - NVME_ID_CNS_CSI_NS_ACTIVE_LIST = 0x07, - NVME_ID_CNS_CS_INDEPENDENT_ID_NS = 0x08, - 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, - NVME_ID_CNS_PRIMARY_CTRL_CAPS = 0x14, - NVME_ID_CNS_SCNDRY_CTRL_LIST = 0x15, - NVME_ID_CNS_NS_GRANULARITY = 0x16, - NVME_ID_CNS_UUID_LIST = 0x17, - NVME_ID_CNS_DOMAIN_LIST = 0x18, - NVME_ID_CNS_ENDURANCE_GROUP_ID = 0x19, - NVME_ID_CNS_CSI_NS_PRESENT_LIST = 0x1a, - NVME_ID_CNS_CSI_NS_PRESENT = 0x1b, - NVME_ID_CNS_CSI = 0x1c, -}; - -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 -#define NVME_NIDT_CSI_LEN 1 - -enum { - NVME_NIDT_EUI64 = 0x01, - NVME_NIDT_NGUID = 0x02, - NVME_NIDT_UUID = 0x03, - NVME_NIDT_CSI = 0x04, -}; - -#define NVME_MAX_NVMSET 31 - -struct nvme_nvmset_attr_entry { - __le16 id; - __le16 endurance_group_id; - __u8 rsvd4[4]; - __le32 random_4k_read_typical; - __le32 opt_write_size; - __u8 total_nvmset_cap[16]; - __u8 unalloc_nvmset_cap[16]; - __u8 rsvd48[80]; -}; - -struct nvme_id_nvmset { - __u8 nid; - __u8 rsvd1[127]; - struct nvme_nvmset_attr_entry ent[NVME_MAX_NVMSET]; -}; - -struct nvme_id_ns_granularity_list_entry { - __le64 namespace_size_granularity; - __le64 namespace_capacity_granularity; -}; - -struct nvme_id_ns_granularity_list { - __le32 attributes; - __u8 num_descriptors; - __u8 rsvd[27]; - struct nvme_id_ns_granularity_list_entry entry[16]; -}; - -#define NVME_MAX_UUID_ENTRIES 128 -struct nvme_id_uuid_list_entry { - __u8 header; - __u8 rsvd1[15]; - __u8 uuid[16]; -}; - -struct nvme_id_uuid_list { - struct nvme_id_uuid_list_entry entry[NVME_MAX_UUID_ENTRIES]; -}; - -/** - * struct nvme_telemetry_log_page_hdr - structure for telemetry log page - * @lpi: Log page identifier - * @iee_oui: IEEE OUI Identifier - * @dalb1: Data area 1 last block - * @dalb2: Data area 2 last block - * @dalb3: Data area 3 last block - * @dalb4: Data area 4 last block - * @ctrlavail: Controller initiated data available - * @ctrldgn: Controller initiated telemetry Data Generation Number - * @rsnident: Reason Identifier - * @telemetry_dataarea: Contains telemetry data block - * - * This structure can be used for both telemetry host-initiated log page - * and controller-initiated log page. - */ -struct nvme_telemetry_log_page_hdr { - __u8 lpi; - __u8 rsvd[4]; - __u8 iee_oui[3]; - __le16 dalb1; - __le16 dalb2; - __le16 dalb3; - __u8 rsvd1[2]; - __le32 dalb4; - __u8 rsvd2[362]; - __u8 ctrlavail; - __u8 ctrldgn; - __u8 rsnident[128]; - __u8 telemetry_dataarea[0]; -}; - -struct nvme_endurance_group_log { - __u8 critical_warning; - __u8 rsvd1[2]; - __u8 avl_spare; - __u8 avl_spare_threshold; - __u8 percent_used; - __u8 rsvd6[26]; - __u8 endurance_estimate[16]; - __u8 data_units_read[16]; - __u8 data_units_written[16]; - __u8 media_units_written[16]; - __u8 host_read_cmds[16]; - __u8 host_write_cmds[16]; - __u8 media_data_integrity_err[16]; - __u8 num_err_info_log_entries[16]; - __u8 rsvd160[352]; -}; - -struct nvme_smart_log { - __u8 critical_warning; - __u8 temperature[2]; - __u8 avail_spare; - __u8 spare_thresh; - __u8 percent_used; - __u8 endu_grp_crit_warn_sumry; - __u8 rsvd7[25]; - __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_self_test_res { - __u8 dsts; - __u8 seg; - __u8 vdi; - __u8 rsvd3; - __le64 poh; - __le32 nsid; - __le64 flba; - __u8 sct; - __u8 sc; - __u8 vs[2]; -} __attribute__((packed)); - -enum { - NVME_ST_CODE_SHIFT = 4, - NVME_ST_CODE_SHORT_OP = 0x1, - NVME_ST_CODE_EXT_OP = 0x2, - NVME_ST_CODE_VS = 0xe, - NVME_ST_RES_MASK = 0xf, - NVME_ST_RES_NO_ERR = 0x0, - NVME_ST_RES_ABORTED = 0x1, - NVME_ST_RES_CLR = 0x2, - NVME_ST_RES_NS_REMOVED = 0x3, - NVME_ST_RES_ABORTED_FORMAT = 0x4, - NVME_ST_RES_FATAL_ERR = 0x5, - NVME_ST_RES_UNKNOWN_SEG_FAIL = 0x6, - NVME_ST_RES_KNOWN_SEG_FAIL = 0x7, - NVME_ST_RES_ABORTED_UNKNOWN = 0x8, - NVME_ST_RES_ABORTED_SANITIZE = 0x9, - NVME_ST_RES_NOT_USED = 0xf, - NVME_ST_VALID_NSID = 1 << 0, - NVME_ST_VALID_FLBA = 1 << 1, - NVME_ST_VALID_SCT = 1 << 2, - NVME_ST_VALID_SC = 1 << 3, - NVME_ST_REPORTS = 20, - NVME_ST_LOG_ENTRY_SIZE = 28, - NVME_ST_LOG_HEAD_SIZE = 4, -}; - -struct nvme_self_test_log { - __u8 crnt_dev_selftest_oprn; - __u8 crnt_dev_selftest_compln; - __u8 rsvd2[2]; - struct nvme_self_test_res result[20]; -} __attribute__((packed)); - -struct nvme_fw_slot_info_log { - __u8 afi; - __u8 rsvd1[7]; - __le64 frs[7]; - __u8 rsvd64[448]; -}; - -struct nvme_lba_status_desc { - __le64 dslba; - __le32 nlb; - __u8 rsvd_12; - __u8 status; - __u8 rsvd_15_14[2]; -}; - -struct nvme_lba_status { - __le32 nlsd; - __u8 cmpc; - __u8 rsvd_7_5[3]; - struct nvme_lba_status_desc descs[0]; -}; - -/* NVMe Namespace Write Protect State */ -enum { - NVME_NS_NO_WRITE_PROTECT = 0, - NVME_NS_WRITE_PROTECT, - NVME_NS_WRITE_PROTECT_POWER_CYCLE, - NVME_NS_WRITE_PROTECT_PERMANENT, -}; - -#define NVME_MAX_CHANGED_NAMESPACES 1024 - -struct nvme_changed_ns_list_log { - __le32 log[NVME_MAX_CHANGED_NAMESPACES]; -}; - -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, - NVME_CMD_EFFECTS_UUID_SEL = 1 << 19, -}; - -struct nvme_effects_log { - __le32 acs[256]; - __le32 iocs[256]; - __u8 resv[2048]; -}; - -enum nvme_ana_state { - NVME_ANA_OPTIMIZED = 0x01, - NVME_ANA_NONOPTIMIZED = 0x02, - NVME_ANA_INACCESSIBLE = 0x03, - NVME_ANA_PERSISTENT_LOSS = 0x04, - NVME_ANA_CHANGE = 0x0f, -}; - -struct nvme_ana_group_desc { - __le32 grpid; - __le32 nnsids; - __le64 chgcnt; - __u8 state; - __u8 rsvd17[15]; - __le32 nsids[]; -}; - -/* flag for the log specific field of the ANA log */ -#define NVME_ANA_LOG_RGO (1 << 0) - -struct nvme_ana_rsp_hdr { - __le64 chgcnt; - __le16 ngrps; - __le16 rsvd10[3]; -}; - -/* persistent event type 02h */ -struct nvme_fw_commit_event { - __le64 old_fw_rev; - __le64 new_fw_rev; - __u8 fw_commit_action; - __u8 fw_slot; - __u8 sct_fw; - __u8 sc_fw; - __le16 vndr_assign_fw_commit_rc; -} __attribute__((packed)); - -/* persistent event type 03h */ -struct nvme_time_stamp_change_event { - __le64 previous_timestamp; - __le64 ml_secs_since_reset; -}; - -/* persistent event type 04h */ -struct nvme_power_on_reset_info_list { - __le16 cid; - __u8 fw_act; - __u8 op_in_prog; - __u8 rsvd4[12]; - __le32 ctrl_power_cycle; - __le64 power_on_ml_seconds; - __le64 ctrl_time_stamp; -} __attribute__((packed)); - -/* persistent event type 05h */ -struct nvme_nss_hw_err_event { - __le16 nss_hw_err_event_code; - __u8 rsvd2[2]; - __u8 *add_hw_err_info; -}; - -/* persistent event type 06h */ -struct nvme_change_ns_event { - __le32 nsmgt_cdw10; - __u8 rsvd4[4]; - __le64 nsze; - __u8 rsvd16[8]; - __le64 nscap; - __u8 flbas; - __u8 dps; - __u8 nmic; - __u8 rsvd35; - __le32 ana_grp_id; - __le16 nvmset_id; - __le16 rsvd42; - __le32 nsid; -}; - -/* persistent event type 07h */ -struct nvme_format_nvm_start_event { - __le32 nsid; - __u8 fna; - __u8 rsvd5[3]; - __le32 format_nvm_cdw10; -}; - -/* persistent event type 08h */ -struct nvme_format_nvm_compln_event { - __le32 nsid; - __u8 smallest_fpi; - __u8 format_nvm_status; - __le16 compln_info; - __le32 status_field; -}; - -/* persistent event type 09h */ -struct nvme_sanitize_start_event { - __le32 sani_cap; - __le32 sani_cdw10; - __le32 sani_cdw11; -}; - -/* persistent event type 0Ah */ -struct nvme_sanitize_compln_event { - __le16 sani_prog; - __le16 sani_status; - __le16 cmpln_info; - __u8 rsvd6[2]; -}; - -/* persistent event type 0Dh */ -struct nvme_thermal_exc_event { - __u8 over_temp; - __u8 threshold; -}; - -/* persistent event entry head */ -struct nvme_persistent_event_entry_head { - __u8 etype; - __u8 etype_rev; - __u8 ehl; - __u8 rsvd3; - __le16 ctrl_id; - __le64 etimestamp; - __u8 rsvd14[6]; - __le16 vsil; - __le16 el; -} __attribute__((packed)); - -/* persistent event log head */ -struct nvme_persistent_event_log_head { - __u8 log_id; - __u8 rsvd1[3]; - __le32 tnev; - __le64 tll; - __u8 log_rev; - __u8 rsvd17; - __le16 head_len; - __le64 timestamp; - __u8 poh[16]; - __le64 pcc; - __le16 vid; - __le16 ssvid; - __u8 sn[20]; - __u8 mn[40]; - __u8 subnqn[256]; - __le16 gen_number; - __le32 rci; - __u8 rsvd378[102]; - __u8 supp_event_bm[32]; -} __attribute__((packed)); - -enum nvme_persistent_event_types { - NVME_SMART_HEALTH_EVENT = 0x01, - NVME_FW_COMMIT_EVENT = 0x02, - NVME_TIMESTAMP_EVENT = 0x03, - NVME_POWER_ON_RESET_EVENT = 0x04, - NVME_NSS_HW_ERROR_EVENT = 0x05, - NVME_CHANGE_NS_EVENT = 0x06, - NVME_FORMAT_START_EVENT = 0x07, - NVME_FORMAT_COMPLETION_EVENT = 0x08, - NVME_SANITIZE_START_EVENT = 0x09, - NVME_SANITIZE_COMPLETION_EVENT = 0x0a, - NVME_THERMAL_EXCURSION_EVENT = 0x0d -}; - -enum nvme_persistent_event_log_actions { - NVME_PEVENT_LOG_READ = 0x0, - NVME_PEVENT_LOG_EST_CTX_AND_READ = 0x1, - NVME_PEVENT_LOG_RELEASE_CTX = 0x2, -}; - -/** - * struct nvme_event_agg_log_page - is common for both - * predictable latency event aggregate log and endurance - * group event aggregate log - * @num_entries: indicates the number of entries in the list. - * @entries: indicates NVMSET ID or ENDURANCE Group ID entries - */ -struct nvme_event_agg_log_page { - __le64 num_entries; - __le16 entries[]; -}; - -struct nvme_predlat_per_nvmset_log_page { - __u8 status; - __u8 rsvd1; - __le16 event_type; - __u8 rsvd4[28]; - __le64 dtwin_rtyp; - __le64 dtwin_wtyp; - __le64 dtwin_timemax; - __le64 ndwin_timemin_high; - __le64 ndwin_timemin_low; - __u8 rsvd72[56]; - __le64 dtwin_restimate; - __le64 dtwin_westimate; - __le64 dtwin_testimate; - __u8 rsvd152[360]; -}; - -struct nvme_lba_status_range_desc { - __le64 rslba; - __le32 rnlb; - __u8 rsvd12[4]; -}; - -struct nvme_lba_status_ns_element { - __le32 neid; - __le32 nlrd; - __u8 ratype; - __u8 rsvd9[7]; -}; - -struct nvme_lba_status_hdr { - __le32 lslplen; - __le32 nlslne; - __le32 estulb; - __u8 rsvd12[2]; - __le16 lsgc; -}; - -struct nvme_resv_notif_log { - __le64 log_page_count; - __u8 resv_notif_log_type; - __u8 num_logs; - __u8 rsvd10[2]; - __le32 nsid; - __u8 rsvd16[48]; -}; - -struct nvme_boot_part_hdr { - __u8 lid; - __u8 rsvd1[3]; - __le32 bpinfo; - __u8 rsvd8[8]; -}; - -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, -}; - -struct nvme_lba_range_type { - __u8 type; - __u8 attributes; - __u8 rsvd2[14]; - __le64 slba; - __le64 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, -}; - -/* Predictable Latency Mode - Deterministic Threshold Configuration Data */ -struct nvme_plm_config { - __le16 enable_event; - __u8 rsvd2[30]; - __le64 dtwin_reads_thresh; - __le64 dtwin_writes_thresh; - __le64 dtwin_time_thresh; - __u8 rsvd56[456]; -}; - -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_verify = 0x0c, - nvme_cmd_resv_register = 0x0d, - nvme_cmd_resv_report = 0x0e, - nvme_cmd_resv_acquire = 0x11, - nvme_cmd_resv_release = 0x15, - nvme_cmd_copy = 0x19, - nvme_zns_cmd_mgmt_send = 0x79, - nvme_zns_cmd_mgmt_recv = 0x7a, - nvme_zns_cmd_append = 0x7d, -}; - -/* - * 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, -}; - -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_PIREMAP = 1 << 9, - 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, - NVME_RW_STORAGE_TAG_CHECK = 1 << 8, -}; - -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_copy_range { - __u8 rsvd0[8]; - __le64 slba; - __le16 nlb; - __u8 rsvd18[6]; - __le32 eilbrt; - __le16 elbatm; - __le16 elbat; -}; - -/* Features */ -struct nvme_feat_auto_pst { - __le64 entries[32]; -}; - -struct nvme_mi_host_metadata_element_desc { - __u8 type; /* Element Type */ - __u8 rev; /* Element Revision */ - __u16 len; /* Element Length */ - __u8 val[0]; /* Element Value (UTF-8) */ -}; - -struct nvme_mi_host_metadata { - __u8 ndesc; - __u8 rsvd1; - struct nvme_mi_host_metadata_element_desc descs[0]; -}; - -enum { - NVME_MI_CTRL_METADATA_OS_CTRL_NAME = 0x01, - NVME_MI_CTRL_METADATA_OS_DRIVER_NAME = 0x02, - NVME_MI_CTRL_METADATA_OS_DRIVER_VER = 0x03, - NVME_MI_CTRL_METADATA_PRE_BOOT_CTRL_NAME = 0x04, - NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_NAME = 0x05, - NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_VER = 0x06, - - NVME_MI_NS_METADATA_OS_NS_NAME = 0x01, - NVME_MI_NS_METADATA_PRE_BOOT_NS_NAME = 0x02, -}; - -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_dev_self_test = 0x14, - nvme_admin_ns_attach = 0x15, - nvme_admin_keep_alive = 0x18, - nvme_admin_directive_send = 0x19, - nvme_admin_directive_recv = 0x1a, - nvme_admin_virtual_mgmt = 0x1c, - nvme_admin_nvme_mi_send = 0x1d, - nvme_admin_nvme_mi_recv = 0x1e, - nvme_admin_capacity_mgmt = 0x20, - nvme_admin_lockdown_cmd = 0x24, - nvme_admin_dbbuf = 0x7C, - nvme_admin_format_nvm = 0x80, - nvme_admin_security_send = 0x81, - nvme_admin_security_recv = 0x82, - nvme_admin_sanitize_nvm = 0x84, - nvme_admin_get_lba_status = 0x86, -}; - -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_LOG_SUPPORTED_PAGES = 0x00, - NVME_LOG_ERROR = 0x01, - NVME_LOG_SMART = 0x02, - NVME_LOG_FW_SLOT = 0x03, - NVME_LOG_CHANGED_NS = 0x04, - NVME_LOG_CMD_EFFECTS = 0x05, - NVME_LOG_DEVICE_SELF_TEST = 0x06, - NVME_LOG_TELEMETRY_HOST = 0x07, - NVME_LOG_TELEMETRY_CTRL = 0x08, - NVME_LOG_ENDURANCE_GROUP = 0x09, - NVME_LOG_PRELAT_PER_NVMSET = 0x0a, - NVME_LOG_ANA = 0x0c, - NVME_LOG_PRELAT_EVENT_AGG = 0x0b, - NVME_LOG_PERSISTENT_EVENT = 0x0d, - NVME_LOG_LBA_STATUS = 0x0e, - NVME_LOG_ENDURANCE_GROUP_EVENT_AGG = 0x0f, - NVME_LOG_BOOT_PARTITION = 0x15, - NVME_LOG_FID_SUPPORT_EFFECTS = 0x12, - NVME_LOG_DISC = 0x70, - NVME_LOG_RESERVATION = 0x80, - NVME_LOG_SANITIZE = 0x81, - NVME_LOG_ZONE_CHANGED_LIST = 0xbf, - NVME_FWACT_REPL = (0 << 3), - NVME_FWACT_REPL_ACTV = (1 << 3), - NVME_FWACT_ACTV = (2 << 3), -}; - -enum nvme_feat { - NVME_FEAT_NONE = 0x0, - 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_HCTM = 0X10, - NVME_FEAT_NOPSC = 0X11, - NVME_FEAT_RRL = 0x12, - NVME_FEAT_PLM_CONFIG = 0x13, - NVME_FEAT_PLM_WINDOW = 0x14, - NVME_LBA_STATUS_INFO = 0x15, - NVME_FEAT_HOST_BEHAVIOR = 0x16, - NVME_FEAT_SANITIZE = 0x17, - NVME_FEAT_ENDURANCE = 0x18, - NVME_FEAT_IOCS_PROFILE = 0x19, - NVME_FEAT_SPINUP_CONTROL= 0x1a, - NVME_FEAT_SW_PROGRESS = 0x80, - NVME_FEAT_HOST_ID = 0x81, - NVME_FEAT_RESV_MASK = 0x82, - NVME_FEAT_RESV_PERSIST = 0x83, - NVME_FEAT_WRITE_PROTECT = 0x84, - - NVME_MI_FEAT_CTRL_METADATA = 0x7E, - NVME_MI_FEAT_NS_METADATA = 0x7F, - -} __attribute__ ((__packed__)); - -enum { - NVME_NO_LOG_LSP = 0x0, - NVME_NO_LOG_LPO = 0x0, - NVME_LOG_ANA_LSP_RGO = 0x1, - NVME_TELEM_LSP_CREATE = 0x1, -}; - -/* 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_NUM_CMPLTED_PASS_MASK = 0x00F8, - 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, - NVME_SANITIZE_LOG_ND_COMPLETED_SUCCESS = 0x0004, -}; - -#define NVME_IDENTIFY_DATA_SIZE 4096 - -struct nvme_host_mem_buf_desc { - __le64 addr; - __le32 size; - __u8 rsvd[4]; -}; - -/* 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; - __le32 est_ovrwrt_time_with_no_deallocate; - __le32 est_blk_erase_time_with_no_deallocate; - __le32 est_crypto_erase_time_with_no_deallocate; - __u8 rsvd32[480]; -}; - -/* - * 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, -}; - -/* - * 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]; - __le16 pkey; - __u8 resv10[246]; - } rdma; - struct tcp { - __u8 sectype; - } tcp; - } 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_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 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_effects_log_page { - __le32 acs[256]; - __le32 iocs[256]; - __u8 resv[2048]; -}; - -struct nvme_error_log_page { - __le64 error_count; - __le16 sqid; - __le16 cmdid; - __le16 status_field; - __le16 parm_error_location; - __le64 lba; - __le32 nsid; - __u8 vs; - __u8 trtype; - __u8 resv[2]; - __le64 cs; - __le16 trtype_spec_info; - __u8 resv2[22]; -}; - -struct nvme_firmware_log_page { - __u8 afi; - __u8 resv[7]; - __u8 frs[7][8]; - __u8 resv2[448]; -}; - -struct nvme_host_mem_buffer { - __le32 hsize; - __le32 hmdlal; - __le32 hmdlau; - __le32 hmdlec; - __u8 rsvd16[4080]; -}; - -struct nvme_auto_pst { - __le32 data; - __u8 rsvd[4]; -}; - -struct nvme_timestamp { - __u8 timestamp[6]; - __u8 attr; - __u8 rsvd; -}; - -struct nvme_controller_list { - __le16 num; - __le16 identifier[2047]; -}; - -struct nvme_primary_ctrl_caps { - __le16 cntlid; /* Controller Identifier */ - __le16 portid; /* Port Identifier */ - __u8 crt; /* Controller Resource Types */ - __u8 rsvd5[27]; - __le32 vqfrt; /* VQ Resources Flexible Total */ - __le32 vqrfa; /* VQ Resources Flexible Assigned */ - __le16 vqrfap; /* VQ Resources Flexible Allocated to Primary */ - __le16 vqprt; /* VQ Resources Private Total */ - __le16 vqfrsm; /* VQ Resources Flexible Secondary Maximum */ - __le16 vqgran; /* VQ Flexible Resource Preferred Granularity */ - __u8 rsvd48[16]; - __le32 vifrt; /* VI Resources Flexible Total */ - __le32 virfa; /* VI Resources Flexible Assigned */ - __le16 virfap; /* VI Resources Flexible Allocated to Primary */ - __le16 viprt; /* VI Resources Private Total */ - __le16 vifrsm; /* VI Resources Flexible Secondary Maximum */ - __le16 vigran; /* VI Flexible Resource Preferred Granularity */ - __u8 rsvd80[4016]; -}; - -struct nvme_secondary_controller_entry { - __le16 scid; /* Secondary Controller Identifier */ - __le16 pcid; /* Primary Controller Identifier */ - __u8 scs; /* Secondary Controller State */ - __u8 rsvd5[3]; - __le16 vfn; /* Virtual Function Number */ - __le16 nvq; /* Number of VQ Flexible Resources Assigned */ - __le16 nvi; /* Number of VI Flexible Resources Assigned */ - __u8 rsvd14[18]; -}; - -struct nvme_secondary_controllers_list { - __u8 num; - __u8 rsvd[31]; - struct nvme_secondary_controller_entry sc_entry[127]; -}; - -struct nvme_bar_cap { - __le16 mqes; - __u8 ams_cqr; - __u8 to; - __le16 bps_css_nssrs_dstrd; - __u8 mpsmax_mpsmin; - __u8 rsvd_cmbs_pmrs; -}; - -struct nvme_endurance_group_list { - __le16 num; - __le16 identifier[2047]; -}; - -/* - * is_64bit_reg - It checks whether given offset of the controller register is - * 64bit or not. - * @offset: offset of controller register field in bytes - * - * It gives true if given offset is 64bit register, otherwise it returns false. - * - * Notes: This function does not care about transport so that the offset is - * not going to be checked inside of this function for the unsupported fields - * in a specific transport. For example, BPMBL(Boot Partition Memory Buffer - * Location) register is not supported by fabrics, but it can be chcked here. - */ -static inline bool is_64bit_reg(__u32 offset) -{ - if (offset == NVME_REG_CAP || - offset == NVME_REG_ASQ || - offset == NVME_REG_ACQ || - offset == NVME_REG_BPMBL) - return true; - - return false; -} - -enum { - NVME_SCT_GENERIC = 0x0, - NVME_SCT_CMD_SPECIFIC = 0x1, - NVME_SCT_MEDIA = 0x2, - NVME_SCT_PATH = 0x3, -}; - -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_CMB_INVALID_USE = 0x12, - NVME_SC_PRP_INVALID_OFFSET = 0x13, - NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED= 0x14, - NVME_SC_OPERATION_DENIED = 0x15, - NVME_SC_SGL_INVALID_OFFSET = 0x16, - - NVME_SC_INCONSISTENT_HOST_ID= 0x18, - NVME_SC_KEEP_ALIVE_EXPIRED = 0x19, - NVME_SC_KEEP_ALIVE_INVALID = 0x1A, - NVME_SC_PREEMPT_ABORT = 0x1B, - NVME_SC_SANITIZE_FAILED = 0x1C, - NVME_SC_SANITIZE_IN_PROGRESS = 0x1D, - NVME_SC_SGL_DATA_BLK_GRAN_INVALID= 0x1e, - NVME_SC_CMD_NOT_SUP_QUEUE_IN_CMB = 0x1f, - - NVME_SC_NS_WRITE_PROTECTED = 0x20, - NVME_SC_CMD_INTERRUPTED = 0x21, - NVME_SC_TRANSIENT_TRANSPORT = 0x22, - NVME_SC_PROHIBITED_BY_CMD_AND_FEAT = 0x23, - NVME_SC_ADMIN_CMD_MEDIA_NOT_READY = 0x24, - - NVME_SC_LBA_RANGE = 0x80, - NVME_SC_CAP_EXCEEDED = 0x81, - NVME_SC_NS_NOT_READY = 0x82, - NVME_SC_RESERVATION_CONFLICT = 0x83, - NVME_SC_FORMAT_IN_PROGRESS = 0x84, - - /* - * 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_ACTIVATE_PROHIBITED = 0x113, - NVME_SC_OVERLAPPING_RANGE = 0x114, - NVME_SC_NS_INSUFFICIENT_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_DEVICE_SELF_TEST_IN_PROGRESS= 0x11d, - NVME_SC_BP_WRITE_PROHIBITED = 0x11e, - NVME_SC_INVALID_CTRL_ID = 0x11f, - NVME_SC_INVALID_SECONDARY_CTRL_STATE= 0x120, - NVME_SC_INVALID_NUM_CTRL_RESOURCE = 0x121, - NVME_SC_INVALID_RESOURCE_ID = 0x122, - NVME_SC_PMR_SAN_PROHIBITED = 0x123, - NVME_SC_ANA_INVALID_GROUP_ID= 0x124, - NVME_SC_ANA_ATTACH_FAIL = 0x125, - NVME_SC_INSUFFICIENT_CAP = 0x126, - NVME_SC_NS_ATTACHMENT_LIMIT_EXCEEDED = 0x127, - NVME_SC_PROHIBIT_CMD_EXEC_NOT_SUPPORTED = 0x128, - - /* - * Command Set Specific - Namespace Types commands: - */ - NVME_SC_IOCS_NOT_SUPPORTED = 0x129, - NVME_SC_IOCS_NOT_ENABLED = 0x12A, - NVME_SC_IOCS_COMBINATION_REJECTED = 0x12B, - NVME_SC_INVALID_IOCS = 0x12C, - NVME_SC_ID_UNAVAILABLE = 0x12D, - - /* - * I/O Command Set Specific - NVM commands: - */ - NVME_SC_BAD_ATTRIBUTES = 0x180, - NVME_SC_INVALID_PI = 0x181, - NVME_SC_READ_ONLY = 0x182, - NVME_SC_CMD_SIZE_LIMIT_EXCEEDED = 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, - - /* - * I/O Command Set Specific - Zoned Namespace commands: - */ - NVME_SC_ZONE_BOUNDARY_ERROR = 0x1B8, - NVME_SC_ZONE_IS_FULL = 0x1B9, - NVME_SC_ZONE_IS_READ_ONLY = 0x1BA, - NVME_SC_ZONE_IS_OFFLINE = 0x1BB, - NVME_SC_ZONE_INVALID_WRITE = 0x1BC, - NVME_SC_TOO_MANY_ACTIVE_ZONES = 0x1BD, - NVME_SC_TOO_MANY_OPEN_ZONES = 0x1BE, - NVME_SC_ZONE_INVALID_STATE_TRANSITION = 0x1BF, - - /* - * 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_STORAGE_TAG_CHECK = 0x288, - - /* - * Path-related Errors: - */ - NVME_SC_INTERNAL_PATH_ERROR = 0x300, - NVME_SC_ANA_PERSISTENT_LOSS = 0x301, - NVME_SC_ANA_INACCESSIBLE = 0x302, - NVME_SC_ANA_TRANSITION = 0x303, - - /* - * Controller Detected Path errors - */ - NVME_SC_CTRL_PATHING_ERROR = 0x360, - - /* - * Host Detected Path Errors - */ - NVME_SC_HOST_PATHING_ERROR = 0x370, - NVME_SC_HOST_CMD_ABORT = 0x371, - - NVME_SC_CRD = 0x1800, - NVME_SC_DNR = 0x4000, -}; - -#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) - - -/** - * struct nvme_zns_lbafe - - * zsze: - * zdes: - */ -struct nvme_zns_lbafe { - __le64 zsze; - __u8 zdes; - __u8 rsvd9[7]; -}; - -/** - * struct nvme_zns_id_ns - Zoned Namespace Command Set Specific - * Identify Namespace Data Structure - * @zoc: Zone Operation Characteristics - * @ozcs: Optional Zoned Command Support - * @mar: Maximum Active Resources - * @mor: Maximum Open Resources - * @rrl: Reset Recommended Limit - * @frl: Finish Recommended Limit - * @lbafe: LBA Format Extension - * @vs: Vendor Specific - */ -struct nvme_zns_id_ns { - __le16 zoc; - __le16 ozcs; - __le32 mar; - __le32 mor; - __le32 rrl; - __le32 frl; - __le32 rrl1; - __le32 rrl2; - __le32 rrl3; - __le32 frl1; - __le32 frl2; - __le32 frl3; - __u8 rsvd44[2772]; - struct nvme_zns_lbafe lbafe[64]; - __u8 vs[256]; -}; - -struct nvme_id_ctrl_nvm { - __u8 vsl; - __u8 wzsl; - __u8 wusl; - __u8 dmrl; - __le32 dmrsl; - __le64 dmsl; - __u8 rsvd16[4080]; -}; - -/** - * struct nvme_zns_id_ctrl - - * @zasl: - */ -struct nvme_zns_id_ctrl { - __u8 zasl; - __u8 rsvd1[4095]; -}; - -#define NVME_ZNS_CHANGED_ZONES_MAX 511 - -/** - * struct nvme_zns_changed_zone_log - ZNS Changed Zone List log - * @nrzid: - * @zid: - */ -struct nvme_zns_changed_zone_log { - __le16 nrzid; - __u8 rsvd2[6]; - __le64 zid[NVME_ZNS_CHANGED_ZONES_MAX]; -}; - -/** - * enum nvme_zns_zt - - */ -enum nvme_zns_zt { - NVME_ZONE_TYPE_SEQWRITE_REQ = 0x2, -}; - -/** - * enum nvme_zns_za - - */ -enum nvme_zns_za { - NVME_ZNS_ZA_ZFC = 1 << 0, - NVME_ZNS_ZA_FZR = 1 << 1, - NVME_ZNS_ZA_RZR = 1 << 2, - NVME_ZNS_ZA_ZDEV = 1 << 7, -}; - -/** - * enum nvme_zns_zs - - */ -enum nvme_zns_zs { - NVME_ZNS_ZS_EMPTY = 0x1, - NVME_ZNS_ZS_IMPL_OPEN = 0x2, - NVME_ZNS_ZS_EXPL_OPEN = 0x3, - NVME_ZNS_ZS_CLOSED = 0x4, - NVME_ZNS_ZS_READ_ONLY = 0xd, - NVME_ZNS_ZS_FULL = 0xe, - NVME_ZNS_ZS_OFFLINE = 0xf, -}; - -/** - * struct nvme_zns_desc - - */ -struct nvme_zns_desc { - __u8 zt; - __u8 zs; - __u8 za; - __u8 zai; - __u8 rsvd4[4]; - __le64 zcap; - __le64 zslba; - __le64 wp; - __u8 rsvd32[32]; -}; - -/** - * struct nvme_zone_report - - */ -struct nvme_zone_report { - __le64 nr_zones; - __u8 resv8[56]; - struct nvme_zns_desc entries[]; -}; - -enum nvme_zns_send_action { - NVME_ZNS_ZSA_CLOSE = 0x1, - NVME_ZNS_ZSA_FINISH = 0x2, - NVME_ZNS_ZSA_OPEN = 0x3, - NVME_ZNS_ZSA_RESET = 0x4, - NVME_ZNS_ZSA_OFFLINE = 0x5, - NVME_ZNS_ZSA_SET_DESC_EXT = 0x10, -}; - -enum nvme_zns_recv_action { - NVME_ZNS_ZRA_REPORT_ZONES = 0x0, - NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES = 0x1, -}; - -enum nvme_zns_report_options { - NVME_ZNS_ZRAS_REPORT_ALL = 0x0, - NVME_ZNS_ZRAS_REPORT_EMPTY = 0x1, - NVME_ZNS_ZRAS_REPORT_IMPL_OPENED = 0x2, - NVME_ZNS_ZRAS_REPORT_EXPL_OPENED = 0x3, - NVME_ZNS_ZRAS_REPORT_CLOSED = 0x4, - NVME_ZNS_ZRAS_REPORT_FULL = 0x5, - NVME_ZNS_ZRAS_REPORT_READ_ONLY = 0x6, - NVME_ZNS_ZRAS_REPORT_OFFLINE = 0x7, -}; - -struct nvme_id_domain_attr_entry { - __le16 dom_id; - __u8 rsvd2[14]; - __u8 dom_cap[16]; - __u8 unalloc_dom_cap[16]; - __u8 max_egrp_dom_cap[16]; - __u8 rsvd64[64]; -}; - -struct nvme_id_domain_list { - __u8 num_entries; - __u8 rsvd1[127]; - struct nvme_id_domain_attr_entry domain_attr[]; -}; - -enum { - NVME_FID_EFFECTS_FSUPP = 1 << 0, - NVME_FID_EFFECTS_UDCC = 1 << 1, - NVME_FID_EFFECTS_NCC = 1 << 2, - NVME_FID_EFFECTS_NIC = 1 << 3, - NVME_FID_EFFECTS_CCC = 1 << 4, - NVME_FID_EFFECTS_UUID_SEL = 1 << 19, - NVME_FID_SCOPE_SHIFT = 20, - NVME_FID_SCOPE_MASK = 0xfff, - NVME_FID_SCOPE_NS = 1 << 0, - NVME_FID_SCOPE_CTRL = 1 << 1, - NVME_FID_SCOPE_NVM_SET = 1 << 2, - NVME_FID_SCOPE_ENDGRP = 1 << 3, - NVME_FID_SCOPE_DOMAIN = 1 << 4, - NVME_FID_SCOPE_NSS = 1 << 5, -}; - -struct nvme_fid_support_effects { - __le32 fid_support[256]; -}; - -struct nvme_support_log_pages { - __le32 lid_support[256]; -}; - -#endif /* _LINUX_NVME_H */ diff --git a/linux/nvme_ioctl.h b/linux/nvme_ioctl.h deleted file mode 100644 index b4fd4e2..0000000 --- a/linux/nvme_ioctl.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 <linux/types.h> -#include <sys/ioctl.h> - -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; -}; - -struct nvme_passthru_cmd64 { - __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 rsvd2; - __u64 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_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) -#define NVME_IOCTL_ADMIN64_CMD _IOWR('N', 0x47, struct nvme_passthru_cmd64) -#define NVME_IOCTL_IO64_CMD _IOWR('N', 0x48, struct nvme_passthru_cmd64) - -#endif /* _UAPI_LINUX_NVME_IOCTL_H */ diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..6a7678d --- /dev/null +++ b/meson.build @@ -0,0 +1,276 @@ +################################################################################ +project( + 'nvme-cli', ['c', 'cpp'], + meson_version: '>= 0.47.0', + license: 'LGPLv2+', + version: '2.0', + default_options: [ + 'c_std=gnu99', + 'buildtype=release', + 'prefix=/usr', + 'warning_level=1', + ] +) + +################################################################################ +cc = meson.get_compiler('c') + +prefixdir = get_option('prefix') +datadir = join_paths(prefixdir, get_option('datadir')) +mandir = join_paths(prefixdir, get_option('mandir')) +sbindir = join_paths(prefixdir, get_option('sbindir')) +sysconfdir = join_paths(prefixdir, get_option('sysconfdir')) + +udevrulesdir = join_paths(prefixdir, get_option('udevrulesdir')) +dracutrulesdir = join_paths(prefixdir, get_option('dracutrulesdir')) +systemddir = join_paths(prefixdir, get_option('systemddir')) + +############################################################################### +conf = configuration_data() +requires = '' + +conf.set('SYSCONFDIR', '"@0@"'.format(sysconfdir)) + +libnvme_dep = dependency('libnvme', fallback : ['libnvme', 'libnvme_dep']) + +# Check for libuuid availability +libuuid_dep = dependency('uuid', required: true) +conf.set('CONFIG_LIBUUID', libuuid_dep.found(), description: 'Is libuuid available?') + +# Check for libjson-c availability +json_c_dep = dependency('json-c', version: '>=0.13', fallback : ['json-c', 'json_c_dep']) +if json_c_dep.found() + conf.set('CONFIG_JSONC', true, description: 'Is json-c available?') + if json_c_dep.version().version_compare('>=0.14') + conf.set('CONFIG_JSONC_14', true, description: 'Is json-c at least 0.14?') + requires = 'Requires: json-c >= 0.14' + else + requires = 'Requires: json-c >= 0.13' + endif +endif + +# Check for libhugetlbfs availability +if cc.has_header('hugetlbfs.h') + libhugetlbfs_dep = cc.find_library('hugetlbfs', + required : false) + have_libhugetlbfs = libhugetlbfs_dep.found() +else + libhugetlbfs_dep = [] + have_libhugetlbfs = false +endif +conf.set('CONFIG_LIBHUGETLBFS', have_libhugetlbfs, description: 'Is libhugetlbfs available?') + +# Check for zlib availability +libz_dep = dependency('zlib', fallback : ['zlib', 'zlib_dep']) + +# Set the nvme-cli version +conf.set('NVME_VERSION', '"' + meson.project_version() + '"') + +# local (cross-compilable) implementations of ccan configure steps +conf.set10( + 'HAVE_BUILTIN_TYPES_COMPATIBLE_P', + cc.compiles( + '''int main(void) { + return __builtin_types_compatible_p(int, long); + } + ''', + name: '__builtin_type_compatible_p' + ), + description: 'Is __builtin_types_compatible_p available?' +) +conf.set10( + 'HAVE_TYPEOF', + cc.compiles( + '''int main(void) { + int a = 1; + typeof(a) b; + b = a; + } + ''', + name: 'typeof' + ), + description: 'Is typeof available?' +) +conf.set10( + 'HAVE_BYTESWAP_H', + cc.compiles( + '''#include <byteswap.h>''', + name: 'byteswap.h' + ), + description: 'Is byteswap.h include-able?' +) +conf.set10( + 'HAVE_BSWAP_64', + cc.links( + '''#include <byteswap.h> + int main(void) { + return bswap_64(0); + } + ''', + name: 'bswap64' + ), + description: 'Is bswap_64 available?' +) +conf.set10( + 'HAVE_LITTLE_ENDIAN', + build_machine.endian() == 'little', + description: 'Building for little-endian' +) +conf.set10( + 'HAVE_BIG_ENDIAN', + build_machine.endian() == 'big', + description: 'Building for big-endian' +) +conf.set10( + 'HAVE_ISBLANK', + cc.links( + '''#include <ctype.h> + int main(int argc, char **argv) { + return isblank(argv[0][0]); + } + ''', + name: 'isblank' + ), + description: 'Is isblank() available?' +) +conf.set10( + 'HAVE_SYS_RANDOM', + cc.compiles( + '''#include <sys/random.h>''', + name: 'sys/random.h' + ), + description: 'Is sys/random.h(getrandom) include-able?' +) + +configure_file( + output: 'config.h', + configuration: conf +) + +################################################################################ +libtype = get_option('default_library') +if libtype == 'static' + requires = '' +endif + +substs = configuration_data() +substs.set('NAME', meson.project_name()) +substs.set('VERSION', meson.project_version()) +substs.set('LICENSE', meson.project_license()[0]) +substs.set('UDEVRULESDIR', udevrulesdir) +substs.set('DRACUTRILESDIR', dracutrulesdir) +substs.set('REQUIRES', requires) +substs.set('DATADIR', datadir) +substs.set('MANDIR', mandir) +substs.set('SBINDIR', sbindir) +substs.set('SYSCONFDIR', sysconfdir) +substs.set('SYSTEMDDIR', systemddir) +substs.set('SYSTEMCTL', get_option('systemctl')) + +configure_file( + input: 'nvme.spec.in', + output: 'nvme.spec', + configuration: substs, +) + +disc = configure_file( + input: 'etc/discovery.conf.in', + output: 'discovery.conf', + configuration: substs, +) + +dracut_files = [ + '70-nvmf-autoconnect.conf', +] + +foreach file : dracut_files + configure_file( + input: 'nvmf-autoconnect/dracut-conf/' + file + '.in', + output: file, + configuration: substs, + ) +endforeach + +systemd_files = [ + 'nvmefc-boot-connections.service', + 'nvmf-autoconnect.service', + 'nvmf-connect.target', + 'nvmf-connect@.service', +] + +foreach file : systemd_files + configure_file( + input: 'nvmf-autoconnect/systemd/' + file + '.in', + output: file, + configuration: substs, + ) +endforeach + +udev_files = [ + '70-nvmf-autoconnect.rules', + '71-nvmf-iopolicy-netapp.rules', +] + +foreach file : udev_files + configure_file( + input: 'nvmf-autoconnect/udev-rules/' + file + '.in', + output: file, + configuration: substs, + ) +endforeach + +################################################################################ +add_project_arguments(['-fomit-frame-pointer', '-D_GNU_SOURCE', + '-include', 'config.h'], language : 'c') +incdir = include_directories(['ccan']) + +################################################################################ +sources = [ + 'fabrics.c', + 'nvme.c', + 'nvme-models.c', + 'nvme-print.c', + 'nvme-rpmb.c', + 'plugin.c', +] + +subdir('ccan') +subdir('plugins') +subdir('tests') +subdir('util') +subdir('Documentation') + +executable( + 'nvme', + sources, + dependencies: [ libnvme_dep, libuuid_dep, json_c_dep, libz_dep, + libhugetlbfs_dep ], + include_directories: incdir, + install: true, + install_dir: sbindir +) + +################################################################################ +install_data('completions/bash-nvme-completion.sh', + rename: 'nvme', + install_dir: datadir + '/bash-completion/completions') +install_data('completions/_nvme', + install_dir: datadir + '/zsh/site-functions') + +foreach file : dracut_files + install_data(meson.current_build_dir() + '/' + file, + install_dir: dracutrulesdir) +endforeach + +foreach file : systemd_files + install_data(meson.current_build_dir() + '/' + file, + install_dir: systemddir) +endforeach + +foreach file : udev_files + install_data(meson.current_build_dir() + '/' + file, + install_dir: udevrulesdir) +endforeach + +install_data(disc, + install_dir: join_paths(sysconfdir, 'nvme')) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..224faae --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,8 @@ +option('udevrulesdir', type : 'string', value : 'etc/udev/rules.d', description : 'directory for udev rules files') +option('dracutrulesdir', type : 'string', value : 'lib/dracut/dracut.conf.d/', description : 'directory for dracut rules files') +option('systemddir', type : 'string', value : 'lib/systemd/', description : 'directory for systemd files') +option('htmldir', type : 'string', value : '', description : 'directory for HTML documentation') +option('systemctl', type : 'string', value : '/usr/bin/systemctl', description : 'path to systemctl binary') + +option('docs', type : 'combo', choices : ['false', 'html', 'man', 'all'], description : 'install documentation') +option('docs-build', type : 'boolean', value : false, description : 'build documentation') diff --git a/nvme-builtin.h b/nvme-builtin.h index fe00f44..fec97fd 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -12,9 +12,12 @@ COMMAND_LIST( ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl) ENTRY("id-ns", "Send NVMe Identify Namespace, display structure", id_ns) ENTRY("id-ns-granularity", "Send NVMe Identify Namespace Granularity List, display structure", id_ns_granularity) + ENTRY("id-ns-lba-format", "Send NVMe Identify Namespace for the specified LBA Format index, display structure", id_ns_lba_format) ENTRY("list-ns", "Send NVMe Identify List, display structure", list_ns) ENTRY("list-ctrl", "Send NVMe Identify Controller List, display structure", list_ctrl) ENTRY("nvm-id-ctrl", "Send NVMe Identify Controller NVM Command Set, display structure", nvm_id_ctrl) + ENTRY("nvm-id-ns", "Send NVMe Identify Namespace NVM Command Set, display structure", nvm_id_ns) + ENTRY("nvm-id-ns-lba-format", "Send NVMe Identify Namespace NVM Command Set for the specified LBA Format index, display structure", nvm_id_ns_lba_format) ENTRY("primary-ctrl-caps", "Send NVMe Identify Primary Controller Capabilities", primary_ctrl_caps) ENTRY("list-secondary", "List Secondary Controllers associated with a Primary Controller", list_secondary_ctrl) ENTRY("cmdset-ind-id-ns", "I/O Command Set Independent Identify Namespace", cmd_set_independent_id_ns) @@ -49,6 +52,10 @@ COMMAND_LIST( ENTRY("device-self-test", "Perform the necessary tests to observe the performance", device_self_test) ENTRY("self-test-log", "Retrieve the SELF-TEST Log, show it", self_test_log) ENTRY("supported-log-pages", "Retrieve the Supported Log pages details, show it", get_supported_log_pages) + ENTRY("fid-support-effects-log", "Retrieve FID Support and Effects log and show it", get_fid_support_effects_log) + ENTRY("mi-cmd-support-effects-log", "Retrieve MI Command Support and Effects log and show it", get_mi_cmd_support_effects_log) + ENTRY("media-unit-stat-log", "Retrieve the configuration and wear of media units, show it", get_media_unit_stat_log) + ENTRY("supported-cap-config-log", "Retrieve the list of Supported Capacity Configuration Descriptors", get_supp_cap_config_log) 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("get-property", "Get a property and show the resulting value", get_property) @@ -85,14 +92,19 @@ COMMAND_LIST( ENTRY("connect", "Connect to NVMeoF subsystem", connect_cmd) ENTRY("disconnect", "Disconnect from NVMeoF subsystem", disconnect_cmd) ENTRY("disconnect-all", "Disconnect from all connected NVMeoF subsystems", disconnect_all_cmd) + ENTRY("config", "Configuration of NVMeoF subsystems", config_cmd) ENTRY("gen-hostnqn", "Generate NVMeoF host NQN", gen_hostnqn_cmd) ENTRY("show-hostnqn", "Show NVMeoF host NQN", show_hostnqn_cmd) + ENTRY("gen-dhchap-key", "Generate NVMeoF DH-HMAC-CHAP host key", gen_dhchap_key) + ENTRY("check-dhchap-key", "Validate NVMeoF DH-HMAC-CHAP host key", check_dhchap_key) + ENTRY("gen-tls-key", "Generate NVMeoF TLS PSK", gen_tls_key) + ENTRY("check-tls-key", "Validate NVMeoF TLS PSK", check_tls_key) ENTRY("dir-receive", "Submit a Directive Receive command, return results", dir_receive) ENTRY("dir-send", "Submit a Directive Send command, return results", dir_send) ENTRY("virt-mgmt", "Manage Flexible Resources between Primary and Secondary Controller ", virtual_mgmt) ENTRY("rpmb", "Replay Protection Memory Block commands", rpmb_cmd) - ENTRY("fid-support-effects-log", "Submit Feature ID Support and Effects Log, Return result", get_fid_support_effects_log) ENTRY("lockdown", "Submit a Lockdown command,return result", lockdown_cmd) + ENTRY("dim", "Send Discovery Information Management command to a Discovery Controller", dim_cmd) ); #endif diff --git a/nvme-filters.c b/nvme-filters.c deleted file mode 100644 index 17c375f..0000000 --- a/nvme-filters.c +++ /dev/null @@ -1,104 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#include "nvme.h" - -/* global, used for controller specific namespace filter */ -int current_index; - -int scan_ctrl_namespace_filter(const struct dirent *d) -{ - int c, i, n; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) { - if (sscanf(d->d_name, "nvme%dc%dn%d", &i, &c, &n) == 3) - return 1; - if (sscanf(d->d_name, "nvme%dn%d", &i, &n) == 2) - return 1; - } - return 0; -} - -int scan_namespace_filter(const struct dirent *d) -{ - int i, n; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) - if (sscanf(d->d_name, "nvme%dn%d", &i, &n) == 2) - return 1; - return 0; -} - -int scan_ctrl_paths_filter(const struct dirent *d) -{ - int id, cntlid, nsid; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) { - if (sscanf(d->d_name, "nvme%dc%dn%d", &id, &cntlid, &nsid) == 3) - return 1; - if (sscanf(d->d_name, "nvme%dn%d", &id, &nsid) == 2) - return 1; - } - - return 0; -} - -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; - if (sscanf(d->d_name, "nvme%dn", &id) == 1) - return 1; - return 0; - } - - return 0; -} - -int scan_subsys_filter(const struct dirent *d) -{ - int id; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme-subsys")) { - if (sscanf(d->d_name, "nvme-subsys%d", &id) != 1) - return 0; - return 1; - } - - return 0; -} - -int scan_dev_filter(const struct dirent *d) -{ - int ctrl, ns, part; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) { - if (sscanf(d->d_name, "nvme%dn%dp%d", &ctrl, &ns, &part) == 3) - return 0; - if (sscanf(d->d_name, "nvme%dn%d", &ctrl, &ns) == 2) - return ctrl == current_index; - } - return 0; -} diff --git a/nvme-ioctl.c b/nvme-ioctl.c deleted file mode 100644 index 5a57a25..0000000 --- a/nvme-ioctl.c +++ /dev/null @@ -1,1157 +0,0 @@ -#include <assert.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <errno.h> - -#include <getopt.h> -#include <fcntl.h> -#include <inttypes.h> -#include <locale.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <math.h> - -#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; - - return ioctl(fd, NVME_IOCTL_ID); -} - -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, - struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, ioctl_cmd, cmd); -} - -int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, NVME_IOCTL_ADMIN_CMD, cmd); -} - -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, unsigned long 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, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, - __u16 appmask, __u64 storage_tag, void *data, __u32 buffer_size, - void *metadata, __u32 mbuffer_size) -{ - struct nvme_passthru_cmd cmd = { - .opcode = opcode, - .nsid = nsid, - .metadata = (__u64)(uintptr_t) metadata, - .addr = (__u64)(uintptr_t) data, - .cdw2 = storage_tag & 0xffffffff, - .cdw3 = (storage_tag >> 32) & 0xffff, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nblocks | (control << 16), - .cdw13 = dsmgmt, - .cdw14 = reftag, - .cdw15 = apptag | (appmask << 16), - .data_len = buffer_size, - .metadata_len = mbuffer_size, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask, - __u64 storage_tag) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_verify, - .nsid = nsid, - .cdw2 = storage_tag & 0xffffffff, - .cdw3 = (storage_tag >> 32) & 0xffff, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nblocks | (control << 16), - .cdw14 = reftag, - .cdw15 = apptag | (appmask << 16), - }; - - return nvme_submit_io_passthru(fd, &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_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, - __u64 storage_tag) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_write_zeroes, - .nsid = nsid, - .cdw2 = storage_tag & 0xffffffff, - .cdw3 = (storage_tag >> 32) & 0xffff, - .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(int *ctx_attrs, int *llbas, - unsigned long long *slbas, - __u16 nr_ranges) -{ - int i; - struct nvme_dsm_range *dsm = malloc(nr_ranges * sizeof(*dsm)); - - if (!dsm) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - 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_copy(int fd, __u32 nsid, struct nvme_copy_range *copy, __u64 sdlba, - __u16 nr, __u8 prinfor, __u8 prinfow, __u8 dtype, __u16 dspec, - __u8 format, int lr, int fua, __u32 ilbrt, __u16 lbatm, - __u16 lbat) -{ - __u32 cdw12 = ((nr - 1) & 0xff) | ((format & 0xf) << 8) | - ((prinfor & 0xf) << 12) | ((dtype & 0xf) << 20) | - ((prinfow & 0xf) << 26) | ((fua & 0x1) << 30) | - ((lr & 0x1) << 31); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_copy, - .nsid = nsid, - .addr = (__u64)(uintptr_t)copy, - .data_len = nr * sizeof(*copy), - .cdw10 = sdlba & 0xffffffff, - .cdw11 = sdlba >> 32, - .cdw12 = cdw12, - .cdw13 = (dspec & 0xffff) << 16, - .cdw14 = ilbrt, - .cdw15 = (lbatm << 16) | lbat, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -struct nvme_copy_range *nvme_setup_copy_range(int *nlbs, unsigned long long *slbas, - int *eilbrts, int *elbatms, int *elbats, __u16 nr) -{ - struct nvme_copy_range *copy = malloc(nr * sizeof(*copy)); - if (!copy) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return NULL; - } - - for (int i = 0; i < nr; i++) { - copy[i].nlb = cpu_to_le16(nlbs[i]); - copy[i].slba = cpu_to_le64(slbas[i]); - copy[i].eilbrt = cpu_to_le32(eilbrts[i]); - copy[i].elbatm = cpu_to_le16(elbatms[i]); - copy[i].elbat = cpu_to_le16(elbats[i]); - } - - return copy; -} - -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 & 0x7) | (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 & 0x7) | (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 & 0x7) | (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 + 1) << 2, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_identify13(int fd, __u32 nsid, __u32 cdw10, __u32 cdw11, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_identify, - .nsid = nsid, - .addr = (__u64)(uintptr_t) data, - .data_len = NVME_IDENTIFY_DATA_SIZE, - .cdw10 = cdw10, - .cdw11 = cdw11, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data) -{ - return nvme_identify13(fd, nsid, cdw10, 0, data); -} - -int nvme_identify_ctrl(int fd, void *data) -{ - memset(data, 0, sizeof(struct nvme_id_ctrl)); - 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_csi(int fd, __u32 nsid, __u8 csi, bool all, void *data) -{ - int cns; - - if (csi) { - cns = all ? NVME_ID_CNS_CSI_NS_PRESENT_LIST : NVME_ID_CNS_CSI_NS_ACTIVE_LIST; - } else { - cns = all ? NVME_ID_CNS_NS_PRESENT_LIST : NVME_ID_CNS_NS_ACTIVE_LIST; - } - - return nvme_identify13(fd, nsid, cns, csi << 24, data); -} - -int nvme_cmd_set_independent_identify_ns(int fd, __u32 nsid, void *data) -{ - return nvme_identify(fd, nsid, NVME_ID_CNS_CS_INDEPENDENT_ID_NS, 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_primary_ctrl_caps(int fd, void *data) -{ - return nvme_identify(fd, 0, NVME_ID_CNS_PRIMARY_CTRL_CAPS, data); -} - -int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data) -{ - return nvme_identify(fd, nsid, (cntid << 16) | NVME_ID_CNS_SCNDRY_CTRL_LIST, 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_identify_nvmset(int fd, __u16 nvmset_id, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_NVMSET_LIST, nvmset_id, data); -} - -int nvme_identify_ns_granularity(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_NS_GRANULARITY, 0, data); -} - -int nvme_identify_uuid(int fd, void *data) -{ - return nvme_identify(fd, 0, NVME_ID_CNS_UUID_LIST, data); -} - -int nvme_identify_ctrl_nvm(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 0, data); -} - -int nvme_zns_identify_ns(int fd, __u32 nsid, void *data) -{ - return nvme_identify13(fd, nsid, NVME_ID_CNS_CSI_ID_NS, 2 << 24, data); -} - -int nvme_zns_identify_ctrl(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 2 << 24, data); -} - -int nvme_identify_iocs(int fd, __u16 cntid, void *data) -{ - return nvme_identify(fd, 0, (cntid << 16) | NVME_ID_CNS_CSI, data); -} - -int nvme_identify_domain_list(int fd, __u16 dom_id, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_DOMAIN_LIST, dom_id, data); -} - -int nvme_identify_endurance_group_list(int fd, __u16 endgrp_id, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_ENDURANCE_GROUP_ID, endgrp_id, data); -} - -int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, - __u16 lsi, bool rae, __u8 uuid_ix, __u8 csi, bool ot, - __u32 data_len, void *data) -{ - __u32 numd = (data_len >> 2) - 1; - __u16 numdu = numd >> 16, numdl = numd & 0xffff; - __u32 cdw10 = log_id | (numdl << 16) | (rae ? 1 << 15 : 0) | lsp << 8; - __u32 cdw14 = uuid_ix | (ot ? 1 << 23 : 0) | csi << 24; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_get_log_page, - .nsid = nsid, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .cdw10 = cdw10, - .cdw11 = numdu | (lsi << 16), - .cdw12 = lpo & 0xffffffff, - .cdw13 = lpo >> 32, - .cdw14 = cdw14, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, - __u64 lpo, __u16 lsi, bool rae, __u32 data_len, - void *data) -{ - return nvme_get_log14(fd, nsid, log_id, lsp, lpo, lsi, rae, 0, - 0, false, data_len, data); -} - -int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae, - __u8 lsp, __u32 data_len, void *data) -{ - __u32 offset = 0, xfer_len = data_len; - void *ptr = data; - int ret; - - /* - * 4k is the smallest possible transfer unit, so by - * restricting ourselves for 4k transfers we avoid having - * to check the MDTS value of the controller. - */ - do { - xfer_len = data_len - offset; - if (xfer_len > 4096) - xfer_len = 4096; - - ret = nvme_get_log13(fd, nsid, log_id, lsp, - offset, 0, rae, xfer_len, ptr); - if (ret) - return ret; - - offset += xfer_len; - ptr += xfer_len; - } while (offset < data_len); - - return 0; -} - -int nvme_get_telemetry_log(int fd, void *lp, int generate_report, - int ctrl_init, size_t log_page_size, __u64 offset) -{ - if (ctrl_init) - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_CTRL, - NVME_NO_LOG_LSP, offset, - 0, 1, log_page_size, lp); - if (generate_report) - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, - NVME_TELEM_LSP_CREATE, offset, - 0, 1, log_page_size, lp); - else - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, - NVME_NO_LOG_LSP, offset, - 0, 1, log_page_size, lp); -} - -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, true, - NVME_NO_LOG_LSP, sizeof(*fw_log), fw_log); -} - -int nvme_changed_ns_list_log(int fd, struct nvme_changed_ns_list_log *changed_ns_list_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_CHANGED_NS, true, - NVME_NO_LOG_LSP, sizeof(changed_ns_list_log->log), - changed_ns_list_log->log); -} - -int nvme_error_log(int fd, int entries, struct nvme_error_log_page *err_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_ERROR, false, - NVME_NO_LOG_LSP, entries * sizeof(*err_log), err_log); -} - -int nvme_endurance_log(int fd, __u16 group_id, struct nvme_endurance_group_log *endurance_log) -{ - return nvme_get_log13(fd, 0, NVME_LOG_ENDURANCE_GROUP, 0, 0, group_id, 0, - sizeof(*endurance_log), endurance_log); -} - -int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log) -{ - return nvme_get_log(fd, nsid, NVME_LOG_SMART, false, - NVME_NO_LOG_LSP, sizeof(*smart_log), smart_log); -} - -int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo) -{ - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_ANA, rgo, 0, 0, - true, ana_log_len, ana_log); -} - -int nvme_self_test_log(int fd, __u32 size, struct nvme_self_test_log *self_test_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_DEVICE_SELF_TEST, false, - NVME_NO_LOG_LSP, size, self_test_log); -} - -int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, false, - NVME_NO_LOG_LSP, sizeof(*effects_log), effects_log); -} - -int nvme_supported_log(int fd, struct nvme_support_log_pages *supports) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_SUPPORTED_PAGES, false, - NVME_NO_LOG_LSP, sizeof(*supports), supports); -} - -int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size) -{ - return nvme_get_log(fd, 0, NVME_LOG_DISC, false, NVME_NO_LOG_LSP, size, log); -} - -int nvme_sanitize_log(int fd, bool rae, struct nvme_sanitize_log_page *sanitize_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, rae, - NVME_NO_LOG_LSP, sizeof(*sanitize_log), sanitize_log); -} - -int nvme_predictable_latency_per_nvmset_log(int fd, - __u16 nvmset_id, - struct nvme_predlat_per_nvmset_log_page *plpns_log) -{ - return nvme_get_log13(fd, NVME_NSID_ALL, - NVME_LOG_PRELAT_PER_NVMSET, 0, 0, nvmset_id, - false, sizeof(*plpns_log), plpns_log); -} - -int nvme_predictable_latency_event_agg_log(int fd, - void *pea_log, bool rae, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, - NVME_LOG_PRELAT_EVENT_AGG, rae, NVME_NO_LOG_LSP, - size, pea_log); -} - -int nvme_persistent_event_log(int fd, __u8 action, __u32 size, - void *pevent_log_info) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_PERSISTENT_EVENT, - false, action, size, pevent_log_info); -} - -int nvme_endurance_group_event_agg_log(int fd, - void *endurance_log, bool rae, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, - NVME_LOG_ENDURANCE_GROUP_EVENT_AGG, rae, NVME_NO_LOG_LSP, - size, endurance_log); -} - -int nvme_lba_status_log(int fd, void *lba_status, bool rae, - __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_LBA_STATUS, - rae, NVME_NO_LOG_LSP, size, lba_status); -} - -int nvme_resv_notif_log(int fd, struct nvme_resv_notif_log *resv) -{ - return nvme_get_log(fd, 0, NVME_LOG_RESERVATION, false, - NVME_NO_LOG_LSP, sizeof(*resv), resv); -} - -int nvme_boot_part_log(int fd, __u8 lsp, void *data, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_BOOT_PARTITION, - false, lsp, size, data); -} - -int nvme_fid_support_effects_log(int fd, struct nvme_fid_support_effects *fid_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_FID_SUPPORT_EFFECTS, false, - NVME_NO_LOG_LSP, sizeof(*fid_log), fid_log); -} - -int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11, - __u32 cdw12, __u32 cdw14, __u32 data_len, void *data, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = opcode, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw14 = cdw14, - .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, __u32 cdw12, - bool save, __u8 uuid_index, __u32 data_len, void *data, __u32 *result) -{ - __u32 cdw10 = fid | (save ? 1 << 31 : 0); - __u32 cdw14 = uuid_index; - - return nvme_feature(fd, nvme_admin_set_features, nsid, cdw10, value, - cdw12, cdw14, data_len, data, result); -} - - -int nvme_get_property(int fd, int offset, uint64_t *value) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_fabrics_command, - .nsid = nvme_fabrics_type_property_get, - .cdw10 = is_64bit_reg(offset), - .cdw11 = offset, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && value) - *value = cmd.result; - return err; -} - -int nvme_get_properties(int fd, void **pbar) -{ - int offset; - uint64_t value; - int err, size = getpagesize(); - - *pbar = malloc(size); - if (!*pbar) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return -ENOMEM; - } - - memset(*pbar, 0xff, size); - for (offset = NVME_REG_CAP; offset <= NVME_REG_CMBSZ;) { - err = nvme_get_property(fd, offset, &value); - if (err > 0 && (err & 0xff) == NVME_SC_INVALID_FIELD) { - err = 0; - value = -1; - } else if (err) { - free(*pbar); - break; - } - if (is_64bit_reg(offset)) { - *(uint64_t *)(*pbar + offset) = value; - offset += 8; - } else { - *(uint32_t *)(*pbar + offset) = value; - offset += 4; - } - } - - return err; -} - -int nvme_set_property(int fd, int offset, uint64_t value) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_fabrics_command, - .nsid = nvme_fabrics_type_property_set, - .cdw10 = is_64bit_reg(offset), - .cdw11 = offset, - .cdw12 = value & 0xffffffff, - .cdw13 = value >> 32, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel, __u32 cdw11, - __u8 uuid_index, __u32 data_len, void *data, __u32 *result) -{ - __u32 cdw10 = fid | sel << 8; - __u32 cdw14 = uuid_index; - - return nvme_feature(fd, nvme_admin_get_features, nsid, cdw10, cdw11, - 0, cdw14, data_len, data, result); -} - -int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi, - __u8 pil, __u8 ms, __u32 timeout) -{ - __u8 lbafl = lbaf & 0xf; - __u8 lbafu = (lbaf >> 4) & 0x3; - __u32 cdw10 = lbafl | ms << 4 | pi << 5 | pil << 8 | ses << 9 | - lbafu << 12; - - 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 anagrpid, __u16 nvmsetid, __u8 csi, - __u32 timeout, __u32 *result) -{ - struct nvme_id_ns ns = { - .nsze = cpu_to_le64(nsze), - .ncap = cpu_to_le64(ncap), - .flbas = flbas, - .dps = dps, - .nmic = nmic, - .anagrpid = anagrpid, - .nvmsetid = nvmsetid, - }; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_mgmt, - .addr = (__u64)(uintptr_t) ((void *)&ns), - .cdw10 = 0, - .cdw11 = csi << 24, - .data_len = 0x1000, - .timeout_ms = timeout, - }; - 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, __u32 timeout) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_mgmt, - .nsid = nsid, - .cdw10 = 1, - .timeout_ms = timeout, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist, - bool attach) -{ - struct nvme_controller_list cntlist = { - .num = cpu_to_le16(num_ctrls), - }; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_attach, - .nsid = nsid, - .addr = (__u64)(uintptr_t)&cntlist, - .cdw10 = attach ? 0 : 1, - .data_len = 0x1000, - }; - int i; - - for (i = 0; i < num_ctrls; i++) - cntlist.identifier[i] = cpu_to_le16(ctrlist[i]); - - return nvme_submit_admin_passthru(fd, &cmd); -} - -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, __u32 *result) -{ - int err; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_activate_fw, - .cdw10 = (bpid << 31) | (action << 3) | slot, - }; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 data_len, void *data) -{ - 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 = data_len, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 al, __u32 data_len, void *data) -{ - 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, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_lockdown(int fd, __u8 scp, __u8 prhbt, __u8 ifc, __u8 ofi, - __u8 uuid) -{ - __u32 cdw10 = ofi << 8 | (ifc & 0x3) << 5 | (prhbt & 0x1) << 4 | (scp & 0xF); - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_lockdown_cmd, - .cdw10 = cdw10, - .cdw14 = uuid & 0x3F, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_lba_status(int fd, __u32 namespace_id, __u64 slba, __u32 mndw, - __u8 atype, __u16 rl, void *data, __u32 timeout_ms) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_get_lba_status, - .nsid = namespace_id, - .addr = (__u64)(uintptr_t) data, - .data_len = (mndw + 1) * 4, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = mndw, - .cdw13 = (atype << 24) | rl, - .timeout_ms = timeout_ms, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -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; -} - -int nvme_cap_mgmt(int fd, __u8 op, __u16 element_id, __u32 dw11, - __u32 dw12, __u32 *result) -{ - int err; - __u32 dw10 = op | element_id << 16; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_capacity_mgmt, - .cdw10 = dw10, - .cdw11 = dw11, - .cdw12 = dw12, - }; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_sanitize(int fd, __u8 sanact, __u8 ause, __u8 owpass, __u8 oipbp, - __u8 no_dealloc, __u32 ovrpat) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_sanitize_nvm, - .cdw10 = no_dealloc << 9 | oipbp << 8 | - owpass << NVME_SANITIZE_OWPASS_SHIFT | - ause << 3 | sanact, - .cdw11 = ovrpat, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_self_test_start(int fd, __u32 nsid, __u8 stc) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_dev_self_test, - .nsid = nsid, - .cdw10 = stc, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_virtual_mgmt(int fd, __u32 cdw10, __u32 cdw11, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_virtual_mgmt, - .cdw10 = cdw10, - .cdw11 = cdw11, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - - return err; -} - -int nvme_zns_mgmt_send(int fd, __u32 nsid, __u64 slba, bool select_all, - __u32 timeout, enum nvme_zns_send_action zsa, __u32 data_len, - void *data) -{ - __u32 cdw10 = slba & 0xffffffff; - __u32 cdw11 = slba >> 32; - __u32 cdw13 = zsa | (!!select_all) << 8; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_send, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)data, - .data_len = data_len, - .timeout_ms = timeout, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_zns_mgmt_recv(int fd, __u32 nsid, __u64 slba, - enum nvme_zns_recv_action zra, __u8 zrasf, - bool zras_feat, __u32 data_len, void *data) -{ - __u32 cdw10 = slba & 0xffffffff; - __u32 cdw11 = slba >> 32; - __u32 cdw12 = (data_len >> 2) - 1; - __u32 cdw13 = zra | zrasf << 8 | zras_feat << 16; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_recv, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)data, - .data_len = data_len, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_zns_report_zones(int fd, __u32 nsid, __u64 slba, bool extended, - enum nvme_zns_report_options opts, bool partial, - __u32 data_len, void *data) -{ - enum nvme_zns_recv_action zra; - - if (extended) - zra = NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES; - else - zra = NVME_ZNS_ZRA_REPORT_ZONES; - - return nvme_zns_mgmt_recv(fd, nsid, slba, zra, opts, partial, - data_len, data); -} - -int nvme_zns_append(int fd, __u32 nsid, __u64 zslba, __u16 nlb, __u16 control, - __u32 ilbrt, __u16 lbat, __u16 lbatm, __u32 data_len, - void *data, __u32 metadata_len, void *metadata, - __u64 *result) -{ - __u32 cdw10 = zslba & 0xffffffff; - __u32 cdw11 = zslba >> 32; - __u32 cdw12 = nlb | (control << 16); - __u32 cdw14 = ilbrt; - __u32 cdw15 = lbat | (lbatm << 16); - - struct nvme_passthru_cmd64 cmd = { - .opcode = nvme_zns_cmd_append, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw14 = cdw14, - .cdw15 = cdw15, - .metadata = (__u64)(uintptr_t)metadata, - .addr = (__u64)(uintptr_t)data, - .metadata_len = metadata_len, - .data_len = data_len, - }; - - int err; - - err = ioctl(fd, NVME_IOCTL_IO64_CMD, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} diff --git a/nvme-ioctl.h b/nvme-ioctl.h deleted file mode 100644 index 31eb7c3..0000000 --- a/nvme-ioctl.h +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef _NVME_LIB_H -#define _NVME_LIB_H - -#include <linux/types.h> -#include <stdbool.h> -#include "linux/nvme_ioctl.h" -#include "nvme.h" - -#define NVME_IOCTL_TIMEOUT 120000 /* in milliseconds */ - -int nvme_get_nsid(int fd); - -/* Generic passthrough */ -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, - struct nvme_passthru_cmd *cmd); -int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd); -int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd); - -int nvme_passthru(int fd, unsigned long 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, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, - __u16 appmask, __u64 storage_tag, void *data, __u32 buffer_size, - void *metadata, __u32 mbuffer_size); - -/* 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, - __u64 storage_tag); - -int nvme_write_uncorrectable(int fd, __u32 nsid, __u64 slba, __u16 nlb); - -int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask, - __u64 storage_tag); - -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(int *ctx_attrs, int *llbas, - unsigned long long *slbas, - __u16 nr_ranges); - -int nvme_copy(int fd, __u32 nsid, struct nvme_copy_range *copy, __u64 sdlba, - __u16 nr, __u8 prinfor, __u8 prinfow, __u8 dtype, __u16 dspec, - __u8 format, int lr, int fua, __u32 ilbrt, __u16 lbatm, - __u16 lbat); -struct nvme_copy_range *nvme_setup_copy_range(int *nlbs, unsigned long long *slbas, - int *eilbrts, int *elbatms, int *elbats, __u16 nr); - -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_identify13(int fd, __u32 nsid, __u32 cdw10, __u32 cdw11, void *data); -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_csi(int fd, __u32 nsid, __u8 csi, bool all, void *data); -int nvme_cmd_set_independent_identify_ns(int fd, __u32 nsid, 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_identify_nvmset(int fd, __u16 nvmset_id, void *data); -int nvme_identify_uuid(int fd, void *data); -int nvme_identify_primary_ctrl_caps(int fd, void *data); -int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data); -int nvme_identify_ns_granularity(int fd, void *data); -int nvme_identify_ctrl_nvm(int fd, void *data); -int nvme_zns_identify_ctrl(int fd, void *data); -int nvme_zns_identify_ns(int fd, __u32 nsid, void *data); -int nvme_identify_iocs(int fd, __u16 cntid, void *data); -int nvme_identify_domain_list(int fd, __u16 dom_id, void *data); -int nvme_identify_endurance_group_list(int fd, __u16 endgrp_id, void *data); -int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae, - __u8 lsp, __u32 data_len, void *data); -int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, - __u16 group_id, bool rae, __u8 uuid_ix, __u8 csi, bool ot, - __u32 data_len, void *data); -int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, - __u64 lpo, __u16 lsi, bool rae, __u32 data_len, - void *data); -int nvme_get_telemetry_log(int fd, void *lp, int generate_report, - int ctrl_gen, size_t log_page_size, __u64 offset); -int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log); -int nvme_changed_ns_list_log(int fd, - struct nvme_changed_ns_list_log *changed_ns_list_log); -int nvme_error_log(int fd, 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_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo); -int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log); -int nvme_supported_log(int fd, struct nvme_support_log_pages *supports); -int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size); -int nvme_sanitize_log(int fd, bool rae, struct nvme_sanitize_log_page *sanitize_log); -int nvme_predictable_latency_per_nvmset_log(int fd, - __u16 nvmset_id, struct nvme_predlat_per_nvmset_log_page *plpns_log); -int nvme_predictable_latency_event_agg_log(int fd, void *pea_log, - bool rae, __u32 size); -int nvme_persistent_event_log(int fd, __u8 action, __u32 size, - void *pevent_log_info); -int nvme_endurance_group_event_agg_log(int fd, void *endurance_log, - bool rae, __u32 size); -int nvme_endurance_log(int fd, __u16 group_id, - struct nvme_endurance_group_log *endurance_log); -int nvme_lba_status_log(int fd, void *lba_status, bool rae, - __u32 size); -int nvme_resv_notif_log(int fd, struct nvme_resv_notif_log *resv); -int nvme_boot_part_log(int fd, __u8 lsp, void *data, __u32 size); -int nvme_fid_support_effects_log(int fd, struct nvme_fid_support_effects *fid_log); -int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, - __u32 cdw11, __u32 cdw12, __u32 cdw14, __u32 data_len, void *data, - __u32 *result); -int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, __u32 cdw12, - bool save, __u8 uuid_index, __u32 data_len, void *data, __u32 *result); -int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel, - __u32 cdw11, __u8 uuid_index, __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 anagrpid, __u16 nvmsetid, __u8 csi, - __u32 timeout, __u32 *result); -int nvme_ns_delete(int fd, __u32 nsid, __u32 timeout); - -int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist, bool attach); - -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, __u32 *result); - -int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 data_len, void *data); -int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 al, __u32 data_len, void *data); -int nvme_lockdown(int fd, __u8 scp, __u8 prhbt, __u8 ifc, __u8 ofi, - __u8 uuid); - -int nvme_subsystem_reset(int fd); -int nvme_reset_controller(int fd); -int nvme_ns_rescan(int fd); - -int nvme_get_lba_status(int fd, __u32 namespace_id, __u64 slba, __u32 mndw, - __u8 atype, __u16 rl, void *data, __u32 timeout_ms); -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_cap_mgmt(int fd, __u8 op, __u16 element_id, __u32 dw11, - __u32 dw12, __u32 *result); -int nvme_get_properties(int fd, void **pbar); -int nvme_set_property(int fd, int offset, uint64_t value); -int nvme_get_property(int fd, int offset, uint64_t *value); -int nvme_sanitize(int fd, __u8 sanact, __u8 ause, __u8 owpass, __u8 oipbp, - __u8 no_dealloc, __u32 ovrpat); -int nvme_self_test_start(int fd, __u32 nsid, __u8 stc); -int nvme_self_test_log(int fd, __u32 nsid, struct nvme_self_test_log *self_test_log); -int nvme_virtual_mgmt(int fd, __u32 cdw10, __u32 cdw11, __u32 *result); - -int nvme_zns_mgmt_send(int fd, __u32 nsid, __u64 slba, bool select_all, - __u32 timeout, enum nvme_zns_send_action zsa, __u32 data_len, - void *data); -int nvme_zns_mgmt_recv(int fd, __u32 nsid, __u64 slba, - enum nvme_zns_recv_action zra, __u8 zrasf, - bool zras_feat, __u32 data_len, void *data); -int nvme_zns_report_zones(int fd, __u32 nsid, __u64 slba, bool extended, - enum nvme_zns_report_options opts, bool partial, - __u32 data_len, void *data); -int nvme_zns_append(int fd, __u32 nsid, __u64 zslba, __u16 nlb, __u16 control, - __u32 ilbrt, __u16 lbat, __u16 lbatm, __u32 data_len, - void *data, __u32 metadata_len, void *metadata, - __u64 *result); - -#endif /* _NVME_LIB_H */ diff --git a/nvme-lightnvm.c b/nvme-lightnvm.c deleted file mode 100644 index d81fac6..0000000 --- a/nvme-lightnvm.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * lightnvm.c -- LightNVM NVMe integration. - * - * Copyright (c) 2016, CNEX Labs. - * - * Written by Matias Bjoerling <matias@cnexlabs.com> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#include <errno.h> -#include <inttypes.h> - -#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 - 1); - strncpy(init.mmtype, mmtype, NVM_MMTYPE_LEN - 1); - - 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) { - lnvm_close(fd); - 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) { - lnvm_close(fd); - 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 over_prov, 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 - 1); - strncpy(c.tgtname, tgtname, DISK_NAME_LEN - 1); - strncpy(c.tgttype, tgttype, NVM_TTYPE_NAME_MAX - 1); - c.flags = flags; - - /* Fall back into simple IOCTL version if no extended attributes used */ - if (over_prov != -1) { - c.conf.type = NVM_CONFIG_TYPE_EXTENDED; - c.conf.e.lun_begin = lun_begin; - c.conf.e.lun_end = lun_end; - c.conf.e.over_prov = over_prov; - } else { - c.conf.type = NVM_CONFIG_TYPE_SIMPLE; - c.conf.s.lun_begin = lun_begin; - c.conf.s.lun_end = lun_end; - } - - 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 - 1); - 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 - 1); - 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(void *t, int human) -{ - struct nvme_nvm_id12_group *grp = t; - uint32_t mpos = (uint32_t)le32_to_cpu(grp->mpos); - uint32_t mccap = (uint32_t)le32_to_cpu(grp->mccap); - - printf(" mtype : %d\n", grp->mtype); - if (human) { - if (grp->mtype == LNVM_IDFY_GRP_MTYPE_NAND) - printf(" NAND Flash Memory\n"); - else - printf(" Reserved\n"); - } - printf(" fmtype : %d\n", grp->fmtype); - if (human) { - if (grp->fmtype == LNVM_IDFY_GRP_FMTYPE_SLC) - printf(" Single bit Level Cell flash (SLC)\n"); - else if (grp->fmtype == LNVM_IDFY_GRP_FMTYPE_MLC) - printf(" Two bit Level Cell flash (MLC)\n"); - else if (grp->fmtype == LNVM_IDFY_GRP_FMTYPE_TLC) - printf(" Three bit Level Cell flash (TLC)\n"); - else - printf(" Reserved\n"); - } - 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", mpos); - if (human) { - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_SNGL_PLN_RD)) - printf(" [0]: Single plane read\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_DUAL_PLN_RD)) - printf(" [1]: Dual plane read\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_QUAD_PLN_RD)) - printf(" [2]: Quad plane read\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_SNGL_PLN_PRG)) - printf(" [8]: Single plane program\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_DUAL_PLN_PRG)) - printf(" [9]: Dual plane program\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_QUAD_PLN_PRG)) - printf(" [10]: Quad plane program\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_SNGL_PLN_ERS)) - printf(" [16]: Single plane erase\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_DUAL_PLN_ERS)) - printf(" [17]: Dual plane erase\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_QUAD_PLN_ERS)) - printf(" [18]: Quad plane erase\n"); - } - printf(" mccap : %#x\n", mccap); - if (human) { - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_SLC)) - printf(" [0]: SLC mode\n"); - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_CMD_SUSP)) - printf(" [1]: Command suspension\n"); - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_SCRAMBLE)) - printf(" [2]: Scramble\n"); - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_ENCRYPT)) - printf(" [3]: Encryption\n"); - } - 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_id12_ns(void *t, unsigned int flags) -{ - int i; - int human = flags & VERBOSE; - struct nvme_nvm_id12 *id = t; - - uint32_t cap = (uint32_t) le32_to_cpu(id->cap); - uint32_t dom = (uint32_t) le32_to_cpu(id->dom); - uint32_t cgrps = id->cgrps; - - 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); - if (human) { - if (!id->vmnt) - printf(" Generic/Enable opcodes as found in this spec."); - else - printf(" Reserved/Reserved for future opcode configurations"); - } - printf("\n"); - printf("cgrps : %d\n", id->cgrps); - printf("cap : %#x\n", cap); - if (human) { - if (cap & (1 << LNVM_IDFY_CAP_BAD_BLK_TBL_MGMT)) - printf(" [0]: Bad block table management\n"); - if (cap & (1 << LNVM_IDFY_CAP_HYBRID_CMD_SUPP)) - printf(" [1]: Hybrid command support\n"); - } - printf("dom : %#x\n", dom); - if (human) { - if (dom & (1 << LNVM_IDFY_DOM_HYBRID_MODE)) - printf(" [0]: Hybrid mode (L2P MAP is in device)\n"); - if (dom & (1 << LNVM_IDFY_DOM_ECC_MODE)) - printf(" [1]: Error Code Correction(ECC) mode\n"); - } - show_lnvm_ppaf(&id->ppaf); - - for (i = 0; i < cgrps; i++) { - printf("grp : %d\n", i); - show_lnvm_id_grp((void *)&id->groups[i], human); - } -} - -static void show_lnvm_id20_ns(struct nvme_nvm_id20 *id, unsigned int flags) -{ - int human = flags & VERBOSE; - uint32_t mccap = (uint32_t) le32_to_cpu(id->mccap); - - printf("ver_major : %#x\n", id->mjr); - printf("ver_minor : %#x\n", id->mnr); - - printf("mccap : %#x\n", mccap); - if (human) { - if (mccap & (1 << LNVM_IDFY_CAP_VCOPY)) - printf(" [0]: Vector copy support\n"); - if (mccap & (1 << LNVM_IDFY_CAP_MRESETS)) - printf(" [1]: Multiple resets support\n"); - } - printf("wit : %d\n", id->wit); - - printf("lba format\n"); - printf(" grp len : %d\n", id->lbaf.grp_len); - printf(" pu len : %d\n", id->lbaf.pu_len); - printf(" chk len : %d\n", id->lbaf.chk_len); - printf(" clba len : %d\n", id->lbaf.lba_len); - - printf("geometry\n"); - printf(" num_grp : %d\n", le16_to_cpu(id->num_grp)); - printf(" num_pu : %d\n", le16_to_cpu(id->num_pu)); - printf(" num_chk : %d\n", le32_to_cpu(id->num_chk)); - printf(" clba : %d\n", le32_to_cpu(id->clba)); - printf("write req\n"); - printf(" ws_min : %d\n", le32_to_cpu(id->ws_min)); - printf(" ws_opt : %d\n", le32_to_cpu(id->ws_opt)); - printf(" mw_cunits : %d\n", le32_to_cpu(id->mw_cunits)); - printf(" maxoc : %d\n", le32_to_cpu(id->maxoc)); - printf(" maxocpu : %d\n", le32_to_cpu(id->maxocpu)); - printf("perf metrics\n"); - printf(" trdt (ns) : %d\n", le32_to_cpu(id->trdt)); - printf(" trdm (ns) : %d\n", le32_to_cpu(id->trdm)); - printf(" twrt (ns) : %d\n", le32_to_cpu(id->twrt)); - printf(" twrm (ns) : %d\n", le32_to_cpu(id->twrm)); - printf(" tcrst (ns) : %d\n", le32_to_cpu(id->tcrst)); - printf(" tcrsm (ns) : %d\n", le32_to_cpu(id->tcrsm)); -} - -static void show_lnvm_id_ns(struct nvme_nvm_id *id, unsigned int flags) -{ - switch (id->ver_id) { - case 1: - show_lnvm_id12_ns((void *) id, flags); - break; - case 2: - show_lnvm_id20_ns((void *) id, flags); - break; - default: - fprintf(stderr, "Version %d not supported.\n", - id->ver_id); - } -} - -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 = sizeof(struct nvme_nvm_id), - }; - - 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 & BINARY) - d_raw((unsigned char *)&nvm_id, sizeof(nvm_id)); - else - show_lnvm_id_ns(&nvm_id, flags); - } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", - nvme_status_to_string(err), err, nsid); - return err; -} - -static inline const char *print_chunk_state(__u8 cs) -{ - switch (cs) { - case 1 << 0: return "FREE"; - case 1 << 1: return "CLOSED"; - case 1 << 2: return "OPEN"; - case 1 << 3: return "OFFLINE"; - default: return "UNKNOWN"; - } -} - -static inline const char *print_chunk_type(__u8 ct) -{ - switch (ct & 0xF) { - case 1 << 0: return "SEQWRITE_REQ"; - case 1 << 1: return "RANDWRITE_ALLOWED"; - default: return "UNKNOWN"; - } -} - -static inline const char *print_chunk_attr(__u8 ct) -{ - switch (ct & 0xF0) { - case 1 << 4: return "DEVIATED"; - default: return "NONE"; - } -} - -static void show_lnvm_chunk_log(struct nvme_nvm_chunk_desc *chunk_log, - __u32 data_len) -{ - int nr_entry = data_len / sizeof(struct nvme_nvm_chunk_desc); - int idx; - - printf("Total chunks in namespace: %d\n", nr_entry); - for (idx = 0; idx < nr_entry; idx++) { - struct nvme_nvm_chunk_desc *desc = &chunk_log[idx]; - - printf(" [%5d] { ", idx); - printf("SLBA: 0x%016"PRIx64, le64_to_cpu(desc->slba)); - printf(", WP: 0x%016"PRIx64, le64_to_cpu(desc->wp)); - printf(", CNLB: 0x%016"PRIx64, le64_to_cpu(desc->cnlb)); - printf(", State: %-8s", print_chunk_state(desc->cs)); - printf(", Type: %-20s", print_chunk_type(desc->ct)); - printf(", Attr: %-8s", print_chunk_attr(desc->ct)); - printf(", WLI: %4d }\n", desc->wli); - } -} - -int lnvm_do_chunk_log(int fd, __u32 nsid, __u32 data_len, void *data, - unsigned int flags) -{ - int err; - - err = nvme_get_log13(fd, nsid, NVM_LID_CHUNK_INFO, 0, 0, 0, - false, data_len, data); - if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", - nvme_status_to_string(err), err, nsid); - - goto out; - } else if (err < 0) { - err = -errno; - perror("nvme_get_log13"); - - goto out; - } - - if (flags & BINARY) - d_raw(data, data_len); - else - show_lnvm_chunk_log(data, data_len); - -out: - 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_id12 *id, - struct ppa_addr ppa, - unsigned int flags) -{ - struct nvme_nvm_id12_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 = bufsz, - .ppa = cpu_to_le64(ppa.ppa), - }; - void *tmp = &cmd; - struct nvme_passthru_cmd *nvme_cmd = tmp; - - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, nvme_cmd); - if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); - free(bbtbl); - return err; - } - - if (flags & BINARY) - 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_id12 nvm_id; - struct ppa_addr ppa; - int err; - void *tmp = &nvm_id; - - err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *)tmp); - if (err) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); - return err; - } - - if (nvm_id.ver_id != 1) { - fprintf(stderr, "Get bad block table not supported on version %d\n", - nvm_id.ver_id); - return -EINVAL; - } - - 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, - }; - void *tmp = &cmd; - struct nvme_passthru_cmd *nvme_cmd = tmp; - - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, nvme_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_id12 nvm_id; - struct ppa_addr ppa; - int err; - void *tmp = &nvm_id; - - err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *)tmp); - if (err) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); - return err; - } - - if (nvm_id.ver_id != 1) { - fprintf(stderr, "Set bad block table not supported on version %d\n", - nvm_id.ver_id); - return -EINVAL; - } - - 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); -} diff --git a/nvme-lightnvm.h b/nvme-lightnvm.h deleted file mode 100644 index 19660b7..0000000 --- a/nvme-lightnvm.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2016 CNEX Labs. All rights reserved. - * - * Author: Matias Bjoerling <matias@cnexlabs.com> - * - * 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; - __u64 metadata; - __u64 addr; - __u32 metadata_len; - __u32 data_len; - __le64 ppa; - __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_id12_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)); - -enum { - LNVM_IDFY_CAP_BAD_BLK_TBL_MGMT = 0, - LNVM_IDFY_CAP_HYBRID_CMD_SUPP = 1, - LNVM_IDFY_CAP_VCOPY = 0, - LNVM_IDFY_CAP_MRESETS = 1, - LNVM_IDFY_DOM_HYBRID_MODE = 0, - LNVM_IDFY_DOM_ECC_MODE = 1, - LNVM_IDFY_GRP_MTYPE_NAND = 0, - LNVM_IDFY_GRP_FMTYPE_SLC = 0, - LNVM_IDFY_GRP_FMTYPE_MLC = 1, - LNVM_IDFY_GRP_FMTYPE_TLC = 2, - LNVM_IDFY_GRP_MPOS_SNGL_PLN_RD = 0, - LNVM_IDFY_GRP_MPOS_DUAL_PLN_RD = 1, - LNVM_IDFY_GRP_MPOS_QUAD_PLN_RD = 2, - LNVM_IDFY_GRP_MPOS_SNGL_PLN_PRG = 8, - LNVM_IDFY_GRP_MPOS_DUAL_PLN_PRG = 9, - LNVM_IDFY_GRP_MPOS_QUAD_PLN_PRG = 10, - LNVM_IDFY_GRP_MPOS_SNGL_PLN_ERS = 16, - LNVM_IDFY_GRP_MPOS_DUAL_PLN_ERS = 17, - LNVM_IDFY_GRP_MPOS_QUAD_PLN_ERS = 18, - LNVM_IDFY_GRP_MCCAP_SLC = 0, - LNVM_IDFY_GRP_MCCAP_CMD_SUSP = 1, - LNVM_IDFY_GRP_MCCAP_SCRAMBLE = 2, - LNVM_IDFY_GRP_MCCAP_ENCRYPT = 3, -}; - -struct nvme_nvm_id12 { - __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_id12_group groups[4]; -} __attribute__((packed)); - -struct nvme_nvm_id20_addrf { - __u8 grp_len; - __u8 pu_len; - __u8 chk_len; - __u8 lba_len; - __u8 resv[4]; -} __attribute__((packed)); - -struct nvme_nvm_id20 { - __u8 mjr; - __u8 mnr; - __u8 resv[6]; - - struct nvme_nvm_id20_addrf lbaf; - - __le32 mccap; - __u8 resv2[12]; - - __u8 wit; - __u8 resv3[31]; - - /* Geometry */ - __le16 num_grp; - __le16 num_pu; - __le32 num_chk; - __le32 clba; - __u8 resv4[52]; - - /* Write data requirements */ - __le32 ws_min; - __le32 ws_opt; - __le32 mw_cunits; - __le32 maxoc; - __le32 maxocpu; - __u8 resv5[44]; - - /* Performance related metrics */ - __le32 trdt; - __le32 trdm; - __le32 twrt; - __le32 twrm; - __le32 tcrst; - __le32 tcrsm; - __u8 resv6[40]; - - /* Reserved area */ - __u8 resv7[2816]; - - /* Vendor specific */ - __u8 vs[1024]; -} __attribute__((packed)); - -struct nvme_nvm_id { - __u8 ver_id; - __u8 resv[4095]; -} __attribute__((packed)); - -enum { - NVM_LID_CHUNK_INFO = 0xCA, -}; - -struct nvme_nvm_chunk_desc { - __u8 cs; - __u8 ct; - __u8 wli; - __u8 rsvd_7_3[5]; - __u64 slba; - __u64 cnlb; - __u64 wp; -}; - -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_get_identity(int fd, int nsid, struct nvme_nvm_id *nvm_id); - -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); -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_chunk_log(int, __u32, __u32, void *, 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 diff --git a/nvme-print.c b/nvme-print.c index f631b34..d0ddb53 100755..100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -1,11 +1,14 @@ #include <assert.h> +#include <errno.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <sys/stat.h> +#include <uuid/uuid.h> #include "nvme.h" +#include "libnvme.h" #include "nvme-print.h" #include "nvme-models.h" #include "util/suffix.h" @@ -22,6 +25,15 @@ static const uint8_t zero_uuid[16] = { 0 }; static const uint8_t invalid_uuid[16] = {[0 ... 15] = 0xff }; static const char dash[100] = {[0 ... 99] = '-'}; +struct nvme_bar_cap { + __u16 mqes; + __u8 ams_cqr; + __u8 to; + __u16 bps_css_nssrs_dstrd; + __u8 mpsmax_mpsmin; + __u8 rsvd_cmbs_pmrs; +}; + static long double int128_to_double(__u8 *data) { int i; @@ -37,15 +49,15 @@ static long double int128_to_double(__u8 *data) static const char *nvme_ana_state_to_string(enum nvme_ana_state state) { switch (state) { - case NVME_ANA_OPTIMIZED: + case NVME_ANA_STATE_OPTIMIZED: return "optimized"; - case NVME_ANA_NONOPTIMIZED: + case NVME_ANA_STATE_NONOPTIMIZED: return "non-optimized"; - case NVME_ANA_INACCESSIBLE: + case NVME_ANA_STATE_INACCESSIBLE: return "inaccessible"; - case NVME_ANA_PERSISTENT_LOSS: + case NVME_ANA_STATE_PERSISTENT_LOSS: return "persistent-loss"; - case NVME_ANA_CHANGE: + case NVME_ANA_STATE_CHANGE: return "change"; } return "invalid state"; @@ -66,8 +78,8 @@ const char *nvme_cmd_to_string(int admin, __u8 opcode) case nvme_admin_get_features: return "Get Features"; case nvme_admin_async_event: return "Asynchronous Event Request"; case nvme_admin_ns_mgmt: return "Namespace Management"; - case nvme_admin_activate_fw: return "Firmware Commit"; - case nvme_admin_download_fw: return "Firmware Image Download"; + case nvme_admin_fw_commit: return "Firmware Commit"; + case nvme_admin_fw_download: return "Firmware Image Download"; case nvme_admin_dev_self_test: return "Device Self-test"; case nvme_admin_ns_attach: return "Namespace Attachment"; case nvme_admin_keep_alive: return "Keep Alive"; @@ -98,39 +110,45 @@ const char *nvme_cmd_to_string(int admin, __u8 opcode) case nvme_cmd_resv_release: return "Reservation Release"; case nvme_cmd_verify: return "Verify"; case nvme_cmd_copy: return "Copy"; + case nvme_zns_cmd_mgmt_send: return "Zone Management Send"; + case nvme_zns_cmd_mgmt_recv: return "Zone Management Receive"; + case nvme_zns_cmd_append: return "Zone Append"; } } return "Unknown"; } -static char *fw_to_string(__u8 fw[]) +static const char *fw_to_string(char *c) { - static char frs[9]; + static char ret[9]; + int i; - snprintf(frs, sizeof(frs), "%-.*s", 8, fw); - return frs; + for (i = 0; i < 8; i++) + ret[i] = c[i] >= '!' && c[i] <= '~' ? c[i] : '.'; + ret[i] = '\0'; + return ret; } static const char *get_sanitize_log_sstat_status_str(__u16 status) { - switch (status & NVME_SANITIZE_LOG_STATUS_MASK) { - case NVME_SANITIZE_LOG_NEVER_SANITIZED: + switch (status & NVME_SANITIZE_SSTAT_STATUS_MASK) { + case NVME_SANITIZE_SSTAT_STATUS_NEVER_SANITIZED: return "NVM Subsystem has never been sanitized."; - case NVME_SANITIZE_LOG_COMPLETED_SUCCESS: + case NVME_SANITIZE_SSTAT_STATUS_COMPLETE_SUCCESS: return "Most Recent Sanitize Command Completed Successfully."; - case NVME_SANITIZE_LOG_IN_PROGESS: + case NVME_SANITIZE_SSTAT_STATUS_IN_PROGESS: return "Sanitize in Progress."; - case NVME_SANITIZE_LOG_COMPLETED_FAILED: + case NVME_SANITIZE_SSTAT_STATUS_COMPLETED_FAILED: return "Most Recent Sanitize Command Failed."; - case NVME_SANITIZE_LOG_ND_COMPLETED_SUCCESS: + case NVME_SANITIZE_SSTAT_STATUS_ND_COMPLETE_SUCCESS: return "Most Recent Sanitize Command (No-Deallocate After Sanitize) Completed Successfully."; default: return "Unknown"; } } -static void json_nvme_id_ns(struct nvme_id_ns *ns) +static void json_nvme_id_ns(struct nvme_id_ns *ns, bool cap_only) { char nguid_buf[2 * sizeof(ns->nguid) + 1], eui64_buf[2 * sizeof(ns->eui64) + 1]; @@ -143,54 +161,63 @@ static void json_nvme_id_ns(struct nvme_id_ns *ns) root = json_create_object(); - json_object_add_value_uint(root, "nsze", le64_to_cpu(ns->nsze)); - json_object_add_value_uint(root, "ncap", le64_to_cpu(ns->ncap)); - json_object_add_value_uint(root, "nuse", le64_to_cpu(ns->nuse)); - json_object_add_value_int(root, "nsfeat", ns->nsfeat); + if (!cap_only) { + json_object_add_value_uint64(root, "nsze", le64_to_cpu(ns->nsze)); + json_object_add_value_uint64(root, "ncap", le64_to_cpu(ns->ncap)); + json_object_add_value_uint64(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); + if (!cap_only) + 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); - json_object_add_value_int(root, "nsattr", ns->nsattr); - json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid)); + if (!cap_only) { + 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, "dlfeat", ns->dlfeat); + 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); + json_object_add_value_int(root, "nsattr", ns->nsattr); + json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid)); + + if (ns->nsfeat & 0x10) { + json_object_add_value_int(root, "npwg", le16_to_cpu(ns->npwg)); + json_object_add_value_int(root, "npwa", le16_to_cpu(ns->npwa)); + json_object_add_value_int(root, "npdg", le16_to_cpu(ns->npdg)); + json_object_add_value_int(root, "npda", le16_to_cpu(ns->npda)); + json_object_add_value_int(root, "nows", le16_to_cpu(ns->nows)); + } - if (ns->nsfeat & 0x10) { - json_object_add_value_int(root, "npwg", le16_to_cpu(ns->npwg)); - json_object_add_value_int(root, "npwa", le16_to_cpu(ns->npwa)); - json_object_add_value_int(root, "npdg", le16_to_cpu(ns->npdg)); - json_object_add_value_int(root, "npda", le16_to_cpu(ns->npda)); - json_object_add_value_int(root, "nows", le16_to_cpu(ns->nows)); + json_object_add_value_int(root, "mssrl", le16_to_cpu(ns->mssrl)); + json_object_add_value_int(root, "mcl", le32_to_cpu(ns->mcl)); + json_object_add_value_int(root, "msrc", ns->msrc); } + json_object_add_value_int(root, "nulbaf", ns->nulbaf); - json_object_add_value_int(root, "mssrl", le16_to_cpu(ns->mssrl)); - json_object_add_value_int(root, "mcl", le32_to_cpu(ns->mcl)); - json_object_add_value_int(root, "msrc", ns->msrc); + if (!cap_only) { + json_object_add_value_int(root, "anagrpid", le32_to_cpu(ns->anagrpid)); + json_object_add_value_int(root, "endgid", le16_to_cpu(ns->endgid)); - json_object_add_value_int(root, "anagrpid", le32_to_cpu(ns->anagrpid)); - json_object_add_value_int(root, "endgid", le16_to_cpu(ns->endgid)); - - memset(eui64, 0, sizeof(eui64_buf)); - for (i = 0; i < sizeof(ns->eui64); i++) - eui64 += sprintf(eui64, "%02x", ns->eui64[i]); + 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]); + 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); + 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); @@ -330,28 +357,28 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, struct json_object *psd = json_create_object(); json_object_add_value_int(psd, "max_power", - le16_to_cpu(ctrl->psd[i].max_power)); + le16_to_cpu(ctrl->psd[i].mp)); json_object_add_value_int(psd, "flags", ctrl->psd[i].flags); json_object_add_value_uint(psd, "entry_lat", - le32_to_cpu(ctrl->psd[i].entry_lat)); + le32_to_cpu(ctrl->psd[i].enlat)); json_object_add_value_uint(psd, "exit_lat", - le32_to_cpu(ctrl->psd[i].exit_lat)); + le32_to_cpu(ctrl->psd[i].exlat)); json_object_add_value_int(psd, "read_tput", - ctrl->psd[i].read_tput); + ctrl->psd[i].rrt); json_object_add_value_int(psd, "read_lat", - ctrl->psd[i].read_lat); + ctrl->psd[i].rrl); json_object_add_value_int(psd, "write_tput", - ctrl->psd[i].write_tput); + ctrl->psd[i].rwt); json_object_add_value_int(psd, "write_lat", - ctrl->psd[i].write_lat); + ctrl->psd[i].rwl); json_object_add_value_int(psd, "idle_power", - le16_to_cpu(ctrl->psd[i].idle_power)); + le16_to_cpu(ctrl->psd[i].idlp)); json_object_add_value_int(psd, "idle_scale", - ctrl->psd[i].idle_scale); + ctrl->psd[i].ips); json_object_add_value_int(psd, "active_power", - le16_to_cpu(ctrl->psd[i].active_power)); + le16_to_cpu(ctrl->psd[i].actp)); json_object_add_value_int(psd, "active_work_scale", - ctrl->psd[i].active_work_scale); + nvme_psd_power_scale(ctrl->psd[i].apws)); json_array_add_value_object(psds, psd); } @@ -376,7 +403,7 @@ static void json_error_log(struct nvme_error_log_page *err_log, int entries) for (i = 0; i < entries; i++) { struct json_object *error = json_create_object(); - json_object_add_value_uint(error, "error_count", + json_object_add_value_uint64(error, "error_count", le64_to_cpu(err_log[i].error_count)); json_object_add_value_int(error, "sqid", le16_to_cpu(err_log[i].sqid)); @@ -388,13 +415,13 @@ static void json_error_log(struct nvme_error_log_page *err_log, int entries) le16_to_cpu(err_log[i].status_field & 0x1)); json_object_add_value_int(error, "parm_error_location", le16_to_cpu(err_log[i].parm_error_location)); - json_object_add_value_uint(error, "lba", + json_object_add_value_uint64(error, "lba", le64_to_cpu(err_log[i].lba)); json_object_add_value_uint(error, "nsid", le32_to_cpu(err_log[i].nsid)); json_object_add_value_int(error, "vs", err_log[i].vs); json_object_add_value_int(error, "trtype", err_log[i].trtype); - json_object_add_value_uint(error, "cs", + json_object_add_value_uint64(error, "cs", le64_to_cpu(err_log[i].cs)); json_object_add_value_int(error, "trtype_spec_info", le16_to_cpu(err_log[i].trtype_spec_info)); @@ -407,8 +434,8 @@ static void json_error_log(struct nvme_error_log_page *err_log, int entries) json_free_object(root); } -static void json_nvme_resv_report(struct nvme_reservation_status *status, - int bytes, __u32 cdw11) +static void json_nvme_resv_report(struct nvme_resv_status *status, + int bytes, bool eds) { struct json_object *root; struct json_object *rcs; @@ -425,7 +452,7 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status, rcs = json_create_array(); /* check Extended Data Structure bit */ - if ((cdw11 & 0x1) == 0) { + if (!eds) { /* * if status buffer was too small, don't loop past the end of * the buffer @@ -442,16 +469,15 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status, le16_to_cpu(status->regctl_ds[i].cntlid)); json_object_add_value_int(rc, "rcsts", status->regctl_ds[i].rcsts); - json_object_add_value_uint(rc, "hostid", + json_object_add_value_uint64(rc, "hostid", le64_to_cpu(status->regctl_ds[i].hostid)); - json_object_add_value_uint(rc, "rkey", + json_object_add_value_uint64(rc, "rkey", 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]; + char hostid[33]; /* if status buffer was too small, don't loop past the end of the buffer */ entries = (bytes - 64) / 64; @@ -463,14 +489,14 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status, struct json_object *rc = json_create_object(); json_object_add_value_int(rc, "cntlid", - le16_to_cpu(ext_status->regctl_eds[i].cntlid)); + le16_to_cpu(status->regctl_eds[i].cntlid)); json_object_add_value_int(rc, "rcsts", - ext_status->regctl_eds[i].rcsts); - json_object_add_value_uint(rc, "rkey", - le64_to_cpu(ext_status->regctl_eds[i].rkey)); + status->regctl_eds[i].rcsts); + json_object_add_value_uint64(rc, "rkey", + le64_to_cpu(status->regctl_eds[i].rkey)); for (j = 0; j < 16; j++) sprintf(hostid + j * 2, "%02x", - ext_status->regctl_eds[i].hostid[j]); + status->regctl_eds[i].hostid[j]); json_object_add_value_string(rc, "hostid", hostid); json_array_add_value_object(rcs, rc); @@ -482,28 +508,31 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status, json_free_object(root); } -static void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname) +static void json_fw_log(struct nvme_firmware_slot *fw_log, const char *devname) { - int i; struct json_object *root; struct json_object *fwsi; char fmt[21]; + char str[32]; + int i; + __le64 *frs; 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++) { - if (strcmp(fw_to_string(fw_log->frs[i]), "\0")) { + if (fw_log->frs[i][0]) { snprintf(fmt, sizeof(fmt), "Firmware Rev Slot %d", i + 1); - json_object_add_value_string(fwsi, fmt, - fw_to_string(fw_log->frs[i])); + frs = (__le64 *)&fw_log->frs[i]; + snprintf(str, sizeof(str), "%"PRIu64" (%s)", + le64_to_cpu(*frs), + 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); @@ -511,7 +540,7 @@ static void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devna json_free_object(root); } -static void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, +static void json_changed_ns_list_log(struct nvme_ns_list *log, const char *devname) { struct json_object *root; @@ -521,7 +550,7 @@ static void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, __u32 nsid; int i; - if (log->log[0] == cpu_to_le32(0xffffffff)) + if (log->ns[0] == cpu_to_le32(0xffffffff)) return; root = json_create_object(); @@ -530,8 +559,8 @@ static void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, json_object_add_value_string(root, "Changed Namespace List Log", devname); - for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) { - nsid = le32_to_cpu(log->log[i]); + for (i = 0; i < NVME_ID_NS_LIST_MAX; i++) { + nsid = le32_to_cpu(log->ns[i]); if (nsid == 0) break; @@ -687,10 +716,10 @@ static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, json_free_object(root); } -static void json_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname) +static void json_ana_log(struct nvme_ana_log *ana_log, const char *devname) { - int offset = sizeof(struct nvme_ana_rsp_hdr); - struct nvme_ana_rsp_hdr *hdr = ana_log; + int offset = sizeof(struct nvme_ana_log); + struct nvme_ana_log *hdr = ana_log; struct nvme_ana_group_desc *ana_desc; struct json_object *desc_list; struct json_object *ns_list; @@ -706,7 +735,7 @@ static void json_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname) json_object_add_value_string(root, "Asymmetric Namespace Access Log for NVMe device", devname); - json_object_add_value_uint(root, "chgcnt", + json_object_add_value_uint64(root, "chgcnt", le64_to_cpu(hdr->chgcnt)); json_object_add_value_uint(root, "ngrps", le16_to_cpu(hdr->ngrps)); @@ -755,12 +784,12 @@ static void json_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_en root = json_create_object(); json_object_add_value_int(root, "Current Device Self-Test Operation", - self_test->crnt_dev_selftest_oprn); + self_test->current_operation); json_object_add_value_int(root, "Current Device Self-Test Completion", - self_test->crnt_dev_selftest_compln); + self_test->completion); valid = json_create_array(); - num_entries = min(dst_entries, NVME_ST_REPORTS); + num_entries = min(dst_entries, NVME_LOG_ST_MAX_RESULTS); for (i = 0; i < num_entries; i++) { valid_attrs = json_create_object(); json_object_add_value_int(valid_attrs, "Self test result", @@ -773,18 +802,19 @@ static void json_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_en self_test->result[i].seg); json_object_add_value_int(valid_attrs, "Valid Diagnostic Information", self_test->result[i].vdi); - json_object_add_value_uint(valid_attrs, "Power on hours", + json_object_add_value_uint64(valid_attrs, "Power on hours", le64_to_cpu(self_test->result[i].poh)); - if (self_test->result[i].vdi & NVME_ST_VALID_NSID) + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_NSID) json_object_add_value_int(valid_attrs, "Namespace Identifier", le32_to_cpu(self_test->result[i].nsid)); - if (self_test->result[i].vdi & NVME_ST_VALID_FLBA) - json_object_add_value_uint(valid_attrs, "Failing LBA", + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_FLBA) { + json_object_add_value_uint64(valid_attrs, "Failing LBA", le64_to_cpu(self_test->result[i].flba)); - if (self_test->result[i].vdi & NVME_ST_VALID_SCT) + } + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_SCT) json_object_add_value_int(valid_attrs, "Status Code Type", self_test->result[i].sct); - if (self_test->result[i].vdi & NVME_ST_VALID_SC) + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_SC) json_object_add_value_int(valid_attrs, "Status Code", self_test->result[i].sc); json_object_add_value_int(valid_attrs, "Vendor Specific", @@ -799,7 +829,8 @@ add: json_free_object(root); } -static void json_effects_log(struct nvme_effects_log_page *effects_log) +struct json_object* json_effects_log(enum nvme_csi csi, + struct nvme_cmd_effects_log *effects_log) { struct json_object *root; struct json_object *acs; @@ -809,6 +840,8 @@ static void json_effects_log(struct nvme_effects_log_page *effects_log) __u32 effect; root = json_create_object(); + json_object_add_value_uint(root, "command_set_identifier", csi); + acs = json_create_object(); for (opcode = 0; opcode < 256; opcode++) { effect = le32_to_cpu(effects_log->acs[opcode]); @@ -832,9 +865,24 @@ static void json_effects_log(struct nvme_effects_log_page *effects_log) } json_object_add_value_object(root, "io_cmd_set", iocs); - json_print_object(root, NULL); + return root; +} + +void json_effects_log_list(struct list_head *list) { + struct json_object *json_list; + nvme_effects_log_node_t *node; + + json_list = json_create_array(); + + list_for_each(list, node, node) { + struct json_object *json_page = + json_effects_log(node->csi, &node->effects); + json_array_add_value_object(json_list, json_page); + } + + json_print_object(json_list, NULL); printf("\n"); - json_free_object(root); + json_free_object(json_list); } static void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, @@ -845,40 +893,41 @@ static void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, struct json_object *sstat; const char *status_str; char str[128]; - __u16 status = le16_to_cpu(sanitize_log->status); + __u16 status = le16_to_cpu(sanitize_log->sstat); root = json_create_object(); dev = json_create_object(); sstat = json_create_object(); json_object_add_value_int(dev, "sprog", - le16_to_cpu(sanitize_log->progress)); + le16_to_cpu(sanitize_log->sprog)); json_object_add_value_int(sstat, "global_erased", - (status & NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED) >> 8); + (status & NVME_SANITIZE_SSTAT_GLOBAL_DATA_ERASED) >> 8); json_object_add_value_int(sstat, "no_cmplted_passes", - (status & NVME_SANITIZE_LOG_NUM_CMPLTED_PASS_MASK) >> 3); + (status >> NVME_SANITIZE_SSTAT_COMPLETED_PASSES_SHIFT) & + NVME_SANITIZE_SSTAT_COMPLETED_PASSES_MASK); status_str = get_sanitize_log_sstat_status_str(status); - sprintf(str, "(%d) %s", status & NVME_SANITIZE_LOG_STATUS_MASK, + sprintf(str, "(%d) %s", status & NVME_SANITIZE_SSTAT_STATUS_MASK, status_str); json_object_add_value_string(sstat, "status", str); json_object_add_value_object(dev, "sstat", sstat); json_object_add_value_uint(dev, "cdw10_info", - le32_to_cpu(sanitize_log->cdw10_info)); + le32_to_cpu(sanitize_log->scdw10)); json_object_add_value_uint(dev, "time_over_write", - le32_to_cpu(sanitize_log->est_ovrwrt_time)); + le32_to_cpu(sanitize_log->eto)); json_object_add_value_uint(dev, "time_block_erase", - le32_to_cpu(sanitize_log->est_blk_erase_time)); + le32_to_cpu(sanitize_log->etbe)); json_object_add_value_uint(dev, "time_crypto_erase", - le32_to_cpu(sanitize_log->est_crypto_erase_time)); + le32_to_cpu(sanitize_log->etce)); json_object_add_value_uint(dev, "time_over_write_no_dealloc", - le32_to_cpu(sanitize_log->est_ovrwrt_time_with_no_deallocate)); + le32_to_cpu(sanitize_log->etond)); json_object_add_value_uint(dev, "time_block_erase_no_dealloc", - le32_to_cpu(sanitize_log->est_blk_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize_log->etbend)); json_object_add_value_uint(dev, "time_crypto_erase_no_dealloc", - le32_to_cpu(sanitize_log->est_crypto_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize_log->etcend)); json_object_add_value_object(root, devname, dev); json_print_object(root, NULL); @@ -886,8 +935,8 @@ static void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, json_free_object(root); } -void json_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, +static void json_predictable_latency_per_nvmset( + struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id) { struct json_object *root; @@ -899,22 +948,22 @@ void json_predictable_latency_per_nvmset( plpns_log->status); json_object_add_value_uint(root, "event_type", le16_to_cpu(plpns_log->event_type)); - json_object_add_value_uint(root, "dtwin_reads_typical", - le64_to_cpu(plpns_log->dtwin_rtyp)); - json_object_add_value_uint(root, "dtwin_writes_typical", - le64_to_cpu(plpns_log->dtwin_wtyp)); - json_object_add_value_uint(root, "dtwin_time_maximum", - le64_to_cpu(plpns_log->dtwin_timemax)); - json_object_add_value_uint(root, "ndwin_time_minimum_high", - le64_to_cpu(plpns_log->ndwin_timemin_high)); - json_object_add_value_uint(root, "ndwin_time_minimum_low", - le64_to_cpu(plpns_log->ndwin_timemin_low)); - json_object_add_value_uint(root, "dtwin_reads_estimate", - le64_to_cpu(plpns_log->dtwin_restimate)); - json_object_add_value_uint(root, "dtwin_writes_estimate", - le64_to_cpu(plpns_log->dtwin_westimate)); - json_object_add_value_uint(root, "dtwin_time_estimate", - le64_to_cpu(plpns_log->dtwin_testimate)); + json_object_add_value_uint64(root, "dtwin_reads_typical", + le64_to_cpu(plpns_log->dtwin_rt)); + json_object_add_value_uint64(root, "dtwin_writes_typical", + le64_to_cpu(plpns_log->dtwin_wt)); + json_object_add_value_uint64(root, "dtwin_time_maximum", + le64_to_cpu(plpns_log->dtwin_tmax)); + json_object_add_value_uint64(root, "ndwin_time_minimum_high", + le64_to_cpu(plpns_log->ndwin_tmin_hi)); + json_object_add_value_uint64(root, "ndwin_time_minimum_low", + le64_to_cpu(plpns_log->ndwin_tmin_lo)); + json_object_add_value_uint64(root, "dtwin_reads_estimate", + le64_to_cpu(plpns_log->dtwin_re)); + json_object_add_value_uint64(root, "dtwin_writes_estimate", + le64_to_cpu(plpns_log->dtwin_we)); + json_object_add_value_uint64(root, "dtwin_time_estimate", + le64_to_cpu(plpns_log->dtwin_te)); json_print_object(root, NULL); printf("\n"); @@ -922,7 +971,7 @@ void json_predictable_latency_per_nvmset( } void nvme_show_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, + struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id, const char *devname, enum nvme_print_flags flags) { @@ -941,25 +990,25 @@ void nvme_show_predictable_latency_per_nvmset( printf("Event Type: %u\n", le16_to_cpu(plpns_log->event_type)); printf("DTWIN Reads Typical: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_rtyp)); + le64_to_cpu(plpns_log->dtwin_rt)); printf("DTWIN Writes Typical: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_wtyp)); + le64_to_cpu(plpns_log->dtwin_wt)); printf("DTWIN Time Maximum: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_timemax)); + le64_to_cpu(plpns_log->dtwin_tmax)); printf("NDWIN Time Minimum High: %"PRIu64" \n", - le64_to_cpu(plpns_log->ndwin_timemin_high)); + le64_to_cpu(plpns_log->ndwin_tmin_hi)); printf("NDWIN Time Minimum Low: %"PRIu64"\n", - le64_to_cpu(plpns_log->ndwin_timemin_low)); + le64_to_cpu(plpns_log->ndwin_tmin_lo)); printf("DTWIN Reads Estimate: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_restimate)); + le64_to_cpu(plpns_log->dtwin_re)); printf("DTWIN Writes Estimate: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_westimate)); + le64_to_cpu(plpns_log->dtwin_we)); printf("DTWIN Time Estimate: %"PRIu64"\n\n\n", - le64_to_cpu(plpns_log->dtwin_testimate)); + le64_to_cpu(plpns_log->dtwin_te)); } -void json_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, +static void json_predictable_latency_event_agg_log( + struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries) { struct json_object *root; @@ -970,7 +1019,7 @@ void json_predictable_latency_event_agg_log( root = json_create_object(); num_entries = le64_to_cpu(pea_log->num_entries); - json_object_add_value_uint(root, "num_entries_avail", + json_object_add_value_uint64(root, "num_entries_avail", num_entries); valid = json_create_array(); @@ -988,7 +1037,7 @@ void json_predictable_latency_event_agg_log( } void nvme_show_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, + struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags) { @@ -1015,6 +1064,26 @@ void nvme_show_predictable_latency_event_agg_log( } } +const char *nvme_pel_event_to_string(int type) +{ + switch (type) { + case NVME_PEL_SMART_HEALTH_EVENT: return "SMART/Health Log Snapshot Event(0x1)"; + case NVME_PEL_FW_COMMIT_EVENT: return "Firmware Commit Event(0x2)"; + case NVME_PEL_TIMESTAMP_EVENT: return "Timestamp Change Event(0x3)"; + case NVME_PEL_POWER_ON_RESET_EVENT: return "Power-on or Reset Event(0x4)"; + case NVME_PEL_NSS_HW_ERROR_EVENT: return "NVM Subsystem Hardware Error Event(0x5)"; + case NVME_PEL_CHANGE_NS_EVENT: return "Change Namespace Event(0x6)"; + case NVME_PEL_FORMAT_START_EVENT: return "Format NVM Start Event(0x7)"; + case NVME_PEL_FORMAT_COMPLETION_EVENT: return "Format NVM Completion Event(0x8)"; + case NVME_PEL_SANITIZE_START_EVENT: return "Sanitize Start Event(0x9)"; + case NVME_PEL_SANITIZE_COMPLETION_EVENT: return "Sanitize Completion Event(0xa)"; + case NVME_PEL_SET_FEATURE_EVENT: return "Set Feature Event(0xb)"; + case NVME_PEL_TELEMETRY_CRT: return "Set Telemetry CRT Event(0xc)"; + case NVME_PEL_THERMAL_EXCURSION_EVENT: return "Thermal Excursion Event(0xd)"; + default: return NULL; + } +} + static const char *nvme_show_nss_hw_error(__u16 error_code) { switch (error_code) { @@ -1043,7 +1112,30 @@ static const char *nvme_show_nss_hw_error(__u16 error_code) } } -void json_persistent_event_log(void *pevent_log_info, __u32 size) +static void add_bitmap(int i, __u8 seb, struct json_object *root, int json_flag) +{ + char evt_str[50]; + char key[128]; + + for (int bit = 0; bit < 8; bit++) { + if (nvme_pel_event_to_string(bit + i * 8)) { + if (json_flag == 1) { + sprintf(key, "bitmap_%x", (bit + i * 8)); + if ((seb >> bit) & 0x1) + snprintf(evt_str, sizeof(evt_str), "Support %s", + nvme_pel_event_to_string(bit + i * 8)); + json_object_add_value_string(root, key, evt_str); + } else { + if (nvme_pel_event_to_string(bit + i * 8)) + if ((seb >> bit) & 0x1) + printf(" Support %s\n", + nvme_pel_event_to_string(bit + i * 8)); + } + } + } +} + +static void json_persistent_event_log(void *pevent_log_info, __u32 size) { struct json_object *root; struct json_object *valid_attrs; @@ -1051,19 +1143,21 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) __u32 offset, por_info_len, por_info_list; __u64 *fw_rev; char key[128]; + char fw_str[50]; + struct nvme_smart_log *smart_event; struct nvme_fw_commit_event *fw_commit_event; struct nvme_time_stamp_change_event *ts_change_event; struct nvme_power_on_reset_info_list *por_event; struct nvme_nss_hw_err_event *nss_hw_err_event; - struct nvme_change_ns_event *ns_event; + struct nvme_change_ns_event *ns_event; struct nvme_format_nvm_start_event *format_start_event; struct nvme_format_nvm_compln_event *format_cmpln_event; struct nvme_sanitize_start_event *sanitize_start_event; struct nvme_sanitize_compln_event *sanitize_cmpln_event; struct nvme_thermal_exc_event *thermal_exc_event; - struct nvme_persistent_event_log_head *pevent_log_head; - struct nvme_persistent_event_entry_head *pevent_entry_head; + struct nvme_persistent_event_log *pevent_log_head; + struct nvme_persistent_event_entry *pevent_entry_head; root = json_create_object(); valid = json_create_array(); @@ -1083,20 +1177,20 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) (int)sizeof(pevent_log_head->subnqn), pevent_log_head->subnqn); json_object_add_value_uint(root, "log_id", - pevent_log_head->log_id); + pevent_log_head->lid); json_object_add_value_uint(root, "total_num_of_events", le32_to_cpu(pevent_log_head->tnev)); - json_object_add_value_uint(root, "total_log_len", + json_object_add_value_uint64(root, "total_log_len", le64_to_cpu(pevent_log_head->tll)); json_object_add_value_uint(root, "log_revision", - pevent_log_head->log_rev); + pevent_log_head->rv); json_object_add_value_uint(root, "log_header_len", - le16_to_cpu(pevent_log_head->head_len)); - json_object_add_value_uint(root, "timestamp", - le64_to_cpu(pevent_log_head->timestamp)); + le16_to_cpu(pevent_log_head->lhl)); + json_object_add_value_uint64(root, "timestamp", + le64_to_cpu(pevent_log_head->ts)); json_object_add_value_float(root, "power_on_hours", int128_to_double(pevent_log_head->poh)); - json_object_add_value_uint(root, "power_cycle_count", + json_object_add_value_uint64(root, "power_cycle_count", le64_to_cpu(pevent_log_head->pcc)); json_object_add_value_uint(root, "pci_vid", le16_to_cpu(pevent_log_head->vid)); @@ -1110,11 +1204,9 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(root, "rci", le32_to_cpu(pevent_log_head->rci)); for (int i = 0; i < 32; i++) { - if (pevent_log_head->supp_event_bm[i] == 0) + if (pevent_log_head->seb[i] == 0) continue; - sprintf(key, "bitmap_%d", i); - json_object_add_value_uint(root, key, - pevent_log_head->supp_event_bm[i]); + add_bitmap(i, pevent_log_head->seb[i], root, 1); } } else { printf("No log data can be shown with this log len at least " \ @@ -1132,17 +1224,22 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) le16_to_cpu(pevent_entry_head->el)) >= size) break; valid_attrs = json_create_object(); - - json_object_add_value_uint(valid_attrs, "event_type", - pevent_entry_head->etype); + + json_object_add_value_uint(valid_attrs, "event_number", i); + json_object_add_value_string(valid_attrs, "event_type", + nvme_pel_event_to_string(pevent_entry_head->etype)); json_object_add_value_uint(valid_attrs, "event_type_rev", pevent_entry_head->etype_rev); json_object_add_value_uint(valid_attrs, "event_header_len", pevent_entry_head->ehl); + json_object_add_value_uint(valid_attrs, "event_header_additional_info", + pevent_entry_head->ehai); json_object_add_value_uint(valid_attrs, "ctrl_id", - le16_to_cpu(pevent_entry_head->ctrl_id)); - json_object_add_value_uint(valid_attrs, "event_time_stamp", - le64_to_cpu(pevent_entry_head->etimestamp)); + le16_to_cpu(pevent_entry_head->cntlid)); + json_object_add_value_uint64(valid_attrs, "event_time_stamp", + le64_to_cpu(pevent_entry_head->ets)); + json_object_add_value_uint(valid_attrs, "port_id", + le16_to_cpu(pevent_entry_head->pelpid)); json_object_add_value_uint(valid_attrs, "vu_info_len", le16_to_cpu(pevent_entry_head->vsil)); json_object_add_value_uint(valid_attrs, "event_len", @@ -1151,7 +1248,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) offset += pevent_entry_head->ehl + 3; switch (pevent_entry_head->etype) { - case NVME_SMART_HEALTH_EVENT: + case NVME_PEL_SMART_HEALTH_EVENT: smart_event = pevent_log_info + offset; unsigned int temperature = ((smart_event->temperature[1] << 8) | smart_event->temperature[0]); @@ -1222,12 +1319,16 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "thm_temp2_total_time", le32_to_cpu(smart_event->thm_temp2_total_time)); break; - case NVME_FW_COMMIT_EVENT: + case NVME_PEL_FW_COMMIT_EVENT: fw_commit_event = pevent_log_info + offset; - json_object_add_value_uint(valid_attrs, "old_fw_rev", - le64_to_cpu(fw_commit_event->old_fw_rev)); - json_object_add_value_uint(valid_attrs, "new_fw_rev", - le64_to_cpu(fw_commit_event->new_fw_rev)); + snprintf(fw_str, sizeof(fw_str), "%"PRIu64" (%s)", + le64_to_cpu(fw_commit_event->old_fw_rev), + fw_to_string((char *)&fw_commit_event->old_fw_rev)); + json_object_add_value_string(valid_attrs, "old_fw_rev", fw_str); + snprintf(fw_str, sizeof(fw_str), "%"PRIu64" (%s)", + le64_to_cpu(fw_commit_event->new_fw_rev), + fw_to_string((char *)&fw_commit_event->new_fw_rev)); + json_object_add_value_string(valid_attrs, "new_fw_rev", fw_str); json_object_add_value_uint(valid_attrs, "fw_commit_action", fw_commit_event->fw_commit_action); json_object_add_value_uint(valid_attrs, "fw_slot", @@ -1240,23 +1341,25 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) "vu_assign_fw_commit_rc", le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc)); break; - case NVME_TIMESTAMP_EVENT: + case NVME_PEL_TIMESTAMP_EVENT: ts_change_event = pevent_log_info + offset; - json_object_add_value_uint(valid_attrs, "prev_ts", + json_object_add_value_uint64(valid_attrs, "prev_ts", le64_to_cpu(ts_change_event->previous_timestamp)); - json_object_add_value_uint(valid_attrs, + json_object_add_value_uint64(valid_attrs, "ml_secs_since_reset", le64_to_cpu(ts_change_event->ml_secs_since_reset)); break; - case NVME_POWER_ON_RESET_EVENT: + case NVME_PEL_POWER_ON_RESET_EVENT: por_info_len = (le16_to_cpu(pevent_entry_head->el) - le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev)); por_info_list = por_info_len / sizeof(*por_event); fw_rev = pevent_log_info + offset; - json_object_add_value_uint(valid_attrs, "fw_rev", - le64_to_cpu(*fw_rev)); + snprintf(fw_str, sizeof(fw_str), "%"PRIu64" (%s)", + le64_to_cpu(*fw_rev), + fw_to_string((char *)fw_rev)); + json_object_add_value_string(valid_attrs, "fw_rev", fw_str); for (int i = 0; i < por_info_list; i++) { por_event = pevent_log_info + offset + sizeof(*fw_rev) + i * sizeof(*por_event); @@ -1268,24 +1371,24 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) por_event->op_in_prog); json_object_add_value_uint(valid_attrs, "ctrl_power_cycle", le32_to_cpu(por_event->ctrl_power_cycle)); - json_object_add_value_uint(valid_attrs, "power_on_ml_secs", + json_object_add_value_uint64(valid_attrs, "power_on_ml_secs", le64_to_cpu(por_event->power_on_ml_seconds)); - json_object_add_value_uint(valid_attrs, "ctrl_time_stamp", + json_object_add_value_uint64(valid_attrs, "ctrl_time_stamp", le64_to_cpu(por_event->ctrl_time_stamp)); } break; - case NVME_NSS_HW_ERROR_EVENT: + case NVME_PEL_NSS_HW_ERROR_EVENT: nss_hw_err_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nss_hw_err_code", le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code)); break; - case NVME_CHANGE_NS_EVENT: + case NVME_PEL_CHANGE_NS_EVENT: ns_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nsmgt_cdw10", le32_to_cpu(ns_event->nsmgt_cdw10)); - json_object_add_value_uint(valid_attrs, "nsze", + json_object_add_value_uint64(valid_attrs, "nsze", le64_to_cpu(ns_event->nsze)); - json_object_add_value_uint(valid_attrs, "nscap", + json_object_add_value_uint64(valid_attrs, "nscap", le64_to_cpu(ns_event->nscap)); json_object_add_value_uint(valid_attrs, "flbas", ns_event->flbas); @@ -1300,7 +1403,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "nsid", le32_to_cpu(ns_event->nsid)); break; - case NVME_FORMAT_START_EVENT: + case NVME_PEL_FORMAT_START_EVENT: format_start_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nsid", le32_to_cpu(format_start_event->nsid)); @@ -1309,7 +1412,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "format_nvm_cdw10", le32_to_cpu(format_start_event->format_nvm_cdw10)); break; - case NVME_FORMAT_COMPLETION_EVENT: + case NVME_PEL_FORMAT_COMPLETION_EVENT: format_cmpln_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nsid", le32_to_cpu(format_cmpln_event->nsid)); @@ -1322,7 +1425,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "status_field", le32_to_cpu(format_cmpln_event->status_field)); break; - case NVME_SANITIZE_START_EVENT: + case NVME_PEL_SANITIZE_START_EVENT: sanitize_start_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "SANICAP", le32_to_cpu(sanitize_start_event->sani_cap)); @@ -1331,7 +1434,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "sani_cdw11", le32_to_cpu(sanitize_start_event->sani_cdw11)); break; - case NVME_SANITIZE_COMPLETION_EVENT: + case NVME_PEL_SANITIZE_COMPLETION_EVENT: sanitize_cmpln_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "sani_prog", le16_to_cpu(sanitize_cmpln_event->sani_prog)); @@ -1340,7 +1443,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "cmpln_info", le16_to_cpu(sanitize_cmpln_event->cmpln_info)); break; - case NVME_THERMAL_EXCURSION_EVENT: + case NVME_PEL_THERMAL_EXCURSION_EVENT: thermal_exc_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "over_temp", thermal_exc_event->over_temp); @@ -1378,12 +1481,27 @@ static void nvme_show_persistent_event_log_rci(__le32 pel_header_rci) printf("\tReporting Context Port Identifier (RCPID): %#x\n\n", rcpid); } +static void nvme_show_persistent_event_entry_ehai(__u8 ehai) +{ + __u8 rsvd1 = (ehai & 0xfc) >> 2; + __u8 pit = ehai & 0x03; + + printf(" [7:2] : %#x\tReserved\n", rsvd1); + printf("\tPort Identifier Type (PIT): %u(%s)\n", pit, + (pit == 0x00) ? "PIT not reported and PELPID does not apply" : + (pit == 0x01) ? "NVM subsystem port" : + (pit == 0x10) ? "NVMe-MI port" : + (pit == 0x11) ? "Event not associated with any port and PELPID does not apply" : "Reserved"); +} + void nvme_show_persistent_event_log(void *pevent_log_info, __u8 action, __u32 size, const char *devname, enum nvme_print_flags flags) { __u32 offset, por_info_len, por_info_list; __u64 *fw_rev; + int fid, cdw11, dword_cnt; + unsigned char *mem_buf = NULL; struct nvme_smart_log *smart_event; struct nvme_fw_commit_event *fw_commit_event; struct nvme_time_stamp_change_event *ts_change_event; @@ -1394,9 +1512,10 @@ void nvme_show_persistent_event_log(void *pevent_log_info, struct nvme_format_nvm_compln_event *format_cmpln_event; struct nvme_sanitize_start_event *sanitize_start_event; struct nvme_sanitize_compln_event *sanitize_cmpln_event; + struct nvme_set_feature_event *set_feat_event; struct nvme_thermal_exc_event *thermal_exc_event; - struct nvme_persistent_event_log_head *pevent_log_head; - struct nvme_persistent_event_entry_head *pevent_entry_head; + struct nvme_persistent_event_log *pevent_log_head; + struct nvme_persistent_event_entry *pevent_entry_head; int human = flags & VERBOSE; if (flags & BINARY) @@ -1410,15 +1529,15 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Action for Persistent Event Log: %u\n", action); if (size >= offset) { pevent_log_head = pevent_log_info; - printf("Log Identifier: %u\n", pevent_log_head->log_id); + printf("Log Identifier: %u\n", pevent_log_head->lid); printf("Total Number of Events: %u\n", le32_to_cpu(pevent_log_head->tnev)); printf("Total Log Length : %"PRIu64"\n", le64_to_cpu(pevent_log_head->tll)); - printf("Log Revision: %u\n", pevent_log_head->log_rev); - printf("Log Header Length: %u\n", pevent_log_head->head_len); + printf("Log Revision: %u\n", pevent_log_head->rv); + printf("Log Header Length: %u\n", pevent_log_head->lhl); printf("Timestamp: %"PRIu64"\n", - le64_to_cpu(pevent_log_head->timestamp)); + le64_to_cpu(pevent_log_head->ts)); printf("Power On Hours (POH): %'.0Lf\n", int128_to_double(pevent_log_head->poh)); printf("Power Cycle Count: %"PRIu64"\n", @@ -1438,14 +1557,13 @@ void nvme_show_persistent_event_log(void *pevent_log_info, le16_to_cpu(pevent_log_head->gen_number)); printf("Reporting Context Information (RCI): %u\n", le32_to_cpu(pevent_log_head->rci)); - if(human) + if (human) nvme_show_persistent_event_log_rci(pevent_log_head->rci); - printf("Supported Events Bitmap: "); + printf("Supported Events Bitmap: \n"); for (int i = 0; i < 32; i++) { - if (pevent_log_head->supp_event_bm[i] == 0) + if (pevent_log_head->seb[i] == 0) continue; - printf("BitMap[%d] is 0x%x\n", i, - pevent_log_head->supp_event_bm[i]); + add_bitmap(i, pevent_log_head->seb[i], NULL, 0); } } else { printf("No log data can be shown with this log len at least " \ @@ -1464,14 +1582,19 @@ void nvme_show_persistent_event_log(void *pevent_log_info, if ((offset + pevent_entry_head->ehl + 3 + le16_to_cpu(pevent_entry_head->el)) >= size) break; - - printf("Event Type: %u\n", pevent_entry_head->etype); + printf("Event Number: %u\n", i); + printf("Event Type: %s\n", nvme_pel_event_to_string(pevent_entry_head->etype)); printf("Event Type Revision: %u\n", pevent_entry_head->etype_rev); printf("Event Header Length: %u\n", pevent_entry_head->ehl); + printf("Event Header Additional Info: %u\n", pevent_entry_head->ehai); + if (human) + nvme_show_persistent_event_entry_ehai(pevent_entry_head->ehai); printf("Controller Identifier: %u\n", - le16_to_cpu(pevent_entry_head->ctrl_id)); + le16_to_cpu(pevent_entry_head->cntlid)); printf("Event Timestamp: %"PRIu64"\n", - le64_to_cpu(pevent_entry_head->etimestamp)); + le64_to_cpu(pevent_entry_head->ets)); + printf("Port Identifier: %u\n", + le16_to_cpu(pevent_entry_head->pelpid)); printf("Vendor Specific Information Length: %u\n", le16_to_cpu(pevent_entry_head->vsil)); printf("Event Length: %u\n", le16_to_cpu(pevent_entry_head->el)); @@ -1479,18 +1602,20 @@ void nvme_show_persistent_event_log(void *pevent_log_info, offset += pevent_entry_head->ehl + 3; switch (pevent_entry_head->etype) { - case NVME_SMART_HEALTH_EVENT: + case NVME_PEL_SMART_HEALTH_EVENT: smart_event = pevent_log_info + offset; - printf("Smart Health Event: \n"); + printf("Smart Health Event Entry: \n"); nvme_show_smart_log(smart_event, NVME_NSID_ALL, devname, flags); break; - case NVME_FW_COMMIT_EVENT: + case NVME_PEL_FW_COMMIT_EVENT: fw_commit_event = pevent_log_info + offset; - printf("FW Commit Event: \n"); - printf("Old Firmware Revision: %"PRIu64"\n", - le64_to_cpu(fw_commit_event->old_fw_rev)); - printf("New Firmware Revision: %"PRIu64"\n", - le64_to_cpu(fw_commit_event->new_fw_rev)); + printf("FW Commit Event Entry: \n"); + printf("Old Firmware Revision: %"PRIu64" (%s)\n", + le64_to_cpu(fw_commit_event->old_fw_rev), + fw_to_string((char *)&fw_commit_event->old_fw_rev)); + printf("New Firmware Revision: %"PRIu64" (%s)\n", + le64_to_cpu(fw_commit_event->new_fw_rev), + fw_to_string((char *)&fw_commit_event->new_fw_rev)); printf("FW Commit Action: %u\n", fw_commit_event->fw_commit_action); printf("FW Slot: %u\n", fw_commit_event->fw_slot); @@ -1501,23 +1626,24 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Vendor Assigned Firmware Commit Result Code: %u\n", le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc)); break; - case NVME_TIMESTAMP_EVENT: + case NVME_PEL_TIMESTAMP_EVENT: ts_change_event = pevent_log_info + offset; - printf("Time Stamp Change Event: \n"); + printf("Time Stamp Change Event Entry: \n"); printf("Previous Timestamp: %"PRIu64"\n", le64_to_cpu(ts_change_event->previous_timestamp)); printf("Milliseconds Since Reset: %"PRIu64"\n", le64_to_cpu(ts_change_event->ml_secs_since_reset)); break; - case NVME_POWER_ON_RESET_EVENT: + case NVME_PEL_POWER_ON_RESET_EVENT: por_info_len = (le16_to_cpu(pevent_entry_head->el) - le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev)); por_info_list = por_info_len / sizeof(*por_event); - printf("Power On Reset Event: \n"); + printf("Power On Reset Event Entry: \n"); fw_rev = pevent_log_info + offset; - printf("Firmware Revision: %"PRIu64"\n", le64_to_cpu(*fw_rev)); + printf("Firmware Revision: %"PRIu64" (%s)\n", le64_to_cpu(*fw_rev), + fw_to_string((char *)fw_rev)); printf("Reset Information List: \n"); for (int i = 0; i < por_info_list; i++) { @@ -1536,15 +1662,15 @@ void nvme_show_persistent_event_log(void *pevent_log_info, le64_to_cpu(por_event->ctrl_time_stamp)); } break; - case NVME_NSS_HW_ERROR_EVENT: + case NVME_PEL_NSS_HW_ERROR_EVENT: nss_hw_err_event = pevent_log_info + offset; - printf("NVM Subsystem Hardware Error Event Code: %u, %s\n", + printf("NVM Subsystem Hardware Error Event Code Entry: %u, %s\n", le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code), nvme_show_nss_hw_error(nss_hw_err_event->nss_hw_err_event_code)); break; - case NVME_CHANGE_NS_EVENT: + case NVME_PEL_CHANGE_NS_EVENT: ns_event = pevent_log_info + offset; - printf("Change Namespace Event: \n"); + printf("Change Namespace Event Entry: \n"); printf("Namespace Management CDW10: %u\n", le32_to_cpu(ns_event->nsmgt_cdw10)); printf("Namespace Size: %"PRIu64"\n", @@ -1561,9 +1687,9 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("NVM Set Identifier: %u\n", le16_to_cpu(ns_event->nvmset_id)); printf("Namespace ID: %u\n", le32_to_cpu(ns_event->nsid)); break; - case NVME_FORMAT_START_EVENT: + case NVME_PEL_FORMAT_START_EVENT: format_start_event = pevent_log_info + offset; - printf("Format NVM Start Event: \n"); + printf("Format NVM Start Event Entry: \n"); printf("Namespace Identifier: %u\n", le32_to_cpu(format_start_event->nsid)); printf("Format NVM Attributes: %u\n", @@ -1571,9 +1697,9 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Format NVM CDW10: %u\n", le32_to_cpu(format_start_event->format_nvm_cdw10)); break; - case NVME_FORMAT_COMPLETION_EVENT: + case NVME_PEL_FORMAT_COMPLETION_EVENT: format_cmpln_event = pevent_log_info + offset; - printf("Format NVM Completion Event: \n"); + printf("Format NVM Completion Event Entry: \n"); printf("Namespace Identifier: %u\n", le32_to_cpu(format_cmpln_event->nsid)); printf("Smallest Format Progress Indicator: %u\n", @@ -1585,18 +1711,18 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Status Field: %u\n", le32_to_cpu(format_cmpln_event->status_field)); break; - case NVME_SANITIZE_START_EVENT: + case NVME_PEL_SANITIZE_START_EVENT: sanitize_start_event = pevent_log_info + offset; - printf("Sanitize Start Event: \n"); + printf("Sanitize Start Event Entry: \n"); printf("SANICAP: %u\n", sanitize_start_event->sani_cap); printf("Sanitize CDW10: %u\n", le32_to_cpu(sanitize_start_event->sani_cdw10)); printf("Sanitize CDW11: %u\n", le32_to_cpu(sanitize_start_event->sani_cdw11)); break; - case NVME_SANITIZE_COMPLETION_EVENT: + case NVME_PEL_SANITIZE_COMPLETION_EVENT: sanitize_cmpln_event = pevent_log_info + offset; - printf("Sanitize Completion Event: \n"); + printf("Sanitize Completion Event Entry: \n"); printf("Sanitize Progress: %u\n", le16_to_cpu(sanitize_cmpln_event->sani_prog)); printf("Sanitize Status: %u\n", @@ -1604,9 +1730,27 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Completion Information: %u\n", le16_to_cpu(sanitize_cmpln_event->cmpln_info)); break; - case NVME_THERMAL_EXCURSION_EVENT: + case NVME_PEL_SET_FEATURE_EVENT: + set_feat_event = pevent_log_info + offset; + printf("Set Feature Event Entry: \n"); + dword_cnt = set_feat_event->layout & 0x03; + fid = le32_to_cpu(set_feat_event->cdw_mem[0]) & 0x000f; + cdw11 = le32_to_cpu(set_feat_event->cdw_mem[1]); + + if (((set_feat_event->layout & 0xff) >> 2) != 0) + mem_buf = (unsigned char *)(set_feat_event + 4 + dword_cnt * 4); + + printf("Set Feature ID :%#02x (%s), value:%#08x\n", fid, + nvme_feature_to_string(fid), cdw11); + + nvme_feature_show_fields(fid, cdw11, mem_buf); + break; + case NVME_PEL_TELEMETRY_CRT: + d(pevent_log_info + offset, 512, 16, 1); + break; + case NVME_PEL_THERMAL_EXCURSION_EVENT: thermal_exc_event = pevent_log_info + offset; - printf("Thermal Excursion Event: \n"); + printf("Thermal Excursion Event Entry: \n"); printf("Over Temperature: %u\n", thermal_exc_event->over_temp); printf("Threshold: %u\n", thermal_exc_event->threshold); break; @@ -1619,7 +1763,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, } void json_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries) { struct json_object *root; @@ -1627,7 +1771,7 @@ void json_endurance_group_event_agg_log( struct json_object *valid; root = json_create_object(); - json_object_add_value_uint(root, "num_entries_avail", + json_object_add_value_uint64(root, "num_entries_avail", le64_to_cpu(endurance_log->num_entries)); valid = json_create_array(); @@ -1644,7 +1788,7 @@ void json_endurance_group_event_agg_log( } void nvme_show_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags) { @@ -1667,16 +1811,16 @@ void nvme_show_endurance_group_event_agg_log( } } -void json_lba_status_log(void *lba_status) +static void json_lba_status_log(void *lba_status) { struct json_object *root; struct json_object *desc; struct json_object *element; struct json_object *desc_list; struct json_object *elements_list; - struct nvme_lba_status_hdr *hdr; - struct nvme_lba_status_ns_element *ns_element; - struct nvme_lba_status_range_desc *range_desc; + struct nvme_lba_status_log *hdr; + struct nvme_lbas_ns_element *ns_element; + struct nvme_lba_rd *range_desc; int offset = sizeof(*hdr); __u32 num_lba_desc, num_elements; @@ -1704,7 +1848,7 @@ void json_lba_status_log(void *lba_status) for (int i = 0; i < num_lba_desc; i++) { range_desc = lba_status + offset; desc = json_create_object(); - json_object_add_value_uint(desc, "rslba", + json_object_add_value_uint64(desc, "rslba", le64_to_cpu(range_desc->rslba)); json_object_add_value_uint(desc, "rnlb", le32_to_cpu(range_desc->rnlb)); @@ -1730,9 +1874,9 @@ void json_lba_status_log(void *lba_status) void nvme_show_lba_status_log(void *lba_status, __u32 size, const char *devname, enum nvme_print_flags flags) { - struct nvme_lba_status_hdr *hdr; - struct nvme_lba_status_ns_element *ns_element; - struct nvme_lba_status_range_desc *range_desc; + struct nvme_lba_status_log *hdr; + struct nvme_lbas_ns_element *ns_element; + struct nvme_lba_rd *range_desc; int offset = sizeof(*hdr); __u32 num_lba_desc, num_elements; @@ -1787,17 +1931,17 @@ static const char *resv_notif_to_string(__u8 type) } } -static void json_resv_notif_log(struct nvme_resv_notif_log *resv) +static void json_resv_notif_log(struct nvme_resv_notification_log *resv) { struct json_object *root; root = json_create_object(); - json_object_add_value_uint(root, "count", - le64_to_cpu(resv->log_page_count)); + json_object_add_value_uint64(root, "count", + le64_to_cpu(resv->lpc)); json_object_add_value_uint(root, "rn_log_type", - resv->resv_notif_log_type); + resv->rnlpt); json_object_add_value_uint(root, "num_logs", - resv->num_logs); + resv->nalp); json_object_add_value_uint(root, "nsid", le32_to_cpu(resv->nsid)); @@ -1806,7 +1950,7 @@ static void json_resv_notif_log(struct nvme_resv_notif_log *resv) json_free_object(root); } -void nvme_show_resv_notif_log(struct nvme_resv_notif_log *resv, +void nvme_show_resv_notif_log(struct nvme_resv_notification_log *resv, const char *devname, enum nvme_print_flags flags) { if (flags & BINARY) @@ -1816,35 +1960,16 @@ void nvme_show_resv_notif_log(struct nvme_resv_notif_log *resv, printf("Reservation Notif Log for device: %s\n", devname); printf("Log Page Count : %"PRIx64"\n", - le64_to_cpu(resv->log_page_count)); + le64_to_cpu(resv->lpc)); printf("Resv Notif Log Page Type : %u (%s)\n", - resv->resv_notif_log_type, - resv_notif_to_string(resv->resv_notif_log_type)); - printf("Num of Available Log Pages : %u\n", resv->num_logs); + resv->rnlpt, + resv_notif_to_string(resv->rnlpt)); + printf("Num of Available Log Pages : %u\n", resv->nalp); printf("Namespace ID: : %"PRIx32"\n", le32_to_cpu(resv->nsid)); } -static void json_boot_part_log(void *bp_log) -{ - struct nvme_boot_part_hdr *hdr; - struct json_object *root; - - hdr = bp_log; - root = json_create_object(); - - json_object_add_value_uint(root, "count", hdr->lid); - json_object_add_value_uint(root, "abpid", - (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); - json_object_add_value_uint(root, "bpsz", - le32_to_cpu(hdr->bpinfo) & 0x7fff); - - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); -} - -static void json_fid_support_effects_log(struct nvme_fid_support_effects *fid_log) +static void json_fid_support_effects_log(struct nvme_fid_supported_effects_log *fid_log) { struct json_object *root; struct json_object *fids; @@ -1857,7 +1982,7 @@ static void json_fid_support_effects_log(struct nvme_fid_support_effects *fid_lo fids_list = json_create_array(); for (fid = 0; fid < 256; fid++) { fid_support = le32_to_cpu(fid_log->fid_support[fid]); - if (fid_support & NVME_FID_EFFECTS_FSUPP) { + if (fid_support & NVME_FID_SUPPORTED_EFFECTS_FSUPP) { fids = json_create_object(); sprintf(key, "fid_%u", fid); json_object_add_value_uint(fids, key, fid_support); @@ -1871,22 +1996,6 @@ static void json_fid_support_effects_log(struct nvme_fid_support_effects *fid_lo json_free_object(root); } -void nvme_show_boot_part_log(void *bp_log, const char *devname, - __u32 size, enum nvme_print_flags flags) -{ - struct nvme_boot_part_hdr *hdr; - if (flags & BINARY) - return d_raw((unsigned char *)bp_log, size); - if (flags & JSON) - return json_boot_part_log(bp_log); - - hdr = bp_log; - printf("Boot Partition Log for device: %s\n", devname); - printf("Log ID: %u\n", hdr->lid); - printf("Boot Partition Size: %u KiB\n", le32_to_cpu(hdr->bpinfo) & 0x7fff); - printf("Active BPID: %u\n", (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); -} - static void nvme_show_fid_support_effects_log_human(__u32 fid_support) { const char *set = "+"; @@ -1894,23 +2003,23 @@ static void nvme_show_fid_support_effects_log_human(__u32 fid_support) __u16 fsp; printf(" FSUPP+"); - printf(" UDCC%s", (fid_support & NVME_FID_EFFECTS_UDCC) ? set : clr); - printf(" NCC%s", (fid_support & NVME_FID_EFFECTS_NCC) ? set : clr); - printf(" NIC%s", (fid_support & NVME_FID_EFFECTS_NIC) ? set : clr); - printf(" CCC%s", (fid_support & NVME_FID_EFFECTS_CCC) ? set : clr); - printf(" USS%s", (fid_support & NVME_FID_EFFECTS_UUID_SEL) ? set : clr); + printf(" UDCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_UDCC) ? set : clr); + printf(" NCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_NCC) ? set : clr); + printf(" NIC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_NIC) ? set : clr); + printf(" CCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_CCC) ? set : clr); + printf(" USS%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_UUID_SEL) ? set : clr); - fsp = (fid_support >> NVME_FID_SCOPE_SHIFT) & NVME_FID_SCOPE_MASK; + fsp = (fid_support >> NVME_FID_SUPPORTED_EFFECTS_SCOPE_SHIFT) & NVME_FID_SUPPORTED_EFFECTS_SCOPE_MASK; - printf(" NAMESPACE SCOPE%s", (fsp & NVME_FID_SCOPE_NS) ? set : clr); - printf(" CONTROLLER SCOPE%s", (fsp & NVME_FID_SCOPE_CTRL) ? set : clr); - printf(" NVM SET SCOPE%s", (fsp & NVME_FID_SCOPE_NVM_SET) ? set : clr); - printf(" ENDURANCE GROUP SCOPE%s", (fsp & NVME_FID_SCOPE_ENDGRP) ? set : clr); - printf(" DOMAIN SCOPE%s", (fsp & NVME_FID_SCOPE_DOMAIN) ? set : clr); - printf(" NVM Subsystem SCOPE%s", (fsp & NVME_FID_SCOPE_NSS) ? set : clr); + printf(" NAMESPACE SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NS) ? set : clr); + printf(" CONTROLLER SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_CTRL) ? set : clr); + printf(" NVM SET SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NVM_SET) ? set : clr); + printf(" ENDURANCE GROUP SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_ENDGRP) ? set : clr); + printf(" DOMAIN SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_DOMAIN) ? set : clr); + printf(" NVM Subsystem SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NSS) ? set : clr); } -void nvme_show_fid_support_effects_log(struct nvme_fid_support_effects *fid_log, +void nvme_show_fid_support_effects_log(struct nvme_fid_supported_effects_log *fid_log, const char *devname, enum nvme_print_flags flags) { __u32 fid_effect; @@ -1925,7 +2034,7 @@ void nvme_show_fid_support_effects_log(struct nvme_fid_support_effects *fid_log, printf("Admin Command Set\n"); for (i = 0; i < 256; i++) { fid_effect = le32_to_cpu(fid_log->fid_support[i]); - if (fid_effect & NVME_FID_EFFECTS_FSUPP) { + if (fid_effect & NVME_FID_SUPPORTED_EFFECTS_FSUPP) { printf("FID %02x -> Support Effects Log: %08x", i, fid_effect); if (human) @@ -1936,86 +2045,489 @@ void nvme_show_fid_support_effects_log(struct nvme_fid_support_effects *fid_log, } } -static void nvme_show_subsystem(struct nvme_subsystem *s) +static void json_mi_cmd_support_effects_log(struct nvme_mi_cmd_supported_effects_log *mi_cmd_log) { + struct json_object *root; + struct json_object *mi_cmds; + struct json_object *mi_cmds_list; + unsigned int mi_cmd; + char key[128]; + __u32 mi_cmd_support; + + root = json_create_object(); + mi_cmds_list = json_create_array(); + for (mi_cmd = 0; mi_cmd < 256; mi_cmd++) { + mi_cmd_support = le32_to_cpu(mi_cmd_log->mi_cmd_support[mi_cmd]); + if (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_CSUPP) { + mi_cmds = json_create_object(); + sprintf(key, "mi_cmd_%u", mi_cmd); + json_object_add_value_uint(mi_cmds, key, mi_cmd_support); + json_array_add_value_object(mi_cmds_list, mi_cmds); + } + } + + json_object_add_value_object(root, "mi_command_support", mi_cmds_list); + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static void nvme_show_mi_cmd_support_effects_log_human(__u32 mi_cmd_support) +{ + const char *set = "+"; + const char *clr = "-"; + __u16 csp; + + printf(" CSUPP+"); + printf(" UDCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_UDCC) ? set : clr); + printf(" NCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_NCC) ? set : clr); + printf(" NIC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_NIC) ? set : clr); + printf(" CCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_CCC) ? set : clr); + + csp = (mi_cmd_support >> NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_SHIFT) & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_MASK; + + printf(" NAMESPACE SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NS) ? set : clr); + printf(" CONTROLLER SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_CTRL) ? set : clr); + printf(" NVM SET SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NVM_SET) ? set : clr); + printf(" ENDURANCE GROUP SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_ENDGRP) ? set : clr); + printf(" DOMAIN SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_DOMAIN) ? set : clr); + printf(" NVM Subsystem SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NSS) ? set : clr); +} + +void nvme_show_mi_cmd_support_effects_log(struct nvme_mi_cmd_supported_effects_log *mi_cmd_log, + const char *devname, enum nvme_print_flags flags) +{ + __u32 mi_cmd_effect; + int i, human = flags & VERBOSE; + + if (flags & BINARY) + return d_raw((unsigned char *)mi_cmd_log, sizeof(*mi_cmd_log)); + if (flags & JSON) + return json_mi_cmd_support_effects_log(mi_cmd_log); + + printf("MI Commands Support Effects Log for device: %s\n", devname); + printf("Admin Command Set\n"); + for (i = 0; i < NVME_LOG_MI_CMD_SUPPORTED_EFFECTS_MAX; i++) { + mi_cmd_effect = le32_to_cpu(mi_cmd_log->mi_cmd_support[i]); + if (mi_cmd_effect & NVME_MI_CMD_SUPPORTED_EFFECTS_CSUPP) { + printf("MI CMD %02x -> Support Effects Log: %08x", i, + mi_cmd_effect); + if (human) + nvme_show_mi_cmd_support_effects_log_human(mi_cmd_effect); + else + printf("\n"); + } + } +} + +static void json_boot_part_log(void *bp_log) +{ + struct nvme_boot_partition *hdr; + struct json_object *root; + + hdr = bp_log; + root = json_create_object(); + + json_object_add_value_uint(root, "count", hdr->lid); + json_object_add_value_uint(root, "abpid", + (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); + json_object_add_value_uint(root, "bpsz", + le32_to_cpu(hdr->bpinfo) & 0x7fff); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_boot_part_log(void *bp_log, const char *devname, + __u32 size, enum nvme_print_flags flags) +{ + struct nvme_boot_partition *hdr; + if (flags & BINARY) + return d_raw((unsigned char *)bp_log, size); + if (flags & JSON) + return json_boot_part_log(bp_log); + + hdr = bp_log; + printf("Boot Partition Log for device: %s\n", devname); + printf("Log ID: %u\n", hdr->lid); + printf("Boot Partition Size: %u KiB\n", le32_to_cpu(hdr->bpinfo) & 0x7fff); + printf("Active BPID: %u\n", (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); +} + +static void json_media_unit_stat_log(struct nvme_media_unit_stat_log *mus) +{ + struct json_object *root; + struct json_object *entries; + struct json_object *entry; int i; - printf("%s - NQN=%s\n", s->name, s->subsysnqn); - printf("\\\n"); + root = json_create_object(); + entries = json_create_array(); + + json_object_add_value_uint(root, "nmu", le16_to_cpu(mus->nmu)); + json_object_add_value_uint(root, "cchans", le16_to_cpu(mus->cchans)); + json_object_add_value_uint(root, "sel_config", le16_to_cpu(mus->sel_config)); - for (i = 0; i < s->nr_ctrls; i++) { - printf(" +- %s %s %s %s %s\n", s->ctrls[i].name, - s->ctrls[i].transport ? : "", - s->ctrls[i].address ? : "", - s->ctrls[i].state ? : "", - s->ctrls[i].ana_state ? : ""); + for (i = 0; i < mus->nmu; i++) { + entry = json_create_object(); + json_object_add_value_uint(entry, "muid", le16_to_cpu(mus->mus_desc[i].muid)); + json_object_add_value_uint(entry, "domainid", le16_to_cpu(mus->mus_desc[i].domainid)); + json_object_add_value_uint(entry, "endgid", le16_to_cpu(mus->mus_desc[i].endgid)); + json_object_add_value_uint(entry, "nvmsetid", le16_to_cpu(mus->mus_desc[i].nvmsetid)); + json_object_add_value_uint(entry, "cap_adj_fctr", le16_to_cpu(mus->mus_desc[i].cap_adj_fctr)); + json_object_add_value_uint(entry, "avl_spare", mus->mus_desc[i].avl_spare); + json_object_add_value_uint(entry, "percent_used", mus->mus_desc[i].percent_used); + json_object_add_value_uint(entry, "mucs", mus->mus_desc[i].mucs); + json_object_add_value_uint(entry, "cio", mus->mus_desc[i].cio); + json_array_add_value_object(entries, entry); } + + json_object_add_value_array(root, "mus_list", entries); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); } -static void json_print_nvme_subsystem_list(struct nvme_topology *t) +void nvme_show_media_unit_stat_log(struct nvme_media_unit_stat_log *mus_log, + enum nvme_print_flags flags) +{ + int i; + int nmu = le16_to_cpu(mus_log->nmu); + + if (flags & BINARY) + return d_raw((unsigned char *)mus_log, sizeof(*mus_log)); + else if (flags & JSON) + return json_media_unit_stat_log(mus_log); + + printf("Number of Media Unit Status Descriptors: %u\n", nmu); + printf("Number of Channels: %u\n", le16_to_cpu(mus_log->cchans)); + printf("Selected Configuration: %u\n", le16_to_cpu(mus_log->sel_config)); + for (i = 0; i < nmu; i++) { + printf("Media Unit Status Descriptor: %u\n", i); + printf("Media Unit Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].muid)); + printf("Domain Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].domainid)); + printf("Endurance Group Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].endgid)); + printf("NVM Set Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].nvmsetid)); + printf("Capacity Adjustment Factor: %u\n", + le16_to_cpu(mus_log->mus_desc[i].cap_adj_fctr)); + printf("Available Spare: %u\n", mus_log->mus_desc[i].avl_spare); + printf("Percentage Used: %u\n", mus_log->mus_desc[i].percent_used); + printf("Number of Channels: %u\n", mus_log->mus_desc[i].mucs); + printf("Channel Identifiers Offset: %u\n", mus_log->mus_desc[i].cio); + } +} + +static void json_supported_cap_config_log( + struct nvme_supported_cap_config_list_log *cap_log) { - struct json_object *subsystem_attrs, *path_attrs; - struct json_object *subsystems, *paths; struct json_object *root; - int i, j; + struct json_object *cap_list; + struct json_object *capacity; + struct json_object *end_list; + struct json_object *set_list; + struct json_object *set; + struct json_object *chan_list; + struct json_object *channel; + struct json_object *media_list; + struct json_object *media; + struct json_object *endurance; + struct nvme_end_grp_chan_desc *chan_desc; + int i, j, k, l, m, sccn, egcn, egsets, egchans, chmus; root = json_create_object(); - subsystems = json_create_array(); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; + json_object_add_value_uint(root, "sccn", cap_log->sccn); + cap_list = json_create_array(); + sccn = cap_log->sccn; + for (i = 0; i < sccn; i++) { + capacity = json_create_object(); + json_object_add_value_uint(capacity, "cap_config_id", + le16_to_cpu(cap_log->cap_config_desc[i].cap_config_id)); + json_object_add_value_uint(capacity, "domainid", + le16_to_cpu(cap_log->cap_config_desc[i].domainid)); + json_object_add_value_uint(capacity, "egcn", + le16_to_cpu(cap_log->cap_config_desc[i].egcn)); + end_list = json_create_array(); + egcn = le16_to_cpu(cap_log->cap_config_desc[i].egcn); + for (j = 0; j < egcn; j++) { + endurance = json_create_object(); + json_object_add_value_uint(endurance, "endgid", + le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].endgid)); + json_object_add_value_uint(endurance, "cap_adj_factor", + le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].cap_adj_factor)); + json_object_add_value_float(endurance, "tegcap", + int128_to_double(cap_log->cap_config_desc[i].egcd[j].tegcap)); + json_object_add_value_float(endurance, "segcap", + int128_to_double(cap_log->cap_config_desc[i].egcd[j].segcap)); + json_object_add_value_uint(endurance, "egsets", + le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].egsets)); + egsets = le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].egsets); + set_list = json_create_array(); + for (k = 0; k < egsets; k++) { + set = json_create_object(); + json_object_add_value_uint(set, "nvmsetid", + le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].nvmsetid[k])); + json_array_add_value_object(set_list, set); + } + chan_desc = (struct nvme_end_grp_chan_desc *) \ + ((cap_log->cap_config_desc[i].egcd[j].nvmsetid[0]) * (sizeof(__u16)*egsets)); + egchans = le16_to_cpu(chan_desc->egchans); + json_object_add_value_uint(endurance, "egchans", + le16_to_cpu(chan_desc->egchans)); + chan_list = json_create_array(); + for (l = 0; l < egchans; l++) { + channel = json_create_object(); + json_object_add_value_uint(channel, "chanid", + le16_to_cpu(chan_desc->chan_config_desc[l].chanid)); + json_object_add_value_uint(channel, "chmus", + le16_to_cpu(chan_desc->chan_config_desc[l].chmus)); + chmus = le16_to_cpu(chan_desc->chan_config_desc[l].chmus); + media_list = json_create_array(); + for (m = 0; m < chmus; m++) { + media = json_create_object(); + json_object_add_value_uint(media, "chanid", + le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].muid)); + json_object_add_value_uint(media, "chmus", + le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].mudl)); + json_array_add_value_object(media_list, media); + } + json_object_add_value_array(channel, "Media Descriptor", media_list); + json_array_add_value_object(chan_list, channel); + } + json_object_add_value_array(endurance, "Channel Descriptor", chan_list); + json_object_add_value_array(endurance, "NVM Set IDs", set_list); + json_array_add_value_object(end_list, endurance); + } + json_object_add_value_array(capacity, "Endurance Descriptor", end_list); + json_array_add_value_object(cap_list, capacity); + } - subsystem_attrs = json_create_object(); - json_object_add_value_string(subsystem_attrs, - "Name", s->name); - json_object_add_value_string(subsystem_attrs, - "NQN", s->subsysnqn); + json_object_add_value_array(root, "Capacity Descriptor", cap_list); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} - json_array_add_value_object(subsystems, subsystem_attrs); +void nvme_show_supported_cap_config_log( + struct nvme_supported_cap_config_list_log *cap, + enum nvme_print_flags flags) +{ + struct nvme_end_grp_chan_desc *chan_desc; + int i, j, k, l, m, sccn, egcn, egsets, egchans, chmus; - paths = json_create_array(); - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + if (flags & BINARY) + return d_raw((unsigned char *)cap, sizeof(*cap)); + else if (flags & JSON) + return json_supported_cap_config_log(cap); + + sccn = cap->sccn; + printf("Number of Supported Capacity Configurations: %u\n", sccn); + for (i = 0; i < sccn; i++) { + printf("Capacity Configuration Descriptor: %u\n", i); + printf("Capacity Configuration Identifier: %u\n", + le16_to_cpu(cap->cap_config_desc[i].cap_config_id)); + printf("Domain Identifier: %u\n", + le16_to_cpu(cap->cap_config_desc[i].domainid)); + egcn = le16_to_cpu(cap->cap_config_desc[i].egcn); + printf("Number of Endurance Group Configuration Descriptors: %u\n", egcn); + for(j = 0; j < egcn; j++) { + printf("Endurance Group Identifier: %u\n", + le16_to_cpu(cap->cap_config_desc[i].egcd[j].endgid)); + printf("Capacity Adjustment Factor: %u\n", + le16_to_cpu(cap->cap_config_desc[i].egcd[j].cap_adj_factor)); + printf("Total Endurance Group Capacity: %'.0Lf\n", + int128_to_double(cap->cap_config_desc[i].egcd[j].tegcap)); + printf("Spare Endurance Group Capacity: %'.0Lf\n", + int128_to_double(cap->cap_config_desc[i].egcd[j].segcap)); + printf("Endurance Estimate: %'.0Lf\n", + int128_to_double(cap->cap_config_desc[i].egcd[j].end_est)); + egsets = le16_to_cpu(cap->cap_config_desc[i].egcd[j].egsets); + printf("Number of NVM Sets: %u\n", egsets); + for(k = 0; k < egsets; k++) { + printf("NVM Set %d Identifier: %u\n", i, + le16_to_cpu(cap->cap_config_desc[i].egcd[j].nvmsetid[k])); + } + chan_desc = (struct nvme_end_grp_chan_desc *) \ + ((cap->cap_config_desc[i].egcd[j].nvmsetid[0]) * (sizeof(__u16)*egsets)); + egchans = le16_to_cpu(chan_desc->egchans); + printf("Number of Channels: %u\n", egchans); + for(l = 0; l < egchans; l++) { + printf("Channel Identifier: %u\n", + le16_to_cpu(chan_desc->chan_config_desc[l].chanid)); + chmus = le16_to_cpu(chan_desc->chan_config_desc[l].chmus); + printf("Number of Channel Media Units: %u\n", chmus); + for(m = 0; m < chmus; m++) { + printf("Media Unit Identifier: %u\n", + le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].muid)); + printf("Media Unit Descriptor Length: %u\n", + le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].mudl)); + } + } + } + } +} + +static unsigned int nvme_show_subsystem_multipath(nvme_subsystem_t s) +{ + nvme_ns_t n; + unsigned int i = 0; + + nvme_subsystem_for_each_ns(s, n) { + nvme_path_t p; + + nvme_namespace_for_each_path(n, p) { + nvme_ctrl_t c = nvme_path_get_ctrl(p); + + printf(" +- %s %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c), + nvme_path_get_ana_state(p)); + i++; + } + } + + return i; +} + +static void nvme_show_subsystem_ctrls(nvme_subsystem_t s) +{ + nvme_ctrl_t c; + + nvme_subsystem_for_each_ctrl(s, c) { + printf(" +- %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c)); + } +} + +static void nvme_show_subsystem(nvme_root_t r) +{ + nvme_host_t h; + + nvme_for_each_host(r, h) { + nvme_subsystem_t s; + + nvme_for_each_subsystem(h, s) { + printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); + printf("\\\n"); + + if (!nvme_show_subsystem_multipath(s)) + nvme_show_subsystem_ctrls(s); + } + } +} + +static unsigned int json_print_nvme_subsystem_multipath(nvme_subsystem_t s, + json_object *paths) +{ + nvme_ns_t n; + unsigned int i = 0; + + nvme_subsystem_for_each_ns(s, n) { + nvme_path_t p; + + nvme_namespace_for_each_path(n, p) { + struct json_object *path_attrs; + nvme_ctrl_t c = nvme_path_get_ctrl(p); path_attrs = json_create_object(); json_object_add_value_string(path_attrs, "Name", - c->name); - if (c->transport) - json_object_add_value_string(path_attrs, - "Transport", c->transport); - if (c->address) - json_object_add_value_string(path_attrs, - "Address", c->address); - if (c->state) - json_object_add_value_string(path_attrs, - "State", c->state); - if (c->ana_state) - json_object_add_value_string(path_attrs, - "ANAState", c->ana_state); + nvme_ctrl_get_name(c)); + json_object_add_value_string(path_attrs, "Transport", + nvme_ctrl_get_transport(c)); + json_object_add_value_string(path_attrs, "Address", + nvme_ctrl_get_address(c)); + json_object_add_value_string(path_attrs, "State", + nvme_ctrl_get_state(c)); + json_object_add_value_string(path_attrs, "ANAState", + nvme_path_get_ana_state(p)); json_array_add_value_object(paths, path_attrs); + i++; } - if (j) - json_object_add_value_array(subsystem_attrs, "Paths", - paths); } - if (i) - json_object_add_value_array(root, "Subsystems", subsystems); + return i; +} + +static void json_print_nvme_subsystem_ctrls(nvme_subsystem_t s, + json_object *paths) +{ + nvme_ctrl_t c; + + nvme_subsystem_for_each_ctrl(s, c) { + struct json_object *path_attrs; + + path_attrs = json_create_object(); + json_object_add_value_string(path_attrs, "Name", + nvme_ctrl_get_name(c)); + json_object_add_value_string(path_attrs, "Transport", + nvme_ctrl_get_transport(c)); + json_object_add_value_string(path_attrs, "Address", + nvme_ctrl_get_address(c)); + json_object_add_value_string(path_attrs, "State", + nvme_ctrl_get_state(c)); + json_array_add_value_object(paths, path_attrs); + } +} + +static void json_print_nvme_subsystem_list(nvme_root_t r) +{ + struct json_object *host_attrs, *subsystem_attrs; + struct json_object *subsystems, *paths; + struct json_object *root; + nvme_host_t h; + + root = json_create_array(); + + nvme_for_each_host(r, h) { + nvme_subsystem_t s; + + host_attrs = json_create_object(); + json_object_add_value_string(host_attrs, "HostNQN", + nvme_host_get_hostnqn(h)); + json_object_add_value_string(host_attrs, "HostID", + nvme_host_get_hostid(h)); + subsystems = json_create_array(); + nvme_for_each_subsystem(h, s) { + subsystem_attrs = json_create_object(); + json_object_add_value_string(subsystem_attrs, "Name", + nvme_subsystem_get_name(s)); + json_object_add_value_string(subsystem_attrs, "NQN", + nvme_subsystem_get_nqn(s)); + + json_array_add_value_object(subsystems, subsystem_attrs); + paths = json_create_array(); + + if (!json_print_nvme_subsystem_multipath(s, paths)) + json_print_nvme_subsystem_ctrls(s, paths); + + json_object_add_value_array(subsystem_attrs, "Paths", + paths); + } + json_object_add_value_array(host_attrs, "Subsystems", subsystems); + json_array_add_value_object(root, host_attrs); + } json_print_object(root, NULL); printf("\n"); json_free_object(root); } -void nvme_show_subsystem_list(struct nvme_topology *t, - enum nvme_print_flags flags) +void nvme_show_subsystem_list(nvme_root_t r, enum nvme_print_flags flags) { - int i; - if (flags & JSON) - return json_print_nvme_subsystem_list(t); - - for (i = 0; i < t->nr_subsystems; i++) - nvme_show_subsystem(&t->subsystems[i]); + return json_print_nvme_subsystem_list(r); + nvme_show_subsystem(r); } static void nvme_show_registers_cap(struct nvme_bar_cap *cap) @@ -2379,25 +2891,6 @@ static void nvme_show_registers_pmrmscu(uint32_t pmrmscu) pmrmscu); } -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) -{ - const volatile __u32 *p = addr; - __u32 low, high; - - low = le32_to_cpu(*p); - high = le32_to_cpu(*(p + 1)); - - return ((__u64) high << 32) | low; -} - static void json_ctrl_registers(void *bar) { uint64_t cap, asq, acq, bpmbl, cmbmsc; @@ -2623,7 +3116,7 @@ void nvme_show_single_property(int offset, uint64_t value64, int human) uint32_t value32; if (!human) { - if (is_64bit_reg(offset)) + if (nvme_is_64bit_reg(offset)) printf("property: 0x%02x (%s), value: %"PRIx64"\n", offset, nvme_register_to_string(offset), value64); @@ -2673,85 +3166,11 @@ void nvme_show_single_property(int offset, uint64_t value64, int human) void nvme_show_relatives(const char *name) { - unsigned id, i, nsid = NVME_NSID_ALL; - char *path = NULL; - bool block = true; - int ret; - - ret = sscanf(name, "nvme%dn%d", &id, &nsid); - switch (ret) { - case 1: - if (asprintf(&path, "/sys/class/nvme/%s", name) < 0) - path = NULL; - block = false; - break; - case 2: - if (asprintf(&path, "/sys/block/%s/device", name) < 0) - path = NULL; - break; - default: - return; - } - - if (!path) - return; - - if (block) { - struct nvme_topology t = { }; - char *subsysnqn; - int err; - - subsysnqn = get_nvme_subsnqn(path); - if (!subsysnqn) { - free(path); - return; - } - err = scan_subsystems(&t, subsysnqn, 0, 0, NULL); - if (err || t.nr_subsystems != 1) { - free(subsysnqn); - free(path); - return; - } - - fprintf(stderr, "Namespace %s has parent controller(s):", name); - for (i = 0; i < t.subsystems[0].nr_ctrls; i++) - fprintf(stderr, "%s%s", i ? ", " : "", - t.subsystems[0].ctrls[i].name); - fprintf(stderr, "\n\n"); - free(subsysnqn); - free_topology(&t); - } else { - struct dirent **paths; - bool comma = false; - int n, ns, cntlid; - - n = scandir(path, &paths, scan_ctrl_paths_filter, alphasort); - if (n < 0) { - free(path); - return; - } - - fprintf(stderr, "Controller %s has child namespace(s):", name); - for (i = 0; i < n; i++) { - if (sscanf(paths[i]->d_name, "nvme%dc%dn%d", - &id, &cntlid, &ns) != 3) { - if (sscanf(paths[i]->d_name, "nvme%dn%d", - &id, &ns) != 2) { - continue; - } - } - fprintf(stderr, "%snvme%dn%d", comma ? ", " : "", id, - ns); - comma = true; - } - fprintf(stderr, "\n\n"); - free(paths); - } - free(path); + /* XXX: TBD */ } -void d_json(unsigned char *buf, int len, int width, int group, - struct json_object *array) +static void d_json(unsigned char *buf, int len, int width, int group, + struct json_object *array) { int i, line_done = 0; char ascii[32 + 1]; @@ -2811,49 +3230,22 @@ void d_raw(unsigned char *buf, unsigned len) { unsigned i; for (i = 0; i < len; i++) - putchar(*(buf + i)); + putchar(*(buf+i)); } void nvme_show_status(__u16 status) { - fprintf(stderr, "NVMe status: %s(%#x)\n", nvme_status_to_string(status), - status); -} - -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--; - } + fprintf(stderr, "NVMe status: %s(%#x)\n", + nvme_status_to_string(status, false), status); } static const char *nvme_uuid_to_string(uuid_t uuid) { /* large enough to hold uuid str (37) + null-termination byte */ static char uuid_str[40]; -#ifdef LIBUUID + uuid_unparse_lower(uuid, uuid_str); -#else - static const char *hex_digits = "0123456789abcdef"; - char *p = &uuid_str[0]; - int i; - for (i = 0; i < 16; i++) { - *p++ = hex_digits[(uuid.b[i] & 0xf0) >> 4]; - *p++ = hex_digits[uuid.b[i] & 0x0f]; - if (i == 3 || i == 5 || i == 7 || i == 9) - *p++ = '-'; - } - *p = '\0'; -#endif return uuid_str; } @@ -3133,6 +3525,20 @@ static void nvme_show_id_ctrl_lpa(__u8 lpa) printf("\n"); } +static void nvme_show_id_ctrl_elpe(__u8 elpe) +{ + printf(" [7:0] : %d (0's based)\tError Log Page Entries (ELPE)\n", + elpe); + printf("\n"); +} + +static void nvme_show_id_ctrl_npss(__u8 npss) +{ + printf(" [7:0] : %d (0's based)\tNumber of Power States Support (NPSS)\n", + npss); + printf("\n"); +} + static void nvme_show_id_ctrl_avscc(__u8 avscc) { __u8 rsvd = (avscc & 0xFE) >> 1; @@ -3157,18 +3563,32 @@ static void nvme_show_id_ctrl_apsta(__u8 apsta) static void nvme_show_id_ctrl_wctemp(__le16 wctemp) { - printf(" [16:0] : %ld C (%u Kelvin)\tWarning temperature (WCTEMP)\n", + printf(" [15:0] : %ld°C (%u Kelvin)\tWarning Composite Temperature Threshold (WCTEMP)\n", kelvin_to_celsius(le16_to_cpu(wctemp)), le16_to_cpu(wctemp)); printf("\n"); } static void nvme_show_id_ctrl_cctemp(__le16 cctemp) { - printf(" [16:0] : %ld C (%u Kelvin)\tCritical temperature (CCTEMP)\n", + printf(" [15:0] : %ld°C (%u Kelvin)\tCritical Composite Temperature Threshold (CCTEMP)\n", kelvin_to_celsius(le16_to_cpu(cctemp)), le16_to_cpu(cctemp)); printf("\n"); } +static void nvme_show_id_ctrl_tnvmcap(__u8 *tnvmcap) +{ + printf("[127:0] : %.0Lf\tTotal NVM Capacity (TNVMCAP)\n", + int128_to_double(tnvmcap)); + printf("\n"); +} + +static void nvme_show_id_ctrl_unvmcap(__u8 *unvmcap) +{ + printf("[127:0] : %.0Lf\tUnallocated NVM Capacity (UNVMCAP)\n", + int128_to_double(unvmcap)); + printf("\n"); +} + void nvme_show_id_ctrl_rpmbs(__le32 ctrl_rpmbs) { __u32 rpmbs = le32_to_cpu(ctrl_rpmbs); @@ -3200,6 +3620,20 @@ static void nvme_show_id_ctrl_hctma(__le16 ctrl_hctma) printf("\n"); } +static void nvme_show_id_ctrl_mntmt(__le16 mntmt) +{ + printf(" [15:0] : %ld°C (%u Kelvin)\tMinimum Thermal Management Temperature (MNTMT)\n", + kelvin_to_celsius(le16_to_cpu(mntmt)), le16_to_cpu(mntmt)); + printf("\n"); +} + +static void nvme_show_id_ctrl_mxtmt(__le16 mxtmt) +{ + printf(" [15:0] : %ld°C (%u Kelvin)\tMaximum Thermal Management Temperature (MXTMT)\n", + kelvin_to_celsius(le16_to_cpu(mxtmt)), le16_to_cpu(mxtmt)); + printf("\n"); +} + static void nvme_show_id_ctrl_sanicap(__le32 ctrl_sanicap) { __u32 sanicap = le32_to_cpu(ctrl_sanicap); @@ -3234,7 +3668,7 @@ static void nvme_show_id_ctrl_sanicap(__le32 ctrl_sanicap) static void nvme_show_id_ctrl_anacap(__u8 anacap) { __u8 nz = (anacap & 0x80) >> 7; - __u8 grpid_change = (anacap & 0x40) >> 6; + __u8 grpid_static = (anacap & 0x40) >> 6; __u8 rsvd = (anacap & 0x20) >> 5; __u8 ana_change = (anacap & 0x10) >> 4; __u8 ana_persist_loss = (anacap & 0x08) >> 3; @@ -3245,7 +3679,7 @@ static void nvme_show_id_ctrl_anacap(__u8 anacap) printf(" [7:7] : %#x\tNon-zero group ID %sSupported\n", nz, nz ? "" : "Not "); printf(" [6:6] : %#x\tGroup ID does %schange\n", - grpid_change, grpid_change ? "" : "not "); + grpid_static, grpid_static ? "not " : ""); if (rsvd) printf(" [5:5] : %#x\tReserved\n", rsvd); printf(" [4:4] : %#x\tANA Change state %sSupported\n", @@ -3518,14 +3952,19 @@ static void nvme_show_id_ns_nsfeat(__u8 nsfeat) static void nvme_show_id_ns_flbas(__u8 flbas) { - __u8 rsvd = (flbas & 0xE0) >> 5; + __u8 rsvd = (flbas & 0x80) >> 7; + __u8 msb2_lbaf = (flbas & NVME_NS_FLBAS_HIGHER_MASK) >> 5; __u8 mdedata = (flbas & 0x10) >> 4; - __u8 lbaf = flbas & 0xF; + __u8 lsb4_lbaf = flbas & NVME_NS_FLBAS_LOWER_MASK; + if (rsvd) - printf(" [7:5] : %#x\tReserved\n", rsvd); + printf(" [7:7] : %#x\tReserved\n", rsvd); + printf(" [6:5] : %#x\tMost significant 2 bits of Current LBA Format Selected\n", + msb2_lbaf); 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(" [3:0] : %#x\tLeast significant 4 bits of Current LBA Format Selected\n", + lsb4_lbaf); printf("\n"); } @@ -3636,6 +4075,17 @@ static void nvme_show_id_ns_fpi(__u8 fpi) printf("\n"); } +static void nvme_show_id_ns_nsattr(__u8 nsattr) +{ + __u8 rsvd = (nsattr & 0xFE) >> 1; + __u8 write_protected = nsattr & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tNamespace %sWrite Protected\n", + write_protected, write_protected ? "" : "Not "); + printf("\n"); +} + static void nvme_show_id_ns_dlfeat(__u8 dlfeat) { __u8 rsvd = (dlfeat & 0xE0) >> 5; @@ -3656,83 +4106,99 @@ static void nvme_show_id_ns_dlfeat(__u8 dlfeat) } void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, - enum nvme_print_flags flags) + unsigned int lba_index, bool cap_only, enum nvme_print_flags flags) { - int human = flags & VERBOSE; + bool human = flags & VERBOSE; int vs = flags & VS; int i; + __u8 flbas; + char *in_use = "(in use)"; if (flags & BINARY) return d_raw((unsigned char *)ns, sizeof(*ns)); if (flags & JSON) - return json_nvme_id_ns(ns); + return json_nvme_id_ns(ns, cap_only); + + if (!cap_only) { + printf("NVME Identify Namespace %d:\n", nsid); + printf("nsze : %#"PRIx64"\n", le64_to_cpu(ns->nsze)); + printf("ncap : %#"PRIx64"\n", le64_to_cpu(ns->ncap)); + printf("nuse : %#"PRIx64"\n", le64_to_cpu(ns->nuse)); + printf("nsfeat : %#x\n", ns->nsfeat); + if (human) + nvme_show_id_ns_nsfeat(ns->nsfeat); + } else + printf("NVMe Identify Namespace for LBA format[%d]:\n", lba_index); - printf("NVME Identify Namespace %d:\n", nsid); - printf("nsze : %#"PRIx64"\n", le64_to_cpu(ns->nsze)); - printf("ncap : %#"PRIx64"\n", le64_to_cpu(ns->ncap)); - printf("nuse : %#"PRIx64"\n", le64_to_cpu(ns->nuse)); - printf("nsfeat : %#x\n", ns->nsfeat); - if (human) - nvme_show_id_ns_nsfeat(ns->nsfeat); printf("nlbaf : %d\n", ns->nlbaf); - printf("flbas : %#x\n", ns->flbas); - if (human) - nvme_show_id_ns_flbas(ns->flbas); + if (!cap_only) { + printf("flbas : %#x\n", ns->flbas); + if (human) + nvme_show_id_ns_flbas(ns->flbas); + } else + in_use = ""; + printf("mc : %#x\n", ns->mc); if (human) nvme_show_id_ns_mc(ns->mc); printf("dpc : %#x\n", ns->dpc); if (human) nvme_show_id_ns_dpc(ns->dpc); - printf("dps : %#x\n", ns->dps); - if (human) - nvme_show_id_ns_dps(ns->dps); - printf("nmic : %#x\n", ns->nmic); - if (human) - nvme_show_id_ns_nmic(ns->nmic); - printf("rescap : %#x\n", ns->rescap); - if (human) - nvme_show_id_ns_rescap(ns->rescap); - printf("fpi : %#x\n", ns->fpi); - if (human) - nvme_show_id_ns_fpi(ns->fpi); - printf("dlfeat : %d\n", ns->dlfeat); - if (human) - nvme_show_id_ns_dlfeat(ns->dlfeat); - 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)); - if (ns->nsfeat & 0x10) { - printf("npwg : %u\n", le16_to_cpu(ns->npwg)); - printf("npwa : %u\n", le16_to_cpu(ns->npwa)); - printf("npdg : %u\n", le16_to_cpu(ns->npdg)); - printf("npda : %u\n", le16_to_cpu(ns->npda)); - printf("nows : %u\n", le16_to_cpu(ns->nows)); - } - printf("mssrl : %u\n", le16_to_cpu(ns->mssrl)); - printf("mcl : %d\n", le32_to_cpu(ns->mcl)); - printf("msrc : %u\n", ns->msrc); - printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); - printf("nsattr : %u\n", ns->nsattr); - printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); - printf("endgid : %d\n", le16_to_cpu(ns->endgid)); - - printf("nguid : "); - for (i = 0; i < 16; i++) - printf("%02x", ns->nguid[i]); - printf("\n"); + if (!cap_only) { + printf("dps : %#x\n", ns->dps); + if (human) + nvme_show_id_ns_dps(ns->dps); + printf("nmic : %#x\n", ns->nmic); + if (human) + nvme_show_id_ns_nmic(ns->nmic); + printf("rescap : %#x\n", ns->rescap); + if (human) + nvme_show_id_ns_rescap(ns->rescap); + printf("fpi : %#x\n", ns->fpi); + if (human) + nvme_show_id_ns_fpi(ns->fpi); + printf("dlfeat : %d\n", ns->dlfeat); + if (human) + nvme_show_id_ns_dlfeat(ns->dlfeat); + 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)); + if (ns->nsfeat & 0x10) { + printf("npwg : %u\n", le16_to_cpu(ns->npwg)); + printf("npwa : %u\n", le16_to_cpu(ns->npwa)); + printf("npdg : %u\n", le16_to_cpu(ns->npdg)); + printf("npda : %u\n", le16_to_cpu(ns->npda)); + printf("nows : %u\n", le16_to_cpu(ns->nows)); + } + printf("mssrl : %u\n", le16_to_cpu(ns->mssrl)); + printf("mcl : %d\n", le32_to_cpu(ns->mcl)); + printf("msrc : %u\n", ns->msrc); + } + printf("nulbaf : %u\n", ns->nulbaf); + if (!cap_only) { + printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); + printf("nsattr : %u\n", ns->nsattr); + printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); + printf("endgid : %d\n", le16_to_cpu(ns->endgid)); + + 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"); + printf("eui64 : "); + for (i = 0; i < 8; i++) + printf("%02x", ns->eui64[i]); + printf("\n"); + } - for (i = 0; i <= ns->nlbaf; i++) { + nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); + for (i = 0; i <= ns->nlbaf + ns->nulbaf; i++) { if (human) printf("LBA Format %2d : Metadata Size: %-3d bytes - " "Data Size: %-2d bytes - Relative Performance: %#x %s %s\n", @@ -3741,15 +4207,14 @@ void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, 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)" : ""); + i == flbas ? 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)" : ""); + ns->lbaf[i].rp, i == flbas ? in_use : ""); } - if (vs) { + if (vs && !cap_only) { printf("vs[]:\n"); d(ns->vs, sizeof(ns->vs), 16, 1); } @@ -3784,7 +4249,7 @@ static void nvme_show_cmd_set_independent_id_ns_nstat(__u8 nstat) } static void json_nvme_cmd_set_independent_id_ns( - struct nvme_cmd_set_independent_id_ns *ns) + struct nvme_id_independent_id_ns *ns) { struct json_object *root; root = json_create_object(); @@ -3805,7 +4270,7 @@ static void json_nvme_cmd_set_independent_id_ns( } void nvme_show_cmd_set_independent_id_ns( - struct nvme_cmd_set_independent_id_ns *ns, unsigned int nsid, + struct nvme_id_independent_id_ns *ns, unsigned int nsid, enum nvme_print_flags flags) { int human = flags & VERBOSE; @@ -3830,6 +4295,8 @@ void nvme_show_cmd_set_independent_id_ns( nvme_show_id_ns_fpi(ns->fpi); printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); printf("nsattr : %u\n", ns->nsattr); + if (human) + nvme_show_id_ns_nsattr(ns->nsattr); printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); printf("endgid : %d\n", le16_to_cpu(ns->endgid)); @@ -3847,10 +4314,7 @@ static void json_nvme_id_ns_descs(void *data) union { __u8 eui64[NVME_NIDT_EUI64_LEN]; __u8 nguid[NVME_NIDT_NGUID_LEN]; - -#ifdef LIBUUID uuid_t uuid; -#endif __u8 csi; } desc; @@ -3889,14 +4353,13 @@ static void json_nvme_id_ns_descs(void *data) nidt_name = "nguid"; break; -#ifdef LIBUUID case NVME_NIDT_UUID: memcpy(desc.uuid, data + off, sizeof(desc.uuid)); uuid_unparse_lower(desc.uuid, json_str); len = sizeof(desc.uuid); nidt_name = "uuid"; break; -#endif + case NVME_NIDT_CSI: memcpy(&desc.csi, data + off, sizeof(desc.csi)); json_str_p += sprintf(json_str_p, "%#x", desc.csi); @@ -3942,10 +4405,8 @@ void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flag { int pos, len = 0; int i; -#ifdef LIBUUID uuid_t uuid; char uuid_str[37]; -#endif __u8 eui64[8]; __u8 nguid[16]; __u8 csi; @@ -3979,14 +4440,12 @@ void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flag 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 case NVME_NIDT_CSI: memcpy(&csi, data + pos + sizeof(*cur), 1); printf("csi : %#x\n", csi); @@ -4032,35 +4491,35 @@ static void nvme_show_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); + __u16 max_power = le16_to_cpu(ctrl->psd[i].mp); printf("ps %4d : mp:", i); - if (ctrl->psd[i].flags & NVME_PS_FLAGS_MAX_POWER_SCALE) + if (ctrl->psd[i].flags & NVME_PSD_FLAGS_MXPS) 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) + if (ctrl->psd[i].flags & NVME_PSD_FLAGS_NOPS) 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)); + le32_to_cpu(ctrl->psd[i].enlat), + le32_to_cpu(ctrl->psd[i].exlat), + ctrl->psd[i].rrt, ctrl->psd[i].rrl, + ctrl->psd[i].rwt, ctrl->psd[i].rwl); + print_ps_power_and_scale(ctrl->psd[i].idlp, + nvme_psd_power_scale(ctrl->psd[i].ips)); printf(" active_power:"); - print_ps_power_and_scale(ctrl->psd[i].active_power, - POWER_SCALE(ctrl->psd[i].active_work_scale)); + print_ps_power_and_scale(ctrl->psd[i].actp, + nvme_psd_power_scale(ctrl->psd[i].apws)); printf("\n"); } } -void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, +void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, void (*vendor_show)(__u8 *vs, struct json_object *root)) { bool human = flags & VERBOSE, vs = flags & VS; @@ -4123,7 +4582,11 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, if (human) nvme_show_id_ctrl_lpa(ctrl->lpa); printf("elpe : %d\n", ctrl->elpe); + if (human) + nvme_show_id_ctrl_elpe(ctrl->elpe); printf("npss : %d\n", ctrl->npss); + if (human) + nvme_show_id_ctrl_npss(ctrl->npss); printf("avscc : %#x\n", ctrl->avscc); if (human) nvme_show_id_ctrl_avscc(ctrl->avscc); @@ -4140,7 +4603,11 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, 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)); + if (human) + nvme_show_id_ctrl_tnvmcap(ctrl->tnvmcap); printf("unvmcap : %.0Lf\n", int128_to_double(ctrl->unvmcap)); + if (human) + nvme_show_id_ctrl_unvmcap(ctrl->unvmcap); printf("rpmbs : %#x\n", le32_to_cpu(ctrl->rpmbs)); if (human) nvme_show_id_ctrl_rpmbs(ctrl->rpmbs); @@ -4152,7 +4619,11 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, if (human) nvme_show_id_ctrl_hctma(ctrl->hctma); printf("mntmt : %d\n", le16_to_cpu(ctrl->mntmt)); + if (human) + nvme_show_id_ctrl_mntmt(ctrl->mntmt); printf("mxtmt : %d\n", le16_to_cpu(ctrl->mxtmt)); + if (human) + nvme_show_id_ctrl_mxtmt(ctrl->mxtmt); printf("sanicap : %#x\n", le32_to_cpu(ctrl->sanicap)); if (human) nvme_show_id_ctrl_sanicap(ctrl->sanicap); @@ -4228,11 +4699,6 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, } } -void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode) -{ - __nvme_show_id_ctrl(ctrl, mode, NULL); -} - static void json_nvme_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm) { struct json_object *root; @@ -4243,7 +4709,7 @@ static void json_nvme_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm) json_object_add_value_uint(root, "wusl", ctrl_nvm->wusl); json_object_add_value_uint(root, "dmrl", ctrl_nvm->dmrl); json_object_add_value_uint(root, "dmrsl", le32_to_cpu(ctrl_nvm->dmrsl)); - json_object_add_value_uint(root, "dmsl", le64_to_cpu(ctrl_nvm->dmsl)); + json_object_add_value_uint64(root, "dmsl", le64_to_cpu(ctrl_nvm->dmsl)); json_print_object(root, NULL); printf("\n"); @@ -4267,6 +4733,95 @@ void nvme_show_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm, printf("dmsl : %"PRIu64"\n", le64_to_cpu(ctrl_nvm->dmsl)); } +static void json_nvme_nvm_id_ns(struct nvme_nvm_id_ns *nvm_ns, + struct nvme_id_ns *ns, bool cap_only) +{ + struct json_object *root; + struct json_object *elbafs; + int i; + + root = json_create_object(); + + if (!cap_only) { + json_object_add_value_uint64(root, "lbstm", le64_to_cpu(nvm_ns->lbstm)); + } + json_object_add_value_int(root, "pic", nvm_ns->pic); + + elbafs = json_create_array(); + json_object_add_value_array(root, "elbafs", elbafs); + + for (i = 0; i <= ns->nlbaf; i++) { + struct json_object *elbaf = json_create_object(); + unsigned int elbaf_val = le32_to_cpu(nvm_ns->elbaf[i]); + + json_object_add_value_int(elbaf, "sts", elbaf_val & 0x7F); + json_object_add_value_int(elbaf, "pif", (elbaf_val >> 7) & 0x3); + + json_array_add_value_object(elbafs, elbaf); + } + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void nvme_show_nvm_id_ns_pic(__u8 pic) +{ + __u8 rsvd = (pic & 0xFC) >> 2; + __u8 pic_16bpistm = (pic & 0x2) >> 1; + __u8 pic_16bpists = pic & 0x1; + + if (rsvd) + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\t16b Guard Protection Information Storage Tag Mask\n", + pic_16bpistm); + printf(" [0:0] : %#x\t16b Guard Protection Information Storage Tag Support\n", + pic_16bpists); + printf("\n"); +} + +void nvme_show_nvm_id_ns(struct nvme_nvm_id_ns *nvm_ns, unsigned int nsid, + struct nvme_id_ns *ns, unsigned int lba_index, + bool cap_only, enum nvme_print_flags flags) +{ + int i, verbose = flags & VERBOSE; + __u32 elbaf; + int pif, sts; + char *in_use = "(in use)"; + + if (flags & BINARY) + return d_raw((unsigned char *)nvm_ns, sizeof(*nvm_ns)); + else if (flags & JSON) + return json_nvme_nvm_id_ns(nvm_ns, ns, cap_only); + + if (!cap_only) { + printf("NVMe NVM Identify Namespace %d:\n", nsid); + printf("lbstm : %#"PRIx64"\n", le64_to_cpu(nvm_ns->lbstm)); + } else { + printf("NVMe NVM Identify Namespace for LBA format[%d]:\n", lba_index); + in_use = ""; + } + printf("pic : %#x\n", nvm_ns->pic); + if (verbose) + nvme_show_nvm_id_ns_pic(nvm_ns->pic); + + for (i = 0; i <= ns->nlbaf + ns->nulbaf; i++) { + elbaf = le32_to_cpu(nvm_ns->elbaf[i]); + pif = (elbaf >> 7) & 0x3; + sts = elbaf & 0x7f; + if (verbose) + printf("Extended LBA Format %2d : Protection Information Format: " + "%s(%d) - Storage Tag Size (MSB): %-2d %s\n", + i, pif == 3 ? "Reserved" : + pif == 2 ? "64b Guard" : + pif == 1 ? "32b Guard" : "16b Guard", + pif, sts, i == (ns->flbas & 0xf) ? in_use : ""); + else + printf("elbaf %2d : pif:%d lbads:%-2d %s\n", i, + pif, sts, i == (ns->flbas & 0xf) ? in_use : ""); + } +} + static void json_nvme_zns_id_ctrl(struct nvme_zns_id_ctrl *ctrl) { struct json_object *root; @@ -4290,7 +4845,7 @@ void nvme_show_zns_id_ctrl(struct nvme_zns_id_ctrl *ctrl, unsigned int mode) printf("zasl : %u\n", ctrl->zasl); } -void json_nvme_zns_id_ns(struct nvme_zns_id_ns *ns, +static void json_nvme_zns_id_ns(struct nvme_zns_id_ns *ns, struct nvme_id_ns *id_ns) { struct json_object *root; @@ -4310,6 +4865,10 @@ void json_nvme_zns_id_ns(struct nvme_zns_id_ns *ns, json_object_add_value_int(root, "frl1", le32_to_cpu(ns->frl1)); json_object_add_value_int(root, "frl2", le32_to_cpu(ns->frl2)); json_object_add_value_int(root, "frl3", le32_to_cpu(ns->frl3)); + json_object_add_value_int(root, "numzrwa", le32_to_cpu(ns->numzrwa)); + json_object_add_value_int(root, "zrwafg", le16_to_cpu(ns->zrwafg)); + json_object_add_value_int(root, "zrwasz", le16_to_cpu(ns->zrwasz)); + json_object_add_value_int(root, "zrwacap", ns->zrwacap); lbafs = json_create_array(); json_object_add_value_array(root, "lbafe", lbafs); @@ -4346,13 +4905,16 @@ static void show_nvme_id_ns_zoned_zoc(__le16 ns_zoc) static void show_nvme_id_ns_zoned_ozcs(__le16 ns_ozcs) { __u16 ozcs = le16_to_cpu(ns_ozcs); - __u8 rsvd = (ozcs & 0xfffe) >> 1; + __u8 rsvd = (ozcs & 0xfffc) >> 2; __u8 razb = ozcs & 0x1; + __u8 zrwasup = (ozcs & 0x2) >> 1; if (rsvd) printf(" [15:1] : %#x\tReserved\n", rsvd); printf(" [0:0] : %#x\t Read Across Zone Boundaries: %s\n", razb, razb ? "Yes" : "No"); + printf(" [1:1] : %#x\t Zone Random Write Area: %s\n", zrwasup, + zrwasup ? "Yes" : "No"); } static void nvme_show_zns_id_ns_recommandeded_limit(__le32 ns_rl, int human, @@ -4365,13 +4927,26 @@ static void nvme_show_zns_id_ns_recommandeded_limit(__le32 ns_rl, int human, printf("%s : %u\n", target_limit, recommandeded_limit); } +static void nvme_show_zns_id_ns_zrwacap(__u8 zrwacap) +{ + __u8 rsvd = (zrwacap & 0xfe) >> 1; + __u8 expflushsup = zrwacap & 0x1; + + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\t Explicit ZRWA Flush Operations: %s\n", + expflushsup, expflushsup ? "Yes" : "No"); +} + void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, struct nvme_id_ns *id_ns, unsigned long flags) { int human = flags & VERBOSE, vs = flags & VS; - uint8_t lbaf = id_ns->flbas & NVME_NS_FLBAS_LBA_MASK; + uint8_t lbaf; int i; + nvme_id_ns_flbas_to_lbaf_inuse(id_ns->flbas, &lbaf); + if (flags & BINARY) return d_raw((unsigned char *)ns, sizeof(*ns)); else if (flags & JSON) @@ -4422,6 +4997,16 @@ void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, nvme_show_zns_id_ns_recommandeded_limit(ns->frl, human, "frl2"); nvme_show_zns_id_ns_recommandeded_limit(ns->frl, human, "frl3"); + printf("numzrwa : %#x\n", le32_to_cpu(ns->numzrwa)); + printf("zrwafg : %u\n", le16_to_cpu(ns->zrwafg)); + printf("zrwasz : %u\n", le16_to_cpu(ns->zrwasz)); + if (human) { + printf("zrwacap : %u\tZone Random Write Area Capability\n", ns->zrwacap); + nvme_show_zns_id_ns_zrwacap(ns->zrwacap); + } else { + printf("zrwacap : %u\n", ns->zrwacap); + } + for (i = 0; i <= id_ns->nlbaf; i++){ if (human) printf("LBA Format Extension %2d : Zone Size: 0x%"PRIx64" LBAs - " @@ -4440,7 +5025,7 @@ void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, } } -static void json_nvme_list_ns(__u32 *ns_list) +static void json_nvme_list_ns(struct nvme_ns_list *ns_list) { struct json_object *root; struct json_object *valid_attrs; @@ -4451,10 +5036,10 @@ static void json_nvme_list_ns(__u32 *ns_list) valid = json_create_array(); for (i = 0; i < 1024; i++) { - if (ns_list[i]) { + if (ns_list->ns[i]) { valid_attrs = json_create_object(); json_object_add_value_uint(valid_attrs, "nsid", - le32_to_cpu(ns_list[i])); + le32_to_cpu(ns_list->ns[i])); json_array_add_value_object(valid, valid_attrs); } } @@ -4464,15 +5049,15 @@ static void json_nvme_list_ns(__u32 *ns_list) json_free_object(root); } -void nvme_show_list_ns(__u32 *ns_list, enum nvme_print_flags flags) +void nvme_show_list_ns(struct nvme_ns_list *ns_list, enum nvme_print_flags flags) { int i; if (flags & JSON) return json_nvme_list_ns(ns_list); for (i = 0; i < 1024; i++) { - if (ns_list[i]) - printf("[%4u]:%#x\n", i, le32_to_cpu(ns_list[i])); + if (ns_list->ns[i]) + printf("[%4u]:%#x\n", i, le32_to_cpu(ns_list->ns[i])); } } @@ -4530,33 +5115,41 @@ static char *zone_state_to_string(__u8 state) } } +void json_nvme_finish_zone_list(__u64 nr_zones, + struct json_object *zone_list) +{ + struct json_object *root = json_create_object(); + json_object_add_value_uint(root, "nr_zones", nr_zones); + json_object_add_value_array(root, "zone_list", zone_list); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + static void json_nvme_zns_report_zones(void *report, __u32 descs, - __u8 ext_size, __u32 report_size, __u64 nr_zones) { - struct json_object *root; - struct json_object *zone_list; + __u8 ext_size, __u32 report_size, + struct json_object *zone_list) +{ struct json_object *zone; struct json_object *ext_data; struct nvme_zone_report *r = report; struct nvme_zns_desc *desc; int i; - root = json_create_object(); - zone_list = json_create_array(); - - - json_object_add_value_uint(root, "nr_zones", nr_zones); - for (i = 0; i < descs; i++) { desc = (struct nvme_zns_desc *) (report + sizeof(*r) + i * (sizeof(*desc) + ext_size)); zone = json_create_object(); - json_object_add_value_uint(zone, "slba", le64_to_cpu(desc->zslba)); - json_object_add_value_uint(zone, "wp", le64_to_cpu(desc->wp)); - json_object_add_value_uint(zone, "cap", le64_to_cpu(desc->zcap)); - json_object_add_value_string(zone, "state", + json_object_add_value_uint64(zone, "slba", + le64_to_cpu(desc->zslba)); + json_object_add_value_uint64(zone, "wp", + le64_to_cpu(desc->wp)); + json_object_add_value_uint64(zone, "cap", + le64_to_cpu(desc->zcap)); + json_object_add_value_string(zone, "state", zone_state_to_string(desc->zs >> 4)); - json_object_add_value_string(zone, "type", + json_object_add_value_string(zone, "type", zone_type_to_string(desc->zt)); json_object_add_value_uint(zone, "attrs", desc->za); json_object_add_value_uint(zone, "attrs", desc->zai); @@ -4564,9 +5157,9 @@ static void json_nvme_zns_report_zones(void *report, __u32 descs, if (ext_size) { if (desc->za & NVME_ZNS_ZA_ZDEV) { ext_data = json_create_array(); - d_json((unsigned char *)desc + sizeof(*desc), + d_json((unsigned char *)desc + sizeof(*desc), ext_size, 16, 1, ext_data); - json_object_add_value_array(zone, "ext_data", + json_object_add_value_array(zone, "ext_data", ext_data); } else { json_object_add_value_string(zone, "ext_data", "Not valid"); @@ -4575,11 +5168,6 @@ static void json_nvme_zns_report_zones(void *report, __u32 descs, json_array_add_value_object(zone_list, zone); } - - json_object_add_value_array(root, "zone_list", zone_list); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); } static void nvme_show_zns_report_zone_attributes(__u8 za, __u8 zai) @@ -4601,7 +5189,8 @@ static void nvme_show_zns_report_zone_attributes(__u8 za, __u8 zai) } void nvme_show_zns_report_zones(void *report, __u32 descs, - __u8 ext_size, __u32 report_size, unsigned long flags) + __u8 ext_size, __u32 report_size, unsigned long flags, + struct json_object *zone_list) { struct nvme_zone_report *r = report; struct nvme_zns_desc *desc; @@ -4614,8 +5203,8 @@ void nvme_show_zns_report_zones(void *report, __u32 descs, if (flags & BINARY) return d_raw((unsigned char *)report, report_size); else if (flags & JSON) - return json_nvme_zns_report_zones(report, descs, - ext_size, report_size, nr_zones); + return json_nvme_zns_report_zones(report, descs, + ext_size, report_size, zone_list); for (i = 0; i < descs; i++) { desc = (struct nvme_zns_desc *) @@ -4642,7 +5231,7 @@ void nvme_show_zns_report_zones(void *report, __u32 descs, } } -static void json_nvme_list_ctrl(struct nvme_controller_list *ctrl_list, __u16 num) +static void json_nvme_list_ctrl(struct nvme_ctrl_list *ctrl_list, __u16 num) { struct json_object *root; struct json_object *valid_attrs; @@ -4669,12 +5258,14 @@ static void json_nvme_list_ctrl(struct nvme_controller_list *ctrl_list, __u16 nu json_free_object(root); } -void nvme_show_list_ctrl(struct nvme_controller_list *ctrl_list, +void nvme_show_list_ctrl(struct nvme_ctrl_list *ctrl_list, enum nvme_print_flags flags) { int i; __u16 num = le16_to_cpu(ctrl_list->num); + if (flags & BINARY) + return d_raw((unsigned char *)ctrl_list, sizeof(*ctrl_list)); if (flags & JSON) return json_nvme_list_ctrl(ctrl_list, num); @@ -4684,7 +5275,7 @@ void nvme_show_list_ctrl(struct nvme_controller_list *ctrl_list, } } -static void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset) +static void json_nvme_id_nvmset(struct nvme_id_nvmset_list *nvmset) { __u32 nent = nvmset->nid; struct json_object *entries; @@ -4700,17 +5291,17 @@ static void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset) struct json_object *entry = json_create_object(); json_object_add_value_int(entry, "nvmset_id", - le16_to_cpu(nvmset->ent[i].id)); + le16_to_cpu(nvmset->ent[i].nvmsetid)); json_object_add_value_int(entry, "endurance_group_id", - le16_to_cpu(nvmset->ent[i].endurance_group_id)); + le16_to_cpu(nvmset->ent[i].endgid)); json_object_add_value_int(entry, "random_4k_read_typical", - le32_to_cpu(nvmset->ent[i].random_4k_read_typical)); + le32_to_cpu(nvmset->ent[i].rr4kt)); json_object_add_value_int(entry, "optimal_write_size", - le32_to_cpu(nvmset->ent[i].opt_write_size)); + le32_to_cpu(nvmset->ent[i].ows)); json_object_add_value_float(entry, "total_nvmset_cap", - int128_to_double(nvmset->ent[i].total_nvmset_cap)); + int128_to_double(nvmset->ent[i].tnvmsetcap)); json_object_add_value_float(entry, "unalloc_nvmset_cap", - int128_to_double(nvmset->ent[i].unalloc_nvmset_cap)); + int128_to_double(nvmset->ent[i].unvmsetcap)); json_array_add_value_object(entries, entry); } @@ -4720,7 +5311,7 @@ static void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset) json_free_object(root); } -void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id, +void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id, enum nvme_print_flags flags) { int i; @@ -4737,22 +5328,22 @@ void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id, printf(" NVM Set Attribute Entry[%2d]\n", i); printf(".................\n"); printf("nvmset_id : %d\n", - le16_to_cpu(nvmset->ent[i].id)); + le16_to_cpu(nvmset->ent[i].endgid)); printf("endurance_group_id : %d\n", - le16_to_cpu(nvmset->ent[i].endurance_group_id)); + le16_to_cpu(nvmset->ent[i].endgid)); printf("random_4k_read_typical : %u\n", - le32_to_cpu(nvmset->ent[i].random_4k_read_typical)); + le32_to_cpu(nvmset->ent[i].rr4kt)); printf("optimal_write_size : %u\n", - le32_to_cpu(nvmset->ent[i].opt_write_size)); + le32_to_cpu(nvmset->ent[i].ows)); printf("total_nvmset_cap : %.0Lf\n", - int128_to_double(nvmset->ent[i].total_nvmset_cap)); + int128_to_double(nvmset->ent[i].tnvmsetcap)); printf("unalloc_nvmset_cap : %.0Lf\n", - int128_to_double(nvmset->ent[i].unalloc_nvmset_cap)); + int128_to_double(nvmset->ent[i].unvmsetcap)); printf(".................\n"); } } -static void json_nvme_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps) +static void json_nvme_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *caps) { struct json_object *root; @@ -4793,15 +5384,15 @@ static void nvme_show_primary_ctrl_caps_crt(__u8 crt) printf(" [0:0] %#x\tVQ Resources are %ssupported\n", vq, vq ? "" : "not "); } -void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps, - enum nvme_print_flags flags) +void nvme_show_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *caps, + enum nvme_print_flags flags) { int human = flags & VERBOSE; if (flags & BINARY) return d_raw((unsigned char *)caps, sizeof(*caps)); else if (flags & JSON) - return json_nvme_primary_ctrl_caps(caps); + return json_nvme_primary_ctrl_cap(caps); printf("NVME Identify Primary Controller Capabilities:\n"); printf("cntlid : %#x\n", le16_to_cpu(caps->cntlid)); @@ -4823,10 +5414,10 @@ void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps, printf("vigran : %d\n", le16_to_cpu(caps->vigran)); } -static void json_nvme_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, +static void json_nvme_list_secondary_ctrl(const struct nvme_secondary_ctrl_list *sc_list, __u32 count) { - const struct nvme_secondary_controller_entry *sc_entry = &sc_list->sc_entry[0]; + const struct nvme_secondary_ctrl *sc_entry = &sc_list->sc_entry[0]; __u32 nent = min(sc_list->num, count); struct json_object *entries; struct json_object *root; @@ -4865,10 +5456,10 @@ static void json_nvme_list_secondary_ctrl(const struct nvme_secondary_controller } void nvme_show_list_secondary_ctrl( - const struct nvme_secondary_controllers_list *sc_list, + const struct nvme_secondary_ctrl_list *sc_list, __u32 count, enum nvme_print_flags flags) { - const struct nvme_secondary_controller_entry *sc_entry = + const struct nvme_secondary_ctrl *sc_entry = &sc_list->sc_entry[0]; static const char * const state_desc[] = { "Offline", "Online" }; @@ -4920,10 +5511,10 @@ static void json_nvme_id_ns_granularity_list( for (i = 0; i <= glist->num_descriptors; i++) { struct json_object *entry = json_create_object(); - json_object_add_value_uint(entry, "namespace-size-granularity", - le64_to_cpu(glist->entry[i].namespace_size_granularity)); - json_object_add_value_uint(entry, "namespace-capacity-granularity", - le64_to_cpu(glist->entry[i].namespace_capacity_granularity)); + json_object_add_value_uint64(entry, "namespace-size-granularity", + le64_to_cpu(glist->entry[i].nszegran)); + json_object_add_value_uint64(entry, "namespace-capacity-granularity", + le64_to_cpu(glist->entry[i].ncapgran)); json_array_add_value_object(entries, entry); } @@ -4955,9 +5546,9 @@ void nvme_show_id_ns_granularity_list(const struct nvme_id_ns_granularity_list * printf("\n Entry[%2d] :\n", i); printf("................\n"); printf(" NSG : Namespace Size Granularity : 0x%"PRIx64"\n", - le64_to_cpu(glist->entry[i].namespace_size_granularity)); + le64_to_cpu(glist->entry[i].nszegran)); printf(" NCG : Namespace Capacity Granularity : 0x%"PRIx64"\n", - le64_to_cpu(glist->entry[i].namespace_capacity_granularity)); + le64_to_cpu(glist->entry[i].ncapgran)); } } @@ -4970,7 +5561,7 @@ static void json_nvme_id_uuid_list(const struct nvme_id_uuid_list *uuid_list) root = json_create_object(); entries = json_create_array(); /* The 0th entry is reserved */ - for (i = 1; i < NVME_MAX_UUID_ENTRIES; i++) { + for (i = 1; i < NVME_ID_UUID_LIST_MAX; i++) { uuid_t uuid; struct json_object *entry = json_create_object(); @@ -5002,7 +5593,7 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, /* The 0th entry is reserved */ printf("NVME Identify UUID:\n"); - for (i = 1; i < NVME_MAX_UUID_ENTRIES; i++) { + for (i = 1; i < NVME_ID_UUID_LIST_MAX; i++) { uuid_t uuid; char *association = ""; uint8_t identifier_association = uuid_list->entry[i].header & 0x3; @@ -5037,69 +5628,6 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, } } -static void nvme_show_iocs_vector(__u64 iocs_vec) -{ - __u64 rsvd3 = iocs_vec >> 3; - __u8 zns_cmd_set = (iocs_vec >> 2) & 0x1; - __u8 kv_cmd_set = (iocs_vec >> 1) & 0x1; - __u8 nvm_cmd_set = iocs_vec & 0x1; - - if (rsvd3) - printf(" [63:3] : %"PRIx64"\tReserved3\n", le64_to_cpu(rsvd3)); - printf(" [2:2] : %#x\tZNS Command Set %sSelected\n", - zns_cmd_set, zns_cmd_set ? "" : "not "); - printf(" [1:1] : %#x\tKV Command Set %sSelected\n", - kv_cmd_set, kv_cmd_set ? "" : "not "); - printf(" [0:0] : %#x\tNVM Command Set %sSelected\n", - nvm_cmd_set, nvm_cmd_set ? "" : "not "); - printf("\n"); -} - -static void json_id_iocs(struct nvme_id_iocs *iocs) -{ - struct json_object *root; - struct json_object *entries; - int i; - - root = json_create_object(); - entries = json_create_array(); - - for (i = 0; i < NVME_NUM_IOCS_COMBINATIONS; i++) { - if (iocs->iocs[i]) { - struct json_object *entry = json_create_object(); - json_object_add_value_uint(entry, "iocs", - le64_to_cpu(iocs->iocs[i])); - json_array_add_value_object(entries, entry); - } - } - - json_object_add_value_array(root, "iocs_list", entries); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - -} - -void nvme_show_id_iocs(struct nvme_id_iocs *iocs, enum nvme_print_flags flags) -{ - if (flags & BINARY) - return d_raw((unsigned char *)iocs, sizeof(*iocs)); - else if (flags & JSON) - return json_id_iocs(iocs); - - bool human = flags & VERBOSE; - int i; - - for (i = 0; i < NVME_NUM_IOCS_COMBINATIONS; i++) { - if (iocs->iocs[i]) { - printf("I/O Command Set Combination[%u]: %"PRIx64"\n", i, - (uint64_t)le64_to_cpu(iocs->iocs[i])); - if (human) - nvme_show_iocs_vector(le64_to_cpu(iocs->iocs[i])); - } - } -} - static void json_id_domain_list(struct nvme_id_domain_list *id_dom) { struct json_object *root; @@ -5111,9 +5639,9 @@ static void json_id_domain_list(struct nvme_id_domain_list *id_dom) root = json_create_object(); entries = json_create_array(); - json_object_add_value_uint(root, "num_dom_entries", id_dom->num_entries); + json_object_add_value_uint(root, "num_dom_entries", id_dom->num); - for (i = 0; i < id_dom->num_entries; i++) { + for (i = 0; i < id_dom->num; i++) { entry = json_create_object(); dom_cap = int128_to_double(id_dom->domain_attr[i].dom_cap); unalloc_dom_cap = int128_to_double(id_dom->domain_attr[i].unalloc_dom_cap); @@ -5142,8 +5670,8 @@ void nvme_show_id_domain_list(struct nvme_id_domain_list *id_dom, else if (flags & JSON) return json_id_domain_list(id_dom); - printf("Number of Domain Entires: %u\n", id_dom->num_entries); - for (i = 0; i < id_dom->num_entries; i++) { + printf("Number of Domain Entires: %u\n", id_dom->num); + for (i = 0; i < id_dom->num; i++) { printf("Domain Id for Attr Entry[%u]: %u\n", i, le16_to_cpu(id_dom->domain_attr[i].dom_id)); printf("Domain Capacity for Attr Entry[%u]: %.0Lf\\n", i, @@ -5155,7 +5683,7 @@ void nvme_show_id_domain_list(struct nvme_id_domain_list *id_dom, } } -static void json_nvme_endurance_group_list(struct nvme_endurance_group_list *endgrp_list) +static void json_nvme_endurance_group_list(struct nvme_id_endurance_group_list *endgrp_list) { struct json_object *root; struct json_object *valid_attrs; @@ -5181,7 +5709,7 @@ static void json_nvme_endurance_group_list(struct nvme_endurance_group_list *end json_free_object(root); } -void nvme_show_endurance_group_list(struct nvme_endurance_group_list *endgrp_list, +void nvme_show_endurance_group_list(struct nvme_id_endurance_group_list *endgrp_list, enum nvme_print_flags flags) { int i; @@ -5196,6 +5724,16 @@ void nvme_show_endurance_group_list(struct nvme_endurance_group_list *endgrp_lis } } +void nvme_show_id_iocs(struct nvme_id_iocs *iocs) +{ + __u16 i; + + for (i = 0; i < 512; i++) + if (iocs->iocsc[i]) + printf("I/O Command Set Combination[%u]:%"PRIx64"\n", i, + (uint64_t)le64_to_cpu(iocs->iocsc[i])); +} + static const char *nvme_trtype_to_string(__u8 trtype) { switch (trtype) { @@ -5224,15 +5762,16 @@ void nvme_show_error_log(struct nvme_error_log_page *err_log, int entries, entries); printf(".................\n"); for (i = 0; i < entries; i++) { + __u16 status = le16_to_cpu(err_log[i].status_field) >> 0x1; + printf(" Entry[%2d] \n", i); printf(".................\n"); printf("error_count : %"PRIu64"\n", 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 >> 0x1, - nvme_status_to_string( - le16_to_cpu(err_log[i].status_field) >> 1)); + printf("status_field : %#x(%s)\n", status, + nvme_status_to_string(status, false)); printf("phase_tag : %#x\n", le16_to_cpu(err_log[i].status_field & 0x1)); printf("parm_err_loc : %#x\n", @@ -5250,15 +5789,15 @@ void nvme_show_error_log(struct nvme_error_log_page *err_log, int entries, } } -void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, - __u32 cdw11, enum nvme_print_flags flags) +void nvme_show_resv_report(struct nvme_resv_status *status, int bytes, + bool eds, enum nvme_print_flags flags) { int i, j, regctl, entries; if (flags & BINARY) return d_raw((unsigned char *)status, bytes); else if (flags & JSON) - return json_nvme_resv_report(status, bytes, cdw11); + return json_nvme_resv_report(status, bytes, eds); regctl = status->regctl[0] | (status->regctl[1] << 8); @@ -5269,7 +5808,7 @@ void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, printf("ptpls : %d\n", status->ptpls); /* check Extended Data Structure bit */ - if ((cdw11 & 0x1) == 0) { + if (!eds) { /* * if status buffer was too small, don't loop past the end of * the buffer @@ -5290,8 +5829,6 @@ void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, 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) @@ -5300,25 +5837,27 @@ void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, for (i = 0; i < regctl; i++) { printf("regctlext[%d] :\n", i); printf(" cntlid : %x\n", - le16_to_cpu(ext_status->regctl_eds[i].cntlid)); + le16_to_cpu(status->regctl_eds[i].cntlid)); printf(" rcsts : %x\n", - ext_status->regctl_eds[i].rcsts); + status->regctl_eds[i].rcsts); printf(" rkey : %"PRIx64"\n", - le64_to_cpu(ext_status->regctl_eds[i].rkey)); + le64_to_cpu(status->regctl_eds[i].rkey)); printf(" hostid : "); for (j = 0; j < 16; j++) printf("%x", - ext_status->regctl_eds[i].hostid[j]); + status->regctl_eds[i].hostid[j]); printf("\n"); } } printf("\n"); } -void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log, +void nvme_show_fw_log(struct nvme_firmware_slot *fw_log, const char *devname, enum nvme_print_flags flags) { int i; + __le64 *frs; + if (flags & BINARY) return d_raw((unsigned char *)fw_log, sizeof(*fw_log)); if (flags & JSON) @@ -5327,12 +5866,16 @@ void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log, printf("Firmware Log for device:%s\n", devname); printf("afi : %#x\n", fw_log->afi); for (i = 0; i < 7; i++) { - if (strcmp(fw_to_string(fw_log->frs[i]), "\0")) - printf("frs%d : %s\n", i + 1, fw_to_string(fw_log->frs[i])); + if (fw_log->frs[i][0]) { + frs = (__le64 *)&fw_log->frs[i]; + printf("frs%d : %#016"PRIx64" (%s)\n", i + 1, + le64_to_cpu(*frs), + fw_to_string(fw_log->frs[i])); + } } } -void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, +void nvme_show_changed_ns_list_log(struct nvme_ns_list *log, const char *devname, enum nvme_print_flags flags) { @@ -5344,9 +5887,9 @@ void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, else if (flags & JSON) return json_changed_ns_list_log(log, devname); - if (log->log[0] != cpu_to_le32(0XFFFFFFFF)) { - for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) { - nsid = le32_to_cpu(log->log[i]); + if (log->ns[0] != cpu_to_le32(NVME_NSID_ALL)) { + for (i = 0; i < NVME_ID_NS_LIST_MAX; i++) { + nsid = le32_to_cpu(log->ns[i]); if (nsid == 0) break; @@ -5354,64 +5897,117 @@ void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, } } else printf("more than %d ns changed\n", - NVME_MAX_CHANGED_NAMESPACES); + NVME_ID_NS_LIST_MAX); } -static void nvme_show_effects_log_human(__u32 effect) +static void nvme_show_effects_log_human(FILE *stream, __u32 effect) { const char *set = "+"; const char *clr = "-"; - printf(" CSUPP+"); - printf(" LBCC%s", (effect & NVME_CMD_EFFECTS_LBCC) ? set : clr); - printf(" NCC%s", (effect & NVME_CMD_EFFECTS_NCC) ? set : clr); - printf(" NIC%s", (effect & NVME_CMD_EFFECTS_NIC) ? set : clr); - printf(" CCC%s", (effect & NVME_CMD_EFFECTS_CCC) ? set : clr); - printf(" USS%s", (effect & NVME_CMD_EFFECTS_UUID_SEL) ? set : clr); + fprintf(stream, " CSUPP+"); + fprintf(stream, " LBCC%s", (effect & NVME_CMD_EFFECTS_LBCC) ? set : clr); + fprintf(stream, " NCC%s", (effect & NVME_CMD_EFFECTS_NCC) ? set : clr); + fprintf(stream, " NIC%s", (effect & NVME_CMD_EFFECTS_NIC) ? set : clr); + fprintf(stream, " CCC%s", (effect & NVME_CMD_EFFECTS_CCC) ? set : clr); + fprintf(stream, " USS%s", (effect & NVME_CMD_EFFECTS_UUID_SEL) ? set : clr); if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 0) - printf(" No command restriction\n"); + fprintf(stream, " No command restriction\n"); else if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 1) - printf(" No other command for same namespace\n"); + fprintf(stream, " No other command for same namespace\n"); else if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 2) - printf(" No other command for any namespace\n"); + fprintf(stream, " No other command for any namespace\n"); else - printf(" Reserved CSE\n"); + fprintf(stream, " Reserved CSE\n"); } -void nvme_show_effects_log(struct nvme_effects_log_page *effects, - unsigned int flags) -{ - int i, human = flags & VERBOSE; +void nvme_print_effects_entry(FILE* stream, int admin, int index, __le32 entry, unsigned int human) { __u32 effect; + char *format_string; - if (flags & BINARY) - return d_raw((unsigned char *)effects, sizeof(*effects)); - else if (flags & JSON) - return json_effects_log(effects); + format_string = admin ? "ACS%-6d[%-32s] %08x" : "IOCS%-5d[%-32s] %08x"; - printf("Admin Command Set\n"); - for (i = 0; i < 256; i++) { - effect = le32_to_cpu(effects->acs[i]); - if (effect & NVME_CMD_EFFECTS_CSUPP) { - printf("ACS%-6d[%-32s] %08x", i, - nvme_cmd_to_string(1, i), effect); - if (human) - nvme_show_effects_log_human(effect); - else - printf("\n"); + effect = le32_to_cpu(entry); + if (effect & NVME_CMD_EFFECTS_CSUPP) { + fprintf(stream, format_string, index, nvme_cmd_to_string(admin, index), + effect); + if (human) + nvme_show_effects_log_human(stream, effect); + else + fprintf(stream, "\n"); + } +} + +void nvme_print_effects_log_segment(int admin, int a, int b, struct nvme_cmd_effects_log *effects, char* header, int human) { + FILE *stream; + char *stream_location; + size_t stream_size; + + stream = open_memstream(&stream_location, &stream_size); + if (!stream) { + perror("Failed to open stream"); + return; + } + + for (int i = a; i < b; i++) { + if (admin) { + nvme_print_effects_entry(stream, admin, i, effects->acs[i], human); + } + else { + nvme_print_effects_entry(stream, admin, i, + effects->iocs[i], human); } } - printf("\nNVM Command Set\n"); - for (i = 0; i < 256; i++) { - effect = le32_to_cpu(effects->iocs[i]); - if (effect & NVME_CMD_EFFECTS_CSUPP) { - printf("IOCS%-5d[%-32s] %08x", i, - nvme_cmd_to_string(0, i), effect); - if (human) - nvme_show_effects_log_human(effect); - else - printf("\n"); + + fclose(stream); + + if (stream_size && header) { + printf("%s\n", header); + fwrite(stream_location, stream_size, 1, stdout); + printf("\n"); + } + + free(stream_location); +} + +void nvme_print_effects_log_page(enum nvme_csi csi, struct nvme_cmd_effects_log *effects, int flags) { + int human = flags & VERBOSE; + + switch (csi) { + case NVME_CSI_NVM: + printf("NVM Command Set Log Page\n"); + printf("%-.80s\n", dash); + break; + case NVME_CSI_ZNS: + printf("ZNS Command Set Log Page\n"); + printf("%-.80s\n", dash); + break; + default: + printf("Unknown Command Set Log Page\n"); + printf("%-.80s\n", dash); + break; + } + + nvme_print_effects_log_segment(1, 0, 0xbf, effects, "Admin Commands", human); + nvme_print_effects_log_segment(1, 0xc0, 0xff, effects, "Vendor Specific Admin Commands", human); + nvme_print_effects_log_segment(0, 0, 0x80, effects, "I/O Commands", human); + nvme_print_effects_log_segment(0, 0x80, 0x100, effects, "Vendor Specific I/O Commands", human); +} + +void nvme_print_effects_log_pages(struct list_head *list, + int flags) +{ + if (flags & JSON) + return json_effects_log_list(list); + + nvme_effects_log_node_t *node; + list_for_each(list, node, node) { + if (flags & BINARY) { + d_raw((unsigned char *)&node->effects, sizeof(node->effects)); + } + else { + nvme_print_effects_log_page(node->csi, &node->effects, flags); } } } @@ -5419,28 +6015,28 @@ void nvme_show_effects_log(struct nvme_effects_log_page *effects, const char *nvme_log_to_string(__u8 lid) { switch (lid) { - case NVME_LOG_SUPPORTED_PAGES: return "Supported Log Pages"; - case NVME_LOG_ERROR: return "Error Information"; - case NVME_LOG_SMART: return "SMART Information"; - case NVME_LOG_FW_SLOT: return "Firmware Slot Information"; - case NVME_LOG_CHANGED_NS: return "Changed Namespace List"; - case NVME_LOG_CMD_EFFECTS: return "Commands Supported and Effects"; - case NVME_LOG_DEVICE_SELF_TEST: return "Device Self-test"; - case NVME_LOG_TELEMETRY_HOST: return "Telemetry Host-Initiated"; - case NVME_LOG_TELEMETRY_CTRL: return "Telemetry Controller-Initiated"; - case NVME_LOG_ENDURANCE_GROUP: return "Endurance Group Information"; - case NVME_LOG_PRELAT_PER_NVMSET: return "Predictable Latency Per NVM Set"; - case NVME_LOG_ANA: return "Asymmetric Namespace Access"; - case NVME_LOG_PRELAT_EVENT_AGG: return "Predictable Latency Event Aggregate"; - case NVME_LOG_PERSISTENT_EVENT: return "Persistent Event Log"; - case NVME_LOG_LBA_STATUS: return "LBA Status Information"; - case NVME_LOG_ENDURANCE_GROUP_EVENT_AGG: return "Endurance Group Event Aggregate"; - case NVME_LOG_BOOT_PARTITION: return "Boot Partition"; - case NVME_LOG_FID_SUPPORT_EFFECTS: return "FID Supported and Effects"; - case NVME_LOG_DISC: return "Discovery"; - case NVME_LOG_RESERVATION: return "Reservation Notification"; - case NVME_LOG_SANITIZE: return "Sanitize Status"; - case NVME_LOG_ZONE_CHANGED_LIST: return "Host Identifier"; + case NVME_LOG_LID_SUPPORTED_LOG_PAGES: return "Supported Log Pages"; + case NVME_LOG_LID_ERROR: return "Error Information"; + case NVME_LOG_LID_SMART: return "SMART / Health Information"; + case NVME_LOG_LID_FW_SLOT: return "Firmware Slot Information"; + case NVME_LOG_LID_CHANGED_NS: return "Changed Namespace List"; + case NVME_LOG_LID_CMD_EFFECTS: return "Commands Supported and Effects"; + case NVME_LOG_LID_DEVICE_SELF_TEST: return "Device Self-test"; + case NVME_LOG_LID_TELEMETRY_HOST: return "Telemetry Host-Initiated"; + case NVME_LOG_LID_TELEMETRY_CTRL: return "Telemetry Controller-Initiated"; + case NVME_LOG_LID_ENDURANCE_GROUP: return "Endurance Group Information"; + case NVME_LOG_LID_PREDICTABLE_LAT_NVMSET: return "Predictable Latency Per NVM Set"; + case NVME_LOG_LID_PREDICTABLE_LAT_AGG: return "Predictable Latency Event Aggregate"; + case NVME_LOG_LID_ANA: return "Asymmetric Namespace Access"; + case NVME_LOG_LID_PERSISTENT_EVENT: return "Persistent Event Log"; + case NVME_LOG_LID_LBA_STATUS: return "LBA Status Information"; + case NVME_LOG_LID_ENDURANCE_GRP_EVT: return "Endurance Group Event Aggregate"; + case NVME_LOG_LID_FID_SUPPORTED_EFFECTS: return "Feature Identifiers Supported and Effects"; + case NVME_LOG_LID_BOOT_PARTITION: return "Boot Partition"; + case NVME_LOG_LID_DISCOVER: return "Discovery"; + case NVME_LOG_LID_RESERVATION: return "Reservation Notification"; + case NVME_LOG_LID_SANITIZE: return "Sanitize Status"; + case NVME_LOG_LID_ZNS_CHANGED_ZONES: return "Changed Zone List"; default: return "Unknown"; } } @@ -5452,13 +6048,13 @@ static void nvme_show_support_log_human(__u32 support, __u8 lid) printf(" LSUPP is %s\n", (support & 0x1) ? set : clr); printf(" IOS is %s\n", ((support >> 0x1) & 0x1) ? set : clr); - if (lid == NVME_LOG_PERSISTENT_EVENT) { + if (lid == NVME_LOG_LID_PERSISTENT_EVENT) { printf(" Establish Context and Read 512 Bytes of Header is %s\n", ((support >> 0x16) & 0x1) ? set : clr); } } -static void json_support_log(struct nvme_support_log_pages *support_log) +static void json_support_log(struct nvme_supported_log_pages *support_log) { struct json_object *root; struct json_object *valid; @@ -5486,7 +6082,7 @@ static void json_support_log(struct nvme_support_log_pages *support_log) json_free_object(root); } -void nvme_show_supported_log(struct nvme_support_log_pages *support_log, +void nvme_show_supported_log(struct nvme_supported_log_pages *support_log, const char *devname, enum nvme_print_flags flags) { int lid, human = flags & VERBOSE; @@ -5584,7 +6180,7 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, printf(" Persistent Mem. RO[5] : %d\n", (smart->critical_warning & 0x20) >> 5); } - printf("temperature : %ld C (%u Kelvin)\n", + printf("temperature : %ld°C (%u Kelvin)\n", kelvin_to_celsius(temperature), temperature); printf("available_spare : %u%%\n", smart->avail_spare); @@ -5623,7 +6219,7 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, if (temp == 0) continue; - printf("Temperature Sensor %d : %ld C (%u Kelvin)\n", + printf("Temperature Sensor %d : %ld°C (%u Kelvin)\n", i + 1, kelvin_to_celsius(temp), temp); } printf("Thermal Management T1 Trans Count : %u\n", @@ -5636,11 +6232,11 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, le32_to_cpu(smart->thm_temp2_total_time)); } -void nvme_show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname, +void nvme_show_ana_log(struct nvme_ana_log *ana_log, const char *devname, enum nvme_print_flags flags, size_t len) { - int offset = sizeof(struct nvme_ana_rsp_hdr); - struct nvme_ana_rsp_hdr *hdr = ana_log; + int offset = sizeof(struct nvme_ana_log); + struct nvme_ana_log *hdr = ana_log; struct nvme_ana_group_desc *desc; size_t nsid_buf_size; void *base = ana_log; @@ -5680,7 +6276,7 @@ void nvme_show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname, } } -static void nvme_show_self_test_result(struct nvme_self_test_res *res, +static void nvme_show_self_test_result(struct nvme_st_result *res, enum nvme_print_flags flags) { static const char *const test_res[] = { @@ -5697,17 +6293,17 @@ static void nvme_show_self_test_result(struct nvme_self_test_res *res, "Operation was aborted for unknown reason", "Operation was aborted due to a sanitize operation", "Reserved", - [NVME_ST_RES_NOT_USED] = "Entry not used (does not contain a result)", + [NVME_ST_RESULT_NOT_USED] = "Entry not used (does not contain a result)", }; __u8 op, code; - op = res->dsts & NVME_ST_RES_MASK; + op = res->dsts & NVME_ST_RESULT_MASK; printf(" Operation Result : %#x", op); if (flags & VERBOSE) printf(" %s", (op < ARRAY_SIZE(test_res) && test_res[op]) ? test_res[op] : test_res[ARRAY_SIZE(test_res) - 1]); printf("\n"); - if (op == NVME_ST_RES_NOT_USED) + if (op == NVME_ST_RESULT_NOT_USED) return; code = res->dsts >> NVME_ST_CODE_SHIFT; @@ -5715,10 +6311,10 @@ static void nvme_show_self_test_result(struct nvme_self_test_res *res, if (flags & VERBOSE) { switch (code) { - case NVME_ST_CODE_SHORT_OP: + case NVME_ST_CODE_SHORT: printf(" Short device self-test operation"); break; - case NVME_ST_CODE_EXT_OP: + case NVME_ST_CODE_EXTENDED: printf(" Extended device self-test operation"); break; case NVME_ST_CODE_VS: @@ -5731,26 +6327,26 @@ static void nvme_show_self_test_result(struct nvme_self_test_res *res, } printf("\n"); - if (op == NVME_ST_RES_KNOWN_SEG_FAIL) + if (op == NVME_ST_RESULT_KNOWN_SEG_FAIL) printf(" Segment Number : %#x\n", res->seg); printf(" Valid Diagnostic Information : %#x\n", res->vdi); printf(" Power on hours (POH) : %#"PRIx64"\n", (uint64_t)le64_to_cpu(res->poh)); - if (res->vdi & NVME_ST_VALID_NSID) + if (res->vdi & NVME_ST_VALID_DIAG_INFO_NSID) printf(" Namespace Identifier : %#x\n", le32_to_cpu(res->nsid)); - if (res->vdi & NVME_ST_VALID_FLBA) + if (res->vdi & NVME_ST_VALID_DIAG_INFO_FLBA) printf(" Failing LBA : %#"PRIx64"\n", (uint64_t)le64_to_cpu(res->flba)); - if (res->vdi & NVME_ST_VALID_SCT) + if (res->vdi & NVME_ST_VALID_DIAG_INFO_SCT) printf(" Status Code Type : %#x\n", res->sct); - if (res->vdi & NVME_ST_VALID_SC) { + if (res->vdi & NVME_ST_VALID_DIAG_INFO_SC) { printf(" Status Code : %#x", res->sc); if (flags & VERBOSE) printf(" %s", nvme_status_to_string( - (res->sct & 7) << 8 | res->sc)); + (res->sct & 7) << 8 | res->sc, false)); printf("\n"); } printf(" Vendor Specific : %#x %#x\n", @@ -5769,9 +6365,9 @@ void nvme_show_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_entr return json_self_test_log(self_test, dst_entries); printf("Device Self Test Log for NVME device:%s\n", devname); - printf("Current operation : %#x\n", self_test->crnt_dev_selftest_oprn); - printf("Current Completion : %u%%\n", self_test->crnt_dev_selftest_compln); - num_entries = min(dst_entries, NVME_ST_REPORTS); + printf("Current operation : %#x\n", self_test->current_operation); + printf("Current Completion : %u%%\n", self_test->completion); + num_entries = min(dst_entries, NVME_LOG_ST_MAX_RESULTS); for (i = 0; i < num_entries; i++) { printf("Self Test Result[%d]:\n", i); nvme_show_self_test_result(&self_test->result[i], flags); @@ -5793,10 +6389,11 @@ static void nvme_show_sanitize_log_sstat(__u16 status) printf("\t[2:0]\t%s\n", str); str = "Number of completed passes if most recent operation was overwrite"; printf("\t[7:3]\t%s:\t%u\n", str, - (status & NVME_SANITIZE_LOG_NUM_CMPLTED_PASS_MASK) >> 3); + (status >> NVME_SANITIZE_SSTAT_COMPLETED_PASSES_SHIFT) & + NVME_SANITIZE_SSTAT_COMPLETED_PASSES_MASK); printf("\t [8]\t"); - if (status & NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED) + if (status & NVME_SANITIZE_SSTAT_GLOBAL_DATA_ERASED) str = "Global Data Erased set: no NS LB in the NVM subsystem "\ "has been written to and no PMR in the NVM subsystem "\ "has been enabled"; @@ -5817,83 +6414,85 @@ void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, const char *devname, enum nvme_print_flags flags) { int human = flags & VERBOSE; - __u16 status = le16_to_cpu(sanitize->status) & NVME_SANITIZE_LOG_STATUS_MASK; + __u16 status = le16_to_cpu(sanitize->sstat) & NVME_SANITIZE_SSTAT_STATUS_MASK; if (flags & BINARY) - return d_raw((unsigned char *)sanitize, sizeof(*sanitize)); - else if (flags & JSON) - return json_sanitize_log(sanitize, devname); + d_raw((unsigned char *)sanitize, sizeof(*sanitize)); + else if (flags & JSON) { + json_sanitize_log(sanitize, devname); + return; + } printf("Sanitize Progress (SPROG) : %u", - le16_to_cpu(sanitize->progress)); + le16_to_cpu(sanitize->sprog)); - if (human && status == NVME_SANITIZE_LOG_IN_PROGESS) - nvme_show_sanitize_log_sprog(le16_to_cpu(sanitize->progress)); + if (human && status == NVME_SANITIZE_SSTAT_STATUS_IN_PROGESS) + nvme_show_sanitize_log_sprog(le16_to_cpu(sanitize->sprog)); else printf("\n"); printf("Sanitize Status (SSTAT) : %#x\n", - le16_to_cpu(sanitize->status)); + le16_to_cpu(sanitize->sstat)); if (human) - nvme_show_sanitize_log_sstat(le16_to_cpu(sanitize->status)); + nvme_show_sanitize_log_sstat(le16_to_cpu(sanitize->sstat)); printf("Sanitize Command Dword 10 Information (SCDW10) : %#x\n", - le32_to_cpu(sanitize->cdw10_info)); + le32_to_cpu(sanitize->scdw10)); nvme_show_estimate_sanitize_time("Estimated Time For Overwrite ", - le32_to_cpu(sanitize->est_ovrwrt_time)); + le32_to_cpu(sanitize->eto)); nvme_show_estimate_sanitize_time("Estimated Time For Block Erase ", - le32_to_cpu(sanitize->est_blk_erase_time)); + le32_to_cpu(sanitize->etbe)); nvme_show_estimate_sanitize_time("Estimated Time For Crypto Erase ", - le32_to_cpu(sanitize->est_crypto_erase_time)); + le32_to_cpu(sanitize->etce)); nvme_show_estimate_sanitize_time("Estimated Time For Overwrite (No-Deallocate) ", - le32_to_cpu(sanitize->est_ovrwrt_time_with_no_deallocate)); + le32_to_cpu(sanitize->etond)); nvme_show_estimate_sanitize_time("Estimated Time For Block Erase (No-Deallocate) ", - le32_to_cpu(sanitize->est_blk_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize->etbend)); nvme_show_estimate_sanitize_time("Estimated Time For Crypto Erase (No-Deallocate)", - le32_to_cpu(sanitize->est_crypto_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize->etcend)); } -const char *nvme_feature_to_string(enum nvme_feat feature) +const char *nvme_feature_to_string(enum nvme_features_id feature) { switch (feature) { - case NVME_FEAT_NONE: return "Reserved"; - 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_NOPSC: return "Non-Operational Power State Config"; - case NVME_FEAT_RRL: return "Read Recovery Level"; - case NVME_FEAT_PLM_CONFIG: return "Predicatable Latency Mode Config"; - case NVME_FEAT_PLM_WINDOW: return "Predicatable Latency Mode Window"; - case NVME_LBA_STATUS_INFO: return "LBA Status Infomation Attributes"; - case NVME_FEAT_ENDURANCE: return "Enduarance Event Group Configuration"; - case NVME_FEAT_IOCS_PROFILE: return "I/O Command Set Profile"; - 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"; - case NVME_FEAT_TIMESTAMP: return "Timestamp"; - case NVME_FEAT_WRITE_PROTECT: return "Namespce Write Protect"; - case NVME_FEAT_HCTM: return "Host Controlled Thermal Management"; - case NVME_FEAT_HOST_BEHAVIOR: return "Host Behavior"; - case NVME_FEAT_SANITIZE: return "Sanitize"; - case NVME_MI_FEAT_CTRL_METADATA:return "MI Controller Metadata"; - case NVME_MI_FEAT_NS_METADATA: return "MI Namespace Metadata"; - case NVME_FEAT_SPINUP_CONTROL: return "Spinup Control"; + case NVME_FEAT_FID_ARBITRATION: return "Arbitration"; + case NVME_FEAT_FID_POWER_MGMT: return "Power Management"; + case NVME_FEAT_FID_LBA_RANGE: return "LBA Range Type"; + case NVME_FEAT_FID_TEMP_THRESH: return "Temperature Threshold"; + case NVME_FEAT_FID_ERR_RECOVERY:return "Error Recovery"; + case NVME_FEAT_FID_VOLATILE_WC: return "Volatile Write Cache"; + case NVME_FEAT_FID_NUM_QUEUES: return "Number of Queues"; + case NVME_FEAT_FID_IRQ_COALESCE:return "Interrupt Coalescing"; + case NVME_FEAT_FID_IRQ_CONFIG: return "Interrupt Vector Configuration"; + case NVME_FEAT_FID_WRITE_ATOMIC:return "Write Atomicity Normal"; + case NVME_FEAT_FID_ASYNC_EVENT: return "Async Event Configuration"; + case NVME_FEAT_FID_AUTO_PST: return "Autonomous Power State Transition"; + case NVME_FEAT_FID_HOST_MEM_BUF:return "Host Memory Buffer"; + case NVME_FEAT_FID_TIMESTAMP: return "Timestamp"; + case NVME_FEAT_FID_KATO: return "Keep Alive Timer"; + case NVME_FEAT_FID_HCTM: return "Host Controlled Thermal Management"; + case NVME_FEAT_FID_NOPSC: return "Non-Operational Power State Config"; + case NVME_FEAT_FID_RRL: return "Read Recovery Level"; + case NVME_FEAT_FID_PLM_CONFIG: return "Predicatable Latency Mode Config"; + case NVME_FEAT_FID_PLM_WINDOW: return "Predicatable Latency Mode Window"; + case NVME_FEAT_FID_LBA_STS_INTERVAL: return "LBA Status Interval"; + case NVME_FEAT_FID_HOST_BEHAVIOR: return "Host Behavior"; + case NVME_FEAT_FID_SANITIZE: return "Sanitize"; + case NVME_FEAT_FID_ENDURANCE_EVT_CFG: return "Enduarance Event Group Configuration"; + case NVME_FEAT_FID_IOCS_PROFILE: return "I/O Command Set Profile"; + case NVME_FEAT_FID_SPINUP_CONTROL: return "Spinup Control"; + case NVME_FEAT_FID_ENH_CTRL_METADATA: return "Enhanced Controller Metadata"; + case NVME_FEAT_FID_CTRL_METADATA: return "Controller Metadata"; + case NVME_FEAT_FID_NS_METADATA: return "Namespace Metadata"; + case NVME_FEAT_FID_SW_PROGRESS: return "Software Progress"; + case NVME_FEAT_FID_HOST_ID: return "Host Identifier"; + case NVME_FEAT_FID_RESV_MASK: return "Reservation Notification Mask"; + case NVME_FEAT_FID_RESV_PERSIST:return "Reservation Persistence"; + case NVME_FEAT_FID_WRITE_PROTECT: return "Namespce Write Protect"; } /* * We don't use the "default:" statement to let the compiler warning if - * some values of the enum nvme_feat are missing in the switch(). + * some values of the enum nvme_features_id are missing in the switch(). * The following return is acting as the default: statement. */ return "Unknown"; @@ -5925,6 +6524,7 @@ const char *nvme_select_to_string(int sel) case 1: return "Default"; case 2: return "Saved"; case 3: return "Supported capabilities"; + case 8: return "Changed"; default: return "Reserved"; } } @@ -5939,242 +6539,6 @@ void nvme_show_select_result(__u32 result) printf(" Feature is changeable\n"); } -const char *nvme_status_to_string(__u16 status) -{ - switch (status & 0x7ff) { - case NVME_SC_SUCCESS: - return "SUCCESS: The command completed successfully"; - case NVME_SC_INVALID_OPCODE: - return "INVALID_OPCODE: The associated command opcode field is not valid"; - case NVME_SC_INVALID_FIELD: - return "INVALID_FIELD: A reserved coded value or an unsupported value in a defined field"; - case NVME_SC_CMDID_CONFLICT: - return "CMDID_CONFLICT: The command identifier is already in use"; - case NVME_SC_DATA_XFER_ERROR: - return "DATA_XFER_ERROR: Error while trying to transfer the data or metadata"; - case NVME_SC_POWER_LOSS: - return "POWER_LOSS: Command aborted due to power loss notification"; - case NVME_SC_INTERNAL: - return "INTERNAL: The command was not completed successfully due to an internal error"; - case NVME_SC_ABORT_REQ: - return "ABORT_REQ: The command was aborted due to a Command Abort request"; - case NVME_SC_ABORT_QUEUE: - return "ABORT_QUEUE: The command was aborted due to a Delete I/O Submission Queue request"; - case NVME_SC_FUSED_FAIL: - return "FUSED_FAIL: The command was aborted due to the other command in a fused operation failing"; - case NVME_SC_FUSED_MISSING: - return "FUSED_MISSING: The command was aborted due to a Missing Fused Command"; - case NVME_SC_INVALID_NS: - return "INVALID_NS: The namespace or the format of that namespace is invalid"; - case NVME_SC_CMD_SEQ_ERROR: - return "CMD_SEQ_ERROR: The command was aborted due to a protocol violation in a multicommand sequence"; - case NVME_SC_SGL_INVALID_LAST: - return "SGL_INVALID_LAST: The command includes an invalid SGL Last Segment or SGL Segment descriptor."; - case NVME_SC_SGL_INVALID_COUNT: - return "SGL_INVALID_COUNT: There is an SGL Last Segment descriptor or an SGL Segment descriptor in a location other than the last descriptor of a segment based on the length indicated."; - case NVME_SC_SGL_INVALID_DATA: - return "SGL_INVALID_DATA: This may occur if the length of a Data SGL is too short."; - case NVME_SC_SGL_INVALID_METADATA: - return "SGL_INVALID_METADATA: This may occur if the length of a Metadata SGL is too short"; - case NVME_SC_SGL_INVALID_TYPE: - return "SGL_INVALID_TYPE: The type of an SGL Descriptor is a type that is not supported by the controller."; - case NVME_SC_CMB_INVALID_USE: - return "CMB_INVALID_USE: The attempted use of the Controller Memory Buffer is not supported by the controller."; - case NVME_SC_PRP_INVALID_OFFSET: - return "PRP_INVALID_OFFSET: The Offset field for a PRP entry is invalid."; - case NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED: - return "ATOMIC_WRITE_UNIT_EXCEEDED: The length specified exceeds the atomic write unit size."; - case NVME_SC_OPERATION_DENIED: - return "OPERATION_DENIED: The command was denied due to lack of access rights."; - case NVME_SC_SGL_INVALID_OFFSET: - return "SGL_INVALID_OFFSET: The offset specified in a descriptor is invalid."; - case NVME_SC_INCONSISTENT_HOST_ID: - return "INCONSISTENT_HOST_ID: The NVM subsystem detected the simultaneous use of 64-bit and 128-bit Host Identifier values on different controllers."; - case NVME_SC_KEEP_ALIVE_EXPIRED: - return "KEEP_ALIVE_EXPIRED: The Keep Alive Timer expired."; - case NVME_SC_KEEP_ALIVE_INVALID: - return "KEEP_ALIVE_INVALID: The Keep Alive Timeout value specified is invalid."; - case NVME_SC_PREEMPT_ABORT: - return "PREEMPT_ABORT: The command was aborted due to a Reservation Acquire command with the Reservation Acquire Action (RACQA) set to 010b (Preempt and Abort)."; - case NVME_SC_SANITIZE_FAILED: - return "SANITIZE_FAILED: The most recent sanitize operation failed and no recovery actions has been successfully completed"; - case NVME_SC_SANITIZE_IN_PROGRESS: - return "SANITIZE_IN_PROGRESS: The requested function is prohibited while a sanitize operation is in progress"; - case NVME_SC_SGL_DATA_BLK_GRAN_INVALID: - return "NVME_SC_SGL_DATA_BLK_GRAN_INVALID: Address alignment or Length granularity for an SGL Data Block descriptor is invalid"; - case NVME_SC_CMD_NOT_SUP_QUEUE_IN_CMB: - return "NVME_SC_CMD_NOT_SUP_QUEUE_IN_CMB: does not support submission of the command to a SQ or completion to a CQ in the CMB"; - case NVME_SC_IOCS_NOT_SUPPORTED: - return "IOCS_NOT_SUPPORTED: The I/O command set is not supported"; - case NVME_SC_IOCS_NOT_ENABLED: - return "IOCS_NOT_ENABLED: The I/O command set is not enabled"; - case NVME_SC_IOCS_COMBINATION_REJECTED: - return "IOCS_COMBINATION_REJECTED: The I/O command set combination is rejected"; - case NVME_SC_INVALID_IOCS: - return "INVALID_IOCS: the I/O command set is invalid"; - case NVME_SC_ID_UNAVAILABLE: - return "NVME_SC_ID_UNAVAILABLE: The number of Endurance Groups or NVM Sets supported has been exceeded."; - case NVME_SC_LBA_RANGE: - return "LBA_RANGE: The command references a LBA that exceeds the size of the namespace"; - case NVME_SC_NS_WRITE_PROTECTED: - return "NS_WRITE_PROTECTED: The command is prohibited while the namespace is write protected by the host."; - case NVME_SC_TRANSIENT_TRANSPORT: - return "TRANSIENT_TRANSPORT: A transient transport error was detected."; - case NVME_SC_PROHIBITED_BY_CMD_AND_FEAT: - return "NVME_SC_PROHIBITED_BY_CMD_AND_FEAT: command was aborted due to execution being prohibited by the Command and Feature Lockdown"; - case NVME_SC_ADMIN_CMD_MEDIA_NOT_READY: - return "NVME_SC_ADMIN_CMD_MEDIA_NOT_READY: Admin command requires access to media and the media is not ready"; - case NVME_SC_CAP_EXCEEDED: - return "CAP_EXCEEDED: The execution of the command has caused the capacity of the namespace to be exceeded"; - case NVME_SC_NS_NOT_READY: - return "NS_NOT_READY: The namespace is not ready to be accessed as a result of a condition other than a condition that is reported as an Asymmetric Namespace Access condition"; - case NVME_SC_RESERVATION_CONFLICT: - return "RESERVATION_CONFLICT: The command was aborted due to a conflict with a reservation held on the accessed namespace"; - case NVME_SC_FORMAT_IN_PROGRESS: - return "FORMAT_IN_PROGRESS: A Format NVM command is in progress on the namespace."; - case NVME_SC_ZONE_BOUNDARY_ERROR: - return "ZONE_BOUNDARY_ERROR: Invalid Zone Boundary crossing"; - case NVME_SC_ZONE_IS_FULL: - return "ZONE_IS_FULL: The accessed zone is in ZSF:Full state"; - case NVME_SC_ZONE_IS_READ_ONLY: - return "ZONE_IS_READ_ONLY: The accessed zone is in ZSRO:Read Only state"; - case NVME_SC_ZONE_IS_OFFLINE: - return "ZONE_IS_OFFLINE: The access zone is in ZSO:Offline state"; - case NVME_SC_ZONE_INVALID_WRITE: - return "ZONE_INVALID_WRITE: The write to zone was not at the write pointer offset"; - case NVME_SC_TOO_MANY_ACTIVE_ZONES: - return "TOO_MANY_ACTIVE_ZONES: The controller does not allow additional active zones"; - case NVME_SC_TOO_MANY_OPEN_ZONES: - return "TOO_MANY_OPEN_ZONES: The controller does not allow additional open zones"; - case NVME_SC_ZONE_INVALID_STATE_TRANSITION: - return "INVALID_ZONE_STATE_TRANSITION: The zone state change was invalid"; - case NVME_SC_CQ_INVALID: - return "CQ_INVALID: The Completion Queue identifier specified in the command does not exist"; - case NVME_SC_QID_INVALID: - return "QID_INVALID: The creation of the I/O Completion Queue failed due to an invalid queue identifier specified as part of the command. An invalid queue identifier is one that is currently in use or one that is outside the range supported by the controller"; - case NVME_SC_QUEUE_SIZE: - return "QUEUE_SIZE: The host attempted to create an I/O Completion Queue with an invalid number of entries"; - case NVME_SC_ABORT_LIMIT: - return "ABORT_LIMIT: The number of concurrently outstanding Abort commands has exceeded the limit indicated in the Identify Controller data structure"; - case NVME_SC_ABORT_MISSING: - return "ABORT_MISSING: The abort command is missing"; - case NVME_SC_ASYNC_LIMIT: - return "ASYNC_LIMIT: The number of concurrently outstanding Asynchronous Event Request commands has been exceeded"; - case NVME_SC_FIRMWARE_SLOT: - return "FIRMWARE_SLOT: The firmware slot indicated is invalid or read only. This error is indicated if the firmware slot exceeds the number supported"; - case NVME_SC_FIRMWARE_IMAGE: - return "FIRMWARE_IMAGE: The firmware image specified for activation is invalid and not loaded by the controller"; - case NVME_SC_INVALID_VECTOR: - return "INVALID_VECTOR: The creation of the I/O Completion Queue failed due to an invalid interrupt vector specified as part of the command"; - case NVME_SC_INVALID_LOG_PAGE: - return "INVALID_LOG_PAGE: The log page indicated is invalid. This error condition is also returned if a reserved log page is requested"; - case NVME_SC_INVALID_FORMAT: - return "INVALID_FORMAT: The LBA Format specified is not supported. This may be due to various conditions"; - case NVME_SC_FW_NEEDS_CONV_RESET: - return "FW_NEEDS_CONVENTIONAL_RESET: The firmware commit was successful, however, activation of the firmware image requires a conventional reset"; - case NVME_SC_INVALID_QUEUE: - return "INVALID_QUEUE: This error indicates that it is invalid to delete the I/O Completion Queue specified. The typical reason for this error condition is that there is an associated I/O Submission Queue that has not been deleted."; - case NVME_SC_FEATURE_NOT_SAVEABLE: - return "FEATURE_NOT_SAVEABLE: The Feature Identifier specified does not support a saveable value"; - case NVME_SC_FEATURE_NOT_CHANGEABLE: - return "FEATURE_NOT_CHANGEABLE: The Feature Identifier is not able to be changed"; - case NVME_SC_FEATURE_NOT_PER_NS: - return "FEATURE_NOT_PER_NS: The Feature Identifier specified is not namespace specific. The Feature Identifier settings apply across all namespaces"; - case NVME_SC_FW_NEEDS_SUBSYS_RESET: - return "FW_NEEDS_SUBSYSTEM_RESET: The firmware commit was successful, however, activation of the firmware image requires an NVM Subsystem"; - case NVME_SC_FW_NEEDS_RESET: - return "FW_NEEDS_RESET: The firmware commit was successful; however, the image specified does not support being activated without a reset"; - case NVME_SC_FW_NEEDS_MAX_TIME: - return "FW_NEEDS_MAX_TIME_VIOLATION: The image specified if activated immediately would exceed the Maximum Time for Firmware Activation (MTFA) value reported in Identify Controller. To activate the firmware, the Firmware Commit command needs to be re-issued and the image activated using a reset"; - case NVME_SC_FW_ACTIVATE_PROHIBITED: - return "FW_ACTIVATION_PROHIBITED: The image specified is being prohibited from activation by the controller for vendor specific reasons"; - case NVME_SC_OVERLAPPING_RANGE: - return "OVERLAPPING_RANGE: This error is indicated if the firmware image has overlapping ranges"; - case NVME_SC_NS_INSUFFICIENT_CAP: - return "NS_INSUFFICIENT_CAPACITY: Creating the namespace requires more free space than is currently available. The Command Specific Information field of the Error Information Log specifies the total amount of NVM capacity required to create the namespace in bytes"; - case NVME_SC_NS_ID_UNAVAILABLE: - return "NS_ID_UNAVAILABLE: The number of namespaces supported has been exceeded"; - case NVME_SC_NS_ALREADY_ATTACHED: - return "NS_ALREADY_ATTACHED: The controller is already attached to the namespace specified"; - case NVME_SC_NS_IS_PRIVATE: - return "NS_IS_PRIVATE: The namespace is private and is already attached to one controller"; - case NVME_SC_NS_NOT_ATTACHED: - return "NS_NOT_ATTACHED: The request to detach the controller could not be completed because the controller is not attached to the namespace"; - case NVME_SC_THIN_PROV_NOT_SUPP: - return "THIN_PROVISIONING_NOT_SUPPORTED: Thin provisioning is not supported by the controller"; - case NVME_SC_CTRL_LIST_INVALID: - return "CONTROLLER_LIST_INVALID: The controller list provided is invalid"; - case NVME_SC_DEVICE_SELF_TEST_IN_PROGRESS: - return "DEVICE_SELF_TEST_IN_PROGRESS: The controller or NVM subsystem already has a device self-test operation in process."; - case NVME_SC_BP_WRITE_PROHIBITED: - return "BOOT PARTITION WRITE PROHIBITED: The command is trying to modify a Boot Partition while it is locked"; - case NVME_SC_INVALID_CTRL_ID: - return "INVALID_CTRL_ID: An invalid Controller Identifier was specified."; - case NVME_SC_INVALID_SECONDARY_CTRL_STATE: - return "INVALID_SECONDARY_CTRL_STATE: The action requested for the secondary controller is invalid based on the current state of the secondary controller and its primary controller."; - case NVME_SC_INVALID_NUM_CTRL_RESOURCE: - return "INVALID_NUM_CTRL_RESOURCE: The specified number of Flexible Resources is invalid"; - case NVME_SC_INVALID_RESOURCE_ID: - return "INVALID_RESOURCE_ID: At least one of the specified resource identifiers was invalid"; - case NVME_SC_ANA_INVALID_GROUP_ID: - return "ANA_INVALID_GROUP_ID: The specified ANA Group Identifier (ANAGRPID) is not supported in the submitted command."; - case NVME_SC_ANA_ATTACH_FAIL: - return "ANA_ATTACH_FAIL: The controller is not attached to the namespace as a result of an ANA condition"; - case NVME_SC_INSUFFICIENT_CAP: - return "NVME_SC_INSUFFICIENT_CAP: Requested operation requires more free space than is currently available"; - case NVME_SC_NS_ATTACHMENT_LIMIT_EXCEEDED: - return "NVME_SC_NS_ATTACHMENT_LIMIT_EXCEEDED: Attaching the ns to a controller causes max number of ns attachments allowed to be exceeded"; - case NVME_SC_PROHIBIT_CMD_EXEC_NOT_SUPPORTED: - return "NVME_SC_PROHIBIT_CMD_EXEC_NOT_SUPPORTED: Prohibition of Command Execution Not Supported"; - case NVME_SC_BAD_ATTRIBUTES: - return "BAD_ATTRIBUTES: Bad attributes were given"; - case NVME_SC_INVALID_PI: - return "INVALID_PROTECION_INFO: The Protection Information Field settings specified in the command are invalid"; - case NVME_SC_READ_ONLY: - return "WRITE_ATTEMPT_READ_ONLY_RANGE: The LBA range specified contains read-only blocks"; - case NVME_SC_CMD_SIZE_LIMIT_EXCEEDED: - return "CMD_SIZE_LIMIT_EXCEEDED: Command size limit exceeded"; - case NVME_SC_WRITE_FAULT: - return "WRITE_FAULT: The write data could not be committed to the media"; - case NVME_SC_READ_ERROR: - return "READ_ERROR: The read data could not be recovered from the media"; - case NVME_SC_GUARD_CHECK: - return "GUARD_CHECK: The command was aborted due to an end-to-end guard check failure"; - case NVME_SC_APPTAG_CHECK: - return "APPTAG_CHECK: The command was aborted due to an end-to-end application tag check failure"; - case NVME_SC_REFTAG_CHECK: - return "REFTAG_CHECK: The command was aborted due to an end-to-end reference tag check failure"; - case NVME_SC_COMPARE_FAILED: - return "COMPARE_FAILED: The command failed due to a miscompare during a Compare command"; - case NVME_SC_ACCESS_DENIED: - return "ACCESS_DENIED: Access to the namespace and/or LBA range is denied due to lack of access rights"; - case NVME_SC_UNWRITTEN_BLOCK: - return "UNWRITTEN_BLOCK: The command failed due to an attempt to read from an LBA range containing a deallocated or unwritten logical block"; - case NVME_SC_STORAGE_TAG_CHECK: - return "NVME_SC_STORAGE_TAG_CHECK: command was aborted due to an end-to-end storage tag check failure"; - case NVME_SC_INTERNAL_PATH_ERROR: - return "INTERNAL_PATH_ERROT: The command was not completed as the result of a controller internal error"; - case NVME_SC_ANA_PERSISTENT_LOSS: - return "ASYMMETRIC_NAMESPACE_ACCESS_PERSISTENT_LOSS: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace being in the ANA Persistent Loss state"; - case NVME_SC_ANA_INACCESSIBLE: - return "ASYMMETRIC_NAMESPACE_ACCESS_INACCESSIBLE: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace being in the ANA Inaccessible state"; - case NVME_SC_ANA_TRANSITION: - return "ASYMMETRIC_NAMESPACE_ACCESS_TRANSITION: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace transitioning between Asymmetric Namespace Access states"; - case NVME_SC_CTRL_PATHING_ERROR: - return "CONTROLLER_PATHING_ERROR: A pathing error was detected by the controller"; - case NVME_SC_HOST_PATHING_ERROR: - return "HOST_PATHING_ERROR: A pathing error was detected by the host"; - case NVME_SC_HOST_CMD_ABORT: - return "HOST_COMMAND_ABORT: The command was aborted as a result of host action"; - case NVME_SC_CMD_INTERRUPTED: - return "CMD_INTERRUPTED: Command processing was interrupted and the controller is unable to successfully complete the command. The host should retry the command."; - case NVME_SC_PMR_SAN_PROHIBITED: - return "Sanitize Prohibited While Persistent Memory Region is Enabled: A sanitize operation is prohibited while the Persistent Memory Region is enabled."; - default: - return "Unknown"; - } -} - static const char *nvme_feature_lba_type_to_string(__u8 type) { switch (type) { @@ -6196,20 +6560,20 @@ void nvme_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) ? + printf("\ttype : %#x - %s\n", lbrt->entry[i].type, + nvme_feature_lba_type_to_string(lbrt->entry[i].type)); + printf("\tattributes : %#x - %s, %s\n", lbrt->entry[i].attributes, + (lbrt->entry[i].attributes & 0x0001) ? "LBA range may be overwritten" : "LBA range should not be overwritten", - ((lbrt[i].attributes & 0x0002) >> 1) ? + ((lbrt->entry[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", le64_to_cpu(lbrt[i].slba)); - printf("\tnlb : %#"PRIx64"\n", le64_to_cpu(lbrt[i].nlb)); + printf("\tslba : %#"PRIx64"\n", le64_to_cpu(lbrt->entry[i].slba)); + printf("\tnlb : %#"PRIx64"\n", le64_to_cpu(lbrt->entry[i].nlb)); printf("\tguid : "); for (j = 0; j < 16; j++) - printf("%02x", lbrt[i].guid[j]); + printf("%02x", lbrt->entry[i].guid[j]); printf("\n"); } } @@ -6250,19 +6614,22 @@ static const char *nvme_feature_temp_sel_to_string(__u8 sel) } } -static void nvme_show_auto_pst(struct nvme_auto_pst *apst) +static void nvme_show_auto_pst(struct nvme_feat_auto_pst *apst) { int i; + __u64 value; printf( "\tAuto PST Entries"); printf("\t.................\n"); for (i = 0; i < 32; i++) { + value = le64_to_cpu(apst->apst_entry[i]); + printf("\tEntry[%2d] \n", i); printf("\t.................\n"); printf("\tIdle Time Prior to Transition (ITPT): %u ms\n", - (le32_to_cpu(apst[i].data) & 0xffffff00) >> 8); + (__u32)(value >> NVME_APST_ENTRY_ITPT_SHIFT) & NVME_APST_ENTRY_ITPT_MASK); printf("\tIdle Transition Power State (ITPS): %u\n", - (le32_to_cpu(apst[i].data) & 0x000000f8) >> 3); + (__u32)(value >> NVME_APST_ENTRY_ITPS_SHIFT ) & NVME_APST_ENTRY_ITPS_MASK); printf("\t.................\n"); } } @@ -6290,7 +6657,7 @@ static void nvme_show_timestamp(struct nvme_timestamp *ts) "continuously since the Timestamp value was initialized."); } -static void nvme_show_host_mem_buffer(struct nvme_host_mem_buffer *hmb) +static void nvme_show_host_mem_buffer(struct nvme_host_mem_buf_attrs *hmb) { printf("\tHost Memory Descriptor List Entry Count (HMDLEC): %u\n", le32_to_cpu(hmb->hmdlec)); @@ -6302,16 +6669,16 @@ static void nvme_show_host_mem_buffer(struct nvme_host_mem_buffer *hmb) le32_to_cpu(hmb->hsize)); } -static const char *nvme_show_ns_write_protect_config(__u8 state) +static const char *nvme_show_ns_wp_cfg(enum nvme_ns_write_protect_cfg state) { switch (state) { - case NVME_NS_NO_WRITE_PROTECT: + case NVME_NS_WP_CFG_NONE: return "No Write Protect"; - case NVME_NS_WRITE_PROTECT: + case NVME_NS_WP_CFG_PROTECT: return "Write Protect"; - case NVME_NS_WRITE_PROTECT_POWER_CYCLE: + case NVME_NS_WP_CFG_PROTECT_POWER_CYCLE: return "Write Protect Until Power Cycle"; - case NVME_NS_WRITE_PROTECT_PERMANENT: + case NVME_NS_WP_CFG_PROTECT_PERMANENT: return "Permanent Write Protect"; default: return "Reserved"; @@ -6325,9 +6692,9 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, int count, i; switch (dtype) { - case NVME_DIR_IDENTIFY: + case NVME_DIRECTIVE_DTYPE_IDENTIFY: switch (doper) { - case NVME_DIR_RCV_ID_OP_PARAM: + case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM: printf("\tDirective support \n"); printf("\t\tIdentify Directive : %s\n", (*field & 0x1) ? "supported":"not supported"); @@ -6344,9 +6711,9 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, "invalid directive operations for Identify Directives\n"); } break; - case NVME_DIR_STREAMS: + case NVME_DIRECTIVE_DTYPE_STREAMS: switch (doper) { - case NVME_DIR_RCV_ST_OP_PARAM: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM: printf("\tMax Streams Limit (MSL): %u\n", *(__u16 *) field); printf("\tNVM Subsystem Streams Available (NSSA): %u\n", @@ -6364,7 +6731,7 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, printf("\tNamespace Streams Open (NSO): %u\n", *(__u16 *) (field + 24)); break; - case NVME_DIR_RCV_ST_OP_STATUS: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS: count = *(__u16 *) field; printf("\tOpen Stream Count : %u\n", *(__u16 *) field); for ( i = 0; i < count; i++ ) { @@ -6372,7 +6739,7 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, *(__u16 *) (field + ((i + 1) * 2))); } break; - case NVME_DIR_RCV_ST_OP_RESOURCE: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE: printf("\tNamespace Streams Allocated (NSA): %u\n", result & 0xffff); break; @@ -6419,88 +6786,110 @@ static const char *nvme_plm_window(__u32 plm) void nvme_show_lba_status_info(__u32 result) { - printf("\tLBA Status Information Poll Interval (LSIPI) : %u\n", (result >> 16) & 0xffff); + printf("\tLBA Status Information Poll Interval (LSIPI) : %u\n", (result >> 16) & 0xffff); printf("\tLBA Status Information Report Interval (LSIRI): %u\n", result & 0xffff); } static void nvme_show_plm_config(struct nvme_plm_config *plmcfg) { - printf("\tEnable Event :%04x\n", le16_to_cpu(plmcfg->enable_event)); - printf("\tDTWIN Reads Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_reads_thresh)); - printf("\tDTWIN Writes Threshold:%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_writes_thresh)); - printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_time_thresh)); -} - -static char* nvme_show_mi_host_metadata_type_to_string(enum nvme_feat fid, __u8 type) -{ - switch (fid) { - case NVME_MI_FEAT_CTRL_METADATA: - switch (type) { - case NVME_MI_CTRL_METADATA_OS_CTRL_NAME: - return "Operating System Controller Name"; - case NVME_MI_CTRL_METADATA_OS_DRIVER_NAME: - return "Operating System Driver Name"; - case NVME_MI_CTRL_METADATA_OS_DRIVER_VER: - return "Operating System Driver Version"; - case NVME_MI_CTRL_METADATA_PRE_BOOT_CTRL_NAME: - return "Pre-boot Controller Name"; - case NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_NAME: - return "Pre-boot Driver Name"; - case NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_VER: - return "Pre-boot Driver Version"; - default: - return "Unknown Controller Type"; - } - case NVME_MI_FEAT_NS_METADATA: - switch (type) { - case NVME_MI_NS_METADATA_OS_NS_NAME: - return "Operating System Namespace Name"; - case NVME_MI_NS_METADATA_PRE_BOOT_NS_NAME: - return "Pre-boot Namespace Name"; - default: - return "Unknown Namespace Type"; - } - default: - return "Unknown Feature"; - } -} - -static void nvme_show_mi_host_metadata(enum nvme_feat fid, - struct nvme_mi_host_metadata *data) -{ - struct nvme_mi_host_metadata_element_desc *desc = &data->descs[0]; - int i; - char val[4096]; - __u16 len; - - printf("\tNum Metadata Element Descriptors: %d\n", data->ndesc); - for (i = 0; i < data->ndesc; i++) { - len = le16_to_cpu(desc->len); - strncpy(val, (char *)desc->val, min(sizeof(val) - 1, len)); - - printf("\tElement[%-3d]:\n", i); - printf("\t\tType : 0x%02x (%s)\n", desc->type, - nvme_show_mi_host_metadata_type_to_string(fid, desc->type)); - printf("\t\tRevision : %d\n", desc->rev); - printf("\t\tLength : %d\n", len); - printf("\t\tValue : %s\n", val); - - desc = (struct nvme_mi_host_metadata_element_desc *) - &desc->val[desc->len]; - } -} - -void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, - unsigned char *buf) + printf("\tEnable Event :%04x\n", le16_to_cpu(plmcfg->ee)); + printf("\tDTWIN Reads Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinrt)); + printf("\tDTWIN Writes Threshold:%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinwt)); + printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwintt)); +} + +static char *nvme_show_host_metadata_type_to_string(enum nvme_features_id fid, + __u8 type) +{ + switch (fid) { + case NVME_FEAT_FID_ENH_CTRL_METADATA: + case NVME_FEAT_FID_CTRL_METADATA: + switch (type) { + case NVME_CTRL_METADATA_OS_CTRL_NAME: + return "Operating System Controller Name"; + case NVME_CTRL_METADATA_OS_DRIVER_NAME: + return "Operating System Driver Name"; + case NVME_CTRL_METADATA_OS_DRIVER_VER: + return "Operating System Driver Version"; + case NVME_CTRL_METADATA_PRE_BOOT_CTRL_NAME: + return "Pre-boot Controller Name"; + case NVME_CTRL_METADATA_PRE_BOOT_DRIVER_NAME: + return "Pre-boot Driver Name"; + case NVME_CTRL_METADATA_PRE_BOOT_DRIVER_VER: + return "Pre-boot Driver Version"; + case NVME_CTRL_METADATA_SYS_PROC_MODEL: + return "System Processor Model"; + case NVME_CTRL_METADATA_CHIPSET_DRV_NAME: + return "Chipset Driver Name"; + case NVME_CTRL_METADATA_CHIPSET_DRV_VERSION: + return "Chipset Driver Version"; + case NVME_CTRL_METADATA_OS_NAME_AND_BUILD: + return "Operating System Name and Build"; + case NVME_CTRL_METADATA_SYS_PROD_NAME: + return "System Product Name"; + case NVME_CTRL_METADATA_FIRMWARE_VERSION: + return "Firmware Version"; + case NVME_CTRL_METADATA_OS_DRIVER_FILENAME: + return "Operating System Driver Filename"; + case NVME_CTRL_METADATA_DISPLAY_DRV_NAME: + return "Display Driver Name"; + case NVME_CTRL_METADATA_DISPLAY_DRV_VERSION: + return "Display Driver Version"; + case NVME_CTRL_METADATA_HOST_DET_FAIL_REC: + return "Host-Determined Failure Record"; + default: + return "Unknown Controller Type"; + } + case NVME_FEAT_FID_NS_METADATA: + switch (type) { + case NVME_NS_METADATA_OS_NS_NAME: + return "Operating System Namespace Name"; + case NVME_NS_METADATA_PRE_BOOT_NS_NAME: + return "Pre-boot Namespace Name"; + case NVME_NS_METADATA_OS_NS_QUAL_1: + return "Operating System Namespace Name Qualifier 1"; + case NVME_NS_METADATA_OS_NS_QUAL_2: + return "Operating System Namespace Name Qualifier 2"; + default: + return "Unknown Namespace Type"; + } + default: + return "Unknown Feature"; + } +} + +static void nvme_show_host_metadata(enum nvme_features_id fid, + struct nvme_host_metadata *data) +{ + struct nvme_metadata_element_desc *desc = &data->descs[0]; + int i; + char val[4096]; + __u16 len; + + printf("\tNum Metadata Element Descriptors: %d\n", data->ndesc); + for (i = 0; i < data->ndesc; i++) { + len = le16_to_cpu(desc->len); + strncpy(val, (char *)desc->val, min(sizeof(val) - 1, len)); + + printf("\tElement[%-3d]:\n", i); + printf("\t\tType : 0x%02x (%s)\n", desc->type, + nvme_show_host_metadata_type_to_string(fid, desc->type)); + printf("\t\tRevision : %d\n", desc->rev); + printf("\t\tLength : %d\n", len); + printf("\t\tValue : %s\n", val); + + desc = (struct nvme_metadata_element_desc *) + &desc->val[desc->len]; + } +} + +void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf) { __u8 field; uint64_t ull; switch (fid) { - case NVME_FEAT_NONE: - printf("\tFeature Identifier Reserved\n"); - break; - case NVME_FEAT_ARBITRATION: + case NVME_FEAT_FID_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); @@ -6510,135 +6899,153 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, else printf("%u\n", 1 << (result & 0x00000007)); break; - case NVME_FEAT_POWER_MGMT: + case NVME_FEAT_FID_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: + case NVME_FEAT_FID_LBA_RANGE: field = result & 0x0000003f; printf("\tNumber of LBA Ranges (NUM): %u\n", field + 1); nvme_show_lba_range((struct nvme_lba_range_type *)buf, field); break; - case NVME_FEAT_TEMP_THRESH: + case NVME_FEAT_FID_TEMP_THRESH: field = (result & 0x00300000) >> 20; - printf("\tThreshold Type Select (THSEL): %u - %s\n", field, nvme_feature_temp_type_to_string(field)); + 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): %ld C (%u Kelvin)\n", + printf("\tThreshold Temperature Select (TMPSEL): %u - %s\n", + field, nvme_feature_temp_sel_to_string(field)); + printf("\tTemperature Threshold (TMPTH): %ld°C (%u Kelvin)\n", kelvin_to_celsius(result & 0x0000ffff), result & 0x0000ffff); 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); + case NVME_FEAT_FID_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: + case NVME_FEAT_FID_VOLATILE_WC: printf("\tVolatile Write Cache Enable (WCE): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); break; - case NVME_FEAT_NUM_QUEUES: + case NVME_FEAT_FID_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: + case NVME_FEAT_FID_IRQ_COALESCE: printf("\tAggregation Time (TIME): %u usec\n", ((result & 0x0000ff00) >> 8) * 100); printf("\tAggregation Threshold (THR): %u\n", (result & 0x000000ff) + 1); break; - case NVME_FEAT_IRQ_CONFIG: + case NVME_FEAT_FID_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: + case NVME_FEAT_FID_WRITE_ATOMIC: printf("\tDisable Normal (DN): %s\n", (result & 0x00000001) ? "True":"False"); break; - case NVME_FEAT_ASYNC_EVENT: - printf("\tZone Descriptor Changed Notices: %s\n", ((result >> 27) & 0x1) ? "Send async event":"Do not send async event"); - printf("\tDiscovery Log Page Change Notices: %s\n", ((result & 0x80000000) >> 31) ? "Send async event":"Do not send async event"); - printf("\tEndurance Group Event Aggregate Log Change Notices: %s\n", ((result & 0x00004000) >> 14) ? "Send async event":"Do not send async event"); - printf("\tLBA Status Information Notices : %s\n", ((result & 0x00002000) >> 13) ? "Send async event":"Do not send async event"); - printf("\tPredictable Latency Event Aggregate Log Change Notices: %s\n", ((result & 0x00001000) >> 12) ? "Send async event":"Do not send async event"); - printf("\tAsymmetric Namespace Access Change Notices: %s\n", ((result & 0x00000800) >> 11) ? "Send async event":"Do not send async event"); - printf("\tTelemetry Log Notices : %s\n", ((result & 0x00000400) >> 10) ? "Send async event":"Do not send 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 async event":"Do not send async event"); - printf("\tSMART / Health Critical Warnings: %s\n", (result & 0x000000ff) ? "Send async event":"Do not send async event"); + case NVME_FEAT_FID_ASYNC_EVENT: + printf("\tDiscovery Log Page Change Notices: %s\n", + ((result & 0x80000000) >> 31) ? "Send async event":"Do not send async event"); + printf("\tEndurance Group Event Aggregate Log Change Notices: %s\n", + ((result & 0x00004000) >> 14) ? "Send async event":"Do not send async event"); + printf("\tLBA Status Information Notices : %s\n", + ((result & 0x00002000) >> 13) ? "Send async event":"Do not send async event"); + printf("\tPredictable Latency Event Aggregate Log Change Notices: %s\n", + ((result & 0x00001000) >> 12) ? "Send async event":"Do not send async event"); + printf("\tAsymmetric Namespace Access Change Notices: %s\n", + ((result & 0x00000800) >> 11) ? "Send async event":"Do not send async event"); + printf("\tTelemetry Log Notices : %s\n", + ((result & 0x00000400) >> 10) ? "Send async event":"Do not send 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 async event":"Do not send async 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"); - nvme_show_auto_pst((struct nvme_auto_pst *)buf); + case NVME_FEAT_FID_AUTO_PST: + printf("\tAutonomous Power State Transition Enable (APSTE): %s\n", + (result & 0x00000001) ? "Enabled":"Disabled"); + nvme_show_auto_pst((struct nvme_feat_auto_pst *)buf); break; - case NVME_FEAT_HOST_MEM_BUF: + case NVME_FEAT_FID_HOST_MEM_BUF: printf("\tEnable Host Memory (EHM): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); - nvme_show_host_mem_buffer((struct nvme_host_mem_buffer *)buf); + nvme_show_host_mem_buffer((struct nvme_host_mem_buf_attrs *)buf); break; - case NVME_FEAT_SW_PROGRESS: - printf("\tPre-boot Software Load Count (PBSLC): %u\n", result & 0x000000ff); + case NVME_FEAT_FID_TIMESTAMP: + nvme_show_timestamp((struct nvme_timestamp *)buf); break; - case NVME_FEAT_PLM_CONFIG: + case NVME_FEAT_FID_KATO: + printf("\tKeep Alive Timeout (KATO) in milliseconds: %u\n", result); + break; + case NVME_FEAT_FID_HCTM: + printf("\tThermal Management Temperature 1 (TMT1) : %u Kelvin (%ld°C)\n", + result >> 16, kelvin_to_celsius(result >> 16)); + printf("\tThermal Management Temperature 2 (TMT2) : %u Kelvin (%ld°C)\n", + result & 0x0000ffff, kelvin_to_celsius(result & 0x0000ffff)); + break; + case NVME_FEAT_FID_NOPSC: + printf("\tNon-Operational Power State Permissive Mode Enable (NOPPME): %s\n", + (result & 1) ? "True" : "False"); + break; + case NVME_FEAT_FID_RRL: + printf("\tRead Recovery Level (RRL): %u\n", result & 0xf); + break; + case NVME_FEAT_FID_PLM_CONFIG: printf("\tPredictable Latency Window Enabled: %s\n", result & 0x1 ? "True":"False"); nvme_show_plm_config((struct nvme_plm_config *)buf); break; - case NVME_FEAT_PLM_WINDOW: + case NVME_FEAT_FID_PLM_WINDOW: printf("\tWindow Select: %s", nvme_plm_window(result)); break; - case NVME_LBA_STATUS_INFO: + case NVME_FEAT_FID_LBA_STS_INTERVAL: nvme_show_lba_status_info(result); break; - case NVME_FEAT_ENDURANCE: + case NVME_FEAT_FID_HOST_BEHAVIOR: + printf("\tHost Behavior Support: %s\n", (buf[0] & 0x1) ? "True" : "False"); + break; + case NVME_FEAT_FID_SANITIZE: + printf("\tNo-Deallocate Response Mode (NODRM) : %u\n", result & 0x1); + break; + case NVME_FEAT_FID_ENDURANCE_EVT_CFG: printf("\tEndurance Group Identifier (ENDGID): %u\n", result & 0xffff); printf("\tEndurance Group Critical Warnings : %u\n", (result >> 16) & 0xff); break; - case NVME_FEAT_IOCS_PROFILE: - printf("\tI/O Command Set Comination Index(IOCSCI): %u\n", result & 0x1ff); + case NVME_FEAT_FID_IOCS_PROFILE: + printf("\tI/O Command Set Profile: %s\n", result & 0x1 ? "True":"False"); + break; + case NVME_FEAT_FID_SPINUP_CONTROL: + printf("\tSpinup control feature Enabled: %s\n", (result & 1) ? "True" : "False"); + break; + case NVME_FEAT_FID_ENH_CTRL_METADATA: + case NVME_FEAT_FID_CTRL_METADATA: + case NVME_FEAT_FID_NS_METADATA: + nvme_show_host_metadata(fid, (struct nvme_host_metadata *)buf); break; - case NVME_FEAT_HOST_ID: + case NVME_FEAT_FID_SW_PROGRESS: + printf("\tPre-boot Software Load Count (PBSLC): %u\n", result & 0x000000ff); + break; + case NVME_FEAT_FID_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"); + case NVME_FEAT_FID_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: + case NVME_FEAT_FID_RESV_PERSIST: printf("\tPersist Through Power Loss (PTPL): %s\n", (result & 0x00000001) ? "True":"False"); break; - case NVME_FEAT_WRITE_PROTECT: - printf("\tNamespace Write Protect state: %s\n", nvme_show_ns_write_protect_config(result & 0x7)); - break; - case NVME_FEAT_TIMESTAMP: - nvme_show_timestamp((struct nvme_timestamp *)buf); - break; - case NVME_FEAT_HCTM: - printf("\tThermal Management Temperature 1 (TMT1) : %u Kelvin (%ld C)\n", - result >> 16, kelvin_to_celsius(result >> 16)); - printf("\tThermal Management Temperature 2 (TMT2) : %u Kelvin (%ld C)\n", - result & 0x0000ffff, kelvin_to_celsius(result & 0x0000ffff)); - break; - case NVME_FEAT_KATO: - printf("\tKeep Alive Timeout (KATO) in milliseconds: %u\n", result); - break; - case NVME_FEAT_NOPSC: - printf("\tNon-Operational Power State Permissive Mode Enable (NOPPME): %s\n", (result & 1) ? "True" : "False"); - break; - case NVME_FEAT_HOST_BEHAVIOR: - printf("\tHost Behavior Support Advanced Command Retry Enable (ACRE): %s\n", (buf[0] == 1) ? "True" : "False"); - printf("\tHost Behavior Support Extended Telemetry Data Area 4 Supported (ETDAS): %s\n", (buf[1] == 1) ? "True" : "False"); - printf("\tHost Behavior Support LBA Format Extension Enable (LBAFEE): %s\n", (buf[2] == 1) ? "True" : "False"); + case NVME_FEAT_FID_WRITE_PROTECT: + printf("\tNamespace Write Protect: %s\n", nvme_show_ns_wp_cfg(result)); break; - case NVME_FEAT_SANITIZE: - printf("\tNo-Deallocate Response Mode (NODRM) : %u\n", result & 0x1); - break; - case NVME_FEAT_RRL: - printf("\tRead Recovery Level (RRL): %u\n", result & 0xf); - break; - case NVME_MI_FEAT_CTRL_METADATA: - case NVME_MI_FEAT_NS_METADATA: - nvme_show_mi_host_metadata(fid, (struct nvme_mi_host_metadata *)buf); - break; - case NVME_FEAT_SPINUP_CONTROL: - printf("\tSpinup control feature Enabled: %s\n", (result & 1) ? "True" : "False"); + default: break; } } @@ -6676,409 +7083,383 @@ void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len, } } -static void nvme_show_list_item(struct nvme_namespace *n) +static void nvme_dev_full_path(nvme_ns_t n, char *path, size_t len) { - long long lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - double nsze = le64_to_cpu(n->ns.nsze) * lba; - double nuse = le64_to_cpu(n->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], path[256]; struct stat st; - int ret; - if (!n->ctrl) + snprintf(path, len, "/dev/%s", nvme_ns_get_name(n)); + if (stat(path, &st) == 0) return; - sprintf(path, "%s%s", n->ctrl->path, n->name); - ret = stat(path, &st); - if (ret < 0) + snprintf(path, len, "/dev/spdk/%s", nvme_ns_get_name(n)); + if (stat(path, &st) == 0) return; - 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, - le16_to_cpu(n->ns.lbaf[(n->ns.flbas & 0x0f)].ms)); - printf("%-21s %-*.*s %-*.*s %-9d %-26s %-16s %-.*s\n", path, - (int)sizeof(n->ctrl->id.sn), (int)sizeof(n->ctrl->id.sn), n->ctrl->id.sn, - (int)sizeof(n->ctrl->id.mn), (int)sizeof(n->ctrl->id.mn), n->ctrl->id.mn, - n->nsid, usage, format, (int)sizeof(n->ctrl->id.fr), n->ctrl->id.fr); + /* + * We could start trying to search for it but let's make + * it simple and just don't show the path at all. + */ + snprintf(path, len, "%s", nvme_ns_get_name(n)); } -static void nvme_show_simple_list(struct nvme_topology *t) +static void nvme_generic_full_path(nvme_ns_t n, char *path, size_t len) { - int i, j, k; - - printf("%-21s %-20s %-40s %-9s %-26s %-16s %-8s\n", - "Node", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev"); - printf("%-.21s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", dash, dash, - dash, dash, dash, dash, dash); - - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; + int head_instance; + int instance; + struct stat st; - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + sscanf(nvme_ns_get_name(n), "nvme%dn%d", &instance, &head_instance); + snprintf(path, len, "/dev/ng%dn%d", instance, head_instance); - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; - nvme_show_list_item(n); - } - } + if (stat(path, &st) == 0) + return; - for (j = 0; j < s->nr_namespaces; j++) { - struct nvme_namespace *n = &s->namespaces[j]; - nvme_show_list_item(n); - } - } + snprintf(path, len, "/dev/spkd/ng%dn%d", instance, head_instance); + if (stat(path, &st) == 0) + return; + /* + * We could start trying to search for it but let's make + * it simple and just don't show the path at all. + */ + snprintf(path, len, "ng%dn%d", instance, head_instance); } -static void nvme_show_details_ns(struct nvme_namespace *n, bool ctrl) +void nvme_show_list_item(nvme_ns_t n) { - long long lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - double nsze = le64_to_cpu(n->ns.nsze) * lba; - double nuse = le64_to_cpu(n->ns.nuse) * lba; + char usage[128] = { 0 }, format[128] = { 0 }; + char devname[128] = { 0 }; char genname[128] = { 0 }; + + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * 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]; - char generic[128]; + snprintf(usage, sizeof(usage), "%6.2f %2sB / %6.2f %2sB", nuse, + u_suffix, nsze, s_suffix); + snprintf(format, sizeof(format), "%3.0f %2sB + %2d B", (double)lba, + l_suffix, nvme_ns_get_meta_size(n)); - int instance; - int head_instance; + nvme_dev_full_path(n, devname, sizeof(devname)); + nvme_generic_full_path(n, genname, sizeof(genname)); - if (!n->ctrl) - return; + printf("%-21s %-21s %-20s %-40s %-9d %-26s %-16s %-8s\n", + devname, genname, nvme_ns_get_serial(n), + nvme_ns_get_model(n), nvme_ns_get_nsid(n), usage, format, + nvme_ns_get_firmware(n)); +} - 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, - le16_to_cpu(n->ns.lbaf[(n->ns.flbas & 0x0f)].ms)); +static void nvme_show_simple_list(nvme_root_t r) +{ + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_ns_t n; - sscanf(n->name, "nvme%dn%d", &instance, &head_instance); - sprintf(generic, "ng%dn%d", instance, head_instance); + printf("%-21s %-21s %-20s %-40s %-9s %-26s %-16s %-8s\n", + "Node", "Generic", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev"); + printf("%-.21s %-.21s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", + dash, dash, dash, dash, dash, dash, dash, dash); - printf("%-12s %-16s %-8d %-26s %-16s ", n->name, generic, n->nsid, usage, format); + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ns(s, n) + nvme_show_list_item(n); - if (ctrl) - printf("%s", n->ctrl->name); - else { - struct nvme_subsystem *s = n->ctrl->subsys; - int i, j; - bool comma = false; + nvme_subsystem_for_each_ctrl(s, c) + nvme_ctrl_for_each_ns(c, n) + nvme_show_list_item(n); + } + } +} - for (i = 0; i < s->nr_ctrls; i++) { - struct nvme_ctrl *c = &s->ctrls[i]; +static void nvme_show_ns_details(nvme_ns_t n) +{ + char usage[128] = { 0 }, format[128] = { 0 }; + char devname[128] = { 0 }, genname[128] = { 0 }; - for (j = 0; j < c->nr_namespaces; j++) { - struct nvme_namespace *ns = &c->namespaces[j]; + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; - if (ns->nsid == n->nsid) { - printf("%s%s", comma ? ", " : "", - c->name); - comma = true; - } - } - } - } - printf("\n"); + const char *s_suffix = suffix_si_get(&nsze); + const char *u_suffix = suffix_si_get(&nuse); + const char *l_suffix = suffix_binary_get(&lba); + + 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, + nvme_ns_get_meta_size(n)); + + nvme_dev_full_path(n, devname, sizeof(devname)); + nvme_generic_full_path(n, genname, sizeof(genname)); + + printf("%-12s %-12s %-8x %-26s %-16s ", devname, + genname, nvme_ns_get_nsid(n), usage, format); } -static void nvme_show_detailed_list(struct nvme_topology *t) +static void nvme_show_detailed_list(nvme_root_t r) { - int i, j, k; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_path_t p; + nvme_ns_t n; - printf("NVM Express Subsystems\n\n"); printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers"); printf("%-.16s %-.96s %-.16s\n", dash, dash, dash); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - printf("%-16s %-96s ", s->name, s->subsysnqn); - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + bool first = true; + printf("%-16s %-96s ", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); - printf("%s%s", j ? ", " : "", c->name); + nvme_subsystem_for_each_ctrl(s, c) { + printf("%s%s", first ? "": ", ", + nvme_ctrl_get_name(c)); + first = false; + } + printf("\n"); } - printf("\n"); - }; + } + printf("\n"); - printf("\nNVM Express Controllers\n\n"); printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s %-16s\n", "Device", "SN", "MN", "FR", "TxPort", "Address", "Subsystem", "Namespaces"); printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.12s %-.16s\n", dash, dash, dash, dash, dash, dash, dash, dash); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - - for (j = 0; j < s->nr_ctrls; j++) { - bool comma = false; - struct nvme_ctrl *c = &s->ctrls[j]; - printf("%-8s %-.20s %-.40s %-.8s %-6s %-14s %-12s ", - c->name, c->id.sn, c->id.mn, c->id.fr, - c->transport ? : "", c->address ? : "", s->name); - - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + bool first = true; + + printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s ", + nvme_ctrl_get_name(c), + nvme_ctrl_get_serial(c), + nvme_ctrl_get_model(c), + nvme_ctrl_get_firmware(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_subsystem_get_name(s)); + + nvme_ctrl_for_each_ns(c, n) { + printf("%s%s", first ? "": ", ", + nvme_ns_get_name(n)); + first = false; + } - printf("%s%s", comma ? ", " : "", n->name); - comma = true; + nvme_ctrl_for_each_path(c, p) { + n = nvme_path_get_ns(p); + if (!n) + continue; + printf("%s%s", first ? "": ", ", + nvme_ns_get_name(n)); + first = false; + } + printf("\n"); } - printf("\n"); } } + printf("\n"); - printf("\nNVM Express Namespaces\n\n"); - printf("%-12s %-12s %-8s %-26s %-16s %-16s\n", "Device", "Generic", "NSID", "Usage", "Format", "Controllers"); - printf("%-.12s %-.12s %-.8s %-.26s %-.16s %-.16s\n", dash, dash, dash, dash, dash, dash); - - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - - if (s->nr_namespaces) { - for (j = 0; j < s->nr_namespaces; j++) { - struct nvme_namespace *n = &s->namespaces[j]; - nvme_show_details_ns(n, false); + printf("%-12s %-12s %-8s %-26s %-16s %-16s\n", "Device", "Generic", + "NSID", "Usage", "Format", "Controllers"); + printf("%-.12s %-.12s %-.8s %-.26s %-.16s %-.16s\n", dash, dash, dash, + dash, dash, dash); + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + nvme_ctrl_for_each_ns(c, n) { + nvme_show_ns_details(n); + printf("%s\n", nvme_ctrl_get_name(c)); + } } - } else { - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; - nvme_show_details_ns(n, true); + nvme_subsystem_for_each_ns(s, n) { + bool first = true; + + nvme_show_ns_details(n); + nvme_subsystem_for_each_ctrl(s, c) { + printf("%s%s", first ? "" : ", ", + nvme_ctrl_get_name(c)); + first = false; } + printf("\n"); } } } } -static void json_detail_ns(struct nvme_namespace *n, struct json_object *ns_attrs) +static void json_detail_list(nvme_root_t r) { - long long lba; - double nsze, nuse; - - lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - nsze = le64_to_cpu(n->ns.nsze) * lba; - nuse = le64_to_cpu(n->ns.nuse) * lba; - - json_object_add_value_string(ns_attrs, "NameSpace", n->name); - json_object_add_value_uint(ns_attrs, "NSID", n->nsid); - - json_object_add_value_uint(ns_attrs, "UsedBytes", nuse); - json_object_add_value_uint(ns_attrs, "MaximumLBA", - le64_to_cpu(n->ns.nsze)); - json_object_add_value_uint(ns_attrs, "PhysicalSize", nsze); - json_object_add_value_uint(ns_attrs, "SectorSize", lba); -} + struct json_object *jroot = json_create_object(); + struct json_object *jdev = json_create_array(); -static void json_detail_list(struct nvme_topology *t) -{ - int i, j, k; - struct json_object *root; - struct json_object *devices; - char formatter[41] = { 0 }; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_path_t p; + nvme_ns_t n; - root = json_create_object(); - devices = json_create_array(); - - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - struct json_object *subsys_attrs; - struct json_object *namespaces, *ctrls; - - subsys_attrs = json_create_object(); - json_object_add_value_string(subsys_attrs, "Subsystem", s->name); - json_object_add_value_string(subsys_attrs, "SubsystemNQN", s->subsysnqn); - - ctrls = json_create_array(); - json_object_add_value_array(subsys_attrs, "Controllers", ctrls); - for (j = 0; j < s->nr_ctrls; j++) { - struct json_object *ctrl_attrs = json_create_object(); - struct nvme_ctrl *c = &s->ctrls[j]; - struct json_object *namespaces; - - json_object_add_value_string(ctrl_attrs, "Controller", c->name); - if (c->transport) - json_object_add_value_string(ctrl_attrs, "Transport", c->transport); - if (c->address) - json_object_add_value_string(ctrl_attrs, "Address", c->address); - if (c->state) - json_object_add_value_string(ctrl_attrs, "State", c->state); - if (c->hostnqn) - json_object_add_value_string(ctrl_attrs, "HostNQN", c->hostnqn); - if (c->hostid) - json_object_add_value_string(ctrl_attrs, "HostID", c->hostid); - - format(formatter, sizeof(formatter), c->id.fr, sizeof(c->id.fr)); - json_object_add_value_string(ctrl_attrs, "Firmware", formatter); - - format(formatter, sizeof(formatter), c->id.mn, sizeof(c->id.mn)); - json_object_add_value_string(ctrl_attrs, "ModelNumber", formatter); - - format(formatter, sizeof(formatter), c->id.sn, sizeof(c->id.sn)); - json_object_add_value_string(ctrl_attrs, "SerialNumber", formatter); - - namespaces = json_create_array(); - - for (k = 0; k < c->nr_namespaces; k++) { - struct json_object *ns_attrs = json_create_object(); - struct nvme_namespace *n = &c->namespaces[k]; - - json_detail_ns(n, ns_attrs); - json_array_add_value_object(namespaces, ns_attrs); - } - if (k) - json_object_add_value_array(ctrl_attrs, "Namespaces", namespaces); - else - json_free_array(namespaces); + nvme_for_each_host(r, h) { + struct json_object *hss = json_create_object(); + struct json_object *jsslist = json_create_array(); - json_array_add_value_object(ctrls, ctrl_attrs); - } + json_object_add_value_string(hss, "HostNQN", nvme_host_get_hostnqn(h)); + json_object_add_value_string(hss, "HostID", nvme_host_get_hostid(h)); - namespaces = json_create_array(); - for (k = 0; k < s->nr_namespaces; k++) { - struct json_object *ns_attrs = json_create_object(); - struct nvme_namespace *n = &s->namespaces[k]; + nvme_for_each_subsystem(h , s) { + struct json_object *jss = json_create_object(); + struct json_object *jctrls = json_create_array(); + struct json_object *jnss = json_create_array(); - json_detail_ns(n, ns_attrs); - json_array_add_value_object(namespaces, ns_attrs); - } - if (k) - json_object_add_value_array(subsys_attrs, "Namespaces", namespaces); - else - json_free_array(namespaces); + json_object_add_value_string(jss, "Subsystem", nvme_subsystem_get_name(s)); + json_object_add_value_string(jss, "SubsystemNQN", nvme_subsystem_get_nqn(s)); - json_array_add_value_object(devices, subsys_attrs); - } + nvme_subsystem_for_each_ctrl(s, c) { + struct json_object *jctrl = json_create_object(); + struct json_object *jnss = json_create_array(); + struct json_object *jpaths = json_create_array(); - json_object_add_value_array(root, "Devices", devices); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); -} + json_object_add_value_string(jctrl, "Controller", nvme_ctrl_get_name(c)); + json_object_add_value_string(jctrl, "SerialNumber", nvme_ctrl_get_serial(c)); + json_object_add_value_string(jctrl, "ModelNumber", nvme_ctrl_get_model(c)); + json_object_add_value_string(jctrl, "Firmware", nvme_ctrl_get_firmware(c)); + json_object_add_value_string(jctrl, "Transport", nvme_ctrl_get_transport(c)); + json_object_add_value_string(jctrl, "Address", nvme_ctrl_get_address(c)); -static void json_simple_ns(struct nvme_namespace *n, struct json_object *devices) -{ - struct json_object *device_attrs; - char formatter[41] = { 0 }; - double nsze, nuse; - int ret, index = -1; - long long lba; - char *devnode; - struct stat st; + nvme_ctrl_for_each_ns(c, n) { + struct json_object *jns = json_create_object(); + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; - if (!n->ctrl) - return; + json_object_add_value_string(jns, "NameSpace", nvme_ns_get_name(n)); + json_object_add_value_int(jns, "NSID", nvme_ns_get_nsid(n)); + json_object_add_value_int(jns, "UsedBytes", nuse); + json_object_add_value_int(jns, "MaximumLBA", nvme_ns_get_lba_count(n)); + json_object_add_value_int(jns, "PhysicalSize", nsze); + json_object_add_value_int(jns, "SectorSize", lba); - if (asprintf(&devnode, "%s%s", n->ctrl->path, n->name) < 0) - return; + json_array_add_value_object(jnss, jns); + } + json_object_add_value_object(jctrl, "Namespaces", jnss); - ret = stat(devnode, &st); - if (ret < 0) - return; + nvme_ctrl_for_each_path(c, p) { + struct json_object *jpath = json_create_object(); - device_attrs = json_create_object(); - json_object_add_value_int(device_attrs, "NameSpace", n->nsid); + json_object_add_value_string(jpath, "Path", nvme_path_get_name(p)); + json_object_add_value_string(jpath, "ANAState", nvme_path_get_ana_state(p)); - json_object_add_value_string(device_attrs, "DevicePath", devnode); - free(devnode); + json_array_add_value_object(jpaths, jpath); + } + json_object_add_value_object(jctrl, "Paths", jpaths); - format(formatter, sizeof(formatter), - n->ctrl->id.fr, - sizeof(n->ctrl->id.fr)); + json_array_add_value_object(jctrls, jctrl); + } + json_object_add_value_object(jss, "Controllers", jctrls); - json_object_add_value_string(device_attrs, "Firmware", formatter); + nvme_subsystem_for_each_ns(s, n) { + struct json_object *jns = json_create_object(); - if (sscanf(n->ctrl->name, "nvme%d", &index) == 1) - json_object_add_value_int(device_attrs, "Index", index); + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; - format(formatter, sizeof(formatter), - n->ctrl->id.mn, - sizeof(n->ctrl->id.mn)); + json_object_add_value_string(jns, "NameSpace", nvme_ns_get_name(n)); + json_object_add_value_int(jns, "NSID", nvme_ns_get_nsid(n)); + json_object_add_value_int(jns, "UsedBytes", nuse); + json_object_add_value_int(jns, "MaximumLBA", nvme_ns_get_lba_count(n)); + json_object_add_value_int(jns, "PhysicalSize", nsze); + json_object_add_value_int(jns, "SectorSize", lba); - json_object_add_value_string(device_attrs, "ModelNumber", formatter); + json_array_add_value_object(jnss, jns); + } + json_object_add_value_object(jss, "Namespaces", jnss); - if (index >= 0 && n->ctrl->transport && !strcmp(n->ctrl->transport, "pcie")) { - char *product = nvme_product_name(index); + json_array_add_value_object(jsslist, jss); + } - json_object_add_value_string(device_attrs, "ProductName", product); - free((void*)product); + json_object_add_value_object(hss, "Subsystems", jsslist); + json_array_add_value_object(jdev, hss); } + json_object_add_value_array(jroot, "Devices", jdev); + json_print_object(jroot, NULL); + printf("\n"); + json_free_object(jroot); +} - format(formatter, sizeof(formatter), - n->ctrl->id.sn, - sizeof(n->ctrl->id.sn)); +static struct json_object *json_list_item(nvme_ns_t n) +{ + struct json_object *jdevice = json_create_object(); + char devname[128] = { 0 }; - json_object_add_value_string(device_attrs, "SerialNumber", formatter); + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; - lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - nsze = le64_to_cpu(n->ns.nsze) * lba; - nuse = le64_to_cpu(n->ns.nuse) * lba; + nvme_dev_full_path(n, devname, sizeof(devname)); - json_object_add_value_uint(device_attrs, "UsedBytes", nuse); - json_object_add_value_uint(device_attrs, "MaximumLBA", - le64_to_cpu(n->ns.nsze)); - json_object_add_value_uint(device_attrs, "PhysicalSize", nsze); - json_object_add_value_uint(device_attrs, "SectorSize", lba); + json_object_add_value_int(jdevice, "NameSpace", nvme_ns_get_nsid(n)); + json_object_add_value_string(jdevice, "DevicePath", devname); + json_object_add_value_string(jdevice, "Firmware", nvme_ns_get_firmware(n)); + json_object_add_value_string(jdevice, "ModelNumber", nvme_ns_get_model(n)); + json_object_add_value_string(jdevice, "SerialNumber", nvme_ns_get_serial(n)); + json_object_add_value_int(jdevice, "UsedBytes", nuse); + json_object_add_value_int(jdevice, "MaximumLBA", nvme_ns_get_lba_count(n)); + json_object_add_value_int(jdevice, "PhysicalSize", nsze); + json_object_add_value_int(jdevice, "SectorSize", lba); - json_array_add_value_object(devices, device_attrs); + return jdevice; } -static void json_simple_list(struct nvme_topology *t) +static void json_simple_list(nvme_root_t r) { - struct json_object *root; - struct json_object *devices; - int i, j, k; + struct json_object *jroot = json_create_object(); + struct json_object *jdevices = json_create_array(); - root = json_create_object(); - devices = json_create_array(); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_ns_t n; - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ns(s, n) + json_array_add_value_object(jdevices, + json_list_item(n)); - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; - json_simple_ns(n, devices); - } - } - - for (j = 0; j < s->nr_namespaces; j++) { - struct nvme_namespace *n = &s->namespaces[j]; - json_simple_ns(n, devices); + nvme_subsystem_for_each_ctrl(s, c) + nvme_ctrl_for_each_ns(c, n) + json_array_add_value_object(jdevices, + json_list_item(n)); } } - json_object_add_value_array(root, "Devices", devices); - json_print_object(root, NULL); + json_object_add_value_array(jroot, "Devices", jdevices); + json_print_object(jroot, NULL); printf("\n"); - json_free_object(root); + json_free_object(jroot); } -static void json_print_list_items(struct nvme_topology *t, +static void json_print_list_items(nvme_root_t r, enum nvme_print_flags flags) { if (flags & VERBOSE) - json_detail_list(t); + json_detail_list(r); else - json_simple_list(t); + json_simple_list(r); } -void nvme_show_list_items(struct nvme_topology *t, enum nvme_print_flags flags) +void nvme_show_list_items(nvme_root_t r, enum nvme_print_flags flags) { if (flags & JSON) - json_print_list_items(t, flags); + json_print_list_items(r, flags); else if (flags & VERBOSE) - nvme_show_detailed_list(t); + nvme_show_detailed_list(r); else - nvme_show_simple_list(t); + nvme_show_simple_list(r); } diff --git a/nvme-print.h b/nvme-print.h index 15b9d2a..7c1ac26 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -4,122 +4,134 @@ #include "nvme.h" #include <inttypes.h> +#include <ccan/list/list.h> + +typedef struct nvme_effects_log_node { + enum nvme_csi csi; + struct nvme_cmd_effects_log effects; + struct list_node node; +} nvme_effects_log_node_t; + 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 nvme_show_status(__u16 status); +void nvme_show_lba_status_info(__u32 result); void nvme_show_relatives(const char *name); -const char *nvme_cmd_to_string(int admin, __u8 opcode); -void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, + +void nvme_show_id_iocs(struct nvme_id_iocs *iocs); +void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root)); -void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode); void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, - enum nvme_print_flags flags); + unsigned int lba_index, bool cap_only, enum nvme_print_flags flags); void nvme_show_cmd_set_independent_id_ns( - struct nvme_cmd_set_independent_id_ns *ns, unsigned int nsid, + struct nvme_id_independent_id_ns *ns, unsigned int nsid, enum nvme_print_flags flags); -void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11, +void nvme_show_resv_report(struct nvme_resv_status *status, int bytes, bool eds, enum nvme_print_flags flags); void nvme_show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges); +void nvme_show_supported_log(struct nvme_supported_log_pages *support, + const char *devname, enum nvme_print_flags flags); void nvme_show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname, enum nvme_print_flags flags); void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname, enum nvme_print_flags flags); -void nvme_show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname, +void nvme_show_ana_log(struct nvme_ana_log *ana_log, const char *devname, enum nvme_print_flags flags, size_t len); void nvme_show_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_entries, __u32 size, const char *devname, enum nvme_print_flags flags); -void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname, +void nvme_show_fw_log(struct nvme_firmware_slot *fw_log, const char *devname, enum nvme_print_flags flags); -void nvme_show_effects_log(struct nvme_effects_log_page *effects, unsigned int flags); -void nvme_show_supported_log(struct nvme_support_log_pages *support, - const char *devname, enum nvme_print_flags flags); -void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, +void nvme_print_effects_log_pages(struct list_head *list, int flags); +void nvme_show_changed_ns_list_log(struct nvme_ns_list *log, const char *devname, enum nvme_print_flags flags); void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log, __u16 group_id, const char *devname, enum nvme_print_flags flags); void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, const char *devname, enum nvme_print_flags flags); -void json_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, - __u16 nvmset_id); void nvme_show_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, + struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id, const char *devname, enum nvme_print_flags flags); -void json_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, - __u64 log_entries); void nvme_show_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, + struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags); -void json_persistent_event_log(void *pevent_log_info, __u32 size); void nvme_show_persistent_event_log(void *pevent_log_info, __u8 action, __u32 size, const char *devname, enum nvme_print_flags flags); void json_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries); void nvme_show_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags); -void json_lba_status_log(void *lba_status); void nvme_show_lba_status_log(void *lba_status, __u32 size, const char *devname, enum nvme_print_flags flags); -void nvme_show_resv_notif_log(struct nvme_resv_notif_log *resv, +void nvme_show_resv_notif_log(struct nvme_resv_notification_log *resv, const char *devname, enum nvme_print_flags flags); void nvme_show_boot_part_log(void *bp_log, const char *devname, __u32 size, enum nvme_print_flags flags); -void nvme_show_fid_support_effects_log(struct nvme_fid_support_effects *fid_log, +void nvme_show_fid_support_effects_log(struct nvme_fid_supported_effects_log *fid_log, + const char *devname, enum nvme_print_flags flags); +void nvme_show_mi_cmd_support_effects_log(struct nvme_mi_cmd_supported_effects_log *mi_cmd_log, const char *devname, enum nvme_print_flags flags); +void nvme_show_media_unit_stat_log(struct nvme_media_unit_stat_log *mus, + enum nvme_print_flags flags); +void nvme_show_supported_cap_config_log(struct nvme_supported_cap_config_list_log *caplog, + enum nvme_print_flags flags); void nvme_show_ctrl_registers(void *bar, bool fabrics, enum nvme_print_flags flags); void nvme_show_single_property(int offset, uint64_t prop, int human); void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flags); void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len, enum nvme_print_flags flags); -void nvme_show_list_items(struct nvme_topology *t, enum nvme_print_flags flags); -void nvme_show_subsystem_list(struct nvme_topology *t, - enum nvme_print_flags flags); -void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id, +void nvme_show_list_items(nvme_root_t t, enum nvme_print_flags flags); +void nvme_show_subsystem_list(nvme_root_t t, enum nvme_print_flags flags); +void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id, enum nvme_print_flags flags); -void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps, +void nvme_show_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *cap, enum nvme_print_flags flags); -void nvme_show_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, +void nvme_show_list_secondary_ctrl(const struct nvme_secondary_ctrl_list *sc_list, __u32 count, enum nvme_print_flags flags); void nvme_show_id_ns_granularity_list(const struct nvme_id_ns_granularity_list *glist, enum nvme_print_flags flags); void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, enum nvme_print_flags flags); -void nvme_show_id_iocs(struct nvme_id_iocs *iocs, enum nvme_print_flags flags); -void nvme_show_list_ctrl(struct nvme_controller_list *ctrl_list, - enum nvme_print_flags flags); -void nvme_show_list_ns(__u32 *ns_list, enum nvme_print_flags flags); +void nvme_show_list_ctrl(struct nvme_ctrl_list *ctrl_list, + enum nvme_print_flags flags); void nvme_show_id_domain_list(struct nvme_id_domain_list *id_dom, enum nvme_print_flags flags); -void nvme_show_endurance_group_list(struct nvme_endurance_group_list *endgrp_list, +void nvme_show_endurance_group_list(struct nvme_id_endurance_group_list *endgrp_list, + enum nvme_print_flags flags); +void nvme_show_list_ns(struct nvme_ns_list *ns_list, enum nvme_print_flags flags); -void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned char *buf); +void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf); void nvme_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 result, void *buf, __u32 len, enum nvme_print_flags flags); void nvme_show_select_result(__u32 result); -void nvme_show_lba_status_info(__u32 result); void nvme_show_zns_id_ctrl(struct nvme_zns_id_ctrl *ctrl, unsigned int mode); void nvme_show_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm, enum nvme_print_flags flags); +void nvme_show_nvm_id_ns(struct nvme_nvm_id_ns *nvm_ns, unsigned int nsid, + struct nvme_id_ns *ns, unsigned int lba_index, + bool cap_only, enum nvme_print_flags flags); void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, struct nvme_id_ns *id_ns, unsigned long flags); void nvme_show_zns_changed( struct nvme_zns_changed_zone_log *log, unsigned long flags); void nvme_show_zns_report_zones(void *report, __u32 descs, - __u8 ext_size, __u32 report_size, unsigned long flags); + __u8 ext_size, __u32 report_size, unsigned long flags, + struct json_object *zone_list); +void json_nvme_finish_zone_list(__u64 nr_zones, + struct json_object *zone_list); +void nvme_show_list_item(nvme_ns_t n); -const char *nvme_status_to_string(__u16 status); +const char *nvme_cmd_to_string(int admin, __u8 opcode); const char *nvme_select_to_string(int sel); -const char *nvme_feature_to_string(enum nvme_feat feature); +const char *nvme_feature_to_string(enum nvme_features_id feature); const char *nvme_register_to_string(int reg); #endif diff --git a/nvme-rpmb.c b/nvme-rpmb.c index a7658f5..7a92934 100644 --- a/nvme-rpmb.c +++ b/nvme-rpmb.c @@ -25,10 +25,11 @@ #include <sys/socket.h> #include <linux/if_alg.h> #include <linux/socket.h> +#include <limits.h> +#include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #define CREATE_CMD @@ -265,14 +266,49 @@ struct rpmb_config_block_t { #define RPMB_NVME_SECP 0xEA #define RPMB_NVME_SPSP 0x0001 -#define SEND_RPMB_REQ(tgt, size, req) \ -nvme_sec_send(fd, 0, tgt, RPMB_NVME_SPSP, RPMB_NVME_SECP, size, \ - (unsigned char *)(req)) - -#define RECV_RPMB_RSP(tgt, size, rsp) \ -nvme_sec_recv(fd, 0, tgt, RPMB_NVME_SPSP, RPMB_NVME_SECP, size, size, \ - (unsigned char *)(rsp)) - +static int send_rpmb_req(int fd, unsigned char tgt, int size, + struct rpmb_data_frame_t *req) +{ + struct nvme_security_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = 0, + .nssf = tgt, + .spsp0 = RPMB_NVME_SPSP, + .spsp1 = 0, + .secp = RPMB_NVME_SECP, + .tl = 0, + .data_len = size, + .data = (void *)req, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + + return nvme_security_send(&args); +} + +static int recv_rpmb_rsp(int fd, int tgt, int size, + struct rpmb_data_frame_t *rsp) +{ + + struct nvme_security_receive_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = 0, + .nssf = tgt, + .spsp0 = RPMB_NVME_SPSP, + .spsp1 = 0, + .secp = RPMB_NVME_SECP, + .al = 0, + .data_len = size, + .data = (void *)rsp, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + + return nvme_security_receive(&args); +} + /* Initialize nonce value in rpmb request frame */ static void rpmb_nonce_init(struct rpmb_data_frame_t *req) { @@ -385,7 +421,7 @@ rpmb_read_request(int fd, sprintf((char *)msg, "RPMB request 0x%04x to target 0x%x", req->type, req->target); - error = SEND_RPMB_REQ(req->target, req_size, req); + error = send_rpmb_req(fd, req->target, req_size, req); if (error != 0) { fprintf(stderr, "%s failed with error = 0x%x\n", msg, error); @@ -400,7 +436,7 @@ rpmb_read_request(int fd, } /* Read result of previous request */ - error = RECV_RPMB_RSP(req->target, rsp_size, rsp); + error = recv_rpmb_rsp(fd, req->target, rsp_size, rsp); if (error) { fprintf(stderr, "error 0x%x receiving response for %s\n", error, msg); @@ -561,7 +597,7 @@ static int rpmb_program_auth_key(int fd, unsigned char target, /* re-use response buffer */ memset(rsp, 0, rsp_size); - err = RECV_RPMB_RSP(req->target, rsp_size, (unsigned char *)rsp); + err = recv_rpmb_rsp(fd, req->target, rsp_size, rsp); if (err != 0) { err = check_rpmb_response(req, rsp, "Failed to Program Key"); } @@ -621,7 +657,7 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, memcpy(req->mac, mac, 32); /* send the request and get response */ - error = SEND_RPMB_REQ(tgt, req_size, (unsigned char *)req); + error = send_rpmb_req(fd, tgt, req_size, req); if (error != 0) { fprintf(stderr, "RPMB request 0x%04x for 0x%x, error: %d\n", req->type, tgt, error); @@ -632,7 +668,7 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, rsp = (struct rpmb_data_frame_t *)calloc(rsp_size, 1); rsp->target = req->target; rsp->type = RPMB_REQ_READ_RESULT; - error = SEND_RPMB_REQ(tgt, rsp_size, (unsigned char *)rsp); + error = send_rpmb_req(fd, tgt, rsp_size, rsp); if (error != 0 || rsp->result != 0) { fprintf(stderr, "Write-data read result 0x%x, error = 0x%x\n", rsp->result, error); @@ -641,7 +677,7 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, /* Read final response */ memset(rsp, 0, rsp_size); - error = RECV_RPMB_RSP(tgt, rsp_size, (unsigned char *)rsp); + error = recv_rpmb_rsp(fd, tgt, rsp_size, rsp); if (error != 0) fprintf(stderr, "Auth data write recv error = 0x%x\n", error); else @@ -726,7 +762,7 @@ static int rpmb_write_config_block(int fd, unsigned char *cfg_buf, memcpy(req->mac, mac, sizeof(req->mac)); - error = SEND_RPMB_REQ(0, req_size, (unsigned char *)req); + error = send_rpmb_req(fd, 0, req_size, req); if (error != 0) { fprintf(stderr, "Write-config RPMB request, error = 0x%x\n", error); @@ -746,7 +782,7 @@ static int rpmb_write_config_block(int fd, unsigned char *cfg_buf, rsp->target = req->target; rsp->type = RPMB_REQ_READ_RESULT; /* get the response and validate */ - error = RECV_RPMB_RSP(req->target, rsp_size, rsp); + error = recv_rpmb_rsp(fd, req->target, rsp_size, rsp); if (error != 0) { fprintf(stderr,"Failed getting write-config response\ error = 0x%x\n", error); @@ -926,11 +962,11 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p if (cfg.msgfile == 0) { struct rpmb_config_block_t *cfg = (struct rpmb_config_block_t *)msg_buf; - printf("Boot Parition Protection is %s\n", + printf("Boot Partition Protection is %s\n", ((cfg->bp_enable & 0x1) ? "Enabled" : "Disabled")); - printf("Boot Parition 1 is %s\n", + printf("Boot Partition 1 is %s\n", ((cfg->bp_lock & 0x2) ? "Locked" : "Unlocked")); - printf("Boot Parition 0 is %s\n", + printf("Boot Partition 0 is %s\n", ((cfg->bp_lock & 0x1) ? "Locked" : "Unlocked")); } else { printf("Saving received config data to %s file\n", cfg.msgfile); diff --git a/nvme-status.c b/nvme-status.c deleted file mode 100644 index 270eb06..0000000 --- a/nvme-status.c +++ /dev/null @@ -1,190 +0,0 @@ -#include <linux/types.h> -#include <stdbool.h> -#include <errno.h> - -#include "nvme.h" -#include "nvme-status.h" - -static inline __u8 nvme_generic_status_to_errno(__u16 status) -{ - switch (status) { - case NVME_SC_INVALID_OPCODE: - case NVME_SC_INVALID_FIELD: - case NVME_SC_INVALID_NS: - case NVME_SC_SGL_INVALID_LAST: - case NVME_SC_SGL_INVALID_COUNT: - case NVME_SC_SGL_INVALID_DATA: - case NVME_SC_SGL_INVALID_METADATA: - case NVME_SC_SGL_INVALID_TYPE: - case NVME_SC_SGL_INVALID_OFFSET: - case NVME_SC_CMB_INVALID_USE: - case NVME_SC_PRP_INVALID_OFFSET: - return EINVAL; - case NVME_SC_CMDID_CONFLICT: - return EADDRINUSE; - case NVME_SC_DATA_XFER_ERROR: - case NVME_SC_INTERNAL: - case NVME_SC_SANITIZE_FAILED: - return EIO; - case NVME_SC_POWER_LOSS: - case NVME_SC_ABORT_REQ: - case NVME_SC_ABORT_QUEUE: - case NVME_SC_FUSED_FAIL: - case NVME_SC_FUSED_MISSING: - return EWOULDBLOCK; - case NVME_SC_CMD_SEQ_ERROR: - return EILSEQ; - case NVME_SC_SANITIZE_IN_PROGRESS: - case NVME_SC_FORMAT_IN_PROGRESS: - return EINPROGRESS; - case NVME_SC_NS_WRITE_PROTECTED: - case NVME_SC_NS_NOT_READY: - case NVME_SC_RESERVATION_CONFLICT: - return EACCES; - case NVME_SC_LBA_RANGE: - return EREMOTEIO; - case NVME_SC_CAP_EXCEEDED: - return ENOSPC; - case NVME_SC_OPERATION_DENIED: - return EPERM; - } - - return EIO; -} - -static inline __u8 nvme_cmd_specific_status_to_errno(__u16 status) -{ - switch (status) { - case NVME_SC_CQ_INVALID: - case NVME_SC_QID_INVALID: - case NVME_SC_QUEUE_SIZE: - case NVME_SC_FIRMWARE_SLOT: - case NVME_SC_FIRMWARE_IMAGE: - case NVME_SC_INVALID_VECTOR: - case NVME_SC_INVALID_LOG_PAGE: - case NVME_SC_INVALID_FORMAT: - case NVME_SC_INVALID_QUEUE: - case NVME_SC_NS_INSUFFICIENT_CAP: - case NVME_SC_NS_ID_UNAVAILABLE: - case NVME_SC_CTRL_LIST_INVALID: - case NVME_SC_BAD_ATTRIBUTES: - case NVME_SC_INVALID_PI: - case NVME_SC_INVALID_CTRL_ID: - case NVME_SC_INVALID_SECONDARY_CTRL_STATE: - case NVME_SC_INVALID_NUM_CTRL_RESOURCE: - case NVME_SC_INVALID_RESOURCE_ID: - case NVME_SC_ANA_INVALID_GROUP_ID: - return EINVAL; - case NVME_SC_ABORT_LIMIT: - case NVME_SC_ASYNC_LIMIT: - return EDQUOT; - case NVME_SC_FW_NEEDS_CONV_RESET: - case NVME_SC_FW_NEEDS_SUBSYS_RESET: - case NVME_SC_FW_NEEDS_MAX_TIME: - return ERESTART; - case NVME_SC_FEATURE_NOT_SAVEABLE: - case NVME_SC_FEATURE_NOT_CHANGEABLE: - case NVME_SC_FEATURE_NOT_PER_NS: - case NVME_SC_FW_ACTIVATE_PROHIBITED: - case NVME_SC_NS_IS_PRIVATE: - case NVME_SC_BP_WRITE_PROHIBITED: - case NVME_SC_READ_ONLY: - case NVME_SC_PMR_SAN_PROHIBITED: - return EPERM; - case NVME_SC_OVERLAPPING_RANGE: - case NVME_SC_NS_NOT_ATTACHED: - return ENOSPC; - case NVME_SC_NS_ALREADY_ATTACHED: - return EALREADY; - case NVME_SC_THIN_PROV_NOT_SUPP: - return EOPNOTSUPP; - case NVME_SC_DEVICE_SELF_TEST_IN_PROGRESS: - return EINPROGRESS; - } - - return EIO; -} - -static inline __u8 nvme_fabrics_status_to_errno(__u16 status) -{ - switch (status) { - case NVME_SC_CONNECT_FORMAT: - case NVME_SC_CONNECT_INVALID_PARAM: - return EINVAL; - case NVME_SC_CONNECT_CTRL_BUSY: - return EBUSY; - case NVME_SC_CONNECT_RESTART_DISC: - return ERESTART; - case NVME_SC_CONNECT_INVALID_HOST: - return ECONNREFUSED; - case NVME_SC_DISCOVERY_RESTART: - return EAGAIN; - case NVME_SC_AUTH_REQUIRED: - return EPERM; - } - - return EIO; -} - -static inline __u8 nvme_path_status_to_errno(__u16 status) -{ - switch (status) { - case NVME_SC_INTERNAL_PATH_ERROR: - case NVME_SC_ANA_PERSISTENT_LOSS: - case NVME_SC_ANA_INACCESSIBLE: - case NVME_SC_ANA_TRANSITION: - case NVME_SC_CTRL_PATHING_ERROR: - case NVME_SC_HOST_PATHING_ERROR: - case NVME_SC_HOST_CMD_ABORT: - return EACCES; - } - - return EIO; -} - -/* - * nvme_status_to_errno - It converts given status to errno mapped - * @status: >= 0 for nvme status field in completion queue entry, - * < 0 for linux internal errors - * @fabrics: true if given status is for fabrics - * - * Notes: This function will convert a given status to an errno mapped - */ -__u8 nvme_status_to_errno(int status, bool fabrics) -{ - __u8 sct; - - if (!status) - return 0; - - if (status < 0) { - if (errno) - return errno; - return status; - } - - /* - * The actual status code is enough with masking 0xff, but we need to - * cover status code type which is 3bits with 0x7ff. - */ - status &= 0x7ff; - - sct = nvme_status_type(status); - switch (sct) { - case NVME_SCT_GENERIC: - return nvme_generic_status_to_errno(status); - case NVME_SCT_CMD_SPECIFIC: - if (!fabrics) { - return nvme_cmd_specific_status_to_errno(status); - } - return nvme_fabrics_status_to_errno(status); - case NVME_SCT_PATH: - return nvme_path_status_to_errno(status); - } - - /* - * Media, integrity related status, and the others will be mapped to - * EIO. - */ - return EIO; -} diff --git a/nvme-status.h b/nvme-status.h deleted file mode 100644 index 92a474c..0000000 --- a/nvme-status.h +++ /dev/null @@ -1,14 +0,0 @@ -#include <linux/types.h> -#include <stdbool.h> - -/* - * nvme_status_type - It gives SCT(Status Code Type) in status field in - * completion queue entry. - * @status: status field located at DW3 in completion queue entry - */ -static inline __u8 nvme_status_type(__u16 status) -{ - return (status & 0x700) >> 8; -} - -__u8 nvme_status_to_errno(int status, bool fabrics); diff --git a/nvme-topology.c b/nvme-topology.c deleted file mode 100644 index 0a22f6b..0000000 --- a/nvme-topology.c +++ /dev/null @@ -1,801 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mman.h> - -#include "nvme.h" -#include "nvme-ioctl.h" - -#ifdef HAVE_SYSTEMD -#include <systemd/sd-id128.h> -#define NVME_HOSTNQN_ID SD_ID128_MAKE(c7,f4,61,81,12,be,49,32,8c,83,10,6f,9d,dd,d8,6b) -#endif - -static const char *dev = "/dev/"; -static const char *subsys_dir = "/sys/class/nvme-subsystem/"; -static void free_ctrl(struct nvme_ctrl *c); - -char *get_nvme_subsnqn(char *path) -{ - char sspath[320], *subsysnqn; - int fd, ret; - - snprintf(sspath, sizeof(sspath), "%s/subsysnqn", path); - - fd = open(sspath, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Failed to open %s: %s\n", - sspath, strerror(errno)); - return NULL; - } - - subsysnqn = calloc(1, 256); - if (!subsysnqn) - goto close_fd; - - ret = read(fd, subsysnqn, 256); - if (ret < 0) { - fprintf(stderr, "Failed to read %s: %s\n", sspath, - strerror(errno)); - free(subsysnqn); - subsysnqn = NULL; - } else if (subsysnqn[strlen(subsysnqn) - 1] == '\n') { - subsysnqn[strlen(subsysnqn) - 1] = '\0'; - } - -close_fd: - close(fd); - return subsysnqn; -} - -char *nvme_get_ctrl_attr(const char *path, const char *attr) -{ - char *attrpath, *value; - ssize_t ret; - int fd, i; - - ret = asprintf(&attrpath, "%s/%s", path, attr); - if (ret < 0) - return NULL; - - value = calloc(1, 1024); - if (!value) - goto err_free_path; - - fd = open(attrpath, O_RDONLY); - if (fd < 0) - goto err_free_value; - - ret = read(fd, value, 1024); - if (ret < 0) { - fprintf(stderr, "read :%s :%s\n", attrpath, strerror(errno)); - goto err_close_fd; - } - - if (value[strlen(value) - 1] == '\n') - value[strlen(value) - 1] = '\0'; - - for (i = 0; i < strlen(value); i++) { - if (value[i] == ',' ) - value[i] = ' '; - } - - close(fd); - free(attrpath); - return value; -err_close_fd: - close(fd); -err_free_value: - free(value); -err_free_path: - free(attrpath); - return NULL; -} - -static char *path_trim_last(char *path, char needle) -{ - int i; - i = strlen(path); - if (i>0 && path[i-1] == needle) // remove trailing slash - path[--i] = 0; - for (; i>0; i--) - if (path[i] == needle) { - path[i] = 0; - return path+i+1; - } - return NULL; -} - -static void legacy_get_pci_bdf(char *node, char *bdf) -{ - int ret; - char path[264], nodetmp[264]; - struct stat st; - char *p, *__path = path; - - bdf[0] = 0; - strcpy(nodetmp, node); - p = path_trim_last(nodetmp, '/'); - sprintf(path, "/sys/block/%s/device", p); - ret = readlink(path, nodetmp, sizeof(nodetmp)); - if (ret <= 0) - return; - nodetmp[ret] = 0; - /* The link value is either "device -> ../../../0000:86:00.0" or "device -> ../../nvme0" */ - (void) path_trim_last(path, '/'); - sprintf(path+strlen(path), "/%s/device", nodetmp); - ret = stat(path, &st); - if (ret < 0) - return; - if ((st.st_mode & S_IFLNK) == 0) { - /* follow the second link to get the PCI address */ - ret = readlink(path, __path, sizeof(path)); - if (ret <= 0) - return; - path[ret] = 0; - } - else - (void) path_trim_last(path, '/'); - - p = path_trim_last(path, '/'); - if (p && strlen(p) == 12) - strcpy(bdf, p); -} - -static int scan_namespace(struct nvme_namespace *n) -{ - int ret, fd; - char *path; - - ret = asprintf(&path, "%s%s", n->ctrl->path, n->name); - if (ret < 0) - return ret; - - fd = open(path, O_RDONLY); - if (fd < 0) { - ret = fd; - goto free; - } - if (!n->nsid) { - ret = nvme_get_nsid(fd); - if (ret < 0) - goto close_fd; - n->nsid = ret; - } - - ret = nvme_identify_ns(fd, n->nsid, 0, &n->ns); -close_fd: - close(fd); -free: - free(path); - return ret; -} - -static char *get_nvme_ctrl_path_ana_state(char *path, int nsid) -{ - struct dirent **paths; - char *ana_state; - int i, n; - - ana_state = calloc(1, 16); - if (!ana_state) - return NULL; - - n = scandir(path, &paths, scan_ctrl_paths_filter, alphasort); - if (n <= 0) { - free(ana_state); - return NULL; - } - for (i = 0; i < n; i++) { - int id, cntlid, ns, fd; - char *ctrl_path; - ssize_t ret; - - if (sscanf(paths[i]->d_name, "nvme%dc%dn%d", - &id, &cntlid, &ns) != 3) { - if (sscanf(paths[i]->d_name, "nvme%dn%d", - &id, &ns) != 2) { - continue; - } - } - if (ns != nsid) - continue; - - ret = asprintf(&ctrl_path, "%s/%s/ana_state", - path, paths[i]->d_name); - if (ret < 0) { - free(ana_state); - ana_state = NULL; - break; - } - fd = open(ctrl_path, O_RDONLY); - if (fd < 0) { - free(ctrl_path); - free(ana_state); - ana_state = NULL; - break; - } - ret = read(fd, ana_state, 16); - if (ret < 0) { - fprintf(stderr, "Failed to read ANA state from %s\n", - ctrl_path); - free(ana_state); - ana_state = NULL; - } else if (ana_state[strlen(ana_state) - 1] == '\n') - ana_state[strlen(ana_state) - 1] = '\0'; - close(fd); - free(ctrl_path); - break; - } - for (i = 0; i < n; i++) - free(paths[i]); - free(paths); - return ana_state; -} - -static bool ns_attached_to_ctrl(int nsid, struct nvme_ctrl *ctrl) -{ - struct nvme_namespace *n; - int i; - - for (i = 0; i < ctrl->nr_namespaces; i++) { - n = &ctrl->namespaces[i]; - if (nsid == n->nsid) - return true; - } - return false; -} - -static int scan_ctrl(struct nvme_ctrl *c, char *p, __u32 ns_instance) -{ - struct nvme_namespace *n; - struct dirent **ns; - char *path; - int i, fd, ret; - - ret = asprintf(&path, "%s/%s", p, c->name); - if (ret < 0) - return ret; - - c->address = nvme_get_ctrl_attr(path, "address"); - c->transport = nvme_get_ctrl_attr(path, "transport"); - c->state = nvme_get_ctrl_attr(path, "state"); - c->hostnqn = nvme_get_ctrl_attr(path, "hostnqn"); - c->hostid = nvme_get_ctrl_attr(path, "hostid"); - - if (ns_instance) - c->ana_state = get_nvme_ctrl_path_ana_state(path, ns_instance); - - ret = scandir(path, &ns, scan_ctrl_namespace_filter, alphasort); - if (ret == -1) { - fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); - return errno; - } - - c->nr_namespaces = ret; - c->namespaces = calloc(c->nr_namespaces, sizeof(*n)); - if (c->namespaces) { - for (i = 0; i < c->nr_namespaces; i++) { - char *ns_path, nsid[16]; - int ns_fd; - - n = &c->namespaces[i]; - n->name = strdup(ns[i]->d_name); - n->ctrl = c; - ret = asprintf(&ns_path, "%s/%s/nsid", path, n->name); - if (ret < 0) - continue; - ns_fd = open(ns_path, O_RDONLY); - if (ns_fd < 0) { - free(ns_path); - continue; - } - ret = read(ns_fd, nsid, 16); - if (ret < 0) { - close(ns_fd); - free(ns_path); - continue; - } - n->nsid = (unsigned)strtol(nsid, NULL, 10); - scan_namespace(n); - close(ns_fd); - free(ns_path); - } - } else { - i = c->nr_namespaces; - c->nr_namespaces = 0; - } - - while (i--) - free(ns[i]); - free(ns); - free(path); - - ret = asprintf(&path, "%s%s", c->path, c->name); - if (ret < 0) - return ret; - - fd = open(path, O_RDONLY); - if (fd < 0) - goto free; - - ret = nvme_identify_ctrl(fd, &c->id); - if (ret < 0) - goto close_fd; -close_fd: - close(fd); -free: - free(path); - return 0; -} - -static int scan_subsystem(struct nvme_subsystem *s, __u32 ns_instance, int nsid) -{ - struct dirent **ctrls, **ns; - struct nvme_namespace *n; - struct nvme_ctrl *c; - int i, j = 0, ret; - char *path; - - ret = asprintf(&path, "%s%s", subsys_dir, s->name); - if (ret < 0) - return ret; - - s->subsysnqn = get_nvme_subsnqn(path); - ret = scandir(path, &ctrls, scan_ctrls_filter, alphasort); - if (ret == -1) { - fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); - return errno; - } - s->nr_ctrls = ret; - s->ctrls = calloc(s->nr_ctrls, sizeof(*c)); - for (i = 0; i < s->nr_ctrls; i++) { - c = &s->ctrls[j]; - c->name = strdup(ctrls[i]->d_name); - c->path = strdup(dev); - c->subsys = s; - scan_ctrl(c, path, ns_instance); - - if (!ns_instance || ns_attached_to_ctrl(nsid, c)) - j++; - else - free_ctrl(c); - } - s->nr_ctrls = j; - - while (i--) - free(ctrls[i]); - free(ctrls); - - ret = scandir(path, &ns, scan_namespace_filter, alphasort); - if (ret == -1) { - fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); - return errno; - } - - s->nr_namespaces = ret; - s->namespaces = calloc(s->nr_namespaces, sizeof(*n)); - if (s->namespaces) { - for (i = 0; i < s->nr_namespaces; i++) { - n = &s->namespaces[i]; - n->name = strdup(ns[i]->d_name); - for (j = 0; j < s->nr_ctrls; j++) { - n->ctrl = &s->ctrls[j]; - if (!strcmp(n->ctrl->state, "live") && - !scan_namespace(n)) - break; - } - } - } else { - i = s->nr_namespaces; - s->nr_namespaces = 0; - } - - while (i--) - free(ns[i]); - free(ns); - - free(path); - return 0; -} - -static int verify_legacy_ns(struct nvme_namespace *n) -{ - struct nvme_ctrl *c = n->ctrl; - struct nvme_id_ctrl id; - char *path; - int ret, fd; - - ret = asprintf(&path, "%s%s", n->ctrl->path, n->name); - if (ret < 0) - return ret; - - if (!n->ctrl->transport && !n->ctrl->address) { - char tmp_address[64] = ""; - legacy_get_pci_bdf(path, tmp_address); - if (tmp_address[0]) { - if (asprintf(&n->ctrl->transport, "pcie") < 0) - return -1; - if (asprintf(&n->ctrl->address, "%s", tmp_address) < 0) - return -1; - } - } - - fd = open(path, O_RDONLY); - free (path); - - if (fd < 0) - return fd; - - ret = nvme_identify_ctrl(fd, &id); - close(fd); - - if (ret) - return ret; - - if (memcmp(id.mn, c->id.mn, sizeof(id.mn)) || - memcmp(id.sn, c->id.sn, sizeof(id.sn))) - return -ENODEV; - return 0; -} - -/* - * For pre-subsystem enabled kernel. Topology information is limited, but we can - * assume controller names are always a prefix to their namespaces, i.e. nvme0 - * is the controller to nvme0n1 for such older kernels. We will also assume - * every controller is its own subsystem. - */ -static int legacy_list(struct nvme_topology *t, char *dev_dir) -{ - struct nvme_ctrl *c; - struct nvme_subsystem *s; - struct nvme_namespace *n; - struct dirent **devices, **namespaces; - int ret = 0, fd, i; - char *path; - - t->nr_subsystems = scandir(dev_dir, &devices, scan_ctrls_filter, alphasort); - if (t->nr_subsystems == -1) { - fprintf(stderr, "Failed to open %s: %s\n", dev_dir, strerror(errno)); - return errno; - } - - t->subsystems = calloc(t->nr_subsystems, sizeof(*s)); - for (i = 0; i < t->nr_subsystems; i++) { - int j; - - s = &t->subsystems[i]; - s->nr_ctrls = 1; - s->ctrls = calloc(s->nr_ctrls, sizeof(*c)); - s->name = strdup(devices[i]->d_name); - s->subsysnqn = strdup(s->name); - s->nr_namespaces = 0; - - c = s->ctrls; - c->name = strdup(s->name); - sscanf(c->name, "nvme%d", ¤t_index); - c->path = strdup(dev_dir); - c->nr_namespaces = scandir(c->path, &namespaces, scan_dev_filter, - alphasort); - c->namespaces = calloc(c->nr_namespaces, sizeof(*n)); - if (!c->namespaces) { - while (c->nr_namespaces--) - free(namespaces[c->nr_namespaces]); - free(namespaces); - continue; - } - - ret = asprintf(&path, "%s%s", c->path, c->name); - if (ret < 0) - continue; - ret = 0; - - fd = open(path, O_RDONLY); - if (fd > 0) { - nvme_identify_ctrl(fd, &c->id); - close(fd); - } - free(path); - - for (j = 0; j < c->nr_namespaces; j++) { - n = &c->namespaces[j]; - n->name = strdup(namespaces[j]->d_name); - n->ctrl = c; - scan_namespace(n); - ret = verify_legacy_ns(n); - if (ret) - goto free; - } - while (j--) - free(namespaces[j]); - free(namespaces); - } - -free: - while (i--) - free(devices[i]); - free(devices); - return ret; -} - -static void free_ctrl(struct nvme_ctrl *c) -{ - int i; - - for (i = 0; i < c->nr_namespaces; i++) { - struct nvme_namespace *n = &c->namespaces[i]; - free(n->name); - } - free(c->name); - free(c->path); - free(c->transport); - free(c->address); - free(c->state); - free(c->hostnqn); - free(c->hostid); - free(c->ana_state); - free(c->namespaces); -} - -static void free_subsystem(struct nvme_subsystem *s) -{ - int i; - - for (i = 0; i < s->nr_ctrls; i++) - free_ctrl(&s->ctrls[i]); - for (i = 0; i < s->nr_namespaces; i++) { - struct nvme_namespace *n = &s->namespaces[i]; - free(n->name); - } - free(s->name); - free(s->subsysnqn); - free(s->ctrls); - free(s->namespaces); -} - -static int scan_subsystem_dir(struct nvme_topology *t, char *dev_dir) -{ - struct nvme_topology dev_dir_t = { }; - int ret, i, total_nr_subsystems; - - ret = legacy_list(&dev_dir_t, dev_dir); - if (ret != 0) - return ret; - - total_nr_subsystems = t->nr_subsystems + dev_dir_t.nr_subsystems; - t->subsystems = realloc(t->subsystems, - total_nr_subsystems * sizeof(struct nvme_subsystem)); - for (i = 0; i < dev_dir_t.nr_subsystems; i++){ - t->subsystems[i+t->nr_subsystems] = dev_dir_t.subsystems[i]; - } - t->nr_subsystems = total_nr_subsystems; - - return 0; -} - -int scan_subsystems(struct nvme_topology *t, const char *subsysnqn, - __u32 ns_instance, int nsid, char *dev_dir) -{ - struct nvme_subsystem *s; - struct dirent **subsys; - int ret = 0, i, j = 0; - - t->nr_subsystems = scandir(subsys_dir, &subsys, scan_subsys_filter, - alphasort); - if (t->nr_subsystems < 0) { - ret = legacy_list(t, (char *)dev); - if (ret != 0) - return ret; - } else { - - t->subsystems = calloc(t->nr_subsystems, sizeof(*s)); - for (i = 0; i < t->nr_subsystems; i++) { - s = &t->subsystems[j]; - s->name = strdup(subsys[i]->d_name); - scan_subsystem(s, ns_instance, nsid); - - if (!subsysnqn || !strcmp(s->subsysnqn, subsysnqn)) - j++; - else - free_subsystem(s); - } - t->nr_subsystems = j; - - while (i--) - free(subsys[i]); - free(subsys); - } - - if (dev_dir != NULL && strcmp(dev_dir, "/dev/")) { - ret = scan_subsystem_dir(t, dev_dir); - } - - return ret; -} - -void free_topology(struct nvme_topology *t) -{ - int i; - - for (i = 0; i < t->nr_subsystems; i++) - free_subsystem(&t->subsystems[i]); - free(t->subsystems); -} - -char *nvme_char_from_block(char *dev) -{ - char *path = NULL; - char buf[256] = {0}; - int ret, id, nsid; - - ret = sscanf(dev, "nvme%dn%d", &id, &nsid); - switch (ret) { - case 1: - return strdup(dev); - break; - case 2: - if (asprintf(&path, "/sys/block/%s/device", dev) < 0) - path = NULL; - break; - default: - fprintf(stderr, "%s is not an nvme device\n", dev); - return NULL; - } - - if (!path) - return NULL; - - ret = readlink(path, buf, sizeof(buf)); - if (ret > 0) { - char *r = strdup(basename(buf)); - - free(path); - if (sscanf(r, "nvme%d", &id) != 1) { - fprintf(stderr, "%s is not a physical nvme controller\n", r); - free(r); - r = NULL; - } - return r; - } - - free(path); - ret = asprintf(&path, "nvme%d", id); - if (ret < 0) - return NULL; - return path; -} - -int nvme_logical_block_size_from_ns_char(const char *dev) -{ - int ret; - int id, nsid; - char *path = NULL; - char *s; - - ret = sscanf(dev, "ng%dn%d", &id, &nsid); - if (ret != 2) - return -EINVAL; - - if (asprintf(&path, "/sys/block/nvme%dn%d/queue", id, nsid) < 0) - path = NULL; - - if (!path) - return -EINVAL; - - s = nvme_get_ctrl_attr(path, "logical_block_size"); - if (!s) - return -EINVAL; - - return atoi(s); -} - -void *mmap_registers(const char *dev) -{ - int fd; - char *base, path[512]; - void *membase; - - base = nvme_char_from_block((char *)dev); - if (!base) - return NULL; - - 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, open failed %s\n", - base, strerror(errno)); - free(base); - return NULL; - } - - membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0); - if (membase == MAP_FAILED) { - fprintf(stderr, "%s failed to map. ", base); - fprintf(stderr, "Did your kernel enable CONFIG_IO_STRICT_DEVMEM?\n"); - membase = NULL; - } - - free(base); - close(fd); - return membase; -} - -#define PATH_DMI_ENTRIES "/sys/firmware/dmi/entries" - -int uuid_from_dmi(char *system_uuid) -{ - int f; - DIR *d; - struct dirent *de; - char buf[512]; - - system_uuid[0] = '\0'; - d = opendir(PATH_DMI_ENTRIES); - if (!d) - return -ENXIO; - while ((de = readdir(d))) { - char filename[PATH_MAX]; - int len, type; - - if (de->d_name[0] == '.') - continue; - sprintf(filename, "%s/%s/type", PATH_DMI_ENTRIES, de->d_name); - f = open(filename, O_RDONLY); - if (f < 0) - continue; - len = read(f, buf, 512); - close(f); - if (len < 0) - continue; - if (sscanf(buf, "%d", &type) != 1) - continue; - if (type != 1) - continue; - sprintf(filename, "%s/%s/raw", PATH_DMI_ENTRIES, de->d_name); - f = open(filename, O_RDONLY); - if (f < 0) - continue; - len = read(f, buf, 512); - close(f); - if (len < 0) - continue; - /* Sigh. https://en.wikipedia.org/wiki/Overengineering */ - /* DMTF SMBIOS 3.0 Section 7.2.1 System UUID */ - sprintf(system_uuid, - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - (uint8_t)buf[8 + 3], (uint8_t)buf[8 + 2], - (uint8_t)buf[8 + 1], (uint8_t)buf[8 + 0], - (uint8_t)buf[8 + 5], (uint8_t)buf[8 + 4], - (uint8_t)buf[8 + 7], (uint8_t)buf[8 + 6], - (uint8_t)buf[8 + 8], (uint8_t)buf[8 + 9], - (uint8_t)buf[8 + 10], (uint8_t)buf[8 + 11], - (uint8_t)buf[8 + 12], (uint8_t)buf[8 + 13], - (uint8_t)buf[8 + 14], (uint8_t)buf[8 + 15]); - break; - } - closedir(d); - return strlen(system_uuid) ? 0 : -ENXIO; -} - -int uuid_from_systemd(char *systemd_uuid) -{ -#ifdef HAVE_SYSTEMD - sd_id128_t id; - - if (sd_id128_get_machine_app_specific(NVME_HOSTNQN_ID, &id) < 0) - return -ENXIO; - - sprintf(systemd_uuid, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); - return 0; -#else - return -ENOTSUP; -#endif -} @@ -23,7 +23,9 @@ /** * This program uses NVMe IOCTLs to run native nvme commands to a device. */ - +#include "config.h" +#include "nvme/tree.h" +#include "nvme/types.h" #include <errno.h> #include <getopt.h> #include <fcntl.h> @@ -36,31 +38,46 @@ #include <math.h> #include <dirent.h> #include <libgen.h> +#include <zlib.h> -#ifdef LIBHUGETLBFS +#ifdef CONFIG_LIBHUGETLBFS #include <hugetlbfs.h> #endif #include <linux/fs.h> -#include <sys/ioctl.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> +#if HAVE_SYS_RANDOM + #include <sys/random.h> +#endif + #include "common.h" +#include "nvme.h" +#include "libnvme.h" #include "nvme-print.h" -#include "nvme-ioctl.h" -#include "nvme-status.h" -#include "nvme-lightnvm.h" #include "plugin.h" +#include "util/base64.h" -#include "argconfig.h" +#include "util/argconfig.h" #include "fabrics.h" #define CREATE_CMD #include "nvme-builtin.h" +struct feat_cfg { + enum nvme_features_id feature_id; + __u32 namespace_id; + enum nvme_get_features_sel sel; + __u32 cdw11; + __u8 uuid_index; + __u32 data_len; + bool raw_binary; + bool human_readable; +}; + static struct stat nvme_stat; const char *devicename; @@ -84,23 +101,12 @@ static struct program nvme = { .extensions = &builtin, }; -static __u16 nvme_feat_buf_len[0x100] = { - [NVME_FEAT_LBA_RANGE] = 4096, - [NVME_FEAT_AUTO_PST] = 256, - [NVME_FEAT_HOST_MEM_BUF] = 4096, - [NVME_FEAT_HOST_ID] = 8, - [NVME_FEAT_PLM_CONFIG] = 512, - [NVME_FEAT_TIMESTAMP] = 8, - [NVME_FEAT_HOST_BEHAVIOR] = 512, - [NVME_MI_FEAT_CTRL_METADATA] = 4096, - [NVME_MI_FEAT_NS_METADATA] = 4096, -}; - const char *output_format = "Output format: normal|json|binary"; static const char *output_format_no_binary = "Output format: normal|json"; -static void *__nvme_alloc(size_t len, bool *huge) -{ +static void *mmap_registers(nvme_root_t r, const char *dev); + +static void *__nvme_alloc(size_t len, bool *huge) { void *p; if (!posix_memalign(&p, getpagesize(), len)) { @@ -113,11 +119,13 @@ static void *__nvme_alloc(size_t len, bool *huge) #define HUGE_MIN 0x80000 -#ifdef LIBHUGETLBFS +#ifdef CONFIG_LIBHUGETLBFS void nvme_free(void *p, bool huge) { - if (huge) - free_hugepage_region(p); + if (huge) { + if (p) + free_hugepage_region(p); + } else free(p); } @@ -148,6 +156,57 @@ void *nvme_alloc(size_t len, bool *huge) } #endif +const char *nvme_strerror(int errnum) +{ + if (errnum >= ENVME_CONNECT_RESOLVE) + return nvme_errno_to_string(errnum); + return strerror(errnum); +} + +int map_log_level(int verbose, bool quiet) +{ + int log_level; + + switch (verbose) { + case 0: + log_level = LOG_WARNING; + break; + case 1: + log_level = LOG_NOTICE; + break; + case 2: + log_level = LOG_INFO; + break; + default: + log_level = LOG_DEBUG; + break; + } + if (quiet) + log_level = LOG_ERR; + + return log_level; +} + +static ssize_t getrandom_bytes(void *buf, size_t buflen) +{ +#if HAVE_SYS_RANDOM + return getrandom(buf, buflen, GRND_NONBLOCK); +#else + ssize_t result; + int fd, err = 0; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) + return fd; + result = read(fd, buf, buflen); + if (result < 0) + err = errno; + close(fd); + errno = err; + return result; +#endif +} + static bool is_chardev(void) { return S_ISCHR(nvme_stat.st_mode); @@ -158,17 +217,12 @@ static bool is_blkdev(void) return S_ISBLK(nvme_stat.st_mode); } -static bool is_ns_chardev(void) -{ - return !strncmp(devicename, "ng", 2) && S_ISCHR(nvme_stat.st_mode); -} - -static int open_dev(char *dev) +static int open_dev(char *dev, int flags) { int err, fd; devicename = basename(dev); - err = open(dev, O_RDONLY); + err = open(dev, flags); if (err < 0) goto perror; fd = err; @@ -199,7 +253,7 @@ static int check_arg_dev(int argc, char **argv) return 0; } -static int get_dev(int argc, char **argv) +static int get_dev(int argc, char **argv, int flags) { int ret; @@ -207,7 +261,7 @@ static int get_dev(int argc, char **argv) if (ret) return ret; - return open_dev(argv[optind]); + return open_dev(argv[optind], flags); } int parse_and_open(int argc, char **argv, const char *desc, @@ -219,13 +273,23 @@ int parse_and_open(int argc, char **argv, const char *desc, if (ret) return ret; - ret = get_dev(argc, argv); + ret = get_dev(argc, argv, O_RDONLY); if (ret < 0) argconfig_print_help(desc, opts); return ret; } +int open_exclusive(int argc, char **argv, int ignore_exclusive) +{ + int flags = O_RDONLY; + + if (!ignore_exclusive) + flags |= O_EXCL; + + return get_dev(argc, argv, flags); +} + enum nvme_print_flags validate_output_format(const char *format) { if (!format) @@ -252,15 +316,17 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug int err = -1, fd; struct config { - __u32 namespace_id; - int raw_binary; - char *output_format; - int human_readable; + __u32 namespace_id; + char *output_format; + bool raw_binary; + bool human_readable; }; struct config cfg = { - .namespace_id = NVME_NSID_ALL, - .output_format = "normal", + .namespace_id = NVME_NSID_ALL, + .output_format = "normal", + .raw_binary = false, + .human_readable = false, }; @@ -284,18 +350,18 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug if (cfg.human_readable) flags |= VERBOSE; - err = nvme_smart_log(fd, cfg.namespace_id, &smart_log); + err = nvme_get_log_smart(fd, cfg.namespace_id, true, &smart_log); if (!err) nvme_show_smart_log(&smart_log, cfg.namespace_id, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("smart log"); + fprintf(stderr, "smart log: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_ana_log(int argc, char **argv, struct command *cmd, @@ -309,9 +375,10 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, size_t ana_log_len; struct nvme_id_ctrl ctrl; enum nvme_print_flags flags; + enum nvme_log_ana_lsp lsp; struct config { - char *output_format; + char *output_format; }; struct config cfg = { @@ -333,69 +400,64 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, err = nvme_identify_ctrl(fd, &ctrl); if (err) { - fprintf(stderr, "ERROR : nvme_identify_ctrl() failed 0x%x\n", - err); + fprintf(stderr, "ERROR : nvme_identify_ctrl() failed: %s\n", + nvme_strerror(errno)); goto close_fd; } - ana_log_len = sizeof(struct nvme_ana_rsp_hdr) + + ana_log_len = sizeof(struct nvme_ana_log) + le32_to_cpu(ctrl.nanagrpid) * sizeof(struct nvme_ana_group_desc); if (!(ctrl.anacap & (1 << 6))) ana_log_len += le32_to_cpu(ctrl.mnan) * sizeof(__le32); ana_log = malloc(ana_log_len); if (!ana_log) { - perror("malloc"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } - err = nvme_ana_log(fd, ana_log, ana_log_len, groups ? NVME_ANA_LOG_RGO : 0); + lsp = groups ? NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY : + NVME_LOG_ANA_LSP_RGO_NAMESPACES; + + err = nvme_get_log_ana(fd, lsp, true, 0, ana_log_len, ana_log); if (!err) { nvme_show_ana_log(ana_log, devicename, flags, ana_log_len); } else if (err > 0) nvme_show_status(err); else - perror("ana-log"); + fprintf(stderr, "ana-log: %s", nvme_strerror(errno)); free(ana_log); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); -} - -__u16 get_feat_buf_len(unsigned short feature) { - return nvme_feat_buf_len[feature]; + return err; } -static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_telemetry_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) { const char *desc = "Retrieve telemetry log and write to binary file"; const char *fname = "File name to save raw binary, includes header"; const char *hgen = "Have the host tell the controller to generate the report"; const char *cgen = "Gather report generated by the controller."; const char *dgen = "Pick which telemetry data area to report. Default is 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4."; - const size_t bs = 512; - struct nvme_telemetry_log_page_hdr *hdr; - struct nvme_id_ctrl ctrl; - size_t full_size, offset = bs; - int err = -1, fd, output; - void *page_log; - __u32 result; - void *buf = NULL; + struct nvme_telemetry_log *log; + int err = 0, fd, output; + size_t total_size; + __u8 *data_ptr = NULL; + int data_written = 0, data_remaining = 0; struct config { - char *file_name; - __u32 host_gen; - int ctrl_init; - int data_area; + char *file_name; + __u32 host_gen; + bool ctrl_init; + int data_area; }; struct config cfg = { - .file_name = NULL, - .host_gen = 1, - .ctrl_init = 0, - .data_area = 3, + .file_name = NULL, + .host_gen = 1, + .ctrl_init = false, + .data_area = 3, }; OPT_ARGS(opts) = { @@ -412,135 +474,68 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct if (!cfg.file_name) { fprintf(stderr, "Please provide an output file!\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } cfg.host_gen = !!cfg.host_gen; - hdr = malloc(bs); - page_log = malloc(bs); - if (!hdr || !page_log) { - perror("failed to allocate buf for log\n"); - errno = ENOMEM; - err = -1; - goto free_mem; - } - memset(hdr, 0, bs); - output = open(cfg.file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (output < 0) { fprintf(stderr, "Failed to open output file %s: %s!\n", cfg.file_name, strerror(errno)); err = output; - goto free_mem; + goto close_fd; } - err = nvme_get_telemetry_log(fd, hdr, cfg.host_gen, cfg.ctrl_init, bs, 0); - if (err < 0) - perror("get-telemetry-log"); - else if (err > 0) { - nvme_show_status(err); - fprintf(stderr, "Failed to acquire telemetry header %d!\n", err); - goto close_output; - } + if (cfg.ctrl_init) + err = nvme_get_ctrl_telemetry(fd, true, &log, cfg.data_area, &total_size); + else if (cfg.host_gen) + err = nvme_get_new_host_telemetry(fd, &log, cfg.data_area, &total_size); + else + err = nvme_get_host_telemetry(fd, &log, cfg.data_area, &total_size); - err = write(output, (void *) hdr, bs); - if (err != bs) { - fprintf(stderr, "Failed to flush all data to file!\n"); + if (err < 0) { + fprintf(stderr, "get-telemetry-log: %s\n", + nvme_strerror(errno)); + } else if (err > 0) { + nvme_show_status(err); + fprintf(stderr, "Failed to acquire telemetry log %d!\n", err); goto close_output; } - switch (cfg.data_area) { - case 1: - full_size = (le16_to_cpu(hdr->dalb1) * bs) + offset; - break; - case 2: - full_size = (le16_to_cpu(hdr->dalb2) * bs) + offset; - break; - case 3: - full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset; - break; - case 4: - err = nvme_identify_ctrl(fd, &ctrl); - if (err) { - perror("identify-ctrl"); - goto close_output; - } - - if (posix_memalign(&buf, getpagesize(), nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR])) { - fprintf(stderr, "can not allocate feature payload\n"); - errno = ENOMEM; - err = -1; - goto close_output; - } - memset(buf, 0, nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR]); - - err = nvme_get_feature(fd, NVME_NSID_ALL, NVME_FEAT_HOST_BEHAVIOR, 0, 0, - 0, nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR], buf, &result); - if (err > 0) { - nvme_show_status(err); - } else if (err < 0) { - perror("get-feature"); - } else { - if ((ctrl.lpa & 0x40)) { - if (((unsigned char *)buf)[1] == 1) - full_size = (le32_to_cpu(hdr->dalb4) * bs) + offset; - else { - fprintf(stderr, "Data area 4 unsupported, Host Behavior Support ETDAS not set to 1\n"); - errno = EINVAL; - err = -1; - } - } else { - fprintf(stderr, "Data area 4 unsupported, bit 6 of Log Page Attributes not set\n"); - errno = EINVAL; - err = -1; - } - } - free(buf); - if (err) - goto close_output; - break; - default: - fprintf(stderr, "Invalid data area requested\n"); - errno = EINVAL; - err = -1; - goto close_output; - } + data_written = 0; + data_remaining = total_size; + data_ptr = (__u8 *)log; - /* - * Continuously pull data until the offset hits the end of the last - * block. - */ - while (offset != full_size) { - err = nvme_get_telemetry_log(fd, page_log, 0, cfg.ctrl_init, bs, offset); - if (err < 0) { - perror("get-telemetry-log"); + while (data_remaining) { + data_written = write(output, data_ptr, data_remaining); + if (data_written < 0) { + data_remaining = data_written; break; - } else if (err > 0) { - fprintf(stderr, "Failed to acquire full telemetry log!\n"); - nvme_show_status(err); + } else if (data_written <= data_remaining) { + data_remaining -= data_written; + data_ptr += data_written; + } else { + /* Unexpected overwrite */ + fprintf(stderr, "Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x\n", + data_remaining, data_written); break; } + } - err = write(output, (void *) page_log, bs); - if (err != bs) { - fprintf(stderr, "Failed to flush all data to file!\n"); - break; - } - err = 0; - offset += bs; + if (fsync(output) < 0) { + fprintf(stderr, "ERROR : %s: : fsync : %s\n", __func__, strerror(errno)); + return -1; } + free(log); + close_output: close(output); -free_mem: - free(hdr); - free(page_log); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_endurance_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -549,16 +544,16 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct const char *desc = "Retrieves endurance groups log page and prints the log."; const char *group_id = "The endurance group identifier"; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - char *output_format; - __u16 group_id; + char *output_format; + __u16 group_id; }; struct config cfg = { - .output_format = "normal", - .group_id = 0, + .output_format = "normal", + .group_id = 0, }; OPT_ARGS(opts) = { @@ -575,17 +570,38 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct if (flags < 0) goto close_fd; - err = nvme_endurance_log(fd, cfg.group_id, &endurance_log); + err = nvme_get_log_endurance_group(fd, cfg.group_id, &endurance_log); if (!err) nvme_show_endurance_log(&endurance_log, cfg.group_id, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("endurance log"); + fprintf(stderr, "endurance log: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; +} + +void collect_effects_log(int fd, enum nvme_csi csi, struct list_head *list, int flags) +{ + int err; + nvme_effects_log_node_t *node = malloc(sizeof(nvme_effects_log_node_t)); + if (!node) + return; + node->csi = csi; + + err = nvme_get_log_cmd_effects(fd, csi, &node->effects); + if (!err) { + list_add(list, &node->node); + return; + } + else if (err > 0) + nvme_show_status(err); + else + fprintf(stderr, "effects log page: %s\n", nvme_strerror(errno)); + + free(node); } static int get_effects_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -593,25 +609,34 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl const char *desc = "Retrieve command effects log page and print the table."; const char *raw = "show log in binary format"; const char *human_readable = "show log in readable format"; - struct nvme_effects_log_page effects; + const char *csi = ""; + struct list_head log_pages; + nvme_effects_log_node_t *node; + + void *bar = NULL; int err = -1, fd; enum nvme_print_flags flags; struct config { - int raw_binary; - int human_readable; - char *output_format; + char *output_format; + bool human_readable; + bool raw_binary; + int csi; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", + .human_readable = false, + .raw_binary = false, + .csi = -1, }; OPT_ARGS(opts) = { OPT_FMT("output-format", 'o', &cfg.output_format, output_format), OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_INT("csi", 'c', &cfg.csi, csi), OPT_END() }; @@ -627,17 +652,52 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl if (cfg.human_readable) flags |= VERBOSE; - err = nvme_effects_log(fd, &effects); - if (!err) - nvme_show_effects_log(&effects, flags); - else if (err > 0) - nvme_show_status(err); - else - perror("effects log page"); + list_head_init(&log_pages); + + if (cfg.csi < 0) { + nvme_root_t nvme_root; + uint64_t cap; + int nvme_command_set_supported; + int other_command_sets_supported; + nvme_root = nvme_scan(NULL); + bar = mmap_registers(nvme_root, devicename); + nvme_free_tree(nvme_root); + + if (!bar) { + goto close_fd; + } + cap = mmio_read64(bar + NVME_REG_CAP); + munmap(bar, getpagesize()); + + nvme_command_set_supported = NVME_CAP_CSS(cap) & NVME_CAP_CSS_NVM; + other_command_sets_supported = NVME_CAP_CSS(cap) & NVME_CAP_CSS_CSI; + + + if (nvme_command_set_supported) { + collect_effects_log(fd, NVME_CSI_NVM, &log_pages, flags); + } + + if (other_command_sets_supported) { + collect_effects_log(fd, NVME_CSI_ZNS, &log_pages, flags); + } + + nvme_print_effects_log_pages(&log_pages, flags); + + } + else { + collect_effects_log(fd, cfg.csi, &log_pages, flags); + nvme_print_effects_log_pages(&log_pages, flags); + } + + close_fd: + while ((node = list_pop(&log_pages, nvme_effects_log_node_t, node))) { + free(node); + } + close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_supported_log_pages(int argc, char **argv, struct command *cmd, @@ -645,18 +705,19 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd, { const char *desc = "Retrieve supported logs and print the table."; const char *verbose = "Increase output verbosity"; - struct nvme_support_log_pages supports; + struct nvme_supported_log_pages supports; int err = -1, fd; enum nvme_print_flags flags; struct config { - int verbose; - char *output_format; + char *output_format; + bool verbose; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", + .verbose = false }; OPT_ARGS(opts) = { @@ -676,18 +737,19 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd, if (cfg.verbose) flags |= VERBOSE; - err = nvme_supported_log(fd, &supports); + err = nvme_get_log_supported_log_pages(fd, false, &supports); if (!err) nvme_show_supported_log(&supports, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("supported log pages"); + fprintf(stderr, "supported log pages: %s", + nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -703,14 +765,15 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug int err = -1, fd; struct config { - __u32 log_entries; - int raw_binary; - char *output_format; + __u32 log_entries; + char *output_format; + bool raw_binary; }; struct config cfg = { - .log_entries = 64, - .output_format = "normal", + .log_entries = 64, + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -732,7 +795,6 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug if (!cfg.log_entries) { fprintf(stderr, "non-zero log-entries is required param\n"); - errno = EINVAL; err = -1; goto close_fd; } @@ -743,7 +805,6 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug goto close_fd; } else if (err) { fprintf(stderr, "could not identify controller\n"); - errno = ENODEV; err = -1; goto close_fd; } @@ -751,13 +812,11 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug 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) { - perror("could not alloc buffer for error log\n"); - errno = ENOMEM; err = -1; goto close_fd; } - err = nvme_error_log(fd, cfg.log_entries, err_log); + err = nvme_get_log_error(fd, cfg.log_entries, true, err_log); if (!err) nvme_show_error_log(err_log, cfg.log_entries, devicename, flags); else if (err > 0) @@ -768,7 +827,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -776,17 +835,18 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin const char *desc = "Retrieve the firmware log for the "\ "specified device in either decoded format (default) or binary."; const char *raw = "use binary output"; - struct nvme_firmware_log_page fw_log; + struct nvme_firmware_slot fw_log; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - int raw_binary; - char *output_format; + char *output_format; + bool raw_binary; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -805,36 +865,37 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin if (cfg.raw_binary) flags = BINARY; - err = nvme_fw_log(fd, &fw_log); + err = nvme_get_log_fw_slot(fd, true, &fw_log); if (!err) nvme_show_fw_log(&fw_log, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("fw log"); + fprintf(stderr, "fw log: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - struct nvme_changed_ns_list_log changed_ns_list_log; const char *desc = "Retrieve Changed Namespaces log for the given device "\ "in either decoded format "\ "(default) or binary."; const char *raw = "output in binary format"; + struct nvme_ns_list changed_ns_list_log; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - int raw_binary; - char *output_format; + char *output_format; + bool raw_binary; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -853,18 +914,19 @@ static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, s if (cfg.raw_binary) flags = BINARY; - err = nvme_changed_ns_list_log(fd, &changed_ns_list_log); + err = nvme_get_log_changed_ns_list(fd, true, &changed_ns_list_log); if (!err) nvme_show_changed_ns_list_log(&changed_ns_list_log, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("changed ns list log"); + fprintf(stderr, "changed ns list log: %s\n", + nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_pred_lat_per_nvmset_log(int argc, char **argv, @@ -875,25 +937,26 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, "format(default),json or binary."; const char *nvmset_id = "NVM Set Identifier"; const char *raw = "use binary output"; - struct nvme_predlat_per_nvmset_log_page plpns_log; + struct nvme_nvmset_predictable_lat_log plpns_log; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - __u16 nvmset_id; - char *output_format; - int raw_binary; + __u16 nvmset_id; + char *output_format; + bool raw_binary; }; struct config cfg = { - .nvmset_id = 1, - .output_format = "normal", + .nvmset_id = 1, + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { - OPT_SHRT("nvmset-id", 'i', &cfg.nvmset_id, nvmset_id), + OPT_SHRT("nvmset-id", 'i', &cfg.nvmset_id, nvmset_id), OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() }; @@ -907,20 +970,20 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, if (cfg.raw_binary) flags = BINARY; - err = nvme_predictable_latency_per_nvmset_log(fd, - cfg.nvmset_id, &plpns_log); + err = nvme_get_log_predictable_lat_nvmset(fd, cfg.nvmset_id, &plpns_log); if (!err) nvme_show_predictable_latency_per_nvmset(&plpns_log, cfg.nvmset_id, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("predictable latency per nvm set"); + fprintf(stderr, "predictable latency per nvm set: %s\n", + nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_pred_lat_event_agg_log(int argc, char **argv, @@ -934,23 +997,24 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, "log Entries list"; const char *rae = "Retain an Asynchronous Event"; const char *raw = "use binary output"; - void *pea_log; - struct nvme_id_ctrl ctrl; enum nvme_print_flags flags; - int err = -1, fd; + struct nvme_id_ctrl ctrl; __u32 log_size; + void *pea_log; + int err, fd; struct config { - __u64 log_entries; - bool rae; - char *output_format; - int raw_binary; + __u64 log_entries; + bool rae; + char *output_format; + bool raw_binary; }; struct config cfg = { - .log_entries = 2044, - .rae = false, - .output_format = "normal", + .log_entries = 2044, + .rae = false, + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -973,14 +1037,14 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, if (!cfg.log_entries) { fprintf(stderr, "non-zero log-entries is required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } err = nvme_identify_ctrl(fd, &ctrl); if (err < 0) { - perror("identify controller"); + fprintf(stderr, "identify controller: %s\n", + nvme_strerror(errno)); goto close_fd; } else if (err) { nvme_show_status(err); @@ -991,28 +1055,25 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, log_size = sizeof(__u64) + cfg.log_entries * sizeof(__u16); pea_log = calloc(log_size, 1); if (!pea_log) { - perror("could not alloc buffer for predictable " \ - "latency event agggregate log entries\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } - err = nvme_predictable_latency_event_agg_log(fd, pea_log, cfg.rae, - log_size); + err = nvme_get_log_predictable_lat_event(fd, cfg.rae, 0, log_size, pea_log); if (!err) nvme_show_predictable_latency_event_agg_log(pea_log, cfg.log_entries, log_size, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("predictable latency event gggregate log page"); + fprintf(stderr, "predictable latency event aggregate log page: %s", + nvme_strerror(errno)); free(pea_log); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_persistent_event_log(int argc, char **argv, @@ -1025,28 +1086,29 @@ static int get_persistent_event_log(int argc, char **argv, " processing this persistent log page command."; const char *log_len = "number of bytes to retrieve"; const char *raw = "use binary output"; - void *pevent_log_info; - struct nvme_persistent_event_log_head *pevent_log_head, *collected_head; + struct nvme_persistent_event_log *pevent, *pevent_collected; enum nvme_print_flags flags; - int err = -1, fd; + void *pevent_log_info; + int err, fd; bool huge; struct config { - __u8 action; - __u32 log_len; - int raw_binary; - char *output_format; + __u8 action; + __u32 log_len; + char *output_format; + bool raw_binary; }; struct config cfg = { - .action = 0xff, - .log_len = 0, - .output_format = "normal", + .action = 0xff, + .log_len = 0, + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { OPT_BYTE("action", 'a', &cfg.action, action), - OPT_UINT("log_len", 'l', &cfg.log_len, log_len), + OPT_UINT("log_len", 'l', &cfg.log_len, log_len), OPT_FMT("output-format", 'o', &cfg.output_format, output_format), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() @@ -1062,42 +1124,33 @@ static int get_persistent_event_log(int argc, char **argv, if (cfg.raw_binary) flags = BINARY; - if (cfg.action > 3) { - fprintf(stderr, "invalid action field: %u\n", cfg.action); - errno = EINVAL; - err = -1; - goto close_fd; - } - - pevent_log_head = calloc(sizeof(*pevent_log_head), 1); - if (!pevent_log_head) { - perror("could not alloc buffer for persistent " \ - "event log header\n"); - errno = ENOMEM; - err = -1; + pevent = calloc(sizeof(*pevent), 1); + if (!pevent) { + err = -ENOMEM; goto close_fd; } - err = nvme_persistent_event_log(fd, cfg.action, - sizeof(*pevent_log_head), pevent_log_head); + err = nvme_get_log_persistent_event(fd, cfg.action, + sizeof(*pevent), pevent); if (err < 0) { - perror("persistent event log"); - goto free_head; + fprintf(stderr, "persistent event log: %s\n", + nvme_strerror(errno)); + goto free_pevent; } else if (err) { nvme_show_status(err); - goto free_head; + goto free_pevent; } if (cfg.action == NVME_PEVENT_LOG_RELEASE_CTX) { printf("Releasing Persistent Event Log Context\n"); - goto free_head; + goto free_pevent; } if (!cfg.log_len && cfg.action != NVME_PEVENT_LOG_EST_CTX_AND_READ) { - cfg.log_len = le64_to_cpu(pevent_log_head->tll); + cfg.log_len = le64_to_cpu(pevent->tll); } else if (!cfg.log_len && cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ) { printf("Establishing Persistent Event Log Context\n"); - goto free_head; + goto free_pevent; } /* @@ -1112,45 +1165,45 @@ static int get_persistent_event_log(int argc, char **argv, pevent_log_info = nvme_alloc(cfg.log_len, &huge); if (!pevent_log_info) { - perror("could not alloc buffer for persistent event log page\n"); - errno = ENOMEM; - err = -1; - goto free_head; + err = -ENOMEM; + goto free_pevent; } - err = nvme_persistent_event_log(fd, cfg.action, + err = nvme_get_log_persistent_event(fd, cfg.action, cfg.log_len, pevent_log_info); if (!err) { - err = nvme_persistent_event_log(fd, cfg.action, - sizeof(*pevent_log_head), pevent_log_head); + err = nvme_get_log_persistent_event(fd, cfg.action, + sizeof(*pevent), pevent); if (err < 0) { - perror("persistent event log"); + fprintf(stderr, "persistent event log: %s\n", + nvme_strerror(errno)); goto free; } else if (err) { nvme_show_status(err); goto free; } - collected_head = pevent_log_info; - if(collected_head->gen_number != pevent_log_head->gen_number) { + pevent_collected = pevent_log_info; + if (pevent_collected->gen_number != pevent->gen_number) { printf("Collected Persistent Event Log may be invalid, "\ "Re-read the log is reiquired\n"); goto free; } + nvme_show_persistent_event_log(pevent_log_info, cfg.action, cfg.log_len, devicename, flags); - } - else if (err > 0) + } else if (err > 0) nvme_show_status(err); else - perror("persistent event log"); + fprintf(stderr, "persistent event log: %s\n", + nvme_strerror(errno)); free: nvme_free(pevent_log_info, huge); -free_head: - free(pevent_log_head); +free_pevent: + free(pevent); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_endurance_event_agg_log(int argc, char **argv, @@ -1167,20 +1220,21 @@ static int get_endurance_event_agg_log(int argc, char **argv, void *endurance_log; struct nvme_id_ctrl ctrl; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; __u32 log_size; struct config { - __u64 log_entries; - bool rae; - char *output_format; - int raw_binary; + __u64 log_entries; + bool rae; + char *output_format; + bool raw_binary; }; struct config cfg = { - .log_entries = 2044, - .rae = false, - .output_format = "normal", + .log_entries = 2044, + .rae = false, + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -1203,19 +1257,18 @@ static int get_endurance_event_agg_log(int argc, char **argv, if (!cfg.log_entries) { fprintf(stderr, "non-zero log-entries is required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } err = nvme_identify_ctrl(fd, &ctrl); if (err < 0) { - perror("identify controller"); + fprintf(stderr, "identify controller: %s\n", + nvme_strerror(errno)); goto close_fd; } else if (err) { fprintf(stderr, "could not identify controller\n"); - errno = ENODEV; - err = -1; + err = -ENODEV; goto close_fd; } @@ -1223,28 +1276,25 @@ static int get_endurance_event_agg_log(int argc, char **argv, log_size = sizeof(__u64) + cfg.log_entries * sizeof(__u16); endurance_log = calloc(log_size, 1); if (!endurance_log) { - perror("could not alloc buffer for endurance group" \ - " event agggregate log entries\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } - err = nvme_endurance_group_event_agg_log(fd, endurance_log, cfg.rae, - log_size); + err = nvme_get_log_endurance_grp_evt(fd, cfg.rae, 0, log_size, endurance_log); if (!err) nvme_show_endurance_group_event_agg_log(endurance_log, cfg.log_entries, log_size, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("endurance group event aggregate log page"); + fprintf(stderr, "endurance group event aggregate log page: %s\n", + nvme_strerror(errno)); free(endurance_log); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_lba_status_log(int argc, char **argv, @@ -1256,17 +1306,17 @@ static int get_lba_status_log(int argc, char **argv, const char *rae = "Retain an Asynchronous Event"; void *lab_status; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; __u32 lslplen; struct config { - bool rae; - char *output_format; + bool rae; + char *output_format; }; struct config cfg = { - .rae = false, - .output_format = "normal", + .rae = false, + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -1283,9 +1333,10 @@ static int get_lba_status_log(int argc, char **argv, if (flags < 0) goto close_fd; - err = nvme_lba_status_log(fd, &lslplen, true, sizeof(__u32)); + err = nvme_get_log_lba_status(fd, true, 0, sizeof(__u32), &lslplen); if (err < 0) { - perror("lba status log page"); + fprintf(stderr, "lba status log page: %s\n", + nvme_strerror(errno)); goto close_fd; } else if (err) { nvme_show_status(err); @@ -1294,25 +1345,24 @@ static int get_lba_status_log(int argc, char **argv, lab_status = calloc(lslplen, 1); if (!lab_status) { - perror("could not alloc buffer for lba status log"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } - err = nvme_lba_status_log(fd, lab_status, cfg.rae, lslplen); + err = nvme_get_log_lba_status(fd, cfg.rae, 0, lslplen, lab_status); if (!err) nvme_show_lba_status_log(lab_status, lslplen, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("lba status log page"); + fprintf(stderr, "lba status log page: %s\n", + nvme_strerror(errno)); free(lab_status); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_resv_notif_log(int argc, char **argv, @@ -1323,16 +1373,16 @@ static int get_resv_notif_log(int argc, char **argv, "log page and prints it, for the given " \ "device in either decoded format(default), " \ "json or binary."; - struct nvme_resv_notif_log resv; + struct nvme_resv_notification_log resv; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - char *output_format; + char *output_format; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -1348,18 +1398,19 @@ static int get_resv_notif_log(int argc, char **argv, if (flags < 0) goto close_fd; - err = nvme_resv_notif_log(fd, &resv); + err = nvme_get_log_reservation(fd, true, &resv); if (!err) nvme_show_resv_notif_log(&resv, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("resv notifi log"); + fprintf(stderr, "resv notifi log: %s\n", + nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } @@ -1371,22 +1422,22 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct "json or binary."; const char *lsp = "log specific field"; const char *fname = "boot partition data output file name"; - struct nvme_boot_part_hdr boot; + struct nvme_boot_partition boot; __u8 *bp_log; enum nvme_print_flags flags; int err = -1, fd = 0, output = 0; __u32 bpsz = 0; struct config { - __u8 lsp; - char *output_format; - char *file_name; + __u8 lsp; + char *file_name; + char *output_format; }; struct config cfg = { - .lsp = 0, - .file_name = NULL, - .output_format = "normal", + .lsp = 0, + .output_format = "normal", + .file_name = NULL, }; OPT_ARGS(opts) = { @@ -1406,14 +1457,12 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct if (!cfg.file_name) { fprintf(stderr, "Please provide an output file!\n"); - errno = EINVAL; err = -1; goto close_fd; } if (cfg.lsp > 128) { fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp); - errno = EINVAL; err = -1; goto close_fd; } @@ -1426,9 +1475,11 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct goto close_fd; } - err = nvme_boot_part_log(fd, cfg.lsp, &boot, sizeof(boot)); + err = nvme_get_log_boot_partition(fd, false, cfg.lsp, + sizeof(boot), &boot); if (err < 0) { - perror("boot partition log"); + fprintf(stderr, "boot partition log: %s\n", + nvme_strerror(errno)); goto close_output; } else if (err) { nvme_show_status(err); @@ -1438,19 +1489,20 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct bpsz = (boot.bpinfo & 0x7fff) * 128 * 1024; bp_log = calloc(sizeof(boot) + bpsz, 1); if (!bp_log) { - perror("could not alloc buffer for boot partition log"); - errno = ENOMEM; err = -1; goto close_output; } - err = nvme_boot_part_log(fd, cfg.lsp, &bp_log, sizeof(boot) + bpsz); + err = nvme_get_log_boot_partition(fd, false, cfg.lsp, + sizeof(boot) + bpsz, + (struct nvme_boot_partition *)bp_log); if (!err) nvme_show_boot_part_log(&bp_log, devicename, flags, sizeof(boot) + bpsz); else if (err > 0) nvme_show_status(err); else - perror("boot partition log"); + fprintf(stderr, "boot partition log: %s\n", + nvme_strerror(errno)); err = write(output, (void *) bp_log + sizeof(boot), bpsz); if (err != bpsz) { @@ -1467,7 +1519,118 @@ close_output: close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; +} + +static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Retrieve the configuration and wear of media units and print it"; + const char *domainid = "Domain Identifier"; + const char *raw = "use binary output"; + struct nvme_media_unit_stat_log mus; + + int err = -1, fd; + enum nvme_print_flags flags; + + struct config { + __u16 domainid; + char *output_format; + bool raw_binary; + }; + + struct config cfg = { + .domainid = 0, + .output_format = "normal", + .raw_binary = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("domain-id", 'd', &cfg.domainid, domainid), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + + if (cfg.raw_binary) + flags = BINARY; + + err = nvme_get_log_media_unit_stat(fd, cfg.domainid, &mus); + if (!err) + nvme_show_media_unit_stat_log(&mus, flags); + else if (err > 0) + nvme_show_status(err); + else + fprintf(stderr, "media unit status log: %s\n", + nvme_strerror(errno)); + +close_fd: + close(fd); +ret: + return err; +} + +static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Retrieve the list of Supported Capacity Configuration Descriptors"; + const char *domainid = "Domain Identifier"; + const char *raw = "use binary output"; + struct nvme_supported_cap_config_list_log cap_log; + + int err = -1, fd; + enum nvme_print_flags flags; + + struct config { + __u16 domainid; + char *output_format; + bool raw_binary; + }; + + struct config cfg = { + .domainid = 0, + .output_format = "normal", + .raw_binary = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("domain-id", 'd', &cfg.domainid, domainid), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + + if (cfg.raw_binary) + flags = BINARY; + + err = nvme_get_log_support_cap_config_list(fd, cfg.domainid, &cap_log); + if (!err) + nvme_show_supported_cap_config_log(&cap_log, flags); + else if (err > 0) + nvme_show_status(err); + else + perror("supported capacity configuration list log"); + +close_fd: + close(fd); +ret: + return err; } static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -1487,35 +1650,37 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl const char *uuid_index = "UUID index"; const char *csi = "command set identifier"; const char *offset_type = "offset type"; - int err = -1, fd; + int err, fd; unsigned char *log; struct config { - __u16 lsi; - __u32 namespace_id; - __u8 log_id; - __u32 log_len; - __u32 aen; - __u64 lpo; - __u8 lsp; - __u8 uuid_index; - __u8 csi; - int ot; - int rae; - int raw_binary; + __u32 namespace_id; + __u8 log_id; + __u32 log_len; + __u32 aen; + __u64 lpo; + __u8 lsp; + __u16 lsi; + bool rae; + __u8 uuid_index; + bool raw_binary; + __u8 csi; + bool ot; }; struct config cfg = { - .namespace_id = NVME_NSID_ALL, - .log_id = 0xff, - .log_len = 0, - .lpo = NVME_NO_LOG_LPO, - .lsp = NVME_NO_LOG_LSP, - .lsi = 0, - .rae = 0, - .uuid_index = 0, - .csi = 0, - .ot = 0, + .namespace_id = NVME_NSID_ALL, + .log_id = 0xff, + .log_len = 0, + .aen = 0, + .lpo = NVME_LOG_LPO_NONE, + .lsp = NVME_LOG_LSP_NONE, + .lsi = NVME_LOG_LSI_NONE, + .rae = false, + .uuid_index = NVME_UUID_NONE, + .raw_binary = false, + .csi = NVME_CSI_NVM, + .ot = false, }; OPT_ARGS(opts) = { @@ -1528,9 +1693,9 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl OPT_SHRT("lsi", 'S', &cfg.lsi, lsi), OPT_FLAG("rae", 'r', &cfg.rae, rae), OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_BYTE("csi", 'y', &cfg.csi, csi), OPT_FLAG("ot", 'O', &cfg.ot, offset_type), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() }; @@ -1544,23 +1709,20 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl } if (!cfg.log_len) { - fprintf(stderr, "non-zero log-len is required param\n"); - errno = EINVAL; - err = -1; + perror("non-zero log-len is required param\n"); + err = -EINVAL; goto close_fd; } if (cfg.lsp > 128) { - fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp); - errno = EINVAL; - err = -1; + perror("invalid lsp param\n"); + err = -EINVAL; goto close_fd; } if (cfg.uuid_index > 128) { - fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index); - errno = EINVAL; - err = -1; + perror("invalid uuid index param\n"); + err = -EINVAL; goto close_fd; } @@ -1571,27 +1733,42 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl goto close_fd; } - err = nvme_get_log14(fd, cfg.namespace_id, cfg.log_id, - cfg.lsp, cfg.lpo, cfg.lsi, cfg.rae, - cfg.uuid_index, cfg.csi, cfg.ot, cfg.log_len, log); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = cfg.log_id, + .nsid = cfg.namespace_id, + .lpo = cfg.lpo, + .lsp = cfg.lsp, + .lsi = cfg.lsi, + .rae = cfg.rae, + .uuidx = cfg.uuid_index, + .csi = cfg.csi, + .ot = cfg.ot, + .len = cfg.log_len, + .log = log, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_get_log(&args); if (!err) { if (!cfg.raw_binary) { printf("Device:%s log-id:%d namespace-id:%#x\n", - devicename, cfg.log_id, - cfg.namespace_id); + 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) nvme_show_status(err); else - perror("log page"); + fprintf(stderr, "log page: %s\n", nvme_strerror(errno)); free(log); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int sanitize_log(int argc, char **argv, struct command *command, struct plugin *plugin) @@ -1602,18 +1779,20 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p const char *human_readable = "show log in readable format"; struct nvme_sanitize_log_page sanitize_log; enum nvme_print_flags flags; - int fd, err = -1; + int fd, err; struct config { - bool rae; - int raw_binary; - int human_readable; - char *output_format; + bool rae; + char *output_format; + bool human_readable; + bool raw_binary; }; struct config cfg = { - .rae = false, - .output_format = "normal", + .rae = false, + .output_format = "normal", + .human_readable = false, + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -1636,17 +1815,18 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p if (cfg.human_readable) flags |= VERBOSE; - err = nvme_sanitize_log(fd, cfg.rae, &sanitize_log); + err = nvme_get_log_sanitize(fd, cfg.rae, &sanitize_log); if (!err) nvme_show_sanitize_log(&sanitize_log, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("sanitize status log"); + fprintf(stderr, "sanitize status log: %s\n", + nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_fid_support_effects_log(int argc, char **argv, struct command *cmd, @@ -1654,17 +1834,18 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm { const char *desc = "Retrieve FID Support and Effects log and show it."; const char *human_readable = "show log in readable format"; - struct nvme_fid_support_effects fid_support_log; + struct nvme_fid_supported_effects_log fid_support_log; enum nvme_print_flags flags; int fd, err = -1; struct config { - int human_readable; - char *output_format; + char *output_format; + bool human_readable; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", + .human_readable = false, }; OPT_ARGS(opts) = { @@ -1683,17 +1864,67 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm if (cfg.human_readable) flags |= VERBOSE; - err = nvme_fid_support_effects_log(fd, &fid_support_log); + err = nvme_get_log_fid_supported_effects(fd, false, &fid_support_log); if (!err) nvme_show_fid_support_effects_log(&fid_support_log, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("fid support effects log"); + fprintf(stderr, "fid support effects log: %s\n", + nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; +} + +static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Retrieve NVMe-MI Command Support and Effects log and show it."; + const char *human_readable = "show log in readable format"; + struct nvme_mi_cmd_supported_effects_log mi_cmd_support_log; + enum nvme_print_flags flags; + int fd, err = -1; + + struct config { + char *output_format; + bool human_readable; + }; + + struct config cfg = { + .output_format = "normal", + .human_readable = false, + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + if (cfg.human_readable) + flags |= VERBOSE; + + err = nvme_get_log_mi_cmd_supported_effects(fd, false, &mi_cmd_support_log); + if (!err) + nvme_show_mi_cmd_support_effects_log(&mi_cmd_support_log, devicename, flags); + else if (err > 0) + nvme_show_status(err); + else + fprintf(stderr, "mi command support effects log: %s\n", + nvme_strerror(errno)); +close_fd: + close(fd); +ret: + return err; } static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -1702,19 +1933,20 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * "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 = -1, fd; - struct nvme_controller_list *cntlist; + int err, fd; + struct nvme_ctrl_list *cntlist; enum nvme_print_flags flags; struct config { - __u16 cntid; - __u32 namespace_id; - char *output_format; + __u16 cntid; + __u32 namespace_id; + char *output_format; }; struct config cfg = { - .cntid = 0, - .output_format = "normal", + .cntid = 0, + .namespace_id = NVME_NSID_NONE, + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -1731,31 +1963,31 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * err = flags = validate_output_format(cfg.output_format); if (flags < 0) goto close_fd; - if (flags != JSON && flags != NORMAL) { - err = -EINVAL; - goto close_fd; - } if (posix_memalign((void *)&cntlist, getpagesize(), 0x1000)) { fprintf(stderr, "can not allocate controller list payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } - err = nvme_identify_ctrl_list(fd, cfg.namespace_id, cfg.cntid, cntlist); + if (cfg.namespace_id == NVME_NSID_NONE) + err = nvme_identify_ctrl_list(fd, cfg.cntid, cntlist); + else + err = nvme_identify_nsid_ctrl_list(fd, cfg.namespace_id, + cfg.cntid, cntlist); if (!err) nvme_show_list_ctrl(cntlist, flags); else if (err > 0) nvme_show_status(err); else - perror("id controller list"); + fprintf(stderr, "id controller list: %s\n", + nvme_strerror(errno)); free(cntlist); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -1765,25 +1997,27 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl const char *namespace_id = "first nsid returned list should start from"; const char *csi = "I/O command set identifier"; const char *all = "show all namespaces in the subsystem, whether attached or inactive"; - int err = -1, fd; - __le32 ns_list[1024]; + int err, fd; + struct nvme_ns_list ns_list; enum nvme_print_flags flags; struct config { - __u32 namespace_id; - int all; - __u8 csi; - char *output_format; + __u32 namespace_id; + int csi; + bool all; + char *output_format; }; struct config cfg = { - .namespace_id = 1, + .namespace_id = 1, + .csi = -1, + .all = false, .output_format = "normal", }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_BYTE("csi", 'y', &cfg.csi, csi), + OPT_INT("csi", 'y', &cfg.csi, csi), OPT_FLAG("all", 'a', &cfg.all, all), OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary), OPT_END() @@ -1802,20 +2036,95 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl } if (!cfg.namespace_id) { - errno = EINVAL; - err = -1; + err = -EINVAL; fprintf(stderr, "invalid nsid parameter\n"); goto close_fd; } - err = nvme_identify_ns_list_csi(fd, cfg.namespace_id - 1, cfg.csi, - !!cfg.all, ns_list); + if (cfg.csi < 0) { + if (cfg.all) + err = nvme_identify_allocated_ns_list(fd, + cfg.namespace_id - 1, &ns_list); + else + err = nvme_identify_active_ns_list(fd, + cfg.namespace_id - 1, &ns_list); + + } else { + if (cfg.all) + err = nvme_identify_allocated_ns_list_csi(fd, + cfg.namespace_id - 1, cfg.csi, &ns_list); + else + err = nvme_identify_active_ns_list_csi(fd, + cfg.namespace_id - 1, cfg.csi, &ns_list); + } + + if (!err) + nvme_show_list_ns(&ns_list, flags); + else if (err > 0) + nvme_show_status(err); + else + fprintf(stderr, "id namespace list: %s", + nvme_strerror(errno)); +close_fd: + close(fd); +ret: + return err; +} + +static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send an Identify Namespace command to the given "\ + "device, returns capability field properties of the specified "\ + "LBA Format index in various formats."; + const char *lba_format_index = "The index into the LBA Format list "\ + "identifying the LBA Format capabilities that are to be returned"; + const char *uuid_index = "UUID index"; + const char *verbose = "Increase output verbosity"; + enum nvme_print_flags flags; + struct nvme_id_ns ns; + int err = -1, fd; + + struct config { + __u16 lba_format_index; + __u8 uuid_index; + bool verbose; + char *output_format; + }; + + struct config cfg = { + .lba_format_index = 0, + .uuid_index = NVME_UUID_NONE, + .verbose = false, + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_UINT("lba-format-index", 'i', &cfg.lba_format_index, lba_format_index), + OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index), + OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + + if (cfg.verbose) + flags |= VERBOSE; + + err = nvme_identify_ns_csi_user_data_format(fd, cfg.lba_format_index, + cfg.uuid_index, NVME_CSI_NVM, &ns); if (!err) - nvme_show_list_ns(ns_list, flags); + nvme_show_id_ns(&ns, 0, cfg.lba_format_index, true, flags); else if (err > 0) nvme_show_status(err); else - perror("id namespace list"); + perror("identify namespace for specific LBA format"); close_fd: close(fd); ret: @@ -1829,17 +2138,17 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, "group id"; const char *endurance_grp_id = "Endurance Group ID"; int err = -1, fd; - struct nvme_endurance_group_list *endgrp_list; + struct nvme_id_endurance_group_list *endgrp_list; enum nvme_print_flags flags; struct config { - __u16 endgrp_id; - char *output_format; + __u16 endgrp_id; + char *output_format; }; struct config cfg = { - .endgrp_id = 0, - .output_format = "normal", + .endgrp_id = 0, + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -1862,8 +2171,6 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, } if (posix_memalign((void *)&endgrp_list, getpagesize(), 0x1000)) { - fprintf(stderr, "can not allocate memory for endurance gropu list\n"); - errno = ENOMEM; err = -1; goto close_fd; } @@ -1874,13 +2181,14 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, else if (err > 0) nvme_show_status(err); else - perror("id endurance group list"); + fprintf(stderr, "Id endurance group list: %s", + nvme_strerror(errno)); free(endgrp_list); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -1893,7 +2201,7 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * "the namespace is not already inactive, once deleted."; const char *namespace_id = "namespace to delete"; const char *timeout = "timeout value, in milliseconds"; - int err = -1, fd; + int err, fd; struct config { __u32 namespace_id; @@ -1902,7 +2210,7 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * struct config cfg = { .namespace_id = 0, - .timeout = NVME_IOCTL_TIMEOUT, + .timeout = 120000, }; OPT_ARGS(opts) = { @@ -1916,44 +2224,46 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", + nvme_strerror(errno)); goto close_fd; } } - err = nvme_ns_delete(fd, cfg.namespace_id, cfg.timeout); + err = nvme_ns_mgmt_delete(fd, cfg.namespace_id); if (!err) printf("%s: Success, deleted nsid:%d\n", cmd->name, cfg.namespace_id); else if (err > 0) nvme_show_status(err); else - perror("delete namespace"); + fprintf(stderr, "delete namespace: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd) { - int err = -1, num, i, fd, list[2048]; + int err, num, fd, i, list[2048]; + struct nvme_ctrl_list cntlist; __u16 ctrlist[2048]; const char *namespace_id = "namespace to attach"; const char *cont = "optional comma-sep controller id list"; struct config { - char *cntlist; - __u32 namespace_id; + __u32 namespace_id; + char *cntlist; }; struct config cfg = { - .cntlist = "", - .namespace_id = 0, + .namespace_id = 0, + .cntlist = "", }; OPT_ARGS(opts) = { @@ -1969,8 +2279,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s if (!cfg.namespace_id) { fprintf(stderr, "%s: namespace-id parameter required\n", cmd->name); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } @@ -1982,15 +2291,19 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s if (num == -1) { fprintf(stderr, "%s: controller id list is malformed\n", cmd->name); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } for (i = 0; i < num; i++) - ctrlist[i] = (uint16_t)list[i]; + ctrlist[i] = (__u16)list[i]; + + nvme_init_ctrl_list(&cntlist, num, ctrlist); - err = nvme_ns_attachment(fd, cfg.namespace_id, num, ctrlist, attach); + if (attach) + err = nvme_ns_attach_ctrls(fd, cfg.namespace_id, &cntlist); + else + err = nvme_ns_detach_ctrls(fd, cfg.namespace_id, &cntlist); if (!err) printf("%s: Success, nsid:%d\n", cmd->name, cfg.namespace_id); @@ -2002,7 +2315,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int attach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2040,11 +2353,12 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * const char *anagrpid = "ANA Group Identifier (ANAGRPID)"; const char *nvmsetid = "NVM Set Identifier (NVMSETID)"; const char *csi = "command set identifier (CSI)"; + const char *lbstm = "logical block storage tag mask (LBSTM)"; const char *timeout = "timeout value, in milliseconds"; const char *bs = "target block size, specify only if \'FLBAS\' "\ "value not entered"; - int err = -1, fd, i; + int err = 0, fd, i; struct nvme_id_ns ns; __u32 nsid; @@ -2058,15 +2372,22 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * __u16 nvmsetid; __u64 bs; __u32 timeout; - __u8 csi; + __u8 csi; + __u64 lbstm; }; struct config cfg = { + .nsze = 0, + .ncap = 0, .flbas = 0xff, + .dps = 0, + .nmic = 0, .anagrpid = 0, .nvmsetid = 0, .bs = 0x00, - .timeout = NVME_IOCTL_TIMEOUT, + .timeout = 120000, + .csi = 0, + .lbstm = 0, }; OPT_ARGS(opts) = { @@ -2080,6 +2401,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * OPT_SUFFIX("block-size", 'b', &cfg.bs, bs), OPT_UINT("timeout", 't', &cfg.timeout, timeout), OPT_BYTE("csi", 'y', &cfg.csi, csi), + OPT_SUFFIX("lbstm", 'l', &cfg.lbstm, lbstm), OPT_END() }; @@ -2090,8 +2412,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * if (cfg.flbas != 0xff && cfg.bs != 0x00) { fprintf(stderr, "Invalid specification of both FLBAS and Block Size, please specify only one\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.bs) { @@ -2099,14 +2420,14 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * fprintf(stderr, "Invalid value for block size (%"PRIu64"). Block size must be a power of two\n", (uint64_t)cfg.bs); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_identify_ns(fd, NVME_NSID_ALL, 0, &ns); + err = nvme_identify_ns(fd, NVME_NSID_ALL, &ns); if (err) { if (err < 0) - perror("identify-namespace"); + fprintf(stderr, "identify-namespace: %s", + nvme_strerror(errno)); else { fprintf(stderr, "identify failed\n"); nvme_show_status(err); @@ -2128,51 +2449,93 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * fprintf(stderr, "Please correct block size, or specify FLBAS directly\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_ns_create(fd, cfg.nsze, cfg.ncap, cfg.flbas, cfg.dps, cfg.nmic, - cfg.anagrpid, cfg.nvmsetid, cfg.csi, cfg.timeout, - &nsid); + struct nvme_id_ns ns2 = { + .nsze = cpu_to_le64(cfg.nsze), + .ncap = cpu_to_le64(cfg.ncap), + .flbas = cfg.flbas, + .dps = cfg.dps, + .nmic = cfg.nmic, + .anagrpid = cpu_to_le32(cfg.anagrpid), + .nvmsetid = cpu_to_le16(cfg.nvmsetid), + .lbstm = cpu_to_le64(cfg.lbstm), + }; + + err = nvme_ns_mgmt_create(fd, &ns2, &nsid, cfg.timeout, cfg.csi); if (!err) printf("%s: Success, created nsid:%d\n", cmd->name, nsid); else if (err > 0) nvme_show_status(err); else - perror("create namespace"); + fprintf(stderr, "create namespace: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; +} + +static bool nvme_match_device_filter(nvme_subsystem_t s, + nvme_ctrl_t c, nvme_ns_t ns, void *f_args) +{ + int ret, instance, nsid, s_num; + char *devname = f_args; + + if (!devname || !strlen(devname)) + return true; + + ret = sscanf(devname, "nvme%dn%d", &instance, &nsid); + if (ret != 2) + return true; + + if (s) { + ret = sscanf(nvme_subsystem_get_name(s), "nvme-subsys%d", + &s_num); + if (ret == 1 && s_num == instance) + return true; + } + if (c) { + s = nvme_ctrl_get_subsystem(c); + + ret = sscanf(nvme_subsystem_get_name(s), "nvme-subsys%d", + &s_num); + if (ret == 1 && s_num == instance) + return true; + } + if (ns) { + if (!strcmp(devname, nvme_ns_get_name(ns))) + return true; + } + + return false; } static int list_subsys(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - struct nvme_topology t = { }; + nvme_root_t r = NULL; enum nvme_print_flags flags; - char *subsysnqn = NULL; const char *desc = "Retrieve information for subsystems"; const char *verbose = "Increase output verbosity"; - __u32 ns_instance = 0; - int err = -1, nsid = 0; + nvme_scan_filter_t filter = NULL; + int err; struct config { - char *output_format; - int verbose; + char *output_format; + int verbose; }; struct config cfg = { - .output_format = "normal", - .verbose = 0, + .output_format = "normal", + .verbose = 0, }; OPT_ARGS(opts) = { OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary), - OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), + OPT_INCR("verbose", 'v', &cfg.verbose, verbose), OPT_END() }; @@ -2181,95 +2544,77 @@ static int list_subsys(int argc, char **argv, struct command *cmd, goto ret; devicename = NULL; - if (optind < argc) { - char path[512]; - int id, fd; - - devicename = basename(argv[optind]); - if (sscanf(devicename, "nvme%dn%d", &id, &ns_instance) != 2) { - fprintf(stderr, "%s is not a NVMe namespace device\n", - argv[optind]); - errno = EINVAL; - err = -1; - goto ret; - } - sprintf(path, "/dev/%s", devicename); - fd = open(path, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Cannot read nsid from %s\n", - devicename); - errno = EINVAL; - err = -1; - goto ret; - } - nsid = nvme_get_nsid(fd); - close(fd); - if (nsid < 0) { - fprintf(stderr, "Cannot read nsid from %s\n", - devicename); - errno = EINVAL; - err = -1; - goto ret; - } - sprintf(path, "/sys/block/%s/device", devicename); - subsysnqn = get_nvme_subsnqn(path); - if (!subsysnqn) { - fprintf(stderr, "Cannot read subsys NQN from %s\n", - devicename); - errno = EINVAL; - err = -1; - goto ret; - } - optind++; - } + if (optind < argc) + devicename = basename(argv[optind++]); err = flags = validate_output_format(cfg.output_format); if (flags < 0) - goto free; + goto ret; if (flags != JSON && flags != NORMAL) { - errno = EINVAL; - err = -1; - goto free; + err = -EINVAL; + goto ret; } if (cfg.verbose) flags |= VERBOSE; - err = scan_subsystems(&t, subsysnqn, ns_instance, nsid, NULL); + r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); + if (!r) { + if (devicename) + fprintf(stderr, + "Failed to scan nvme subsystem for %s\n", + devicename); + else + fprintf(stderr, "Failed to scan nvme subsystem\n"); + err = -errno; + goto ret; + } + + if (devicename) { + int subsys_num, nsid; + + if (sscanf(devicename,"nvme%dn%d", + &subsys_num, &nsid) != 2) { + fprintf(stderr, "Invalid device name %s\n", devicename); + err = -EINVAL; + goto ret; + } + filter = nvme_match_device_filter; + } + + err = nvme_scan_topology(r, filter, (void *)devicename); if (err) { - fprintf(stderr, "Failed to scan namespaces\n"); - goto free; + fprintf(stderr, "Failed to scan topology: %s\n", + nvme_strerror(errno)); + goto ret; } - nvme_show_subsystem_list(&t, flags); -free: - free_topology(&t); - free(subsysnqn); + + nvme_show_subsystem_list(r, flags); + ret: - return nvme_status_to_errno(err, false); + if (r) + nvme_free_tree(r); + return err; } static int list(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve basic information for all NVMe namespaces"; - const char *device_dir = "Additional directory to search for devices"; const char *verbose = "Increase output verbosity"; - struct nvme_topology t = { }; enum nvme_print_flags flags; - int err = -1; + nvme_root_t r; + int err = 0; struct config { - char *device_dir; - char *output_format; - int verbose; + char *output_format; + bool verbose; }; struct config cfg = { - .device_dir = NULL, - .output_format = "normal", - .verbose = 0, + .output_format = "normal", + .verbose = false, }; OPT_ARGS(opts) = { - OPT_STRING("directory", 'd', "DIR", &cfg.device_dir, device_dir), OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary), OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), OPT_END() @@ -2289,15 +2634,24 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi if (cfg.verbose) flags |= VERBOSE; - err = scan_subsystems(&t, NULL, 0, 0, cfg.device_dir); - if (err) { - fprintf(stderr, "Failed to scan namespaces\n"); + r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); + return -errno; + } + err = nvme_scan_topology(r, NULL, NULL); + if (err < 0) { + fprintf(stderr, "Failed to scan topoplogy: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); return err; } - nvme_show_list_items(&t, flags); - free_topology(&t); - return 0; + nvme_show_list_items(r, flags); + nvme_free_tree(r); + + return err; } int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, @@ -2313,17 +2667,20 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, const char *human_readable = "show identify in readable format"; enum nvme_print_flags flags; struct nvme_id_ctrl ctrl; - int err = -1, fd; + int err, fd; struct config { - int vendor_specific; - int raw_binary; - int human_readable; - char *output_format; + bool vendor_specific; + char *output_format; + bool raw_binary; + bool human_readable; }; struct config cfg = { - .output_format = "normal", + .vendor_specific = false, + .output_format = "normal", + .raw_binary = false, + .human_readable = false, }; OPT_ARGS(opts) = { @@ -2350,15 +2707,15 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, err = nvme_identify_ctrl(fd, &ctrl); if (!err) - __nvme_show_id_ctrl(&ctrl, flags, vs); + nvme_show_id_ctrl(&ctrl, flags, vs); else if (err > 0) nvme_show_status(err); else - perror("identify controller"); + fprintf(stderr, "identify controller: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2377,15 +2734,15 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, int fd, err = -1; struct config { - char *output_format; + char *output_format; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", }; OPT_ARGS(opts) = { - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), OPT_END() }; @@ -2397,13 +2754,156 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, if (flags < 0) goto close_fd; - err = nvme_identify_ctrl_nvm(fd, &ctrl_nvm); + err = nvme_nvm_identify_ctrl(fd, &ctrl_nvm); if (!err) nvme_show_id_ctrl_nvm(&ctrl_nvm, flags); else if (err > 0) nvme_show_status(err); else - perror("nvm identify controller"); + fprintf(stderr, "nvm identify controller: %s\n", nvme_strerror(errno)); +close_fd: + close(fd); +ret: + return err; +} + +static int nvm_id_ns(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Send an Identify Namespace NVM Command Set "\ + "command to the given device and report information about "\ + "the specified namespace in various formats."; + const char *namespace_id = "identifier of desired namespace"; + const char *uuid_index = "UUID index"; + const char *verbose = "Increase output verbosity"; + enum nvme_print_flags flags; + struct nvme_nvm_id_ns id_ns; + struct nvme_id_ns ns; + int fd, err = -1; + + struct config { + __u32 namespace_id; + __u8 uuid_index; + char *output_format; + bool verbose; + }; + + struct config cfg = { + .namespace_id = 0, + .uuid_index = NVME_UUID_NONE, + .output_format = "normal", + .verbose = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + + if (cfg.verbose) + flags |= VERBOSE; + + if (!cfg.namespace_id) { + err = nvme_get_nsid(fd, &cfg.namespace_id); + if (err < 0) { + perror("get-namespace-id"); + goto close_fd; + } + } + + err = nvme_identify_ns(fd, cfg.namespace_id, &ns); + if (err) { + nvme_show_status(err); + goto close_fd; + } + + err = nvme_identify_ns_csi(fd, cfg.namespace_id, cfg.uuid_index, + NVME_CSI_NVM, &id_ns); + if (!err) + nvme_show_nvm_id_ns(&id_ns, cfg.namespace_id, &ns, 0, false, flags); + else if (err > 0) + nvme_show_status(err); + else + perror("nvm identify namespace"); +close_fd: + close(fd); +ret: + return nvme_status_to_errno(err, false); +} + +static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send an NVM Command Set specific Identify Namespace " + "command to the given device, returns capability field properties of " + "the specified LBA Format index in the specified namespace in various " + "formats."; + const char *lba_format_index = "The index into the LBA Format list "\ + "identifying the LBA Format capabilities that are to be returned"; + const char *uuid_index = "UUID index"; + const char *verbose = "Increase output verbosity"; + enum nvme_print_flags flags; + struct nvme_id_ns ns; + struct nvme_nvm_id_ns nvm_ns; + int err = -1, fd; + + struct config { + __u16 lba_format_index; + __u8 uuid_index; + bool verbose; + char *output_format; + }; + + struct config cfg = { + .lba_format_index = 0, + .uuid_index = NVME_UUID_NONE, + .verbose = false, + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_UINT("lba-format-index", 'i', &cfg.lba_format_index, lba_format_index), + OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index), + OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + + if (cfg.verbose) + flags |= VERBOSE; + + err = nvme_identify_ns(fd, NVME_NSID_ALL, &ns); + if (err) { + ns.nlbaf = NVME_FEAT_LBA_RANGE_MAX - 1; + ns.nulbaf = 0; + } + err = nvme_identify_iocs_ns_csi_user_data_format(fd, cfg.lba_format_index, + cfg.uuid_index, NVME_CSI_NVM, &nvm_ns); + if (!err) + nvme_show_nvm_id_ns(&nvm_ns, 0, &ns, cfg.lba_format_index, true, + flags); + else if (err > 0) + nvme_show_status(err); + else + perror("NVM identify namespace for specific LBA format"); close_fd: close(fd); ret: @@ -2418,18 +2918,19 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p const char *raw = "show descriptors in binary format"; const char *namespace_id = "identifier of desired namespace"; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; void *nsdescs; struct config { - __u32 namespace_id; - int raw_binary; - char *output_format; + __u32 namespace_id; + char *output_format; + bool raw_binary; }; struct config cfg = { - .namespace_id = 0, - .output_format = "normal", + .namespace_id = 0, + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -2450,17 +2951,15 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p flags = BINARY; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) { - fprintf(stderr, "can not allocate controller list payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } @@ -2470,12 +2969,12 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p else if (err > 0) nvme_show_status(err); else - perror("identify namespace"); + fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); free(nsdescs); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2492,25 +2991,29 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug enum nvme_print_flags flags; struct nvme_id_ns ns; - int err = -1, fd; + int err, fd; struct config { - __u32 namespace_id; - int vendor_specific; - int raw_binary; - int human_readable; - int force; - char *output_format; + __u32 namespace_id; + bool force; + bool vendor_specific; + bool raw_binary; + char *output_format; + bool human_readable; }; struct config cfg = { - .namespace_id = 0, - .output_format = "normal", + .namespace_id = 0, + .force = false, + .vendor_specific = false, + .raw_binary = false, + .output_format = "normal", + .human_readable = false, }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_FLAG("force", 'f', &cfg.force, force), + OPT_FLAG("force", 0, &cfg.force, force), OPT_FLAG("vendor-specific", 'v', &cfg.vendor_specific, vendor_specific), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_FMT("output-format", 'o', &cfg.output_format, output_format), @@ -2533,24 +3036,28 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug flags |= VERBOSE; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } - err = nvme_identify_ns(fd, cfg.namespace_id, cfg.force, &ns); + if (cfg.force) + err = nvme_identify_allocated_ns(fd, cfg.namespace_id, &ns); + else + err = nvme_identify_ns(fd, cfg.namespace_id, &ns); + if (!err) - nvme_show_id_ns(&ns, cfg.namespace_id, flags); + nvme_show_id_ns(&ns, cfg.namespace_id, 0, false, flags); else if (err > 0) nvme_show_status(err); else - perror("identify namespace"); + fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int cmd_set_independent_id_ns(int argc, char **argv, @@ -2564,19 +3071,21 @@ static int cmd_set_independent_id_ns(int argc, char **argv, const char *namespace_id = "identifier of desired namespace"; enum nvme_print_flags flags; - struct nvme_cmd_set_independent_id_ns ns; + struct nvme_id_independent_id_ns ns; int err = -1, fd; struct config { - __u32 namespace_id; - int raw_binary; - int human_readable; - char *output_format; + __u32 namespace_id; + bool raw_binary; + char *output_format; + bool human_readable; }; struct config cfg = { - .namespace_id = 0, - .output_format = "normal", + .namespace_id = 0, + .raw_binary = false, + .output_format = "normal", + .human_readable = false, }; OPT_ARGS(opts) = { @@ -2600,24 +3109,24 @@ static int cmd_set_independent_id_ns(int argc, char **argv, flags |= VERBOSE; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = cfg.namespace_id = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; } } - err = nvme_cmd_set_independent_identify_ns(fd, cfg.namespace_id, &ns); + err = nvme_identify_independent_identify_ns(fd, cfg.namespace_id, &ns); if (!err) nvme_show_cmd_set_independent_id_ns(&ns, cfg.namespace_id, flags); else if (err > 0) nvme_show_status(err); else - perror("I/O command set independent identify namespace"); + fprintf(stderr, "I/O command set independent identify namespace: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2628,14 +3137,14 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct struct nvme_id_ns_granularity_list *granularity_list; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - char *output_format; + char *output_format; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -2653,8 +3162,7 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct if (posix_memalign((void *)&granularity_list, getpagesize(), NVME_IDENTIFY_DATA_SIZE)) { fprintf(stderr, "can not allocate granularity list payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } @@ -2664,12 +3172,12 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct else if (err > 0) nvme_show_status(err); else - perror("identify namespace granularity"); + fprintf(stderr, "identify namespace granularity: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2680,18 +3188,18 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * "in either binary format or json format"; const char *nvmset_id = "NVM Set Identify value"; - struct nvme_id_nvmset nvmset; + struct nvme_id_nvmset_list nvmset; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - __u16 nvmset_id; - char *output_format; + __u16 nvmset_id; + char *output_format; }; struct config cfg = { - .nvmset_id = 0, - .output_format = "normal", + .nvmset_id = 0, + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -2708,18 +3216,18 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * if (flags < 0) goto close_fd; - err = nvme_identify_nvmset(fd, cfg.nvmset_id, &nvmset); + err = nvme_identify_nvmset_list(fd, cfg.nvmset_id, &nvmset); if (!err) nvme_show_id_nvmset(&nvmset, cfg.nvmset_id, flags); else if (err > 0) nvme_show_status(err); else - perror("identify nvm set list"); + fprintf(stderr, "identify nvm set list: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2732,16 +3240,18 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl struct nvme_id_uuid_list uuid_list; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - int raw_binary; - int human_readable; - char *output_format; + char *output_format; + bool raw_binary; + bool human_readable; }; struct config cfg = { - .output_format = "normal", + .output_format = "normal", + .raw_binary = false, + .human_readable = false, }; OPT_ARGS(opts) = { @@ -2769,11 +3279,11 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl else if (err > 0) nvme_show_status(err); else - perror("identify UUID list"); + fprintf(stderr, "identify UUID list: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false);; + return err;; } static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2782,26 +3292,19 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl "given device, returns properties of the specified controller "\ "in either human-readable or binary format."; const char *controller_id = "identifier of desired controller"; - const char *human_readable = "show info in human readable format"; struct nvme_id_iocs iocs; - enum nvme_print_flags flags; int err, fd; struct config { - __u16 cntid; - char *output_format; - int human_readable; + __u16 cntid; }; struct config cfg = { - .cntid = 0xffff, - .output_format = "normal", + .cntid = 0xffff, }; OPT_ARGS(opts) = { - OPT_SHRT("controller-id", 'c', &cfg.cntid, controller_id), - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), + OPT_SHRT("controller-id", 'c', &cfg.cntid, controller_id), OPT_END() }; @@ -2811,25 +3314,18 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl goto ret; } - err = flags = validate_output_format(cfg.output_format); - if (flags < 0) - goto close_fd; - if (cfg.human_readable) - flags |= VERBOSE; - err = nvme_identify_iocs(fd, cfg.cntid, &iocs); if (!err) { printf("NVMe Identify I/O Command Set:\n"); - nvme_show_id_iocs(&iocs, flags); + nvme_show_id_iocs(&iocs); } else if (err > 0) nvme_show_status(err); else - perror("NVMe Identify I/O Command Set"); + fprintf(stderr, "NVMe Identify I/O Command Set: %s\n", nvme_strerror(errno)); -close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int id_domain(int argc, char **argv, struct command *cmd, struct plugin *plugin) { @@ -2842,13 +3338,13 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * int err, fd; struct config { - __u16 dom_id; - char *output_format; + __u16 dom_id; + char *output_format; }; struct config cfg = { - .dom_id = 0xffff, - .output_format = "normal", + .dom_id = 0xffff, + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -2875,18 +3371,19 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * } else if (err > 0) nvme_show_status(err); else - perror("NVMe Identify Domain List"); + fprintf(stderr, "NVMe Identify Domain List: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = 0, nsid, fd; - const char *desc = "Get namespce ID of a the block device."; + const char *desc = "Get namespace ID of a the block device."; + int err = 0, fd; + unsigned int nsid; OPT_ARGS(opts) = { OPT_END() @@ -2896,9 +3393,9 @@ static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin * if (fd < 0) goto ret; - nsid = nvme_get_nsid(fd); - if (nsid <= 0) { - perror(devicename); + err = nvme_get_nsid(fd, &nsid); + if (err < 0) { + fprintf(stderr, "get namespace ID: %s\n", nvme_strerror(errno)); err = errno; goto close_fd; } @@ -2908,7 +3405,7 @@ static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin * close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -2928,21 +3425,21 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi "8h: Secondary Assign\n"\ "9h: Secondary Online"; const char *nr = "Number of Controller Resources(NR)"; - int fd, err = -1; - __u32 result, cdw10; + int fd, err; + __u32 result; struct config { - __u16 cntlid; - __u8 rt; - __u8 act; - __u16 nr; + __u16 cntlid; + __u8 rt; + __u8 act; + __u16 nr; }; struct config cfg = { - .cntlid = 0, - .rt = 0, - .act = 0, - .nr = 0, + .cntlid = 0, + .rt = 0, + .act = 0, + .nr = 0, }; OPT_ARGS(opts) = { @@ -2957,43 +3454,56 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi if (fd < 0) goto ret; - cdw10 = cfg.act | (cfg.rt << 8) | (cfg.cntlid << 16); - - err = nvme_virtual_mgmt(fd, cdw10, cfg.nr, &result); + struct nvme_virtual_mgmt_args args = { + .args_size = sizeof(args), + .fd = fd, + .act = cfg.act, + .rt = cfg.rt, + .cntlid = cfg.cntlid, + .nr = cfg.nr, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_virtual_mgmt(&args); if (!err) { printf("success, Number of Controller Resources Modified "\ "(NRM):%#x\n", result); } else if (err > 0) { nvme_show_status(err); } else - perror("virt-mgmt"); + fprintf(stderr, "virt-mgmt: %s\n", nvme_strerror(errno)); close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct plugin *plugin) { + const char *cntlid = "Controller ID"; const char *desc = "Send an Identify Primary Controller Capabilities "\ "command to the given device and report the information in a "\ "decoded format (default), json or binary."; const char *human_readable = "show info in readable format"; - struct nvme_primary_ctrl_caps caps; + struct nvme_primary_ctrl_cap caps; - int err = -1, fd; + int err, fd; enum nvme_print_flags flags; struct config { - char *output_format; - int human_readable; + __u16 cntlid; + char *output_format; + bool human_readable; }; struct config cfg = { - .output_format = "normal", + .cntlid = 0, + .output_format = "normal", + .human_readable = false, }; OPT_ARGS(opts) = { + OPT_UINT("cntlid", 'c', &cfg.cntlid, cntlid), OPT_FMT("output-format", 'o', &cfg.output_format, output_format), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), OPT_END() @@ -3009,17 +3519,17 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct if (cfg.human_readable) flags |= VERBOSE; - err = nvme_identify_primary_ctrl_caps(fd, &caps); + err = nvme_identify_primary_ctrl(fd, cfg.cntlid, &caps); if (!err) - nvme_show_primary_ctrl_caps(&caps, flags); + nvme_show_primary_ctrl_cap(&caps, flags); else if (err > 0) nvme_show_status(err); else - perror("identify primary controller capabilities"); + fprintf(stderr, "identify primary controller capabilities: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3030,22 +3540,22 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc const char *namespace_id = "optional namespace attached to controller"; const char *num_entries = "number of entries to retrieve"; - struct nvme_secondary_controllers_list *sc_list; + struct nvme_secondary_ctrl_list *sc_list; enum nvme_print_flags flags; - int err = -1, fd; + int err, fd; struct config { - __u16 cntid; - __u32 num_entries; - __u32 namespace_id; - char *output_format; + __u16 cntid; + __u32 namespace_id; + __u32 num_entries; + char *output_format; }; struct config cfg = { - .cntid = 0, - .namespace_id = 0, - .output_format = "normal", - .num_entries = ARRAY_SIZE(sc_list->sc_entry), + .cntid = 0, + .namespace_id = 0, + .num_entries = ARRAY_SIZE(sc_list->sc_entry), + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -3066,15 +3576,13 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc if (!cfg.num_entries) { fprintf(stderr, "non-zero num-entries is required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (posix_memalign((void *)&sc_list, getpagesize(), sizeof(*sc_list))) { fprintf(stderr, "can not allocate controller list payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } @@ -3084,14 +3592,14 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc else if (err > 0) nvme_show_status(err); else - perror("id secondary controller list"); + fprintf(stderr, "id secondary controller list: %s\n", nvme_strerror(errno)); free(sc_list); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int device_self_test(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3105,16 +3613,16 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p "2h Start a extended device self-test operation\n"\ "eh Start a vendor specific device self-test operation\n"\ "fh abort the device self-test operation\n"; - int fd, err = -1; + int fd, err; struct config { - __u32 namespace_id; - __u8 stc; + __u32 namespace_id; + __u8 stc; }; struct config cfg = { - .namespace_id = NVME_NSID_ALL, - .stc = 0, + .namespace_id = NVME_NSID_ALL, + .stc = 0, }; OPT_ARGS(opts) = { @@ -3127,7 +3635,15 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p if (fd < 0) goto ret; - err = nvme_self_test_start(fd, cfg.namespace_id, cfg.stc); + struct nvme_dev_self_test_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .stc = cfg.stc, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_dev_self_test(&args); if (!err) { if (cfg.stc == 0xf) printf("Aborting device self-test operation\n"); @@ -3138,11 +3654,11 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p } else if (err > 0) { nvme_show_status(err); } else - perror("Device self-test"); + fprintf(stderr, "Device self-test: %s\n", nvme_strerror(errno)); close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int self_test_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3154,20 +3670,20 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug "by default all the 20 entries will be retrieved"; const char *verbose = "Increase output verbosity"; - struct nvme_self_test_log self_test_log; + struct nvme_self_test_log log; enum nvme_print_flags flags; - int err = -1, fd; - __u32 log_size; + int err, fd; struct config { - __u8 dst_entries; - char *output_format; - int verbose; + __u8 dst_entries; + char *output_format; + bool verbose; }; struct config cfg = { - .dst_entries = NVME_ST_REPORTS, - .output_format = "normal", + .dst_entries = NVME_LOG_ST_MAX_RESULTS, + .output_format = "normal", + .verbose = false, }; OPT_ARGS(opts) = { @@ -3187,22 +3703,146 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug if (cfg.verbose) flags |= VERBOSE; - log_size = NVME_ST_LOG_HEAD_SIZE + cfg.dst_entries * NVME_ST_LOG_ENTRY_SIZE; - err = nvme_self_test_log(fd, log_size, &self_test_log); + err = nvme_get_log_device_self_test(fd, &log); if (!err) - nvme_show_self_test_log(&self_test_log, cfg.dst_entries, log_size, + nvme_show_self_test_log(&log, cfg.dst_entries, 0, devicename, flags); else if (err > 0) nvme_show_status(err); else - perror("self test log"); + fprintf(stderr, "self test log: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } -static int get_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_feature_id(int fd, struct feat_cfg *cfg, void **buf, + __u32 *result) +{ + if (!cfg->data_len) + nvme_get_feature_length(cfg->feature_id, cfg->cdw11, + &cfg->data_len); + + /* check for Extended Host Identifier */ + if (cfg->feature_id == NVME_FEAT_FID_HOST_ID && (cfg->cdw11 & 0x1)) + cfg->data_len = 16; + + if (cfg->sel == 3) + cfg->data_len = 0; + + if (cfg->data_len) { + if (posix_memalign(buf, getpagesize(), cfg->data_len)) { + return -1; + } + memset(*buf, 0, cfg->data_len); + } + + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = cfg->feature_id, + .nsid = cfg->namespace_id, + .sel = cfg->sel, + .cdw11 = cfg->cdw11, + .uuidx = cfg->uuid_index, + .data_len = cfg->data_len, + .data = *buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = result, + }; + return nvme_get_features(&args); +} + +static void get_feature_id_print(struct feat_cfg cfg, int err, __u32 result, + void *buf) +{ + if (!err) { + if (!cfg.raw_binary || !buf) { + printf("get-feature:%#0*x (%s), %s value:%#0*x\n", + cfg.feature_id ? 4 : 2, cfg.feature_id, + nvme_feature_to_string(cfg.feature_id), + nvme_select_to_string(cfg.sel), result ? 10 : 8, + result); + if (cfg.sel == 3) + nvme_show_select_result(result); + else if (cfg.human_readable) + nvme_feature_show_fields(cfg.feature_id, result, + buf); + else if (buf) + d(buf, cfg.data_len, 16, 1); + } else if (buf) { + d_raw(buf, cfg.data_len); + } + } else if (err > 0) { + if (err != NVME_SC_INVALID_FIELD) + nvme_show_status(err); + } else { + fprintf(stderr, "get-feature: %s\n", nvme_strerror(errno)); + } +} + +static int get_feature_id_changed(int fd, struct feat_cfg cfg, bool changed) +{ + int err; + int err_def = 0; + __u32 result; + __u32 result_def; + void *buf = NULL; + void *buf_def = NULL; + + if (changed) + cfg.sel = 0; + + err = get_feature_id(fd, &cfg, &buf, &result); + + if (!err && changed) { + cfg.sel = 1; + err_def = get_feature_id(fd, &cfg, &buf_def, &result_def); + } + + if (changed) + cfg.sel = 8; + + if (err || !changed || err_def || result != result_def || + (buf && buf_def && !strcmp(buf, buf_def))) + get_feature_id_print(cfg, err, result, buf); + + free(buf); + free(buf_def); + + return err; +} + +static int get_feature_ids(int fd, struct feat_cfg cfg) +{ + int err = 0; + int i; + int feat_max = 0x100; + int feat_num = 0; + bool changed = false; + + if (cfg.sel == 8) + changed = true; + + if (cfg.feature_id) + feat_max = cfg.feature_id + 1; + + for (i = cfg.feature_id; i < feat_max; i++, feat_num++) { + cfg.feature_id = i; + err = get_feature_id_changed(fd, cfg, changed); + if (err && err != NVME_SC_INVALID_FIELD) + break; + } + + if (err == NVME_SC_INVALID_FIELD && feat_num == 1) + nvme_show_status(err); + + return err; +} + +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 "\ @@ -3214,40 +3854,30 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin "are vendor-specific and not changeable. Use set-feature to "\ "change saveable Features."; const char *raw = "show feature in binary format"; - const char *namespace_id = "identifier of desired namespace"; const char *feature_id = "feature identifier"; - const char *sel = "[0-3]: current/default/saved/supported"; + const char *namespace_id = "identifier of desired namespace"; + const char *sel = "[0-3,8]: current/default/saved/supported/changed"; 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 feature in readable format"; const char *uuid_index = "specify uuid index"; - int err = -1, fd; - __u32 result; - void *buf = NULL; - - struct config { - __u32 namespace_id; - __u8 feature_id; - __u8 sel; - __u32 cdw11; - __u8 uuid_index; - __u32 data_len; - int raw_binary; - int human_readable; - }; + int err; + int fd; - struct config cfg = { - .namespace_id = 0, - .feature_id = 0, - .sel = 0, - .cdw11 = 0, - .uuid_index = 0, - .data_len = 0, + struct feat_cfg cfg = { + .feature_id = 0, + .namespace_id = 0, + .sel = 0, + .data_len = 0, + .raw_binary = false, + .cdw11 = 0, + .uuid_index = 0, + .human_readable = false, }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_BYTE("feature-id", 'f', &cfg.feature_id, feature_id), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_BYTE("sel", 's', &cfg.sel, sel), OPT_UINT("data-len", 'l', &cfg.data_len, data_len), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), @@ -3262,85 +3892,35 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { if (errno != ENOTTY) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } - cfg.namespace_id = NVME_NSID_ALL; } } - if (cfg.sel > 7) { + if (cfg.sel > 8) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); - errno = EINVAL; - err = -1; - goto close_fd; - } - if (!cfg.feature_id) { - fprintf(stderr, "feature-id required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.uuid_index > 128) { fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index); - errno = EINVAL; err = -1; goto close_fd; } - if (!cfg.data_len) - cfg.data_len = nvme_feat_buf_len[cfg.feature_id]; - - /* check for Extended Host Identifier */ - if (cfg.feature_id == NVME_FEAT_HOST_ID && (cfg.cdw11 & 0x1)) - cfg.data_len = 16; - - 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"); - errno = ENOMEM; - err = -1; - goto close_fd; - } - memset(buf, 0, cfg.data_len); - } - - err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11, - cfg.uuid_index, cfg.data_len, buf, &result); - if (!err) { - if (!cfg.raw_binary || !buf) { - printf("get-feature:%#0*x (%s), %s value:%#0*x\n", - cfg.feature_id ? 4 : 2, cfg.feature_id, - nvme_feature_to_string(cfg.feature_id), - nvme_select_to_string(cfg.sel), result ? 10 : 8, - result); - if (cfg.sel == 3) - nvme_show_select_result(result); - else if (cfg.human_readable) - nvme_feature_show_fields(cfg.feature_id, result, buf); - else if (buf) - d(buf, cfg.data_len, 16, 1); - } else if (buf) - d_raw(buf, cfg.data_len); - } else if (err > 0) { - nvme_show_status(err); - } else - perror("get-feature"); - - free(buf); + err = get_feature_ids(fd, cfg); close_fd: close(fd); + ret: - return nvme_status_to_errno(err, false); + return err; } static int fw_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3356,22 +3936,22 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin const char *fw = "firmware file (required)"; const char *xfer = "transfer chunksize limit"; const char *offset = "starting dword offset, default 0"; - int err = -1, fd, fw_fd = -1; + int err, fd, fw_fd = -1; unsigned int fw_size; struct stat sb; void *fw_buf, *buf; bool huge; struct config { - char *fw; - __u32 xfer; - __u32 offset; + char *fw; + __u32 xfer; + __u32 offset; }; struct config cfg = { - .fw = "", - .xfer = 4096, - .offset = 0, + .fw = "", + .xfer = 4096, + .offset = 0, }; OPT_ARGS(opts) = { @@ -3390,8 +3970,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin if (fw_fd < 0) { fprintf(stderr, "Failed to open firmware file %s: %s\n", cfg.fw, strerror(errno)); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } @@ -3404,8 +3983,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin fw_size = sb.st_size; if ((fw_size & 0x3) || (fw_size == 0)) { fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fw_fd; } @@ -3418,9 +3996,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin fw_buf = nvme_alloc(fw_size, &huge); if (!fw_buf) { - perror("No memory for f/w size:\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fw_fd; } @@ -3434,9 +4010,18 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin while (fw_size > 0) { cfg.xfer = min(cfg.xfer, fw_size); - err = nvme_fw_download(fd, cfg.offset, cfg.xfer, fw_buf); + struct nvme_fw_download_args args = { + .args_size = sizeof(args), + .fd = fd, + .offset = cfg.offset, + .data_len = cfg.xfer, + .data = fw_buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_fw_download(&args); if (err < 0) { - perror("fw-download"); + fprintf(stderr, "fw-download: %s\n", nvme_strerror(errno)); break; } else if (err != 0) { nvme_show_status(err); @@ -3456,7 +4041,7 @@ close_fw_fd: close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static char *nvme_fw_status_reset_type(__u16 status) @@ -3479,19 +4064,19 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * 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 = -1, fd; + int err, fd; __u32 result; struct config { - __u8 slot; - __u8 action; - __u8 bpid; + __u8 slot; + __u8 action; + __u8 bpid; }; struct config cfg = { - .slot = 0, - .action = 0, - .bpid = 0, + .slot = 0, + .action = 0, + .bpid = 0, }; OPT_ARGS(opts) = { @@ -3507,26 +4092,32 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * if (cfg.slot > 7) { fprintf(stderr, "invalid slot:%d\n", cfg.slot); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.action > 7 || cfg.action == 4 || cfg.action == 5) { fprintf(stderr, "invalid action:%d\n", cfg.action); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.bpid > 1) { fprintf(stderr, "invalid boot partition id:%d\n", cfg.bpid); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_fw_commit(fd, cfg.slot, cfg.action, cfg.bpid, &result); + struct nvme_fw_commit_args args = { + .args_size = sizeof(args), + .fd = fd, + .slot = cfg.slot, + .action = cfg.action, + .bpid = cfg.bpid, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_fw_commit(&args); if (err < 0) - perror("fw-commit"); + fprintf(stderr, "fw-commit: %s\n", nvme_strerror(errno)); else if (err != 0) switch (err & 0x7ff) { case NVME_SC_FW_NEEDS_CONV_RESET: @@ -3563,13 +4154,13 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + 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 = -1, fd; + int err, fd; OPT_ARGS(opts) = { OPT_END() @@ -3585,18 +4176,18 @@ static int subsystem_reset(int argc, char **argv, struct command *cmd, struct pl fprintf(stderr, "Subsystem-reset: NVM Subsystem Reset not supported.\n"); else - perror("Subsystem-reset"); + fprintf(stderr, "Subsystem-reset: %s\n", nvme_strerror(errno)); } close(fd); ret: - return nvme_status_to_errno(err, false); + 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 = -1, fd; + int err, fd; OPT_ARGS(opts) = { OPT_END() @@ -3606,13 +4197,13 @@ static int reset(int argc, char **argv, struct command *cmd, struct plugin *plug if (fd < 0) goto ret; - err = nvme_reset_controller(fd); + err = nvme_ctrl_reset(fd); if (err < 0) - perror("Reset"); + fprintf(stderr, "Reset: %s\n", nvme_strerror(errno)); close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3630,11 +4221,11 @@ static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin * err = nvme_ns_rescan(fd); if (err < 0) - perror("Namespace Rescan"); + fprintf(stderr, "Namespace Rescan"); close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3646,25 +4237,24 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p const char *ause_desc = "Allow unrestricted sanitize exit."; const char *sanact_desc = "Sanitize action."; const char *ovrpat_desc = "Overwrite pattern."; - - int fd, ret = -1; + int fd, err; struct config { - int no_dealloc; - int oipbp; - __u8 owpass; - int ause; - __u8 sanact; - __u32 ovrpat; + bool no_dealloc; + bool oipbp; + __u8 owpass; + bool ause; + __u8 sanact; + __u32 ovrpat; }; struct config cfg = { - .no_dealloc = 0, - .oipbp = 0, - .owpass = 0, - .ause = 0, - .sanact = 0, - .ovrpat = 0, + .no_dealloc = false, + .oipbp = false, + .owpass = 0, + .ause = false, + .sanact = 0, + .ovrpat = 0, }; OPT_ARGS(opts) = { @@ -3677,59 +4267,149 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p OPT_END() }; - ret = fd = parse_and_open(argc, argv, desc, opts); + err = fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) goto ret; switch (cfg.sanact) { - case NVME_SANITIZE_ACT_CRYPTO_ERASE: - case NVME_SANITIZE_ACT_BLOCK_ERASE: - case NVME_SANITIZE_ACT_EXIT: - case NVME_SANITIZE_ACT_OVERWRITE: + case NVME_SANITIZE_SANACT_EXIT_FAILURE: + case NVME_SANITIZE_SANACT_START_BLOCK_ERASE: + case NVME_SANITIZE_SANACT_START_OVERWRITE: + case NVME_SANITIZE_SANACT_START_CRYPTO_ERASE: break; default: fprintf(stderr, "Invalid Sanitize Action\n"); - errno = EINVAL; - ret = -1; + err = -EINVAL; goto close_fd; } - if (cfg.sanact == NVME_SANITIZE_ACT_EXIT) { + if (cfg.sanact == NVME_SANITIZE_SANACT_EXIT_FAILURE) { if (cfg.ause || cfg.no_dealloc) { fprintf(stderr, "SANACT is Exit Failure Mode\n"); - errno = EINVAL; - ret = -1; + err = -EINVAL; goto close_fd; } } - if (cfg.sanact == NVME_SANITIZE_ACT_OVERWRITE) { - if (cfg.owpass >= 16) { - fprintf(stderr, "OWPASS out of range [0-15]\n"); - errno = EINVAL; - ret = -1; + if (cfg.sanact == NVME_SANITIZE_SANACT_START_OVERWRITE) { + if (cfg.owpass > 16) { + fprintf(stderr, "OWPASS out of range [0-16]\n"); + err = -EINVAL; goto close_fd; } } else { if (cfg.owpass || cfg.oipbp || cfg.ovrpat) { fprintf(stderr, "SANACT is not Overwrite\n"); - errno = EINVAL; - ret = -1; + err = -EINVAL; goto close_fd; } } - ret = nvme_sanitize(fd, cfg.sanact, cfg.ause, cfg.owpass, cfg.oipbp, - cfg.no_dealloc, cfg.ovrpat); - if (ret < 0) - perror("sanitize"); - else if (ret > 0) - nvme_show_status(ret); + struct nvme_sanitize_nvm_args args = { + .args_size = sizeof(args), + .fd = fd, + .sanact = cfg.sanact, + .ause = cfg.ause, + .owpass = cfg.owpass, + .oipbp = cfg.oipbp, + .nodas = cfg.no_dealloc, + .ovrpat = cfg.ovrpat, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_sanitize_nvm(&args); + if (err < 0) + fprintf(stderr, "sanitize: %s\n", nvme_strerror(errno)); + else if (err > 0) + nvme_show_status(err); close_fd: close(fd); ret: - return nvme_status_to_errno(ret, false); + return err; +} + +static int nvme_get_properties(int fd, void **pbar) +{ + int offset, err, size = getpagesize(); + __u64 value; + + *pbar = malloc(size); + if (!*pbar) { + fprintf(stderr, "malloc: %s\n", strerror(errno)); + return -1; + } + + memset(*pbar, 0xff, size); + for (offset = NVME_REG_CAP; offset <= NVME_REG_CMBSZ;) { + struct nvme_get_property_args args = { + .args_size = sizeof(args), + .fd = fd, + .offset = offset, + .value = &value, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + }; + err = nvme_get_property(&args); + if (err > 0 && (err & 0xff) == NVME_SC_INVALID_FIELD) { + err = 0; + value = -1; + } else if (err) { + free(*pbar); + break; + } + if (nvme_is_64bit_reg(offset)) { + *(uint64_t *)(*pbar + offset) = value; + offset += 8; + } else { + *(uint32_t *)(*pbar + offset) = value; + offset += 4; + } + } + + return err; +} + +static void *mmap_registers(nvme_root_t r, const char *dev) +{ + nvme_ctrl_t c = NULL; + nvme_ns_t n = NULL; + + char path[512]; + void *membase; + int fd; + + c = nvme_scan_ctrl(r, devicename); + if (c) { + snprintf(path, sizeof(path), "%s/device/resource0", + nvme_ctrl_get_sysfs_dir(c)); + nvme_free_ctrl(c); + } else { + n = nvme_scan_namespace(devicename); + if (!n) { + fprintf(stderr, "Unable to find %s\n", devicename); + return NULL; + } + snprintf(path, sizeof(path), "%s/device/device/resource0", + nvme_ns_get_sysfs_dir(n)); + nvme_free_ns(n); + } + + fd = open(path, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s did not find a pci resource, open failed %s\n", + devicename, strerror(errno)); + return NULL; + } + + membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0); + if (membase == MAP_FAILED) { + fprintf(stderr, "%s failed to map. ", devicename); + fprintf(stderr, "Did your kernel enable CONFIG_IO_STRICT_DEVMEM?\n"); + membase = NULL; + } + + close(fd); + return membase; } static int show_registers(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3740,18 +4420,19 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu "output_format == normal"; enum nvme_print_flags flags; + nvme_root_t r; bool fabrics = true; - int fd, err = -1; + int fd, err; void *bar; struct config { - int human_readable; - char *output_format; + char *output_format; + bool human_readable; }; struct config cfg = { - .human_readable = 0, - .output_format = "normal", + .output_format = "normal", + .human_readable = false, }; OPT_ARGS(opts) = { @@ -3764,6 +4445,7 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu if (fd < 0) goto ret; + r = nvme_scan(NULL); err = flags = validate_output_format(cfg.output_format); if (flags < 0) goto close_fd; @@ -3772,7 +4454,7 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu err = nvme_get_properties(fd, &bar); if (err) { - bar = mmap_registers(devicename); + bar = mmap_registers(r, devicename); fabrics = false; if (bar) err = 0; @@ -3787,8 +4469,9 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu munmap(bar, getpagesize()); close_fd: close(fd); + nvme_free_tree(r); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_property(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3799,17 +4482,17 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi const char *offset = "offset of the requested property"; const char *human_readable = "show property in readable format"; - int fd, err = -1; - uint64_t value; + int fd, err; + __u64 value; struct config { - int offset; - int human_readable; + int offset; + bool human_readable; }; struct config cfg = { - .offset = -1, - .human_readable = 0, + .offset = -1, + .human_readable = false, }; OPT_ARGS(opts) = { @@ -3824,14 +4507,20 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi if (cfg.offset == -1) { fprintf(stderr, "offset required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_get_property(fd, cfg.offset, &value); + struct nvme_get_property_args args = { + .args_size = sizeof(args), + .fd = fd, + .offset = cfg.offset, + .value = &value, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + }; + err = nvme_get_property(&args); if (err < 0) { - perror("get-property"); + fprintf(stderr, "get-property: %s\n", nvme_strerror(errno)); } else if (!err) { nvme_show_single_property(cfg.offset, value, cfg.human_readable); } else if (err > 0) { @@ -3841,7 +4530,7 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int set_property(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3850,16 +4539,16 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi "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 = -1; + int fd, err; struct config { - int offset; - int value; + int offset; + int value; }; struct config cfg = { - .offset = -1, - .value = -1, + .offset = -1, + .value = -1, }; OPT_ARGS(opts) = { @@ -3874,20 +4563,26 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi if (cfg.offset == -1) { fprintf(stderr, "offset required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.value == -1) { fprintf(stderr, "value required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_set_property(fd, cfg.offset, cfg.value); + struct nvme_set_property_args args = { + .args_size = sizeof(args), + .fd = fd, + .offset = cfg.offset, + .value = cfg.value, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_set_property(&args); if (err < 0) { - perror("set-property"); + fprintf(stderr, "set-property: %s\n", nvme_strerror(errno)); } else if (!err) { printf("set-property: %02x (%s), value: %#08x\n", cfg.offset, nvme_register_to_string(cfg.offset), cfg.value); @@ -3898,7 +4593,7 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int format(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3908,8 +4603,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu "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 = "[0-63]: LBA format lower (LBAFL) and upper (LBAFU), "\ - "mention directly LBAF format that needs be applied (required)"; + 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"; @@ -3920,32 +4614,34 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; struct nvme_id_ns ns; struct nvme_id_ctrl ctrl; - int err = -1, fd, i; + int err, fd, i; int block_size; __u8 prev_lbaf = 0; struct config { - __u32 namespace_id; - __u32 timeout; - __u8 lbaf; - __u8 ses; - __u8 pi; - __u8 pil; - __u8 ms; - __u64 bs; - int reset; - int force; + __u32 namespace_id; + __u32 timeout; + __u8 lbaf; + __u8 ses; + __u8 pi; + __u8 pil; + __u8 ms; + bool reset; + bool force; + __u64 bs; }; struct config cfg = { - .namespace_id = 0, - .timeout = 600000, - .lbaf = 0xff, - .ses = 0, - .pi = 0, - .reset = 0, - .force = 0, - .bs = 0, + .namespace_id = 0, + .timeout = 600000, + .lbaf = 0xff, + .ses = 0, + .pi = 0, + .pil = 0, + .ms = 0, + .reset = false, + .force = false, + .bs = 0, }; OPT_ARGS(opts) = { @@ -3957,20 +4653,35 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu OPT_BYTE("pil", 'p', &cfg.pil, pil), OPT_BYTE("ms", 'm', &cfg.ms, ms), OPT_FLAG("reset", 'r', &cfg.reset, reset), - OPT_FLAG("force", 'f', &cfg.force, force), + OPT_FLAG("force", 0, &cfg.force, force), OPT_SUFFIX("block-size", 'b', &cfg.bs, bs), OPT_END() }; - err = fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = argconfig_parse(argc, argv, desc, opts); + if (err) + goto ret; + + err = fd = open_exclusive(argc, argv, cfg.force); + if (fd < 0) { + if (errno == EBUSY) { + fprintf(stderr, "Failed to open %s.\n", + basename(argv[optind])); + fprintf(stderr, + "Namespace is currently busy.\n"); + if (!cfg.force) + fprintf(stderr, + "Use the force [--force] option to ignore that.\n"); + } else { + argconfig_print_help(desc, opts); + } goto ret; + } if (cfg.lbaf != 0xff && cfg.bs !=0) { fprintf(stderr, "Invalid specification of both LBAF and Block Size, please specify only one\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.bs) { @@ -3978,15 +4689,14 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu fprintf(stderr, "Invalid value for block size (%"PRIu64"), must be a power of two\n", (uint64_t) cfg.bs); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } } err = nvme_identify_ctrl(fd, &ctrl); if (err) { - perror("identify-ctrl"); + fprintf(stderr, "identify-ctrl: %s\n", nvme_strerror(errno)); goto close_fd; } @@ -3998,9 +4708,9 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu */ cfg.namespace_id = NVME_NSID_ALL; } else if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } @@ -4010,23 +4720,22 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu "Invalid namespace ID, " "specify a namespace to format or use '-n 0xffffffff' " "to format all namespaces on this controller.\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.namespace_id != NVME_NSID_ALL) { - err = nvme_identify_ns(fd, cfg.namespace_id, 0, &ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &ns); if (err) { if (err < 0) - perror("identify-namespace"); + fprintf(stderr, "identify-namespace: %s\n", nvme_strerror(errno)); else { fprintf(stderr, "identify failed\n"); nvme_show_status(err); } goto close_fd; } - prev_lbaf = ns.flbas & 0xf; + nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &prev_lbaf); if (cfg.bs) { for (i = 0; i < 16; ++i) { @@ -4042,8 +4751,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu (uint64_t)cfg.bs); fprintf(stderr, "Please correct block size, or specify LBAF directly\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } } else if (cfg.lbaf == 0xff) @@ -4055,32 +4763,27 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu /* ses & pi checks set to 7 for forward-compatibility */ if (cfg.ses > 7) { fprintf(stderr, "invalid secure erase settings:%d\n", cfg.ses); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - if (cfg.lbaf > 63) { + if (cfg.lbaf > 15) { fprintf(stderr, "invalid lbaf:%d\n", cfg.lbaf); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.pi > 7) { fprintf(stderr, "invalid pi:%d\n", cfg.pi); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.pil > 1) { fprintf(stderr, "invalid pil:%d\n", cfg.pil); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.ms > 1) { fprintf(stderr, "invalid ms:%d\n", cfg.ms); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } @@ -4091,15 +4794,26 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu nvme_show_relatives(devicename); fprintf(stderr, "WARNING: Format may irrevocably delete this device's data.\n" "You have 10 seconds to press Ctrl-C to cancel this operation.\n\n" - "Use the force [--force|-f] option to suppress this warning.\n"); + "Use the force [--force] option to suppress this warning.\n"); sleep(10); fprintf(stderr, "Sending format operation ... \n"); } - err = nvme_format(fd, cfg.namespace_id, cfg.lbaf, cfg.ses, cfg.pi, - cfg.pil, cfg.ms, cfg.timeout); + struct nvme_format_nvm_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .lbaf = cfg.lbaf, + .mset = cfg.ms, + .pi = cfg.pi, + .pil = cfg.pil, + .ses = cfg.ses, + .timeout = cfg.timeout, + .result = NULL, + }; + err = nvme_format_nvm(&args); if (err < 0) - perror("format"); + fprintf(stderr, "format: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else { @@ -4136,13 +4850,13 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu } } if (cfg.reset && is_chardev()) - nvme_reset_controller(fd); + nvme_ctrl_reset(fd); } close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } #define STRTOUL_AUTO_BASE (0) @@ -4167,30 +4881,30 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin const char *cdw12 = "feature cdw12, if used"; const char *save = "specifies that the controller shall save the attribute"; const char *uuid_index = "specify uuid index"; - int err = -1; + int err; __u32 result; void *buf = NULL; int fd, ffd = STDIN_FILENO; struct config { - char *file; - __u32 namespace_id; - __u8 feature_id; - __u64 value; - __u32 cdw12; - __u8 uuid_index; - __u32 data_len; - int save; + __u32 namespace_id; + __u8 feature_id; + __u64 value; + __u32 cdw12; + __u8 uuid_index; + __u32 data_len; + char *file; + bool save; }; struct config cfg = { - .file = "", - .namespace_id = 0, - .feature_id = 0, - .value = 0, - .uuid_index = 0, - .data_len = 0, - .save = 0, + .namespace_id = 0, + .feature_id = 0, + .value = 0, + .uuid_index = 0, + .data_len = 0, + .file = "", + .save = false, }; OPT_ARGS(opts) = { @@ -4210,10 +4924,10 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { if (errno != ENOTTY) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } @@ -4223,26 +4937,24 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.uuid_index > 128) { fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index); - errno = EINVAL; err = -1; goto close_fd; } if (!cfg.data_len) - cfg.data_len = nvme_feat_buf_len[cfg.feature_id]; + nvme_get_feature_length(cfg.feature_id, cfg.value, + &cfg.data_len); if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } memset(buf, 0, cfg.data_len); @@ -4255,16 +4967,15 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin * should use the buffer method if the value exceeds this * length. */ - if (NVME_FEAT_TIMESTAMP == cfg.feature_id && cfg.value) { + if (NVME_FEAT_FID_TIMESTAMP == cfg.feature_id && cfg.value) { memcpy(buf, &cfg.value, NVME_FEAT_TIMESTAMP_DATA_SIZE); } else { if (strlen(cfg.file)) { ffd = open(cfg.file, O_RDONLY); if (ffd <= 0) { - errno = EINVAL; fprintf(stderr, "Failed to open file %s: %s\n", - cfg.file, strerror(errno)); - err = -1; + cfg.file, strerror(errno)); + err = -EINVAL; goto free; } } @@ -4279,21 +4990,35 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin } } - err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, - cfg.cdw12, cfg.save, cfg.uuid_index, cfg.data_len, buf, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = cfg.feature_id, + .nsid = cfg.namespace_id, + .cdw11 = cfg.value, + .cdw12 = cfg.cdw12, + .save = cfg.save, + .uuidx = cfg.uuid_index, + .cdw15 = 0, + .data_len = cfg.data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err < 0) { - perror("set-feature"); + fprintf(stderr, "set-feature: %s\n", nvme_strerror(errno)); } else if (!err) { printf("set-feature:%#0*x (%s), value:%#0*"PRIx64", cdw12:%#0*x, save:%#x\n", cfg.feature_id ? 4 : 2, cfg.feature_id, nvme_feature_to_string(cfg.feature_id), cfg.value ? 10 : 8, (uint64_t)cfg.value, cfg.cdw12 ? 10 : 8, cfg.cdw12, cfg.save); - if (cfg.feature_id == NVME_LBA_STATUS_INFO) { + if (cfg.feature_id == NVME_FEAT_FID_LBA_STS_INTERVAL) { nvme_show_lba_status_info(result); } if (buf) { - if (cfg.feature_id == NVME_FEAT_LBA_RANGE) + if (cfg.feature_id == NVME_FEAT_FID_LBA_RANGE) nvme_show_lba_range((struct nvme_lba_range_type *)buf, result); else @@ -4309,7 +5034,7 @@ free: close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -4326,24 +5051,26 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p const char *tl = "transfer length (cf. SPC-4)"; const char *namespace_id = "desired namespace"; const char *nssf = "NVMe Security Specific Field"; - int err = -1, fd, sec_fd = -1; + int err, fd, sec_fd = STDIN_FILENO; void *sec_buf; unsigned int sec_size; struct config { - __u32 namespace_id; - char *file; - __u8 nssf; - __u8 secp; - __u16 spsp; - __u32 tl; + __u32 namespace_id; + char *file; + __u8 nssf; + __u8 secp; + __u16 spsp; + __u32 tl; }; struct config cfg = { - .file = "", - .secp = 0, - .spsp = 0, - .tl = 0, + .namespace_id = 0, + .file = "", + .nssf = 0, + .secp = 0, + .spsp = 0, + .tl = 0, }; OPT_ARGS(opts) = { @@ -4365,16 +5092,6 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p err = -EINVAL; goto close_fd; } - - sec_fd = open(cfg.file, O_RDONLY); - if (sec_fd < 0) { - fprintf(stderr, "Failed to open %s: %s\n", - cfg.file, strerror(errno)); - errno = EINVAL; - err = -1; - goto close_fd; - } - if ((cfg.tl & 3) != 0) fprintf(stderr, "WARNING: --tl not dword aligned; unaligned bytes may be truncated\n"); @@ -4399,15 +5116,13 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p sec_size = cfg.tl > sb.st_size ? cfg.tl : sb.st_size; } - sec_size = sb.st_size; - if (posix_memalign(&sec_buf, getpagesize(), sec_size)) { - fprintf(stderr, "No memory for security size:%d\n", sec_size); - errno = ENOMEM; - err = -1; + if (posix_memalign(&sec_buf, getpagesize(), cfg.tl)) { + fprintf(stderr, "No memory for security size:%d\n", cfg.tl); + err = -ENOMEM; goto close_sec_fd; } - memset(sec_buf, 0, cfg.tl); // ensure zero fill if cfg.tl > sec_size + memset(sec_buf, 0, cfg.tl); // ensure zero fill if buf_size > sec_size err = read(sec_fd, sec_buf, sec_size); if (err < 0) { @@ -4417,10 +5132,23 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p goto free; } - err = nvme_sec_send(fd, cfg.namespace_id, cfg.nssf, cfg.spsp, cfg.secp, - cfg.tl, sec_buf); + struct nvme_security_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .nssf = cfg.nssf, + .spsp0 = cfg.spsp & 0xff, + .spsp1 = cfg.spsp >> 8, + .secp = cfg.secp, + .tl = cfg.tl, + .data_len = cfg.tl, + .data = sec_buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_security_send(&args); if (err < 0) - perror("security-send"); + fprintf(stderr, "security-send: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -4433,7 +5161,7 @@ close_sec_fd: close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -4449,34 +5177,37 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p const char *endir = "directive enable"; const char *ttype = "target directive type to be enabled/disabled"; const char *human_readable = "show directive in readable format"; - int err = -1, fd; + const char *input = "write/send file (default stdin)"; + 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; + __u32 namespace_id; + __u32 data_len; + __u8 dtype; + __u8 ttype; + __u16 dspec; + __u8 doper; + __u16 endir; + bool human_readable; + bool raw_binary; + char *file; }; struct config cfg = { - .file = "", - .namespace_id = 1, - .data_len = 0, - .dspec = 0, - .dtype = 0, - .ttype = 0, - .doper = 0, - .endir = 1, + .namespace_id = 1, + .data_len = 0, + .dtype = 0, + .ttype = 0, + .dspec = 0, + .doper = 0, + .endir = 1, + .human_readable = false, + .raw_binary = false, + .file = "", }; OPT_ARGS(opts) = { @@ -4489,6 +5220,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p OPT_SHRT("endir", 'e', &cfg.endir, endir), OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_FILE("input-file", 'i', &cfg.file, input), OPT_END() }; @@ -4497,48 +5229,43 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p goto ret; switch (cfg.dtype) { - case NVME_DIR_IDENTIFY: + case NVME_DIRECTIVE_DTYPE_IDENTIFY: switch (cfg.doper) { - case NVME_DIR_SND_ID_OP_ENABLE: + case NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR: if (!cfg.ttype) { fprintf(stderr, "target-dir required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } dw12 = cfg.ttype << 8 | cfg.endir; break; default: fprintf(stderr, "invalid directive operations for Identify Directives\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } break; - case NVME_DIR_STREAMS: + case NVME_DIRECTIVE_DTYPE_STREAMS: switch (cfg.doper) { - case NVME_DIR_SND_ST_OP_REL_ID: - case NVME_DIR_SND_ST_OP_REL_RSC: + case NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER: + case NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE: break; default: fprintf(stderr, "invalid directive operations for Streams Directives\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } break; default: fprintf(stderr, "invalid directive type\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } memset(buf, 0, cfg.data_len); @@ -4550,8 +5277,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p if (ffd <= 0) { fprintf(stderr, "Failed to open file %s: %s\n", cfg.file, strerror(errno)); - errno = EINVAL; - err = -1; + err = -EINVAL; goto free; } } @@ -4564,10 +5290,22 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p } } - err = nvme_dir_send(fd, cfg.namespace_id, cfg.dspec, cfg.dtype, cfg.doper, - cfg.data_len, dw12, buf, &result); + struct nvme_directive_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .dspec = cfg.dspec, + .doper = cfg.doper, + .dtype = cfg.dtype, + .cdw12 = dw12, + .data_len = cfg.data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_directive_send(&args); if (err < 0) { - perror("dir-send"); + fprintf(stderr, "dir-send: %s\n", nvme_strerror(errno)); goto close_ffd; } if (!err) { @@ -4589,12 +5327,12 @@ free: close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = -1, fd; + 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"; @@ -4602,15 +5340,15 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin const char *block_count = "number of blocks (zeroes based) on device to access"; struct config { - __u64 start_block; - __u32 namespace_id; - __u16 block_count; + __u32 namespace_id; + __u64 start_block; + __u16 block_count; }; struct config cfg = { - .start_block = 0, - .namespace_id = 0, - .block_count = 0, + .namespace_id = 0, + .start_block = 0, + .block_count = 0, }; OPT_ARGS(opts) = { @@ -4625,17 +5363,25 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } - err = nvme_write_uncorrectable(fd, cfg.namespace_id, cfg.start_block, - cfg.block_count); + struct nvme_io_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.start_block, + .nlb = cfg.block_count, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_write_uncorrectable(&args); if (err < 0) - perror("write uncorrectable"); + fprintf(stderr, "write uncorrectable: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -4644,12 +5390,12 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = -1, fd; + int err, fd; __u16 control = 0; const char *desc = "The Write Zeroes command is used to set a "\ "range of logical blocks to zero."; @@ -4657,7 +5403,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi 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 *force_unit_access = "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)"; @@ -4669,29 +5415,33 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi "part of end-to-end data protection processing"; struct config { - __u64 start_block; - __u32 namespace_id; - __u32 ref_tag; - __u16 app_tag; - __u16 app_tag_mask; - __u16 block_count; - __u8 prinfo; - __u64 storage_tag; - int deac; - int limited_retry; - int force_unit_access; - int storage_tag_check; + __u32 namespace_id; + __u64 start_block; + __u16 block_count; + bool deac; + bool limited_retry; + bool force_unit_access; + __u8 prinfo; + __u32 ref_tag; + __u16 app_tag_mask; + __u16 app_tag; + __u64 storage_tag; + bool storage_tag_check; }; struct config cfg = { - .start_block = 0, - .block_count = 0, - .prinfo = 0, - .ref_tag = 0, - .app_tag_mask = 0, - .app_tag = 0, - .storage_tag = 0, - .storage_tag_check = 0, + .namespace_id = 0, + .start_block = 0, + .block_count = 0, + .deac = false, + .limited_retry = false, + .force_unit_access = false, + .prinfo = 0, + .ref_tag = 0, + .app_tag_mask = 0, + .app_tag = 0, + .storage_tag = 0, + .storage_tag_check = false, }; OPT_ARGS(opts) = { @@ -4700,7 +5450,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), OPT_FLAG("deac", 'd', &cfg.deac, deac), OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry), - OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force), + OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access), OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo), OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag), OPT_SHRT("app-tag-mask", 'm', &cfg.app_tag_mask, app_tag_mask), @@ -4715,33 +5465,44 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi goto ret; if (cfg.prinfo > 0xf) { - fprintf(stderr, "invalid prinfo: %u\n", cfg.prinfo); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } control |= (cfg.prinfo << 10); if (cfg.limited_retry) - control |= NVME_RW_LR; + control |= NVME_IO_LR; if (cfg.force_unit_access) - control |= NVME_RW_FUA; + control |= NVME_IO_FUA; if (cfg.deac) - control |= NVME_RW_DEAC; + control |= NVME_IO_DEAC; if (cfg.storage_tag_check) - control |= NVME_RW_STORAGE_TAG_CHECK; + control |= NVME_SC_STORAGE_TAG_CHECK; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_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, cfg.storage_tag); + struct nvme_io_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.start_block, + .nlb = cfg.block_count, + .control = control, + .reftag = cfg.ref_tag, + .apptag = cfg.app_tag, + .appmask = cfg.app_tag_mask, + .storage_tag = cfg.storage_tag, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_write_zeros(&args); if (err < 0) - perror("write-zeroes"); + fprintf(stderr, "write-zeroes: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -4750,7 +5511,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -4768,43 +5529,43 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin 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 = -1, fd; + 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; + __u32 ctx_attrs[256] = {0,}; + __u32 nlbs[256] = {0,}; + __u64 slbas[256] = {0,}; + struct nvme_dsm_range dsm[256]; struct config { - char *ctx_attrs; - char *blocks; - char *slbas; - int ad; - int idw; - int idr; - __u32 cdw11; - __u32 namespace_id; + __u32 namespace_id; + char *ctx_attrs; + char *blocks; + char *slbas; + bool ad; + bool idw; + bool idr; + __u32 cdw11; }; struct config cfg = { - .ctx_attrs = "", - .blocks = "", - .slbas = "", - .namespace_id = 0, - .ad = 0, - .idw = 0, - .idr = 0, - .cdw11 = 0, + .namespace_id = 0, + .ctx_attrs = "", + .blocks = "", + .slbas = "", + .ad = false, + .idw = false, + .idr = false, + .cdw11 = 0, }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_LIST("ctx-attrs", 'a', &cfg.ctx_attrs, context_attrs), - OPT_LIST("blocks", 'b', &cfg.blocks, blocks), - OPT_LIST("slbs", 's', &cfg.slbas, starting_blocks), - OPT_FLAG("ad", 'd', &cfg.ad, ad), - OPT_FLAG("idw", 'w', &cfg.idw, idw), - OPT_FLAG("idr", 'r', &cfg.idr, idr), + OPT_LIST("blocks", 'b', &cfg.blocks, blocks), + OPT_LIST("slbs", 's', &cfg.slbas, starting_blocks), + OPT_FLAG("ad", 'd', &cfg.ad, ad), + OPT_FLAG("idw", 'w', &cfg.idw, idw), + OPT_FLAG("idr", 'r', &cfg.idr, idr), OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11), OPT_END() }; @@ -4813,49 +5574,49 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin if (fd < 0) goto ret; - nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, ctx_attrs, ARRAY_SIZE(ctx_attrs)); - nb = argconfig_parse_comma_sep_array(cfg.blocks, nlbs, ARRAY_SIZE(nlbs)); - ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, ARRAY_SIZE(slbas)); + nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, (int *)ctx_attrs, ARRAY_SIZE(ctx_attrs)); + nb = argconfig_parse_comma_sep_array(cfg.blocks, (int *)nlbs, ARRAY_SIZE(nlbs)); + ns = argconfig_parse_comma_sep_array_long(cfg.slbas, (unsigned long long *)slbas, ARRAY_SIZE(slbas)); nr = max(nc, max(nb, ns)); if (!nr || nr > 256) { fprintf(stderr, "No range definition provided\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } if (!cfg.cdw11) cfg.cdw11 = (cfg.ad << 2) | (cfg.idw << 1) | (cfg.idr << 0); - dsm = nvme_setup_dsm_range(ctx_attrs, nlbs, slbas, nr); - if (!dsm) { - fprintf(stderr, "failed to allocate data set payload\n"); - errno = ENOMEM; - err = -1; - goto close_fd; - } - - err = nvme_dsm(fd, cfg.namespace_id, cfg.cdw11, dsm, nr); + nvme_init_dsm_range(dsm, ctx_attrs, nlbs, slbas, nr); + struct nvme_dsm_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .attrs = cfg.cdw11, + .nr_ranges = nr, + .dsm = dsm, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_dsm(&args); if (err < 0) - perror("data-set management"); + fprintf(stderr, "data-set management: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else printf("NVMe DSM: success\n"); - free(dsm); - close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -4883,62 +5644,73 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi const char *d_dspec = "directive specific (write part)"; const char *d_format = "source range entry format"; - int err = -1, fd; + int err, fd; uint16_t nr, nb, ns, nrts, natms, nats; - int nlbs[128] = { 0 }; + __u16 nlbs[128] = { 0 }; unsigned long long slbas[128] = {0,}; - int eilbrts[128] = { 0 }; - int elbatms[128] = { 0 }; - int elbats[128] = { 0 }; - struct nvme_copy_range *copy; + __u32 eilbrts[128] = { 0 }; + __u32 elbatms[128] = { 0 }; + __u32 elbats[128] = { 0 }; + struct nvme_copy_range copy[128]; struct config { - __u32 namespace_id; - __u64 sdlba; - char *nlbs; - char *slbas; - __u32 ilbrt; - char *eilbrts; - __u16 lbatm; - char *elbatms; - __u16 lbat; - char *elbats; - __u8 prinfow; - __u8 prinfor; - int lr; - int fua; - __u8 dtype; - __u16 dspec; - __u8 format; + __u32 namespace_id; + __u64 sdlba; + char *slbas; + char *nlbs; + bool lr; + bool fua; + __u8 prinfow; + __u8 prinfor; + __u32 ilbrt; + char *eilbrts; + __u16 lbat; + char *elbatms; + __u16 lbatm; + char *elbats; + __u8 dtype; + __u16 dspec; + __u8 format; }; struct config cfg = { - .namespace_id = 0, - .nlbs = "", - .slbas = "", - .eilbrts = "", - .elbatms = "", - .elbats = "", + .namespace_id = 0, + .sdlba = 0, + .slbas = "", + .nlbs = "", + .lr = false, + .fua = false, + .prinfow = 0, + .prinfor = 0, + .ilbrt = 0, + .eilbrts = "", + .lbat = 0, + .elbats = "", + .lbatm = 0, + .elbatms = "", + .dtype = 0, + .dspec = 0, + .format = 0, }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, d_nsid), - OPT_SUFFIX("sdlba", 'd', &cfg.sdlba, d_sdlba), - OPT_LIST("slbs", 's', &cfg.slbas, d_slbas), - OPT_LIST("blocks", 'b', &cfg.nlbs, d_nlbs), - OPT_FLAG("limited-retry", 'l', &cfg.lr, d_lr), - OPT_FLAG("force-unit-access", 'f', &cfg.fua, d_fua), - OPT_BYTE("prinfow", 'p', &cfg.prinfow, d_prinfow), - OPT_BYTE("prinfor", 'P', &cfg.prinfor, d_prinfor), - OPT_UINT("ref-tag", 'r', &cfg.ilbrt, d_ilbrt), - OPT_LIST("expected-ref-tags", 'R', &cfg.eilbrts, d_eilbrts), - OPT_SHRT("app-tag", 'a', &cfg.lbat, d_lbat), - OPT_LIST("expected-app-tags", 'A', &cfg.elbats, d_elbats), - OPT_SHRT("app-tag-mask", 'm', &cfg.lbatm, d_lbatm), - OPT_LIST("expected-app-tag-masks", 'M', &cfg.elbatms, d_elbatms), - OPT_BYTE("dir-type", 'T', &cfg.dtype, d_dtype), - OPT_SHRT("dir-spec", 'S', &cfg.dspec, d_dspec), - OPT_BYTE("format", 'F', &cfg.format, d_format), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, d_nsid), + OPT_SUFFIX("sdlba", 'd', &cfg.sdlba, d_sdlba), + OPT_LIST("slbs", 's', &cfg.slbas, d_slbas), + OPT_LIST("blocks", 'b', &cfg.nlbs, d_nlbs), + OPT_FLAG("limited-retry", 'l', &cfg.lr, d_lr), + OPT_FLAG("force-unit-access", 'f', &cfg.fua, d_fua), + OPT_BYTE("prinfow", 'p', &cfg.prinfow, d_prinfow), + OPT_BYTE("prinfor", 'P', &cfg.prinfor, d_prinfor), + OPT_UINT("ref-tag", 'r', &cfg.ilbrt, d_ilbrt), + OPT_LIST("expected-ref-tags", 'R', &cfg.eilbrts, d_eilbrts), + OPT_SHRT("app-tag", 'a', &cfg.lbat, d_lbat), + OPT_LIST("expected-app-tags", 'A', &cfg.elbats, d_elbats), + OPT_SHRT("app-tag-mask", 'm', &cfg.lbatm, d_lbatm), + OPT_LIST("expected-app-tag-masks", 'M', &cfg.elbatms, d_elbatms), + OPT_BYTE("dir-type", 'T', &cfg.dtype, d_dtype), + OPT_SHRT("dir-spec", 'S', &cfg.dspec, d_dspec), + OPT_BYTE("format", 'F', &cfg.format, d_format), OPT_END() }; @@ -4948,52 +5720,61 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi goto ret; } - nb = argconfig_parse_comma_sep_array(cfg.nlbs, nlbs, ARRAY_SIZE(nlbs)); + nb = argconfig_parse_comma_sep_array(cfg.nlbs, (int *)nlbs, ARRAY_SIZE(nlbs)); ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, ARRAY_SIZE(slbas)); - nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, eilbrts, ARRAY_SIZE(eilbrts)); - natms = argconfig_parse_comma_sep_array(cfg.elbatms, elbatms, ARRAY_SIZE(elbatms)); - nats = argconfig_parse_comma_sep_array(cfg.elbats, elbats, ARRAY_SIZE(elbats)); + nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, (int *)eilbrts, ARRAY_SIZE(eilbrts)); + natms = argconfig_parse_comma_sep_array(cfg.elbatms, (int *)elbatms, ARRAY_SIZE(elbatms)); + nats = argconfig_parse_comma_sep_array(cfg.elbats, (int *)elbats, ARRAY_SIZE(elbats)); nr = max(nb, max(ns, max(nrts, max(natms, nats)))); if (!nr || nr > 128) { fprintf(stderr, "invalid range\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } - copy = nvme_setup_copy_range(nlbs, slbas, eilbrts, elbatms, elbats, nr); - if (!copy) { - fprintf(stderr, "failed to allocate payload\n"); - errno = ENOMEM; - err = -1; - goto close_fd; - } - - err = nvme_copy(fd, cfg.namespace_id, copy, cfg.sdlba, nr, cfg.prinfor, - cfg.prinfow, cfg.dtype, cfg.dspec, cfg.format, cfg.lr, - cfg.fua, cfg.ilbrt, cfg.lbatm, cfg.lbat); + nvme_init_copy_range(copy, nlbs, (__u64 *)slbas, eilbrts, elbatms, elbats, nr); + + struct nvme_copy_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .copy = copy, + .sdlba = cfg.sdlba, + .nr = nr, + .prinfor = cfg.prinfor, + .prinfow = cfg.prinfow, + .dtype = cfg.dtype, + .dspec = cfg.dspec, + .format = cfg.format, + .lr = cfg.lr, + .fua = cfg.fua, + .ilbrt = cfg.ilbrt, + .lbatm = cfg.lbatm, + .lbat = cfg.lbat, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_copy(&args); if (err < 0) - perror("NVMe Copy"); + fprintf(stderr, "NVMe Copy: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else printf("NVMe Copy: success\n"); - free(copy); - close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int flush(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5004,14 +5785,14 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug "flushed by the controller, from any namespace, depending on controller and "\ "associated namespace status."; const char *namespace_id = "identifier of desired namespace"; - int err = -1, fd; + int err, fd; struct config { - __u32 namespace_id; + __u32 namespace_id; }; struct config cfg = { - .namespace_id = 0, + .namespace_id = 0, }; OPT_ARGS(opts) = { @@ -5024,16 +5805,16 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } err = nvme_flush(fd, cfg.namespace_id); if (err < 0) - perror("flush"); + fprintf(stderr, "flush: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -5041,7 +5822,7 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5058,23 +5839,24 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi const char *rtype = "reservation type"; const char *racqa = "reservation acquire action"; const char *iekey = "ignore existing res. key"; - int err = -1, fd; + int err, fd; struct config { - __u32 namespace_id; - __u64 crkey; - __u64 prkey; - __u8 rtype; - __u8 racqa; - int iekey; + __u32 namespace_id; + __u64 crkey; + __u64 prkey; + __u8 rtype; + __u8 racqa; + bool iekey; }; struct config cfg = { - .namespace_id = 0, - .crkey = 0, - .prkey = 0, - .rtype = 0, - .racqa = 0, + .namespace_id = 0, + .crkey = 0, + .prkey = 0, + .rtype = 0, + .racqa = 0, + .iekey = false, }; OPT_ARGS(opts) = { @@ -5092,23 +5874,33 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } if (cfg.racqa > 7) { fprintf(stderr, "invalid racqa:%d\n", cfg.racqa); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_resv_acquire(fd, cfg.namespace_id, cfg.rtype, cfg.racqa, - !!cfg.iekey, cfg.crkey, cfg.prkey); + struct nvme_resv_acquire_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .rtype = cfg.rtype, + .racqa = cfg.racqa, + .iekey = !!cfg.iekey, + .crkey = cfg.crkey, + .nrkey = cfg.prkey, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_resv_acquire(&args); if (err < 0) - perror("reservation acquire"); + fprintf(stderr, "reservation acquire: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -5117,7 +5909,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int resv_register(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5131,23 +5923,23 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug const char *nrkey = "new reservation key"; const char *rrega = "reservation registration action"; const char *cptpl = "change persistence through power loss setting"; - int err = -1, fd; + int err, fd; struct config { - __u32 namespace_id; - __u64 crkey; - __u64 nrkey; - __u8 rrega; - __u8 cptpl; - int iekey; + __u32 namespace_id; + __u64 crkey; + __u64 nrkey; + __u8 rrega; + __u8 cptpl; + bool iekey; }; struct config cfg = { - .namespace_id = 0, - .crkey = 0, - .nrkey = 0, - .rrega = 0, - .cptpl = 0, + .namespace_id = 0, + .crkey = 0, + .nrkey = 0, + .rrega = 0, + .cptpl = false, }; OPT_ARGS(opts) = { @@ -5165,30 +5957,39 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } if (cfg.cptpl > 3) { fprintf(stderr, "invalid cptpl:%d\n", cfg.cptpl); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.rrega > 7) { fprintf(stderr, "invalid rrega:%d\n", cfg.rrega); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_resv_register(fd, cfg.namespace_id, cfg.rrega, cfg.cptpl, - !!cfg.iekey, cfg.crkey, cfg.nrkey); + struct nvme_resv_register_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .rrega = cfg.rrega, + .cptpl = cfg.cptpl, + .iekey = !!cfg.iekey, + .crkey = cfg.crkey, + .nrkey = cfg.nrkey, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_resv_register(&args); if (err < 0) - perror("reservation register"); + fprintf(stderr, "reservation register: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -5197,7 +5998,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int resv_release(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5215,22 +6016,22 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi const char *iekey = "ignore existing res. key"; const char *rtype = "reservation type"; const char *rrela = "reservation release action"; - int err = -1, fd; + int err, fd; struct config { - __u32 namespace_id; - __u64 crkey; - __u8 rtype; - __u8 rrela; - __u8 iekey; + __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, + .namespace_id = 0, + .crkey = 0, + .rtype = 0, + .rrela = 0, + .iekey = 0, }; OPT_ARGS(opts) = { @@ -5247,23 +6048,32 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi goto ret; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } if (cfg.rrela > 7) { fprintf(stderr, "invalid rrela:%d\n", cfg.rrela); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - err = nvme_resv_release(fd, cfg.namespace_id, cfg.rtype, cfg.rrela, - !!cfg.iekey, cfg.crkey); + struct nvme_resv_release_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .rtype = cfg.rtype, + .rrela = cfg.rrela, + .iekey = !!cfg.iekey, + .crkey = cfg.crkey, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_resv_release(&args); if (err < 0) - perror("reservation release"); + fprintf(stderr, "reservation release: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -5272,7 +6082,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int resv_report(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5284,32 +6094,33 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin "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 *eds = "request extended data structure"; const char *raw = "dump output in binary format"; - struct nvme_reservation_status *status; + struct nvme_resv_status *status; enum nvme_print_flags flags; - int err = -1, fd, size; + int err, fd, size; struct config { - __u32 namespace_id; - __u32 numd; - __u32 cdw11; - int raw_binary; - char *output_format; + __u32 namespace_id; + __u32 numd; + __u8 eds; + char *output_format; + bool raw_binary; }; struct config cfg = { - .namespace_id = 0, - .numd = 0, - .cdw11 = 0, - .output_format = "normal", + .namespace_id = 0, + .numd = 0, + .eds = false, + .output_format = "normal", + .raw_binary = false, }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_UINT("numd", 'd', &cfg.numd, numd), - OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11), + OPT_FLAG("eds", 'e', &cfg.eds, eds), OPT_FMT("output-format", 'o', &cfg.output_format, output_format), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() @@ -5326,9 +6137,9 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin flags = BINARY; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } @@ -5342,24 +6153,33 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin if (posix_memalign((void **)&status, getpagesize(), size)) { fprintf(stderr, "No memory for resv report:%d\n", size); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } memset(status, 0, size); - err = nvme_resv_report(fd, cfg.namespace_id, cfg.numd, cfg.cdw11, status); + struct nvme_resv_report_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .eds = cfg.eds, + .len = size, + .report = status, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_resv_report(&args); if (!err) - nvme_show_resv_report(status, size, cfg.cdw11, flags); + nvme_show_resv_report(status, size, cfg.eds, flags); else if (err > 0) nvme_show_status(err); else - perror("reservation report"); + fprintf(stderr, "reservation report: %s\n", nvme_strerror(errno)); free(status); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } unsigned long long elapsed_utime(struct timeval start_time, @@ -5375,19 +6195,19 @@ static int submit_io(int opcode, char *command, const char *desc, { struct timeval start_time, end_time; void *buffer, *mbuffer = NULL; - int err = -1; + 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, nsid = 0; + __u32 dsmgmt = 0; int logical_block_size = 0; long long buffer_size = 0, mbuffer_size = 0; bool huge; struct nvme_id_ns ns; __u8 lba_index, ms = 0; - const char *namespace_id = "desired namespace"; + const char *namespace_id = "Identifier of desired namespace"; 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"; @@ -5400,55 +6220,66 @@ static int submit_io(int opcode, char *command, const char *desc, 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 *force_unit_access = "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)"; + const char *dsm = "dataset management attributes (lower 8 bits)"; const char *storage_tag_check = "This bit specifies the Storage Tag field shall be " \ "checked as part of end-to-end data protection processing"; const char *storage_tag = "storage tag, CDW2 and CDW3 (00:47) bits "\ "(for end to end PI)"; + const char *force = "The \"I know what I'm doing\" flag, do not enforce exclusive access for write"; struct config { - __u32 namespace_id; - __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; - __u64 storage_tag; - int limited_retry; - int force_unit_access; - int storage_tag_check; - int show; - int dry_run; - int latency; + __u32 namespace_id; + __u64 start_block; + __u16 block_count; + __u64 data_size; + __u64 metadata_size; + __u32 ref_tag; + char *data; + char *metadata; + __u8 prinfo; + __u16 app_tag_mask; + __u16 app_tag; + __u64 storage_tag; + bool limited_retry; + bool force_unit_access; + bool storage_tag_check; + __u8 dtype; + __u16 dspec; + __u8 dsmgmt; + bool show; + bool dry_run; + bool latency; + bool force; }; struct config cfg = { .namespace_id = 0, - .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, - .storage_tag_check = 0, + .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, .storage_tag = 0, + .limited_retry = false, + .force_unit_access = false, + .storage_tag_check = false, + .dtype = 0, + .dspec = 0, + .dsmgmt = 0, + .show = false, + .dry_run = false, + .latency = false, + .force = false, }; OPT_ARGS(opts) = { @@ -5465,50 +6296,70 @@ static int submit_io(int opcode, char *command, const char *desc, OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag), OPT_SUFFIX("storage-tag", 'g', &cfg.storage_tag, storage_tag), OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry), - OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force), + OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access), OPT_FLAG("storage-tag-check", 'C', &cfg.storage_tag_check, storage_tag_check), OPT_BYTE("dir-type", 'T', &cfg.dtype, dtype), OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec), - OPT_SHRT("dsm", 'D', &cfg.dsmgmt, dsm), + OPT_BYTE("dsm", 'D', &cfg.dsmgmt, dsm), OPT_FLAG("show-command", 'v', &cfg.show, show), OPT_FLAG("dry-run", 'w', &cfg.dry_run, dry), OPT_FLAG("latency", 't', &cfg.latency, latency), + OPT_FLAG("force", 0, &cfg.force, force), OPT_END() }; - err = fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - goto ret; + if (opcode != nvme_cmd_write) { + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + } else { + err = argconfig_parse(argc, argv, desc, opts); + if (err) + goto ret; + err = fd = open_exclusive(argc, argv, cfg.force); + if (err < 0) { + if (errno == EBUSY) { + fprintf(stderr, "Failed to open %s.\n", + basename(argv[optind])); + fprintf(stderr, + "Namespace is currently busy.\n"); + if (!cfg.force) + fprintf(stderr, + "Use the force [--force] option to ignore that.\n"); + } else { + argconfig_print_help(desc, opts); + } + goto ret; + } + } if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } dfd = mfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO; if (cfg.prinfo > 0xf) { - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } dsmgmt = cfg.dsmgmt; control |= (cfg.prinfo << 10); if (cfg.limited_retry) - control |= NVME_RW_LR; + control |= NVME_IO_LR; if (cfg.force_unit_access) - control |= NVME_RW_FUA; + control |= NVME_IO_FUA; if (cfg.storage_tag_check) - control |= NVME_RW_STORAGE_TAG_CHECK; + control |= NVME_SC_STORAGE_TAG_CHECK; if (cfg.dtype) { if (cfg.dtype > 0xf) { fprintf(stderr, "Invalid directive type, %x\n", cfg.dtype); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } control |= cfg.dtype << 4; @@ -5519,36 +6370,29 @@ static int submit_io(int opcode, char *command, const char *desc, dfd = open(cfg.data, flags, mode); if (dfd < 0) { perror(cfg.data); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } - mfd = dfd; } + if (strlen(cfg.metadata)) { mfd = open(cfg.metadata, flags, mode); if (mfd < 0) { perror(cfg.metadata); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_dfd; } } if (!cfg.data_size) { fprintf(stderr, "data size not provided\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_mfd; } - if (is_ns_chardev()) { - logical_block_size = - nvme_logical_block_size_from_ns_char(devicename); - } else { - if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) + if (nvme_get_logical_block_size(fd, cfg.namespace_id, + &logical_block_size) < 0) goto close_mfd; - } buffer_size = (cfg.block_count + 1) * logical_block_size; if (cfg.data_size < buffer_size) { @@ -5560,27 +6404,20 @@ static int submit_io(int opcode, char *command, const char *desc, buffer = nvme_alloc(buffer_size, &huge); if (!buffer) { - perror("can not allocate io payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_mfd; } if (cfg.metadata_size) { - err = nsid = nvme_get_nsid(fd); - if (err < 0) { - perror("get-namespace-id"); - goto close_mfd; - } - err = nvme_identify_ns(fd, nsid, false, &ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &ns); if (err) { nvme_show_status(err); goto free_buffer; } else if (err < 0) { - perror("identify namespace"); + fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); goto free_buffer; } - lba_index = ns.flbas & NVME_NS_FLBAS_LBA_MASK; + nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index); ms = ns.lbaf[lba_index].ms; mbuffer_size = (cfg.block_count + 1) * ms; if (ms && cfg.metadata_size < mbuffer_size) { @@ -5591,9 +6428,7 @@ static int submit_io(int opcode, char *command, const char *desc, } mbuffer = malloc(mbuffer_size); if (!mbuffer) { - perror("can not allocate buf for io metadata payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto free_buffer; } memset(mbuffer, 0, mbuffer_size); @@ -5619,48 +6454,68 @@ static int submit_io(int opcode, char *command, const char *desc, } } - if (cfg.show) { - printf("opcode : %02x\n", opcode); - printf("nsid : %02x\n", cfg.namespace_id); - printf("control : %04x\n", control); - printf("nblocks : %04x\n", cfg.block_count); - printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mbuffer); - printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer); - printf("slba : %"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.show || cfg.dry_run) { + printf("opcode : %02x\n", opcode); + printf("nsid : %02x\n", cfg.namespace_id); + printf("flags : %02x\n", 0); + printf("control : %04x\n", control); + printf("nblocks : %04x\n", cfg.block_count); + printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mbuffer); + printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer); + printf("slba : %"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); printf("storagetagcheck : %04x\n", cfg.storage_tag_check); printf("storagetag : %"PRIx64"\n", (uint64_t)cfg.storage_tag); } if (cfg.dry_run) goto free_mbuffer; + struct nvme_io_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.start_block, + .nlb = cfg.block_count, + .control = control, + .dsm = cfg.dsmgmt, + .dspec = cfg.dspec, + .reftag = cfg.ref_tag, + .apptag = cfg.app_tag, + .appmask = cfg.app_tag_mask, + .storage_tag = cfg.storage_tag, + .data_len = buffer_size, + .data = buffer, + .metadata_len = cfg.metadata_size, + .metadata = mbuffer, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; gettimeofday(&start_time, NULL); - err = nvme_io(fd, opcode, cfg.namespace_id, cfg.start_block, cfg.block_count, - control, dsmgmt, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask, - cfg.storage_tag, buffer, buffer_size, mbuffer, mbuffer_size); + if (opcode & 1) + err = nvme_write(&args); + else + err = nvme_read(&args); 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"); + fprintf(stderr, "submit-io: %s\n", nvme_strerror(errno)); else if (err) nvme_show_status(err); else { if (!(opcode & 1) && write(dfd, (void *)buffer, cfg.data_size) < 0) { fprintf(stderr, "write: %s: failed to write buffer to output file\n", strerror(errno)); - errno = EINVAL; - err = -1; + err = -EINVAL; } else if (!(opcode & 1) && cfg.metadata_size && write(mfd, (void *)mbuffer, mbuffer_size) < 0) { fprintf(stderr, "write: %s: failed to write meta-data buffer to output file\n", strerror(errno)); - errno = EINVAL; - err = -1; + err = -EINVAL; } else fprintf(stderr, "%s: Success\n", command); } @@ -5677,7 +6532,7 @@ close_dfd: close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int compare(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5705,14 +6560,14 @@ static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin * static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = -1, fd; + int err, fd; __u16 control = 0; const char *desc = "Verify specified logical blocks on the given device."; 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 cached data before performing the verify operation"; + const char *force_unit_access = "force device to commit cached data before performing the verify operation"; 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)"; @@ -5723,31 +6578,31 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin "be checked as part of Verify operation"; struct config { - __u64 start_block; - __u32 namespace_id; - __u32 ref_tag; - __u16 app_tag; - __u16 app_tag_mask; - __u16 block_count; - __u8 prinfo; - __u64 storage_tag; - int storage_tag_check; - int limited_retry; - int force_unit_access; + __u32 namespace_id; + __u64 start_block; + __u16 block_count; + bool limited_retry; + bool force_unit_access; + __u8 prinfo; + __u32 ref_tag; + __u16 app_tag; + __u16 app_tag_mask; + __u64 storage_tag; + bool storage_tag_check; }; struct config cfg = { - .namespace_id = 0, - .start_block = 0, - .block_count = 0, - .prinfo = 0, - .ref_tag = 0, - .app_tag = 0, - .app_tag_mask = 0, - .limited_retry = 0, - .force_unit_access = 0, - .storage_tag = 0, - .storage_tag_check = 0, + .namespace_id = 0, + .start_block = 0, + .block_count = 0, + .limited_retry = false, + .force_unit_access = false, + .prinfo = 0, + .ref_tag = 0, + .app_tag = 0, + .app_tag_mask = 0, + .storage_tag = 0, + .storage_tag_check = false, }; OPT_ARGS(opts) = { @@ -5755,7 +6610,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block), OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry), - OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force), + OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access), OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo), OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag), OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag), @@ -5770,32 +6625,43 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin goto ret; if (cfg.prinfo > 0xf) { - fprintf(stderr, "invalid 'prinfo' param:%u\n", cfg.prinfo); - errno = EINVAL; - err = -1; + err = EINVAL; goto close_fd; } control |= (cfg.prinfo << 10); if (cfg.limited_retry) - control |= NVME_RW_LR; + control |= NVME_IO_LR; if (cfg.force_unit_access) - control |= NVME_RW_FUA; + control |= NVME_IO_FUA; if (cfg.storage_tag_check) - control |= NVME_RW_STORAGE_TAG_CHECK; + control |= NVME_SC_STORAGE_TAG_CHECK; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); goto close_fd; } } - err = nvme_verify(fd, cfg.namespace_id, cfg.start_block, cfg.block_count, - control, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask, cfg.storage_tag); + struct nvme_io_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.start_block, + .nlb = cfg.block_count, + .control = control, + .reftag = cfg.ref_tag, + .apptag = cfg.app_tag, + .appmask = cfg.app_tag_mask, + .storage_tag = cfg.storage_tag, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_verify(&args); if (err < 0) - perror("verify"); + fprintf(stderr, "verify: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -5804,7 +6670,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin close_fd: close(fd); ret: - return nvme_status_to_errno(err, false);; + return err; } static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5822,24 +6688,27 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p const char *raw = "dump output in binary format"; const char *namespace_id = "desired namespace"; const char *nssf = "NVMe Security Specific Field"; - int err = -1, fd; + int err, fd; void *sec_buf = NULL; struct config { - __u32 namespace_id; - __u32 size; - __u8 secp; - __u8 nssf; - __u16 spsp; - __u32 al; - int raw_binary; + __u32 namespace_id; + __u32 size; + __u8 nssf; + __u8 secp; + __u16 spsp; + __u32 al; + bool raw_binary; }; struct config cfg = { - .size = 0, - .secp = 0, - .spsp = 0, - .al = 0, + .namespace_id = 0, + .size = 0, + .nssf = 0, + .secp = 0, + .spsp = 0, + .al = 0, + .raw_binary = false, }; OPT_ARGS(opts) = { @@ -5861,16 +6730,28 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p if (posix_memalign(&sec_buf, getpagesize(), cfg.size)) { fprintf(stderr, "No memory for security size:%d\n", cfg.size); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } } - err = nvme_sec_recv(fd, cfg.namespace_id, cfg.nssf, cfg.spsp, - cfg.secp, cfg.al, cfg.size, sec_buf); + struct nvme_security_receive_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .nssf = cfg.nssf, + .spsp0 = cfg.spsp & 0xff, + .spsp1 = cfg.spsp >> 8, + .secp = cfg.secp, + .al = cfg.al, + .data_len = cfg.size, + .data = sec_buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_security_receive(&args); if (err < 0) - perror("security receive"); + fprintf(stderr, "security receive: %s\n", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else { @@ -5886,7 +6767,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int get_lba_status(int argc, char **argv, struct command *cmd, @@ -5907,27 +6788,27 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, enum nvme_print_flags flags; unsigned long buf_len; - int err = -1, fd; + int err, fd; void *buf; struct config { - __u32 namespace_id; - __u64 slba; - __u32 mndw; - __u8 atype; - __u16 rl; - __u32 timeout; - char *output_format; + __u32 namespace_id; + __u64 slba; + __u32 mndw; + __u8 atype; + __u16 rl; + __u32 timeout; + char *output_format; }; struct config cfg = { - .namespace_id = 0, - .slba = 0, - .mndw = 0, - .atype = 0, - .rl = 0, - .timeout = 0, - .output_format = "normal", + .namespace_id = 0, + .slba = 0, + .mndw = 0, + .atype = 0, + .rl = 0, + .timeout = 0, + .output_format = "normal", }; OPT_ARGS(opts) = { @@ -5951,33 +6832,41 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, if (!cfg.atype) { fprintf(stderr, "action type (--action) has to be given\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } buf_len = (cfg.mndw + 1) * 4; buf = calloc(1, buf_len); if (!buf) { - perror("could not alloc memory for get lba status"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } - err = nvme_get_lba_status(fd, cfg.namespace_id, cfg.slba, cfg.mndw, - cfg.atype, cfg.rl, buf, cfg.timeout); + struct nvme_get_lba_status_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.slba, + .mndw = cfg.mndw, + .rl = cfg.rl, + .atype = cfg.atype, + .lbas = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_get_lba_status(&args); if (!err) nvme_show_lba_status(buf, buf_len, flags); else if (err > 0) nvme_show_status(err); else - perror("get lba status"); + fprintf(stderr, "get lba status: %s\n", nvme_strerror(errno)); free(buf); close_fd: close(fd); err: - return nvme_status_to_errno(err, false); + return err; } static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5997,23 +6886,23 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug __u32 result; struct config { - __u8 operation; - __u16 element_id; - __u32 dw11; - __u32 dw12; + __u8 operation; + __u16 element_id; + __u32 dw11; + __u32 dw12; }; struct config cfg = { - .operation = 0xff, - .element_id = 0xffff, - .dw11 = 0, - .dw12 = 0, + .operation = 0xff, + .element_id = 0xffff, + .dw11 = 0, + .dw12 = 0, }; OPT_ARGS(opts) = { OPT_BYTE("operation", 'o', &cfg.operation, operation), OPT_SHRT("element-id", 'i', &cfg.element_id, element_id), - OPT_UINT("cap-lower", 'l', &cfg.dw11, cap_lower), + OPT_UINT("cap-lower", 'l', &cfg.dw11, cap_lower), OPT_UINT("cap-upper", 'u', &cfg.dw12, cap_upper), OPT_END() }; @@ -6024,13 +6913,21 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug if (cfg.operation > 0xf) { fprintf(stderr, "invalid operation field: %u\n", cfg.operation); - errno = EINVAL; err = -1; goto close_fd; } - err = nvme_cap_mgmt(fd, cfg.operation, cfg.element_id, cfg.dw11, - cfg.dw12, &result); + struct nvme_capacity_mgmt_args args = { + .args_size = sizeof(args), + .fd = fd, + .op = cfg.operation, + .element_id = cfg.element_id, + .cdw11 = cfg.dw11, + .cdw12 = cfg.dw12, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_capacity_mgmt(&args); if (!err) { printf("Capacity Management Command is Success\n"); if (cfg.operation == 1) { @@ -6041,12 +6938,12 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug } else if (err > 0) nvme_show_status(err); else if (err < 0) - perror("capacity management"); + fprintf(stderr, "capacity management: %s\n", nvme_strerror(errno)); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -6063,29 +6960,31 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin const char *human_readable = "show directive in readable format"; enum nvme_print_flags flags = NORMAL; - int err = -1, fd; + 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; + __u32 namespace_id; + __u32 data_len; + bool raw_binary; + __u8 dtype; + __u16 dspec; + __u8 doper; + __u16 nsr; /* dw12 for NVME_DIR_ST_RCVOP_STATUS */ + bool human_readable; }; struct config cfg = { - .namespace_id = 1, - .data_len = 0, - .dspec = 0, - .dtype = 0, - .doper = 0, - .nsr = 0, + .namespace_id = 1, + .data_len = 0, + .raw_binary = false, + .dtype = 0, + .dspec = 0, + .doper = 0, + .nsr = 0, + .human_readable = false, }; OPT_ARGS(opts) = { @@ -6110,57 +7009,65 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin flags = BINARY; switch (cfg.dtype) { - case NVME_DIR_IDENTIFY: + case NVME_DIRECTIVE_DTYPE_IDENTIFY: switch (cfg.doper) { - case NVME_DIR_RCV_ID_OP_PARAM: + case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM: if (!cfg.data_len) cfg.data_len = 4096; break; default: fprintf(stderr, "invalid directive operations for Identify Directives\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } break; - case NVME_DIR_STREAMS: + case NVME_DIRECTIVE_DTYPE_STREAMS: switch (cfg.doper) { - case NVME_DIR_RCV_ST_OP_PARAM: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM: if (!cfg.data_len) cfg.data_len = 32; break; - case NVME_DIR_RCV_ST_OP_STATUS: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS: if (!cfg.data_len) cfg.data_len = 128 * 1024; break; - case NVME_DIR_RCV_ST_OP_RESOURCE: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE: dw12 = cfg.nsr; break; default: fprintf(stderr, "invalid directive operations for Streams Directives\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } break; default: fprintf(stderr, "invalid directive type\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } 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); + struct nvme_directive_recv_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .dspec = cfg.dspec, + .doper = cfg.doper, + .dtype = cfg.dtype, + .cdw12 = dw12, + .data_len = cfg.data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_directive_recv(&args); if (!err) nvme_directive_show(cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, result, buf, cfg.data_len, @@ -6168,13 +7075,13 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin else if (err > 0) nvme_show_status(err); else if (err < 0) - perror("dir-receive"); + fprintf(stderr, "dir-receive: %s\n", nvme_strerror(errno)); free(buf); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } /* rpmb_cmd_option is defined in nvme-rpmb.c */ @@ -6208,23 +7115,23 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi int fd, err = -1; struct config { - __u8 ofi; - __u8 ifc; - __u8 prhbt; - __u8 scp; - __u8 uuid; + __u8 ofi; + __u8 ifc; + __u8 prhbt; + __u8 scp; + __u8 uuid; }; struct config cfg = { - .ofi = 0, - .ifc = 0, - .prhbt = 0, - .scp = 0, - .uuid = 0, + .ofi = 0, + .ifc = 0, + .prhbt = 0, + .scp = 0, + .uuid = 0, }; OPT_ARGS(opts) = { - OPT_BYTE("ofi", 'o', &cfg.ofi, ofi_desc), + OPT_BYTE("ofi", 'o', &cfg.ofi, ofi_desc), OPT_BYTE("ifc", 'f', &cfg.ifc, ifc_desc), OPT_BYTE("prhbt", 'p', &cfg.prhbt, prhbt_desc), OPT_BYTE("scp", 's', &cfg.scp, scp_desc), @@ -6239,34 +7146,39 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi /* check for input arguement limit */ if (cfg.ifc > 3) { fprintf(stderr, "invalid interface settings:%d\n", cfg.ifc); - errno = EINVAL; err = -1; goto close_fd; } if (cfg.prhbt > 1) { fprintf(stderr, "invalid prohibit settings:%d\n", cfg.prhbt); - errno = EINVAL; err = -1; goto close_fd; } if (cfg.scp > 15) { fprintf(stderr, "invalid scope settings:%d\n", cfg.scp); - errno = EINVAL; err = -1; goto close_fd; } if (cfg.uuid > 127) { fprintf(stderr, "invalid UUID index settings:%d\n", cfg.uuid); - errno = EINVAL; err = -1; goto close_fd; } - err = nvme_lockdown(fd, cfg.scp,cfg.prhbt,cfg.ifc,cfg.ofi, - cfg.uuid); - + struct nvme_lockdown_args args = { + .args_size = sizeof(args), + .fd = fd, + .scp = cfg.scp, + .prhbt = cfg.prhbt, + .ifc = cfg.ifc, + .ofi = cfg.ofi, + .uuidx = cfg.uuid, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_lockdown(&args); if (err < 0) - perror("lockdown"); + fprintf(stderr, "lockdown: %s\n", nvme_strerror(errno)); else if (err > 0) nvme_show_status(err); else @@ -6275,18 +7187,19 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } -static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, - const char *desc, struct command *cmd) +static int passthru(int argc, char **argv, bool admin, + const char *desc, struct command *cmd) { const char *opcode = "opcode (required)"; - const char *flags = "command flags"; + const char *cflags = "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 *metadata = "metadata input or output file"; const char *timeout = "timeout value, in milliseconds"; const char *cdw2 = "command dword 2 value"; const char *cdw3 = "command dword 3 value"; @@ -6296,7 +7209,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, 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 *input = "data input or output file"; const char *raw_binary = "dump output in binary format"; const char *show = "print command before sending"; const char *dry = "show command instead of sending"; @@ -6305,62 +7218,72 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, const char *prefill = "prefill buffers with known byte-value, default 0"; const char *latency = "output latency statistics"; - void *data = NULL, *metadata = NULL; - int err = -1, wfd = STDIN_FILENO, fd; + int flags; + int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; + void *data = NULL, *mdata = NULL; + int err = 0, dfd, mfd, fd; __u32 result; - bool huge; + bool huge = false; const char *cmd_name = NULL; struct timeval start_time, end_time; 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; - int latency; + __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; + char *metadata; + bool raw_binary; + bool show_command; + bool dry_run; + bool read; + bool write; + __u8 prefill; + bool latency; }; 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, + .opcode = 0, + .flags = 0, + .prefill = 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 = "", + .metadata = "", + .raw_binary = false, + .show_command = false, + .dry_run = false, + .read = false, + .write = false, + .latency = false, }; OPT_ARGS(opts) = { OPT_BYTE("opcode", 'o', &cfg.opcode, opcode), - OPT_BYTE("flags", 'f', &cfg.flags, flags), + OPT_BYTE("flags", 'f', &cfg.flags, cflags), OPT_BYTE("prefill", 'p', &cfg.prefill, prefill), OPT_SHRT("rsvd", 'R', &cfg.rsvd, rsvd), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), @@ -6376,6 +7299,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, OPT_UINT("cdw14", '8', &cfg.cdw14, cdw14), OPT_UINT("cdw15", '9', &cfg.cdw15, cdw15), OPT_FILE("input-file", 'i', &cfg.input_file, input), + OPT_FILE("metadata", 'M', &cfg.metadata, metadata), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary), OPT_FLAG("show-command", 's', &cfg.show_command, show), OPT_FLAG("dry-run", 'd', &cfg.dry_run, dry), @@ -6389,33 +7313,47 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, if (fd < 0) goto ret; + flags = cfg.opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT; + dfd = mfd = cfg.opcode & 1 ? STDIN_FILENO : STDOUT_FILENO; if (strlen(cfg.input_file)) { - wfd = open(cfg.input_file, O_RDONLY, - S_IRUSR | S_IRGRP | S_IROTH); - if (wfd < 0) { + dfd = open(cfg.input_file, flags, mode); + if (dfd < 0) { perror(cfg.input_file); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } } + if (cfg.metadata && strlen(cfg.metadata)) { + mfd = open(cfg.metadata, flags, mode); + if (mfd < 0) { + perror(cfg.metadata); + err = -EINVAL; + goto close_dfd; + } + } + if (cfg.metadata_len) { - metadata = malloc(cfg.metadata_len); - if (!metadata) { - perror("can not allocate metadata payload\n"); - errno = ENOMEM; - err = -1; - goto close_wfd; + mdata = malloc(cfg.metadata_len); + if (!mdata) { + err = -ENOMEM; + goto close_mfd; } - memset(metadata, cfg.prefill, cfg.metadata_len); + + if (cfg.write) { + if (read(mfd, mdata, cfg.metadata_len) < 0) { + err = -errno; + perror("failed to read metadata write buffer"); + goto free_metadata; + } + } else + memset(mdata, cfg.prefill, cfg.metadata_len); } + if (cfg.data_len) { data = nvme_alloc(cfg.data_len, &huge); if (!data) { - perror("can not allocate data payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto free_metadata; } @@ -6430,11 +7368,10 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, memset(data, cfg.prefill, cfg.data_len); if (!cfg.read && !cfg.write) { fprintf(stderr, "data direction not given\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto free_data; } else if (cfg.write) { - if (read(wfd, data, cfg.data_len) < 0) { + if (read(dfd, data, cfg.data_len) < 0) { err = -errno; fprintf(stderr, "failed to read write buffer " "%s\n", strerror(errno)); @@ -6443,7 +7380,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, } } - if (cfg.show_command) { + if (cfg.show_command || cfg.dry_run) { printf("opcode : %02x\n", cfg.opcode); printf("flags : %02x\n", cfg.flags); printf("rsvd1 : %04x\n", cfg.rsvd); @@ -6453,7 +7390,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, 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("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mdata); printf("cdw10 : %08x\n", cfg.cdw10); printf("cdw11 : %08x\n", cfg.cdw11); printf("cdw12 : %08x\n", cfg.cdw12); @@ -6467,86 +7404,90 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, gettimeofday(&start_time, NULL); - err = nvme_passthru(fd, ioctl_cmd, cfg.opcode, cfg.flags, cfg.rsvd, + if (admin) + err = nvme_admin_passthru(fd, 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); + cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, + cfg.cdw15, cfg.data_len, data, cfg.metadata_len, + mdata, cfg.timeout, &result); + else + err = nvme_io_passthru(fd, 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, + mdata, cfg.timeout, &result); gettimeofday(&end_time, NULL); - cmd_name = nvme_cmd_to_string(cmd_type, cfg.opcode); + cmd_name = nvme_cmd_to_string(admin, cfg.opcode); if (cfg.latency) printf("%s Command %s latency: %llu us\n", - cmd_type ? "Admin": "IO", + admin ? "Admin": "IO", strcmp(cmd_name, "Unknown") ? cmd_name: "Vendor Specific", elapsed_utime(start_time, end_time)); if (err < 0) - perror("passthru"); + fprintf(stderr, "passthru: %s\n", nvme_strerror(errno)); else if (err) nvme_show_status(err); else { fprintf(stderr, "%s Command %s is Success and result: 0x%08x\n", - cmd_type ? "Admin": "IO", + admin ? "Admin": "IO", strcmp(cmd_name, "Unknown") ? cmd_name: "Vendor Specific", result); - if (!cfg.raw_binary) { + if (cfg.read && cfg.input_file) { + if (write(dfd, (void *)data, cfg.data_len) < 0) + perror("failed to write data buffer"); + if (cfg.metadata_len && cfg.metadata) + if (write(mfd, (void *)mdata, cfg.metadata_len) < 0) + perror("failed to write metadata buffer"); + } else if (!cfg.raw_binary) { 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_metadata: + free(mdata); free_data: nvme_free(data, huge); -free_metadata: - free(metadata); -close_wfd: +close_dfd: if (strlen(cfg.input_file)) - close(wfd); + close(dfd); +close_mfd: + if (strlen(cfg.metadata)) + close(mfd); close_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + 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, 0, desc, cmd); + return passthru(argc, argv, false, 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, 1, desc, cmd); + return passthru(argc, argv, true, desc, cmd); } static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { - int ret; - char uuid_str[37]; /* e.g. 1b4e28ba-2fa1-11d2-883f-0016d3cca427 + \0 */ -#ifdef LIBUUID - uuid_t uuid; -#endif + char *hostnqn; - ret = uuid_from_dmi(uuid_str); - if (ret < 0) - ret = uuid_from_systemd(uuid_str); -#ifdef LIBUUID - if (ret < 0) { - uuid_generate_random(uuid); - uuid_unparse_lower(uuid, uuid_str); - ret = 0; - } -#endif - if (ret < 0) { + hostnqn = nvmf_hostnqn_generate(); + if (!hostnqn) { fprintf(stderr, "\"%s\" not supported. Install lib uuid and rebuild.\n", command->name); return -ENOTSUP; } - printf("nqn.2014-08.org.nvmexpress:uuid:%s\n", uuid_str); + printf("%s\n", hostnqn); + free(hostnqn); return 0; } @@ -6554,45 +7495,468 @@ static int show_hostnqn_cmd(int argc, char **argv, struct command *command, stru { char *hostnqn; - hostnqn = hostnqn_read(); - if (hostnqn) { - fputs(hostnqn, stdout); - free(hostnqn); - return 0; - } else { + hostnqn = nvmf_hostnqn_from_file(); + if (!hostnqn) + hostnqn = nvmf_hostnqn_generate(); + + if (!hostnqn) { fprintf(stderr, "hostnqn is not available -- use nvme gen-hostnqn\n"); - return -ENOENT; + return ENOENT; + } + + fprintf(stdout, "%s\n", hostnqn); + free(hostnqn); + + return 0; +} + + +static int gen_dhchap_key(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Generate a DH-HMAC-CHAP host key usable "\ + "for NVMe In-Band Authentication."; + const char *secret = "Optional secret (in hexadecimal characters) "\ + "to be used to initialize the host key."; + const char *key_len = "Length of the resulting key "\ + "(32, 48, or 64 bytes)."; + const char *hmac = "HMAC function to use for key transformation "\ + "(0 = none, 1 = SHA-256, 2 = SHA-384, 3 = SHA-512)."; + const char *nqn = "Host NQN to use for key transformation."; + + unsigned char *raw_secret; + unsigned char key[68]; + char encoded_key[128]; + unsigned long crc = crc32(0L, NULL, 0); + int err = 0; + + struct config { + char *secret; + unsigned int key_len; + char *nqn; + unsigned int hmac; + }; + + struct config cfg = { + .secret = NULL, + .key_len = 0, + .nqn = NULL, + .hmac = 0, + }; + + OPT_ARGS(opts) = { + OPT_STR("secret", 's', &cfg.secret, secret), + OPT_UINT("key-length", 'l', &cfg.key_len, key_len), + OPT_STR("nqn", 'n', &cfg.nqn, nqn), + OPT_UINT("hmac", 'm', &cfg.hmac, hmac), + OPT_END() + }; + + err = argconfig_parse(argc, argv, desc, opts); + if (err) + return err; + + if (cfg.hmac > 3) { + fprintf(stderr, "Invalid HMAC identifier %u\n", cfg.hmac); + return -EINVAL; + } + if (cfg.hmac > 0) { + switch (cfg.hmac) { + case 1: + if (!cfg.key_len) + cfg.key_len = 32; + else if (cfg.key_len != 32) { + fprintf(stderr, "Invalid key length %d for SHA(256)\n", + cfg.key_len); + return -EINVAL; + } + break; + case 2: + if (!cfg.key_len) + cfg.key_len = 48; + else if (cfg.key_len != 48) { + fprintf(stderr, "Invalid key length %d for SHA(384)\n", + cfg.key_len); + return -EINVAL; + } + break; + case 3: + if (!cfg.key_len) + cfg.key_len = 64; + else if (cfg.key_len != 64) { + fprintf(stderr, "Invalid key length %d for SHA(512)\n", + cfg.key_len); + return -EINVAL; + } + break; + default: + break; + } + } else if (!cfg.key_len) + cfg.key_len = 32; + + if (cfg.key_len != 32 && cfg.key_len != 48 && cfg.key_len != 64) { + fprintf(stderr, "Invalid key length %u\n", cfg.key_len); + return -EINVAL; + } + raw_secret = malloc(cfg.key_len); + if (!raw_secret) + return -ENOMEM; + if (!cfg.secret) { + if (getrandom_bytes(raw_secret, cfg.key_len) < 0) + return -errno; + } else { + int secret_len = 0, i; + unsigned int c; + + for (i = 0; i < strlen(cfg.secret); i+=2) { + if (sscanf(&cfg.secret[i], "%02x", &c) != 1) { + fprintf(stderr, "Invalid secret '%s'\n", + cfg.secret); + return -EINVAL; + } + raw_secret[secret_len++] = (unsigned char)c; + } + if (secret_len != cfg.key_len) { + fprintf(stderr, "Invalid key length (%d bytes)\n", + secret_len); + return -EINVAL; + } + } + + if (!cfg.nqn) { + cfg.nqn = nvmf_hostnqn_from_file(); + if (!cfg.nqn) { + fprintf(stderr, "Could not read host NQN\n"); + return -ENOENT; + } + } + + if (nvme_gen_dhchap_key(cfg.nqn, cfg.hmac, cfg.key_len, + raw_secret, key) < 0) + return -errno; + + crc = crc32(crc, key, cfg.key_len); + key[cfg.key_len++] = crc & 0xff; + key[cfg.key_len++] = (crc >> 8) & 0xff; + key[cfg.key_len++] = (crc >> 16) & 0xff; + key[cfg.key_len++] = (crc >> 24) & 0xff; + + memset(encoded_key, 0, sizeof(encoded_key)); + base64_encode(key, cfg.key_len, encoded_key); + + printf("DHHC-1:%02x:%s:\n", cfg.hmac, encoded_key); + return 0; +} + +static int check_dhchap_key(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Check a DH-HMAC-CHAP host key for usability "\ + "for NVMe In-Band Authentication."; + const char *key = "DH-HMAC-CHAP key (in hexadecimal characters) "\ + "to be validated."; + + unsigned char decoded_key[128]; + unsigned int decoded_len; + u_int32_t crc = crc32(0L, NULL, 0); + u_int32_t key_crc; + int err = 0, hmac; + struct config { + char *key; + }; + + struct config cfg = { + .key = NULL, + }; + + OPT_ARGS(opts) = { + OPT_STR("key", 'k', &cfg.key, key), + OPT_END() + }; + + err = argconfig_parse(argc, argv, desc, opts); + if (err) + return err; + + if (!cfg.key) { + fprintf(stderr, "Key not specified\n"); + return -EINVAL; + } + + if (sscanf(cfg.key, "DHHC-1:%02x:*s", &hmac) != 1) { + fprintf(stderr, "Invalid key header '%s'\n", cfg.key); + return -EINVAL; + } + switch (hmac) { + case 0: + break; + case 1: + if (strlen(cfg.key) != 59) { + fprintf(stderr, "Invalid key length for SHA(256)\n"); + return -EINVAL; + } + break; + case 2: + if (strlen(cfg.key) != 83) { + fprintf(stderr, "Invalid key length for SHA(384)\n"); + return -EINVAL; + } + break; + case 3: + if (strlen(cfg.key) != 103) { + fprintf(stderr, "Invalid key length for SHA(512)\n"); + return -EINVAL; + } + break; + default: + fprintf(stderr, "Invalid HMAC identifier %d\n", hmac); + return -EINVAL; + break; + } + + err = base64_decode(cfg.key + 10, strlen(cfg.key) - 11, + decoded_key); + if (err < 0) { + fprintf(stderr, "Base64 decoding failed, error %d\n", + err); + return err; + } + decoded_len = err; + if (decoded_len < 32) { + fprintf(stderr, "Base64 decoding failed (%s, size %u)\n", + cfg.key + 10, decoded_len); + return -EINVAL; + } + decoded_len -= 4; + if (decoded_len != 32 && decoded_len != 48 && decoded_len != 64) { + fprintf(stderr, "Invalid key length %d\n", decoded_len); + return -EINVAL; } + crc = crc32(crc, decoded_key, decoded_len); + key_crc = ((u_int32_t)decoded_key[decoded_len]) | + ((u_int32_t)decoded_key[decoded_len + 1] << 8) | + ((u_int32_t)decoded_key[decoded_len + 2] << 16) | + ((u_int32_t)decoded_key[decoded_len + 3] << 24); + if (key_crc != crc) { + fprintf(stderr, "CRC mismatch (key %08x, crc %08x)\n", + key_crc, crc); + return -EINVAL; + } + printf("Key is valid (HMAC %d, length %d, CRC %08x)\n", + hmac, decoded_len, crc); + return 0; +} + +static int gen_tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Generate a TLS key in NVMe PSK Interchange format."; + const char *secret = "Optional secret (in hexadecimal characters) "\ + "to be used for the TLS key."; + const char *hmac = "HMAC function to use for the retained key "\ + "(1 = SHA-256, 2 = SHA-384)."; + + unsigned char *raw_secret; + char encoded_key[128]; + int key_len = 32; + unsigned long crc = crc32(0L, NULL, 0); + int err = 0; + + struct config { + char *secret; + unsigned int hmac; + }; + + struct config cfg = { + .secret = NULL, + .hmac = 1, + }; + + OPT_ARGS(opts) = { + OPT_STR("secret", 's', &cfg.secret, secret), + OPT_UINT("hmac", 'm', &cfg.hmac, hmac), + OPT_END() + }; + + err = argconfig_parse(argc, argv, desc, opts); + if (err) + return err; + if (cfg.hmac < 1 || cfg.hmac > 3) { + fprintf(stderr, "Invalid HMAC identifier %u\n", cfg.hmac); + return -EINVAL; + } + + if (cfg.hmac == 2) + key_len = 48; + + raw_secret = malloc(key_len + 4); + if (!raw_secret) + return -ENOMEM; + if (!cfg.secret) { + if (getrandom_bytes(raw_secret, key_len) < 0) + return -errno; + } else { + int secret_len = 0, i; + unsigned int c; + + for (i = 0; i < strlen(cfg.secret); i+=2) { + if (sscanf(&cfg.secret[i], "%02x", &c) != 1) { + fprintf(stderr, "Invalid secret '%s'\n", + cfg.secret); + return -EINVAL; + } + if (i >= key_len) { + fprintf(stderr, + "Skipping excess secret bytes\n"); + break; + } + raw_secret[secret_len++] = (unsigned char)c; + } + if (secret_len != key_len) { + fprintf(stderr, "Invalid key length (%d bytes)\n", + secret_len); + return -EINVAL; + } + } + + crc = crc32(crc, raw_secret, key_len); + raw_secret[key_len++] = crc & 0xff; + raw_secret[key_len++] = (crc >> 8) & 0xff; + raw_secret[key_len++] = (crc >> 16) & 0xff; + raw_secret[key_len++] = (crc >> 24) & 0xff; + + memset(encoded_key, 0, sizeof(encoded_key)); + base64_encode(raw_secret, key_len, encoded_key); + + printf("NVMeTLSkey-1:%02x:%s:\n", cfg.hmac, encoded_key); + return 0; +} + +static int check_tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Check a TLS key for NVMe PSK Interchange format.\n"; + const char *key = "TLS key (in PSK Interchange format) "\ + "to be validated."; + + unsigned char decoded_key[128]; + unsigned int decoded_len; + u_int32_t crc = crc32(0L, NULL, 0); + u_int32_t key_crc; + int err = 0, hmac; + struct config { + char *key; + }; + + struct config cfg = { + .key = NULL, + }; + + OPT_ARGS(opts) = { + OPT_STR("key", 'k', &cfg.key, key), + OPT_END() + }; + + err = argconfig_parse(argc, argv, desc, opts); + if (err) + return err; + + if (!cfg.key) { + fprintf(stderr, "Key not specified\n"); + return -EINVAL; + } + + if (sscanf(cfg.key, "NVMeTLSkey-1:%02x:*s", &hmac) != 1) { + fprintf(stderr, "Invalid key header '%s'\n", cfg.key); + return -EINVAL; + } + switch (hmac) { + case 1: + if (strlen(cfg.key) != 65) { + fprintf(stderr, "Invalid key length %lu for SHA(256)\n", + strlen(cfg.key)); + return -EINVAL; + } + break; + case 2: + if (strlen(cfg.key) != 89) { + fprintf(stderr, "Invalid key length %lu for SHA(384)\n", + strlen(cfg.key)); + return -EINVAL; + } + break; + default: + fprintf(stderr, "Invalid HMAC identifier %d\n", hmac); + return -EINVAL; + break; + } + + err = base64_decode(cfg.key + 16, strlen(cfg.key) - 17, + decoded_key); + if (err < 0) { + fprintf(stderr, "Base64 decoding failed (%s, error %d)\n", + cfg.key + 16, err); + return err; + } + decoded_len = err; + decoded_len -= 4; + if (decoded_len != 32 && decoded_len != 48) { + fprintf(stderr, "Invalid key length %d\n", decoded_len); + return -EINVAL; + } + crc = crc32(crc, decoded_key, decoded_len); + key_crc = ((u_int32_t)decoded_key[decoded_len]) | + ((u_int32_t)decoded_key[decoded_len + 1] << 8) | + ((u_int32_t)decoded_key[decoded_len + 2] << 16) | + ((u_int32_t)decoded_key[decoded_len + 3] << 24); + if (key_crc != crc) { + fprintf(stderr, "CRC mismatch (key %08x, crc %08x)\n", + key_crc, crc); + return -EINVAL; + } + printf("Key is valid (HMAC %d, length %d, CRC %08x)\n", + hmac, decoded_len, crc); + return 0; } 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 fabrics_discover(desc, argc, argv, false); + return nvmf_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 fabrics_discover(desc, argc, argv, true); + return nvmf_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 fabrics_connect(desc, argc, argv); + return nvmf_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 fabrics_disconnect(desc, argc, argv); + return nvmf_disconnect(desc, argc, argv); } -static int disconnect_all_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +int disconnect_all_cmd(int argc, char **argv, struct command *command, + struct plugin *plugin) { const char *desc = "Disconnect from all connected NVMeoF subsystems"; - return fabrics_disconnect_all(desc, argc, argv); + return nvmf_disconnect_all(desc, argc, argv); +} + +static int config_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Configuration of NVMeoF subsystems"; + return nvmf_config(desc, argc, argv); +} + +static int dim_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Send Discovery Information Management command to a Discovery Controller (DC)"; + return nvmf_dim(desc, argc, argv); } void register_extension(struct plugin *plugin) @@ -6617,5 +7981,5 @@ int main(int argc, char **argv) if (err == -ENOTTY) general_help(&builtin); - return err; + return err ? 1 : 0; } diff --git a/nvme.control.in b/nvme.control.in index 46714d4..74d36aa 100644 --- a/nvme.control.in +++ b/nvme.control.in @@ -1,9 +1,9 @@ Package: nvme -Version: @@VERSION@@ +Version: @VERSION@ Section: base Priority: optional Architecture: amd64 -Depends: @@DEPENDS@@ +Depends: @DEPENDS@ Maintainer: Keith Busch <kbusch@kernel.org> Description: NVM-Express Command Line Interface The nvme management tool @@ -22,17 +22,28 @@ #include <sys/time.h> #include "plugin.h" -#ifdef LIBJSONC -#include <json-c/json.h> +#ifdef CONFIG_JSONC +#include <json.h> #define json_create_object(o) json_object_new_object(o) #define json_create_array(a) json_object_new_array(a) #define json_free_object(o) json_object_put(o) #define json_free_array(a) json_object_put(a) #define json_object_add_value_uint(o, k, v) \ - json_object_object_add(o, k, json_object_new_uint64(v)) + json_object_object_add(o, k, json_object_new_int(v)) #define json_object_add_value_int(o, k, v) \ - json_object_object_add(o, k, json_object_new_int64(v)) + json_object_object_add(o, k, json_object_new_int(v)) +#ifdef CONFIG_JSONC_14 +#define json_object_add_value_uint64(o, k, v) \ + json_object_object_add(o, k, json_object_new_uint64(v)) +#else +#define json_object_add_value_uint64(o, k, v) \ + if ((v) > UINT_MAX) { \ + fprintf(stderr, "Value overflow in %s", k); \ + json_object_object_add(o, k, json_object_new_int(-1)); \ + } else \ + json_object_object_add(o, k, json_object_new_int(v)) +#endif #define json_object_add_value_float(o, k, v) \ json_object_object_add(o, k, json_object_new_double(v)) #define json_object_add_value_string(o, k, v) \ @@ -46,12 +57,13 @@ #define json_array_add_value_string(o, v) \ json_object_array_add(o, json_object_new_string(v)) #define json_print_object(o, u) \ - printf("%s", json_object_to_json_string_ext(o, JSON_C_TO_STRING_PRETTY)) + printf("%s", json_object_to_json_string_ext(o, \ + JSON_C_TO_STRING_PRETTY | \ + JSON_C_TO_STRING_NOSLASHESCAPE)) #else #include "util/json.h" #endif #include "util/argconfig.h" -#include "linux/nvme.h" enum nvme_print_flags { NORMAL = 0, @@ -61,55 +73,6 @@ enum nvme_print_flags { BINARY = 1 << 3, /* binary dump raw bytes */ }; -struct nvme_subsystem; -struct nvme_ctrl; - -struct nvme_namespace { - char *name; - struct nvme_ctrl *ctrl; - - unsigned nsid; - struct nvme_id_ns ns; -}; - -struct nvme_ctrl { - char *name; - char *path; - struct nvme_subsystem *subsys; - - char *address; - char *transport; - char *state; - char *ana_state; - char *traddr; - char *trsvcid; - char *host_traddr; - char *host_iface; - char *hostnqn; - char *hostid; - - struct nvme_id_ctrl id; - - int nr_namespaces; - struct nvme_namespace *namespaces; -}; - -struct nvme_subsystem { - char *name; - char *subsysnqn; - - int nr_ctrls; - struct nvme_ctrl *ctrls; - - int nr_namespaces; - struct nvme_namespace *namespaces; -}; - -struct nvme_topology { - int nr_subsystems; - struct nvme_subsystem *subsystems; -}; - #define SYS_NVME "/sys/class/nvme" void register_extension(struct plugin *plugin); @@ -121,30 +84,12 @@ extern const char *output_format; enum nvme_print_flags validate_output_format(const char *format); int __id_ctrl(int argc, char **argv, struct command *cmd, - struct plugin *plugin, void (*vs)(__u8 *vs, struct json_object *root)); -char *nvme_char_from_block(char *block); -int nvme_logical_block_size_from_ns_char(const char *dev); -void *mmap_registers(const char *dev); + struct plugin *plugin, void (*vs)(uint8_t *vs, struct json_object *root)); extern int current_index; -int scan_ctrl_namespace_filter(const struct dirent *d); -int scan_namespace_filter(const struct dirent *d); -int scan_ctrl_paths_filter(const struct dirent *d); -int scan_ctrls_filter(const struct dirent *d); -int scan_subsys_filter(const struct dirent *d); -int scan_dev_filter(const struct dirent *d); - -int scan_subsystems(struct nvme_topology *t, const char *subsysnqn, - __u32 ns_instance, int nsid, char *dev_dir); -void free_topology(struct nvme_topology *t); -char *get_nvme_subsnqn(char *path); -char *nvme_get_ctrl_attr(const char *path, const char *attr); - void *nvme_alloc(size_t len, bool *huge); void nvme_free(void *p, bool huge); - -int uuid_from_dmi(char *uuid); -int uuid_from_systemd(char *uuid); +const char *nvme_strerror(int errnum); unsigned long long elapsed_utime(struct timeval start_time, struct timeval end_time); @@ -154,5 +99,13 @@ static inline void nvme_strip_spaces(char *s, int l) while (l && (s[l] == '\0' || s[l] == ' ')) s[l--] = '\0'; } -__u16 get_feat_buf_len(unsigned short feature); + +/* nvme-print.c */ +const char *nvme_select_to_string(int sel); + +void d(unsigned char *buf, int len, int width, int group); +void d_raw(unsigned char *buf, unsigned len); +uint64_t int48_to_long(uint8_t *data); + +int map_log_level(int verbose, bool quiet); #endif /* _NVME_H */ diff --git a/nvme.spec.in b/nvme.spec.in index 7154a87..f05d0eb 100644 --- a/nvme.spec.in +++ b/nvme.spec.in @@ -1,58 +1,53 @@ Name: nvme -Version: @@VERSION@@ +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): util-linux systemd systemd-udev BuildRoot: %{_tmppath}/%{name}-%{version}-root +@REQUIRES@ %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-spec DESTDIR=%{buildroot} PREFIX=/usr +meson install --destdir %{buildroot} --skip-subprojects +touch %{buildroot}@SYSCONFDIR@/nvme/hostnqn +touch %{buildroot}@SYSCONFDIR@/nvme/hostid %files %defattr(-,root,root) -%doc Documentation/nvme*.1 -%{_sbindir}/nvme -%{_mandir}/man1/nvme*.1* -%{_datadir}/bash-completion/completions/nvme -%{_datadir}/zsh/site-functions/_nvme -%dir %{_sysconfdir}/nvme -%{_sysconfdir}/nvme/hostnqn -%{_sysconfdir}/nvme/hostid -%{_sysconfdir}/nvme/discovery.conf -%{_sysconfdir}/udev/rules.d/70-nvmf-autoconnect.rules -%{_sysconfdir}/udev/rules.d/71-nvmf-iopolicy-netapp.rules -%{_libdir}/dracut/dracut.conf.d/70-nvmf-autoconnect.conf -%{_libdir}/systemd/system/nvmf-connect@.service -%{_libdir}/systemd/system/nvmefc-boot-connections.service -%{_libdir}/systemd/system/nvmf-connect.target -%{_libdir}/systemd/system/nvmf-autoconnect.service +@SBINDIR@/nvme +@MANDIR@/man1/nvme*.1* +@DATADIR@/bash-completion/completions/nvme +@DATADIR@/zsh/site-functions/_nvme +%dir @SYSCONFDIR@/nvme +@SYSCONFDIR@/nvme/hostnqn +@SYSCONFDIR@/nvme/hostid +@SYSCONFDIR@/nvme/discovery.conf +%ghost @SYSCONFDIR@/nvme/config.json +@UDEVRULESDIR@/70-nvmf-autoconnect.rules +@UDEVRULESDIR@/71-nvmf-iopolicy-netapp.rules +@DRACUTRILESDIR@/70-nvmf-autoconnect.conf +@SYSTEMDDIR@/nvmf-connect@.service +@SYSTEMDDIR@/nvmefc-boot-connections.service +@SYSTEMDDIR@/nvmf-connect.target +@SYSTEMDDIR@/nvmf-autoconnect.service %clean rm -rf $RPM_BUILD_ROOT %post if [ $1 -eq 1 ]; then # 1 : This package is being installed for the first time - if [ ! -s %{_sysconfdir}/nvme/hostnqn ]; then - echo $(%{_sbindir}/nvme gen-hostnqn) > %{_sysconfdir}/nvme/hostnqn + if [ ! -s @SYSCONFDIR@/nvme/hostnqn ]; then + echo $(@SBINDIR@/nvme gen-hostnqn) > @SYSCONFDIR@/nvme/hostnqn fi - if [ ! -s %{_sysconfdir}/nvme/hostid ]; then - uuidgen > %{_sysconfdir}/nvme/hostid + if [ ! -s @SYSCONFDIR@/nvme/hostid ]; then + uuidgen > @SYSCONFDIR@/nvme/hostid fi # apply udev and systemd changes that we did diff --git a/nvmf-autoconnect/dracut-conf/70-nvmf-autoconnect.conf.in b/nvmf-autoconnect/dracut-conf/70-nvmf-autoconnect.conf.in index b32f2c3..ba96116 100644 --- a/nvmf-autoconnect/dracut-conf/70-nvmf-autoconnect.conf.in +++ b/nvmf-autoconnect/dracut-conf/70-nvmf-autoconnect.conf.in @@ -1 +1 @@ -install_items+=" @@UDEVRULESDIR@@/70-nvmf-autoconnect.rules " +install_items+=" @UDEVRULESDIR@/70-nvmf-autoconnect.rules " diff --git a/nvmf-autoconnect/systemd/nvmefc-boot-connections.service b/nvmf-autoconnect/systemd/nvmefc-boot-connections.service.in index 33ab8c1..33ab8c1 100644 --- a/nvmf-autoconnect/systemd/nvmefc-boot-connections.service +++ b/nvmf-autoconnect/systemd/nvmefc-boot-connections.service.in diff --git a/nvmf-autoconnect/systemd/nvmf-autoconnect.service b/nvmf-autoconnect/systemd/nvmf-autoconnect.service.in index b1be272..d83d9a1 100644 --- a/nvmf-autoconnect/systemd/nvmf-autoconnect.service +++ b/nvmf-autoconnect/systemd/nvmf-autoconnect.service.in @@ -1,13 +1,13 @@ [Unit] Description=Connect NVMe-oF subsystems automatically during boot -ConditionPathExists=/etc/nvme/discovery.conf +ConditionPathExists=@SYSCONFDIR@/nvme/discovery.conf After=network-online.target Before=remote-fs-pre.target [Service] Type=oneshot ExecStartPre=/sbin/modprobe nvme-fabrics -ExecStart=/usr/sbin/nvme connect-all +ExecStart=@SBINDIR@/nvme connect-all [Install] WantedBy=default.target diff --git a/nvmf-autoconnect/systemd/nvmf-connect.target b/nvmf-autoconnect/systemd/nvmf-connect.target.in index f64a37c..f64a37c 100644 --- a/nvmf-autoconnect/systemd/nvmf-connect.target +++ b/nvmf-autoconnect/systemd/nvmf-connect.target.in diff --git a/nvmf-autoconnect/systemd/nvmf-connect@.service b/nvmf-autoconnect/systemd/nvmf-connect@.service.in index 5fbf081..90f774c 100644 --- a/nvmf-autoconnect/systemd/nvmf-connect@.service +++ b/nvmf-autoconnect/systemd/nvmf-connect@.service.in @@ -11,4 +11,4 @@ Requires=nvmf-connect.target [Service] Type=simple Environment="CONNECT_ARGS=%i" -ExecStart=/bin/sh -c "nvme connect-all --matching --quiet `/bin/echo -e '${CONNECT_ARGS}'`" +ExecStart=/bin/sh -c "@SBINDIR@/nvme connect-all --quiet `/bin/echo -e '${CONNECT_ARGS}'`" diff --git a/nvmf-autoconnect/udev-rules/70-nvmf-autoconnect.rules b/nvmf-autoconnect/udev-rules/70-nvmf-autoconnect.rules.in index cbbebc5..434cc08 100644 --- a/nvmf-autoconnect/udev-rules/70-nvmf-autoconnect.rules +++ b/nvmf-autoconnect/udev-rules/70-nvmf-autoconnect.rules.in @@ -11,9 +11,9 @@ ACTION=="change", SUBSYSTEM=="nvme", ENV{NVME_AEN}=="0x70f002",\ ENV{NVME_TRTYPE}=="*", ENV{NVME_TRADDR}=="*", \ ENV{NVME_TRSVCID}=="*", ENV{NVME_HOST_TRADDR}=="*", \ - RUN+="/bin/systemctl --no-block start nvmf-connect@--device=$kernel\t--transport=$env{NVME_TRTYPE}\t--traddr=$env{NVME_TRADDR}\t--trsvcid=$env{NVME_TRSVCID}\t--host-traddr=$env{NVME_HOST_TRADDR}.service" + RUN+="@SYSTEMCTL@ --no-block start nvmf-connect@--device=$kernel\t--transport=$env{NVME_TRTYPE}\t--traddr=$env{NVME_TRADDR}\t--trsvcid=$env{NVME_TRSVCID}\t--host-traddr=$env{NVME_HOST_TRADDR}.service" # nvme-fc transport generated events (old-style for compatibility) ACTION=="change", SUBSYSTEM=="fc", ENV{FC_EVENT}=="nvmediscovery", \ ENV{NVMEFC_HOST_TRADDR}=="*", ENV{NVMEFC_TRADDR}=="*", \ - RUN+="/bin/systemctl --no-block start nvmf-connect@--device=none\t--transport=fc\t--traddr=$env{NVMEFC_TRADDR}\t--trsvcid=none\t--host-traddr=$env{NVMEFC_HOST_TRADDR}.service" + RUN+="@SYSTEMCTL@ --no-block start nvmf-connect@--device=none\t--transport=fc\t--traddr=$env{NVMEFC_TRADDR}\t--trsvcid=none\t--host-traddr=$env{NVMEFC_HOST_TRADDR}.service" diff --git a/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules b/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in index aefd9d4..aefd9d4 100644 --- a/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules +++ b/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in @@ -121,12 +121,13 @@ void general_help(struct plugin *plugin) 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; + struct command **cmd = plugin->commands; + struct command *cr = NULL; + bool cr_valid = false; if (!argc) { general_help(plugin); @@ -148,18 +149,29 @@ int handle_plugin(int argc, char **argv, struct plugin *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; + while (*cmd) { + if (!strcmp(str, (*cmd)->name) || + ((*cmd)->alias && !strcmp(str, (*cmd)->alias))) + return (*cmd)->fn(argc, argv, *cmd, plugin); + if (!strncmp(str, (*cmd)->name, strlen(str))) { + if (cr) { + cr_valid = false; + } else { + cr = *cmd; + cr_valid = true; + } + } + cmd++; + } - return (cmd->fn(argc, argv, cmd, plugin)); + if (cr && cr_valid) { + sprintf(use, "%s %s <device> [OPTIONS]", prog->name, cr->name); + argconfig_append_usage(use); + return cr->fn(argc, argv, cr, plugin); } /* Check extensions only if this is running the built-in plugin */ - if (plugin->name) { + if (plugin->name) { printf("ERROR: Invalid sub-command '%s' for plugin %s\n", str, plugin->name); return -ENOTTY; } diff --git a/plugins/amzn/amzn-nvme.c b/plugins/amzn/amzn-nvme.c index 47a2d82..cd7d555 100644 --- a/plugins/amzn/amzn-nvme.c +++ b/plugins/amzn/amzn-nvme.c @@ -5,17 +5,11 @@ #include <unistd.h> #include <inttypes.h> -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "argconfig.h" -#include "suffix.h" - #define CREATE_CMD #include "amzn-nvme.h" diff --git a/plugins/dera/dera-nvme.c b/plugins/dera/dera-nvme.c index be78930..f36fc67 100644 --- a/plugins/dera/dera-nvme.c +++ b/plugins/dera/dera-nvme.c @@ -10,12 +10,10 @@ #include <sys/time.h> #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" - -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "dera-nvme.h" @@ -108,7 +106,7 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result) .cdw12 = 0x104, }; - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd); + err = nvme_submit_admin_passthru(fd, &cmd, NULL); if (!err && result) { *result = cmd.result; } @@ -131,8 +129,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin if (fd < 0) return fd; - err = nvme_get_log(fd, 0xffffffff, 0xc0, false, NVME_NO_LOG_LSP, - sizeof(log), &log); + err = nvme_get_log_simple(fd, 0xc0, sizeof(log), &log); if (err) { goto exit; } @@ -189,7 +186,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin printf("fw_loader_version : %.*s\n", 8, log.fw_loader_version); printf("uefi_driver_version : %.*s\n", 8, log.uefi_driver_version); - if (log.pcie_volt_status >= 0 && log.pcie_volt_status <= sizeof(volt_status) / sizeof(const char *)){ + if (log.pcie_volt_status <= sizeof(volt_status) / sizeof(const char *)){ printf("pcie_volt_status : %s\n", volt_status[log.pcie_volt_status]); } else{ @@ -205,7 +202,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin exit: if (err > 0) - fprintf(stderr, "\nNVMe status:%s(0x%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); return err; } diff --git a/plugins/huawei/huawei-nvme.c b/plugins/huawei/huawei-nvme.c index b39d861..116025b 100644 --- a/plugins/huawei/huawei-nvme.c +++ b/plugins/huawei/huawei-nvme.c @@ -26,16 +26,12 @@ #include <sys/stat.h> -#include "linux/nvme_ioctl.h" - +#include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "argconfig.h" -#include "suffix.h" -#include <sys/ioctl.h> +#include "util/suffix.h" #define CREATE_CMD #include "huawei-nvme.h" @@ -50,7 +46,7 @@ struct huawei_list_item { char node[1024]; struct nvme_id_ctrl ctrl; - int nsid; + unsigned nsid; struct nvme_id_ns ns; unsigned block; char ns_name[NS_NAME_LEN]; @@ -87,8 +83,8 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha } item->huawei_device = true; - item->nsid = nvme_get_nsid(fd); - err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); + err = nvme_get_nsid(fd, &item->nsid); + err = nvme_identify_ns(fd, item->nsid, &item->ns); if (err) return err; @@ -211,7 +207,9 @@ static void huawei_print_list_head(struct huawei_list_element_len element_len) 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; + __u8 lba_index; + nvme_id_ns_flbas_to_lbaf_inuse(list_item.ns.flbas, &lba_index); + long long int lba = 1 << list_item.ns.lbaf[lba_index].ds; double nsze = le64_to_cpu(list_item.ns.nsze) * lba; double nuse = le64_to_cpu(list_item.ns.nuse) * lba; @@ -320,7 +318,7 @@ static int huawei_list(int argc, char **argv, struct command *command, if (fmt != JSON && fmt != NORMAL) return -EINVAL; - n = scandir("/dev", &devices, scan_namespace_filter, alphasort); + n = scandir("/dev", &devices, nvme_namespace_filter, alphasort); if (n <= 0) return n; diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c index aaa40ad..80d218c 100644 --- a/plugins/intel/intel-nvme.c +++ b/plugins/intel/intel-nvme.c @@ -5,16 +5,12 @@ #include <unistd.h> #include <inttypes.h> -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" - -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "intel-nvme.h" @@ -351,8 +347,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct config { __u32 namespace_id; - int raw_binary; - int json; + bool raw_binary; + bool json; }; struct config cfg = { @@ -370,8 +366,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, if (fd < 0) return fd; - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_log_simple(fd, 0xca, sizeof(smart_log), &smart_log); if (!err) { if (cfg.json) show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename); @@ -381,8 +376,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, 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); + nvme_show_status(err); return err; } @@ -395,7 +389,7 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu int err, fd; struct config { - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -410,16 +404,14 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, 0xdd, false, - NVME_NO_LOG_LSP, sizeof(log), log); + err = nvme_get_log_simple(fd, 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); + nvme_show_status(err); return err; } @@ -457,7 +449,7 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct const char *desc = "Get Temperature Statistics log and show it."; const char *raw = "dump output in binary format"; struct config { - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -472,16 +464,14 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, 0xc5, false, - NVME_NO_LOG_LSP, sizeof(stats), &stats); + err = nvme_get_log_simple(fd, 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); + nvme_show_status(err); return err; } @@ -497,10 +487,13 @@ struct __attribute__((__packed__)) optane_lat_stats { __u64 data[9]; }; -#define MEDIA_MAJOR_IDX 0 -#define MEDIA_MINOR_IDX 1 -#define MEDIA_MAX_LEN 2 -#define OPTANE_V1000_BUCKET_LEN 8 +#define MEDIA_MAJOR_IDX 0 +#define MEDIA_MINOR_IDX 1 +#define MEDIA_MAX_LEN 2 +#define OPTANE_V1000_BUCKET_LEN 8 +#define OPTANE_V1000_BUCKET_LEN 8 +#define NAND_LAT_STATS_LEN 4868 + static struct intel_lat_stats stats; static struct optane_lat_stats v1000_stats; @@ -529,7 +522,7 @@ enum FormatUnit { #define US_IN_S 1000000 #define US_IN_MS 1000 -static const enum FormatUnit get_seconds_magnitude(__u32 microseconds) +static enum FormatUnit get_seconds_magnitude(__u32 microseconds) { if (microseconds > US_IN_S) return S; @@ -539,7 +532,7 @@ static const enum FormatUnit get_seconds_magnitude(__u32 microseconds) return US; } -static const float convert_seconds(__u32 microseconds) +static float convert_seconds(__u32 microseconds) { float divisor = 1.0; @@ -567,13 +560,15 @@ enum inf_bound_type { * either of "-INF" or "+INF", respectively. */ static void set_unit_string(char *buffer, __u32 microseconds, - enum FormatUnit unit, enum inf_bound_type bound_type) + enum FormatUnit unit, + enum inf_bound_type bound_type) { + char *string; + if (bound_type != NOINF) { - snprintf(buffer, 5, "%s", bound_type ? "+INF" : "-INF"); + snprintf(buffer, BUFSIZE, "%s", bound_type ? "+INF" : "-INF"); return; } - char *string; switch (unit) { case US: @@ -589,8 +584,9 @@ static void set_unit_string(char *buffer, __u32 microseconds, string = "_s"; break; } - snprintf(buffer, 11, "%4.2f%s", - convert_seconds(microseconds), string); + + snprintf(buffer, BUFSIZE, "%4.2f%s", convert_seconds(microseconds), + string); } static void init_buffer(char *buffer, size_t size) @@ -660,12 +656,11 @@ static void show_lat_stats_linear(struct intel_lat_stats *stats, /* * For 4.0-4.5 revision. */ +#define LATENCY_STATS_V4_BASE_BITS 6 +#define LATENCY_STATS_V4_BASE_VAL (1 << LATENCY_STATS_V4_BASE_BITS) + static int lat_stats_log_scale(int i) { - static const int LATENCY_STATS_V4_BASE_BITS = 6; - static const int LATENCY_STATS_V4_BASE_VAL = ( - 1 << LATENCY_STATS_V4_BASE_BITS); - // if (i < 128) if (i < (LATENCY_STATS_V4_BASE_VAL << 1)) return i; @@ -715,8 +710,7 @@ static void json_add_bucket(struct intel_lat_stats *stats, init_buffer(buffer, BUFSIZE); - json_object_add_value_object(bucket_list, - "bucket", bucket); + json_object_array_add(bucket_list, bucket); json_object_add_value_int(bucket, "id", id); set_unit_string(buffer, lower_us, @@ -739,8 +733,7 @@ static void json_add_bucket_optane(struct json_object *bucket_list, __u32 id, init_buffer(buffer, BUFSIZE); - json_object_add_value_object(bucket_list, - "bucket", bucket); + json_object_array_add(bucket_list, bucket); json_object_add_value_int(bucket, "id", id); set_unit_string(buffer, lower_us, @@ -775,7 +768,7 @@ static void json_lat_stats_3_0(struct intel_lat_stats *stats, int write) { struct json_object *root = json_create_object(); - struct json_object *bucket_list = json_create_object(); + struct json_object *bucket_list = json_object_new_array(); lat_stats_make_json_root(root, bucket_list, write); @@ -794,7 +787,7 @@ static void json_lat_stats_4_0(struct intel_lat_stats *stats, int write) { struct json_object *root = json_create_object(); - struct json_object *bucket_list = json_create_object(); + struct json_object *bucket_list = json_object_new_array(); lat_stats_make_json_root(root, bucket_list, write); @@ -847,11 +840,11 @@ static void show_lat_stats_4_0(struct intel_lat_stats *stats) } } -static void jason_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) +static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) { int i; struct json_object *root = json_create_object(); - struct json_object *bucket_list = json_create_object(); + struct json_object *bucket_list = json_object_new_array(); lat_stats_make_json_root(root, bucket_list, write); @@ -951,7 +944,7 @@ static void json_lat_stats(int write) case 1000: switch (media_version[MEDIA_MINOR_IDX]) { case 0: - jason_lat_stats_v1000_0(&v1000_stats, write); + json_lat_stats_v1000_0(&v1000_stats, write); break; default: printf("Unsupported minor revision (%u.%u)\n", @@ -998,6 +991,7 @@ static void show_lat_stats(int write) case 3: case 4: case 5: + case 6: show_lat_stats_4_0(&stats); break; default: @@ -1028,6 +1022,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct { int err, fd; + __u8 data[NAND_LAT_STATS_LEN]; const char *desc = "Get Intel Latency Statistics log and show it."; const char *raw = "Dump output in binary format"; @@ -1035,9 +1030,9 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct const char *write = "Get write statistics (read default)"; struct config { - int raw_binary; - int json; - int write; + bool raw_binary; + bool json; + bool write; }; struct config cfg = { @@ -1054,10 +1049,15 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct if (fd < 0) return fd; - /* Query maj and minor version first */ - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(media_version), - media_version); + /* For optate, latency stats are deleted every time their LID is pulled. + * Therefore, we query the longest lat_stats log page first. + */ + err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, + sizeof(data), &data); + + media_version[0] = (data[1] << 8) | data[0]; + media_version[1] = (data[3] << 8) | data[2]; + if (err) goto close_fd; @@ -1065,11 +1065,23 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct __u32 thresholds[OPTANE_V1000_BUCKET_LEN] = {0}; __u32 result; - err = nvme_get_feature(fd, 0, 0xf7, 0, cfg.write ? 0x1 : 0x0, 0, - sizeof(thresholds), thresholds, &result); + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = 0xf7, + .nsid = 0, + .sel = 0, + .cdw11 = cfg.write ? 0x1 : 0x0, + .uuidx = 0, + .data_len = sizeof(thresholds), + .data = thresholds, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_get_features(&args); if (err) { - fprintf(stderr, "Quering thresholds failed. NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + fprintf(stderr, "Quering thresholds failed. "); + nvme_show_status(err); goto close_fd; } @@ -1083,13 +1095,14 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct } - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(v1000_stats), - &v1000_stats); + /* Move counter values to optate stats struct which has a + * smaller size + */ + memcpy(&v1000_stats, (struct optane_lat_stats *)data, + sizeof(struct optane_lat_stats)); } else { - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(stats), - &stats); + memcpy(&stats, (struct intel_lat_stats *)data, + sizeof(struct intel_lat_stats)); } if (!err) { @@ -1097,11 +1110,16 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct json_lat_stats(cfg.write); else if (!cfg.raw_binary) show_lat_stats(cfg.write); - else - d_raw((unsigned char *)&stats, sizeof(stats)); + else { + if (media_version[0] == 1000) + d_raw((unsigned char *)&v1000_stats, + sizeof(v1000_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); + nvme_show_status(err); close_fd: close(fd); return err; @@ -1213,7 +1231,7 @@ static int read_entire_cmd(struct nvme_passthru_cmd *cmd, int total_size, dword_tfer = min(max_tfer, total_size); while (total_size > 0) { - err = nvme_submit_admin_passthru(ioctl_fd, cmd); + err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL); if (err) { fprintf(stderr, "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n", @@ -1478,8 +1496,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, err = 0; out: if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else if (err < 0) { perror("intel log"); err = EIO; @@ -1518,8 +1535,8 @@ static int enable_lat_stats_tracking(int argc, char **argv, }; const struct argconfig_commandline_options command_line_options[] = { - {"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc}, - {"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc}, + {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc}, + {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc}, {NULL} }; @@ -1540,10 +1557,40 @@ static int enable_lat_stats_tracking(int argc, char **argv, if (fd < 0) return fd; + + struct nvme_get_features_args args_get = { + .args_size = sizeof(args_get), + .fd = fd, + .fid = fid, + .nsid = nsid, + .sel = sel, + .cdw11 = cdw11, + .uuidx = 0, + .data_len = data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + struct nvme_set_features_args args_set = { + .args_size = sizeof(args_set), + .fd = fd, + .fid = fid, + .nsid = nsid, + .cdw11 = option, + .cdw12 = cdw12, + .save = save, + .uuidx = 0, + .cdw15 = 0, + .data_len = data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + switch (option) { case None: - err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf, - &result); + err = nvme_get_features(&args_get); if (!err) { printf( "Latency Statistics Tracking (FID 0x%X) is currently (%i).\n", @@ -1555,11 +1602,9 @@ static int enable_lat_stats_tracking(int argc, char **argv, break; case True: case False: - err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0, - data_len, buf, &result); + err = nvme_set_features(&args_set); if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else if (err < 0) { perror("Enable latency tracking"); fprintf(stderr, "Command failed while parsing.\n"); @@ -1590,12 +1635,12 @@ static int set_lat_stats_thresholds(int argc, char **argv, __u32 result; struct config { - int write; + bool write; char *bucket_thresholds; }; struct config cfg = { - .write = 0, + .write = false, .bucket_thresholds = "", }; @@ -1615,12 +1660,11 @@ static int set_lat_stats_thresholds(int argc, char **argv, * valid buckets a user is allowed to modify. Read or write doesn't * matter */ - err = nvme_get_log(fd, NVME_NSID_ALL, 0xc2, - false, NVME_NO_LOG_LSP, sizeof(media_version), - media_version); + err = nvme_get_log_simple(fd, 0xc2, + sizeof(media_version), media_version); if (err) { - fprintf(stderr, "Querying media version failed. NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + fprintf(stderr, "Querying media version failed. "); + nvme_show_status(err); goto close_fd; } @@ -1635,13 +1679,25 @@ static int set_lat_stats_thresholds(int argc, char **argv, } - err = nvme_set_feature(fd, nsid, fid, cfg.write ? 0x1 : 0x0, - cdw12, save, 0, OPTANE_V1000_BUCKET_LEN, - thresholds, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = fid, + .nsid = nsid, + .cdw11 = cfg.write ? 0x1 : 0x0, + .cdw12 = cdw12, + .save = save, + .uuidx = 0, + .cdw15 = 0, + .data_len = sizeof(thresholds), + .data = thresholds, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else if (err < 0) { perror("Enable latency tracking"); fprintf(stderr, "Command failed while parsing.\n"); diff --git a/plugins/lnvm/lnvm-nvme.c b/plugins/lnvm/lnvm-nvme.c deleted file mode 100644 index 3678176..0000000 --- a/plugins/lnvm/lnvm-nvme.c +++ /dev/null @@ -1,436 +0,0 @@ -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> - -#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."; - int ret; - - struct config { - char *devname; - char *mmtype; - }; - - struct config cfg = { - .devname = "", - .mmtype = "gennvm", - }; - - OPT_ARGS(opts) = { - OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname), - OPT_STRING("mediamgr-name", 'm', "MM", &cfg.mmtype, mmtype), - OPT_END() - }; - - ret = argconfig_parse(argc, argv, desc, opts); - if (ret < 0) - return ret; - - if (!strlen(cfg.devname)) { - fprintf(stderr, "device name missing\n"); - 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."; - int ret; - - OPT_ARGS(opts) = { - OPT_END() - }; - - ret = argconfig_parse(argc, argv, desc, opts); - if (ret < 0) - return ret; - - 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"; - int ret; - - OPT_ARGS(opts) = { - OPT_END() - }; - - ret = argconfig_parse(argc, argv, desc, opts); - if (ret < 0) - return ret; - - 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 *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 flags = 0; - int fd; - - struct config { - __u32 namespace_id; - int raw_binary; - int human_readable; - }; - - struct config cfg = { - .namespace_id = 1, - }; - - OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary), - OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), - OPT_END() - }; - - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; - - if (cfg.human_readable) - flags |= VERBOSE; - else if (cfg.raw_binary) - flags |= BINARY; - - return lnvm_do_id_ns(fd, cfg.namespace_id, flags); -} - -static int lnvm_chunk_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) -{ - const char *desc = "Retrieve the chunk information log for the "\ - "specified given LightNVM device, returns in either "\ - "human-readable or binary format.\n"\ - "This will request Geometry first to get the "\ - "num_grp,num_pu,num_chk first to figure out the total size "\ - "of the log pages."\ - ; - const char *output_format = "Output format: normal|binary"; - const char *human_readable = "Print normal in readable format"; - int err, fmt, fd; - struct nvme_nvm_id20 geo; - struct nvme_nvm_chunk_desc *chunk_log; - __u32 nsid; - __u32 data_len; - unsigned int flags = 0; - - struct config { - char *output_format; - int human_readable; - }; - - struct config cfg = { - .output_format = "normal", - }; - - OPT_ARGS(opts) = { - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), - OPT_END() - }; - - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; - - fmt = validate_output_format(cfg.output_format); - if (fmt < 0) { - err = fmt; - goto close; - } - - if (fmt == BINARY) - flags |= BINARY; - else if (cfg.human_readable) - flags |= VERBOSE; - - nsid = nvme_get_nsid(fd); - - /* - * It needs to figure out how many bytes will be requested by this - * subcommand by the (num_grp * num_pu * num_chk) from the Geometry. - */ - err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *) &geo); - if (err) - goto close; - - data_len = (geo.num_grp * geo.num_pu * geo.num_chk) * - sizeof(struct nvme_nvm_chunk_desc); - chunk_log = malloc(data_len); - if (!chunk_log) { - fprintf(stderr, "cound not alloc for chunk log %dbytes\n", - data_len); - err = -ENOMEM; - goto close; - } - - err = lnvm_do_chunk_log(fd, nsid, data_len, chunk_log, flags); - if (err) - fprintf(stderr, "get log page for chunk information failed\n"); - - free(chunk_log); -close: - close(fd); - return err; -} - -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 *over_prov = "Define over-provision percentage for target."; - const char *flag_factory = "Create target in factory mode"; - int flags; - int ret; - - struct config { - char *devname; - char *tgtname; - char *tgttype; - __u32 lun_begin; - __u32 lun_end; - __u32 over_prov; - - /* flags */ - __u32 factory; - }; - - struct config cfg = { - .devname = "", - .tgtname = "", - .tgttype = "", - .lun_begin = -1, - .lun_end = -1, - .over_prov = -1, - .factory = 0, - }; - - OPT_ARGS(opts) = { - OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname), - OPT_STRING("target-name", 'n', "TARGET", &cfg.tgtname, tgtname), - OPT_STRING("target-type", 't', "TARGETTYPE", &cfg.tgttype, tgttype), - OPT_UINT("lun-begin", 'b', &cfg.lun_begin, lun_begin), - OPT_UINT("lun-end", 'e', &cfg.lun_end, lun_end), - OPT_UINT("over-prov", 'o', &cfg.over_prov, over_prov), - OPT_FLAG("factory", 'f', &cfg.factory, flag_factory), - OPT_END() - }; - - ret = argconfig_parse(argc, argv, desc, opts); - if (ret < 0) - return ret; - - if (!strlen(cfg.devname)) { - fprintf(stderr, "device name missing\n"); - 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, cfg.over_prov, 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 remove. e.g. target0."; - int ret; - - struct config { - char *tgtname; - }; - - struct config cfg = { - .tgtname = "", - }; - - OPT_ARGS(opts) = { - OPT_STRING("target-name", 'n', "TARGET", &cfg.tgtname, tgtname), - OPT_END() - }; - - ret = argconfig_parse(argc, argv, desc, opts); - if (ret < 0) - return ret; - - 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"; - int ret; - - struct config { - char *devname; - int erase_only_marked; - int clear_host_marks; - int clear_bb_marks; - }; - - struct config cfg = { - .devname = "", - }; - - OPT_ARGS(opts) = { - OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname), - OPT_FLAG("erase-only-marked", 'e', &cfg.erase_only_marked, erase_only_marked), - OPT_FLAG("clear-host-side-blks", 's', &cfg.clear_host_marks, host_marks), - OPT_FLAG("clear-bb-blks", 'b', &cfg.clear_bb_marks, bb_marks), - OPT_END() - }; - - ret = argconfig_parse(argc, argv, desc, opts); - if (ret < 0) - return ret; - - if (!strlen(cfg.devname)) { - fprintf(stderr, "device name missing\n"); - 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, - }; - - OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), - OPT_SHRT("channel-id", 'c', &cfg.chid, ch), - OPT_SHRT("lun-id", 'l', &cfg.lunid, lun), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary), - OPT_END() - }; - - fd = parse_and_open(argc, argv, desc, opts); - - if (cfg.raw_binary) - flags |= BINARY; - - 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, - }; - - OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), - OPT_SHRT("channel-id", 'c', &cfg.chid, ch), - OPT_SHRT("lun-id", 'l', &cfg.lunid, lun), - OPT_SHRT("plane-id", 'p', &cfg.plnid, pln), - OPT_SHRT("block-id", 'b', &cfg.blkid, blk), - OPT_SHRT("value", 'v', &cfg.value, value), - OPT_END() - }; - - fd = parse_and_open(argc, argv, desc, opts); - - 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); -} diff --git a/plugins/lnvm/lnvm-nvme.h b/plugins/lnvm/lnvm-nvme.h deleted file mode 100644 index 18dffe1..0000000 --- a/plugins/lnvm/lnvm-nvme.h +++ /dev/null @@ -1,27 +0,0 @@ - -#undef CMD_INC_FILE -#define CMD_INC_FILE plugins/lnvm/lnvm-nvme - -#if !defined(LNVM_NVME) || defined(CMD_HEADER_MULTI_READ) -#define LNVM_NVME - -#include "cmd.h" - -PLUGIN(NAME("lnvm", "LightNVM specific extensions", NVME_VERSION), - 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, "geometry") - ENTRY("chunk-log", "Chunk Information Log Page", lnvm_chunk_log) - 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" diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index e3807f1..c0f4d66 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -5,15 +5,11 @@ #include <unistd.h> #include <time.h> -#include "linux/nvme_ioctl.h" - #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" - -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "memblaze-nvme.h" @@ -79,22 +75,19 @@ static int compare_fw_version(const char *fw1, const char *fw2) #define STR_VER_SIZE (5) -int getlogpage_format_type(char *fw_ver) +int getlogpage_format_type(char *model_name) { - char fw_ver_local[STR_VER_SIZE]; - strncpy(fw_ver_local, fw_ver, STR_VER_SIZE); - *(fw_ver_local + STR_VER_SIZE - 1) = '\0'; - if ( IS_RAISIN(fw_ver_local) - || IS_KUMQUAT(fw_ver_local) - || IS_LOQUAT(fw_ver_local) - ) - { - return INTEL_FORMAT; - } - else + int logpage_format_type = INTEL_FORMAT; + const char *boundary_model_name1 = "P"; // MEMBLAZE P7936DT0640M00 + const char *boundary_model_name2 = "P5920"; // Use INTEL_FORMAT from Raisin P5920. + if (0 == strncmp(model_name, boundary_model_name1, strlen(boundary_model_name1))) { - return MEMBLAZE_FORMAT; + if (strncmp(model_name, boundary_model_name2, strlen(boundary_model_name2)) < 0) + { + logpage_format_type = MEMBLAZE_FORMAT; + } } + return logpage_format_type; } static __u32 item_id_2_u32(struct nvme_memblaze_smart_log_item *item) @@ -232,8 +225,6 @@ static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s, printf("%-32s: %3d%% %s%u%s%u%s%u\n", STR17_01, *nm, STR17_03, *raw, STR17_04, *(raw+2), STR17_05, *(raw+4)); /* 18 RAISIN_SI_VD_POWER_LOSS_PROTECTION */ - get_memblaze_new_smart_info(smart, RAISIN_SI_VD_POWER_LOSS_PROTECTION, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR18_01, *nm, int48_to_long(raw)); /* 19 RAISIN_SI_VD_READ_FAIL */ get_memblaze_new_smart_info(smart, RAISIN_SI_VD_READ_FAIL, nm, raw); printf("%-32s: %3d%% %"PRIu64"\n", STR19_01, *nm, int48_to_long(raw)); @@ -392,7 +383,7 @@ static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname, ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3], ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]); - if (getlogpage_format_type(fw_ver)) // Intel Format & new format + if (getlogpage_format_type(ctrl.mn)) // Intel Format & new format { show_memblaze_smart_log_new(smart, nsid, devname); } @@ -419,7 +410,7 @@ int parse_params(char *str, int number, ...) exit(EINVAL); } - if (isalnum(*c) == 0) { + if (isalnum((int)*c) == 0) { printf("%s is not a valid number\n", c); return 1; } @@ -448,7 +439,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm const char *raw = "dump output in binary format"; struct config { __u32 namespace_id; - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -465,8 +456,8 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm if (fd < 0) return fd; - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log); @@ -474,7 +465,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm 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); + nvme_show_status(err); return err; } @@ -503,7 +494,20 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; - err = nvme_get_feature(fd, 0, feature_id, 0, 0, 0, 0, NULL, &result); + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = feature_id, + .nsid = 0, + .sel = 0, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_get_features(&args); if (err < 0) { perror("get-feature"); } @@ -512,7 +516,7 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd mb_feature_to_string(feature_id), nvme_select_to_string(0), result); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -527,7 +531,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd struct config { __u32 feature_id; __u32 value; - int save; + bool save; }; struct config cfg = { @@ -545,7 +549,22 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; - err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = cfg.feature_id, + .nsid = 0, + .cdw11 = cfg.value, + .cdw12 = 0, + .save = cfg.save, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err < 0) { perror("set-feature"); } @@ -553,7 +572,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -602,7 +621,22 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s } cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2; - err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, 0, 0, 0, NULL, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = cfg.feature_id, + .nsid = 0, + .cdw11 = cfg.value, + .cdw12 = 0, + .save = false, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err < 0) { perror("set-feature"); } @@ -610,7 +644,7 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s printf("set-feature:0x%02X (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -721,13 +755,13 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, if (fd < 0) return fd; glp_high_latency_show_bar(fdi, DO_PRINT_FLAG); - err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf); + err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); - while ( 1) { + while (1) { if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break; - err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf); + err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); if ( err) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); break; } } @@ -739,13 +773,13 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, static int memblaze_fw_commit(int fd, int select) { - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_activate_fw, + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_fw_commit, .cdw10 = 8, .cdw12 = select, }; - return nvme_submit_admin_passthru(fd, &cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } static int mb_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -839,13 +873,21 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str while (fw_size > 0) { xfer = min(xfer, fw_size); - err = nvme_fw_download(fd, offset, xfer, fw_buf); + struct nvme_fw_download_args args = { + .args_size = sizeof(args), + .fd = fd, + .offset = offset, + .data_len = xfer, + .data = fw_buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_fw_download(&args); if (err < 0) { perror("fw-download"); goto out; } else if (err != 0) { - fprintf(stderr, "NVME Admin command error:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); goto out; } fw_buf += xfer; @@ -980,7 +1022,7 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st const char *write = "Get write statistics (read default)"; struct config { - int write; + bool write; }; struct config cfg = { .write = 0, @@ -994,12 +1036,12 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, false, NVME_NO_LOG_LSP, sizeof(stats), &stats); + err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, sizeof(stats), &stats); if (!err) io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG, cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM); else - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); close(fd); return err; @@ -1009,8 +1051,8 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st #define FID 0x68 static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err, fd; - char *desc = "Clear Memblaze devices error log."; + int err, fd; + char *desc = "Clear Memblaze devices error log."; //const char *value = "new value of feature (required)"; //const char *save = "specifies that the controller shall save the attribute"; @@ -1028,24 +1070,38 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, .save = 0, }; - OPT_ARGS(opts) = { - OPT_END() - }; - - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; - - + OPT_ARGS(opts) = { + OPT_END() + }; - err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result); + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = cfg.feature_id, + .nsid = 0, + .cdw11 = cfg.value, + .cdw12 = 0, + .save = cfg.save, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err < 0) { perror("set-feature"); } if (!err) { printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); + /* struct nvme_admin_cmd admin_cmd = { .opcode = OP, @@ -1060,7 +1116,7 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, printf("NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); }; */ - return err; + return err; } static int mb_set_lat_stats(int argc, char **argv, @@ -1092,8 +1148,8 @@ static int mb_set_lat_stats(int argc, char **argv, }; const struct argconfig_commandline_options command_line_options[] = { - {"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc}, - {"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc}, + {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc}, + {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc}, {NULL} }; @@ -1111,12 +1167,41 @@ static int mb_set_lat_stats(int argc, char **argv, else if (cfg.enable || cfg.disable) option = cfg.enable; + struct nvme_get_features_args args_get = { + .args_size = sizeof(args_get), + .fd = fd, + .fid = fid, + .nsid = nsid, + .sel = sel, + .cdw11 = cdw11, + .uuidx = 0, + .data_len = data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + struct nvme_set_features_args args_set = { + .args_size = sizeof(args_set), + .fd = fd, + .fid = fid, + .nsid = nsid, + .cdw11 = option, + .cdw12 = cdw12, + .save = save, + .uuidx = 0, + .cdw15 = 0, + .data_len = data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + if (fd < 0) return fd; switch (option) { case None: - err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf, - &result); + err = nvme_get_features(&args_get); if (!err) { printf( "Latency Statistics Tracking (FID 0x%X) is currently (%i).\n", @@ -1128,17 +1213,15 @@ static int mb_set_lat_stats(int argc, char **argv, break; case True: case False: - err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0, - data_len, buf, &result); + err = nvme_set_features(&args_set); if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else if (err < 0) { perror("Enable latency tracking"); fprintf(stderr, "Command failed while parsing.\n"); } else { printf("Successfully set enable bit for FID (0x%X) to %i.\n", - fid, option); + 0xe2, option); } break; default: diff --git a/plugins/meson.build b/plugins/meson.build new file mode 100644 index 0000000..6f21362 --- /dev/null +++ b/plugins/meson.build @@ -0,0 +1,21 @@ +sources += [ + 'plugins/amzn/amzn-nvme.c', + 'plugins/dera/dera-nvme.c', + 'plugins/huawei/huawei-nvme.c', + 'plugins/intel/intel-nvme.c', + 'plugins/memblaze/memblaze-nvme.c', + 'plugins/micron/micron-nvme.c', + 'plugins/netapp/netapp-nvme.c', + 'plugins/nvidia/nvidia-nvme.c', + 'plugins/scaleflux/sfx-nvme.c', + 'plugins/seagate/seagate-nvme.c', + 'plugins/shannon/shannon-nvme.c', + 'plugins/toshiba/toshiba-nvme.c', + 'plugins/transcend/transcend-nvme.c', + 'plugins/virtium/virtium-nvme.c', + 'plugins/wdc/wdc-utils.c', + 'plugins/wdc/wdc-nvme.c', + 'plugins/ymtc/ymtc-nvme.c', + 'plugins/zns/zns.c', + 'plugins/ocp/ocp-nvme.c', +] diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index 840682d..d333c4c 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -9,12 +9,13 @@ #include <string.h> #include <libgen.h> #include <sys/stat.h> +#include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-status.h" -#include "nvme-ioctl.h" -#include <sys/ioctl.h> +#include "libnvme.h" #include <limits.h> +#include "linux/types.h" +#include "nvme-print.h" + #define CREATE_CMD #include "micron-nvme.h" @@ -30,6 +31,7 @@ #define C2_log_size 4096 #define D0_log_size 512 #define FB_log_size 512 +#define E1_log_size 256 #define MaxLogChunk 16 * 1024 #define CommonChunkSize 16 * 4096 @@ -39,7 +41,7 @@ /* Plugin version major_number.minor_number.patch */ static const char *__version_major = "1"; static const char *__version_minor = "0"; -static const char *__version_patch = "6"; +static const char *__version_patch = "8"; /* supported models of micron plugin; new models should be added at the end * before UNKNOWN_MODEL. Make sure M5410 is first in the list ! @@ -66,7 +68,7 @@ typedef struct _LogPageHeader_t { static void WriteData(__u8 *data, __u32 len, const char *dir, const char *file, const char *msg) { - char tempFolder[PATH_MAX] = { 0 }; + char tempFolder[8192] = { 0 }; FILE *fpOutFile = NULL; sprintf(tempFolder, "%s/%s", dir, file); if ((fpOutFile = fopen(tempFolder, "ab+")) != NULL) { @@ -115,6 +117,7 @@ static eDriveModel GetDriveModel(int idx) } if (vendor_id == MICRON_VENDOR_ID) { switch (device_id) { + case 0x5196: case 0x51A0: case 0x51A1: case 0x51A2: @@ -311,8 +314,8 @@ static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize) LogPageHeader_t *pLogHeader = NULL; if (ucLogID == 0xC1 || ucLogID == 0xC2 || ucLogID == 0xC4) { - err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP, - CommonChunkSize, pTmpBuf); + err = nvme_get_log_simple(nFD, ucLogID, + CommonChunkSize, pTmpBuf); if (err == 0) { pLogHeader = (LogPageHeader_t *) pTmpBuf; LogPageHeader_t *pLogHeader1 = (LogPageHeader_t *) pLogHeader; @@ -334,7 +337,7 @@ static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize) static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer, int nBuffSize) { int err = 0; - struct nvme_admin_cmd cmd = { 0 }; + struct nvme_passthru_cmd cmd = { 0 }; unsigned int uiNumDwords = (unsigned int)nBuffSize / sizeof(unsigned int); unsigned int uiMaxChunk = uiNumDwords; unsigned int uiNumChunks = 1; @@ -380,7 +383,7 @@ static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer cmd.addr = (__u64) (uintptr_t) pTempPtr; cmd.nsid = 0xFFFFFFFF; cmd.data_len = uiXferDwords * 4; - err = nvme_submit_passthru(nFD, NVME_IOCTL_ADMIN_CMD, &cmd); + err = nvme_submit_admin_passthru(nFD, &cmd, NULL); ullBytesRead += uiXferDwords * 4; pTempPtr = pBuffer + ullBytesRead; } @@ -422,8 +425,7 @@ static int GetCommonLogPage(int nFD, unsigned char ucLogID, goto exit_status; } memset(pTempPtr, 0, nBuffSize); - err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP, - nBuffSize, pTempPtr); + err = nvme_get_log_simple(nFD, ucLogID, nBuffSize, pTempPtr); *pBuffer = pTempPtr; exit_status: @@ -454,8 +456,8 @@ static int micron_parse_options(int argc, char **argv, const char *desc, static int micron_fw_commit(int fd, int select) { - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_activate_fw, + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_fw_commit, .cdw10 = 8, .cdw12 = select, }; @@ -554,13 +556,21 @@ static int micron_selective_download(int argc, char **argv, while (fw_size > 0) { xfer = min(xfer, fw_size); - err = nvme_fw_download(fd, offset, xfer, fw_buf); + struct nvme_fw_download_args args = { + .args_size = sizeof(args), + .fd = fd, + .offset = offset, + .data_len = xfer, + .data = fw_buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_fw_download(&args); if (err < 0) { perror("fw-download"); goto out; } else if (err != 0) { - fprintf(stderr, "NVME Admin command error:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); goto out; } fw_buf += xfer; @@ -584,7 +594,6 @@ static int micron_smbus_option(int argc, char **argv, struct command *cmd, struct plugin *plugin) { __u32 result = 0; - __u32 cdw10 = 0; __u32 cdw11 = 0; const char *desc = "Enable/Disable/Get status of SMBUS option on controller"; const char *option = "enable or disable or status"; @@ -627,7 +636,7 @@ static int micron_smbus_option(int argc, char **argv, if (!strcmp(opt.option, "enable")) { cdw11 = opt.value << 1 | 1; - err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result); if (err == 0) { printf("successfully enabled SMBus on drive\n"); } else { @@ -635,8 +644,20 @@ static int micron_smbus_option(int argc, char **argv, } } else if (!strcmp(opt.option, "status")) { - cdw10 = opt.value; - err = nvme_get_feature(fd, 1, fid, cdw10, 0, 0, 0, 0, &result); + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = fid, + .nsid = 1, + .sel = opt.value, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_get_features(&args); if (err == 0) { printf("SMBus status on the drive: %s (returns %s temperature) \n", (result & 1) ? "enabled" : "disabled", @@ -647,7 +668,7 @@ static int micron_smbus_option(int argc, char **argv, } else if (!strcmp(opt.option, "disable")) { cdw11 = opt.value << 1 | 0; - err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result); if (err == 0) { printf("Successfully disabled SMBus on drive\n"); } else { @@ -698,7 +719,7 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, if (strcmp(cfg.fmt, "json") == 0) is_json = true; - err = nvme_smart_log(fd, 0xffffffff, &smart_log); + err = nvme_get_log_smart(fd, 0xffffffff, false, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -933,11 +954,11 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, /* For M51CX models, PCIe errors are cleared using 0xC3 feature */ if (model == M51CX) { - err = nvme_set_feature(fd, 0, fid, (1 << 31), 0, 0, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 0, (1 << 31), false, &result); if (err == 0 && (err = (int)result) == 0) printf("Device correctable errors cleared!\n"); - else if (err > 0) - nvme_show_status(err); + else if (err > 0) + nvme_show_status(err); else printf("Error clearing Device correctable errors = 0x%x\n", err); goto out; @@ -1098,6 +1119,36 @@ ocp_c0_log_page[] = { { "Log Page Version", 2}, { "Log Page GUID", 16}, }, +/* Extended SMART log information */ +e1_log_page[] = { + { "Reserved", 12}, + { "Grown Bad Block Count", 4}, + { "Per Block Max Erase Count", 4}, + { "Power On Minutes", 4}, + { "Reserved", 24}, + { "Write Protect Reason", 4}, + { "Reserved", 12}, + { "Drive Capacity", 8}, + { "Reserved", 8}, + { "Total Erase Count", 8}, + { "Lifetime Use Rate", 8}, + { "Erase Fail Count", 8}, + { "Reserved", 8}, + { "Reported UC Errors", 8}, + { "Reserved", 24}, + { "Program Fail Count", 16}, + { "Total Bytes Read", 16}, + { "Total Bytes Written", 16}, + { "Reserved", 16}, + { "TU Size", 4}, + { "Total Block Stripe Count", 4}, + { "Free Block Stripe Count", 4}, + { "Block Stripe Size", 8}, + { "Reserved", 16}, + { "User Block Min Erase Count", 4}, + { "User Block Avg Erase Count", 4}, + { "User Block Max Erase Count", 4}, +}, /* Vendor Specific Health Log information */ fb_log_page[] = { { "Physical Media Units Written - TLC", 16, 16 }, @@ -1137,8 +1188,8 @@ fb_log_page[] = { { "Normalized Bad System NAND Block Count", 2, 2}, { "Raw Bad System NAND Block Count", 6, 6}, { "Endurance Estimate", 16, 16}, - { "Thermal Throttling Count", 1, 1}, { "Thermal Throttling Status", 1, 1}, + { "Thermal Throttling Count", 1, 1}, { "Unaligned I/O", 8, 8}, { "Physical Media Units Read", 16, 16}, { "Reserved", 279, 0}, @@ -1272,13 +1323,13 @@ static void print_nand_stats_fb(__u8 *buf, __u8 *buf2, __u8 nsze, bool is_json, init_d0_log_page(buf2, nsze); if (is_json) { - for (int i = 0; i < 7; i++) { + for (int i = 4; i < 7; i++) { json_object_add_value_string(stats, - d0_log_page[i].field, - d0_log_page[i].datastr); + d0_log_page[i].field, + d0_log_page[i].datastr); } } else { - for (int i = 0; i < 7; i++) { + for (int i = 4; i < 7; i++) { printf("%-40s : %s\n", d0_log_page[i].field, d0_log_page[i].datastr); } } @@ -1367,42 +1418,115 @@ static int micron_nand_stats(int argc, char **argv, /* pull log details based on the model name */ sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx); - if ((eModel = GetDriveModel(ctrlIdx)) == UNKNOWN_MODEL) { + eModel = GetDriveModel(ctrlIdx); + if ((eModel == UNKNOWN_MODEL) || (eModel == M51CX)) { printf ("Unsupported drive model for vs-nand-stats command\n"); - err = -1; + err = -1; goto out; } - err = nvme_get_log(fd, NVME_NSID_ALL, 0xD0, false, NVME_NO_LOG_LSP, - D0_log_size, extSmartLog); + err = nvme_get_log_simple(fd, 0xD0, D0_log_size, extSmartLog); has_d0_log = (0 == err); /* should check for firmware version if this log is supported or not */ - if (eModel != M5407 && eModel != M5410) { - err = nvme_get_log(fd, NVME_NSID_ALL, 0xFB, false, NVME_NO_LOG_LSP, - FB_log_size, logFB); + if (eModel == M5407 || eModel == M5410) { + err = nvme_get_log_simple(fd, 0xFB, FB_log_size, logFB); has_fb_log = (0 == err); } nsze = (ctrl.vs[987] == 0x12); - if (nsze == 0 && nsze_from_oacs) nsze = ((ctrl.oacs >> 3) & 0x1); - + err = 0; if (has_fb_log) { __u8 spec = (eModel == M5410) ? 0 : 1; /* FB spec version */ print_nand_stats_fb((__u8 *)logFB, (__u8 *)extSmartLog, nsze, is_json, spec); } else if (has_d0_log) { print_nand_stats_d0((__u8 *)extSmartLog, nsze, is_json); - err = 0; + } else { + printf("Unable to retrieve extended smart log for the drive\n"); + err = -ENOTTY; } out: close(fd); if (err > 0) - nvme_show_status(err); - return nvme_status_to_errno(err, false); + nvme_show_status(err); + + return err; } +static void print_ext_smart_logs_e1(__u8 *buf, bool is_json) +{ + struct json_object *root; + struct json_object *logPages; + struct json_object *stats = NULL; + int field_count = sizeof(e1_log_page)/sizeof(e1_log_page[0]); + + if (is_json) { + root = json_create_object(); + stats = json_create_object(); + logPages = json_create_array(); + json_object_add_value_array(root, "SMART Extended Log:0xE1", logPages); + } + else { + printf("SMART Extended Log:0xE1\n"); + } + + print_micron_vs_logs(buf, e1_log_page, field_count, stats, 0); + + if (is_json) { + json_array_add_value_object(logPages, stats); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } +} + +static int micron_smart_ext_log(int argc, char **argv, + struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Retrieve extended SMART logs for the given device "; + unsigned int extSmartLog[E1_log_size/sizeof(int)] = { 0 }; + eDriveModel eModel = UNKNOWN_MODEL; + int fd = 0, err = 0, ctrlIdx = 0; + bool is_json = true; + struct format { + char *fmt; + }; + const char *fmt = "output format json|normal"; + struct format cfg = { + .fmt = "json", + }; + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) { + printf("\nDevice not found \n");; + return -1; + } + if (strcmp(cfg.fmt, "normal") == 0) + is_json = false; + + sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx); + if ((eModel = GetDriveModel(ctrlIdx)) != M51CX) { + printf ("Unsupported drive model for vs-smart-ext-log command\n"); + err = -1; + goto out; + } + err = nvme_get_log_simple(fd, 0xE1, E1_log_size, extSmartLog); + if (!err) { + print_ext_smart_logs_e1((__u8 *)extSmartLog, is_json); + } + +out: + close(fd); + if (err > 0) + nvme_show_status(err); + return err; +} static void GetDriveInfo(const char *strOSDirName, int nFD, struct nvme_id_ctrl *ctrlp) @@ -1487,7 +1611,7 @@ static void GetCtrlIDDInfo(const char *dir, struct nvme_id_ctrl *ctrlp) static void GetSmartlogData(int fd, const char *dir) { struct nvme_smart_log smart_log; - if (nvme_smart_log(fd, -1, &smart_log) == 0) { + if (nvme_get_log_smart(fd, -1, false, &smart_log) == 0) { WriteData((__u8*)&smart_log, sizeof(smart_log), dir, "smart_data.bin", "smart log"); } @@ -1502,7 +1626,7 @@ static void GetErrorlogData(int fd, int entries, const char *dir) if (error_log == NULL) return; - if (nvme_error_log(fd, entries, error_log) == 0) { + if (nvme_get_log_error(fd, entries, false, error_log) == 0) { WriteData((__u8*)error_log, logSize, dir, "error_information_log.bin", "error log"); } @@ -1513,50 +1637,50 @@ static void GetErrorlogData(int fd, int entries, const char *dir) static void GetGenericLogs(int fd, const char *dir) { struct nvme_self_test_log self_test_log; - struct nvme_firmware_log_page fw_log; - struct nvme_effects_log_page effects; - struct nvme_persistent_event_log_head pevent_log_head; + struct nvme_firmware_slot fw_log; + struct nvme_cmd_effects_log effects; + struct nvme_persistent_event_log pevent_log; void *pevent_log_info = NULL; __u32 log_len = 0; int err = 0 ; bool huge = false; /* get self test log */ - if (nvme_self_test_log(fd, sizeof(self_test_log), &self_test_log) == 0) { + if (nvme_get_log_device_self_test(fd, &self_test_log) == 0) { WriteData((__u8*)&self_test_log, sizeof(self_test_log), dir, "drive_self_test.bin", "self test log"); } /* get fw slot info log */ - if (nvme_fw_log(fd, &fw_log) == 0) { + if (nvme_get_log_fw_slot(fd, 1, &fw_log) == 0) { WriteData((__u8*)&fw_log, sizeof(fw_log), dir, "firmware_slot_info_log.bin", "firmware log"); } /* get effects log */ - if (nvme_effects_log(fd, &effects) == 0) { + if (nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &effects) == 0) { WriteData((__u8*)&effects, sizeof(effects), dir, "command_effects_log.bin", "effects log"); } - + /* get persistent event log */ - (void)nvme_persistent_event_log(fd, NVME_PEVENT_LOG_RELEASE_CTX, - sizeof(pevent_log_head), &pevent_log_head); - memset(&pevent_log_head, 0, sizeof(pevent_log_head)); - err = nvme_persistent_event_log(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ, - sizeof(pevent_log_head), &pevent_log_head); + (void)nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_RELEASE_CTX, + sizeof(pevent_log), &pevent_log); + memset(&pevent_log, 0, sizeof(pevent_log)); + err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ, + sizeof(pevent_log), &pevent_log); if (err) { - fprintf(stderr, "Setting persistent event log read ctx failed (ignored)!\n"); + fprintf(stderr, "Failed to set persistent event log read context"); return; } - log_len = le64_to_cpu(pevent_log_head.tll); + log_len = le64_to_cpu(pevent_log.tll); pevent_log_info = nvme_alloc(log_len, &huge); if (!pevent_log_info) { - perror("could not alloc buffer for persistent event log page (ignored)!\n"); + perror("could not alloc buffer for persistent event log page\n"); return; } - err = nvme_persistent_event_log(fd, NVME_PEVENT_LOG_READ, + err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_READ, log_len, pevent_log_info); if (err == 0) { WriteData((__u8*)pevent_log_info, log_len, dir, @@ -1571,7 +1695,7 @@ static void GetNSIDDInfo(int fd, const char *dir, int nsid) char file[PATH_MAX] = { 0 }; struct nvme_id_ns ns; - if (nvme_identify_ns(fd, nsid, 0, &ns) == 0) { + if (nvme_identify_ns(fd, nsid, &ns) == 0) { sprintf(file, "identify_namespace_%d_data.bin", nsid); WriteData((__u8*)&ns, sizeof(ns), dir, file, "id-ns"); } @@ -1617,7 +1741,7 @@ static void GetOSConfig(const char *strOSDirName) } } -static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data, +static int micron_telemetry_log(int fd, __u8 type, __u8 **data, int *logSize, int da) { int err, bs = 512, offset = bs; @@ -1627,7 +1751,10 @@ static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data, __u8 *buffer = (unsigned char *)calloc(bs, 1); if (buffer == NULL) return -1; - err = nvme_get_telemetry_log(fd, buffer, gen, ctrl_init, bs, 0); + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, 0, bs, buffer); + else + err = nvme_get_log_telemetry_host(fd, 0, bs, buffer); if (err != 0) { fprintf(stderr, "Failed to get telemetry log header for 0x%X\n", type); if (buffer != NULL) { @@ -1657,7 +1784,10 @@ static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data, err = 0; if ((buffer = (unsigned char *)realloc(buffer, (size_t)(*logSize))) != NULL) { while (err == 0 && offset != *logSize) { - err = nvme_get_telemetry_log(fd, buffer + offset, gen, ctrl_init, bs, offset); + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, 0, *logSize, buffer + offset); + else + err = nvme_get_log_telemetry_host(fd, 0, *logSize, buffer + offset); offset += bs; } } @@ -1687,8 +1817,7 @@ static int GetTelemetryData(int fd, const char *dir) }; for(i = 0; i < (int)(sizeof(tmap)/sizeof(tmap[0])); i++) { - err = micron_telemetry_log(fd, (tmap[i].log == 0x07), - tmap[i].log, &buffer, &logSize, 0); + err = micron_telemetry_log(fd, tmap[i].log, &buffer, &logSize, 0); if (err == 0 && logSize > 0 && buffer != NULL) { sprintf(msg, "telemetry log: 0x%X", tmap[i].log); WriteData(buffer, logSize, dir, tmap[i].file, msg); @@ -1735,7 +1864,20 @@ static int GetFeatureSettings(int fd, const char *dir) bufp = NULL; } - err = nvme_get_feature(fd, 1, fmap[i].id, 0, 0x0, 0, len, bufp, &attrVal); + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = fmap[i].id, + .nsid = 1, + .sel = 0, + .cdw11 = 0x0, + .uuidx = 0, + .data_len = len, + .data = bufp, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &attrVal, + }; + err = nvme_get_features(&args); if (err == 0) { sprintf(msg, "feature: 0x%X", fmap[i].id); WriteData((__u8*)&attrVal, sizeof(attrVal), dir, fmap[i].file, msg); @@ -1743,7 +1885,7 @@ static int GetFeatureSettings(int fd, const char *dir) WriteData(bufp, len, dir, fmap[i].file, msg); } } else { - fprintf(stderr, "Feature 0x%x data not retrieved, error %d (ignored)!\n", + printf("Feature 0x%x data not retrieved, error %d (ignored)!\n", fmap[i].id, err); errcnt++; } @@ -1757,7 +1899,7 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, const char *desc = "Get drive HW information"; int fd, err = 0; struct nvme_id_ctrl ctrl = { 0 }; - struct nvme_admin_cmd admin_cmd = { 0 }; + struct nvme_passthru_cmd admin_cmd = { 0 }; struct fb_drive_info { unsigned char hw_ver_major; unsigned char hw_ver_minor; @@ -1794,11 +1936,11 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, is_json = true; if (model == M5407) { - admin_cmd.opcode = 0xDA, + admin_cmd.opcode = 0xD4, admin_cmd.addr = (__u64) (uintptr_t) &dinfo; admin_cmd.data_len = (__u32)sizeof(dinfo); admin_cmd.cdw12 = 3; - err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); + err = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (err) { fprintf(stderr, "ERROR : drive-info opcode failed with 0x%x\n", err); return -1; @@ -2025,7 +2167,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log(fd, NVME_NSID_ALL, 0xC2, false, NVME_NO_LOG_LSP, C2_log_size, logC2); + err = nvme_get_log_simple(fd, 0xC2, C2_log_size, logC2); if (err) { fprintf(stderr, "Failed to retrieve fw activation history log, error: %x\n", err); goto out; @@ -2063,11 +2205,320 @@ out: return err; } -static int micron_error_reason(int argc, char **argv, struct command *cmd, +#define MICRON_FID_LATENCY_MONITOR 0xD0 +#define MICRON_LOG_LATENCY_MONITOR 0xD1 + +static int micron_latency_stats_track(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - printf("This command is not implemented for the drive\n"); - return 0; + int err = 0; + __u32 result = 0; + const char *desc = "Enable, Disable or Get cmd latency monitoring stats"; + const char *option = "enable or disable or status, default is status"; + const char *command = "commands to monitor for - all|read|write|trim," + " default is all i.e, enabled for all commands"; + const char *thrtime = "The threshold value to use for latency monitoring in" + " milliseconds, default is 800ms"; + + int fd = 0; + int fid = MICRON_FID_LATENCY_MONITOR; + eDriveModel model = UNKNOWN_MODEL; + uint32_t command_mask = 0x7; /* 1:read 2:write 4:trim 7:all */ + uint32_t timing_mask = 0x08080800; /* R[31-24]:W[23:16]:T[15:8]:0 */ + uint32_t enable = 2; + struct { + char *option; + char *command; + uint32_t threshold; + } opt = { + .option = "status", + .command = "all", + .threshold = 0 + }; + + OPT_ARGS(opts) = { + OPT_STRING("option", 'o', "option", &opt.option, option), + OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_UINT("threshold", 't', &opt.threshold, thrtime), + OPT_END() + }; + + + if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) { + return -1; + } + + if (!strcmp(opt.option, "enable")) { + enable = 1; + } else if (!strcmp(opt.option, "disable")) { + enable = 0; + } else if (strcmp(opt.option, "status")) { + printf("Invalid control option %s specified\n", opt.option); + return -1; + } + + struct nvme_get_features_args g_args = { + .args_size = sizeof(g_args), + .fd = fd, + .fid = fid, + .nsid = 0, + .sel = 0, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + err = nvme_get_features(&g_args); + if (err != 0) { + printf("Failed to retrieve latency monitoring feature status\n"); + return err; + } + + /* If it is to retrieve the status only */ + if (enable == 2) { + printf("Latency Tracking Statistics is currently %s", + (result & 0xFFFF0000) ? "enabled" : "disabled"); + if ((result & 7) == 7) { + printf(" for All commands\n"); + } else if ((result & 7) > 0) { + printf(" for"); + if (result & 1) { + printf(" Read"); + } + if (result & 2) { + printf(" Write"); + } + if (result & 4) { + printf(" Trim"); + } + printf(" commands\n"); + } else if (result == 0) { + printf("\n"); + } + return err; + } + + /* read and validate threshold values if enable option is specified */ + if (enable == 1) { + if (opt.threshold > 2550) { + printf("The maximum threshold value cannot be more than 2550 ms\n"); + return -1; + } + /* timing mask is in terms of 10ms units, so min allowed is 10ms */ + else if ((opt.threshold % 10) != 0) { + printf("The threshold value should be multiple of 10 ms\n"); + return -1; + } + opt.threshold /= 10; + } + + /* read-in command(s) to be monitored */ + if (!strcmp(opt.command, "read")) { + command_mask = 0x1; + timing_mask = (opt.threshold << 24); + } else if (!strcmp(opt.command, "write")) { + command_mask = 0x2; + timing_mask = (opt.threshold << 16); + } else if (!strcmp(opt.command, "read")) { + command_mask = 0x4; + timing_mask = (opt.threshold << 8); + } else if (strcmp(opt.command, "all")) { + printf("Invalid command %s specified for option %s\n", + opt.command, opt.option); + return -1; + } + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = MICRON_FID_LATENCY_MONITOR, + .nsid = 0, + .cdw11 = enable, + .cdw12 = command_mask, + .save = 1, + .uuidx = 0, + .cdw13 = timing_mask, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err == 0) { + printf("Successfully %sed latency monitoring for %s commands\n", + opt.option, opt.command); + } else { + printf("Failed to %s latency monitoring for %s commands\n", + opt.option, opt.command); + } + + close(fd); + return err; +} + + +static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ +#define LATENCY_LOG_ENTRIES 16 + struct latency_log_entry { + uint64_t timestamp; + uint32_t latency; + uint32_t cmdtag; + union { + struct { + uint32_t opcode:8; + uint32_t fuse:2; + uint32_t rsvd1:4; + uint32_t psdt:2; + uint32_t cid:16; + }; + uint32_t dw0; + }; + uint32_t nsid; + uint32_t slba_low; + uint32_t slba_high; + union { + struct { + uint32_t nlb:16; + uint32_t rsvd2:9; + uint32_t deac:1; + uint32_t prinfo:4; + uint32_t fua:1; + uint32_t lr:1; + }; + uint32_t dw12; + }; + uint32_t dsm; + uint32_t rfu[6]; + } log[LATENCY_LOG_ENTRIES]; + eDriveModel model = UNKNOWN_MODEL; + int err = -1; + int fd = -1; + const char *desc = "Display Latency tracking log information"; + OPT_ARGS(opts) = { + OPT_END() + }; + + if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + return err; + memset(&log, 0, sizeof(log)); + err = nvme_get_log_simple(fd, 0xD1, sizeof(log), &log); + if (err) { + if (err < 0) + printf("Unable to retrieve latency stats log the drive\n"); + return err; + } + /* print header and each log entry */ + printf("Timestamp, Latency, CmdTag, Opcode, Fuse, Psdt,Cid, Nsid," + "Slba_L, Slba_H, Nlb, DEAC, PRINFO, FUA,LR\n"); + for (int i = 0; i < LATENCY_LOG_ENTRIES; i++) { + printf("%"PRIu64",%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n", + log[i].timestamp,log[i].latency, log[i].cmdtag, log[i].opcode, + log[i].fuse, log[i].psdt, log[i].cid, log[i].nsid, + log[i].slba_low, log[i].slba_high, log[i].nlb, + log[i].deac, log[i].prinfo, log[i].fua, log[i].lr); + } + printf("\n"); + return err; +} + +static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "display command latency statistics"; + const char *command = "command to display stats - all|read|write|trim" + "default is all"; + int err = 0; + int fd = -1; + eDriveModel model = UNKNOWN_MODEL; + #define LATENCY_BUCKET_COUNT 32 + struct micron_latency_stats { + uint64_t version; /* major << 32 | minior */ + uint64_t all_cmds[LATENCY_BUCKET_COUNT]; + uint64_t read_cmds[LATENCY_BUCKET_COUNT]; + uint64_t write_cmds[LATENCY_BUCKET_COUNT]; + uint64_t trim_cmds[LATENCY_BUCKET_COUNT]; + uint32_t reserved[765]; /* round up to 4K */ + } log; + + struct latency_thresholds { + uint32_t start; + uint32_t end; + char *unit; + } thresholds[LATENCY_BUCKET_COUNT] = { + {0, 50, "us"}, {50, 100, "us"}, {100, 150, "us"}, {150, 200, "us"}, + {200, 300, "us"}, {300, 400, "us"}, {400, 500, "us"}, {500, 600, "us"}, + {600, 700, "us"}, {700, 800, "us"}, {800, 900, "us"}, {900, 1000, "us"}, + {1, 5, "ms"}, {5, 10, "ms"}, {10, 20, "ms"}, {20, 50, "ms"}, {50, 100, "ms"}, + {100, 200, "ms"}, {200, 300, "ms"}, {300, 400, "ms"}, {400, 500, "ms"}, + {500, 600, "ms"}, {600, 700, "ms"}, {700, 800, "ms"}, {800, 900, "ms"}, + {900, 1000, "ms"}, {1, 2, "s"}, {2, 3, "s"}, {3, 4, "s"}, {4, 5, "s"}, + {5,8, "s"}, + {8, INT_MAX, "s"}, + }; + + struct { + char *command; + } opt = { + .command="all" + }; + + uint64_t *cmd_stats = &log.all_cmds[0]; + char *cmd_str = "All"; + + OPT_ARGS(opts) = { + OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_END() + }; + + if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + return err; + if (!strcmp(opt.command, "read")) { + cmd_stats = &log.read_cmds[0]; + cmd_str = "Read"; + } else if (!strcmp(opt.command, "write")) { + cmd_stats = &log.write_cmds[0]; + cmd_str = "Write"; + } else if (!strcmp(opt.command, "trim")) { + cmd_stats = &log.trim_cmds[0]; + cmd_str = "Trim"; + } else if (strcmp(opt.command, "all")) { + printf("Invalid command option %s to display latency stats\n", opt.command); + return -1; + } + + memset(&log, 0, sizeof(log)); + err = nvme_get_log_simple(fd, 0xD0, sizeof(log), &log); + if (err) { + if (err < 0) + printf("Unable to retrieve latency stats log the drive\n"); + return err; + } + printf("Micron IO %s Command Latency Statistics\n" + "Major Revision : %d\nMinor Revision : %d\n", + cmd_str, (int)(log.version >> 32), (int)(log.version & 0xFFFFFFFF)); + printf("=============================================\n"); + printf("Bucket Start End Command Count\n"); + printf("=============================================\n"); + + for (int b = 0; b < LATENCY_BUCKET_COUNT; b++) { + int bucket = b + 1; + char start[32] = { 0 }; + char end[32] = { 0 }; + sprintf(start, "%u%s", thresholds[b].start, thresholds[b].unit); + if (thresholds[b].end == INT_MAX) + sprintf(end, "INF"); + else + sprintf(end, "%u%s", thresholds[b].end, thresholds[b].unit); + printf("%2d %8s %8s %8"PRIu64"\n", + bucket, start, end, cmd_stats[b]); + } + return err; } static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *cmd, @@ -2106,8 +2557,8 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c __u8 nsze; if ((err = nvme_identify_ctrl(fd, &ctrl)) == 0) - err = nvme_get_log(fd, NVME_NSID_ALL, 0xFB, false, NVME_NO_LOG_LSP, - FB_log_size, logFB); + err = nvme_get_log_simple(fd, 0xFB, + FB_log_size, logFB); if (err) { if (err < 0) printf("Unable to retrieve smart log 0xFB for the drive\n"); @@ -2128,8 +2579,7 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log(fd, NVME_NSID_ALL, 0xC0, false, NVME_NO_LOG_LSP, - C0_log_size, logC0); + err = nvme_get_log_simple(fd, 0xC0, C0_log_size, logC0); if (err == 0) { print_smart_cloud_health_log((__u8 *)logC0, is_json); } else if (err < 0) { @@ -2138,8 +2588,8 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c out: close(fd); if (err > 0) - nvme_show_status(err); - return nvme_status_to_errno(err, false); + nvme_show_status(err); + return err; } static int micron_clr_fw_activation_history(int argc, char **argv, @@ -2163,8 +2613,7 @@ static int micron_clr_fw_activation_history(int argc, char **argv, return err; } - //err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, &result); - err = nvme_set_feature(fd, 1, fid, 0, 0, 0, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 1, 0, 0, &result); if (err == 0) err = (int)result; return err; } @@ -2210,22 +2659,64 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, } if (!strcmp(opt.option, "enable")) { - err = nvme_set_feature(fd, 1, fid, 1, 0, (opt.select & 0x1), 0, 0, 0, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = fid, + .nsid = 1, + .cdw11 = 1, + .cdw12 = 0, + .save = (opt.select & 0x1), + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err == 0) { printf("successfully set controller telemetry option\n"); } else { printf("Failed to set controller telemetry option\n"); } } else if (!strcmp(opt.option, "disable")) { - err = nvme_set_feature(fd, 1, fid, 0, 0, (opt.select & 0x1), 0, 0, 0, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = fid, + .nsid = 1, + .cdw11 = 0, + .cdw12 = 0, + .save = (opt.select & 0x1), + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err == 0) { printf("successfully disabled controller telemetry option\n"); } else { printf("Failed to disable controller telemetry option\n"); } } else if (!strcmp(opt.option, "status")) { - opt.select &= 0x3; - err = nvme_get_feature(fd, 1, fid, opt.select, 0, 0, 0, 0, &result); + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = fid, + .nsid = 1, + .sel = opt.select & 0x3, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_get_features(&args); if (err == 0) { printf("Controller telemetry option : %s\n", (result) ? "enabled" : "disabled"); @@ -2385,7 +2876,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, goto out; } int logSize = 0; __u8 *buffer = NULL; const char *dir = "."; - err = micron_telemetry_log(fd, 0, cfg.log, &buffer, &logSize, cfg.data_area); + err = micron_telemetry_log(fd, cfg.log, &buffer, &logSize, cfg.data_area); if (err == 0 && logSize > 0 && buffer != NULL) { sprintf(msg, "telemetry log: 0x%X", cfg.log); WriteData(buffer, logSize, dir, cfg.package, msg); @@ -2397,10 +2888,10 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, printf("Preparing log package. This will take a few seconds...\n"); - // trim spaces out of serial number string */ + /* trim spaces out of serial number string */ int i, j = 0; for (i = 0; i < sizeof(ctrl.sn); i++) { - if (isblank(ctrl.sn[i])) + if (isblank((int)ctrl.sn[i])) continue; sn[j++] = ctrl.sn[i]; } @@ -2420,8 +2911,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, GetSmartlogData(fd, strCtrlDirName); GetErrorlogData(fd, ctrl.elpe, strCtrlDirName); GetGenericLogs(fd, strCtrlDirName); - - // pull if telemetry log data is supported + /* pull if telemetry log data is supported */ if ((ctrl.lpa & 0x8) == 0x8) GetTelemetryData(fd, strCtrlDirName); @@ -2465,8 +2955,8 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (eModel == M5410 || eModel == M5407) err = NVMEGetLogPage(fd, aVendorLogs[i].ucLogPage, dataBuffer, bSize); else - err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, - false, NVME_NO_LOG_LSP, bSize, dataBuffer); + err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + bSize, dataBuffer); } break; @@ -2484,14 +2974,14 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, break; } memset(dataBuffer, 0, bSize); - err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, - false, NVME_NO_LOG_LSP, bSize, dataBuffer); + err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + bSize, dataBuffer); maxSize = aVendorLogs[i].nMaxSize - bSize; while (err == 0 && maxSize > 0 && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) { sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage); WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg); - err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, - false, NVME_NO_LOG_LSP, bSize, dataBuffer); + err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + bSize, dataBuffer); if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef)) break; maxSize -= bSize; diff --git a/plugins/micron/micron-nvme.h b/plugins/micron/micron-nvme.h index be80544..c1b224e 100644 --- a/plugins/micron/micron-nvme.h +++ b/plugins/micron/micron-nvme.h @@ -13,14 +13,17 @@ PLUGIN(NAME("micron", "Micron vendor specific extensions", NVME_VERSION), ENTRY("vs-pcie-stats", "Retrieve Micron PCIe error stats", micron_pcie_stats) ENTRY("clear-pcie-correctable-errors", "Clear correctable PCIe errors", micron_clear_pcie_correctable_errors) ENTRY("vs-internal-log", "Retrieve Micron logs", micron_internal_logs) - ENTRY("vs-telemetry-controller-option", "Enable/Disable controller telemetry log generation", micron_telemetry_cntrl_option) + ENTRY("vs-telemetry-controller-option", "Enable/Disable controller telemetry log generation", micron_telemetry_cntrl_option) ENTRY("vs-nand-stats", "Retrieve NAND Stats", micron_nand_stats) + ENTRY("vs-smart-ext-log", "Retrieve extended SMART logs", micron_smart_ext_log) ENTRY("vs-drive-info", "Retrieve Drive information", micron_drive_info) ENTRY("plugin-version", "Display plugin version info", micron_plugin_version) ENTRY("cloud-SSD-plugin-version", "Display plugin version info", micron_cloud_ssd_plugin_version) ENTRY("log-page-directory", "Retrieve log page directory", micron_logpage_dir) ENTRY("vs-fw-activate-history", "Display FW activation history", micron_fw_activation_history) - ENTRY("vs-error-reason-identifier", "Retrieve Error reason", micron_error_reason) + ENTRY("latency-tracking", "Latency monitoring feature control", micron_latency_stats_track) + ENTRY("latency-stats", "Latency information for tracked commands", micron_latency_stats_info) + ENTRY("latency-logs", "Latency log details tracked by drive", micron_latency_stats_logs) ENTRY("vs-smart-add-log", "Retrieve extended SMART data", micron_ocp_smart_health_logs) ENTRY("clear-fw-activate-history", "Clear FW activation history", micron_clr_fw_activation_history) ENTRY("vs-smbus-option", "Enable/Disable SMBUS on the drive", micron_smbus_option) diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index 15c3923..9630442 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -21,12 +21,13 @@ #include <unistd.h> #include <errno.h> #include <string.h> -#include <sys/ioctl.h> +#include <uuid/uuid.h> +#include "common.h" #include "nvme.h" -#include "nvme-ioctl.h" +#include "libnvme.h" -#include "suffix.h" +#include "util/suffix.h" #define CREATE_CMD #include "netapp-nvme.h" @@ -56,17 +57,17 @@ enum { static const char *dev_path = "/dev/"; struct smdevice_info { - int nsid; + unsigned nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; char dev[265]; }; struct ontapdevice_info { - int nsid; + unsigned nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; - char nsdesc[4096]; + uuid_t uuid; unsigned char log_data[ONTAP_C2_LOG_SIZE]; char dev[265]; }; @@ -105,24 +106,15 @@ static void netapp_nguid_to_str(char *str, __u8 *nguid) static void netapp_get_ns_size(char *size, long long *lba, struct nvme_id_ns *ns) { - *lba = 1 << ns->lbaf[(ns->flbas & 0x0F)].ds; + __u8 lba_index; + nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); + *lba = 1 << ns->lbaf[lba_index].ds; double nsze = le64_to_cpu(ns->nsze) * (*lba); const char *s_suffix = suffix_si_get(&nsze); sprintf(size, "%.2f%sB", nsze, s_suffix); } -static void netapp_uuid_to_str(char *str, void *data) -{ -#ifdef LIBUUID - uuid_t uuid; - struct nvme_ns_id_desc *desc = data; - - memcpy(uuid, data + sizeof(*desc), 16); - uuid_unparse_lower(uuid, str); -#endif -} - static void ontap_labels_to_str(char *dst, char *src, int count) { int i; @@ -249,6 +241,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int "Volume ID %s, Controller %c, Access State %s, %s\n"; char columnstr[] = "%-16s %-30s %-30s %4d %32s %c %-12s %9s\n"; char *formatstr = basestr; /* default to "normal" output format */ + __u8 lba_index; if (format == NCOLUMN) { /* for column output, change output string and print column headers */ @@ -265,11 +258,12 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int else if (format == NJSON) { /* prepare for json output */ root = json_create_object(); - json_devices = json_create_object(); + json_devices = json_create_array(); } for (i = 0; i < count; i++) { - long long int lba = 1 << devices[i].ns.lbaf[(devices[i].ns.flbas & 0x0F)].ds; + nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas, &lba_index); + long long int lba = 1 << devices[i].ns.lbaf[lba_index].ds; double nsze = le64_to_cpu(devices[i].ns.nsze) * lba; const char *s_suffix = suffix_si_get(&nsze); char size[128]; @@ -296,6 +290,8 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int /* complete the json output */ json_object_add_value_array(root, "SMdevices", json_devices); json_print_object(root, NULL); + printf("\n"); + json_free_object(root); } } @@ -331,13 +327,13 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices, } else if (format == NJSON) { /* prepare for json output */ root = json_create_object(); - json_devices = json_create_object(); + json_devices = json_create_array(); } for (i = 0; i < count; i++) { netapp_get_ns_size(size, &lba, &devices[i].ns); - netapp_uuid_to_str(uuid_str, devices[i].nsdesc); + uuid_unparse_lower(devices[i].uuid, uuid_str); netapp_get_ontap_labels(vsname, nspath, devices[i].log_data); if (format == NJSON) { @@ -354,16 +350,18 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices, /* complete the json output */ json_object_add_value_array(root, "ONTAPdevices", json_devices); json_print_object(root, NULL); + printf("\n"); + json_free_object(root); } } static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen) { - struct nvme_admin_cmd get_log; + struct nvme_passthru_cmd get_log; int err; memset(buf, 0, buflen); - memset(&get_log, 0, sizeof(struct nvme_admin_cmd)); + memset(&get_log, 0, sizeof(struct nvme_passthru_cmd)); get_log.opcode = nvme_admin_get_log_page; get_log.nsid = nsid; @@ -378,7 +376,7 @@ static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen) get_log.cdw10 |= ONTAP_C2_LOG_NSINFO_LSP << 8; get_log.cdw11 = numdu; - err = nvme_submit_admin_passthru(fd, &get_log); + err = nvme_submit_admin_passthru(fd, &get_log, NULL); if (err) { fprintf(stderr, "ioctl error %0x\n", err); return 1; @@ -402,8 +400,8 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item, if (strncmp("NetApp E-Series", item->ctrl.mn, 15) != 0) return 0; /* not the right model of controller */ - item->nsid = nvme_get_nsid(fd); - err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); + err = nvme_get_nsid(fd, &item->nsid); + err = nvme_identify_ns(fd, item->nsid, &item->ns); if (err) { fprintf(stderr, "Unable to identify namespace for %s (%s)\n", dev, strerror(err)); @@ -418,6 +416,7 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, const char *dev) { int err; + void *nsdescs; err = nvme_identify_ctrl(fd, &item->ctrl); if (err) { @@ -430,22 +429,30 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, /* not the right controller model */ return 0; - item->nsid = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &item->nsid); - err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); + err = nvme_identify_ns(fd, item->nsid, &item->ns); if (err) { fprintf(stderr, "Unable to identify namespace for %s (%s)\n", dev, strerror(err)); return 0; } - err = nvme_identify_ns_descs(fd, item->nsid, item->nsdesc); + if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) { + fprintf(stderr, "Cannot allocate controller list payload\n"); + return 0; + } + + err = nvme_identify_ns_descs(fd, item->nsid, nsdescs); if (err) { fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n", dev, strerror(err)); return 0; } + memcpy(item->uuid, nsdescs + sizeof(struct nvme_ns_id_desc), sizeof(item->uuid)); + free(nsdescs); + err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE); if (err) { fprintf(stderr, "Unable to get log page data for %s (%s)\n", diff --git a/plugins/nvidia/nvidia-nvme.c b/plugins/nvidia/nvidia-nvme.c index cdf51ab..8ddd16f 100644 --- a/plugins/nvidia/nvidia-nvme.c +++ b/plugins/nvidia/nvidia-nvme.c @@ -5,17 +5,11 @@ #include <unistd.h> #include <inttypes.h> -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "argconfig.h" -#include "suffix.h" - #define CREATE_CMD #include "nvidia-nvme.h" diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c new file mode 100644 index 0000000..6b7fc9d --- /dev/null +++ b/plugins/ocp/ocp-nvme.c @@ -0,0 +1,788 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2022 Meta Platforms, Inc. + * + * Authors: Arthur Shau <arthurshau@fb.com>, + * Wei Zhang <wzhang@fb.com>, + * Venkat Ramesh <venkatraghavan@fb.com> + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <inttypes.h> +#include <errno.h> +#include <limits.h> +#include <fcntl.h> +#include <unistd.h> + +#include "common.h" +#include "nvme.h" +#include "libnvme.h" +#include "plugin.h" +#include "linux/types.h" +#include "nvme-print.h" + +#define CREATE_CMD +#include "ocp-nvme.h" + +/* C0 SCAO Log Page */ +#define C0_SMART_CLOUD_ATTR_LEN 0x200 +#define C0_SMART_CLOUD_ATTR_OPCODE 0xC0 +#define C0_GUID_LENGTH 16 +#define C0_ACTIVE_BUCKET_TIMER_INCREMENT 5 +#define C0_ACTIVE_THRESHOLD_INCREMENT 5 +#define C0_MINIMUM_WINDOW_INCREMENT 100 + +static __u8 scao_guid[C0_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, + 0xF2, 0xA4, 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF }; + +/* C3 Latency Monitor Log Page */ +#define C3_LATENCY_MON_LOG_BUF_LEN 0x200 +#define C3_LATENCY_MON_OPCODE 0xC3 +#define C3_LATENCY_MON_VERSION 0x0001 +#define C3_GUID_LENGTH 16 +static __u8 lat_mon_guid[C3_GUID_LENGTH] = { 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, + 0x6c, 0x9c, 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85 }; + +#define READ 0 +#define WRITE 1 +#define TRIM 2 +#define RESERVED 3 + +typedef enum { + SCAO_PMUW = 0, /* Physical media units written */ + SCAO_PMUR = 16, /* Physical media units read */ + SCAO_BUNBR = 32, /* Bad user nand blocks raw */ + SCAO_BUNBN = 38, /* Bad user nand blocks normalized */ + SCAO_BSNBR = 40, /* Bad system nand blocks raw */ + SCAO_BSNBN = 46, /* Bad system nand blocks normalized */ + SCAO_XRC = 48, /* XOR recovery count */ + SCAO_UREC = 56, /* Uncorrectable read error count */ + SCAO_SEEC = 64, /* Soft ecc error count */ + SCAO_EECE = 72, /* End to end corrected errors */ + SCAO_EEDC = 76, /* End to end detected errors */ + SCAO_SDPU = 80, /* System data percent used */ + SCAO_RFSC = 81, /* Refresh counts */ + SCAO_MXUDEC = 88, /* Max User data erase counts */ + SCAO_MNUDEC = 92, /* Min User data erase counts */ + SCAO_NTTE = 96, /* Number of Thermal throttling events */ + SCAO_CTS = 97, /* Current throttling status */ + SCAO_EVF = 98, /* Errata Version Field */ + SCAO_PVF = 99, /* Point Version Field */ + SCAO_MIVF = 101, /* Minor Version Field */ + SCAO_MAVF = 103, /* Major Version Field */ + SCAO_PCEC = 104, /* PCIe correctable error count */ + SCAO_ICS = 112, /* Incomplete shutdowns */ + SCAO_PFB = 120, /* Percent free blocks */ + SCAO_CPH = 128, /* Capacitor health */ + SCAO_NEV = 130, /* NVMe Errata Version */ + SCAO_UIO = 136, /* Unaligned I/O */ + SCAO_SVN = 144, /* Security Version Number */ + SCAO_NUSE = 152, /* NUSE - Namespace utilization */ + SCAO_PSC = 160, /* PLP start count */ + SCAO_EEST = 176, /* Endurance estimate */ + SCAO_PLRC = 192, /* PCIe Link Retraining Count */ + SCAO_LPV = 494, /* Log page version */ + SCAO_LPG = 496, /* Log page GUID */ +} SMART_CLOUD_ATTRIBUTE_OFFSETS; + +struct __attribute__((__packed__)) ssd_latency_monitor_log { + __u8 feature_status; /* 0x00 */ + __u8 rsvd1; /* 0x01 */ + __le16 active_bucket_timer; /* 0x02 */ + __le16 active_bucket_timer_threshold; /* 0x04 */ + __u8 active_threshold_a; /* 0x06 */ + __u8 active_threshold_b; /* 0x07 */ + __u8 active_threshold_c; /* 0x08 */ + __u8 active_threshold_d; /* 0x09 */ + __le16 active_latency_config; /* 0x0A */ + __u8 active_latency_min_window; /* 0x0C */ + __u8 rsvd2[0x13]; /* 0x0D */ + + __le32 active_bucket_counter[4][4] ; /* 0x20 - 0x5F */ + __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */ + __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */ + __le16 active_latency_stamp_units; /* 0xD8 */ + __u8 rsvd3[0x16]; /* 0xDA */ + + __le32 static_bucket_counter[4][4] ; /* 0xF0 - 0x12F */ + __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */ + __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */ + __le16 static_latency_stamp_units; /* 0x1A8 */ + __u8 rsvd4[0x16]; /* 0x1AA */ + + __le16 debug_log_trigger_enable; /* 0x1C0 */ + __le16 debug_log_measured_latency; /* 0x1C2 */ + __le64 debug_log_latency_stamp; /* 0x1C4 */ + __le16 debug_log_ptr; /* 0x1CC */ + __le16 debug_log_counter_trigger; /* 0x1CE */ + __u8 debug_log_stamp_units; /* 0x1D0 */ + __u8 rsvd5[0x1D]; /* 0x1D1 */ + + __le16 log_page_version; /* 0x1EE */ + __u8 log_page_guid[0x10]; /* 0x1F0 */ +}; + +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; +} + +static int convert_ts(time_t time, char *ts_buf) +{ + struct tm gmTimeInfo; + time_t time_Human, time_ms; + char buf[80]; + + time_Human = time/1000; + time_ms = time % 1000; + + gmtime_r((const time_t *)&time_Human, &gmTimeInfo); + + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &gmTimeInfo); + sprintf(ts_buf, "%s.%03ld GMT", buf, time_ms); + + return 0; +} + +static void ocp_print_C0_log_normal(void *data) +{ + __u8 *log_data = (__u8*)data; + uint16_t smart_log_ver = 0; + + printf("SMART Cloud Attributes :- \n"); + + printf(" Physical media units written - %"PRIu64" %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); + printf(" Physical media units read - %"PRIu64" %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); + printf(" Bad user nand blocks - Raw %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); + printf(" Bad user nand blocks - Normalized %d\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); + printf(" Bad system nand blocks - Raw %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); + printf(" Bad system nand blocks - Normalized %d\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); + printf(" XOR recovery count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); + printf(" Uncorrectable read error count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); + printf(" Soft ecc error count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); + printf(" End to end corrected errors %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); + printf(" End to end detected errors %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); + printf(" System data percent used %d\n", + (__u8)log_data[SCAO_SDPU]); + printf(" Refresh counts %"PRIu64"\n", + (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF)); + printf(" Max User data erase counts %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); + printf(" Min User data erase counts %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); + printf(" Number of Thermal throttling events %d\n", + (__u8)log_data[SCAO_NTTE]); + printf(" Current throttling status 0x%x\n", + (__u8)log_data[SCAO_CTS]); + printf(" PCIe correctable error count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); + printf(" Incomplete shutdowns %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); + printf(" Percent free blocks %d\n", + (__u8)log_data[SCAO_PFB]); + printf(" Capacitor health %"PRIu16"\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); + printf(" Unaligned I/O %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); + printf(" Security Version Number %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); + printf(" NUSE - Namespace utilization %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); + printf(" PLP start count %.0Lf\n", + int128_to_double(&log_data[SCAO_PSC])); + printf(" Endurance estimate %.0Lf\n", + int128_to_double(&log_data[SCAO_EEST])); + smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); + printf(" Log page version %"PRIu16"\n",smart_log_ver); + printf(" Log page GUID 0x"); + printf("%"PRIx64"%"PRIx64"\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); + if(smart_log_ver > 2) { + printf(" Errata Version Field %d\n", + (__u8)log_data[SCAO_EVF]); + printf(" Point Version Field %"PRIu16"\n", + (uint16_t)log_data[SCAO_PVF]); + printf(" Minor Version Field %"PRIu16"\n", + (uint16_t)log_data[SCAO_MIVF]); + printf(" Major Version Field %d\n", + (__u8)log_data[SCAO_MAVF]); + printf(" NVMe Errata Version %d\n", + (__u8)log_data[SCAO_NEV]); + printf(" PCIe Link Retraining Count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); + } + printf("\n"); +} + +static void ocp_print_C0_log_json(void *data) +{ + __u8 *log_data = (__u8*)data; + struct json_object *root; + struct json_object *pmuw; + struct json_object *pmur; + uint16_t smart_log_ver = 0; + + root = json_create_object(); + pmuw = json_create_object(); + pmur = json_create_object(); + + json_object_add_value_uint64(pmuw, "hi", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_uint64(pmuw, "lo", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_object(root, "Physical media units written", pmuw); + json_object_add_value_uint64(pmur, "hi", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_uint64(pmur, "lo", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_object(root, "Physical media units read", pmur); + json_object_add_value_uint64(root, "Bad user nand blocks - Raw", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); + json_object_add_value_uint(root, "Bad user nand blocks - Normalized", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); + json_object_add_value_uint64(root, "Bad system nand blocks - Raw", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); + json_object_add_value_uint(root, "Bad system nand blocks - Normalized", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); + json_object_add_value_uint64(root, "XOR recovery count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); + json_object_add_value_uint64(root, "Uncorrectable read error count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); + json_object_add_value_uint64(root, "Soft ecc error count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); + json_object_add_value_uint(root, "End to end corrected errors", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); + json_object_add_value_uint(root, "End to end detected errors", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); + json_object_add_value_uint(root, "System data percent used", + (__u8)log_data[SCAO_SDPU]); + json_object_add_value_uint64(root, "Refresh counts", + (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF)); + json_object_add_value_uint(root, "Max User data erase counts", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); + json_object_add_value_uint(root, "Min User data erase counts", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); + json_object_add_value_uint(root, "Number of Thermal throttling events", + (__u8)log_data[SCAO_NTTE]); + json_object_add_value_uint(root, "Current throttling status", + (__u8)log_data[SCAO_CTS]); + json_object_add_value_uint64(root, "PCIe correctable error count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); + json_object_add_value_uint(root, "Incomplete shutdowns", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); + json_object_add_value_uint(root, "Percent free blocks", + (__u8)log_data[SCAO_PFB]); + json_object_add_value_uint(root, "Capacitor health", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); + json_object_add_value_uint64(root, "Unaligned I/O", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); + json_object_add_value_uint64(root, "Security Version Number", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); + json_object_add_value_uint64(root, "NUSE - Namespace utilization", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); + json_object_add_value_uint(root, "PLP start count", + int128_to_double(&log_data[SCAO_PSC])); + json_object_add_value_uint64(root, "Endurance estimate", + int128_to_double(&log_data[SCAO_EEST])); + smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); + json_object_add_value_uint(root, "Log page version", smart_log_ver); + char guid[40]; + memset((void*)guid, 0, 40); + sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); + json_object_add_value_string(root, "Log page GUID", guid); + if(smart_log_ver > 2){ + json_object_add_value_uint(root, "Errata Version Field", + (__u8)log_data[SCAO_EVF]); + json_object_add_value_uint(root, "Point Version Field", + (uint16_t)log_data[SCAO_PVF]); + json_object_add_value_uint(root, "Minor Version Field", + (uint16_t)log_data[SCAO_MIVF]); + json_object_add_value_uint(root, "Major Version Field", + (__u8)log_data[SCAO_MAVF]); + json_object_add_value_uint(root, "NVMe Errata Version", + (__u8)log_data[SCAO_NEV]); + json_object_add_value_uint(root, "PCIe Link Retraining Count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); + } + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static int get_c0_log_page(int fd, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i; + + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : OCP : invalid output format\n"); + return fmt; + } + + if ((data = (__u8 *) malloc(sizeof(__u8) * C0_SMART_CLOUD_ATTR_LEN)) == NULL) { + fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof (__u8) * C0_SMART_CLOUD_ATTR_LEN); + + ret = nvme_get_log_simple(fd, C0_SMART_CLOUD_ATTR_OPCODE, + C0_SMART_CLOUD_ATTR_LEN, data); + + if (strcmp(format, "json")) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(ret, false), ret); + + if (ret == 0) { + + /* check log page guid */ + /* Verify GUID matches */ + for (i=0; i<16; i++) { + if (scao_guid[i] != data[SCAO_LPG + i]) { + fprintf(stderr, "ERROR : OCP : Unknown GUID in C0 Log Page data\n"); + int j; + fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", scao_guid[j]); + } + fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", data[SCAO_LPG + j]); + } + fprintf(stderr, "\n"); + + ret = -1; + goto out; + } + } + + /* print the data */ + if (!data) { + fprintf(stderr, "ERROR : OCP : Invalid buffer to read 0xC0 log\n"); + ret = -1; + goto out; + } + switch (fmt) { + case NORMAL: + ocp_print_C0_log_normal(data); + break; + case JSON: + ocp_print_C0_log_json(data); + break; + } + } else { + fprintf(stderr, "ERROR : OCP : Unable to read C0 data from buffer\n"); + } + +out: + free(data); + return ret; +} + +static int ocp_smart_add_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Retrieve latency monitor log data."; + int fd; + int ret = 0; + + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, "output Format: normal|json"), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; + + ret = get_c0_log_page(fd, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n", + ret); + + return ret; +} + +static int ocp_print_C3_log_normal(int fd, struct ssd_latency_monitor_log *log_data) +{ + printf("-Latency Monitor/C3 Log Page Data- \n"); + printf(" Controller : %s\n", devicename); + int i, j; + int pos = 0; + char ts_buf[128]; + + printf(" Feature Status 0x%x \n", + log_data->feature_status); + printf(" Active Bucket Timer %d min \n", + C0_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer)); + printf(" Active Bucket Timer Threshold %d min \n", + C0_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer_threshold)); + printf(" Active Threshold A %d ms \n", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_a+1)); + printf(" Active Threshold B %d ms \n", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_b+1)); + printf(" Active Threshold C %d ms \n", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_c+1)); + printf(" Active Threshold D %d ms \n", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_d+1)); + printf(" Active Latency Minimum Window %d ms \n", + C0_MINIMUM_WINDOW_INCREMENT * + le16_to_cpu(log_data->active_latency_min_window)); + printf(" Active Latency Stamp Units %d \n", + le16_to_cpu(log_data->active_latency_stamp_units)); + printf(" Static Latency Stamp Units %d \n", + le16_to_cpu(log_data->static_latency_stamp_units)); + printf(" Debug Log Trigger Enable %d \n", + le16_to_cpu(log_data->debug_log_trigger_enable)); + + printf(" Read Write Deallocate/Trim \n"); + for (i = 0; i <= 3; i++) { + printf(" Active Latency Mode: Bucket %d %27d %27d %27d \n", + i, + log_data->active_latency_config & (1 << pos), + log_data->active_latency_config & (1 << pos), + log_data->active_latency_config & (1 << pos)); + } + printf("\n"); + for (i = 0; i <= 3; i++) { + printf(" Active Bucket Counter: Bucket %d %27d %27d %27d \n", + i, + le32_to_cpu(log_data->active_bucket_counter[i][READ]), + le32_to_cpu(log_data->active_bucket_counter[i][WRITE]), + le32_to_cpu(log_data->active_bucket_counter[i][TRIM])); + } + + for (i = 0; i <= 3; i++) { + printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n", + i, + le16_to_cpu(log_data->active_measured_latency[i][READ]), + le16_to_cpu(log_data->active_measured_latency[i][WRITE]), + le16_to_cpu(log_data->active_measured_latency[i][TRIM])); + } + + for (i = 0; i <= 3; i++) { + printf(" Active Latency Time Stamp: Bucket %d ", i); + for (j = 0; j <= 2; j++) { + if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) + printf(" N/A "); + else { + convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf); + printf("%s ", ts_buf); + } + } + printf("\n"); + } + + for (i = 0; i <= 3; i++) { + printf(" Static Bucket Counter: Bucket %d %27d %27d %27d \n", + i, + le32_to_cpu(log_data->static_bucket_counter[i][READ]), + le32_to_cpu(log_data->static_bucket_counter[i][WRITE]), + le32_to_cpu(log_data->static_bucket_counter[i][TRIM])); + } + + for (i = 0; i <= 3; i++) { + printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n", + i, + le16_to_cpu(log_data->static_measured_latency[i][READ]), + le16_to_cpu(log_data->static_measured_latency[i][WRITE]), + le16_to_cpu(log_data->static_measured_latency[i][TRIM])); + } + + for (i = 0; i <= 3; i++) { + printf(" Static Latency Time Stamp: Bucket %d ", i); + for (j = 0; j <= 2; j++) { + if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) + printf(" N/A "); + else { + convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf); + printf("%s ", ts_buf); + } + } + printf("\n"); + } + + return 0; +} + +static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data) +{ + int i, j; + int pos = 0; + char buf[128]; + char ts_buf[128]; + char *operation[3] = {"Read", "Write", "Trim"}; + struct json_object *root; + root = json_create_object(); + + json_object_add_value_uint(root, "Feature Status", + log_data->feature_status); + json_object_add_value_uint(root, "Active Bucket Timer", + C0_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer)); + json_object_add_value_uint(root, "Active Bucket Timer Threshold", + C0_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer_threshold)); + json_object_add_value_uint(root, "Active Threshold A", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_a+1)); + json_object_add_value_uint(root, "Active Threshold B", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_b+1)); + json_object_add_value_uint(root, "Active Threshold C", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_c+1)); + json_object_add_value_uint(root, "Active Threshold D", + C0_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_d+1)); + json_object_add_value_uint(root, "Active Lantency Minimum Window", + C0_MINIMUM_WINDOW_INCREMENT * + le16_to_cpu(log_data->active_latency_min_window)); + json_object_add_value_uint(root, "Active Latency Stamp Units", + le16_to_cpu(log_data->active_latency_stamp_units)); + json_object_add_value_uint(root, "Static Latency Stamp Units", + le16_to_cpu(log_data->static_latency_stamp_units)); + json_object_add_value_uint(root, "Debug Log Trigger Enable", + le16_to_cpu(log_data->debug_log_trigger_enable)); + + for (i = 0; i <= 3; i++) { + struct json_object *bucket; + bucket = json_create_object(); + sprintf(buf, "Active Latency Mode: Bucket %d", i); + for (j = 0; j <= 2; j++) { + json_object_add_value_uint(bucket, operation[j], + log_data->active_latency_config & (1 << pos)); + } + json_object_add_value_object(root, buf, bucket); + } + for (i = 0; i <= 3; i++) { + struct json_object *bucket; + bucket = json_create_object(); + sprintf(buf, "Active Bucket Counter: Bucket %d", i); + for (j = 0; j <= 2; j++) { + json_object_add_value_uint(bucket, operation[j], + le32_to_cpu(log_data->active_bucket_counter[i][j])); + } + json_object_add_value_object(root, buf, bucket); + } + for (i = 0; i <= 3; i++) { + struct json_object *bucket; + bucket = json_create_object(); + sprintf(buf, "Active Measured Latency: Bucket %d", i); + for (j = 0; j <= 2; j++) { + json_object_add_value_uint(bucket, operation[j], + le16_to_cpu(log_data->active_measured_latency[i][j])); + } + json_object_add_value_object(root, buf, bucket); + } + for (i = 0; i <= 3; i++) { + struct json_object *bucket; + bucket = json_create_object(); + sprintf(buf, "Active Latency Time Stamp: Bucket %d", i); + for (j = 0; j <= 2; j++) { + if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) + json_object_add_value_string(bucket, operation[j], "NA"); + else { + convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf); + json_object_add_value_string(bucket, operation[j], ts_buf); + } + } + json_object_add_value_object(root, buf, bucket); + } + for (i = 0; i <= 3; i++) { + struct json_object *bucket; + bucket = json_create_object(); + sprintf(buf, "Static Bucket Counter: Bucket %d", i); + for (j = 0; j <= 2; j++) { + json_object_add_value_uint(bucket, operation[j], + le32_to_cpu(log_data->static_bucket_counter[i][j])); + } + json_object_add_value_object(root, buf, bucket); + } + for (i = 0; i <= 3; i++) { + struct json_object *bucket; + bucket = json_create_object(); + sprintf(buf, "Static Measured Latency: Bucket %d", i); + for (j = 0; j <= 2; j++) { + json_object_add_value_uint(bucket, operation[j], + le16_to_cpu(log_data->static_measured_latency[i][j])); + } + json_object_add_value_object(root, buf, bucket); + } + for (i = 0; i <= 3; i++) { + struct json_object *bucket; + bucket = json_create_object(); + sprintf(buf, "Static Latency Time Stamp: Bucket %d", i); + for (j = 0; j <= 2; j++) { + if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) + json_object_add_value_string(bucket, operation[j], "NA"); + else { + convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf); + json_object_add_value_string(bucket, operation[j], ts_buf); + } + } + json_object_add_value_object(root, buf, bucket); + } + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static int get_c3_log_page(int fd, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i; + struct ssd_latency_monitor_log *log_data; + + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : OCP : invalid output format\n"); + return fmt; + } + + if ((data = (__u8 *) malloc(sizeof(__u8) * C3_LATENCY_MON_LOG_BUF_LEN)) == NULL) { + fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof (__u8) * C3_LATENCY_MON_LOG_BUF_LEN); + + ret = nvme_get_log_simple(fd, C3_LATENCY_MON_OPCODE, + C3_LATENCY_MON_LOG_BUF_LEN, data); + + if (strcmp(format, "json")) + fprintf(stderr, + "NVMe Status:%s(%x)\n", + nvme_status_to_string(ret, false), + ret); + + if (ret == 0) { + log_data = (struct ssd_latency_monitor_log*)data; + + /* check log page version */ + if (log_data->log_page_version != C3_LATENCY_MON_VERSION) { + fprintf(stderr, + "ERROR : OCP : invalid latency monitor version\n"); + ret = -1; + goto out; + } + + /* check log page guid */ + /* Verify GUID matches */ + for (i=0; i<16; i++) { + if (lat_mon_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr,"ERROR : OCP : Unknown GUID in C3 Log Page data\n"); + int j; + fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", lat_mon_guid[j]); + } + fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", log_data->log_page_guid[j]); + } + fprintf(stderr, "\n"); + + ret = -1; + goto out; + } + } + + /* print the data */ + if (!log_data) { + fprintf(stderr, + "ERROR : OCP : Invalid C3 log data buffer\n"); + ret = -1; + goto out; + } + switch (fmt) { + case NORMAL: + ocp_print_C3_log_normal(fd, log_data); + break; + case JSON: + ocp_print_C3_log_json(log_data); + break; + } + } else { + fprintf(stderr, + "ERROR : OCP : Unable to read C3 data from buffer\n"); + } + +out: + free(data); + return ret; +} + +static int ocp_latency_monitor_log(int argc, char **argv, struct command *command, + struct plugin *plugin) +{ + const char *desc = "Retrieve latency monitor log data."; + int fd; + int ret = 0; + + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, + "output Format: normal|json"), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; + + ret = get_c3_log_page(fd, cfg.output_format); + if (ret) + fprintf(stderr, + "ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n", + ret); + + return ret; +} diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h new file mode 100644 index 0000000..19378cd --- /dev/null +++ b/plugins/ocp/ocp-nvme.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2022 Meta Platforms, Inc. + * + * Authors: Arthur Shau <arthurshau@fb.com>, + * Wei Zhang <wzhang@fb.com>, + * Venkat Ramesh <venkatraghavan@fb.com> + */ +#undef CMD_INC_FILE +#define CMD_INC_FILE plugins/ocp/ocp-nvme + +#if !defined(OCP_NVME) || defined(CMD_HEADER_MULTI_READ) +#define OCP_NVME + +#include "cmd.h" + +PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION), + COMMAND_LIST( + ENTRY("smart-add-log", "Retrieve extended SMART Information", ocp_smart_add_log) + ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log) + ) +); + +#endif + +#include "define_cmd.h" diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index df7f9a3..a6aaad5 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -6,21 +6,16 @@ #include <linux/fs.h> #include <inttypes.h> #include <asm/byteorder.h> -#include <sys/ioctl.h> #include <sys/sysinfo.h> #include <sys/stat.h> #include <unistd.h> -#include "linux/nvme_ioctl.h" - +#include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" -#include "nvme-status.h" +#include "libnvme.h" #include "plugin.h" - -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "sfx-nvme.h" @@ -114,38 +109,38 @@ struct nvme_additional_smart_log { int nvme_change_cap(int fd, __u32 nsid, __u64 capacity) { - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_change_cap, .nsid = nsid, .cdw10 = (capacity & 0xffffffff), .cdw11 = (capacity >> 32), }; - return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value) { - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_sfx_set_features, .nsid = nsid, .cdw10 = fid, .cdw11 = value, }; - return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result) { int err = 0; - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_sfx_get_features, .nsid = nsid, .cdw10 = fid, }; - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd); + err = nvme_submit_admin_passthru(fd, &cmd, NULL); if (!err && result) { *result = cmd.result; } @@ -343,8 +338,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, const char *json= "Dump output in json format"; struct config { __u32 namespace_id; - int raw_binary; - int json; + bool raw_binary; + bool json; }; struct config cfg = { @@ -361,7 +356,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, NVME_NO_LOG_LSP, + err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, sizeof(smart_log), (void *)&smart_log); if (!err) { if (cfg.json) @@ -372,8 +367,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, 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); + nvme_show_status(err); return err; } @@ -428,8 +422,8 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct const char *raw = "dump output in binary format"; const char *write = "Get write statistics (read default)"; struct config { - int raw_binary; - int write; + bool raw_binary; + bool write; }; struct config cfg = { @@ -443,22 +437,20 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, NVME_NO_LOG_LSP, - sizeof(stats), (void *)&stats); + err = nvme_get_log_simple(fd, cfg.write ? 0xc3 : 0xc1, sizeof(stats), (void *)&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); + nvme_show_status(err); return err; } int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data) { - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_get_log_page, .nsid = nsid, .addr = (__u64)(uintptr_t) data, @@ -470,7 +462,7 @@ int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data cmd.cdw10 = log_id | (numdl << 16); cmd.cdw11 = numdu; - return nvme_submit_admin_passthru(fd, &cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } /** @@ -583,8 +575,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct if (err < 0) { perror("get-bad-block"); } else if (err != 0) { - fprintf(stderr, "NVMe IO command error:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else { bd_table_show(data_buf, buf_size); printf("ScaleFlux get bad block table: success\n"); @@ -616,8 +607,8 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu const char *raw = "dump output in binary format"; const char *json= "Dump output in json format"; struct config { - int raw_binary; - int json; + bool raw_binary; + bool json; }; struct config cfg; @@ -745,9 +736,9 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin struct config { __u64 cap_in_byte; __u32 capacity_in_gb; - int raw_binary; - int json; - int force; + bool raw_binary; + bool json; + bool force; }; struct config cfg = { @@ -790,8 +781,7 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin if (err < 0) perror("sfx-change-cap"); else if (err != 0) - fprintf(stderr, "NVMe IO command error:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); else { printf("ScaleFlux change-capacity: success\n"); ioctl(fd, BLKRRPART); @@ -863,7 +853,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl __u32 namespace_id; __u32 feature_id; __u32 value; - __u32 force; + bool force; }; struct config cfg = { .namespace_id = 1, @@ -902,14 +892,12 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) { if (cfg.namespace_id != 0xffffffff) { - err = nvme_identify_ns(fd, cfg.namespace_id, 0, &ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &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); + nvme_show_status(err); return err; } /* @@ -941,8 +929,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id, sfx_feature_to_string(cfg.feature_id), cfg.value); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -990,8 +977,7 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id, sfx_feature_to_string(cfg.feature_id), result); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); return err; diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c index 9512cda..5f6ce90 100644 --- a/plugins/seagate/seagate-nvme.c +++ b/plugins/seagate/seagate-nvme.c @@ -26,16 +26,14 @@ #include <stdlib.h> #include <unistd.h> #include <inttypes.h> -#include <sys/ioctl.h> #include <sys/stat.h> #include <ctype.h> -#include "linux/nvme_ioctl.h" +#include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD @@ -176,8 +174,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, }; fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, 1, 0xc5, false, NVME_NO_LOG_LSP, - sizeof(logPageMap), &logPageMap); + err = nvme_get_log_simple(fd, 0xc5, sizeof(logPageMap), &logPageMap); if (!err) { if (strcmp(cfg.output_format,"json")) { printf ("Seagate Supported Log-pages count :%d\n", @@ -201,8 +198,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, } if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -739,8 +735,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi if (strcmp(cfg.output_format,"json")) printf("Seagate Extended SMART Information :\n"); - err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP, - sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); if (!err) { if (strcmp(cfg.output_format,"json")) { printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); @@ -762,8 +757,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi * Next get Log Page 0xCF */ - err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP, - sizeof(logPageCF), &logPageCF); + err = nvme_get_log_simple(fd, 0xCF, sizeof(logPageCF), &logPageCF); if (!err) { if(strcmp(cfg.output_format,"json")) { /*printf("Seagate DRAM Supercap SMART Attributes :\n");*/ @@ -778,8 +772,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi } else if (!strcmp(cfg.output_format, "json")) json_print_object(root, NULL); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -844,7 +837,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin if(strcmp(cfg.output_format,"json")) printf("Seagate Temperature Stats Information :\n"); /*STEP-1 : Get Current Temperature from SMART */ - err = nvme_smart_log(fd, 0xffffffff, &smart_log); + err = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -860,8 +853,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin } /* STEP-2 : Get Max temperature form Ext SMART-id 194 */ - err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP, - sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); if (!err) { for(index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) { @@ -880,11 +872,9 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin } } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); - cf_err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP, - sizeof(ExtdSMARTInfo), &logPageCF); + cf_err = nvme_get_log_simple(fd, 0xCF, sizeof(ExtdSMARTInfo), &logPageCF); if(!cf_err) { scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature; @@ -1013,8 +1003,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct if(strcmp(cfg.output_format,"json")) printf("Seagate PCIe error counters Information :\n"); - err = nvme_get_log(fd, 1, 0xCB, false, NVME_NO_LOG_LSP, - sizeof(pcieErrorLog), &pcieErrorLog); + err = nvme_get_log_simple(fd, 0xCB, sizeof(pcieErrorLog), &pcieErrorLog); if (!err) { if(strcmp(cfg.output_format,"json")) { print_vs_pcie_error_log(pcieErrorLog); @@ -1022,7 +1011,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct json_vs_pcie_error_log(pcieErrorLog); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -1034,10 +1023,9 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c const char *save = "specifies that the controller shall save the attribute"; int err, fd; __u32 result; - void *buf = NULL; struct config { - int save; + bool save; }; struct config cfg = { @@ -1051,7 +1039,7 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c fd = parse_and_open(argc, argv, desc, opts); - err = nvme_set_feature(fd, 0, 0xE1, 0xCB, 0, cfg.save, 0, 0, buf, &result); + err = nvme_set_features_simple(fd, 0xE1, 0, 0xCB, cfg.save, &result); if (err < 0) { perror("set-feature"); @@ -1080,7 +1068,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug struct config { __u32 namespace_id; __u32 log_id; - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -1101,8 +1089,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug dump_fd = STDOUT_FILENO; cfg.log_id = (cfg.log_id << 8) | 0x07; - err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id, - NVME_NO_LOG_LSP, offset, 0, false, + err = nvme_get_nsid_log(fd, false, cfg.log_id, cfg.namespace_id, sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; @@ -1119,8 +1106,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug } else seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); else perror("log page"); @@ -1141,9 +1127,24 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug memset(log, 0, blksToGet * 512); - err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id, - NVME_NO_LOG_LSP, offset, 0, false, - blksToGet * 512, (void *)log); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = cfg.log_id, + .nsid = cfg.namespace_id, + .lpo = offset, + .lsp = 0, + .lsi = 0, + .rae = true, + .uuidx = 0, + .csi = NVME_CSI_NVM, + .ot = false, + .len = blksToGet * 512, + .log = (void *)log, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_get_log(&args); if (!err) { offset += blksToGet * 512; @@ -1154,8 +1155,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug } else seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); else perror("log page"); @@ -1182,7 +1182,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug struct config { __u32 namespace_id; - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -1202,8 +1202,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug dump_fd = STDOUT_FILENO; log_id = 0x08; - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, + err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id, sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; @@ -1219,8 +1218,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug } else seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); else perror("log page"); @@ -1241,9 +1239,24 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug memset(log, 0, blksToGet * 512); - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, - blksToGet * 512, (void *)log); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = log_id, + .nsid = cfg.namespace_id, + .lpo = offset, + .lsp = 0, + .lsi = 0, + .rae = true, + .uuidx = 0, + .csi = NVME_CSI_NVM, + .ot = false, + .len = blksToGet * 512, + .log = (void *)log, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_get_log(&args); if (!err) { offset += blksToGet * 512; @@ -1254,8 +1267,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug } else seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); else perror("log page"); @@ -1327,8 +1339,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl } log_id = 0x08; - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, + err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id, sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; @@ -1340,8 +1351,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl */ seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); else perror("log page"); @@ -1363,17 +1373,31 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl memset(log, 0, blksToGet * 512); - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, - blksToGet * 512, (void *)log); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = log_id, + .nsid = cfg.namespace_id, + .lpo = offset, + .lsp = 0, + .lsi = 0, + .rae = true, + .uuidx = 0, + .csi = NVME_CSI_NVM, + .ot = false, + .len = blksToGet * 512, + .log = (void *)log, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_get_log(&args); if (!err) { offset += blksToGet * 512; seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); else perror("log page"); diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c index 1909e45..d79b119 100644 --- a/plugins/shannon/shannon-nvme.c +++ b/plugins/shannon/shannon-nvme.c @@ -5,16 +5,12 @@ #include <unistd.h> #include <inttypes.h> -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" - -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "shannon-nvme.h" @@ -127,7 +123,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, const char *raw = "dump output in binary format"; struct config { __u32 namespace_id; - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -141,8 +137,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, }; fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) show_shannon_smart_log(&smart_log, cfg.namespace_id, devicename); @@ -150,8 +146,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, 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); + nvme_show_status(err); return err; } @@ -181,17 +176,17 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st struct config { __u32 namespace_id; - enum nvme_feat feature_id; + enum nvme_features_id feature_id; __u8 sel; __u32 cdw11; __u32 data_len; - int raw_binary; - int human_readable; + bool raw_binary; + bool human_readable; }; struct config cfg = { .namespace_id = 1, - .feature_id = NVME_FEAT_NONE, + .feature_id = 0, .sel = 0, .cdw11 = 0, .data_len = 0, @@ -231,9 +226,22 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st memset(buf, 0, cfg.data_len); } - err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11, 0, - cfg.data_len, buf, &result); + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = cfg.feature_id, + .nsid = cfg.namespace_id, + .sel = cfg.sel, + .cdw11 = cfg.cdw11, + .uuidx = 0, + .data_len = cfg.data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_get_features(&args); if (!err) { +#if 0 printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id, nvme_feature_to_string(cfg.feature_id), nvme_select_to_string(cfg.sel), result); @@ -247,9 +255,9 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st d_raw(buf, cfg.data_len); } } +#endif } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); if (buf) free(buf); return err; @@ -285,7 +293,7 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st __u32 feature_id; __u32 value; __u32 data_len; - int save; + bool save; }; struct config cfg = { @@ -343,20 +351,35 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st } } - err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, - 0, cfg.save, 0, cfg.data_len, buf, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = cfg.feature_id, + .nsid = cfg.namespace_id, + .cdw11 = cfg.value, + .cdw12 = 0, + .save = cfg.save, + .uuidx = 0, + .cdw15 = 0, + .data_len = cfg.data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err < 0) { perror("set-feature"); goto free; } if (!err) { +#if 0 printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, nvme_feature_to_string(cfg.feature_id), cfg.value); +#endif 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); + nvme_show_status(err); free: if (buf) diff --git a/plugins/shannon/shannon-nvme.h b/plugins/shannon/shannon-nvme.h index db25828..46fc697 100644 --- a/plugins/shannon/shannon-nvme.h +++ b/plugins/shannon/shannon-nvme.h @@ -9,10 +9,10 @@ PLUGIN(NAME("shannon", "Shannon vendor specific extensions", NVME_VERSION), COMMAND_LIST( ENTRY("smart-log-add", "Retrieve Shannon SMART Log, show it", get_additional_smart_log) - ENTRY("get-feature-add", "Get Shannon feature and show the resulting value", get_additional_feature) - ENTRY("set-feature-add", "Set a Shannon feature and show the resulting value", set_additional_feature) - ENTRY("id-ctrl", "Shannon NVMe Identify Controller", shannon_id_ctrl) - ) + ENTRY("set-additioal-feature", "Set additional Shannon feature", set_additional_feature) + ENTRY("get-additional-feature", "Get additional Shannon feature", get_additional_feature) + ENTRY("id-ctrl", "Retrieve Shannon ctrl id, show it", shannon_id_ctrl) + ) ); #endif diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c index cba1af8..fd2e9c1 100644 --- a/plugins/toshiba/toshiba-nvme.c +++ b/plugins/toshiba/toshiba-nvme.c @@ -7,13 +7,11 @@ #include <inttypes.h> #include <stdbool.h> -#include "linux/nvme_ioctl.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "toshiba-nvme.h" @@ -67,7 +65,7 @@ static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* da int err = 0; __u32 result; - err = nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd, + err = nvme_admin_passthru(fd, opcode, flags, rsvd, namespace_id, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, @@ -392,8 +390,7 @@ static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page, if (err) { goto end; } - err = nvme_get_log(fd, namespace_id, log_page, false, - NVME_NO_LOG_LSP, log_len, log); + err = nvme_get_nsid_log(fd, false, log_page, namespace_id, log_len, log); if (err) { fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__, log_page); @@ -476,7 +473,7 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin fprintf(stderr, "%s: couldn't get vendor log 0x%x\n", __func__, cfg.log); end: if (err > 0) - fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -518,8 +515,8 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi if (err < 0) fprintf(stderr, "%s: couldn't get fw log \n", __func__); if (err > 0) - fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, - nvme_status_to_string(err), err); + nvme_show_status(err); + return err; } @@ -550,14 +547,27 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd, if (err) goto end; - err = nvme_set_feature(fd, namespace_id, feature_id, value, cdw12, save, - 0, 0, NULL, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = feature_id, + .nsid = namespace_id, + .cdw11 = value, + .cdw12 = cdw12, + .save = save, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err) fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", __func__); end: if (err > 0) - fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, - nvme_status_to_string(err), err); + nvme_show_status(err); return err; } diff --git a/plugins/transcend/transcend-nvme.c b/plugins/transcend/transcend-nvme.c index dbb56be..85d3cac 100644 --- a/plugins/transcend/transcend-nvme.c +++ b/plugins/transcend/transcend-nvme.c @@ -5,13 +5,9 @@ #include <unistd.h> #include <inttypes.h> -#include "linux/nvme_ioctl.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "argconfig.h" -#include "suffix.h" #define CREATE_CMD #include "transcend-nvme.h" @@ -37,7 +33,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu printf("\nDevice not found \n");; return -1; } - result = nvme_smart_log(fd, 0xffffffff, &smart_log); + result = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log); if (!result) { printf("Transcend NVME heath value: "); percent_used =smart_log.percent_used; @@ -82,7 +78,7 @@ static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin nvmecmd.cdw12=DW12_BAD_BLOCK; nvmecmd.addr = (__u64)(uintptr_t)data; nvmecmd.data_len = 0x1; - result = nvme_submit_admin_passthru(fd,&nvmecmd); + result = nvme_submit_admin_passthru(fd, &nvmecmd, NULL); if(!result) { int badblock = data[0]; printf("Transcend NVME badblock count: %d\n",badblock); diff --git a/plugins/virtium/virtium-nvme.c b/plugins/virtium/virtium-nvme.c index a194a5f..7c2ebec 100644 --- a/plugins/virtium/virtium-nvme.c +++ b/plugins/virtium/virtium-nvme.c @@ -9,13 +9,10 @@ #include <time.h> #include <locale.h> -#include "linux/nvme_ioctl.h" +#include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "argconfig.h" -#include "suffix.h" #define CREATE_CMD #include "virtium-nvme.h" @@ -35,7 +32,7 @@ struct vtview_log_header { char test_name[256]; long int time_stamp; struct nvme_id_ctrl raw_ctrl; - struct nvme_firmware_log_page raw_fw; + struct nvme_firmware_slot raw_fw; }; struct vtview_smart_log_entry { @@ -124,6 +121,8 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l double capacity; char *curlocale; char *templocale; + __u8 lba_index; + nvme_id_ns_flbas_to_lbaf_inuse(smart->raw_ns.flbas, &lba_index); curlocale = setlocale(LC_ALL, NULL); templocale = strdup(curlocale); @@ -133,7 +132,7 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l setlocale(LC_ALL, "C"); - long long int lba = 1 << smart->raw_ns.lbaf[(smart->raw_ns.flbas & 0x0f)].ds; + long long int lba = 1 << smart->raw_ns.lbaf[lba_index].ds; capacity = le64_to_cpu(smart->raw_ns.nsze) * lba; snprintf(tempbuff, sizeof(tempbuff), "log;%s;%lu;%s;%s;%-.*s;", smart->raw_ctrl.sn, smart->time_stamp, smart->path, @@ -273,7 +272,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi struct vtview_smart_log_entry smart; char filename[256] = ""; int ret = 0; - int nsid = 0; + unsigned nsid = 0; memset(smart.path, 0, sizeof(smart.path)); strcpy(smart.path, path); @@ -283,14 +282,14 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi strcpy(filename, cfg->output_file); smart.time_stamp = time(NULL); - nsid = nvme_get_nsid(fd); + ret = nvme_get_nsid(fd, &nsid); - if (nsid <= 0) { + if (ret < 0) { printf("Cannot read namespace-id\n"); return -1; } - ret = nvme_identify_ns(fd, nsid, 0, &smart.raw_ns); + ret = nvme_identify_ns(fd, nsid, &smart.raw_ns); if (ret) { printf("Cannot read namespace identify\n"); return -1; @@ -302,7 +301,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi return -1; } - ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart.raw_smart); + ret = nvme_get_log_smart(fd, NVME_NSID_ALL, true, &smart.raw_smart); if (ret) { printf("Cannot read device SMART log\n"); return -1; @@ -343,7 +342,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str return -1; } - ret = nvme_fw_log(fd, &header.raw_fw); + ret = nvme_get_log_fw_slot(fd, true, &header.raw_fw); if (ret) { printf("Cannot read device firmware log\n"); return -1; @@ -445,7 +444,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl) vt_convert_data_buffer_to_hex_string(&buf[16], 4, true, s); printf("%9sh", s); - temp = ctrl->psd[i].idle_scale; + temp = ctrl->psd[i].ips; snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01)); printf("%3sb", s); @@ -454,7 +453,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl) vt_convert_data_buffer_to_hex_string(&buf[20], 4, true, s); printf("%9sh", s); - temp = ctrl->psd[i].active_work_scale; + temp = ctrl->psd[i].apws; snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01)); printf("%3sb", s); snprintf(s, sizeof(s), "%u%u%u", (((unsigned char)temp) & 0x01), (((unsigned char)temp >> 1) & 0x01), (((unsigned char)temp >> 2) & 0x01)); diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index d5e17b8..486ee36 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -30,18 +30,13 @@ #include <fcntl.h> #include <unistd.h> -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "nvme-status.h" +#include "linux/types.h" +#include "nvme-print.h" -#include "argconfig.h" -#include "suffix.h" -#include <sys/ioctl.h> #define CREATE_CMD #include "wdc-nvme.h" #include "wdc-utils.h" @@ -80,19 +75,27 @@ #define WDC_NVME_SN650_DEV_ID_2 0x2702 #define WDC_NVME_SN650_DEV_ID_3 0x2720 #define WDC_NVME_SN650_DEV_ID_4 0x2721 -#define WDC_NVME_SN450_DEV_ID_1 0x2712 -#define WDC_NVME_SN450_DEV_ID_2 0x2713 +#define WDC_NVME_SN655_DEV_ID 0x2722 +#define WDC_NVME_SN560_DEV_ID_1 0x2712 +#define WDC_NVME_SN560_DEV_ID_2 0x2713 +#define WDC_NVME_SN560_DEV_ID_3 0x2714 #define WDC_NVME_SXSLCL_DEV_ID 0x2001 #define WDC_NVME_SN520_DEV_ID 0x5003 #define WDC_NVME_SN520_DEV_ID_1 0x5004 #define WDC_NVME_SN520_DEV_ID_2 0x5005 +#define WDC_NVME_SN530_DEV_ID 0x5009 #define WDC_NVME_SN720_DEV_ID 0x5002 #define WDC_NVME_SN730A_DEV_ID 0x5006 #define WDC_NVME_SN730B_DEV_ID 0x3714 #define WDC_NVME_SN730B_DEV_ID_1 0x3734 +#define WDC_NVME_SN740_DEV_ID 0x5015 +#define WDC_NVME_SN740_DEV_ID_1 0x5016 +#define WDC_NVME_SN740_DEV_ID_2 0x5017 +#define WDC_NVME_SN740_DEV_ID_3 0x5025 #define WDC_NVME_SN340_DEV_ID 0x500d #define WDC_NVME_ZN350_DEV_ID 0x5010 #define WDC_NVME_ZN350_DEV_ID_1 0x5018 +#define WDC_NVME_SN810_DEV_ID 0x5011 #define WDC_DRIVE_CAP_CAP_DIAG 0x0000000000000001 #define WDC_DRIVE_CAP_INTERNAL_LOG 0x0000000000000002 @@ -129,7 +132,10 @@ #define WDC_DRIVE_CAP_DUI_DATA 0x0000000200000000 #define WDC_SN730B_CAP_VUC_LOG 0x0000000400000000 #define WDC_DRIVE_CAP_DUI 0x0000000800000000 -#define WDC_DRIVE_CAP_PURGE 0x0000001000000000 +#define WDC_DRIVE_CAP_PURGE 0x0000001000000000 +#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE 0x0000002000000000 +#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE 0x0000004000000000 +#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE 0x0000008000000000 #define WDC_DRIVE_CAP_SMART_LOG_MASK (WDC_DRIVE_CAP_C0_LOG_PAGE | WDC_DRIVE_CAP_C1_LOG_PAGE | \ WDC_DRIVE_CAP_CA_LOG_PAGE | WDC_DRIVE_CAP_D0_LOG_PAGE) #define WDC_DRIVE_CAP_CLEAR_PCIE_MASK (WDC_DRIVE_CAP_CLEAR_PCIE | \ @@ -164,6 +170,7 @@ #define WDC_CUSTOMER_ID_0x1004 0x1004 #define WDC_CUSTOMER_ID_0x1008 0x1008 #define WDC_CUSTOMER_ID_0x1304 0x1304 +#define WDC_INVALID_CUSTOMER_ID -1 #define WDC_ALL_PAGE_MASK 0xFFFF #define WDC_C0_PAGE_MASK 0x0001 @@ -305,7 +312,7 @@ /* CA Log Page */ #define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE 0xCA #define WDC_FB_CA_LOG_BUF_LEN 0x80 -#define WDC_BD_CA_LOG_BUF_LEN 0x9C +#define WDC_BD_CA_LOG_BUF_LEN 0xA0 /* Added 4 padding bytes to resolve build warning messages */ /* C0 EOL Status Log Page */ #define WDC_NVME_GET_EOL_STATUS_LOG_OPCODE 0xC0 @@ -323,6 +330,7 @@ #define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID 0xC2 #define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN 0x1000 #define WDC_MAX_NUM_ACT_HIST_ENTRIES 20 +#define WDC_C2_GUID_LENGTH 16 /* C3 Latency Monitor Log Page */ #define WDC_LATENCY_MON_LOG_BUF_LEN 0x200 @@ -512,14 +520,14 @@ typedef enum SCAO_NUSE = 152, /* NUSE - Namespace utilization */ SCAO_PSC = 160, /* PLP start count */ SCAO_EEST = 176, /* Endurance estimate */ - SCAO_PLRC = 192, /* PCIe Link Retraining Count */ + SCAO_PLRC = 192, /* PCIe Link Retraining Count */ SCAO_LPV = 494, /* Log page version */ SCAO_LPG = 496, /* Log page GUID */ } SMART_CLOUD_ATTRIBUTE_OFFSETS; -#define WDC_C2_GUID_LENGTH 16 +#define WDC_C0_GUID_LENGTH 16 -static __u8 scao_guid[WDC_C2_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4, +static __u8 scao_guid[WDC_C0_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4, 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF }; typedef enum @@ -632,10 +640,10 @@ 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 bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id); +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id); static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_drive_essentials(int fd, char *dir, char *key); +static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key); static int wdc_drive_essentials(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_drive_status(int argc, char **argv, struct command *command, @@ -653,7 +661,6 @@ static int wdc_reason_identifier(int argc, char **argv, static int wdc_do_get_reason_id(int fd, char *file, int log_id); static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size); static int wdc_clear_reason_id(int fd); -static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log_page_hdr *log_hdr); static int wdc_log_page_directory(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_do_drive_info(int fd, __u32 *result); @@ -661,10 +668,11 @@ static int wdc_vs_drive_info(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_vs_temperature_stats(int argc, char **argv, struct command *command, struct plugin *plugin); -static __u64 wdc_get_enc_drive_capabilities(int fd); +static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd); static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out); static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, FILE *out, int data_id, int cdw14, int cdw15); -static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data); +static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data); +static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd); /* Drive log data size */ struct wdc_log_size { @@ -802,12 +810,11 @@ struct wdc_c2_cbs_data { __u8 data[]; }; -struct wdc_bd_ca_log_format { +struct __attribute__((__packed__)) wdc_bd_ca_log_format { __u8 field_id; __u8 reserved1[2]; __u8 normalized_value; - __u8 reserved2; - __u8 raw_value[7]; + __u8 raw_value[8]; }; #define READ 0 @@ -904,6 +911,32 @@ struct __attribute__((__packed__)) wdc_ssd_d0_smart_log { __u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */ }; +#define WDC_OCP_C1_GUID_LENGTH 16 +#define WDC_ERROR_REC_LOG_BUF_LEN 512 +#define WDC_ERROR_REC_LOG_ID 0xC1 +#define WDC_ERROR_REC_LOG_VERSION 0002 + +struct __attribute__((__packed__)) wdc_ocp_c1_error_recovery_log { + __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */ + __u8 panic_reset_action; /* 002 - Panic Reset Action */ + __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */ + __le64 panic_id; /* 004 - Panic ID */ + __le32 dev_capabilities; /* 012 - Device Capabilities */ + __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */ + __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */ + __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */ + __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */ + __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout */ + __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 */ + __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout */ + __u8 rsvd2[463]; /* 031 - 463 Reserved Bytes */ + __le16 log_page_version; /* 494 - Log Page Version */ + __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH]; /* 496 - Log Page GUID */ +}; + +static __u8 wdc_ocp_c1_guid[WDC_OCP_C1_GUID_LENGTH] = { 0x44, 0xD9, 0x31, 0x21, 0xFE, 0x30, 0x34, 0xAE, + 0xAB, 0x4D, 0xFD, 0x3D, 0xBA, 0x83, 0x19, 0x5A }; + /* NAND Stats */ struct __attribute__((__packed__)) wdc_nand_stats { __u8 nand_write_tlc[16]; @@ -1015,6 +1048,49 @@ struct __attribute__((__packed__)) wdc_fw_act_history_log_format_c2 { __u8 log_page_guid[WDC_C2_GUID_LENGTH]; }; +#define WDC_OCP_C4_GUID_LENGTH 16 +#define WDC_DEV_CAP_LOG_BUF_LEN 4096 +#define WDC_DEV_CAP_LOG_ID 0xC4 +#define WDC_DEV_CAP_LOG_VERSION 0001 +#define WDC_OCP_C4_NUM_PS_DESCR 127 + +struct __attribute__((__packed__)) wdc_ocp_C4_dev_cap_log { + __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */ + __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */ + __le16 wrt_zeros_support; /* 0004 - Write Zeros Commmand Support */ + __le16 sanitize_support; /* 0006 - Sanitize Command Support */ + __le16 dsm_support; /* 0008 - Dataset Management Command Support */ + __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */ + __le16 fused_support; /* 0012 - Fused Operation Support */ + __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */ + __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */ + __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR];/* 0017 - DSSD Power State Descriptors */ + __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */ + __le16 log_page_version; /* 4078 - Log Page Version */ + __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH]; /* 4080 - Log Page GUID */ +}; + +static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH] = { 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98, + 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7 }; + +#define WDC_OCP_C5_GUID_LENGTH 16 +#define WDC_UNSUPPORTED_REQS_LOG_BUF_LEN 4096 +#define WDC_UNSUPPORTED_REQS_LOG_ID 0xC5 +#define WDC_UNSUPPORTED_REQS_LOG_VERSION 0001 +#define WDC_NUM_UNSUPPORTED_REQ_ENTRIES 253 + +struct __attribute__((__packed__)) wdc_ocp_C5_unsupported_reqs { + __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */ + __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */ + __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES][16]; /* 0016 - Unsupported Requirements List */ + __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */ + __le16 log_page_version; /* 4078 - Log Page Version */ + __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH]; /* 4080 - Log Page GUID */ +}; + +static __u8 wdc_ocp_c5_guid[WDC_OCP_C5_GUID_LENGTH] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB, + 0x63, 0x48, 0x32, 0xD0, 0xB7, 0x98, 0xBB, 0xC7 }; + #define WDC_REASON_INDEX_MAX 16 #define WDC_REASON_ID_ENTRY_LEN 128 #define WDC_REASON_ID_PATH_NAME "/usr/local/nvmecli" @@ -1043,80 +1119,74 @@ static long double int128_to_double(__u8 *data) return result; } -static int wdc_get_pci_ids(uint32_t *device_id, uint32_t *vendor_id) +static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id, + uint32_t *vendor_id) { - int fd, ret = -1; - char *block, path[512], *id; - - id = calloc(1, 32); - if (!id) { - fprintf(stderr, "ERROR : WDC : %s : calloc failed\n", __func__); - return -1; - } - - block = nvme_char_from_block((char *)devicename); + char vid[256], did[256], id[32]; + nvme_ctrl_t c = NULL; + nvme_ns_t n = NULL; + int fd, ret; - /* read the vendor ID from sys fs */ - sprintf(path, "/sys/class/nvme/%s/device/vendor", block); + c = nvme_scan_ctrl(r, devicename); + if (c) { + snprintf(vid, sizeof(vid), "%s/device/vendor", + nvme_ctrl_get_sysfs_dir(c)); + snprintf(did, sizeof(did), "%s/device/device", + nvme_ctrl_get_sysfs_dir(c)); + nvme_free_ctrl(c); + } else { + n = nvme_scan_namespace(devicename); + if (!n) { + fprintf(stderr, "Unable to find %s\n", devicename); + return -1; + } - fd = open(path, O_RDONLY); - if (fd < 0) { - sprintf(path, "/sys/class/misc/%s/device/vendor", block); - fd = open(path, O_RDONLY); + snprintf(vid, sizeof(vid), "%s/device/device/vendor", + nvme_ns_get_sysfs_dir(n)); + snprintf(did, sizeof(did), "%s/device/device/device", + nvme_ns_get_sysfs_dir(n)); + nvme_free_ns(n); } + + fd = open(vid, O_RDONLY); if (fd < 0) { fprintf(stderr, "ERROR : WDC : %s : Open vendor file failed\n", __func__); - ret = -1; - goto free_id; + return -1; } ret = read(fd, id, 32); + close(fd); + if (ret < 0) { fprintf(stderr, "%s: Read of pci vendor id failed\n", __func__); - ret = -1; - goto close_fd; - } else { - if (id[strlen(id) - 1] == '\n') - id[strlen(id) - 1] = '\0'; - - /* convert the device id string to an int */ - *vendor_id = (int)strtol(&id[2], NULL, 16); - ret = 0; + return -1; } - /* read the device ID from sys fs */ - sprintf(path, "/sys/class/nvme/%s/device/device", block); + if (id[strlen(id) - 1] == '\n') + id[strlen(id) - 1] = '\0'; - fd = open(path, O_RDONLY); - if (fd < 0) { - sprintf(path, "/sys/class/misc/%s/device/device", block); - fd = open(path, O_RDONLY); - } + *vendor_id = strtol(id, NULL, 0); + ret = 0; + + fd = open(did, O_RDONLY); if (fd < 0) { fprintf(stderr, "ERROR : WDC : %s : Open device file failed\n", __func__); - ret = -1; - goto close_fd; + return -1; } ret = read(fd, id, 32); + close(fd); + if (ret < 0) { fprintf(stderr, "%s: Read of pci device id failed\n", __func__); - ret = -1; - } else { - if (id[strlen(id) - 1] == '\n') - id[strlen(id) - 1] = '\0'; - - /* convert the device id string to an int */ - *device_id = strtol(&id[2], NULL, 16); - ret = 0; + return -1; } -close_fd: - close(fd); -free_id: - free(block); - free(id); - return ret; + if (id[strlen(id) - 1] == '\n') + id[strlen(id) - 1] = '\0'; + + *device_id = strtol(id, NULL, 0); + return 0; } static int wdc_get_vendor_id(int fd, uint32_t *vendor_id) @@ -1164,13 +1234,13 @@ static int wdc_get_model_number(int fd, char *model) return ret; } -static bool wdc_check_device(int fd) +static bool wdc_check_device(nvme_root_t r, int fd) { int ret; bool supported; uint32_t read_device_id = -1, read_vendor_id = -1; - ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); if (ret < 0) { /* Use the identify nvme command to get vendor id due to NVMeOF device. */ if (wdc_get_vendor_id(fd, &read_vendor_id) < 0) @@ -1210,14 +1280,13 @@ static bool wdc_enc_check_model(int fd) return supported; } -static __u64 wdc_get_drive_capabilities(int fd) { +static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { int ret; uint32_t read_device_id = -1, read_vendor_id = -1; __u64 capabilities = 0; - __u8 *data; - __u32 *cust_id; + __u32 cust_id; - ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); if (ret < 0) { if (wdc_get_vendor_id(fd, &read_vendor_id) < 0) @@ -1227,7 +1296,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/ if (read_device_id == -1 && read_vendor_id != -1) { - capabilities = wdc_get_enc_drive_capabilities(fd); + capabilities = wdc_get_enc_drive_capabilities(r, fd); return capabilities; } @@ -1245,11 +1314,11 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRIVE_CAP_PURGE); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_ADD_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; default: @@ -1265,11 +1334,11 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN640_DEV_ID: @@ -1280,7 +1349,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { /* FALLTHRU */ case WDC_NVME_SN640_DEV_ID_3: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; } @@ -1290,27 +1359,38 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID | WDC_DRIVE_CAP_LOG_PAGE_DIR); - /* verify the 0xC3 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_LATENCY_MON_OPCODE) == true) + /* verify the 0xC1 (OCP Error Recovery) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, fd, WDC_ERROR_REC_LOG_ID) == true) + capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE; + + /* verify the 0xC3 (OCP Latency Monitor) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, fd, WDC_LATENCY_MON_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; + /* verify the 0xC4 (OCP Device Capabilities) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, fd, WDC_DEV_CAP_LOG_ID) == true) + capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE; + + /* verify the 0xC5 (OCP Unsupported Requirments) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, fd, WDC_UNSUPPORTED_REQS_LOG_ID) == true) + capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE; + /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - cust_id = (__u32*)data; - - if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || - (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304)) + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || + (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304)) capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_CLOUD_SSD_VERSION); else @@ -1321,7 +1401,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { /* FALLTHRU */ case WDC_NVME_SN840_DEV_ID_1: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; } /* FALLTHRU */ @@ -1337,11 +1417,11 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRIVE_CAP_LOG_PAGE_DIR ); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN650_DEV_ID: @@ -1349,17 +1429,19 @@ static __u64 wdc_get_drive_capabilities(int fd) { case WDC_NVME_SN650_DEV_ID_2: case WDC_NVME_SN650_DEV_ID_3: case WDC_NVME_SN650_DEV_ID_4: - case WDC_NVME_SN450_DEV_ID_1: - case WDC_NVME_SN450_DEV_ID_2: + case WDC_NVME_SN655_DEV_ID: + case WDC_NVME_SN560_DEV_ID_1: + case WDC_NVME_SN560_DEV_ID_2: + case WDC_NVME_SN560_DEV_ID_3: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; } capabilities |= (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | - WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | + WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID | WDC_DRIVE_CAP_LOG_PAGE_DIR | WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_CLOUD_SSD_VERSION); @@ -1384,6 +1466,8 @@ static __u64 wdc_get_drive_capabilities(int fd) { case WDC_NVME_SN520_DEV_ID_1: /* FALLTHRU */ case WDC_NVME_SN520_DEV_ID_2: + case WDC_NVME_SN530_DEV_ID: + case WDC_NVME_SN810_DEV_ID: capabilities = WDC_DRIVE_CAP_DUI_DATA; break; case WDC_NVME_SN720_DEV_ID: @@ -1393,6 +1477,10 @@ static __u64 wdc_get_drive_capabilities(int fd) { capabilities = WDC_DRIVE_CAP_DUI | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_INFO_2 | WDC_DRIVE_CAP_TEMP_STATS | WDC_DRIVE_CAP_VUC_CLEAR_PCIE | WDC_DRIVE_CAP_PCIE_STATS; break; + case WDC_NVME_SN740_DEV_ID: + case WDC_NVME_SN740_DEV_ID_1: + case WDC_NVME_SN740_DEV_ID_2: + case WDC_NVME_SN740_DEV_ID_3: case WDC_NVME_SN340_DEV_ID: capabilities = WDC_DRIVE_CAP_DUI; break; @@ -1414,12 +1502,11 @@ static __u64 wdc_get_drive_capabilities(int fd) { return capabilities; } -static __u64 wdc_get_enc_drive_capabilities(int fd) { +static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd) { int ret; uint32_t read_vendor_id; __u64 capabilities = 0; - __u8 *data; - __u32 *cust_id; + __u32 cust_id; ret = wdc_get_vendor_id(fd, &read_vendor_id); if (ret < 0) @@ -1431,11 +1518,11 @@ static __u64 wdc_get_enc_drive_capabilities(int fd) { WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_ADD_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; case WDC_NVME_VID_2: @@ -1444,30 +1531,29 @@ static __u64 wdc_get_enc_drive_capabilities(int fd) { WDC_DRIVE_CAP_RESIZE); /* verify the 0xC3 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_LATENCY_MON_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_LATENCY_MON_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; /* verify the 0xCB log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY; /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - cust_id = (__u32*)data; - - if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || - (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304)) + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || + (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304)) capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE); else capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE); @@ -1655,10 +1741,10 @@ bool wdc_get_dev_mng_log_entry(__u32 log_length, return valid_log; } -static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) +static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data) { int ret = -1; - __u8* data; + void* data; struct wdc_c2_log_page_header *hdr_ptr; struct wdc_c2_log_subpage_header *sph; __u32 length = 0; @@ -1668,10 +1754,10 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) *cbs_data = NULL; __u32 device_id, read_vendor_id; - ret = wdc_get_pci_ids(&device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); if(device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) { lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8; - uuid_ix = 0; + uuid_ix = 0; } else lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE; @@ -1682,18 +1768,36 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) memset(data, 0, sizeof (__u8) * WDC_C2_LOG_BUF_LEN); /* get the log page length */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, WDC_C2_LOG_BUF_LEN, data); + struct nvme_get_log_args args_len = { + .args_size = sizeof(args_len), + .fd = fd, + .lid = lid, + .nsid = 0xFFFFFFFF, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_ix, + .csi = NVME_CSI_NVM, + .ot = false, + .len = WDC_C2_LOG_BUF_LEN, + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args_len); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to get 0x%x Log Page length, ret = 0x%x\n", lid, ret); goto end; } hdr_ptr = (struct wdc_c2_log_page_header *)data; + length = le32_to_cpu(hdr_ptr->length); - if (le32_to_cpu(hdr_ptr->length) > WDC_C2_LOG_BUF_LEN) { + if (length > WDC_C2_LOG_BUF_LEN) { /* Log Page buffer too small, free and reallocate the necessary size */ free(data); - data = calloc(le32_to_cpu(hdr_ptr->length), sizeof(__u8)); + data = calloc(length, sizeof(__u8)); if (data == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return false; @@ -1701,7 +1805,25 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) } /* get the log page data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, le32_to_cpu(hdr_ptr->length), data); + struct nvme_get_log_args args_data = { + .args_size = sizeof(args_data), + .fd = fd, + .lid = lid, + .nsid = 0xFFFFFFFF, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_ix, + .csi = NVME_CSI_NVM, + .ot = false, + .len = length, + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args_data); + if (ret) { fprintf(stderr, "ERROR : WDC : Unable to read 0x%x Log Page data, ret = 0x%x\n", lid, ret); goto end; @@ -1712,20 +1834,48 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) length = sizeof(struct wdc_c2_log_page_header); hdr_ptr = (struct wdc_c2_log_page_header *)data; sph = (struct wdc_c2_log_subpage_header *)(data + length); - found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph); - + found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph); if (found) { - *cbs_data = (void *)&sph->data; + *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8)); + if (*cbs_data == NULL) { + fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + goto end; + } + memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length)); } else { /* not found with uuid = 1 try with uuid = 0 */ uuid_ix = 0; /* get the log page data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, le32_to_cpu(hdr_ptr->length), data); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = lid, + .nsid = 0xFFFFFFFF, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_ix, + .csi = NVME_CSI_NVM, + .ot = false, + .len = le32_to_cpu(hdr_ptr->length), + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); + hdr_ptr = (struct wdc_c2_log_page_header *)data; sph = (struct wdc_c2_log_subpage_header *)(data + length); - found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph); + found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph); if (found) { - *cbs_data = (void *)&sph->data; + *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8)); + if (*cbs_data == NULL) { + fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + goto end; + } + memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length)); + } else { /* WD version not found */ fprintf(stderr, "ERROR : WDC : Unable to find correct version of page 0x%x, entry id = %d\n", lid, log_id); @@ -1736,13 +1886,13 @@ end: return found; } -static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id) +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id) { int i; bool found = false; struct wdc_c2_cbs_data *cbs_data = NULL; - if (get_dev_mgment_cbs_data(fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { if (cbs_data != NULL) { for (i = 0; i < le32_to_cpu(cbs_data->length); i++) { if (log_id == cbs_data->data[i]) { @@ -1759,6 +1909,7 @@ static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id) d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length), 16, 1); } #endif + free(cbs_data); } else fprintf(stderr, "ERROR : WDC : cbs_data ptr = NULL\n"); } else @@ -1767,14 +1918,16 @@ static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id) return found; } -static bool wdc_nvme_get_dev_status_log_data(int fd, __le32 *ret_data, +static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, int fd, __le32 *ret_data, __u8 log_id) { __u32 *cbs_data = NULL; - if (get_dev_mgment_cbs_data(fd, log_id, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, fd, log_id, (void *)&cbs_data)) { if (cbs_data != NULL) { memcpy((void *)ret_data, (void *)cbs_data, 4); + free(cbs_data); + return true; } } @@ -1786,16 +1939,16 @@ static bool wdc_nvme_get_dev_status_log_data(int fd, __le32 *ret_data, static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); 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); + nvme_show_status(ret); return ret; } @@ -1804,22 +1957,22 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u int ret; __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN] = {0}; struct wdc_log_size *l; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; l = (struct wdc_log_size *) buf; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_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_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); 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); + nvme_show_status(ret); return ret; } @@ -1833,19 +1986,19 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.addr = (__u64)(uintptr_t)dump_hdr; admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN; admin_cmd.cdw10 = cdw10; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "ERROR : WDC : reading dump length failed\n"); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); } return ret; @@ -1854,9 +2007,9 @@ static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_data, bool last_xfer) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE; admin_cmd.nsid = 0xFFFFFFFF; admin_cmd.addr = (__u64)(uintptr_t)dump_data; @@ -1869,10 +2022,10 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "ERROR : WDC : reading DUI data failed\n"); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); } return ret; @@ -1881,10 +2034,10 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dump_data, bool last_xfer) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; __u64 offset_lo, offset_hi; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE; admin_cmd.nsid = 0xFFFFFFFF; admin_cmd.addr = (__u64)(uintptr_t)dump_data; @@ -1900,10 +2053,10 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum else admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "ERROR : WDC : reading DUI data V2 failed\n"); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); } return ret; @@ -1916,7 +2069,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, __u8 *dump_data; __u32 curr_data_offset, curr_data_len; int i; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; __u32 dump_length = data_len; dump_data = (__u8 *) malloc(sizeof (__u8) * dump_length); @@ -1925,7 +2078,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, return -1; } memset(dump_data, 0, sizeof (__u8) * dump_length); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); curr_data_offset = 0; curr_data_len = xfer_size; i = 0; @@ -1938,10 +2091,9 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, admin_cmd.cdw13 = curr_data_offset; while (curr_data_offset < data_len) { - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { - fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", - __func__, nvme_status_to_string(ret), ret); + nvme_show_status(ret); fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", __func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr); break; @@ -1961,7 +2113,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, } if (ret == 0) { - fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + nvme_show_status(ret); ret = wdc_create_log_file(file, dump_data, dump_length); } free(dump_data); @@ -1975,7 +2127,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, __u8 *dump_data; __u32 curr_data_offset, log_size; int i; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; dump_data = (__u8 *) malloc(sizeof (__u8) * data_len); @@ -1984,7 +2136,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, return -1; } memset(dump_data, 0, sizeof (__u8) * data_len); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN; i = 0; @@ -2003,9 +2155,9 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, admin_cmd.cdw10 = xfer_size >> 2; admin_cmd.cdw13 = curr_data_offset >> 2; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { - fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + nvme_show_status(ret); fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", __func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr); break; @@ -2017,9 +2169,11 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, } if (ret == 0) { - fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + fprintf(stderr, "%s: ", __func__); + nvme_show_status(ret); } else { - fprintf(stderr, "%s: FAILURE: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + fprintf(stderr, "%s: FAILURE: ", __func__); + nvme_show_status(ret); fprintf(stderr, "%s: Partial data may have been captured\n", __func__); snprintf(file + strlen(file), PATH_MAX, "%s", "-PARTIAL"); } @@ -2032,40 +2186,66 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int data_area) { - struct nvme_telemetry_log_page_hdr *hdr; - struct nvme_id_ctrl ctrl; - size_t full_size, offset = WDC_TELEMETRY_HEADER_LENGTH; + struct nvme_telemetry_log *log; + size_t full_size = 0; int err = 0, output; - void *page_log; __u32 host_gen = 1; int ctrl_init = 0; __u32 result; void *buf = NULL; + __u8 *data_ptr = NULL; + int data_written = 0, data_remaining = 0; + struct nvme_id_ctrl ctrl; + __u64 capabilities = 0; + nvme_root_t r; + memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); + err = nvme_identify_ctrl(fd, &ctrl); + if (err) { + fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " + "0x%x\n", err); + goto close_fd; + } + + if (!(ctrl.lpa & 0x8)) { + fprintf(stderr, "Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported\n"); + err = -EINVAL; + goto close_fd; + } + + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if (type == WDC_TELEMETRY_TYPE_HOST) { host_gen = 1; ctrl_init = 0; } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER) { - /* Verify the Controller Initiated Option is enabled */ - err = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, - 0, 4, buf, &result); - if (err == 0) { - if (result == 0) { - /* enabled */ - host_gen = 0; - ctrl_init = 1; + if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { + /* Verify the Controller Initiated Option is enabled */ + err = nvme_get_features_data(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, + 4, buf, &result); + if (err == 0) { + if (result == 0) { + /* enabled */ + host_gen = 0; + ctrl_init = 1; + } + else { + fprintf(stderr, "%s: Controller initiated option telemetry log page disabled\n", __func__); + err = -EINVAL; + goto close_fd; + } } else { - fprintf(stderr, "%s: Controller initiated option telemetry log page disabled\n", __func__); - err = -EINVAL; + fprintf(stderr, "ERROR : WDC: Get telemetry option feature failed."); + nvme_show_status(err); + err = -EPERM; goto close_fd; } - } else { - fprintf(stderr, "ERROR : WDC: Get telemetry option feature failed. NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); - err = -EPERM; - goto close_fd; + } + else { + host_gen = 0; + ctrl_init = 1; } } else { fprintf(stderr, "%s: Invalid type parameter; type = %d\n", __func__, type); @@ -2079,25 +2259,21 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int goto close_fd; } - hdr = malloc(bs); - page_log = malloc(bs); - if (!hdr || !page_log) { - fprintf(stderr, "%s: Failed to allocate 0x%x bytes for log: %s\n", - __func__, bs, strerror(errno)); - err = -ENOMEM; - goto free_mem; - } - memset(hdr, 0, bs); - output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (output < 0) { fprintf(stderr, "%s: Failed to open output file %s: %s!\n", __func__, file, strerror(errno)); err = output; - goto free_mem; + goto close_fd; } - err = nvme_get_telemetry_log(fd, hdr, host_gen, ctrl_init, WDC_TELEMETRY_HEADER_LENGTH, 0); + if (ctrl_init) + err = nvme_get_ctrl_telemetry(fd, true, &log, data_area, &full_size); + else if (host_gen) + err = nvme_get_new_host_telemetry(fd, &log, data_area, &full_size); + else + err = nvme_get_host_telemetry(fd, &log, data_area, &full_size); + if (err < 0) perror("get-telemetry-log"); else if (err > 0) { @@ -2106,102 +2282,39 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int goto close_output; } - err = write(output, (void *) hdr, WDC_TELEMETRY_HEADER_LENGTH); - if (err != WDC_TELEMETRY_HEADER_LENGTH) { - fprintf(stderr, "%s: Failed to flush header data to file!, err = %d\n", __func__, err); - goto close_output; - } - - switch (data_area) { - case 1: - full_size = (le16_to_cpu(hdr->dalb1) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH; - break; - case 2: - full_size = (le16_to_cpu(hdr->dalb2) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH; - break; - case 3: - full_size = (le16_to_cpu(hdr->dalb3) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH; - break; - case 4: - err = nvme_identify_ctrl(fd, &ctrl); - if (err) { - perror("identify-ctrl"); - goto close_output; - } - - if (posix_memalign(&buf, getpagesize(), get_feat_buf_len(NVME_FEAT_HOST_BEHAVIOR))) { - fprintf(stderr, "can not allocate feature payload\n"); - errno = ENOMEM; - err = -1; - goto close_output; - } - memset(buf, 0, get_feat_buf_len(NVME_FEAT_HOST_BEHAVIOR)); - - err = nvme_get_feature(fd, NVME_NSID_ALL, NVME_FEAT_HOST_BEHAVIOR, 0, 0, - 0, get_feat_buf_len(NVME_FEAT_HOST_BEHAVIOR), buf, &result); - if (err > 0) { - nvme_show_status(err); - } else if (err < 0) { - perror("get-feature"); - } else { - if ((ctrl.lpa & 0x40)) { - if (((unsigned char *)buf)[1] == 1) - full_size = (le32_to_cpu(hdr->dalb4) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH; - else { - fprintf(stderr, "Data area 4 unsupported, Host Behavior Support ETDAS not set to 1\n"); - errno = EINVAL; - err = -1; - } - } else { - fprintf(stderr, "Data area 4 unsupported, bit 6 of Log Page Attributes not set\n"); - errno = EINVAL; - err = -1; - } - } - free(buf); - if (err) - goto close_output; - break; - default: - fprintf(stderr, "%s: Invalid data area requested, data area = %d\n", __func__, data_area); - err = -EINVAL; - goto close_output; - } - /* * Continuously pull data until the offset hits the end of the last * block. */ - while (offset < full_size) { - if ((full_size - offset) < bs) - bs = (full_size - offset); + data_written = 0; + data_remaining = full_size; + data_ptr = (__u8 *)log; + while (data_remaining) { + data_written = write(output, data_ptr, data_remaining); - err = nvme_get_telemetry_log(fd, page_log, 0, ctrl_init, bs, offset); - if (err < 0) { - perror("get-telemetry-log"); + if (data_written < 0) { + data_remaining = data_written; break; - } else if (err > 0) { - nvme_show_status(err); - fprintf(stderr, "%s: Failed to acquire full telemetry log!\n", __func__); - nvme_show_status(err); + } else if (data_written <= data_remaining) { + data_remaining -= data_written; + data_ptr += data_written; + } else { + /* Unexpected overwrite */ + fprintf(stderr, "Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x\n", + data_remaining, data_written); break; } + } - err = write(output, (void *) page_log, bs); - if (err != bs) { - fprintf(stderr, "%s: Failed to flush telemetry data to file!, err = %d\n", __func__, err); - break; - } - err = 0; - offset += bs; + if (fsync(output) < 0) { + fprintf(stderr, "ERROR : %s: fsync : %s\n", __func__, strerror(errno)); + return -1; } + free(log); close_output: close(output); -free_mem: - free(hdr); - free(page_log); close_fd: close(fd); @@ -2209,7 +2322,8 @@ close_fd: } -static int wdc_do_cap_diag(int fd, char *file, __u32 xfer_size, int type, int data_area) +static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file, + __u32 xfer_size, int type, int data_area) { int ret = -1; __u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE; @@ -2287,7 +2401,8 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in ret = wdc_dump_dui_data(fd, WDC_NVME_CAP_DUI_HEADER_SIZE, 0x00, (__u8 *)log_hdr, last_xfer); if (ret != 0) { fprintf(stderr, "%s: ERROR : WDC : Get DUI headers failed\n", __func__); - fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + fprintf(stderr, "%s: ERROR : WDC : ", __func__); + nvme_show_status(ret); goto out; } @@ -2368,7 +2483,9 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in if (ret != 0) { fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%x, addr = %p\n", __func__, i, (uint64_t)log_size, curr_data_offset, buffer_addr); - fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + fprintf(stderr, "%s: ERROR : WDC : ", + __func__); + nvme_show_status(ret); break; } @@ -2480,7 +2597,8 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in if (ret != 0) { fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n", __func__, i, (uint64_t)total_size, (uint64_t)curr_data_offset, buffer_addr); - fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + fprintf(stderr, "%s: ERROR : WDC : ", __func__); + nvme_show_status(ret); break; } @@ -2594,7 +2712,8 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in if (ret != 0) { fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n", __func__, i, (uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr); - fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + fprintf(stderr, "%s: ERROR : WDC :", __func__); + nvme_show_status(ret); break; } @@ -2616,8 +2735,7 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in goto out; } - - fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (verbose) fprintf(stderr, "INFO : WDC : Capture Device Unit Info log, length = 0x%"PRIx64"\n", (uint64_t)total_size); @@ -2633,6 +2751,7 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in static int wdc_cap_diag(int argc, char **argv, struct command *command, struct plugin *plugin) { + nvme_root_t r; char *desc = "Capture Diagnostics Log."; char *file = "Output file pathname."; char *size = "Data retrieval transfer size."; @@ -2657,6 +2776,8 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, OPT_END() }; + r = nvme_scan(NULL); + fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; @@ -2672,11 +2793,12 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, if (cfg.file == NULL) snprintf(f + strlen(f), PATH_MAX, "%s", ".bin"); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG) == WDC_DRIVE_CAP_CAP_DIAG) - return wdc_do_cap_diag(fd, f, xfer_size, 0, 0); + return wdc_do_cap_diag(r, fd, f, xfer_size, 0, 0); fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return 0; } @@ -2684,14 +2806,14 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod { int ret; uint32_t *output = NULL; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; if ((output = (uint32_t*)malloc(sizeof(uint32_t))) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return -1; } memset(output, 0, sizeof (uint32_t)); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.data_len = 8; admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE; @@ -2699,7 +2821,7 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod admin_cmd.cdw12 = subopcode; admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret == 0) *len_buf = *output; free(output); @@ -2710,13 +2832,13 @@ static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_ { int ret; uint8_t *output = NULL; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; if ((output = (uint8_t*)calloc(SN730_LOG_CHUNK_SIZE, sizeof(uint8_t))) == NULL) { fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); return -1; } - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.data_len = SN730_LOG_CHUNK_SIZE; admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE; admin_cmd.addr = (uintptr_t)output; @@ -2724,7 +2846,7 @@ static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_ admin_cmd.cdw13 = offset; admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (!ret) memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE); return ret; @@ -2816,22 +2938,22 @@ static int wdc_do_sn730_get_and_tar(int fd, char * outputName) ret = wdc_do_get_sn730_log_len(fd, &full_log_len, SN730_GET_FULL_LOG_LENGTH); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } ret = wdc_do_get_sn730_log_len(fd, &key_log_len, SN730_GET_KEY_LOG_LENGTH); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } ret = wdc_do_get_sn730_log_len(fd, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } ret = wdc_do_get_sn730_log_len(fd, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } @@ -2849,28 +2971,28 @@ static int wdc_do_sn730_get_and_tar(int fd, char * outputName) /* Get the full log */ ret = get_sn730_log_chunks(fd, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } /* Get the key log */ ret = get_sn730_log_chunks(fd, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } /* Get the core dump log */ ret = get_sn730_log_chunks(fd, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } /* Get the extended log */ ret = get_sn730_log_chunks(fd, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE); if (ret) { - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); goto free_buf; } @@ -2919,10 +3041,11 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command char *data_area = "Data area to retrieve up to. Currently only supported on the SN340, SN640, SN730, and SN840 devices."; char *file_size = "Output file size. Currently only supported on the SN340 device."; char *offset = "Output file data offset. Currently only supported on the SN340 device."; - char *type = "Telemetry type - NONE, HOST, or CONTROLLER. Currently only supported on the SN640 and SN840 devices."; + char *type = "Telemetry type - NONE, HOST, or CONTROLLER. Currently only supported on the SN530, SN640, SN730, SN740, SN810, SN840 and ZN350 devices."; char *verbose = "Display more debug messages."; char f[PATH_MAX] = {0}; char fileSuffix[PATH_MAX] = {0}; + nvme_root_t r; __u32 xfer_size = 0; int fd; int telemetry_type = 0, telemetry_data_area = 0; @@ -2937,7 +3060,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command __u64 file_size; __u64 offset; char *type; - int verbose; + bool verbose; }; struct config cfg = { @@ -2947,7 +3070,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command .file_size = 0, .offset = 0, .type = NULL, - .verbose = 0, + .verbose = false, }; OPT_ARGS(opts) = { @@ -2965,12 +3088,16 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } if (cfg.xfer_size != 0) xfer_size = cfg.xfer_size; else { fprintf(stderr, "ERROR : WDC : Invalid length\n"); + nvme_free_tree(r); return -1; } @@ -3010,43 +3137,64 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command } } - capabilities = wdc_get_drive_capabilities(fd); + if ((cfg.type == NULL) || + (!strcmp(cfg.type, "NONE")) || + (!strcmp(cfg.type, "none"))) { + telemetry_type = WDC_TELEMETRY_TYPE_NONE; + data_area = 0; + } else if ((!strcmp(cfg.type, "HOST")) || + (!strcmp(cfg.type, "host"))) { + telemetry_type = WDC_TELEMETRY_TYPE_HOST; + telemetry_data_area = cfg.data_area; + } else if ((!strcmp(cfg.type, "CONTROLLER")) || + (!strcmp(cfg.type, "controller"))) { + telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER; + telemetry_data_area = cfg.data_area; + } else { + fprintf(stderr, "ERROR : WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n"); + return -1; + } + + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { - if (cfg.data_area == 0) - cfg.data_area = 3; /* Set the default DA to 3 if not specified */ - - if ((cfg.type == NULL) || - (!strcmp(cfg.type, "NONE")) || - (!strcmp(cfg.type, "none"))) { - telemetry_type = WDC_TELEMETRY_TYPE_NONE; - data_area = 0; - } else if ((!strcmp(cfg.type, "HOST")) || - (!strcmp(cfg.type, "host"))) { - telemetry_type = WDC_TELEMETRY_TYPE_HOST; - telemetry_data_area = cfg.data_area; - } else if ((!strcmp(cfg.type, "CONTROLLER")) || - (!strcmp(cfg.type, "controller"))) { - telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER; - telemetry_data_area = cfg.data_area; - } else { - fprintf(stderr, "ERROR : WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n"); - return -1; - } + if (telemetry_data_area == 0) + telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ - return wdc_do_cap_diag(fd, f, xfer_size, telemetry_type, telemetry_data_area); + return wdc_do_cap_diag(r, fd, f, xfer_size, + telemetry_type, telemetry_data_area); } if ((capabilities & WDC_DRIVE_CAP_DUI) == WDC_DRIVE_CAP_DUI) { - if (cfg.data_area == 0) { - cfg.data_area = 1; + if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST) || + (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER)) { + if (telemetry_data_area == 0) + telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ + /* Get the desired telemetry log page */ + return wdc_do_cap_telemetry_log(fd, f, xfer_size, telemetry_type, telemetry_data_area); } + else { + if (cfg.data_area == 0) { + cfg.data_area = 1; + } - /* FW requirement - xfer size must be 256k for data area 4 */ - if (cfg.data_area >= 4) - xfer_size = 0x40000; - return wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area, cfg.verbose, cfg.file_size, cfg.offset); + /* FW requirement - xfer size must be 256k for data area 4 */ + if (cfg.data_area >= 4) + xfer_size = 0x40000; + return wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area, + cfg.verbose, cfg.file_size, cfg.offset); + } + } + if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA){ + if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST) || + (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER)) { + if (telemetry_data_area == 0) + telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ + /* Get the desired telemetry log page */ + return wdc_do_cap_telemetry_log(fd, f, xfer_size, telemetry_type, telemetry_data_area); + } + else { + return wdc_do_cap_dui(fd, f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0); + } } - if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA) - return wdc_do_cap_dui(fd, f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0); if ((capabilities & WDC_SN730B_CAP_VUC_LOG) == WDC_SN730B_CAP_VUC_LOG) return wdc_do_sn730_get_and_tar(fd, f); @@ -3151,7 +3299,7 @@ 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; + struct nvme_passthru_cmd admin_cmd; ret = wdc_dump_length(fd, WDC_NVME_DRIVE_LOG_SIZE_OPCODE, WDC_NVME_DRIVE_LOG_SIZE_NDT, @@ -3169,7 +3317,7 @@ static int wdc_do_drive_log(int fd, char *file) } memset(drive_log_data, 0, sizeof (__u8) * drive_log_length); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_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; @@ -3177,9 +3325,8 @@ static int wdc_do_drive_log(int fd, char *file) admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_LOG_SIZE_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), - ret); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + nvme_show_status(ret); if (ret == 0) { ret = wdc_create_log_file(file, drive_log_data, drive_log_length); } @@ -3195,6 +3342,7 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, char f[PATH_MAX] = {0}; int fd; int ret; + nvme_root_t r; __u64 capabilities = 0; struct config { char *file; @@ -3213,9 +3361,13 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; - capabilities = wdc_get_drive_capabilities(fd); + } + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_DRIVE_LOG) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3226,10 +3378,12 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, } if (wdc_get_serial_name(fd, f, PATH_MAX, "drive_log") == -1) { fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); + nvme_free_tree(r); return -1; } ret = wdc_do_drive_log(fd, f); } + nvme_free_tree(r); return ret; } @@ -3239,6 +3393,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, const char *desc = "Get Crash Dump."; const char *file = "Output file pathname."; int fd, ret; + nvme_root_t r; __u64 capabilities = 0; struct config { @@ -3258,10 +3413,15 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; - capabilities = wdc_get_drive_capabilities(fd); + } + + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CRASH_DUMP) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3272,6 +3432,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC : failed to read crash dump\n"); } } + nvme_free_tree(r); return ret; } @@ -3282,6 +3443,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, char *file = "Output file pathname."; int fd; int ret; + nvme_root_t r; __u64 capabilities = 0; struct config { char *file; @@ -3300,10 +3462,14 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_PFAIL_DUMP) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -3313,7 +3479,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC : failed to read pfail crash dump\n"); } } - + nvme_free_tree(r); return ret; } @@ -3371,6 +3537,7 @@ static int wdc_purge(int argc, char **argv, const char *desc = "Send a Purge command."; char *err_str; int fd, ret; + nvme_root_t r; struct nvme_passthru_cmd admin_cmd; __u64 capabilities = 0; @@ -3382,10 +3549,14 @@ static int wdc_purge(int argc, char **argv, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { ret = -1; fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3394,7 +3565,7 @@ static int wdc_purge(int argc, char **argv, memset(&admin_cmd, 0, sizeof (admin_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret > 0) { switch (ret) { case WDC_NVME_PURGE_CMD_SEQ_ERR: @@ -3410,8 +3581,9 @@ static int wdc_purge(int argc, char **argv, } fprintf(stderr, "%s", err_str); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); } + nvme_free_tree(r); return ret; } @@ -3420,11 +3592,12 @@ static int wdc_purge_monitor(int argc, char **argv, { const char *desc = "Send a Purge Monitor command."; int fd, ret; + nvme_root_t r; __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN]; double progress_percent; struct nvme_passthru_cmd admin_cmd; struct wdc_nvme_purge_monitor_data *mon; - __u64 capabilities = 0; + __u64 capabilities; OPT_ARGS(opts) = { OPT_END() @@ -3434,23 +3607,26 @@ static int wdc_purge_monitor(int argc, char **argv, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { ret = -1; fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); } else { memset(output, 0, sizeof (output)); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_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; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret == 0) { mon = (struct wdc_nvme_purge_monitor_data *) output; printf("Purge state = 0x%0x\n", admin_cmd.result); @@ -3463,8 +3639,9 @@ static int wdc_purge_monitor(int argc, char **argv, } } - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); } + nvme_free_tree(r); return ret; } @@ -3762,6 +3939,168 @@ static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_lo json_free_object(root); } +static void wdc_print_error_rec_log_normal(int fd, struct wdc_ocp_c1_error_recovery_log *log_data) +{ + int j; + printf("Error Recovery/C1 Log Page Data \n"); + + printf(" Panic Reset Wait Time : 0x%x \n", le16_to_cpu(log_data->panic_reset_wait_time)); + printf(" Panic Reset Action : 0x%x \n", log_data->panic_reset_action); + printf(" Device Recovery Action 1 : 0x%x \n", log_data->dev_recovery_action1); + printf(" Panic ID : 0x%lx \n", le64_to_cpu(log_data->panic_id)); + printf(" Device Capabilities : 0x%x \n", le32_to_cpu(log_data->dev_capabilities)); + printf(" Vendor Specific Recovery Opcode : 0x%x \n", log_data->vs_recovery_opc); + printf(" Vendor Specific Command CDW12 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw12)); + printf(" Vendor Specific Command CDW13 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw13)); + printf(" Vendor Specific Command Timeout : 0x%x \n", log_data->vs_cmd_to); + printf(" Device Recovery Action 2 : 0x%x \n", log_data->dev_recovery_action2); + printf(" Device Recovery Action 2 Timeout : 0x%x \n", log_data->dev_recovery_action2_to); + printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (j = 0; j < WDC_OCP_C1_GUID_LENGTH; j++) { + printf("%x", log_data->log_page_guid[j]); + } + printf("\n"); +} + +static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data) +{ + struct json_object *root; + root = json_create_object(); + + json_object_add_value_int(root, "Panic Reset Wait Time", le16_to_cpu(log_data->panic_reset_wait_time)); + json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_wait_time); + json_object_add_value_int(root, "Device Recovery Action 1", log_data->dev_recovery_action1); + json_object_add_value_int(root, "Panic ID", le64_to_cpu(log_data->panic_id)); + json_object_add_value_int(root, "Device Capabilities", le32_to_cpu(log_data->dev_capabilities)); + json_object_add_value_int(root, "Vendor Specific Recovery Opcode", log_data->vs_recovery_opc); + json_object_add_value_int(root, "Vendor Specific Command CDW12", le32_to_cpu(log_data->vs_cmd_cdw12)); + json_object_add_value_int(root, "Vendor Specific Command CDW13", le32_to_cpu(log_data->vs_cmd_cdw13)); + json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vs_cmd_to); + json_object_add_value_int(root, "Device Recovery Action 2", log_data->dev_recovery_action2); + json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->dev_recovery_action2_to); + json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + + char guid[40]; + memset((void*)guid, 0, 40); + sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static void wdc_print_dev_cap_log_normal(int fd, struct wdc_ocp_C4_dev_cap_log *log_data) +{ + int j; + printf("Device Capabilities/C4 Log Page Data \n"); + + printf(" Number PCIE Ports : 0x%x \n", le16_to_cpu(log_data->num_pcie_ports)); + printf(" Number OOB Management Interfaces : 0x%x \n", le16_to_cpu(log_data->oob_mgmt_support)); + printf(" Write Zeros Command Support : 0x%x \n", le16_to_cpu(log_data->wrt_zeros_support)); + printf(" Sanitize Command Support : 0x%x \n", le16_to_cpu(log_data->sanitize_support)); + printf(" DSM Command Support : 0x%x \n", le16_to_cpu(log_data->dsm_support)); + printf(" Write Uncorr Command Support : 0x%x \n", le16_to_cpu(log_data->wrt_uncor_support)); + printf(" Fused Command Support : 0x%x \n", le16_to_cpu(log_data->fused_support)); + printf(" Minimum DSSD Power State : 0x%x \n", le16_to_cpu(log_data->min_dssd_ps)); + + for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR; j++) { + printf(" DSSD Power State %d Desriptor : 0x%x \n", j, log_data->dssd_ps_descr[j]); + } + + printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (j = 0; j < WDC_OCP_C4_GUID_LENGTH; j++) { + printf("%x", log_data->log_page_guid[j]); + } + printf("\n"); +} + +static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data) +{ + int j; + struct json_object *root; + root = json_create_object(); + + json_object_add_value_int(root, "Number PCIE Ports", le16_to_cpu(log_data->num_pcie_ports)); + json_object_add_value_int(root, "Number OOB Management Interfaces", le16_to_cpu(log_data->num_pcie_ports)); + json_object_add_value_int(root, "Write Zeros Command Support", le16_to_cpu(log_data->num_pcie_ports)); + json_object_add_value_int(root, "Sanitize Command Support", le16_to_cpu(log_data->num_pcie_ports)); + json_object_add_value_int(root, "DSM Command Support", le16_to_cpu(log_data->num_pcie_ports)); + json_object_add_value_int(root, "Write Uncorr Command Support", le16_to_cpu(log_data->num_pcie_ports)); + json_object_add_value_int(root, "Fused Command Support", le16_to_cpu(log_data->num_pcie_ports)); + json_object_add_value_int(root, "Minimum DSSD Power State", le16_to_cpu(log_data->num_pcie_ports)); + + char dssd_descr_str[40]; + memset((void *)dssd_descr_str, 0, 40); + for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR; j++) { + sprintf((char *)dssd_descr_str, "DSSD Power State %d Descriptor", j); + json_object_add_value_int(root, dssd_descr_str, log_data->dssd_ps_descr[j]); + } + + json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + char guid[40]; + memset((void*)guid, 0, 40); + sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static void wdc_print_unsupported_reqs_log_normal(int fd, struct wdc_ocp_C5_unsupported_reqs *log_data) +{ + int j; + printf("Unsupported Requirements/C5 Log Page Data \n"); + + printf(" Number Unsupported Req IDs : 0x%x \n", le16_to_cpu(log_data->unsupported_count)); + + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { + printf(" Unsupported Requirement List %d : %s \n", j, log_data->unsupported_req_list[j]); + } + + printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (j = 0; j < WDC_OCP_C5_GUID_LENGTH; j++) { + printf("%x", log_data->log_page_guid[j]); + } + printf("\n"); +} + +static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data) +{ + int j; + struct json_object *root; + root = json_create_object(); + + json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count)); + + char unsup_req_list_str[40]; + memset((void *)unsup_req_list_str, 0, 40); + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { + sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j); + json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]); + } + + json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + char guid[40]; + memset((void*)guid, 0, 40); + sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf) { uint64_t converted = 0; @@ -3895,7 +4234,7 @@ static void wdc_print_bd_ca_log_normal(void *data) __u8 *byte_raw; if (bd_data->field_id == 0x00) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devicename, WDC_DE_GLOBAL_NSID); printf("key normalized raw\n"); @@ -3906,7 +4245,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x01) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("erase_fail_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -3914,9 +4253,9 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x02) { - word_raw1 = (__u16*)bd_data->raw_value; - word_raw2 = (__u16*)&bd_data->raw_value[2]; - word_raw3 = (__u16*)&bd_data->raw_value[4]; + word_raw1 = (__u16*)&bd_data->raw_value[1]; + word_raw2 = (__u16*)&bd_data->raw_value[3]; + word_raw3 = (__u16*)&bd_data->raw_value[5]; printf("wear_leveling : %3"PRIu8"%% min: %"PRIu16", max: %"PRIu16", avg: %"PRIu16"\n", bd_data->normalized_value, le16_to_cpu(*word_raw1), @@ -3927,7 +4266,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x03) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("end_to_end_error_detection_count: %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -3935,7 +4274,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x04) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("crc_error_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -3943,7 +4282,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x05) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("timed_workload_media_wear : %3"PRIu8"%% %-.3f%%\n", bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0)); @@ -3952,7 +4291,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x06) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("timed_workload_host_reads : %3"PRIu8"%% %"PRIu64"%%\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -3960,7 +4299,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x07) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("timed_workload_timer : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -3968,8 +4307,8 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x08) { - byte_raw = (__u8*)bd_data->raw_value; - dword_raw = (__u32*)&bd_data->raw_value[1]; + byte_raw = (__u8*)&bd_data->raw_value[1]; + dword_raw = (__u32*)&bd_data->raw_value[2]; printf("thermal_throttle_status : %3"PRIu8"%% %"PRIu16"%%, cnt: %"PRIu16"\n", bd_data->normalized_value, *byte_raw, le32_to_cpu(*dword_raw)); } else { @@ -3977,7 +4316,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x09) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("retry_buffer_overflow_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -3985,7 +4324,7 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x0A) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("pll_lock_loss_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -3993,19 +4332,17 @@ static void wdc_print_bd_ca_log_normal(void *data) } bd_data++; if (bd_data->field_id == 0x0B) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("nand_bytes_written : %3"PRIu8"%% sectors: %.f\n", bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF)); - raw = (__u64*)bd_data->raw_value; } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x0C) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; printf("host_bytes_written : %3"PRIu8"%% sectors: %.f\n", bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF)); - raw = (__u64*)bd_data->raw_value; } else { goto invalid_id; } @@ -4031,71 +4368,81 @@ static void wdc_print_bd_ca_log_json(void *data) root = json_create_object(); if (bd_data->field_id == 0x00) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_int(root, "program_fail_count", - le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); - json_object_add_value_int(root, "normalized", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "program_fail_count normalized", bd_data->normalized_value); + json_object_add_value_int(root, "program_fail_count raw", + le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x01) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_int(root, "erase_fail_count", - le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); - json_object_add_value_int(root, "normalized", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "erase_fail_count normalized", bd_data->normalized_value); + json_object_add_value_int(root, "erase_fail_count raw", + le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x02) { - word_raw = (__u16*)bd_data->raw_value; - json_object_add_value_int(root, "min", le16_to_cpu(*word_raw)); - word_raw = (__u16*)&bd_data->raw_value[2]; - json_object_add_value_int(root, "max", le16_to_cpu(*word_raw)); - word_raw = (__u16*)&bd_data->raw_value[4]; - json_object_add_value_int(root, "avg", le16_to_cpu(*word_raw)); - json_object_add_value_int(root, "wear_leveling-normalized", bd_data->normalized_value); + word_raw = (__u16*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "wear_leveling normalized", bd_data->normalized_value); + json_object_add_value_int(root, "wear_leveling min", le16_to_cpu(*word_raw)); + word_raw = (__u16*)&bd_data->raw_value[3]; + json_object_add_value_int(root, "wear_leveling max", le16_to_cpu(*word_raw)); + word_raw = (__u16*)&bd_data->raw_value[5]; + json_object_add_value_int(root, "wear_leveling avg", le16_to_cpu(*word_raw)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x03) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_int(root, "end_to_end_error_detection_count", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "end_to_end_error_detection_count normalized", + bd_data->normalized_value); + json_object_add_value_int(root, "end_to_end_error_detection_count raw", le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x04) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_int(root, "crc_error_count", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "crc_error_count normalized", + bd_data->normalized_value); + json_object_add_value_int(root, "crc_error_count raw", le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x05) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_float(root, "timed_workload_media_wear", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "timed_workload_media_wear normalized", + bd_data->normalized_value); + json_object_add_value_float(root, "timed_workload_media_wear raw", safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x06) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_int(root, "timed_workload_host_reads", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "timed_workload_host_reads normalized", + bd_data->normalized_value); + json_object_add_value_int(root, "timed_workload_host_reads raw", le64_to_cpu(*raw & 0x00000000000000FF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x07) { - raw = (__u64*)bd_data->raw_value; + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "timed_workload_timer normalized", + bd_data->normalized_value); json_object_add_value_int(root, "timed_workload_timer", le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -4103,54 +4450,67 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x08) { - byte_raw = (__u8*)bd_data->raw_value; + byte_raw = (__u8*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "thermal_throttle_status normalized", + bd_data->normalized_value); json_object_add_value_int(root, "thermal_throttle_status", *byte_raw); - dword_raw = (__u32*)&bd_data->raw_value[1]; - json_object_add_value_int(root, "cnt", le32_to_cpu(*dword_raw)); + dword_raw = (__u32*)&bd_data->raw_value[2]; + json_object_add_value_int(root, "thermal_throttle_cnt", le32_to_cpu(*dword_raw)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x09) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_int(root, "retry_buffer_overflow_count", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "retry_buffer_overflow_count normalized", + bd_data->normalized_value); + json_object_add_value_int(root, "retry_buffer_overflow_count raw", le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x0A) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_int(root, "pll_lock_loss_count", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "pll_lock_loss_count normalized", + bd_data->normalized_value); + json_object_add_value_int(root, "pll_lock_loss_count raw", le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x0B) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_float(root, "nand_bytes_written", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "nand_bytes_written normalized", + bd_data->normalized_value); + json_object_add_value_float(root, "nand_bytes_written raw", safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x0C) { - raw = (__u64*)bd_data->raw_value; - json_object_add_value_float(root, "host_bytes_written", + raw = (__u64*)&bd_data->raw_value[1]; + json_object_add_value_int(root, "host_bytes_written normalized", + bd_data->normalized_value); + json_object_add_value_float(root, "host_bytes_written raw", safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF)); - raw = (__u64*)bd_data->raw_value; } else { goto invalid_id; } goto done; - invalid_id: - printf(" Invalid Field ID = %d\n", bd_data->field_id); + invalid_id: + printf(" Invalid Field ID = %d\n", bd_data->field_id); - done: - return; + done: + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + + return; } @@ -4617,77 +4977,71 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data) printf(" SMART Cloud Attributes :- \n"); - printf(" Physical media units written - %"PRIu64" %"PRIu64"\n", + printf(" Physical media units written : %"PRIu64" %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); - printf(" Physical media units read - %"PRIu64" %"PRIu64"\n", + printf(" Physical media units read : %"PRIu64" %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); - printf(" Bad user nand blocks - Raw %"PRIu64"\n", + printf(" Bad user nand blocks Raw : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); - printf(" Bad user nand blocks - Normalized %d\n", + printf(" Bad user nand blocks Normalized : %d\n", (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); - printf(" Bad system nand blocks - Raw %"PRIu64"\n", + printf(" Bad system nand blocks Raw : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); - printf(" Bad system nand blocks - Normalized %d\n", + printf(" Bad system nand blocks Normalized : %d\n", (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); - printf(" XOR recovery count %"PRIu64"\n", + printf(" XOR recovery count : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); - printf(" Uncorrectable read error count %"PRIu64"\n", + printf(" Uncorrectable read error count : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); - printf(" Soft ecc error count %"PRIu64"\n", + printf(" Soft ecc error count : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); - printf(" End to end corrected errors %"PRIu32"\n", + printf(" End to end corrected errors : %"PRIu32"\n", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); - printf(" End to end detected errors %"PRIu32"\n", + printf(" End to end detected errors : %"PRIu32"\n", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); - printf(" System data percent used %d\n", - (__u8)log_data[SCAO_SDPU]); - printf(" Refresh counts %"PRIu64"\n", + printf(" System data percent used : %d\n", (__u8)log_data[SCAO_SDPU]); + printf(" Refresh counts : %"PRIu64"\n", (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF)); - printf(" Max User data erase counts %"PRIu32"\n", + printf(" Max User data erase counts : %"PRIu32"\n", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); - printf(" Min User data erase counts %"PRIu32"\n", + printf(" Min User data erase counts : %"PRIu32"\n", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); - printf(" Number of Thermal throttling events %d\n", - (__u8)log_data[SCAO_NTTE]); - printf(" Current throttling status 0x%x\n", - (__u8)log_data[SCAO_CTS]); - printf(" PCIe correctable error count %"PRIu64"\n", + printf(" Number of Thermal throttling events : %d\n", (__u8)log_data[SCAO_NTTE]); + printf(" Current throttling status : 0x%x\n", (__u8)log_data[SCAO_CTS]); + printf(" PCIe correctable error count : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); - printf(" Incomplete shutdowns %"PRIu32"\n", + printf(" Incomplete shutdowns : %"PRIu32"\n", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); - printf(" Percent free blocks %d\n", - (__u8)log_data[SCAO_PFB]); - printf(" Capacitor health %"PRIu16"\n", + printf(" Percent free blocks : %d\n", (__u8)log_data[SCAO_PFB]); + printf(" Capacitor health : %"PRIu16"\n", (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); - printf(" Unaligned I/O %"PRIu64"\n", + printf(" Unaligned I/O : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); - printf(" Security Version Number %"PRIu64"\n", + printf(" Security Version Number : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); - printf(" NUSE - Namespace utilization %"PRIu64"\n", + printf(" NUSE Namespace utilization : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - printf(" PLP start count %.0Lf\n", - int128_to_double(&log_data[SCAO_PSC])); - printf(" Endurance estimate %.0Lf\n", - int128_to_double(&log_data[SCAO_EEST])); + printf(" PLP start count : %.0Lf\n", int128_to_double(&log_data[SCAO_PSC])); + printf(" Endurance estimate : %.0Lf\n", int128_to_double(&log_data[SCAO_EEST])); smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); - printf(" Log page version %"PRIu16"\n",smart_log_ver); - printf(" Log page GUID 0x"); + printf(" Log page version : %"PRIu16"\n",smart_log_ver); + printf(" Log page GUID : 0x"); printf("0x%"PRIx64"%"PRIx64"\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); if(smart_log_ver > 2) { - printf(" Errata Version Field %d\n", + printf(" Errata Version Field : %d\n", (__u8)log_data[SCAO_EVF]); - printf(" Point Version Field %"PRIu16"\n", + printf(" Point Version Field : %"PRIu16"\n", (uint16_t)log_data[SCAO_PVF]); - printf(" Minor Version Field %"PRIu16"\n", + printf(" Minor Version Field : %"PRIu16"\n", (uint16_t)log_data[SCAO_MIVF]); - printf(" Major Version Field %d\n", + printf(" Major Version Field : %d\n", (__u8)log_data[SCAO_MAVF]); - printf(" NVMe Errata Version %d\n", + printf(" NVMe Errata Version : %d\n", (__u8)log_data[SCAO_NEV]); - printf(" PCIe Link Retraining Count %"PRIu64"\n", + printf(" PCIe Link Retraining Count : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); } printf("\n"); @@ -4700,27 +5054,27 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) uint16_t smart_log_ver = 0; root = json_create_object(); - json_object_add_value_int(root, "Physical media units written hi", + json_object_add_value_uint64(root, "Physical media units written hi", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_int(root, "Physical media units written lo", + json_object_add_value_uint64(root, "Physical media units written lo", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_int(root, "Physical media units read hi", + json_object_add_value_uint64(root, "Physical media units read hi", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_int(root, "Physical media units read lo", + json_object_add_value_uint64(root, "Physical media units read lo", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_uint(root, "Bad user nand blocks - Raw", + json_object_add_value_uint64(root, "Bad user nand blocks - Raw", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); json_object_add_value_uint(root, "Bad user nand blocks - Normalized", (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); - json_object_add_value_uint(root, "Bad system nand blocks - Raw", + json_object_add_value_uint64(root, "Bad system nand blocks - Raw", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); json_object_add_value_uint(root, "Bad system nand blocks - Normalized", (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); - json_object_add_value_uint(root, "XOR recovery count", + json_object_add_value_uint64(root, "XOR recovery count", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); - json_object_add_value_uint(root, "Uncorrectable read error count", + json_object_add_value_uint64(root, "Uncorrectable read error count", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); - json_object_add_value_uint(root, "Soft ecc error count", + json_object_add_value_uint64(root, "Soft ecc error count", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); json_object_add_value_uint(root, "End to end corrected errors", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); @@ -4728,7 +5082,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); json_object_add_value_uint(root, "System data percent used", (__u8)log_data[SCAO_SDPU]); - json_object_add_value_uint(root, "Refresh counts", + json_object_add_value_uint64(root, "Refresh counts", (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF)); json_object_add_value_uint(root, "Max User data erase counts", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); @@ -4738,7 +5092,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) (__u8)log_data[SCAO_NTTE]); json_object_add_value_uint(root, "Current throttling status", (__u8)log_data[SCAO_CTS]); - json_object_add_value_uint(root, "PCIe correctable error count", + json_object_add_value_uint64(root, "PCIe correctable error count", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); json_object_add_value_uint(root, "Incomplete shutdowns", (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); @@ -4746,11 +5100,11 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) (__u8)log_data[SCAO_PFB]); json_object_add_value_uint(root, "Capacitor health", (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); - json_object_add_value_uint(root, "Unaligned I/O", + json_object_add_value_uint64(root, "Unaligned I/O", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); - json_object_add_value_uint(root, "Security Version Number", + json_object_add_value_uint64(root, "Security Version Number", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); - json_object_add_value_uint(root, "NUSE - Namespace utilization", + json_object_add_value_uint64(root, "NUSE - Namespace utilization", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); json_object_add_value_uint(root, "PLP start count", int128_to_double(&log_data[SCAO_PSC])); @@ -4774,7 +5128,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) (__u8)log_data[SCAO_MAVF]); json_object_add_value_uint(root, "NVMe Errata Version", (__u8)log_data[SCAO_NEV]); - json_object_add_value_uint(root, "PCIe Link Retraining Count", + json_object_add_value_uint64(root, "PCIe Link Retraining Count", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); } json_print_object(root, NULL); @@ -4867,16 +5221,17 @@ static int wdc_print_c0_eol_log(void *data, int fmt) return 0; } -static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 namespace_id) +static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, + int uuid_index, __u32 namespace_id) { int ret = 0; int fmt = -1; int i = 0; __u8 *data; - __u32 *cust_id; + __u32 cust_id; uint32_t device_id, read_vendor_id; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -4884,7 +5239,7 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names return fmt; } - ret = wdc_get_pci_ids(&device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); switch (device_id) { @@ -4894,15 +5249,19 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names case WDC_NVME_SN640_DEV_ID_3: case WDC_NVME_SN840_DEV_ID: case WDC_NVME_SN840_DEV_ID_1: - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + case WDC_NVME_SN650_DEV_ID: + case WDC_NVME_SN650_DEV_ID_1: + case WDC_NVME_SN650_DEV_ID_2: + case WDC_NVME_SN650_DEV_ID_3: + case WDC_NVME_SN650_DEV_ID_4: + case WDC_NVME_SN655_DEV_ID: + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - cust_id = (__u32*)data; - - if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || - (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304)) + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || (cust_id == WDC_CUSTOMER_ID_0x1005)) { if (uuid_index == 0) { @@ -4912,18 +5271,34 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names } if (namespace_id == NVME_NSID_ALL) { - ret = namespace_id = nvme_get_nsid(fd); + ret = nvme_get_nsid(fd, &namespace_id); if (ret < 0) { namespace_id = NVME_NSID_ALL; } } /* Get the 0xC0 log data */ - ret = nvme_get_log14(fd, namespace_id, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + .nsid = namespace_id, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_index, + .csi = NVME_CSI_NVM, + .ot = false, + .len = WDC_NVME_SMART_CLOUD_ATTR_LEN, + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { @@ -4966,11 +5341,27 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names } /* Get the 0xC0 log data */ - ret = nvme_get_log14(fd, NVME_NSID_ALL, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_EOL_STATUS_LOG_LEN, data); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + .nsid = NVME_NSID_ALL, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_index, + .csi = NVME_CSI_NVM, + .ot = false, + .len = WDC_NVME_EOL_STATUS_LOG_LEN, + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -4993,11 +5384,11 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names } /* Get the 0xC0 log data */ - ret = nvme_get_log(fd, NVME_NSID_ALL, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_NVME_EOL_STATUS_LOG_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + WDC_NVME_EOL_STATUS_LOG_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5019,11 +5410,11 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names } /* Get the 0xC0 log data */ - ret = nvme_get_log(fd, NVME_NSID_ALL, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, + WDC_NVME_SMART_CLOUD_ATTR_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5064,6 +5455,57 @@ static int wdc_print_latency_monitor_log(int fd, struct wdc_ssd_latency_monitor_ return 0; } +static int wdc_print_error_rec_log(int fd, struct wdc_ocp_c1_error_recovery_log *log_data, int fmt) +{ + if (!log_data) { + fprintf(stderr, "ERROR : WDC : Invalid C1 log data buffer\n"); + return -1; + } + switch (fmt) { + case NORMAL: + wdc_print_error_rec_log_normal(fd, log_data); + break; + case JSON: + wdc_print_error_rec_log_json(log_data); + break; + } + return 0; +} + +static int wdc_print_dev_cap_log(int fd, struct wdc_ocp_C4_dev_cap_log *log_data, int fmt) +{ + if (!log_data) { + fprintf(stderr, "ERROR : WDC : Invalid C4 log data buffer\n"); + return -1; + } + switch (fmt) { + case NORMAL: + wdc_print_dev_cap_log_normal(fd, log_data); + break; + case JSON: + wdc_print_dev_cap_log_json(log_data); + break; + } + return 0; +} + +static int wdc_print_unsupported_reqs_log(int fd, struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt) +{ + if (!log_data) { + fprintf(stderr, "ERROR : WDC : Invalid C5 log data buffer\n"); + return -1; + } + switch (fmt) { + case NORMAL: + wdc_print_unsupported_reqs_log_normal(fd, log_data); + break; + case JSON: + wdc_print_unsupported_reqs_log_json(log_data); + break; + } + return 0; +} + static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt) { if (!perf) { @@ -5094,6 +5536,9 @@ static int wdc_print_bd_ca_log(void *bd_data, int fmt) case JSON: wdc_print_bd_ca_log_json(bd_data); break; + default: + fprintf(stderr, "ERROR : WDC : Unknown format - %d\n", fmt); + return -1; } return 0; } @@ -5133,16 +5578,16 @@ static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt, __ return 0; } -static int wdc_get_ca_log_page(int fd, char *format) +static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; - __u32 *cust_id; struct wdc_ssd_ca_perf_stats *perf; uint32_t read_device_id, read_vendor_id; + __u32 cust_id; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -5151,25 +5596,25 @@ static int wdc_get_ca_log_page(int fd, char *format) } /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xCA Log Page not supported\n"); return -1; } - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + /* get the FW customer id */ + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id); - - cust_id = (__u32*)data; + ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); switch (read_device_id) { case WDC_NVME_SN200_DEV_ID: - if (*cust_id == WDC_CUSTOMER_ID_0x1005) { + if (cust_id == WDC_CUSTOMER_ID_0x1005) { if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); @@ -5178,10 +5623,10 @@ static int wdc_get_ca_log_page(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_FB_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5193,7 +5638,7 @@ static int wdc_get_ca_log_page(int fd, char *format) } } else { - fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", *cust_id); + fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", cust_id); return -1; } break; @@ -5205,7 +5650,7 @@ static int wdc_get_ca_log_page(int fd, char *format) case WDC_NVME_SN840_DEV_ID: case WDC_NVME_SN840_DEV_ID_1: - if (*cust_id == WDC_CUSTOMER_ID_0x1005) { + if (cust_id == WDC_CUSTOMER_ID_0x1005) { if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); @@ -5214,10 +5659,10 @@ static int wdc_get_ca_log_page(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_FB_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5227,19 +5672,18 @@ static int wdc_get_ca_log_page(int fd, char *format) fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data\n"); ret = -1; } - } else if ((*cust_id == WDC_CUSTOMER_ID_GN) || (*cust_id == WDC_CUSTOMER_ID_GD) || - (*cust_id == WDC_CUSTOMER_ID_BD)) { - + } else if ((cust_id == WDC_CUSTOMER_ID_GN) || (cust_id == WDC_CUSTOMER_ID_GD) || + (cust_id == WDC_CUSTOMER_ID_BD)) { if ((data = (__u8*) malloc(sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return -1; } memset(data, 0, sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_BD_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_BD_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5252,7 +5696,7 @@ static int wdc_get_ca_log_page(int fd, char *format) break; } else { - fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", *cust_id); + fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", cust_id); return -1; } break; @@ -5268,7 +5712,8 @@ static int wdc_get_ca_log_page(int fd, char *format) return ret; } -static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) +static int wdc_get_c1_log_page(nvme_root_t r, int fd, + char *format, uint8_t interval) { int ret = 0; int fmt = -1; @@ -5281,7 +5726,7 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) struct wdc_log_page_subpage_header *sph; struct wdc_ssd_perf_stats *perf; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -5300,10 +5745,10 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) } memset(data, 0, sizeof (__u8) * WDC_ADD_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0x01, WDC_NVME_ADD_LOG_OPCODE, false, - NVME_NO_LOG_LSP, WDC_ADD_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, 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); + nvme_show_status(ret); if (ret == 0) { l = (struct wdc_log_page_header*)data; total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME - 1; @@ -5326,7 +5771,7 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) return ret; } -static int wdc_get_c3_log_page(int fd, char *format) +static int wdc_get_c3_log_page(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; @@ -5334,7 +5779,7 @@ static int wdc_get_c3_log_page(int fd, char *format) int i; struct wdc_ssd_latency_monitor_log *log_data; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -5348,12 +5793,11 @@ static int wdc_get_c3_log_page(int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_LATENCY_MON_LOG_BUF_LEN); - ret = nvme_get_log14(fd, NVME_NSID_ALL, WDC_LATENCY_MON_OPCODE, - NVME_NO_LOG_LSP, NVME_NO_LOG_LPO, 0, 0, - 0, 0, 0, WDC_LATENCY_MON_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_LATENCY_MON_OPCODE, + WDC_LATENCY_MON_LOG_BUF_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); if (ret == 0) { log_data = (struct wdc_ssd_latency_monitor_log*)data; @@ -5386,7 +5830,7 @@ static int wdc_get_c3_log_page(int fd, char *format) } } - /* parse the data */ + /* parse the data */ wdc_print_latency_monitor_log(fd, log_data, fmt); } else { fprintf(stderr, "ERROR : WDC : Unable to read C3 data from buffer\n"); @@ -5395,16 +5839,224 @@ static int wdc_get_c3_log_page(int fd, char *format) out: free(data); return ret; + } -static int wdc_get_d0_log_page(int fd, char *format) +static int wdc_get_ocp_c1_log_page(nvme_root_t r, int fd, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i; + struct wdc_ocp_c1_error_recovery_log *log_data; + + if (!wdc_check_device(r, fd)) + return -1; + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : WDC : invalid output format\n"); + return fmt; + } + + if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN)) == NULL) { + fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof (__u8) * WDC_ERROR_REC_LOG_BUF_LEN); + + ret = nvme_get_log_simple(fd, WDC_ERROR_REC_LOG_ID, + WDC_ERROR_REC_LOG_BUF_LEN, data); + + if (strcmp(format, "json")) + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); + + if (ret == 0) { + log_data = (struct wdc_ocp_c1_error_recovery_log *)data; + + /* check log page version */ + if (log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION) { + fprintf(stderr, "ERROR : WDC : invalid error recovery log version - %d\n", log_data->log_page_version); + ret = -1; + goto out; + } + + /* Verify GUID matches */ + for (i=0; i < WDC_OCP_C1_GUID_LENGTH; i++) { + if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR : WDC : Unknown GUID in C1 Log Page data\n"); + int j; + fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", wdc_ocp_c1_guid[j]); + } + fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", log_data->log_page_guid[j]); + } + fprintf(stderr, "\n"); + + ret = -1; + goto out; + } + } + + /* parse the data */ + wdc_print_error_rec_log(fd, log_data, fmt); + } else { + fprintf(stderr, "ERROR : WDC : Unable to read error recovery (C1) data from buffer\n"); + } + +out: + free(data); + return ret; +} + +static int wdc_get_ocp_c4_log_page(nvme_root_t r, int fd, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i; + struct wdc_ocp_C4_dev_cap_log *log_data; + + if (!wdc_check_device(r, fd)) + return -1; + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : WDC : invalid output format\n"); + return fmt; + } + + if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN)) == NULL) { + fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof (__u8) * WDC_DEV_CAP_LOG_BUF_LEN); + + ret = nvme_get_log_simple(fd, WDC_DEV_CAP_LOG_ID, + WDC_DEV_CAP_LOG_BUF_LEN, data); + + if (strcmp(format, "json")) + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); + + if (ret == 0) { + log_data = (struct wdc_ocp_C4_dev_cap_log *)data; + + /* check log page version */ + if (log_data->log_page_version != WDC_DEV_CAP_LOG_VERSION) { + fprintf(stderr, "ERROR : WDC : invalid device capabilities log version - %d\n", log_data->log_page_version); + ret = -1; + goto out; + } + + /* Verify GUID matches */ + for (i=0; i < WDC_OCP_C4_GUID_LENGTH; i++) { + if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR : WDC : Unknown GUID in C4 Log Page data\n"); + int j; + fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", wdc_ocp_c1_guid[j]); + } + fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", log_data->log_page_guid[j]); + } + fprintf(stderr, "\n"); + + ret = -1; + goto out; + } + } + + /* parse the data */ + wdc_print_dev_cap_log(fd, log_data, fmt); + } else { + fprintf(stderr, "ERROR : WDC : Unable to read device capabilities (C4) data from buffer\n"); + } + +out: + free(data); + return ret; +} + +static int wdc_get_ocp_c5_log_page(nvme_root_t r, int fd, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i; + struct wdc_ocp_C5_unsupported_reqs *log_data; + + if (!wdc_check_device(r, fd)) + return -1; + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : WDC : invalid output format\n"); + return fmt; + } + + if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN)) == NULL) { + fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof (__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN); + + ret = nvme_get_log_simple(fd, WDC_UNSUPPORTED_REQS_LOG_ID, + WDC_UNSUPPORTED_REQS_LOG_BUF_LEN, data); + + if (strcmp(format, "json")) + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); + + if (ret == 0) { + log_data = (struct wdc_ocp_C5_unsupported_reqs *)data; + + /* check log page version */ + if (log_data->log_page_version != WDC_UNSUPPORTED_REQS_LOG_VERSION) { + fprintf(stderr, "ERROR : WDC : invalid unsupported requirements log version - %d\n", log_data->log_page_version); + ret = -1; + goto out; + } + + /* Verify GUID matches */ + for (i=0; i < WDC_OCP_C5_GUID_LENGTH; i++) { + if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR : WDC : Unknown GUID in C5 Log Page data\n"); + int j; + fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", wdc_ocp_c1_guid[j]); + } + fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", log_data->log_page_guid[j]); + } + fprintf(stderr, "\n"); + + ret = -1; + goto out; + } + } + + /* parse the data */ + wdc_print_unsupported_reqs_log(fd, log_data, fmt); + } else { + fprintf(stderr, "ERROR : WDC : Unable to read unsupported requirements (C5) data from buffer\n"); + } + +out: + free(data); + return ret; +} + +static int wdc_get_d0_log_page(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; struct wdc_ssd_d0_smart_log *perf; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -5413,7 +6065,7 @@ static int wdc_get_d0_log_page(int fd, char *format) } /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xD0 Log Page not supported\n"); return -1; } @@ -5424,10 +6076,10 @@ static int wdc_get_d0_log_page(int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_NVME_VU_SMART_LOG_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_VU_SMART_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_NVME_VU_SMART_LOG_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE, + WDC_NVME_VU_SMART_LOG_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5451,6 +6103,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC"; const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0"; const char *namespace_id = "desired namespace id"; + nvme_root_t r; int ret = 0; int uuid_index = 0; int page_mask = 0, num, i; @@ -5486,6 +6139,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, if (fd < 0) return fd; + r = nvme_scan(NULL); if (cfg.log_page_version == 0) { uuid_index = 0; } else if (cfg.log_page_version == 1) { @@ -5530,7 +6184,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC: Unknown log page mask - %s\n", cfg.log_page_mask); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -5541,34 +6195,34 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE) == WDC_DRIVE_CAP_C0_LOG_PAGE) && (page_mask & WDC_C0_PAGE_MASK)) { /* Get 0xC0 log page if possible. */ - ret = wdc_get_c0_log_page(fd, cfg.output_format, uuid_index, cfg.namespace_id); + ret = wdc_get_c0_log_page(r, fd, cfg.output_format, uuid_index, cfg.namespace_id); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the C0 Log Page, ret = %d\n", ret); } if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE)) == (WDC_DRIVE_CAP_CA_LOG_PAGE)) && (page_mask & WDC_CA_PAGE_MASK)) { /* Get the CA Log Page */ - ret = wdc_get_ca_log_page(fd, cfg.output_format); + ret = wdc_get_ca_log_page(r, fd, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the CA Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE) == WDC_DRIVE_CAP_C1_LOG_PAGE) && (page_mask & WDC_C1_PAGE_MASK)) { /* Get the C1 Log Page */ - ret = wdc_get_c1_log_page(fd, cfg.output_format, cfg.interval); + ret = wdc_get_c1_log_page(r, fd, cfg.output_format, cfg.interval); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the C1 Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE) == WDC_DRIVE_CAP_D0_LOG_PAGE) && (page_mask & WDC_D0_PAGE_MASK)) { /* Get the D0 Log Page */ - ret = wdc_get_d0_log_page(fd, cfg.output_format); + ret = wdc_get_d0_log_page(r, fd, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the D0 Log Page, ret = %d\n", ret); } out: - + nvme_free_tree(r); return ret; } @@ -5576,6 +6230,7 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co struct plugin *plugin) { const char *desc = "Retrieve latency monitor log data."; + nvme_root_t r; int fd; int ret = 0; __u64 capabilities = 0; @@ -5597,7 +6252,8 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -5605,12 +6261,140 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co goto out; } - ret = wdc_get_c3_log_page(fd, cfg.output_format); + ret = wdc_get_c3_log_page(r, fd, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : WDC : Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret); + +out: + return ret; +} + +static int wdc_get_error_recovery_log(int argc, char **argv, struct command *command, + struct plugin *plugin) +{ + const char *desc = "Retrieve error recovery log data."; + nvme_root_t r; + int fd; + int ret = 0; + __u64 capabilities = 0; + + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; + + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); + + if ((capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE) == 0) { + fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + ret = -1; + goto out; + } + + ret = wdc_get_ocp_c1_log_page(r, fd, cfg.output_format); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the C3 Log Page, ret = %d\n", ret); + fprintf(stderr, "ERROR : WDC : Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret); out: + return ret; +} + +static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *command, + struct plugin *plugin) +{ + const char *desc = "Retrieve device capabilities log data."; + nvme_root_t r; + int fd; + int ret = 0; + __u64 capabilities = 0; + + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; + + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); + + if ((capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE) == 0) { + fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + ret = -1; + goto out; + } + + ret = wdc_get_ocp_c4_log_page(r, fd, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : WDC : Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret); +out: + return ret; +} + +static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *command, + struct plugin *plugin) +{ + const char *desc = "Retrieve unsupported requirements log data."; + nvme_root_t r; + int fd; + int ret = 0; + __u64 capabilities = 0; + + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; + + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); + + if ((capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE) == 0) { + fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + ret = -1; + goto out; + } + + ret = wdc_get_ocp_c5_log_page(r, fd, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : WDC : Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret); + +out: return ret; } @@ -5624,8 +6408,8 @@ static int wdc_do_clear_pcie_correctable_errors(int fd) admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_PCIE_CORR_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + nvme_show_status(ret); return ret; } @@ -5637,8 +6421,8 @@ static int wdc_do_clear_pcie_correctable_errors_vuc(int fd) memset(&admin_cmd, 0, sizeof (admin_cmd)); admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + nvme_show_status(ret); return ret; } @@ -5648,10 +6432,10 @@ static int wdc_do_clear_pcie_correctable_errors_fid(int fd) __u32 result; __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */ - ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, value, - 0, 0, 0, 0, NULL, &result); + ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, 0, value, + false, &result); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); return ret; } @@ -5660,6 +6444,7 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma { char *desc = "Clear PCIE Correctable Errors."; int fd, ret; + nvme_root_t r; __u64 capabilities = 0; OPT_ARGS(opts) = { @@ -5670,12 +6455,13 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma if (fd < 0) return fd; - if (!wdc_check_device(fd)) { + r = nvme_scan(NULL); + if (!wdc_check_device(r, fd)) { ret = -1; goto out; } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -5693,6 +6479,7 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma } out: + nvme_free_tree(r); return ret; } @@ -5702,6 +6489,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, char *desc = "Get Drive Status."; int fd; int ret = 0; + nvme_root_t r; __le32 system_eol_state; __le32 user_eol_state; __le32 format_corrupt_reason = cpu_to_le32(0xFFFFFFFF); @@ -5718,7 +6506,8 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS) != WDC_DRIVE_CAP_DRIVE_STATUS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -5726,46 +6515,46 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, } /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xC2 Log Page not supported\n"); ret = -1; goto out; } /* Get the assert dump present status */ - if (!wdc_nvme_get_dev_status_log_data(fd, &assert_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); /* Get the thermal throttling status */ - if (!wdc_nvme_get_dev_status_log_data(fd, &thermal_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &thermal_status, WDC_C2_THERMAL_THROTTLE_STATUS_ID)) fprintf(stderr, "ERROR : WDC : Get Thermal Throttling Status Failed\n"); /* Get EOL status */ - if (!wdc_nvme_get_dev_status_log_data(fd, &eol_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &eol_status, WDC_C2_USER_EOL_STATUS_ID)) { fprintf(stderr, "ERROR : WDC : Get User EOL Status Failed\n"); eol_status = cpu_to_le32(-1); } /* Get Customer EOL state */ - if (!wdc_nvme_get_dev_status_log_data(fd, &user_eol_state, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &user_eol_state, WDC_C2_USER_EOL_STATE_ID)) fprintf(stderr, "ERROR : WDC : Get User EOL State Failed\n"); /* Get System EOL state*/ - if (!wdc_nvme_get_dev_status_log_data(fd, &system_eol_state, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &system_eol_state, WDC_C2_SYSTEM_EOL_STATE_ID)) fprintf(stderr, "ERROR : WDC : Get System EOL State Failed\n"); /* Get format corrupt reason*/ - if (!wdc_nvme_get_dev_status_log_data(fd, &format_corrupt_reason, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &format_corrupt_reason, WDC_C2_FORMAT_CORRUPT_REASON_ID)) fprintf(stderr, "ERROR : WDC : Get Format Corrupt Reason Failed\n"); printf(" Drive Status :- \n"); - if (le32_to_cpu(eol_status) >= 0) { + if ((int)le32_to_cpu(eol_status) >= 0) { printf(" Percent Used: %"PRIu32"%%\n", le32_to_cpu(eol_status)); } @@ -5807,6 +6596,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason)); out: + nvme_free_tree(r); return ret; } @@ -5816,6 +6606,7 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, char *desc = "Clear Assert Dump Present Status."; int fd; int ret = -1; + nvme_root_t r; __le32 assert_status = cpu_to_le32(0xFFFFFFFF); __u64 capabilities = 0; struct nvme_passthru_cmd admin_cmd; @@ -5828,13 +6619,14 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT) != WDC_DRIVE_CAP_CLEAR_ASSERT) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; goto out; } - if (!wdc_nvme_get_dev_status_log_data(fd, &assert_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) { fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); ret = -1; @@ -5848,23 +6640,24 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_ASSERT_DUMP_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + nvme_show_status(ret); } else fprintf(stderr, "INFO : WDC : No Assert Dump Present\n"); out: + nvme_free_tree(r); return ret; } -static int wdc_get_fw_act_history(int fd, char *format) +static int wdc_get_fw_act_history(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; struct wdc_fw_act_history_log_hdr *fw_act_history_hdr; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); @@ -5874,7 +6667,7 @@ static int wdc_get_fw_act_history(int fd, char *format) } /* verify the FW Activate History log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) { fprintf(stderr, "ERROR : WDC : %d Log Page not supported\n", WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID); return -1; } @@ -5886,11 +6679,11 @@ static int wdc_get_fw_act_history(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, - false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, + WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5915,17 +6708,33 @@ static int wdc_get_fw_act_history(int fd, char *format) return ret; } -static int wdc_get_fw_act_history_C2(int fd, char *format) +static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd) +{ + + __u32 cust_id = WDC_INVALID_CUSTOMER_ID; + __u32 *cust_id_ptr = NULL; + + if (!(get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id_ptr))) { + fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + } else { + cust_id = *cust_id_ptr; + } + + free(cust_id_ptr); + return cust_id; +} + +static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; - __u32 *cust_id; + __u32 cust_id; struct wdc_fw_act_history_log_format_c2 *fw_act_history_log; __u32 tot_entries = 0, num_entries = 0; __u32 vendor_id = 0, device_id = 0; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); @@ -5933,7 +6742,8 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) fprintf(stderr, "ERROR : WDC : invalid output format\n"); return fmt; } - ret = wdc_get_pci_ids(&device_id, &vendor_id); + + ret = wdc_get_pci_ids(r, &device_id, &vendor_id); if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); @@ -5942,11 +6752,11 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, - false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, + WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); if (strcmp(format, "json")) - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); if (ret == 0) { /* parse the data */ @@ -5955,14 +6765,15 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) if (tot_entries > 0) { /* get the FW customer id */ - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); ret = -1; goto freeData; } num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES) ? tot_entries : WDC_MAX_NUM_ACT_HIST_ENTRIES; - ret = wdc_print_fw_act_history_log(data, num_entries, fmt, *cust_id, vendor_id); + ret = wdc_print_fw_act_history_log(data, num_entries, fmt, cust_id, vendor_id); } else { fprintf(stderr, "INFO : WDC : No FW Activate History entries found.\n"); ret = 0; @@ -5982,6 +6793,7 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com { int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; const char *desc = "Retrieve FW activate history table."; @@ -6004,7 +6816,8 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -6025,8 +6838,24 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com } /* Get the 0xC0 log data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = fd, + .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, + .nsid = 0xFFFFFFFF, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_index, + .csi = NVME_CSI_NVM, + .ot = false, + .len = WDC_NVME_SMART_CLOUD_ATTR_LEN, + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); if (ret == 0) { /* Verify GUID matches */ @@ -6043,19 +6872,21 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com } free(data); - if (c0GuidMatch) { - ret = wdc_get_fw_act_history_C2(fd, cfg.output_format); - } - else { - ret = wdc_get_fw_act_history(fd, cfg.output_format); - } + if (c0GuidMatch) { + ret = wdc_get_fw_act_history_C2(r, fd, + cfg.output_format); + } + else { + ret = wdc_get_fw_act_history(r, fd, cfg.output_format); + } } else { - ret = wdc_get_fw_act_history_C2(fd, cfg.output_format); + ret = wdc_get_fw_act_history_C2(r, fd, cfg.output_format); } if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the FW Activate History, ret = %d\n", ret); out: + nvme_free_tree(r); return ret; } @@ -6069,8 +6900,8 @@ static int wdc_do_clear_fw_activate_history_vuc(int fd) admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_FW_ACT_HIST_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + nvme_show_status(ret); return ret; } @@ -6081,10 +6912,10 @@ static int wdc_do_clear_fw_activate_history_fid(int fd) __u32 result; __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */ - ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, value, - 0, 0, 0, 0, NULL, &result); + ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, 0, value, + false, &result); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); return ret; } @@ -6094,6 +6925,7 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * char *desc = "Clear FW activate history table."; int fd; int ret = -1; + nvme_root_t r; __u64 capabilities = 0; OPT_ARGS(opts) = { @@ -6104,7 +6936,8 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -6119,6 +6952,7 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * } out: + nvme_free_tree(r); return ret; } @@ -6131,21 +6965,21 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm char *status = "Displays the current state of the controller initiated log page."; int fd; int ret = -1; + nvme_root_t r; __u64 capabilities = 0; __u32 result; - void *buf = NULL; struct config { - int disable; - int enable; - int status; + bool disable; + bool enable; + bool status; }; struct config cfg = { - .disable = 0, - .enable = 0, - .status = 0, + .disable = false, + .enable = false, + .status = false, }; OPT_ARGS(opts) = { @@ -6159,7 +6993,8 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -6175,26 +7010,26 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } if (cfg.disable) { - ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 1, - 0, 0, 0, 0, buf, &result); + ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 1, + false, &result); wdc_clear_reason_id(fd); } else { if (cfg.enable) { - ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, - 0, 0, 0, 0, buf, &result); + ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, + false, &result); } else if (cfg.status) { - ret = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, - 0, 4, buf, &result); + ret = nvme_get_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, + &result); if (ret == 0) { if (result) fprintf(stderr, "Controller Option Telemetry Log Page State: Disabled\n"); else fprintf(stderr, "Controller Option Telemetry Log Page State: Enabled\n"); } else { - fprintf(stderr, "ERROR : WDC: NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); } } else { @@ -6207,6 +7042,7 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } out: + nvme_free_tree(r); return ret; } @@ -6261,7 +7097,7 @@ static int wdc_get_max_transfer_len(int fd, __u32 *maxTransferLen) static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logSize) { int ret = WDC_STATUS_FAILURE; - struct nvme_admin_cmd cmd; + struct nvme_passthru_cmd cmd; if(!fd || !logSize ) { @@ -6269,18 +7105,20 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS goto end; } - memset(&cmd,0,sizeof(struct nvme_admin_cmd)); + memset(&cmd,0,sizeof(struct nvme_passthru_cmd)); cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE; cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID; cmd.cdw13 = fileId<<16; cmd.cdw14 = spiDestn; - ret = nvme_submit_admin_passthru(fd, &cmd); + ret = nvme_submit_admin_passthru(fd, &cmd, NULL); if (!ret && logSize) *logSize = cmd.result; - if( ret != WDC_STATUS_SUCCESS) - fprintf(stderr, "ERROR : WDC : VUReadSize() failed, status:%s(0x%x)\n", nvme_status_to_string(ret), ret); + if( ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR : WDC : VUReadSize() failed, "); + nvme_show_status(ret); + } end: return ret; @@ -6289,7 +7127,7 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 offsetInDwords, __u8* dataBuffer, __u32* bufferSize) { int ret = WDC_STATUS_FAILURE; - struct nvme_admin_cmd cmd; + struct nvme_passthru_cmd cmd; __u32 noOfDwordExpected = 0; if(!fd || !dataBuffer || !bufferSize) @@ -6298,7 +7136,7 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off goto end; } - memset(&cmd,0,sizeof(struct nvme_admin_cmd)); + memset(&cmd,0,sizeof(struct nvme_passthru_cmd)); noOfDwordExpected = *bufferSize/sizeof(__u32); cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE; cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID; @@ -6310,10 +7148,12 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer; cmd.data_len = *bufferSize; - ret = nvme_submit_admin_passthru(fd, &cmd); + ret = nvme_submit_admin_passthru(fd, &cmd, NULL); - if( ret != WDC_STATUS_SUCCESS) - fprintf(stderr, "ERROR : WDC : VUReadBuffer() failed, status:%s(0x%x)\n", nvme_status_to_string(ret), ret); + if( ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR : WDC : VUReadBuffer() failed, "); + nvme_show_status(ret); + } end: return ret; @@ -6620,7 +7460,7 @@ static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen, return ret; } -static int wdc_do_drive_essentials(int fd, char *dir, char *key) +static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) { int ret = 0; void *retPtr; @@ -6649,7 +7489,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) struct nvme_id_ns ns; struct nvme_error_log_page *elogBuffer; struct nvme_smart_log smart_log; - struct nvme_firmware_log_page fw_log; + struct nvme_firmware_slot fw_log; PWDC_NVME_DE_VU_LOGPAGES vuLogInput = NULL; WDC_DE_VU_LOG_DIRECTORY deEssentialsList; @@ -6725,7 +7565,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) } memset(&ns, 0, sizeof (struct nvme_id_ns)); - ret = nvme_identify_ns(fd, 1, 0, &ns); + ret = nvme_identify_ns(fd, 1, &ns); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ns() failed, ret = %d\n", ret); } else { @@ -6740,7 +7580,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) dataBuffer = calloc(1, elogBufferSize); elogBuffer = (struct nvme_error_log_page *)dataBuffer; - ret = nvme_error_log(fd, elogNumEntries, elogBuffer); + ret = nvme_get_log_error(fd, elogNumEntries, false, elogBuffer); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_error_log() failed, ret = %d\n", ret); } else { @@ -6754,7 +7594,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) /* Get Smart log page */ memset(&smart_log, 0, sizeof (struct nvme_smart_log)); - ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart_log); + ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_smart_log() failed, ret = %d\n", ret); } else { @@ -6764,14 +7604,14 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) } /* Get FW Slot log page */ - memset(&fw_log, 0, sizeof (struct nvme_firmware_log_page)); - ret = nvme_fw_log(fd, &fw_log); + memset(&fw_log, 0, sizeof (struct nvme_firmware_slot)); + ret = nvme_get_log_fw_slot(fd, true, &fw_log); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_fw_log() failed, ret = %d\n", ret); } else { wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, "FwSLotLog", (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)&fw_log, sizeof(struct nvme_firmware_log_page)); + wdc_WriteToFile(fileName, (char*)&fw_log, sizeof(struct nvme_firmware_slot)); } /* Get VU log pages */ @@ -6785,8 +7625,8 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) dataBuffer = calloc(1, dataBufferSize); memset(dataBuffer, 0, dataBufferSize); - ret = nvme_get_log(fd, WDC_DE_GLOBAL_NSID, deVULogPagesList[vuLogIdx].logPageId, - false, NVME_NO_LOG_LSP, dataBufferSize, dataBuffer); + ret = nvme_get_log_simple(fd, deVULogPagesList[vuLogIdx].logPageId, + dataBufferSize, dataBuffer); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_get_log() for log page 0x%x failed, ret = %d\n", deVULogPagesList[vuLogIdx].logPageId, ret); @@ -6810,8 +7650,8 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) /* skipping LbaRangeType as it is an optional nvme command and not supported */ if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE) continue; - ret = nvme_get_feature(fd, WDC_DE_GLOBAL_NSID, deFeatureIdList[listIdx].featureId, FS_CURRENT, 0, - 0, sizeof(featureIdBuff), &featureIdBuff, &result); + ret = nvme_get_features_data(fd, deFeatureIdList[listIdx].featureId, WDC_DE_GLOBAL_NSID, + sizeof(featureIdBuff), &featureIdBuff, &result); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_get_feature id 0x%x failed, ret = %d\n", @@ -6905,6 +7745,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) } fprintf(stderr, "Get of Drive Essentials data successful\n"); + nvme_free_tree(r); return 0; } @@ -6917,6 +7758,7 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, char k[PATH_MAX] = {0}; char *d_ptr; int fd; + nvme_root_t r; __u64 capabilities = 0; struct config { @@ -6937,9 +7779,11 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return -1; } @@ -6950,49 +7794,49 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, d_ptr = NULL; } - return wdc_do_drive_essentials(fd, d_ptr, k); + return wdc_do_drive_essentials(r, fd, d_ptr, k); } static int wdc_do_drive_resize(int fd, uint64_t new_size) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_RESIZE_CMD); admin_cmd.cdw13 = new_size; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); return ret; } static int wdc_do_namespace_resize(int fd, __u32 nsid, __u32 op_option) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE; admin_cmd.nsid = nsid; admin_cmd.cdw10 = op_option; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); return ret; } static int wdc_do_drive_info(int fd, __u32 *result) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_INFO_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (!ret && result) *result = admin_cmd.result; @@ -7005,6 +7849,7 @@ static int wdc_drive_resize(int argc, char **argv, { const char *desc = "Send a Resize command."; const char *size = "The new size (in GB) to resize the drive to."; + nvme_root_t r; uint64_t capabilities = 0; int fd, ret; @@ -7025,8 +7870,9 @@ static int wdc_drive_resize(int argc, char **argv, if (fd < 0) return fd; - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_RESIZE) == WDC_DRIVE_CAP_RESIZE) { ret = wdc_do_drive_resize(fd, cfg.size); } else { @@ -7037,7 +7883,8 @@ static int wdc_drive_resize(int argc, char **argv, if (!ret) printf("New size: %" PRIu64 " GB\n", cfg.size); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); + nvme_free_tree(r); return ret; } @@ -7047,6 +7894,7 @@ static int wdc_namespace_resize(int argc, char **argv, const char *desc = "Send a Namespace Resize command."; const char *namespace_id = "The namespace id to resize."; const char *op_option = "The over provisioning option to set for namespace."; + nvme_root_t r; uint64_t capabilities = 0; int fd, ret; @@ -7079,8 +7927,9 @@ static int wdc_namespace_resize(int argc, char **argv, return -1; } - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE) == WDC_DRIVE_CAP_NS_RESIZE) { ret = wdc_do_namespace_resize(fd, cfg.namespace_id, cfg.op_option); @@ -7091,7 +7940,8 @@ static int wdc_namespace_resize(int argc, char **argv, ret = -1; } - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); + nvme_free_tree(r); return ret; } @@ -7101,6 +7951,7 @@ static int wdc_reason_identifier(int argc, char **argv, const char *desc = "Retrieve telemetry log reason identifier."; const char *log_id = "Log ID to retrieve - host - 7 or controller - 8"; const char *fname = "File name to save raw binary identifier"; + nvme_root_t r; int fd; int ret; uint64_t capabilities = 0; @@ -7130,7 +7981,9 @@ static int wdc_reason_identifier(int argc, char **argv, if (fd < 0) return fd; - if (cfg.log_id != NVME_LOG_TELEMETRY_HOST && cfg.log_id != NVME_LOG_TELEMETRY_CTRL) { + r = nvme_scan(NULL); + + if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST&& cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) { fprintf(stderr, "ERROR : WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)\n"); ret = -1; goto close_fd; @@ -7154,7 +8007,7 @@ static int wdc_reason_identifier(int argc, char **argv, wdc_UtilsSnprintf((char*)timeStamp, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", timeInfo.year, timeInfo.month, timeInfo.dayOfMonth, timeInfo.hour, timeInfo.minute, timeInfo.second); - if (cfg.log_id == NVME_LOG_TELEMETRY_CTRL) + if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL) snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_ctlr_%s", (char*)timeStamp); else snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_host_%s", (char*)timeStamp); @@ -7170,7 +8023,7 @@ static int wdc_reason_identifier(int argc, char **argv, fprintf(stderr, "%s: filename = %s\n", __func__, f); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_REASON_ID) == WDC_DRIVE_CAP_REASON_ID) { ret = wdc_do_get_reason_id(fd, f, cfg.log_id); } else { @@ -7178,50 +8031,51 @@ static int wdc_reason_identifier(int argc, char **argv, ret = -1; } - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); close_fd: - close(fd); - return ret; + close(fd); + nvme_free_tree(r); + return ret; } static const char *nvme_log_id_to_string(__u8 log_id) { switch (log_id) { - case NVME_LOG_ERROR: return "Error Information Log ID"; - case NVME_LOG_SMART: return "Smart/Health Information Log ID"; - case NVME_LOG_FW_SLOT: return "Firmware Slot Information Log ID"; - case NVME_LOG_CHANGED_NS: return "Namespace Changed Log ID"; - case NVME_LOG_CMD_EFFECTS: return "Commamds Supported and Effects Log ID"; - case NVME_LOG_DEVICE_SELF_TEST: return "Device Self Test Log ID"; - case NVME_LOG_TELEMETRY_HOST: return "Telemetry Host Initiated Log ID"; - case NVME_LOG_TELEMETRY_CTRL: return "Telemetry Controller Generated Log ID"; - case NVME_LOG_ENDURANCE_GROUP: return "Endurance Group Log ID"; - case NVME_LOG_ANA: return "ANA Log ID"; - case NVME_LOG_PERSISTENT_EVENT: return "Persistent Event Log ID"; - case NVME_LOG_DISC: return "Discovery Log ID"; - case NVME_LOG_RESERVATION: return "Reservation Notification Log ID"; - case NVME_LOG_SANITIZE: return "Sanitize Status Log ID"; - - case WDC_LOG_ID_C0: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_C1: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_C2: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_C4: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_C5: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_C6: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_C8: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_CA: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_CB: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_D0: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_D1: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_D6: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_D7: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_D8: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_DE: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_F0: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_F1: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_F2: return "WDC Vendor Unique Log ID"; - case WDC_LOG_ID_FA: return "WDC Vendor Unique Log ID"; + case NVME_LOG_LID_ERROR: return "Error Information Log ID"; + case NVME_LOG_LID_SMART: return "Smart/Health Information Log ID"; + case NVME_LOG_LID_FW_SLOT: return "Firmware Slot Information Log ID"; + case NVME_LOG_LID_CHANGED_NS: return "Namespace Changed Log ID"; + case NVME_LOG_LID_CMD_EFFECTS: return "Commamds Supported and Effects Log ID"; + case NVME_LOG_LID_DEVICE_SELF_TEST: return "Device Self Test Log ID"; + case NVME_LOG_LID_TELEMETRY_HOST: return "Telemetry Host Initiated Log ID"; + case NVME_LOG_LID_TELEMETRY_CTRL: return "Telemetry Controller Generated Log ID"; + case NVME_LOG_LID_ENDURANCE_GROUP: return "Endurance Group Log ID"; + case NVME_LOG_LID_ANA: return "ANA Log ID"; + case NVME_LOG_LID_PERSISTENT_EVENT: return "Persistent Event Log ID"; + case NVME_LOG_LID_DISCOVER: return "Discovery Log ID"; + case NVME_LOG_LID_RESERVATION: return "Reservation Notification Log ID"; + case NVME_LOG_LID_SANITIZE: return "Sanitize Status Log ID"; + + case WDC_LOG_ID_C0: return "WDC Vendor Unique Log ID C0"; + case WDC_LOG_ID_C1: return "WDC Vendor Unique Log ID C1"; + case WDC_LOG_ID_C2: return "WDC Vendor Unique Log ID C2"; + case WDC_LOG_ID_C4: return "WDC Vendor Unique Log ID C4"; + case WDC_LOG_ID_C5: return "WDC Vendor Unique Log ID C5"; + case WDC_LOG_ID_C6: return "WDC Vendor Unique Log ID C6"; + case WDC_LOG_ID_C8: return "WDC Vendor Unique Log ID C8"; + case WDC_LOG_ID_CA: return "WDC Vendor Unique Log ID CA"; + case WDC_LOG_ID_CB: return "WDC Vendor Unique Log ID CB"; + case WDC_LOG_ID_D0: return "WDC Vendor Unique Log ID D0"; + case WDC_LOG_ID_D1: return "WDC Vendor Unique Log ID D1"; + case WDC_LOG_ID_D6: return "WDC Vendor Unique Log ID D6"; + case WDC_LOG_ID_D7: return "WDC Vendor Unique Log ID D7"; + case WDC_LOG_ID_D8: return "WDC Vendor Unique Log ID D8"; + case WDC_LOG_ID_DE: return "WDC Vendor Unique Log ID DE"; + case WDC_LOG_ID_F0: return "WDC Vendor Unique Log ID F0"; + case WDC_LOG_ID_F1: return "WDC Vendor Unique Log ID F1"; + case WDC_LOG_ID_F2: return "WDC Vendor Unique Log ID F2"; + case WDC_LOG_ID_FA: return "WDC Vendor Unique Log ID FA"; default: return "Unknown Log ID"; } @@ -7233,9 +8087,10 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command const char *desc = "Retrieve Log Page Directory."; int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; struct wdc_c2_cbs_data *cbs_data = NULL; - int i; + int i; __u8 log_id = 0; __u32 device_id, read_vendor_id; @@ -7261,25 +8116,26 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command fprintf(stderr, "%s: ERROR : WDC : invalid output format\n", __func__); return ret; } + ret = 0; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; - } - else { - ret = wdc_get_pci_ids(&device_id, &read_vendor_id); + } else { + ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); log_id = (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) ? WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 : WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE; /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, log_id) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, log_id) == false) { fprintf(stderr, "%s: ERROR : WDC : 0x%x Log Page not supported\n", __func__, log_id); ret = -1; goto out; } - if (get_dev_mgment_cbs_data(fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { if (cbs_data != NULL) { printf("Log Page Directory\n"); /* print the supported pages */ @@ -7304,6 +8160,8 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command json_free_object(root); } else fprintf(stderr, "%s: ERROR : WDC : Invalid format, format = %s\n", __func__, cfg.output_format); + + free(cbs_data); } else fprintf(stderr, "%s: ERROR : WDC : NULL_data ptr\n", __func__); } else @@ -7313,6 +8171,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command } out: + nvme_free_tree(r); return ret; } @@ -7419,14 +8278,33 @@ static int wdc_clear_reason_id(int fd) return ret; } +static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log *log_hdr) +{ + int ret = 0; + + if (log_id == NVME_LOG_LID_TELEMETRY_HOST) + ret = nvme_get_log_create_telemetry_host(fd, log_hdr); + else + ret = nvme_get_log_telemetry_ctrl(fd, false, 0, 512, (void *)log_hdr); + + if (ret < 0) + perror("get-telemetry-log"); + else if (ret > 0) { + nvme_show_status(ret); + fprintf(stderr, "%s: ERROR : Failed to acquire telemetry header, ret = %d!\n", __func__, ret); + } + + return ret; +} + static int wdc_do_get_reason_id(int fd, char *file, int log_id) { int ret; - struct nvme_telemetry_log_page_hdr *log_hdr; - __u32 log_hdr_size = sizeof(struct nvme_telemetry_log_page_hdr); + struct nvme_telemetry_log *log_hdr; + __u32 log_hdr_size = sizeof(struct nvme_telemetry_log); __u32 reason_id_size = 0; - log_hdr = (struct nvme_telemetry_log_page_hdr *) malloc(log_hdr_size); + log_hdr = (struct nvme_telemetry_log *) malloc(log_hdr_size); if (log_hdr == NULL) { fprintf(stderr, "%s: ERROR : malloc failed, size : 0x%x, status : %s\n", __func__, log_hdr_size, strerror(errno)); ret = -1; @@ -7443,7 +8321,7 @@ static int wdc_do_get_reason_id(int fd, char *file, int log_id) reason_id_size = sizeof(log_hdr->rsnident); - if (log_id == NVME_LOG_TELEMETRY_CTRL) + if (log_id == NVME_LOG_LID_TELEMETRY_CTRL) wdc_save_reason_id(fd, log_hdr->rsnident, reason_id_size); ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size); @@ -7453,27 +8331,6 @@ out: return ret; } -static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log_page_hdr *log_hdr) -{ - int ret = 0; - int host_gen = 0, ctrl_init = 0; - - if (log_id == NVME_LOG_TELEMETRY_HOST) - host_gen = 1; - else - ctrl_init = 1; - - ret = nvme_get_telemetry_log(fd, log_hdr, host_gen, ctrl_init, 512, 0); - if (ret < 0) - perror("get-telemetry-log"); - else if (ret > 0) { - nvme_show_status(ret); - fprintf(stderr, "%s: ERROR : Failed to acquire telemetry header, ret = %d!\n", __func__, ret); - } - - return ret; -} - static void wdc_print_nand_stats_normal(__u16 version, void *data) { struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data); @@ -7625,11 +8482,11 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) le32_to_cpu(nand_stats->nand_erase_failure)); json_object_add_value_uint(root, "Bad Block Count", le32_to_cpu(nand_stats->bad_block_count)); - json_object_add_value_uint(root, "NAND XOR/RAID Recovery Trigger Events", + json_object_add_value_uint64(root, "NAND XOR/RAID Recovery Trigger Events", le64_to_cpu(nand_stats->nand_rec_trigger_event)); - json_object_add_value_uint(root, "E2E Error Counter", + json_object_add_value_uint64(root, "E2E Error Counter", le64_to_cpu(nand_stats->e2e_error_counter)); - json_object_add_value_uint(root, "Number Successful NS Resizing Events", + json_object_add_value_uint64(root, "Number Successful NS Resizing Events", le64_to_cpu(nand_stats->successful_ns_resize_event)); json_print_object(root, NULL); @@ -7647,13 +8504,13 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); json_object_add_value_uint(root, "Bad NAND Blocks Count - Normalized", le16_to_cpu(temp_norm)); - json_object_add_value_uint(root, "Bad NAND Blocks Count - Raw", + json_object_add_value_uint64(root, "Bad NAND Blocks Count - Raw", le64_to_cpu(temp_raw)); - json_object_add_value_uint(root, "NAND XOR Recovery count", + json_object_add_value_uint64(root, "NAND XOR Recovery count", le64_to_cpu(nand_stats_v3->xor_recovery_count)); - json_object_add_value_uint(root, "UECC Read Error count", + json_object_add_value_uint64(root, "UECC Read Error count", le64_to_cpu(nand_stats_v3->uecc_read_error_count)); - json_object_add_value_uint(root, "SSD End to End corrected errors", + json_object_add_value_uint64(root, "SSD End to End corrected errors", le64_to_cpu(nand_stats_v3->ssd_correction_counts[0])); json_object_add_value_uint(root, "SSD End to End detected errors", le32_to_cpu(nand_stats_v3->ssd_correction_counts[8])); @@ -7661,54 +8518,54 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) le32_to_cpu(nand_stats_v3->ssd_correction_counts[12])); json_object_add_value_uint(root, "System data % life-used", nand_stats_v3->percent_life_used); - json_object_add_value_uint(root, "User Data Erase Counts - SLC Min", + json_object_add_value_uint64(root, "User Data Erase Counts - SLC Min", le64_to_cpu(nand_stats_v3->user_data_erase_counts[0])); - json_object_add_value_uint(root, "User Data Erase Counts - SLC Max", + json_object_add_value_uint64(root, "User Data Erase Counts - SLC Max", le64_to_cpu(nand_stats_v3->user_data_erase_counts[1])); - json_object_add_value_uint(root, "User Data Erase Counts - TLC Min", + json_object_add_value_uint64(root, "User Data Erase Counts - TLC Min", le64_to_cpu(nand_stats_v3->user_data_erase_counts[2])); - json_object_add_value_uint(root, "User Data Erase Counts - TLC Max", + json_object_add_value_uint64(root, "User Data Erase Counts - TLC Max", le64_to_cpu(nand_stats_v3->user_data_erase_counts[3])); temp_ptr = (__u64 *)nand_stats_v3->program_fail_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); json_object_add_value_uint(root, "Program Fail Count - Normalized", le16_to_cpu(temp_norm)); - json_object_add_value_uint(root, "Program Fail Count - Raw", + json_object_add_value_uint64(root, "Program Fail Count - Raw", le64_to_cpu(temp_raw)); temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); json_object_add_value_uint(root, "Erase Fail Count - Normalized", le16_to_cpu(temp_norm)); - json_object_add_value_uint(root, "Erase Fail Count - Raw", + json_object_add_value_uint64(root, "Erase Fail Count - Raw", le64_to_cpu(temp_raw)); json_object_add_value_uint(root, "PCIe Correctable Error Count", le16_to_cpu(nand_stats_v3->correctable_error_count)); json_object_add_value_uint(root, "% Free Blocks (User)", nand_stats_v3->percent_free_blocks_user); - json_object_add_value_uint(root, "Security Version Number", + json_object_add_value_uint64(root, "Security Version Number", le64_to_cpu(nand_stats_v3->security_version_number)); json_object_add_value_uint(root, "% Free Blocks (System)", nand_stats_v3->percent_free_blocks_system); json_object_add_value_float(root, "Data Set Management Commands", int128_to_double(nand_stats_v3->trim_completions)); - json_object_add_value_uint(root, "Estimate of Incomplete Trim Data", + json_object_add_value_uint64(root, "Estimate of Incomplete Trim Data", le64_to_cpu(nand_stats_v3->trim_completions[16])); json_object_add_value_uint(root, "%% of completed trim", nand_stats_v3->trim_completions[24]); json_object_add_value_uint(root, "Background Back-Pressure-Guage", nand_stats_v3->back_pressure_guage); - json_object_add_value_uint(root, "Soft ECC Error Count", + json_object_add_value_uint64(root, "Soft ECC Error Count", le64_to_cpu(nand_stats_v3->soft_ecc_error_count)); - json_object_add_value_uint(root, "Refresh Count", + json_object_add_value_uint64(root, "Refresh Count", le64_to_cpu(nand_stats_v3->refresh_count)); temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); json_object_add_value_uint(root, "Bad System Nand Block Count - Normalized", le16_to_cpu(temp_norm)); - json_object_add_value_uint(root, "Bad System Nand Block Count - Raw", + json_object_add_value_uint64(root, "Bad System Nand Block Count - Raw", le64_to_cpu(temp_raw)); json_object_add_value_float(root, "Endurance Estimate", int128_to_double(nand_stats_v3->endurance_estimate)); @@ -7716,7 +8573,7 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) nand_stats_v3->thermal_throttling_st_ct[0]); json_object_add_value_uint(root, "Thermal Throttling Count", nand_stats_v3->thermal_throttling_st_ct[1]); - json_object_add_value_uint(root, "Unaligned I/O", + json_object_add_value_uint64(root, "Unaligned I/O", le64_to_cpu(nand_stats_v3->unaligned_IO)); json_object_add_value_float(root, "Physical Media Units Read", int128_to_double(nand_stats_v3->physical_media_units)); @@ -7780,38 +8637,38 @@ static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats) struct json_object *root; root = json_create_object(); - json_object_add_value_uint(root, "Unsupported Request Error Counter", + json_object_add_value_uint64(root, "Unsupported Request Error Counter", le64_to_cpu(pcie_stats->unsupportedRequestErrorCount)); - json_object_add_value_uint(root, "ECRC Error Status Counter", + json_object_add_value_uint64(root, "ECRC Error Status Counter", le64_to_cpu(pcie_stats->ecrcErrorStatusCount)); - json_object_add_value_uint(root, "Malformed TLP Status Counter", + json_object_add_value_uint64(root, "Malformed TLP Status Counter", le64_to_cpu(pcie_stats->malformedTlpStatusCount)); - json_object_add_value_uint(root, "Receiver Overflow Status Counter", + json_object_add_value_uint64(root, "Receiver Overflow Status Counter", le64_to_cpu(pcie_stats->receiverOverflowStatusCount)); - json_object_add_value_uint(root, "Unexpected Completion Status Counter", + json_object_add_value_uint64(root, "Unexpected Completion Status Counter", le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount)); - json_object_add_value_uint(root, "Complete Abort Status Counter", + json_object_add_value_uint64(root, "Complete Abort Status Counter", le64_to_cpu(pcie_stats->completeAbortStatusCount)); - json_object_add_value_uint(root, "Completion Timeout Status Counter", + json_object_add_value_uint64(root, "Completion Timeout Status Counter", le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount)); - json_object_add_value_uint(root, "Flow Control Error Status Counter", + json_object_add_value_uint64(root, "Flow Control Error Status Counter", le64_to_cpu(pcie_stats->flowControlErrorStatusCount)); - json_object_add_value_uint(root, "Poisoned TLP Status Counter", + json_object_add_value_uint64(root, "Poisoned TLP Status Counter", le64_to_cpu(pcie_stats->poisonedTlpStatusCount)); - json_object_add_value_uint(root, "Dlink Protocol Error Status Counter", + json_object_add_value_uint64(root, "Dlink Protocol Error Status Counter", le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount)); - json_object_add_value_uint(root, "Advisory Non Fatal Error Status Counter", + json_object_add_value_uint64(root, "Advisory Non Fatal Error Status Counter", le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount)); - json_object_add_value_uint(root, "Replay Timer TO Status Counter", + json_object_add_value_uint64(root, "Replay Timer TO Status Counter", le64_to_cpu(pcie_stats->replayTimerToStatusCount)); - json_object_add_value_uint(root, "Replay Number Rollover Status Counter", + json_object_add_value_uint64(root, "Replay Number Rollover Status Counter", le64_to_cpu(pcie_stats->replayNumRolloverStCount)); - json_object_add_value_uint(root, "Bad DLLP Status Counter", + json_object_add_value_uint64(root, "Bad DLLP Status Counter", le64_to_cpu(pcie_stats->badDllpStatusCount)); - json_object_add_value_uint(root, "Bad TLP Status Counter", + json_object_add_value_uint64(root, "Bad TLP Status Counter", le64_to_cpu(pcie_stats->badTlpStatusCount)); - json_object_add_value_uint(root, "Receiver Error Status Counter", + json_object_add_value_uint64(root, "Receiver Error Status Counter", le64_to_cpu(pcie_stats->receiverErrStatusCount)); json_print_object(root, NULL); @@ -7833,8 +8690,8 @@ static int wdc_do_vs_nand_stats(int fd, char *format) goto out; } - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_NAND_STATS_LOG_ID, - false, NVME_NO_LOG_LSP, WDC_NVME_NAND_STATS_SIZE, (void*)output); + ret = nvme_get_log_simple(fd, WDC_NVME_NAND_STATS_LOG_ID, + WDC_NVME_NAND_STATS_SIZE, (void*)output); if (ret) { fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__); goto out; @@ -7871,6 +8728,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; struct config { @@ -7890,7 +8748,8 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_NAND_STATS) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7901,6 +8760,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC : Failure reading NAND statistics, ret = %d\n", ret); } + nvme_free_tree(r); return ret; } @@ -7908,15 +8768,15 @@ static int wdc_do_vs_pcie_stats(int fd, struct wdc_vs_pcie_stats *pcieStatsPtr) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr; admin_cmd.data_len = pcie_stats_size; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); return ret; } @@ -7928,6 +8788,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; int fmt = -1; struct wdc_vs_pcie_stats *pcieStatsPtr = NULL; @@ -7951,6 +8812,8 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, if (fd < 0) return fd; + + r = nvme_scan(NULL); fmt = validate_output_format(cfg.output_format); if (fmt < 0) { fprintf(stderr, "ERROR : WDC : invalid output format\n"); @@ -7967,7 +8830,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, memset((void *)pcieStatsPtr, 0, pcie_stats_size); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_PCIE_STATS) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7992,6 +8855,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, nvme_free(pcieStatsPtr, huge); out: + nvme_free_tree(r); return ret; } @@ -7999,6 +8863,7 @@ static int wdc_vs_drive_info(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a vs-drive-info command."; + nvme_root_t r; uint64_t capabilities = 0; int fd, ret; __le32 result; @@ -8043,8 +8908,9 @@ static int wdc_vs_drive_info(int argc, char **argv, return ret; } - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) { ret = wdc_do_drive_info(fd, &result); @@ -8097,11 +8963,13 @@ static int wdc_vs_drive_info(int argc, char **argv, } } else { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return -1; } - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); + nvme_free_tree(r); return ret; } @@ -8111,6 +8979,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, const char *desc = "Send a vs-temperature-stats command."; struct nvme_smart_log smart_log; struct nvme_id_ctrl id_ctrl; + nvme_root_t r; uint64_t capabilities = 0; __u32 hctm_tmt; int fd, ret; @@ -8134,6 +9003,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, if (fd < 0) return fd; + r = nvme_scan(NULL); fmt = validate_output_format(cfg.output_format); if (fmt < 0) { fprintf(stderr, "ERROR : WDC : invalid output format\n"); @@ -8142,10 +9012,11 @@ static int wdc_vs_temperature_stats(int argc, char **argv, } /* check if command is supported */ - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS) != WDC_DRIVE_CAP_TEMP_STATS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return -1; } @@ -8153,7 +9024,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, ret = nvme_identify_ctrl(fd, &id_ctrl); if (ret != 0) goto END; - ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart_log); + ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log); if (ret != 0) goto END; @@ -8161,7 +9032,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273; /* retrieve HCTM Thermal Management Temperatures */ - nvme_get_feature(fd, 0, 0x10, 0, 0, 0, 0, 0, &hctm_tmt); + nvme_get_features_simple(fd, 0x10, 0, &hctm_tmt); temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0; temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0; @@ -8213,7 +9084,8 @@ static int wdc_vs_temperature_stats(int argc, char **argv, printf("%s: Invalid format\n", __func__); END: - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_show_status(ret); + nvme_free_tree(r); return ret; } @@ -8221,6 +9093,7 @@ static int wdc_capabilities(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a capabilities command."; + nvme_root_t r; uint64_t capabilities = 0; int fd; @@ -8234,8 +9107,9 @@ static int wdc_capabilities(int argc, char **argv, return fd; /* get capabilities */ - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); /* print command and supported status */ printf("WDC Plugin Capabilities for NVME device:%s\n", devicename); @@ -8298,29 +9172,37 @@ static int wdc_capabilities(int argc, char **argv, capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION ? "Supported" : "Not Supported"); printf("vs-pcie-stats : %s\n", capabilities & WDC_DRIVE_CAP_PCIE_STATS ? "Supported" : "Not Supported"); + printf("get-error-recovery-log : %s\n", + capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE ? "Supported" : "Not Supported"); + printf("get-dev-capabilities-log : %s\n", + capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE ? "Supported" : "Not Supported"); + printf("get-unsupported-reqs-log : %s\n", + capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE ? "Supported" : "Not Supported"); printf("capabilities : Supported\n"); + nvme_free_tree(r); return 0; } static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *command, struct plugin *plugin) { - const char *desc = "Get Cloud SSD Plugin Version command."; - uint64_t capabilities = 0; - int fd; + const char *desc = "Get Cloud SSD Plugin Version command."; + nvme_root_t r; + uint64_t capabilities = 0; + int fd; - OPT_ARGS(opts) = - { - OPT_END() - }; + OPT_ARGS(opts) = { + OPT_END() + }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; - /* get capabilities */ - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + /* get capabilities */ + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION) { /* print command and supported status */ @@ -8329,7 +9211,8 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv, fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); } - return 0; + nvme_free_tree(r); + return 0; } static int wdc_enc_get_log(int argc, char **argv, struct command *command, @@ -8421,7 +9304,7 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, closed_fd: close(fd); ret: - return nvme_status_to_errno(err, false); + return err; } static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, FILE *out, int log_id, int cdw14, int cdw15) @@ -8442,7 +9325,7 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F cmd = (len) ? cmd : buf; len = (len) ? len : 0x20; - struct nvme_admin_cmd nvme_cmd = { + struct nvme_passthru_cmd nvme_cmd = { .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND, .nsid = 0, .addr = (__u64)(uintptr_t) cmd, @@ -8475,14 +9358,14 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F d); #endif nvme_cmd.result = 0; - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd); + err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL); if (err == NVME_SC_INTERNAL) { fprintf(stderr, "%s: WARNING : WDC : No log ID:x%x available\n", __func__, log_id); } else if (err != 0) { - fprintf(stderr, "%s: ERROR : WDC : NVMe Snd Mgmt Status:%s(x%x)\n", - __func__, nvme_status_to_string(err), err ); + fprintf(stderr, "%s: ERROR : WDC : NVMe Snd Mgmt\n", __func__); + nvme_show_status(err); } else { if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE) { @@ -8503,11 +9386,11 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F nvme_cmd.cdw14 = cdw14; nvme_cmd.cdw15 = cdw15; nvme_cmd.result = 0; /* returned result !=0 indicates more data available */ - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd); + err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL); if (err != 0) { more = 0; - fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt Status:%s(x%x)\n", - __func__, nvme_status_to_string(err), err); + fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt ", __func__); + nvme_show_status(err); } else { more = nvme_cmd.result & WDC_RESULT_MORE_DATA; response_size = nvme_cmd.result & ~WDC_RESULT_MORE_DATA; @@ -8529,8 +9412,8 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_ { __u8 *dump_data; __u32 curr_data_offset, curr_data_len; - int i, ret; - struct nvme_admin_cmd admin_cmd; + int i, ret = -1; + struct nvme_passthru_cmd admin_cmd; __u32 dump_length = data_len; __u32 numd; __u16 numdu, numdl; @@ -8541,7 +9424,7 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_ return -1; } memset(dump_data, 0, sizeof (__u8) * dump_length); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); curr_data_offset = 0; curr_data_len = xfer_size; i = 0; @@ -8560,9 +9443,9 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_ #ifdef WDC_NVME_CLI_DEBUG fprintf(stderr, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x \n", admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14); #endif - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - if (ret !=0 ) { - fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n",__func__, nvme_status_to_string(ret), ret); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + if (ret != 0) { + nvme_show_status(ret); fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", __func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr); break; diff --git a/plugins/wdc/wdc-nvme.h b/plugins/wdc/wdc-nvme.h index e046007..da21692 100644 --- a/plugins/wdc/wdc-nvme.h +++ b/plugins/wdc/wdc-nvme.h @@ -4,7 +4,7 @@ #if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ) #define WDC_NVME -#define WDC_PLUGIN_VERSION "1.15.4" +#define WDC_PLUGIN_VERSION "1.16.4" #include "cmd.h" PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION), @@ -37,6 +37,9 @@ PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERS ENTRY("cloud-SSD-plugin-version", "WDC Cloud SSD Plugin Version", wdc_cloud_ssd_plugin_version) ENTRY("vs-pcie-stats", "WDC VS PCIE Statistics", wdc_vs_pcie_stats) ENTRY("get-latency-monitor-log", "WDC Get Latency Monitor Log Page", wdc_get_latency_monitor_log) + ENTRY("get-error-recovery-log", "WDC Get Error Recovery Log Page", wdc_get_error_recovery_log) + ENTRY("get-dev-capabilities-log", "WDC Get Device Capabilities Log Page", wdc_get_dev_capabilities_log) + ENTRY("get-unsupported-reqs-log", "WDC Get Unsupported Requirements Log Page", wdc_get_unsupported_reqs_log) ) ); diff --git a/plugins/ymtc/ymtc-nvme.c b/plugins/ymtc/ymtc-nvme.c index 91e52be..dd5f004 100644 --- a/plugins/ymtc/ymtc-nvme.c +++ b/plugins/ymtc/ymtc-nvme.c @@ -4,15 +4,11 @@ #include <stdlib.h> #include <unistd.h> -#include "linux/nvme_ioctl.h" - #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" - -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "ymtc-nvme.h" @@ -116,7 +112,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, const char *raw = "dump output in binary format"; struct config { __u32 namespace_id; - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -133,8 +129,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, if (fd < 0) return fd; - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) err = show_ymtc_smart_log(fd, cfg.namespace_id, devicename, &smart_log); @@ -142,7 +138,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, 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); + nvme_show_status(err); return err; } diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index 2f765b6..56e53af 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -7,15 +7,110 @@ #include <linux/fs.h> #include <sys/stat.h> +#include "common.h" #include "nvme.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "nvme-print.h" -#include "nvme-status.h" #define CREATE_CMD #include "zns.h" static const char *namespace_id = "Namespace identifier to use"; +static const char dash[100] = { [0 ... 99] = '-' }; + +static int detect_zns(nvme_ns_t ns, int *out_supported) +{ + int err = 0; + char *zoned; + + *out_supported = 0; + + zoned = nvme_get_attr(nvme_ns_get_sysfs_dir(ns), "queue/zoned"); + if (!zoned) { + *out_supported = 0; + return err; + } + + *out_supported = strcmp("host-managed", zoned) == 0; + free(zoned); + + return err; +} + +static int print_zns_list_ns(nvme_ns_t ns) +{ + int supported; + int err = 0; + + err = detect_zns(ns, &supported); + if (err) { + perror("Failed to enumerate namespace"); + return err; + } + + if (supported) { + nvme_show_list_item(ns); + } + + return err; +} + +static int print_zns_list(nvme_root_t nvme_root) +{ + int err = 0; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_ns_t n; + nvme_for_each_host(nvme_root, h) + { + nvme_for_each_subsystem(h, s) + { + nvme_subsystem_for_each_ns(s, n) + { + err = print_zns_list_ns(n); + if (err) + return err; + } + + nvme_subsystem_for_each_ctrl(s, c) + { + nvme_ctrl_for_each_ns(c, n) + { + err = print_zns_list_ns(n); + if (err) + return err; + } + } + } + } + + return err; +} + +static int list(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + int err = 0; + nvme_root_t nvme_root; + + printf("%-21s %-20s %-40s %-9s %-26s %-16s %-8s\n", "Node", "SN", + "Model", "Namespace", "Usage", "Format", "FW Rev"); + printf("%-.21s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", dash, dash, + dash, dash, dash, dash, dash); + + nvme_root = nvme_scan(NULL); + if (nvme_root) { + err = print_zns_list(nvme_root); + } else { + fprintf(stderr, "Failed to scan nvme subsystems\n"); + err = -errno; + } + + nvme_free_tree(nvme_root); + + return err; +} static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { @@ -57,7 +152,7 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl perror("zns identify controller"); close_fd: close(fd); - return nvme_status_to_errno(err, false); + return err; } static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -76,8 +171,8 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug struct config { char *output_format; __u32 namespace_id; - int human_readable; - int vendor_specific; + bool human_readable; + bool vendor_specific; }; struct config cfg = { @@ -105,14 +200,14 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug flags |= VERBOSE; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; } } - err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns); if (err) { nvme_show_status(err); goto close_fd; @@ -127,18 +222,6 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug perror("zns identify namespace"); close_fd: close(fd); - return nvme_status_to_errno(err, false); -} - -static int __zns_mgmt_send(int fd, __u32 namespace_id, __u64 zslba, - bool select_all, __u32 timeout, enum nvme_zns_send_action zsa, - __u32 data_len, void *buf) -{ - int err; - - err = nvme_zns_mgmt_send(fd, namespace_id, zslba, select_all, timeout, zsa, - data_len, buf); - close(fd); return err; } @@ -149,8 +232,9 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug const char *select_all = "send command to all zones"; const char *timeout = "timeout value, in milliseconds"; - int err, fd; + int err, fd, zcapc = 0; char *command; + __u32 result; struct config { __u64 zslba; @@ -171,26 +255,42 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug err = fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) - return errno; + goto ret; err = asprintf(&command, "%s-%s", plugin->name, cmd->name); if (err < 0) goto close_fd; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto free; } } - err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba, - cfg.select_all, cfg.timeout, zsa, 0, NULL); - if (!err) - printf("%s: Success, action:%d zone:%"PRIx64" all:%d nsid:%d\n", + struct nvme_zns_mgmt_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.zslba, + .zsa = zsa, + .select_all = cfg.select_all, + .zsaso = 0, + .data_len = 0, + .data = NULL, + .timeout = cfg.timeout, + .result = &result, + }; + err = nvme_zns_mgmt_send(&args); + if (!err) { + if (zsa == NVME_ZNS_ZSA_RESET) + zcapc = result & 0x1; + + printf("%s: Success, action:%d zone:%"PRIx64" all:%d zcapc:%u nsid:%d\n", command, zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, - cfg.namespace_id); + zcapc, cfg.namespace_id); + } else if (err > 0) nvme_show_status(err); else @@ -199,7 +299,8 @@ free: free(command); close_fd: close(fd); - return nvme_status_to_errno(err, false); +ret: + return err; } static int get_zdes_bytes(int fd, __u32 nsid) @@ -209,7 +310,7 @@ static int get_zdes_bytes(int fd, __u32 nsid) __u8 lbaf; int err; - err = nvme_identify_ns(fd, nsid, false, &id_ns); + err = nvme_identify_ns(fd, nsid, &id_ns); if (err > 0) { nvme_show_status(err); return -1; @@ -227,14 +328,16 @@ static int get_zdes_bytes(int fd, __u32 nsid) return -1; } - lbaf = id_ns.flbas & NVME_NS_FLBAS_LBA_MASK; + nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf); return ns.lbafe[lbaf].zdes << 6; } static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Zone Management Send"; - const char *zslba = "starting LBA of the zone for this command"; + const char *zslba = "starting LBA of the zone for this command"\ + "(for flush action, last lba to flush)"; + const char *zsaso = "Zone Send Action Specific Option"; const char *select_all = "send command to all zones"; const char *zsa = "zone send action"; const char *data_len = "buffer length if data required"; @@ -247,6 +350,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu struct config { __u64 zslba; __u32 namespace_id; + bool zsaso; bool select_all; __u8 zsa; int data_len; @@ -259,6 +363,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba), + OPT_FLAG("zsaso", 'o', &cfg.zsaso, zsaso), OPT_FLAG("select-all", 'a', &cfg.select_all, select_all), OPT_BYTE("zsa", 'z', &cfg.zsa, zsa), OPT_UINT("data-len", 'l', &cfg.data_len, data_len), @@ -272,7 +377,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu return errno; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; @@ -287,15 +392,17 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu if (cfg.zsa == NVME_ZNS_ZSA_SET_DESC_EXT) { if(!cfg.data_len) { - cfg.data_len = get_zdes_bytes(fd, cfg.namespace_id); - if (!cfg.data_len || cfg.data_len < 0) { + int data_len = get_zdes_bytes(fd, cfg.namespace_id); + + if (data_len == 0) { fprintf(stderr, "Zone Descriptor Extensions are not supported\n"); goto close_fd; - } else if (cfg.data_len < 0) { - err = cfg.data_len; + } else if (data_len < 0) { + err = data_len; goto close_fd; } + cfg.data_len = data_len; } if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); @@ -325,8 +432,20 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu } } - err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba, cfg.select_all, - cfg.timeout, cfg.zsa, cfg.data_len, buf); + struct nvme_zns_mgmt_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.zslba, + .zsa = cfg.zsa, + .select_all = cfg.select_all, + .zsaso = cfg.zsaso, + .data_len = cfg.data_len, + .data = buf, + .timeout = cfg.timeout, + .result = NULL, + }; + err = nvme_zns_mgmt_send(&args); if (!err) printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" " "all:%d nsid:%d\n", @@ -344,7 +463,7 @@ free: free(buf); close_fd: close(fd); - return nvme_status_to_errno(err, false); + return err; } static int close_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -364,8 +483,67 @@ static int finish_zone(int argc, char **argv, struct command *cmd, struct plugin static int open_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Open zones\n"; + const char *zslba = "starting LBA of the zone for this command"; + const char *zrwaa = "Allocate Zone Random Write Area to zone"; + const char *select_all = "send command to all zones"; + const char *timeout = "timeout value, in milliseconds"; + + int err, fd; + + struct config { + __u64 zslba; + __u32 namespace_id; + bool zrwaa; + bool select_all; + __u32 timeout; + }; + + struct config cfg = { + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba), + OPT_FLAG("zrwaa", 'r', &cfg.zrwaa, zrwaa), + OPT_FLAG("select-all", 'a', &cfg.select_all, select_all), + OPT_UINT("timeout", 't', &cfg.timeout, timeout), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return errno; + + if (!cfg.namespace_id) { + err = nvme_get_nsid(fd, &cfg.namespace_id); + if (err < 0) { + perror("get-namespace-id"); + goto close_fd; + } + } - return zns_mgmt_send(argc, argv, cmd, plugin, desc, NVME_ZNS_ZSA_OPEN); + struct nvme_zns_mgmt_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.zslba, + .zsa = NVME_ZNS_ZSA_OPEN, + .select_all = cfg.select_all, + .zsaso = cfg.zrwaa, + .data_len = 0, + .data = NULL, + .timeout = cfg.timeout, + .result = NULL, + }; + err = nvme_zns_mgmt_send(&args); + if (!err) + printf("zns-open-zone: Success zone slba:%"PRIx64" nsid:%d\n", + (uint64_t)cfg.zslba, cfg.namespace_id); + else + nvme_show_status(err); +close_fd: + close(fd); + return err; } static int reset_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -386,15 +564,17 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug { const char *desc = "Set Zone Descriptor Extension\n"; const char *zslba = "starting LBA of the zone for this command"; + const char *zrwaa = "Allocate Zone Random Write Area to zone"; const char *data = "optional file for zone extention data (default stdin)"; const char *timeout = "timeout value, in milliseconds"; int fd, ffd = STDIN_FILENO, err; void *buf = NULL; - __u32 data_len; + int data_len; struct config { __u64 zslba; + bool zrwaa; __u32 namespace_id; char *file; __u32 timeout; @@ -405,6 +585,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba), + OPT_FLAG("zrwaa", 'r', &cfg.zrwaa, zrwaa), OPT_FILE("data", 'd', &cfg.file, data), OPT_UINT("timeout", 't', &cfg.timeout, timeout), OPT_END() @@ -415,7 +596,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug return errno; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; @@ -454,8 +635,20 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug goto close_ffd; } - err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba, 0, cfg.timeout, - NVME_ZNS_ZSA_SET_DESC_EXT, data_len, buf); + struct nvme_zns_mgmt_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.zslba, + .zsa = NVME_ZNS_ZSA_SET_DESC_EXT, + .select_all = 0, + .zsaso = cfg.zrwaa, + .data_len = data_len, + .data = buf, + .timeout = cfg.timeout, + .result = NULL, + }; + err = nvme_zns_mgmt_send(&args); if (!err) printf("set-zone-desc: Success, zone:%"PRIx64" nsid:%d\n", (uint64_t)cfg.zslba, cfg.namespace_id); @@ -470,7 +663,67 @@ free: free(buf); close_fd: close(fd); - return nvme_status_to_errno(err, false); + return err; +} + + +static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Flush Explicit ZRWA Range"; + const char *slba = "LBA to flush up to"; + const char *timeout = "timeout value, in milliseconds"; + + int err, fd; + + struct config { + __u64 lba; + __u32 namespace_id; + __u32 timeout; + }; + + struct config cfg = {}; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_SUFFIX("lba", 'l', &cfg.lba, slba), + OPT_UINT("timeout", 't', &cfg.timeout, timeout), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return errno; + + if (!cfg.namespace_id) { + err = nvme_get_nsid(fd, &cfg.namespace_id); + if (err < 0) { + perror("get-namespace-id"); + goto close_fd; + } + } + + struct nvme_zns_mgmt_send_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.lba, + .zsa = NVME_ZNS_ZSA_ZRWA_FLUSH, + .select_all = 0, + .zsaso = 0, + .data_len = 0, + .data = NULL, + .timeout = cfg.timeout, + .result = NULL, + }; + err = nvme_zns_mgmt_send(&args); + if (!err) + printf("zrwa-flush-zone: Success, lba:%"PRIx64" nsid:%d\n", + (uint64_t)cfg.lba, cfg.namespace_id); + else + nvme_show_status(err); +close_fd: + close(fd); + return err; } static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -520,7 +773,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu goto close_fd; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; @@ -541,8 +794,20 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu } } - err = nvme_zns_mgmt_recv(fd, cfg.namespace_id, cfg.zslba, cfg.zra, - cfg.zrasf, cfg.partial, cfg.data_len, data); + struct nvme_zns_mgmt_recv_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .slba = cfg.zslba, + .zra = cfg.zra, + .zrasf = cfg.zrasf, + .zras_feat = cfg.partial, + .data_len = cfg.data_len, + .data = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + err = nvme_zns_mgmt_recv(&args); if (!err) printf("zone-mgmt-recv: Success, action:%d zone:%"PRIx64" nsid:%d\n", cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id); @@ -554,7 +819,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu free(data); close_fd: close(fd); - return nvme_status_to_errno(err, false); + return err; } static int report_zones(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -584,6 +849,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi struct nvme_id_ns id_ns; uint8_t lbaf; __le64 zsze; + struct json_object *zone_list = 0; struct config { char *output_format; @@ -591,7 +857,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi __u32 namespace_id; int num_descs; int state; - int verbose; + bool verbose; bool extended; bool partial; }; @@ -624,7 +890,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi flags |= VERBOSE; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; @@ -639,7 +905,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi } } - err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns); if (err) { nvme_show_status(err); goto close_fd; @@ -648,7 +914,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi err = nvme_zns_identify_ns(fd, cfg.namespace_id, &id_zns); if (!err) { /* get zsze field from zns id ns data - needed for offset calculation */ - lbaf = id_ns.flbas & NVME_NS_FLBAS_LBA_MASK; + nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf); zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze); } else { @@ -664,7 +930,9 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi } err = nvme_zns_report_zones(fd, cfg.namespace_id, 0, - 0, cfg.state, 0, log_len, buff); + cfg.state, false, false, + log_len, buff, + NVME_DEFAULT_IOCTL_TIMEOUT, NULL); if (err > 0) { nvme_show_status(err); goto free_buff; @@ -695,7 +963,10 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi } offset = cfg.zslba; - printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones)); + if (flags & JSON) + zone_list = json_create_array(); + else + printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones)); while (nr_zones_retrieved < nr_zones) { if (nr_zones_retrieved >= nr_zones) @@ -707,27 +978,32 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi } err = nvme_zns_report_zones(fd, cfg.namespace_id, offset, - cfg.extended, cfg.state, cfg.partial, log_len, report); + cfg.state, cfg.extended, + cfg.partial, log_len, report, + NVME_DEFAULT_IOCTL_TIMEOUT, NULL); if (err > 0) { nvme_show_status(err); break; } if (!err) - nvme_show_zns_report_zones(report, nr_zones_chunks, zdes, - log_len, flags); + nvme_show_zns_report_zones(report, nr_zones_chunks, + zdes, log_len, flags, zone_list); nr_zones_retrieved += nr_zones_chunks; offset = (nr_zones_retrieved * zsze); } + if (flags & JSON) + json_nvme_finish_zone_list(total_nr_zones, zone_list); + nvme_free(report, huge); free_buff: free(buff); close_fd: close(fd); - return nvme_status_to_errno(err, false); + return err; } static int zone_append(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -754,6 +1030,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin void *buf = NULL, *mbuf = NULL; __u16 nblocks, control = 0; __u64 result; + __u8 lba_index; struct timeval start_time, end_time; struct nvme_id_ns ns; @@ -764,15 +1041,15 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin __u64 zslba; __u64 data_size; __u64 metadata_size; - int limited_retry; - int fua; + bool limited_retry; + bool fua; __u32 namespace_id; __u32 ref_tag; __u16 lbat; __u16 lbatm; __u8 prinfo; - int piremap; - int latency; + bool piremap; + bool latency; }; struct config cfg = {}; @@ -806,49 +1083,50 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin } if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; } } - err = nvme_identify_ns(fd, cfg.namespace_id, false, &ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &ns); if (err) { nvme_show_status(err); goto close_fd; } - lba_size = 1 << ns.lbaf[(ns.flbas & 0x0f)].ds; + nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index); + lba_size = 1 << ns.lbaf[lba_index].ds; if (cfg.data_size & (lba_size - 1)) { fprintf(stderr, "Data size:%#"PRIx64" not aligned to lba size:%#x\n", (uint64_t)cfg.data_size, lba_size); errno = EINVAL; - goto close_ns; + goto close_fd; } - meta_size = ns.lbaf[(ns.flbas & 0x0f)].ms; + meta_size = ns.lbaf[lba_index].ms; if (meta_size && !(meta_size == 8 && (cfg.prinfo & 0x8)) && (!cfg.metadata_size || cfg.metadata_size % meta_size)) { fprintf(stderr, "Metadata size:%#"PRIx64" not aligned to metadata size:%#x\n", (uint64_t)cfg.metadata_size, meta_size); errno = EINVAL; - goto close_ns; + goto close_fd; } if (cfg.prinfo > 0xf) { fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo); errno = EINVAL; - goto close_ns; + goto close_fd; } if (cfg.data) { dfd = open(cfg.data, O_RDONLY); if (dfd < 0) { perror(cfg.data); - goto close_ns; + goto close_fd; } } @@ -870,7 +1148,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin if (mfd < 0) { perror(cfg.metadata); err = -1; - goto close_dfd; + goto free_data; } } @@ -893,17 +1171,32 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin nblocks = (cfg.data_size / lba_size) - 1; control |= (cfg.prinfo << 10); if (cfg.limited_retry) - control |= NVME_RW_LR; + control |= NVME_IO_LR; if (cfg.fua) - control |= NVME_RW_FUA; + control |= NVME_IO_FUA; if (cfg.piremap) - control |= NVME_RW_PIREMAP; + control |= NVME_IO_ZNS_APPEND_PIREMAP; + + struct nvme_zns_append_args args = { + .args_size = sizeof(args), + .fd = fd, + .nsid = cfg.namespace_id, + .zslba = cfg.zslba, + .nlb = nblocks, + .control = control, + .ilbrt = cfg.ref_tag, + .lbat = cfg.lbat, + .lbatm = cfg.lbatm, + .data_len = cfg.data_size, + .data = buf, + .metadata_len = cfg.metadata_size, + .metadata = mbuf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; gettimeofday(&start_time, NULL); - err = nvme_zns_append(fd, cfg.namespace_id, cfg.zslba, nblocks, - control, cfg.ref_tag, cfg.lbat, cfg.lbatm, - cfg.data_size, buf, cfg.metadata_size, mbuf, - &result); + err = nvme_zns_append(&args); gettimeofday(&end_time, NULL); if (cfg.latency) printf(" latency: zone append: %llu us\n", @@ -926,10 +1219,9 @@ free_data: close_dfd: if (cfg.data) close(dfd); -close_ns: close_fd: close(fd); - return nvme_status_to_errno(err, false); + return err; } static int changed_zone_list(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -967,15 +1259,14 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct goto close_fd; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; } } - err = nvme_get_log(fd, cfg.namespace_id, NVME_LOG_ZONE_CHANGED_LIST, - cfg.rae, NVME_NO_LOG_LSP, sizeof(log), &log); + err = nvme_get_log_zns_changed_zones(fd, cfg.namespace_id, cfg.rae, &log); if (!err) nvme_show_zns_changed(&log, flags); else if (err > 0) @@ -985,5 +1276,5 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct close_fd: close(fd); - return nvme_status_to_errno(err, false); + return err; } diff --git a/plugins/zns/zns.h b/plugins/zns/zns.h index 61063f7..1bdd4d9 100644 --- a/plugins/zns/zns.h +++ b/plugins/zns/zns.h @@ -8,23 +8,24 @@ PLUGIN(NAME("zns", "Zoned Namespace Command Set", NVME_VERSION), COMMAND_LIST( - ENTRY("id-ctrl", "Retrieve ZNS controller identification", id_ctrl) - ENTRY("id-ns", "Retrieve ZNS namespace identification", id_ns) - ENTRY("zone-mgmt-recv", "Sends the zone management receive command", zone_mgmt_recv) - ENTRY("zone-mgmt-send", "Sends the zone management send command", zone_mgmt_send) - ENTRY("report-zones", "Retrieve the Report Zones report", report_zones) - ENTRY("close-zone", "Closes one or more zones", close_zone) - ENTRY("finish-zone", "Finishes one or more zones", finish_zone) - ENTRY("open-zone", "Opens one or more zones", open_zone) - ENTRY("reset-zone", "Resets one or more zones", reset_zone) - ENTRY("offline-zone", "Offlines one or more zones", offline_zone) - ENTRY("set-zone-desc", "Attaches zone descriptor extension data", set_zone_desc) - ENTRY("zone-append", "Writes data and metadata (if applicable), appended to the end of the requested zone", zone_append) - ENTRY("changed-zone-list", "Retrieves the changed zone list log", changed_zone_list) + ENTRY("list", "List all NVMe devices with Zoned Namespace Command Set support", list) + ENTRY("id-ctrl", "Send NVMe Identify Zoned Namespace Controller, display structure", id_ctrl) + ENTRY("id-ns", "Send NVMe Identify Zoned Namespace Namespace, display structure", id_ns) + ENTRY("report-zones", "Report zones associated to a Zoned Namespace", report_zones) + ENTRY("reset-zone", "Reset one or more zones", reset_zone) + ENTRY("close-zone", "Close one or more zones", close_zone) + ENTRY("finish-zone", "Finishe one or more zones", finish_zone) + ENTRY("open-zone", "Open one or more zones", open_zone) + ENTRY("offline-zone", "Offline one or more zones", offline_zone) + ENTRY("set-zone-desc", "Attach zone descriptor extension data to a zone", set_zone_desc) + ENTRY("zrwa-flush-zone", "Flush LBAs associated with a ZRWA to a zone.", zrwa_flush_zone) + ENTRY("changed-zone-list", "Retrieve the changed zone list log", changed_zone_list) + ENTRY("zone-mgmt-recv", "Send the zone management receive command", zone_mgmt_recv) + ENTRY("zone-mgmt-send", "Send the zone management send command", zone_mgmt_send) + ENTRY("zone-append", "Append data and metadata (if applicable) to a zone", zone_append) ) ); #endif #include "define_cmd.h" - diff --git a/scripts/gen-hostnqn.sh b/scripts/gen-hostnqn.sh index 563aa60..3333a86 100644 --- a/scripts/gen-hostnqn.sh +++ b/scripts/gen-hostnqn.sh @@ -1,28 +1,3 @@ -#!/bin/bash +#!/bin/sh -LC_ALL=C - -if [ -e "/proc/device-tree/ibm,partition-uuid" ] ; then - UUID=$(tr -d '\0' < /proc/device-tree/ibm,partition-uuid) -else - UUID=$(dmidecode -s system-uuid | tr -d '[:space:]') -fi - -if [ -z "$UUID" ] ; then - >&2 echo "No UUID found, can't determine hostnqn." - exit 1 -fi - -# convert UUID to lower-case only: -UUID=$(echo $UUID | tr '[:upper:]' '[:lower:]') - -# check UUID format, e.g.: 4c4c4544-0156-4a10-8134-b7d04f383232, so: 8-4-4-4-12 -if ! [[ $UUID =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]] ; then - >&2 echo "UUID has invalid format." - >&2 echo "Invalid UUID: ${UUID}" - exit 2 -fi - -HOSTNQN="nqn.2014-08.org.nvmexpress:uuid:${UUID}" - -echo $HOSTNQN +nvme gen-hostnqn diff --git a/subprojects/json-c.wrap b/subprojects/json-c.wrap new file mode 100644 index 0000000..4ce9ab8 --- /dev/null +++ b/subprojects/json-c.wrap @@ -0,0 +1,12 @@ +[wrap-file] +directory = json-c-0.15 +source_url = https://s3.amazonaws.com/json-c_releases/releases/json-c-0.15.tar.gz +source_filename = json-c-0.15.tar.gz +source_hash = b8d80a1ddb718b3ba7492916237bbf86609e9709fb007e7f7d4322f02341a4c6 +patch_filename = json-c_0.15-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/json-c_0.15-2/get_patch +patch_hash = 2c5c95cf463804ac61309930c76ba9f57b157fef6247d1c6da4395b31a5bfac7 + +[provide] +json-c = json_c_dep + diff --git a/subprojects/libnvme.wrap b/subprojects/libnvme.wrap new file mode 100644 index 0000000..e90127c --- /dev/null +++ b/subprojects/libnvme.wrap @@ -0,0 +1,6 @@ +[wrap-git] +url = https://github.com/linux-nvme/libnvme.git +revision = 033449f7c61c130fd21f0a747075dc15069f73f0 + +[provide] +libnvme = libnvme_dep diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap new file mode 100644 index 0000000..3c7b575 --- /dev/null +++ b/subprojects/zlib.wrap @@ -0,0 +1,12 @@ +[wrap-file] +directory = zlib-1.2.12 +source_url = http://zlib.net/fossils/zlib-1.2.12.tar.gz +source_filename = zlib-1.2.12.tar.gz +source_hash = 91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9 +patch_filename = zlib_1.2.12-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.2.12-1/get_patch +patch_hash = 8ec8344f3fe7b06ad4be768fd416694bc56cb4545ce78b0f1c18b3e72b3ec936 + +[provide] +zlib = zlib_dep + diff --git a/tests/Makefile b/tests/Makefile deleted file mode 100644 index c0f9f31..0000000 --- a/tests/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -############################################################################### -# -# 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 diff --git a/tests/README b/tests/README index 686bd04..b6a4d77 100644 --- a/tests/README +++ b/tests/README @@ -11,18 +11,16 @@ nvmetests 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) + 1. Python(>= 3.3) + 2. nose2 (Installation guide http://nose2.readthedocs.io/) + 3. flake8 (https://pypi.python.org/pypi/flake8) + 4. mypy (https://pypi.org/project/mypy/) + 5. autopep8 (https://pypi.org/project/autopep8/) + 6. isort (https://pypi.org/project/isort/) 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 + $ pip install nose2 flake8 mypy autopep8 isort 2. Overview ----------- @@ -76,12 +74,12 @@ nvmetests 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. + a. Run flake8, mypy, autopep8 and isort on the testcase and fix + errors/warnings. + - Example "$ ninja -C .build lint-python" will run flake8 and + mypy on all the python files in current directory. + - Example "$ ninja -C .build format-python" will run autopep8 and + isort on all the python files in the current directory. 4. Running testcases with framework ----------------------------------- @@ -89,5 +87,5 @@ nvmetests $ nose2 --verbose nvme_writezeros_test $ nose2 --verbose nvme_read_write_test - 2. Running all the testcases with Makefile :- - $ make run + 2. Running all the testcases with ninja :- + $ ninja test -C .build diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..feecb3d --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,79 @@ +tests = [ + 'nvme_attach_detach_ns_test', + 'nvme_compare_test', + 'nvme_create_max_ns_test', + 'nvme_error_log_test', + 'nvme_flush_test', + 'nvme_format_test', + 'nvme_fw_log_test', + 'nvme_get_features_test', + 'nvme_id_ctrl_test', + 'nvme_id_ns_test', + 'nvme_read_write_test', + 'nvme_simple_template_test', + 'nvme_smart_log_test', + 'nvme_test_io', + 'nvme_test_logger', + 'nvme_test', + 'nvme_writeuncor_test', + 'nvme_writezeros_test', + 'nvme_copy_test', + 'nvme_dsm_test', + 'nvme_verify_test', + 'nvme_lba_status_log_test', + 'nvme_get_lba_status_test', +] + +runtests = find_program('nose2', required : false) + +if runtests.found() + foreach t : tests + test(t, runtests, + args: ['--verbose', '--start-dir', meson.current_source_dir(), t], + workdir: meson.current_source_dir(), + env: ['PATH=' + meson.build_root() + ':/usr/bin:/usr/sbin'], + timeout: 500) + endforeach +endif + +python_module = import('python') + +python = python_module.find_installation('python3') + +mypy = find_program( + 'mypy', + required : false, +) +flake8 = find_program( + 'flake8', + required : false, +) +linter_script = files('run_py_linters.py') + +if mypy.found() and flake8.found() + run_target( + 'lint-python', + command : [python, linter_script, 'lint'], + ) +else + message('Mypy or Flake8 not found. Python linting disabled') +endif + + +autopep8 = find_program( + 'autopep8', + required : false, +) +isort = find_program( + 'isort', + required : false, +) + +if autopep8.found() and isort.found() + run_target( + 'format-python', + command : [python, linter_script, 'format'], + ) +else + message('autopep8 or isort not found. Python formating disabled') +endif diff --git a/tests/nvme_attach_detach_ns_test.py b/tests/nvme_attach_detach_ns_test.py index 92a82dd..5ba0d48 100644 --- a/tests/nvme_attach_detach_ns_test.py +++ b/tests/nvme_attach_detach_ns_test.py @@ -28,6 +28,7 @@ NVMe Namespace Management Testcase:- """ import time + from nose.tools import assert_equal from nvme_test import TestNVMe diff --git a/tests/nvme_copy_test.py b/tests/nvme_copy_test.py new file mode 100644 index 0000000..8bee555 --- /dev/null +++ b/tests/nvme_copy_test.py @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# This file is part of nvme-cli +# +# Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Author: Arunpandian J <apj.arun@samsung.com> + +""" +NVMe Copy Testcase:- + + 1. Issue copy command on set of block; shall pass. + +""" + +from nose.tools import assert_equal +from nvme_test import TestNVMe + + +class TestNVMeCopy(TestNVMe): + + """ + Represents NVMe Verify testcase. + - Attributes: + - start_block : starting block of to verify operation. + - range : Range of blocks for DSM operation. + - slbs : 64-bit addr of first block per range + - test_log_dir : directory for logs, temp files. + """ + + def __init__(self): + """ Pre Section for TestNVMeCopy """ + TestNVMe.__init__(self) + self.start_block = 0 + self.range = 1 + self.slbs = 1 + self.namespace = 1 + self.setup_log_dir(self.__class__.__name__) + + def __del__(self): + """ Post Section for TestNVMeCopy """ + TestNVMe.__del__(self) + + def copy(self): + """ Wrapper for nvme copy + - Args: + - None + - Returns: + - return code for nvme copy command. + """ + copy_cmd = "nvme copy " + self.ctrl + \ + " --namespace-id=" + str(self.namespace) + \ + " --sdlba=" + str(self.start_block) + \ + " --blocks=" + str(self.range) + \ + " --slbs=" + str(self.range) + return self.exec_cmd(copy_cmd) + + def test_copy(self): + """ Testcase main """ + assert_equal(self.copy(), 0) diff --git a/tests/nvme_create_max_ns_test.py b/tests/nvme_create_max_ns_test.py index 33a66b7..3316eec 100644 --- a/tests/nvme_create_max_ns_test.py +++ b/tests/nvme_create_max_ns_test.py @@ -28,6 +28,7 @@ NVMe Namespace Management Testcase:- """ import time + from nose.tools import assert_equal from nvme_test import TestNVMe @@ -50,7 +51,8 @@ class TestNVMeCreateMaxNS(TestNVMe): TestNVMe.__init__(self) self.dps = 0 self.flbas = 0 - self.nsze = int(self.get_ncap() / self.get_format() / self.get_max_ns()) + self.nsze = int(self.get_ncap() / + self.get_format() / self.get_max_ns()) self.ncap = self.nsze self.setup_log_dir(self.__class__.__name__) self.max_ns = self.get_max_ns() diff --git a/tests/nvme_dsm_test.py b/tests/nvme_dsm_test.py new file mode 100644 index 0000000..fe3dc01 --- /dev/null +++ b/tests/nvme_dsm_test.py @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# This file is part of nvme-cli +# +# Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Author: Arunpandian J <apj.arun@samsung.com> + +""" +NVMe DSM Testcase:- + + 1. Issue DSM command on set of block; shall pass. + +""" + +from nose.tools import assert_equal +from nvme_test import TestNVMe + + +class TestNVMeDsm(TestNVMe): + + """ + Represents NVMe Verify testcase. + - Attributes: + - start_block : starting block of to verify operation. + - range : Range of blocks for DSM operation. + - test_log_dir : directory for logs, temp files. + """ + + def __init__(self): + """ Pre Section for TestNVMeDsm """ + TestNVMe.__init__(self) + self.start_block = 0 + self.range = 0 + self.namespace = 1 + self.setup_log_dir(self.__class__.__name__) + + def __del__(self): + """ Post Section for TestNVMeDsm """ + TestNVMe.__del__(self) + + def dsm(self): + """ Wrapper for nvme verify + - Args: + - None + - Returns: + - return code for nvme dsm command. + """ + dsm_cmd = "nvme dsm " + self.ctrl + \ + " --namespace-id=" + str(self.namespace) + \ + " --blocks=" + str(self.range) + \ + " --slbs=" + str(self.start_block) + return self.exec_cmd(dsm_cmd) + + def test_dsm(self): + """ Testcase main """ + assert_equal(self.dsm(), 0) diff --git a/tests/nvme_format_test.py b/tests/nvme_format_test.py index 55092fa..6a00ab6 100644 --- a/tests/nvme_format_test.py +++ b/tests/nvme_format_test.py @@ -35,8 +35,9 @@ Namespace Format testcase :- - Delete Namespace. """ -import time import subprocess +import time + from nose.tools import assert_equal from nvme_test import TestNVMe @@ -130,8 +131,8 @@ class TestNVMeFormatCmd(TestNVMe): # 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]) + \ + 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, diff --git a/tests/nvme_fw_log_test.py b/tests/nvme_fw_log_test.py index adb6386..c07ab84 100644 --- a/tests/nvme_fw_log_test.py +++ b/tests/nvme_fw_log_test.py @@ -25,6 +25,7 @@ NVMe Firmware Log Testcase :- """ import subprocess + from nose.tools import assert_equal from nvme_test import TestNVMe @@ -62,7 +63,7 @@ class TestNVMeFwLogCmd(TestNVMe): stdout=subprocess.PIPE, encoding='utf-8') fw_log_output = proc.communicate()[0] - print(fw_log_output + "\n") + print("\n" + fw_log_output + "\n") err = proc.wait() return err diff --git a/tests/nvme_get_features_test.py b/tests/nvme_get_features_test.py index 2e407ef..e327bb0 100644 --- a/tests/nvme_get_features_test.py +++ b/tests/nvme_get_features_test.py @@ -33,6 +33,7 @@ Test the Mandatory features with get features command:- """ import subprocess + from nose.tools import assert_equal from nvme_test import TestNVMe diff --git a/tests/nvme_get_lba_status_test.py b/tests/nvme_get_lba_status_test.py new file mode 100644 index 0000000..5f970c4 --- /dev/null +++ b/tests/nvme_get_lba_status_test.py @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# This file is part of nvme-cli +# +# Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Author: Arunpandian J <apj.arun@samsung.com> + +""" +NVMe LBA Status Log Testcase :- + + 1. Execute get-lba-status on a device. +""" + +import subprocess + +from nose.tools import assert_equal +from nvme_test import TestNVMe + + +class TestNVMeGetLbaStatusCmd(TestNVMe): + + """ + Represents Get LBA Status test. + """ + + def __init__(self): + """ Pre Section for TestNVMeGetLbaStatusCmd. """ + TestNVMe.__init__(self) + self.start_lba = 0 + self.block_count = 0 + self.namespace = 1 + self.max_dw = 1 + self.action = 11 + self.range_len = 1 + self.setup_log_dir(self.__class__.__name__) + + def __del__(self): + """ + Post Section for TestNVMeGetLbaStatusCmd. + + - Call super class's destructor. + """ + TestNVMe.__del__(self) + + def get_lba_status(self): + """ Wrapper for executing nvme get-lba-status. + - Args: + - None + - Returns: + - 0 on success, error code on failure. + """ + err = 0 + get_lba_status_cmd = "nvme get-lba-status " + self.ctrl + \ + " --namespace-id=" + str(self.namespace) + \ + " --start-lba=" + str(self.start_lba) + \ + " --max-dw=" + str(self.max_dw) + \ + " --action=" + str(self.action) + \ + " --range-len=" + str(self.range_len) + proc = subprocess.Popen(get_lba_status_cmd, + shell=True, + stdout=subprocess.PIPE, + encoding='utf-8') + get_lba_status_output = proc.communicate()[0] + print("\n" + get_lba_status_output + "\n") + err = proc.wait() + return err + + def test_get_lba_status(self): + """ Testcase main """ + assert_equal(self.get_lba_status(), 0) diff --git a/tests/nvme_id_ns_test.py b/tests/nvme_id_ns_test.py index cf56187..12e7dc8 100644 --- a/tests/nvme_id_ns_test.py +++ b/tests/nvme_id_ns_test.py @@ -26,6 +26,7 @@ NVme Identify Namespace Testcase:- """ import subprocess + from nose.tools import assert_equal from nvme_test import TestNVMe @@ -78,7 +79,7 @@ class TestNVMeIdentifyNamespace(TestNVMe): - 0 on success, error code on failure. """ err = 0 - for namespace in self.ns_list: + for namespace in self.ns_list: err = self.get_id_ns(str(namespace)) return err diff --git a/tests/nvme_lba_status_log_test.py b/tests/nvme_lba_status_log_test.py new file mode 100644 index 0000000..ecc3fce --- /dev/null +++ b/tests/nvme_lba_status_log_test.py @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# This file is part of nvme-cli +# +# Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Author: Arunpandian J <apj.arun@samsung.com> + +""" +NVMe LBA Status Log Testcase :- + + 1. Execute lba-status-log on a device. +""" + +import subprocess + +from nose.tools import assert_equal +from nvme_test import TestNVMe + + +class TestNVMeLbaStatLogCmd(TestNVMe): + + """ + Represents LBA Status Log test. + """ + + def __init__(self): + """ Pre Section for TestNVMeLbaStatLogCmd. """ + TestNVMe.__init__(self) + self.setup_log_dir(self.__class__.__name__) + + def __del__(self): + """ + Post Section for TestNVMeLbaStatLogCmd. + + - Call super class's destructor. + """ + TestNVMe.__del__(self) + + def get_lba_stat_log(self): + """ Wrapper for executing nvme lba-status-log. + - Args: + - None + - Returns: + - 0 on success, error code on failure. + """ + err = 0 + lba_stat_log_cmd = "nvme lba-status-log " + self.ctrl + proc = subprocess.Popen(lba_stat_log_cmd, + shell=True, + stdout=subprocess.PIPE, + encoding='utf-8') + lba_stat_log_output = proc.communicate()[0] + print("\n" + lba_stat_log_output + "\n") + err = proc.wait() + return err + + def test_lba_stat_log(self): + """ Testcase main """ + assert_equal(self.get_lba_stat_log(), 0) diff --git a/tests/nvme_read_write_test.py b/tests/nvme_read_write_test.py index 4a04f8a..528c791 100644 --- a/tests/nvme_read_write_test.py +++ b/tests/nvme_read_write_test.py @@ -27,6 +27,7 @@ NVMe Read/Write Testcae:- """ import filecmp + from nose.tools import assert_equal from nvme_test_io import TestNVMeIO @@ -41,6 +42,7 @@ class TestNVMeReadWriteTest(TestNVMeIO): - compare_file : data file to use in nvme compare command. - test_log_dir : directory for logs, temp files. """ + def __init__(self): """ Pre Section for TestNVMeReadWriteTest """ TestNVMeIO.__init__(self) diff --git a/tests/nvme_smart_log_test.py b/tests/nvme_smart_log_test.py index e1eb6e5..356aa08 100644 --- a/tests/nvme_smart_log_test.py +++ b/tests/nvme_smart_log_test.py @@ -83,4 +83,6 @@ class TestNVMeSmartLogCmd(TestNVMe): def test_smart_log(self): """ Testcase main """ assert_equal(self.get_smart_log_ctrl(), 0) - assert_equal(self.get_smart_log_all_ns(), 0) + smlp = self.supp_check_id_ctrl("lpa") + if smlp & 0x1 == True: + assert_equal(self.get_smart_log_all_ns(), 0) diff --git a/tests/nvme_test.py b/tests/nvme_test.py index b49c12f..11c89fe 100644 --- a/tests/nvme_test.py +++ b/tests/nvme_test.py @@ -20,15 +20,16 @@ """ Base class for all the testcases """ -import re -import os -import sys import json import mmap -import stat -import time +import os +import re import shutil +import stat import subprocess +import sys +import time + from nose import tools from nose.tools import assert_equal from nvme_test_logger import TestNVMeLogger @@ -477,3 +478,26 @@ class TestNVMe(object): encoding='utf-8') run_io_result = run_io.communicate()[1] assert_equal(run_io_result, None) + + def supp_check_id_ctrl(self, key): + """ Wrapper for support check. + - Args: + - key : search key. + - Returns: + - value for key requested. + """ + id_ctrl = "nvme id-ctrl " + self.ctrl + print("\n" + id_ctrl) + proc = subprocess.Popen(id_ctrl, + shell=True, + stdout=subprocess.PIPE, + encoding='utf-8') + err = proc.wait() + assert_equal(err, 0, "ERROR : nvme Identify controller Data \ + structure failed") + for line in proc.stdout: + if key in line: + key = line.replace(",", "", 1) + print(key) + val = (key.split(':'))[1].strip() + return int(val, 16) diff --git a/tests/nvme_test_io.py b/tests/nvme_test_io.py index 0c5c6bb..aab502a 100644 --- a/tests/nvme_test_io.py +++ b/tests/nvme_test_io.py @@ -20,6 +20,7 @@ """ Inherit TestNVMeIO for nvme read/write operations """ import os + from nose import tools from nvme_test import TestNVMe diff --git a/tests/nvme_test_logger.py b/tests/nvme_test_logger.py index c59fa18..5681628 100644 --- a/tests/nvme_test_logger.py +++ b/tests/nvme_test_logger.py @@ -26,6 +26,7 @@ import sys class TestNVMeLogger(object): """ Represents Logger for NVMe Testframework. """ + def __init__(self, log_file_path): """ Logger setup - Args: diff --git a/tests/nvme_verify_test.py b/tests/nvme_verify_test.py new file mode 100644 index 0000000..c783d5d --- /dev/null +++ b/tests/nvme_verify_test.py @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# This file is part of nvme-cli +# +# Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Author: Arunpandian J <apj.arun@samsung.com> + +""" +NVMe Verify Testcase:- + + 1. Issue verify command on set of block; shall pass. + +""" + +from nose.tools import assert_equal +from nvme_test import TestNVMe + + +class TestNVMeVerify(TestNVMe): + + """ + Represents NVMe Verify testcase. + - Attributes: + - start_block : starting block of to verify operation. + - test_log_dir : directory for logs, temp files. + """ + + def __init__(self): + """ Pre Section for TestNVMeVerify """ + TestNVMe.__init__(self) + self.start_block = 0 + self.block_count = 0 + self.namespace = 1 + self.setup_log_dir(self.__class__.__name__) + + def __del__(self): + """ Post Section for TestNVMeVerify """ + TestNVMe.__del__(self) + + def verify(self): + """ Wrapper for nvme verify + - Args: + - None + - Returns: + - return code for nvme verify command. + """ + verify_cmd = "nvme verify " + self.ctrl + \ + " --namespace-id=" + str(self.namespace) + \ + " --start-block=" + str(self.start_block) + \ + " --block-count=" + str(self.block_count) + return self.exec_cmd(verify_cmd) + + def test_verify(self): + """ Testcase main """ + assert_equal(self.verify(), 0) diff --git a/tests/nvme_writezeros_test.py b/tests/nvme_writezeros_test.py index 157fd78..ba3538c 100644 --- a/tests/nvme_writezeros_test.py +++ b/tests/nvme_writezeros_test.py @@ -28,6 +28,7 @@ NVMe Write Zeros:- """ import filecmp + from nose.tools import assert_equal from nvme_test_io import TestNVMeIO @@ -44,6 +45,7 @@ class TestNVMeWriteZeros(TestNVMeIO): - 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) diff --git a/tests/run_py_linters.py b/tests/run_py_linters.py new file mode 100644 index 0000000..869b3e4 --- /dev/null +++ b/tests/run_py_linters.py @@ -0,0 +1,123 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# Copied from https://github.com/python-sdbus/python-sdbus +# Copyright (C) 2020, 2021 igo95862 + +# This file is part of nvme-cli + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# This library 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 +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +from __future__ import annotations + +from argparse import ArgumentParser +from os import environ +from pathlib import Path +from subprocess import run +from typing import List + +source_root = Path(environ['MESON_SOURCE_ROOT']) +build_dir = Path(environ['MESON_BUILD_ROOT']) + +tests_dir = source_root / 'tests' + +all_python_modules = [ + tests_dir, +] + +mypy_cache_dir = build_dir / '.mypy_cache' + + +def run_mypy(path: Path) -> None: + print(f"Running mypy on {path}") + run( + args=( + 'mypy', '--strict', + '--cache-dir', mypy_cache_dir, + '--python-version', '3.8', + '--namespace-packages', + '--ignore-missing-imports', + path, + ), + check=False, + env={'MYPYPATH': str(tests_dir.absolute()), **environ}, + ) + + +def linter_main() -> None: + run( + args=( + 'flake8', + *all_python_modules, + ), + check=False, + ) + + for x in all_python_modules: + run_mypy(x) + + +def get_all_python_files() -> List[Path]: + python_files: List[Path] = [] + + for python_module in all_python_modules: + if python_module.is_dir(): + for a_file in python_module.iterdir(): + if a_file.suffix == '.py': + python_files.append(a_file) + else: + python_files.append(python_module) + + return python_files + + +def formater_main() -> None: + all_python_files = get_all_python_files() + + run( + args=('autopep8', '--in-place', *all_python_files), + check=False, + ) + + run( + args=( + 'isort', + '-m', 'VERTICAL_HANGING_INDENT', + '--trailing-comma', + *all_python_files, + ), + check=False, + ) + + +def main() -> None: + parser = ArgumentParser() + parser.add_argument( + 'mode', + choices=('lint', 'format'), + ) + + args = parser.parse_args() + + mode = args.mode + + if mode == 'lint': + linter_main() + elif mode == 'format': + formater_main() + else: + raise ValueError('Unknown mode', mode) + + +if __name__ == '__main__': + main() diff --git a/update-docs.sh b/update-docs.sh new file mode 100755 index 0000000..9dbbb26 --- /dev/null +++ b/update-docs.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +BUILDDIR="$(mktemp -d)" +trap 'rm -rf -- $BUILDDIR' EXIT + +meson $BUILDDIR -Ddocs=all -Ddocs-build=true +ninja -C $BUILDDIR +find $BUILDDIR/Documentation -maxdepth 1 \ + \( -name '*.1' -o -name '*.html' \) \ + -exec cp {} Documentation/ \; diff --git a/util/argconfig.c b/util/argconfig.c index 341a049..59d8f1d 100644 --- a/util/argconfig.c +++ b/util/argconfig.c @@ -39,6 +39,7 @@ #include <stdlib.h> #include <stdarg.h> #include <string.h> +#include <stdbool.h> static argconfig_help_func *help_funcs[MAX_HELP_FUNC] = { NULL }; @@ -176,17 +177,8 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, 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; - } + long_opts[option_index].flag = NULL; + long_opts[option_index].val = 0; } option_index++; } @@ -219,10 +211,6 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, } 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]; @@ -282,7 +270,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, } *((uint32_t *) value_addr) = tmp; } else if (s->config_type == CFG_INCREMENT) { - (*((int *)value_addr))++; + *((int *)value_addr) += 1; } else if (s->config_type == CFG_LONG) { *((unsigned long *)value_addr) = strtoul(optarg, &endptr, 0); if (errno || optarg == endptr) { @@ -363,6 +351,8 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, goto out; } *((FILE **) value_addr) = f; + } else if (s->config_type == CFG_FLAG) { + *((bool *)value_addr) = true; } } free(short_opts); diff --git a/util/argconfig.h b/util/argconfig.h index 3147277..a11334b 100644 --- a/util/argconfig.h +++ b/util/argconfig.h @@ -38,7 +38,7 @@ #include <stdarg.h> enum argconfig_types { - CFG_NONE, + CFG_FLAG, CFG_STRING, CFG_INT, CFG_SIZE, @@ -65,7 +65,7 @@ enum argconfig_types { #define OPT_END() { NULL } #define OPT_FLAG(l, s, v, d) \ - {l, s, NULL, CFG_NONE, v, no_argument, d} + {l, s, NULL, CFG_FLAG, v, no_argument, d} #define OPT_SUFFIX(l, s, v, d) \ {l, s, "IONUM", CFG_LONG_SUFFIX, v, required_argument, d} @@ -91,12 +91,16 @@ enum argconfig_types { #define OPT_SHRT(l, s, v, d) \ {l, s, "NUM", CFG_SHORT, v, required_argument, d} +#define OPT_INCR(l, s, v, d) \ + {l, s, "NUM", CFG_INCREMENT, v, no_argument, d} + #define OPT_STRING(l, s, m, v, d) \ {l, s, m, CFG_STRING, v, required_argument, d} #define OPT_FMT(l, s, v, d) OPT_STRING(l, s, "FMT", v, d) #define OPT_FILE(l, s, v, d) OPT_STRING(l, s, "FILE", v, d) #define OPT_LIST(l, s, v, d) OPT_STRING(l, s, "LIST", v, d) +#define OPT_STR(l, s, v, d) OPT_STRING(l, s, "STRING", v, d) struct argconfig_commandline_options { const char *option; diff --git a/util/base64.c b/util/base64.c new file mode 100644 index 0000000..e386c11 --- /dev/null +++ b/util/base64.c @@ -0,0 +1,105 @@ +/* + * base64.c - RFC4648-compliant base64 encoding + * + * Copyright (c) 2020 Hannes Reinecke, SUSE + * + * 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 <stdlib.h> +#include <string.h> +#include <errno.h> + +static const char base64_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + * base64_encode() - base64-encode some bytes + * @src: the bytes to encode + * @srclen: number of bytes to encode + * @dst: (output) the base64-encoded string. Not NUL-terminated. + * + * Encodes the input string using characters from the set [A-Za-z0-9+,]. + * The encoded string is roughly 4/3 times the size of the input string. + * + * Return: length of the encoded string + */ +int base64_encode(const unsigned char *src, int srclen, char *dst) +{ + int i, bits = 0; + u_int32_t ac = 0; + char *cp = dst; + + for (i = 0; i < srclen; i++) { + ac = (ac << 8) | src[i]; + bits += 8; + do { + bits -= 6; + *cp++ = base64_table[(ac >> bits) & 0x3f]; + } while (bits >= 6); + } + if (bits) { + *cp++ = base64_table[(ac << (6 - bits)) & 0x3f]; + bits -= 6; + } + while (bits < 0) { + *cp++ = '='; + bits += 2; + } + + return cp - dst; +} + +/** + * base64_decode() - base64-decode some bytes + * @src: the base64-encoded string to decode + * @len: number of bytes to decode + * @dst: (output) the decoded bytes. + * + * Decodes the base64-encoded bytes @src according to RFC 4648. + * + * Return: number of decoded bytes + */ +int base64_decode(const char *src, int srclen, unsigned char *dst) +{ + u_int32_t ac = 0; + int i, bits = 0; + unsigned char *bp = dst; + + for (i = 0; i < srclen; i++) { + const char *p = strchr(base64_table, src[i]); + + if (src[i] == '=') { + ac = (ac << 6); + bits += 6; + if (bits >= 8) + bits -= 8; + continue; + } + if (p == NULL || src[i] == 0) + return -EINVAL; + ac = (ac << 6) | (p - base64_table); + bits += 6; + if (bits >= 8) { + bits -= 8; + *bp++ = (unsigned char)(ac >> bits); + } + } + if (ac && ((1 << bits) - 1)) + return -EAGAIN; + + return bp - dst; +} diff --git a/util/base64.h b/util/base64.h new file mode 100644 index 0000000..609a877 --- /dev/null +++ b/util/base64.h @@ -0,0 +1,7 @@ +#ifndef _BASE64_H +#define _BASE64_H + +int base64_encode(const unsigned char *src, int len, char *dst); +int base64_decode(const char *src, int len, unsigned char *dst); + +#endif /* _BASE64_H */ diff --git a/util/json.h b/util/json.h index 666c78d..2ef8632 100644 --- a/util/json.h +++ b/util/json.h @@ -54,6 +54,7 @@ int json_object_add_value_type(struct json_object *obj, const char *name, int ty json_object_add_value_type((obj), name, JSON_TYPE_INTEGER, (long long) (val)) #define json_object_add_value_uint(obj, name, val) \ json_object_add_value_type((obj), name, JSON_TYPE_UINT, (unsigned long long) (val)) +#define json_object_add_value_uint64 json_object_add_value_uint #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) \ diff --git a/util/log.c b/util/log.c deleted file mode 100644 index 4a22354..0000000 --- a/util/log.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2021 SUSE LLC - * - * 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 basic logging functionality. - */ - -#include <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <stdbool.h> -#include <syslog.h> -#include <unistd.h> -#include <time.h> -#define LOG_FUNCNAME 1 -#include "log.h" -#include "cleanup.h" - -#ifndef LOG_CLOCK -#define LOG_CLOCK CLOCK_MONOTONIC -#endif - -int log_level = DEFAULT_LOGLEVEL; -bool log_timestamp; -bool log_pid; - -void __attribute__((format(printf, 3, 4))) -__msg(int lvl, const char *func, const char *format, ...) -{ - va_list ap; - char pidbuf[16]; - char timebuf[32]; - static const char *const formats[] = { - "%s%s%s", - "%s%s%s: ", - "%s<%s>%s ", - "%s<%s> %s: ", - "[%s] %s%s ", - "[%s]%s %s: ", - "[%s] <%s>%s ", - "[%s] <%s> %s: ", - }; - char *header __cleanup__(cleanup_charp) = NULL; - char *message __cleanup__(cleanup_charp) = NULL; - int idx; - - if (lvl > log_level) - return; - - if (log_timestamp) { - struct timespec now; - - clock_gettime(LOG_CLOCK, &now); - snprintf(timebuf, sizeof(timebuf), "%6ld.%06ld", - (long)now.tv_sec, now.tv_nsec / 1000); - } else - *timebuf = '\0'; - - if (log_pid) - snprintf(pidbuf, sizeof(pidbuf), "%ld", (long)getpid()); - else - *pidbuf = '\0'; - - idx = ((log_timestamp ? 1 : 0) << 2) | - ((log_pid ? 1 : 0) << 1) | (func ? 1 : 0); - - if (asprintf(&header, formats[idx], timebuf, pidbuf, func ? func : "") - == -1) - header = NULL; - - va_start(ap, format); - if (vasprintf(&message, format, ap) == -1) - message = NULL; - va_end(ap); - - fprintf(stderr, "%s%s", header ? header : "<error>", - message ? message : "<error>"); - -} diff --git a/util/log.h b/util/log.h deleted file mode 100644 index 15107a5..0000000 --- a/util/log.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2021 Martin Wilck, SUSE LLC - * SPDX-License-Identifier: LGPL-2.1-or-newer - */ -#ifndef _LOG_H -#define _LOG_H - -#ifndef MAX_LOGLEVEL -# define MAX_LOGLEVEL LOG_DEBUG -#endif -#ifndef DEFAULT_LOGLEVEL -# define DEFAULT_LOGLEVEL LOG_NOTICE -#endif - -#if (LOG_FUNCNAME == 1) -#define _log_func __func__ -#else -#define _log_func NULL -#endif - -extern int log_level; -extern bool log_timestamp; -extern bool log_pid; - -void __attribute__((format(printf, 3, 4))) -__msg(int lvl, const char *func, const char *format, ...); - -#define msg(lvl, format, ...) \ - do { \ - if ((lvl) <= MAX_LOGLEVEL) \ - __msg(lvl, _log_func, format, ##__VA_ARGS__); \ - } while (0) - -#endif /* _LOG_H */ diff --git a/util/meson.build b/util/meson.build new file mode 100644 index 0000000..e525f0e --- /dev/null +++ b/util/meson.build @@ -0,0 +1,8 @@ +sources += [ + 'util/argconfig.c', + 'util/cleanup.c', + 'util/json.c', + 'util/parser.c', + 'util/suffix.c', + 'util/base64.c', +] diff --git a/util/parser.c b/util/parser.c index 2dd0922..bd74822 100644 --- a/util/parser.c +++ b/util/parser.c @@ -16,9 +16,9 @@ /** * 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 + * @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 @@ -94,12 +94,12 @@ static int match_one(char *s, const char *p, substring_t args[]) /** * 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. + * @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 @@ -118,9 +118,9 @@ int match_token(char *s, const match_table_t table, substring_t args[]) /** * 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 + * @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 @@ -154,8 +154,8 @@ static int match_number(substring_t *s, int *result, int base) /** * match_int: - scan a decimal representation of an integer from a substring_t - * @s: substring_t to be scanned - * @result: resulting integer on success + * @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. @@ -168,8 +168,8 @@ int match_int(substring_t *s, int *result) /** * match_octal: - scan an octal representation of an integer from a substring_t - * @s: substring_t to be scanned - * @result: resulting integer on success + * @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 @@ -182,8 +182,8 @@ int match_octal(substring_t *s, int *result) /** * match_hex: - scan a hex representation of an integer from a substring_t - * @s: substring_t to be scanned - * @result: resulting integer on success + * @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 @@ -196,8 +196,8 @@ int match_hex(substring_t *s, int *result) /** * match_wildcard: - parse if a string matches given wildcard pattern - * @pattern: wildcard pattern - * @str: the string to be parsed + * @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: @@ -246,9 +246,9 @@ bool match_wildcard(const char *pattern, const char *str) /** * 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 + * @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 |