Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libnvme/design/EXCLUSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ if (libnvmf_exclusion_match(ctx, tid))

`libnvmf_exclusion_match()` re-reads the files on every call (no caching), so an edit takes effect on the next connection attempt without restarting anything. This is the only API an orchestrator needs; the create/add/remove calls are for the management tooling.

`nvme connect-all` is itself such an orchestrating path, and libnvme's discovery-connect code consults the list on its behalf: before connecting anything it *enumerated* — a Discovery Log Page entry (including referral DCs), an NBFT record, or a controller listed in `discovery.conf` / `config.json` — it checks for a match and skips with an INFO-level "skipping excluded controller" note. A Discovery Controller named explicitly on the command line (`nvme discover` / `connect-all` with an address) is a targeted human action and is not checked — though the entries *it* enumerates still are.

The match is by design *not* allowed to **block** `nvme connect <args>` or `nvme disconnect <device>`: those are single, targeted human actions where the operator's intent is explicit. The list governs the *orchestrating* paths that decide on their own. As a courtesy, `nvme connect --verbose` does *consult* the list and prints a note when the target matches — a heads-up that you are overriding your own opt-out — but it still connects.

## Managing the list
Expand Down
82 changes: 82 additions & 0 deletions libnvme/src/nvme/fabrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,50 @@ static void nvmf_update_tls_concat(struct nvmf_disc_log_entry *e,
}
}

/*
* Enumerated-connect gate: consult the exclusion list before connecting a
* controller that was enumerated from a Discovery Log Page, the NBFT table,
* or a configuration file. Controllers named explicitly by the user
* ("nvme connect", "nvme discover" with an address) are deliberately not
* checked -- a targeted human action overrides the list.
*/
static bool nvmf_excluded(struct libnvme_global_ctx *ctx,
const char *transport, const char *traddr,
const char *trsvcid, const char *subsysnqn,
const char *host_traddr, const char *host_iface,
const char *hostnqn, const char *hostid)
{
struct libnvmf_tid *tid;
const char *canonical;
bool excluded;

tid = libnvmf_tid_from_fields(transport, traddr, trsvcid, subsysnqn,
host_traddr, host_iface, hostnqn,
hostid);
if (!tid)
return false; /* fail-safe: never block on allocation failure */

excluded = libnvmf_exclusion_match(ctx, tid);
if (excluded) {
canonical = libnvmf_tid_get_canonical(tid);
libnvme_msg(ctx, LIBNVME_LOG_INFO,
"skipping excluded controller %s\n",
canonical ? canonical : subsysnqn);
}
libnvmf_tid_free(tid);

return excluded;
}

static bool nvmf_ctrl_excluded(struct libnvme_global_ctx *ctx,
struct libnvme_host *h, struct libnvme_ctrl *c)
{
return nvmf_excluded(ctx, c->transport, c->traddr, c->trsvcid,
c->subsysnqn, c->host_traddr, c->host_iface,
libnvme_host_get_hostnqn(h),
libnvme_host_get_hostid(h));
}

static int nvmf_connect_disc_entry(libnvme_host_t h,
struct nvmf_disc_log_entry *e,
struct libnvmf_context *fctx,
Expand Down Expand Up @@ -1591,6 +1635,15 @@ static int nvmf_connect_disc_entry(libnvme_host_t h,
fctx->ctrl_params.transport, fctx->ctrl_params.traddr,
fctx->ctrl_params.trsvcid);

if (nvmf_excluded(h->ctx, fctx->ctrl_params.transport,
fctx->ctrl_params.traddr, fctx->ctrl_params.trsvcid,
fctx->ctrl_params.subsysnqn,
fctx->ctrl_params.host_traddr,
fctx->ctrl_params.host_iface,
libnvme_host_get_hostnqn(h),
libnvme_host_get_hostid(h)))
return -EPERM;

ret = libnvme_create_ctrl(h->ctx, &fctx->ctrl_params, &c);
if (ret) {
libnvme_msg(h->ctx, LIBNVME_LOG_DEBUG, "skipping discovery entry, "
Expand Down Expand Up @@ -2642,6 +2695,15 @@ int _discovery_config_json(struct libnvme_global_ctx *ctx,
if (libnvme_ctrl_get_persistent(c))
nfctx.persistent = true;

if (nvmf_excluded(ctx, nfctx.ctrl_params.transport,
nfctx.ctrl_params.traddr, nfctx.ctrl_params.trsvcid,
nfctx.ctrl_params.subsysnqn,
nfctx.ctrl_params.host_traddr,
nfctx.ctrl_params.host_iface,
libnvme_host_get_hostnqn(h),
libnvme_host_get_hostid(h)))
return 0;

if (!force) {
cn = lookup_ctrl(h, &nfctx);
if (cn) {
Expand Down Expand Up @@ -2750,6 +2812,9 @@ __libnvme_public int libnvmf_connect_config_json(struct libnvme_global_ctx *ctx,
strcmp(transport, "fc"))
continue;

if (nvmf_ctrl_excluded(ctx, h, c))
continue;

err = libnvmf_connect_ctrl(c);
if (err) {
if (err == -ENVME_CONNECT_ALREADY)
Expand Down Expand Up @@ -2786,6 +2851,14 @@ __libnvme_public int libnvmf_discovery_config_file(
err = fctx->hooks.parser_next_line(&nfctx, fctx->hooks.user_data);
if (err)
break;
if (nvmf_excluded(ctx, nfctx.ctrl_params.transport,
nfctx.ctrl_params.traddr,
nfctx.ctrl_params.trsvcid,
nfctx.ctrl_params.subsysnqn,
nfctx.ctrl_params.host_traddr,
nfctx.ctrl_params.host_iface,
nfctx.hostnqn, nfctx.hostid))
continue;
libnvmf_discovery(ctx, &nfctx, connect, force);
} while (!err);

Expand Down Expand Up @@ -2951,6 +3024,15 @@ static int nbft_connect(struct libnvme_global_ctx *ctx,
if (c && libnvme_ctrl_get_name(c))
return 0;

if (nvmf_excluded(ctx, fctx->ctrl_params.transport,
fctx->ctrl_params.traddr, fctx->ctrl_params.trsvcid,
fctx->ctrl_params.subsysnqn,
fctx->ctrl_params.host_traddr,
fctx->ctrl_params.host_iface,
libnvme_host_get_hostnqn(h),
libnvme_host_get_hostid(h)))
return 0;

ret = libnvme_create_ctrl(ctx, &fctx->ctrl_params, &c);
if (ret)
return ret;
Expand Down
Loading