Skip to content
Open
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
41 changes: 41 additions & 0 deletions fabrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@

#define NVMF_DEF_DISC_TMO 30

#if DEFAULT_EPCSD_ENABLED
#define EPCSD_DISABLED_DEFAULT_STR
#define EPCSD_ENABLED_DEFAULT_STR " (default)"
#else
#define EPCSD_ENABLED_DEFAULT_STR
#define EPCSD_DISABLED_DEFAULT_STR " (default)"
#endif

/* Name of file to output log pages in their raw format */
static char *raw;
static bool persistent;
Expand Down Expand Up @@ -197,6 +205,7 @@ static int setup_common_context(struct libnvmf_context *fctx,

struct hook_fabrics_data {
struct nvmf_args *fa;
struct libnvme_global_ctx *ctx;
nvme_print_flags_t flags;
bool quiet;
char *raw;
Expand Down Expand Up @@ -322,13 +331,17 @@ static int set_fabrics_options(struct libnvmf_context *fctx,
static int hook_parser_next_line(struct libnvmf_context *fctx, void *user_data)
{
struct hook_fabrics_data *hfd = user_data;
bool epcsd_enabled = false, epcsd_disabled = false;
struct libnvme_host *h = NULL;
struct nvmf_args fa;
char *ptr, *p;
static char line[4096];
int argc, ret = 0;
bool force = false;

NVMF_ARGS(opts, fa,
OPT_FLAG("epcsd", 0, &epcsd_enabled, "Enable persistent discovery for controllers that support it"),
OPT_FLAG("no-epcsd", 0, &epcsd_disabled, "Disable persistent discovery for controllers that support it"),
Comment thread
igaw marked this conversation as resolved.
OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"),
OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"));

Expand All @@ -349,6 +362,11 @@ static int hook_parser_next_line(struct libnvmf_context *fctx, void *user_data)
fa.subsysnqn = NVME_DISC_SUBSYS_NAME;
if (argconfig_parse(argc, hfd->argv, "config", opts))
continue;

if (epcsd_enabled && epcsd_disabled) {
fprintf(stderr, "--epcsd and --no-epcsd are mutually exclusive\n");
continue;
}
} while (!fa.transport && !fa.traddr);

if (!fa.trsvcid)
Expand All @@ -361,6 +379,13 @@ static int hook_parser_next_line(struct libnvmf_context *fctx, void *user_data)
libnvmf_context_set_discovery_hooks(fctx, hook_discovery_log,
hook_parser_init, hook_parser_cleanup, hook_parser_next_line);

libnvme_get_host(hfd->ctx, fa.hostnqn, fa.hostid, &h);
if (epcsd_enabled)
libnvme_host_set_epcsd_enabled(h, true);

if (epcsd_disabled)
libnvme_host_set_epcsd_enabled(h, false);

@igaw igaw Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tempted to argue for

if (epcsd_enabled || epcsd_disabled)
	libnvme_host_set_epcsd_enabled(h, epcsd_enabled);

but this might be a bit too obfuscated...


return 0;
}

Expand Down Expand Up @@ -557,13 +582,17 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect)
char *device = NULL;
bool force = false;
bool json_config = false;
bool epcsd_enabled = false, epcsd_disabled = false;
bool nbft = false, nonbft = false;
char *nbft_path = NBFT_SYSFS_PATH;
char *owner = NULL;
struct libnvme_host *h = NULL;

NVMF_ARGS(opts, fa,
OPT_STRING("device", 'd', "DEV", &device, "use existing discovery controller device"),
OPT_FILE("raw", 'r', &raw, "save raw output to file"),
OPT_FLAG("epcsd", 0, &epcsd_enabled, "Enable persistent discovery for controllers that support it." EPCSD_ENABLED_DEFAULT_STR),
OPT_FLAG("no-epcsd", 0, &epcsd_disabled, "Disable persistent discovery for controllers that support it." EPCSD_DISABLED_DEFAULT_STR),
OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"),
OPT_FLAG("quiet", 0, &quiet, "suppress already connected errors"),
OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file),
Expand All @@ -588,6 +617,11 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect)
return ret;
}

if (epcsd_enabled && epcsd_disabled) {
fprintf(stderr, "--epcsd and --no-epcsd options are mutually exclusive\n");
return -EINVAL;
}

if (!strcmp(config_file, "none"))
config_file = NULL;

Expand Down Expand Up @@ -637,6 +671,7 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect)

struct hook_fabrics_data dld = {
.fa = &fa,
.ctx = ctx,
.flags = flags,
.raw = raw,
};
Expand All @@ -662,6 +697,12 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect)
goto out_free;
}

libnvme_get_host(ctx, fa.hostnqn, fa.hostid, &h);
if (epcsd_enabled)
libnvme_host_set_epcsd_enabled(h, true);

if (epcsd_disabled)
libnvme_host_set_epcsd_enabled(h, false);
ret = libnvmf_discovery(ctx, fctx, connect, force);

out_free:
Expand Down
4 changes: 4 additions & 0 deletions libnvme/doc/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"description": "Enable/disable Persistent Discovery Controller",
"type": "boolean"
},
"supported_persistent_discovery_ctrl": {
"description": "Enable/disable persistent discovery for controllers that support it.",
"type": "boolean"
},
"subsystems": {
"description": "Array of NVMe subsystem properties",
"type": "array",
Expand Down
4 changes: 4 additions & 0 deletions libnvme/doc/config-schema.json.in
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"description": "Enable/disable Persistent Discovery Controller",
"type": "boolean"
},
"supported_persistent_discovery_ctrl": {
"description": "Enable/disable persistent discovery for controllers that support it.",
"type": "boolean"
},
"subsystems": {
"description": "Array of NVMe subsystem properties",
"type": "array",
Expand Down
2 changes: 2 additions & 0 deletions libnvme/libnvme/accessors.i
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,10 @@ Subsystem.__setattr__ = _nvme_guarded_setattr
/* struct libnvme_host */
%rename(Host) libnvme_host;
%rename(libnvme_host_pdc_enabled_set) libnvme_host_set_pdc_enabled;
%rename(libnvme_host_epcsd_enabled_set) libnvme_host_set_epcsd_enabled;
%{
#define libnvme_host_pdc_enabled_set libnvme_host_set_pdc_enabled
#define libnvme_host_epcsd_enabled_set libnvme_host_set_epcsd_enabled
%}
struct libnvme_host {
%immutable hostnqn;
Expand Down
2 changes: 2 additions & 0 deletions libnvme/src/libnvme.ld
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ LIBNVME_3 {
libnvme_get_uuid_list;
libnvme_get_version;
libnvme_host_get_global_ctx;
libnvme_host_is_epcsd_enabled;
libnvme_host_is_pdc_enabled;
libnvme_host_release_fds;
libnvme_host_set_epcsd_enabled;
libnvme_host_set_pdc_enabled;
libnvme_init_ctrl;
libnvme_namespace_first_path;
Expand Down
14 changes: 14 additions & 0 deletions libnvme/src/nvme/fabrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -2351,6 +2351,20 @@ static int _nvmf_discovery(struct libnvme_global_ctx *ctx,
}

numrec = le64_to_cpu(log->numrec);

for (int i = 0; i < numrec; i++) {
struct nvmf_disc_log_entry *e = &log->entries[i];
uint16_t eflags = le16_to_cpu(e->eflags);

if ((e->subtype == NVME_NQN_DISC ||
e->subtype == NVME_NQN_CURR) &&
(eflags & NVMF_DISC_EFLAGS_EPCSD) &&
libnvme_host_is_epcsd_enabled(h, DEFAULT_EPCSD_ENABLED)) {
libnvmf_context_set_persistent(fctx, true);
break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you move this part into the existing loop where we already have the NVMF_DISC_EFLAGS_EPCSD check?

}
}

if (fctx->hooks.discovery_log)
fctx->hooks.discovery_log(fctx, connect, log, numrec,
fctx->hooks.user_data);
Expand Down
9 changes: 9 additions & 0 deletions libnvme/src/nvme/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ static void json_parse_host(struct libnvme_global_ctx *ctx, struct json_object *
attr_obj = json_object_object_get(host_obj, "persistent_discovery_ctrl");
if (attr_obj)
libnvme_host_set_pdc_enabled(h, json_object_get_boolean(attr_obj));
attr_obj = json_object_object_get(host_obj, "supported_persistent_discovery_ctrl");
if (attr_obj)
libnvme_host_set_epcsd_enabled(h, json_object_get_boolean(attr_obj));
subsys_array = json_object_object_get(host_obj, "subsystems");
if (!subsys_array)
return;
Expand Down Expand Up @@ -437,6 +440,9 @@ int json_update_config(struct libnvme_global_ctx *ctx, int fd)
if (h->pdc_enabled_valid)
json_object_object_add(host_obj, "persistent_discovery_ctrl",
json_object_new_boolean(h->pdc_enabled));
if (h->epcsd_enabled_valid)
json_object_object_add(host_obj, "supported_persistent_discovery_ctrl",
json_object_new_boolean(h->epcsd_enabled));
subsys_array = json_object_new_array();
libnvme_for_each_subsystem(h, s) {
json_update_subsys(subsys_array, s);
Expand Down Expand Up @@ -664,6 +670,9 @@ int json_dump_tree(struct libnvme_global_ctx *ctx)
if (h->pdc_enabled_valid)
json_object_object_add(host_obj, "persistent_discovery_ctrl",
json_object_new_boolean(h->pdc_enabled));
if (h->epcsd_enabled_valid)
json_object_object_add(host_obj, "supported_persistent_discovery_ctrl",
json_object_new_boolean(h->epcsd_enabled));
subsys_array = json_object_new_array();
libnvme_for_each_subsystem(h, s) {
json_dump_subsys(subsys_array, s);
Expand Down
7 changes: 7 additions & 0 deletions libnvme/src/nvme/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,13 @@ struct libnvme_host { // !generate-accessors:read=generated,write=none !generat
*/
bool pdc_enabled; // !access:read=none,write=custom
bool pdc_enabled_valid; // !access:read=none

/* epcsd_enabled and epcsd_enabled_valid work together. epcsd_enabled_valid,
* when true, indicates that epcsd_enabled has been explicitly defined.
* epcsd_enabled_valid is internal meta-data for epcsd_enabled.
*/
bool epcsd_enabled; // !access:read=none,write=custom
bool epcsd_enabled_valid; // !access:read=none
};

struct libnvme_fabric_options { // !generate-accessors
Expand Down
15 changes: 15 additions & 0 deletions libnvme/src/nvme/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,21 @@ __libnvme_public struct libnvme_global_ctx *libnvme_host_get_global_ctx(
return h->ctx;
}

__libnvme_public void libnvme_host_set_epcsd_enabled(
libnvme_host_t h, bool enabled)
{
h->epcsd_enabled_valid = true;
h->epcsd_enabled = enabled;
}

__libnvme_public bool libnvme_host_is_epcsd_enabled(
libnvme_host_t h, bool fallback)
{
if (h->epcsd_enabled_valid)
return h->epcsd_enabled;
return fallback;
}

__libnvme_public void libnvme_host_set_pdc_enabled(
libnvme_host_t h, bool enabled)
{
Expand Down
22 changes: 22 additions & 0 deletions libnvme/src/nvme/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@ libnvme_host_t libnvme_next_host(struct libnvme_global_ctx *ctx,
*/
struct libnvme_global_ctx *libnvme_host_get_global_ctx(libnvme_host_t h);

/**
* libnvme_host_set_epcsd_enabled() - Set Explicit Persistent Discovery Controller flag
* @h: Host for which the falg should be set
* @enabled: The bool to set the enabled flag
*
* When libnvme_host_set_epcsd_enabled() is not used to set the PDC flag,
* libnvme_host_is_epcsd_enabled() will return the default value which was
* passed into the function and not the undefined flag value.
*/
void libnvme_host_set_epcsd_enabled(libnvme_host_t h, bool enabled);

/**
* libnvme_host_is_epcsd_enabled() - Is Persistenct Discovery Controller enabled
* @h: Host which to check if PDC is enabled
* @fallback: The fallback default value of the flag when
* @libnvme_host_set_epcsd_enabled has not be used
* to set the flag.
*
* Return: true if PDC is enabled for @h, else false
*/
bool libnvme_host_is_epcsd_enabled(libnvme_host_t h, bool fallback);

/**
* libnvme_host_set_pdc_enabled() - Set Persistent Discovery Controller flag
* @h: Host for which the falg should be set
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ conf.set('NVME_VERSION', '"@0@"'.format(meson.project_version()))
conf.set('LIBNVME_VERSION', '"@0@"'.format(meson.project_version()))

conf.set10('DEFAULT_PDC_ENABLED', get_option('pdc-enabled'))
conf.set10('DEFAULT_EPCSD_ENABLED', get_option('default-epcsd-enabled'))


# local (cross-compilable) implementations of ccan configure steps
conf.set10(
Expand Down
6 changes: 6 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ option(
value : false,
description : 'set default Persistent Discovery Controllers behavior'
)
option(
'default-epcsd-enabled',
type: 'boolean',
value : true,
description : 'by default set Supported Persistent Discovery Controllers to be persistent'
)
option(
'rundir',
type: 'string',
Expand Down
Loading