From 390bd9f2d01e366232384df35ea2c8c7da7d654b Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 2 Jul 2026 11:16:09 +0200 Subject: [PATCH] Make persistent discovery controller configurable for the subsystem Some subsystems / vendors might choose to enable or disable persistent discovery controllers for particular subsystems, independent on the global option to enable PDCs. This patch adds a new subsystem configuration option 'persistent_discovery_controller', which controls whether a PDC should be created for this subsystem. The value defaults to the host PDC setting if not specified in the configuration file. Signed-off-by: Hannes Reinecke --- libnvme/doc/config-schema.json.in | 4 ++++ libnvme/libnvme/accessors.i | 1 + libnvme/src/libnvme.ld | 2 ++ libnvme/src/nvme/accessors.c | 13 +++++++++++++ libnvme/src/nvme/accessors.h | 17 +++++++++++++++++ libnvme/src/nvme/fabrics.c | 3 +-- libnvme/src/nvme/json.c | 15 ++++++++++++++- libnvme/src/nvme/private.h | 1 + libnvme/src/nvme/tree.c | 7 +++++++ 9 files changed, 60 insertions(+), 3 deletions(-) diff --git a/libnvme/doc/config-schema.json.in b/libnvme/doc/config-schema.json.in index 79fac1c6b5..30bc4cda9d 100644 --- a/libnvme/doc/config-schema.json.in +++ b/libnvme/doc/config-schema.json.in @@ -58,6 +58,10 @@ "type": "string", "maxLength": 223 }, + "persistent_discovery_ctrl": { + "description": "Enable/disable Persistent Discovery Controller", + "type": "boolean" + }, "ports": { "description": "Array of NVMe subsystem ports", "type": "array", diff --git a/libnvme/libnvme/accessors.i b/libnvme/libnvme/accessors.i index 0060e8d269..41b193812b 100644 --- a/libnvme/libnvme/accessors.i +++ b/libnvme/libnvme/accessors.i @@ -176,6 +176,7 @@ struct libnvme_subsystem { const char * firmware; %immutable subsystype; const char * subsystype; + bool pdc_enabled; %extend { %immutable iopolicy; const char * iopolicy; diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 9c7a10dd34..8094b49960 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -159,10 +159,12 @@ LIBNVME_3 { libnvme_subsystem_first_ns; libnvme_subsystem_get_host; libnvme_subsystem_get_iopolicy; + libnvme_subsystem_get_pdc_enabled; libnvme_subsystem_lookup_namespace; libnvme_subsystem_next_ctrl; libnvme_subsystem_next_ns; libnvme_subsystem_release_fds; + libnvme_subsystem_set_pdc_enabled; libnvme_transport_handle_get_fd; libnvme_transport_handle_get_mi_ep; libnvme_transport_handle_get_name; diff --git a/libnvme/src/nvme/accessors.c b/libnvme/src/nvme/accessors.c index 14f9be04f3..0a5366c60f 100644 --- a/libnvme/src/nvme/accessors.c +++ b/libnvme/src/nvme/accessors.c @@ -563,6 +563,19 @@ __libnvme_public const char *libnvme_subsystem_get_subsystype( return p->subsystype; } +__libnvme_public void libnvme_subsystem_set_pdc_enabled( + struct libnvme_subsystem *p, + bool pdc_enabled) +{ + p->pdc_enabled = pdc_enabled; +} + +__libnvme_public bool libnvme_subsystem_get_pdc_enabled( + const struct libnvme_subsystem *p) +{ + return p->pdc_enabled; +} + /**************************************************************************** * Accessors for: struct libnvme_host ****************************************************************************/ diff --git a/libnvme/src/nvme/accessors.h b/libnvme/src/nvme/accessors.h index 6c9e910769..002770babc 100644 --- a/libnvme/src/nvme/accessors.h +++ b/libnvme/src/nvme/accessors.h @@ -739,6 +739,23 @@ const char *libnvme_subsystem_get_firmware(const struct libnvme_subsystem *p); */ const char *libnvme_subsystem_get_subsystype(const struct libnvme_subsystem *p); +/** + * libnvme_subsystem_set_pdc_enabled() - Set pdc_enabled. + * @p: The &struct libnvme_subsystem instance to update. + * @pdc_enabled: Value to assign to the pdc_enabled field. + */ +void libnvme_subsystem_set_pdc_enabled( + struct libnvme_subsystem *p, + bool pdc_enabled); + +/** + * libnvme_subsystem_get_pdc_enabled() - Get pdc_enabled. + * @p: The &struct libnvme_subsystem instance to query. + * + * Return: The value of the pdc_enabled field. + */ +bool libnvme_subsystem_get_pdc_enabled(const struct libnvme_subsystem *p); + /**************************************************************************** * Accessors for: struct libnvme_host ****************************************************************************/ diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 01c858943e..242f9a64a9 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -2416,9 +2416,8 @@ static int _nvmf_discovery(struct libnvme_global_ctx *ctx, if (!(eflags & NVMF_DISC_EFLAGS_EPCSD)) disconnect = true; else - disconnect = false; + disconnect = libnvme_subsystem_get_pdc_enabled(s); } - set_discovery_kato(&nfctx); } else { /* NVME_NQN_NVME */ diff --git a/libnvme/src/nvme/json.c b/libnvme/src/nvme/json.c index c3596ad731..4033dbe0c1 100644 --- a/libnvme/src/nvme/json.c +++ b/libnvme/src/nvme/json.c @@ -128,7 +128,7 @@ static void json_parse_port(libnvme_subsystem_t s, struct json_object *port_obj) static void json_parse_subsys(libnvme_host_t h, struct json_object *subsys_obj) { - struct json_object *nqn_obj, *port_array; + struct json_object *nqn_obj, *port_array, *attr_obj; libnvme_subsystem_t s; const char *nqn = ""; int p; @@ -140,6 +140,10 @@ static void json_parse_subsys(libnvme_host_t h, struct json_object *subsys_obj) if (!s) return; + attr_obj = json_object_object_get(subsys_obj, "persistent_discovery_ctrl"); + if (attr_obj) + libnvme_subsystem_set_pdc_enabled(s, json_object_get_boolean(attr_obj)); + port_array = json_object_object_get(subsys_obj, "ports"); if (!port_array) return; @@ -378,6 +382,7 @@ static void json_update_subsys(struct json_object *subsys_array, const char *subsysnqn = libnvme_subsystem_get_subsysnqn(s); struct json_object *subsys_obj = json_object_new_object(); struct json_object *port_array; + bool pdc_enabled = libnvme_subsystem_get_pdc_enabled(s); /* Skip discovery subsystems as the nqn is not unique */ if (!strcmp(subsysnqn, NVME_DISC_SUBSYS_NAME)) { @@ -387,6 +392,10 @@ static void json_update_subsys(struct json_object *subsys_array, json_object_object_add(subsys_obj, "nqn", json_object_new_string(subsysnqn)); + if (pdc_enabled != libnvme_host_is_pdc_enabled(s->h, DEFAULT_PDC_ENABLED)) + json_object_object_add(subsys_obj, "persistent_discovery_ctrl", + json_object_new_boolean(pdc_enabled)); + port_array = json_object_new_array(); libnvme_subsystem_for_each_ctrl(s, c) { json_update_port(port_array, c); @@ -620,11 +629,15 @@ static void json_dump_subsys(struct json_object *subsys_array, { struct json_object *subsys_obj = json_object_new_object(); struct json_object *ns_array; + bool pdc_enabled = libnvme_subsystem_get_pdc_enabled(s); json_object_object_add(subsys_obj, "name", json_object_new_string(libnvme_subsystem_get_name(s))); json_object_object_add(subsys_obj, "nqn", json_object_new_string(libnvme_subsystem_get_subsysnqn(s))); + if (pdc_enabled != libnvme_host_is_pdc_enabled(s->h, DEFAULT_PDC_ENABLED)) + json_object_object_add(subsys_obj, "persistent_discovery_ctrl", + json_object_new_boolean(pdc_enabled)); ns_array = json_object_new_array(); if (!json_dump_subsys_multipath(s, ns_array)) diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index d84ab763ad..9660f1a703 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -377,6 +377,7 @@ struct libnvme_subsystem { // !generate-accessors:read=generated,write=none !ge char *firmware; char *subsystype; char *iopolicy; // !access:read=custom + bool pdc_enabled; // !access:read=generated,write=generated }; struct libnvme_host { // !generate-accessors:read=generated,write=none !generate-python:alias=Host diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index 10bb643919..e3bd8936a3 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -412,6 +412,12 @@ struct libnvme_subsystem *nvme_alloc_subsystem(struct libnvme_host *h, free(s); return NULL; } + /* + * Use the default from the host. + * Any value from the 'subsystem' json configuration + * will override it. + */ + s->pdc_enabled = libnvme_host_is_pdc_enabled(h, DEFAULT_PDC_ENABLED); if (name) libnvme_init_subsystem(s, name); @@ -503,6 +509,7 @@ static int libnvme_create_host(struct libnvme_global_ctx *ctx, list_head_init(&h->subsystems); list_node_init(&h->entry); h->ctx = ctx; + h->pdc_enabled = DEFAULT_PDC_ENABLED; list_add_tail(&ctx->hosts, &h->entry);