nvme-cli is a cross-platform NVMe management utility (Linux/Windows) with an integrated libnvme library (v3.x+). The project uses Meson build system and supports an extensible plugin architecture for vendor-specific commands.
Critical: Starting with nvme-cli 3.x, libnvme is fully integrated into the source tree at libnvme/ - there's no external dependency.
- nvme-cli (
nvme.c,nvme-builtin.h): Main CLI tool with built-in NVMe commands - libnvme (
libnvme/src/nvme/): Cross-platform NVMe library with OS-specific ioctl implementationsioctl.c(Linux),ioctl-windows.c(Windows)
- Plugins (
plugins/*/): Vendor-specific extensions (OCP, WDC, Intel, Solidigm, etc.) - Utilities (
util/): Shared helpers (argument parsing, formatting, cleanup)
Commands use a macro-based registration system via define_cmd.h:
-
Built-in commands (
nvme-builtin.h):COMMAND_LIST( ENTRY("list", "List all NVMe devices", list) ENTRY("id-ctrl", "Send Identify Controller", id_ctrl) )
-
Plugin commands (e.g.,
plugins/ocp/ocp-nvme.h):PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION), COMMAND_LIST( ENTRY("smart-add-log", "Retrieve extended SMART", smart_add_log) ) )
Commands are invoked as: nvme <command> (built-in) or nvme <plugin> <command> (plugin).
- Platform detection: Use Meson's
build_machine.system()checks - OS-specific code: Separate implementations in
libnvme/src/nvme/ioctl-*.c - Windows quirks:
- Network libraries (ws2_32, wsock32, iphlpapi) auto-linked on Windows
- Linux-only features (json-c, liburing, keyutils) auto-disabled on Windows
Linux:
meson setup .build
meson compile -C .build
meson install -C .buildWindows (MSYS2):
meson setup .build
meson compile -C .build
meson install -C .buildWindows (PowerShell):
meson setup .build
meson compile -C .build-Dnvme=enabled|disabled- Build nvme CLI (default: enabled)-Dlibnvme=enabled|disabled- Build libnvme library (default: enabled)-Dtests=true|false- Build tests (default: true)-Ddefault_library=static|shared- Library type-Djson-c=enabled|auto|disabled- JSON support (required for plugins on Linux)
Important: Disabling json-c on Linux disables all plugins.
See scripts/build.sh for CI configurations:
scripts/build.sh- Default buildscripts/build.sh fallback- Download all dependenciesscripts/build.sh static- Static binaryscripts/build.sh libnvme- libnvme only
- Add
ENTRY()tonvme-builtin.h - Implement callback in
nvme.c:static int my_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin)
- Use
argconfigfor option parsing (see existing commands) - Return 0 on success, errno on failure
- Create plugin header in
plugins/<vendor>/<vendor>-nvme.h:#undef CMD_INC_FILE #define CMD_INC_FILE plugins/<vendor>/<vendor>-nvme PLUGIN(NAME("<vendor>", "Description", VERSION), COMMAND_LIST( ENTRY("cmd-name", "Description", callback_fn) ) ) #include "define_cmd.h"
- Implement commands in
plugins/<vendor>/<vendor>-nvme.c - Update
plugins/meson.buildto include new plugin
Python-based tests in tests/:
- Test framework:
nvme_test.py,nvme_test_logger.py - Run with:
meson test -C .buildorpytest tests/ - Tests require real NVMe hardware (controlled by
-Dnvme-tests=true)
You're currently working on Windows implementation (libnvme/src/nvme/ioctl-windows.c). Key points:
- Use Windows API:
DeviceIoControl(),CreateFile(), etc. - Convert Windows errors to errno with helper functions
- Many Linux features unsupported: reset, rescan, io_uring
- Test using MinGW builds
Follow Linux kernel coding style for all code contributions:
- Indentation: Use tabs (not spaces) for indentation, with 8-character tab stops
- Line length: Should not exceed 80 characters with 8-space tabs if possible. This is a soft guideline - readability takes priority, with a hard limit of 100 columns for code.
- Bracing: K&R style - opening brace on same line, closing brace on new line. For conditional statements with single instructions in all branches, do not use braces.
// Multiple statements - use braces if (condition) { do_something(); do_another_thing(); } else { do_something_else(); } // Single statement in all branches - no braces if (condition) do_something(); else do_something_else();
- Naming:
- Functions/variables: lowercase with underscores (
get_smart_log,namespace_id) - Macros/constants: uppercase with underscores (
NVME_LOG_PAGE_SIZE) - Struct members: lowercase with underscores
- Functions/variables: lowercase with underscores (
- Spacing: Space after keywords (
if (,while (), no space for function calls (func() - Pointer declarations: Attach asterisk to type name, not variable name:
type *namenottype* nameint *ptr; // Correct char *str; // Correct void *user_data; // Correct int* ptr; // Wrong
- Comments: Follow these conventions:
- Multi-line block comments: Use Linux kernel style with
/* */wrapper and*prefix:/* * This is a multi-line comment explaining something * with important details across multiple lines. */
- Single-line standalone comments: Use
/* */format:/* Single line comment */ - Inline comments (end-of-line): Use
/* */format:/* Inline comment */ - TODO comments: Use C++ style:
// TODO: description - SPDX license headers: Use C style:
/* SPDX-License-Identifier: ... */
- Multi-line block comments: Use Linux kernel style with
- Type declarations: Prefer kernel types (
__u32,__le16) for hardware structures
See the Linux kernel coding style documentation for complete details.
Follow Linux kernel style:
<area>: <short description>
<detailed description>
Signed-off-by: Name <email>
Examples: nvme: fix buffer overflow, ocp: add latency monitor log
- Return 0 on success, negative errno on failure
- Use
nvme_status_to_errno()for NVMe status codes - Log errors with
nvme_show_error()orperror()
- Use cleanup attributes for auto-cleanup:
_cleanup_(nvme_free_tree),_cleanup_free_ - Defined in
util/cleanup.h - Example:
_cleanup_free_ char *buf = malloc(size);
- nvme-cli: GPL-2.0-or-later (some files GPL-2.0-only)
- libnvme: LGPL-2.1-or-later
- Always include SPDX header:
// SPDX-License-Identifier: GPL-2.0-or-later
nvme.c(11k lines) - Main CLI implementationnvme-builtin.h- Built-in command registrydefine_cmd.h- Command macro magicplugin.c,plugin.h- Plugin infrastructureENVIRONMENT.md- Dependency setup guidemeson.build- Root build configuration
- Plugins disabled: Check if json-c is enabled on Linux builds
- Test failures: Tests require real NVMe hardware and
-Dnvme-tests=true - libnvme not found: In 3.x+, libnvme is integrated - don't install separately
- Wrong command invocation: Plugins use
nvme <plugin> <cmd>, notnvme <cmd>