libnvmf: NVMe Controller Ownership Registry (V2)#3425
Open
martin-belanger wants to merge 4 commits into
Open
Conversation
added 4 commits
June 3, 2026 19:35
Multiple orchestrators (nvme-stas, nvme-discoverd, NBFT) can connect NVMe-oF controllers on the same host simultaneously, with no way to tell which tool manages which controller. Commands like disconnect-all are therefore indiscriminate and can disrupt running daemons. Add a registry under /run/nvme/registry/ so orchestrators can declare and respect ownership of connected controllers. One directory per controller, one plain-text file per attribute — no json-c dependency, trivially inspectable with cat(1), naturally extensible. Signed-off-by: Martin Belanger <martin.belanger@dell.com> Assisted-by: Claude:claude-sonnet-4-6 [Claude Code]
The registry commands belong in a plugin rather than as top-level built-ins to keep the core nvme binary lean and to make it clear these are orchestration tools, not general NVMe commands. 'nvme list -v' gains an Orchestrator column so operators can see at a glance which tool manages each connected controller. Signed-off-by: Martin Belanger <martin.belanger@dell.com> Assisted-by: Claude:claude-sonnet-4-6 [Claude Code]
When an owner name is set in the global context, a registry entry is automatically written after every successful fabrics connect. This lets orchestrators declare ownership without any explicit registration call. libnvme_create_global_ctx() gains an owner parameter so the identity is set at construction time and cannot change during the context lifetime. All callers that do not participate in the registry pass NULL. connect-all --nbft passes "nbft", registering boot-volume controllers so they are protected from accidental disconnection. disconnect-all is now ownership-aware by default: only unowned controllers are disconnected. --owner NAME targets a specific orchestrator; --force restores the original unconditional behaviour and requires confirmation on a terminal. The application field and its filtering mechanism are removed from libnvme_global_ctx and libnvme_subsystem. The application mechanism assumed all orchestrators share a JSON config file, which does not hold for NBFT, nvme-stas, or nvme-discoverd. The registry solves the same coordination problem without that assumption. Signed-off-by: Martin Belanger <martin.belanger@dell.com> Assisted-by: Claude:claude-sonnet-4-6 [Claude Code]
Add man pages for the four registry plugin subcommands: nvme-registry-list(1) nvme-registry-retrieve(1) nvme-registry-update(1) nvme-registry-delete(1) Update nvme-disconnect-all(1) to document the new ownership-aware default behavior and the --owner, --force, and --transport options. Signed-off-by: Martin Belanger <martin.belanger@dell.com> Assisted-by: Claude:claude-sonnet-4-6 [Claude Code]
d9d61fa to
2093849
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This addresses issue #2913. It is a clean replacement for PR #3400, which was closed in favor of this redesigned version.
Problem
Multiple independent orchestrators can establish NVMe-oF controller connections on the same Linux host simultaneously:
nvme connect/nvme connect-all(stateless, one-shot)nvme-stas(stafd/stacd) — production-grade daemon with CDC/fabric-zoning supportnvme-discoverd— ships with nvme-cli, runs by default (future project)All connected controllers appear in a single flat namespace (
/dev/nvmeX) with no indication of which orchestrator created or manages each one. Commands likenvme disconnect-allare therefore indiscriminate and dangerous.The registry gives well-behaved orchestrators the information they need to avoid accidentally disconnecting controllers managed by another tool. It is a cooperative coordination mechanism, not an enforcement boundary — all participants are assumed to cooperate.
What changed from PR #3400
nvme3.json)nvme3/owner)nvme registry-list)nvme registry list)keyattrfor_each(device, owner, user_data)device_for_each(device, user_data)+attr_for_each(attr, value, user_data)libnvmf_context_set_owner()setterlibnvme_create_global_ctx(fp, level, owner)applicationfieldlibnvme_global_ctxandlibnvme_subsystemDesign highlights
Directory-based storage
Mirrors the kernel's sysfs convention. Trivially inspectable with
cat. Extensible — new attributes are new files, no schema change needed. No json-c dependency in the registry path.Atomic write protocol prevents corruption under concurrent access from multiple processes:
Owner is immutable
The owner name is passed at context creation time and fixed for the lifetime of the context:
This expresses the intent clearly — the owner is the identity of the process, not a per-connect property — and makes it impossible to change accidentally at runtime. Pass
NULLto opt out of registry participation entirely.Removal of
applicationThe
applicationfield was a previous attempt to solve the same multi-orchestrator coordination problem. It assumed all orchestrators share a hand-written JSON config file, which is false for every real orchestrator in the ecosystem (NBFT reads firmware tables; nvme-stas uses DNS-SD; nvme-discoverd reacts to udev events).ownersolves the same problem through a shared runtime path (/run/nvme/registry/) without any shared config file assumption.Both
libnvme_global_ctx.applicationandlibnvme_subsystem.applicationare removed, along withlibnvme_get/set_application()and the connect-time filtering logic that compared them. This is an intentional v3.0 API break.Plugin placement
Registry commands live in
plugins/registry/(nvme registry list,nvme registry retrieve, etc.) rather than as top-level built-ins, keeping the core binary lean and signalling that these are orchestration tools rather than general NVMe commands.Commit series
libnvme: add NVMe controller ownership registry—registry.c,registry.h, Python bindings (registry_retrieve,registry_entries,registry_update,registry_delete), C unit tests with 10-process parallel write test, Python unit tests, udev cleanup rule.nvme: add registry plugin and orchestrator column—plugins/registry/plugin with four subcommands,nvme list -vOrchestrator column, CLI integration tests (tests/nvme_registry_test.py).libnvmf: wire registry into connect and disconnect paths— Connect hook in__nvmf_add_ctrl(),libnvme_create_global_ctx()signature change,connect-all --nbftregisters boot controllers asowner=nbft, ownership-awaredisconnect-allwith--owner/--force, removal ofapplicationfrom both structs and all associated code.nvme: add man pages for registry commands and update disconnect-all— Man pages for all four registry subcommands, updatednvme-disconnect-all(1).API changes
Changed
All existing callers pass
NULL(no registry participation).Removed
libnvme_get_application()/libnvme_set_application()libnvme_subsystem_get_application()/libnvme_subsystem_set_application()libnvme_global_ctx.applicationfieldlibnvme_subsystem.applicationfieldAdded
Testing
libnvme/test/registry.c)libnvme/libnvme/tests/test-registry.py)tests/nvme_registry_test.py)-Ujson-c, static): clean build and tests pass