nvme‐discoverd - linux-nvme/nvme-cli GitHub Wiki

nvme-discoverd

nvme-discoverd is a systemd daemon. It is built from the nvme-cli source tree. It keeps a host's NVMe-oF fabric connections up. It connects the Discovery Controllers it is told about. Those come from static configuration, NBFT, Fibre Channel discovery, or (since 3.2, opt-in) mDNS. Once a Discovery Controller is connected, discoverd reads its Discovery Log Page (DLP). It then discovers and connects the I/O Controllers and any referred Discovery Controllers that DLP lists. It retries automatically when a connection fails or drops. It has no role on a host with only local (PCIe) NVMe. It is needed only for NVMe over Fabrics. It is currently a technology preview. It requires the fabrics build option and libsystemd 253 or later.

Since nvme-cli 3.2 (unreleased), nvme-discoverd is built by default when libsystemd 253 or later is available. In 3.0 and 3.1, it is disabled by default. Build with -Dnvme-discoverd=enabled to try it there. The daemon only runs when you enable it:

systemctl enable --now nvme-discoverd.service

Why does it exist?

nvme-cli already autoconnects NVMe-oF targets. It uses a collection of udev rules and one-shot systemd services (see How to set up NVMe-oF autoconnect). That mechanism accreted over several years, one rule at a time. It has two structural gaps. A persistent daemon can close both. A set of udev rules cannot.

  • No retry. Each rule fires once per event. Events are a Discovery Log Page Change AEN, a rediscover, or an FC discovery uevent. Each one starts nvme connect-all for that one target. If the target is momentarily unreachable, that attempt fails. Nothing tries again until the next unrelated event happens to fire. That may be never.
  • The late-NBFT path only works under NetworkManager. A host may boot from a network-attached namespace. One of its interfaces may come up after the initramfs stage. The retry for that case depends on a NetworkManager dispatcher script. systemd-networkd has no equivalent hook. It is common on servers and minimal images. On those hosts the late connection silently never happens.

nvme-discoverd is a long-lived process instead of a chain of one-shot rules. So it can just keep trying. It owns a "desired set" of connections. The set comes from static config, the NBFT table, and Discovery Log Pages already read. It retries anything in that set that isn't currently connected. It does this on its own schedule. It does not wait for any particular event to fire. That retry loop is manager-agnostic by construction. It doesn't care whether NetworkManager, systemd-networkd, or nothing at all is running. So it also fixes the late-NBFT gap above as a side effect. No interface-name matching is involved.

How is it different from nvme-stas?

nvme-discoverd is connect-only. Once it connects something, it never disconnects it in response to DLP changes. There is no logic that decides a subsystem dropped out of the Discovery Log Page and should be torn down. The only disconnects it causes are a systemctl stop and cleanup of a controller the kernel already removed. systemctl stop covers shutdown and a manual stop. This is a deliberate simplification. It avoids the whole class of connect/disconnect ordering bugs. The cost is that it does not implement TP8010 Fabric Zoning. That is where a Centralized Discovery Controller tells the host a subsystem should be disconnected.

nvme-stas is a separate project. It does implement that stateful reconciliation. It also implements TP8009 zeroconf (mDNS) discovery. It does this through its own daemons, stafd and stacd. nvme-discoverd and nvme-stas can both run on the same host. They coordinate through the NVMe-oF ownership registry and the system-wide exclusion list. Neither one touches a connection the other one owns.

mDNS discovery (TP8009)

Since nvme-cli 3.2 (unreleased), nvme-discoverd can find Discovery Controllers through mDNS. This is opt-in. It needs:

  • nvme-discoverd built with the mdns meson option. This option needs libsystemd 258 or later. It is built by default when this version is available.
  • systemd-resolved 258 or later at runtime, with mDNS enabled (MulticastDNS=yes).
  • zeroconf = true in nvme-discoverd.conf:
[Discovery]
zeroconf = true

nvme-discoverd re-reads this setting on SIGHUP.

Working with the legacy autoconnect

Since nvme-cli 3.2, the legacy udev/systemd autoconnect is built only when nvme-discoverd is not built. -Dnvmf-autoconnect=enabled installs both.

If both are installed, the legacy udev rules are active at once. nvme-discoverd runs only when you enable nvme-discoverd.service. While nvme-discoverd is active, nvmf-autoconnect.service and the FC kickstart skip their connect step. So the two do not race.

nvme-discoverd and the autoconnect units start after tlshd.service. Without tlshd, a TLS connection fails at once. This ordering does not start tlshd. You must enable tlshd yourself if you use TLS.

Current limits

  • No TP8010 Fabric Zoning. nvme-discoverd never disconnects a controller because of a discovery change. See How is it different from nvme-stas?
  • In nvme-cli 3.0 and 3.1, nvme-discoverd is not built by default, and the legacy autoconnect does not skip its connect step while nvme-discoverd runs. Both react to the same events. Do not rely on both at once.

The legacy udev/systemd autoconnect mechanism will eventually be deprecated and removed. Then nvme-discoverd (or a successor covering the same job) becomes the only way to autoconnect NVMe-oF targets on Linux. No date is set for that.

See also