nvm_cmd

NVM command (nvm_cmd_*) -- Ver { major(0), minor(1), patch(4) }

Construct and execute NVM commands

Usage:
 nvm_cmd         idfy dev_path [-h] [-v]
 nvm_cmd     rprt_all dev_path [-h] [-v]
 nvm_cmd     rprt_lun dev_path ch lun [-h] [-v]
 nvm_cmd         gbbt dev_path ch lun [-h] [-v]
 nvm_cmd         sbbt dev_path ch lun blk 0xVAL [-h] [-v]
 nvm_cmd        erase dev_path 0xADDR [0xADDR...] [-h] [-v]
 nvm_cmd        write dev_path 0xADDR [0xADDR...] [-h] [-v] [-i FILE]
 nvm_cmd         read dev_path 0xADDR [0xADDR...] [-h] [-v] [-o FILE]
 nvm_cmd         copy dev_path pugrp punit chunk pugrp punit chunk [-h] [-v]

Options:
 -h       Print usage
 -v       Dump CLI state to stdout
 -i  FILE Path to input file
 -o  FILE Path to output file

See: http://lightnvm.io/liblightnvm/cli/ for usage examples

Tip

See section Environment Variables for a full list of environment variables modifying command behavior

Device Identification / Geometry

For Open-Channel drives, both 1.2 and 2.0, then device identification and geometry information can be quiried like so:

nvm_cmd idfy /dev/nvme0n1
# nvm_cmd_idfy
idfy:
  verid: 00000010
  verid_minor: 00000000
  mccap: 00000000000000000000000000000001
lbaf:
  pugrp: 3
  punit: 2
  chunk: 11
  sectr: 13
lgeo:
  npugrp: 8
  npunit: 4
  nchunk: 1474
  nsectr: 6144
wrt:
  ws_min: 24
  ws_opt: 24
  mw_cunits: 192
perf:
  trdt: 40000
  trdm: 80000
  twrt: 1900000
  twrm: 3700000
  tcet: 7000000
  tcem: 20000000

Tip

See section nvm_dev for additional device information.

Media State

For Open-Channel 1.2 drives then media state can be read and written via the bad-block-table interface. See section nvm_bbt for an elaborate description.

For Open-Channel 2.0 drives, the media state can only read, not written. This is facilitated by the NVMe get-log-page, and in liblightnvm provided via the following nvm_cmd_rprt.

To retrieve the entire state:

nvm_cmd rprt_all /dev/nvme0n1 | head -n 20
# nvm_cmd_rprt: (nil)
rprt:
  ndescr: 47168
rprt_descr:
  - { slba: 0x0000000000000000, cnlb: 0x1800, wp: 0x000000000000ffff, cs: 0x08, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000002000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000004000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000006000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000008000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000000000A000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000000000C000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000000000E000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000010000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000012000, cnlb: 0x1800, wp: 0x0000000000001800, cs: 0x02, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000014000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000016000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000000018000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000000001A000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000000001C000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000000001E000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }

To retrieve the state for a single LUN / parallel unit:

nvm_cmd rprt_lun /dev/nvme0n1 4 2 | head -n 20
# nvm_cmd_rprt: 0x5577a06a44d0
naddrs: 1
addrs:
  - {val: 0x0402000000000000, pugrp: 04, punit: 02, chunk: 0000, sectr: 0000}
rprt:
  ndescr: 1474
rprt_descr:
  - { slba: 0x0000000012000000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012002000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012004000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012006000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012008000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000001200A000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000001200C000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x000000001200E000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012010000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012012000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012014000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012016000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }
  - { slba: 0x0000000012018000, cnlb: 0x1800, wp: 0x0000000000000000, cs: 0x01, ct: 0x01, wli: 0x00 }

Submitting IO

The nvm_cmd provides three IO sub-commands which constructs, submits and waits for completion of a single NVMe command using the OCSSD erase(reset), write(vector-write), and read(vector-read) command opcodes.

Perform a read command:

nvm_cmd read /dev/nvme0n1 \
0x0402008e00000000 0x0402008e00000001 0x0402008e00000002 0x0402008e00000003
# nvm_cmd_read: {pmode: SNGL}
naddrs: 4
addrs:
  - {val: 0x0402008e00000000, pugrp: 04, punit: 02, chunk: 0142, sectr: 0000}
  - {val: 0x0402008e00000001, pugrp: 04, punit: 02, chunk: 0142, sectr: 0001}
  - {val: 0x0402008e00000002, pugrp: 04, punit: 02, chunk: 0142, sectr: 0002}
  - {val: 0x0402008e00000003, pugrp: 04, punit: 02, chunk: 0142, sectr: 0003}

Use the -o FILE option, to dump the data read from device to file:

nvm_cmd read /dev/nvme0n1 \
0x0402008e00000000 0x0402008e00000001 0x0402008e00000002 0x0402008e00000003 \
0x0402008e00000004 0x0402008e00000005 0x0402008e00000006 0x0402008e00000007 \
-o /tmp/nvm_dump.bin
# nvm_cmd_read: {pmode: SNGL}
naddrs: 8
addrs:
  - {val: 0x0402008e00000000, pugrp: 04, punit: 02, chunk: 0142, sectr: 0000}
  - {val: 0x0402008e00000001, pugrp: 04, punit: 02, chunk: 0142, sectr: 0001}
  - {val: 0x0402008e00000002, pugrp: 04, punit: 02, chunk: 0142, sectr: 0002}
  - {val: 0x0402008e00000003, pugrp: 04, punit: 02, chunk: 0142, sectr: 0003}
  - {val: 0x0402008e00000004, pugrp: 04, punit: 02, chunk: 0142, sectr: 0004}
  - {val: 0x0402008e00000005, pugrp: 04, punit: 02, chunk: 0142, sectr: 0005}
  - {val: 0x0402008e00000006, pugrp: 04, punit: 02, chunk: 0142, sectr: 0006}
  - {val: 0x0402008e00000007, pugrp: 04, punit: 02, chunk: 0142, sectr: 0007}

Which can then be inspected with for example hexdump:

hexdump /tmp/nvm_dump.bin -C -n 128
00000000  4d 4e 4f 50 51 52 53 54  55 56 57 58 59 5a 41 42  |MNOPQRSTUVWXYZAB|
00000010  43 44 45 46 47 48 49 4a  4b 4c 4d 4e 4f 50 51 52  |CDEFGHIJKLMNOPQR|
00000020  53 54 55 56 57 58 59 5a  41 42 43 44 45 46 47 48  |STUVWXYZABCDEFGH|
00000030  49 4a 4b 4c 4d 4e 4f 50  51 52 53 54 55 56 57 58  |IJKLMNOPQRSTUVWX|
00000040  59 5a 41 42 43 44 45 46  47 48 49 4a 4b 4c 4d 4e  |YZABCDEFGHIJKLMN|
00000050  4f 50 51 52 53 54 55 56  57 58 59 5a 41 42 43 44  |OPQRSTUVWXYZABCD|
00000060  45 46 47 48 49 4a 4b 4c  4d 4e 4f 50 51 52 53 54  |EFGHIJKLMNOPQRST|
00000070  55 56 57 58 59 5a 41 42  43 44 45 46 47 48 49 4a  |UVWXYZABCDEFGHIJ|
00000080