diff --git a/fabrics.c b/fabrics.c index e32b5fdbaf..5c0617c701 100644 --- a/fabrics.c +++ b/fabrics.c @@ -110,9 +110,27 @@ struct nvmf_args { const char *keyring; const char *tls_key; const char *tls_key_identity; + int queue_size; + int nr_io_queues; + int reconnect_delay; + int ctrl_loss_tmo; + int fast_io_fail_tmo; + int keep_alive_tmo; + int nr_write_queues; + int nr_poll_queues; + int tos; + long keyring_id; + long tls_key_id; + long tls_configured_key_id; + bool duplicate_connect; + bool disable_sqflow; + bool hdr_digest; + bool data_digest; + bool tls; + bool concat; }; -#define NVMF_ARGS(n, f, c, ...) \ +#define NVMF_ARGS(n, f, ...) \ NVME_ARGS(n, \ OPT_STRING("transport", 't', "STR", &f.transport, nvmf_tport), \ OPT_STRING("nqn", 'n', "STR", &f.subsysnqn, nvmf_nqn), \ @@ -127,25 +145,31 @@ struct nvmf_args { OPT_STRING("keyring", 0, "STR", &f.keyring, nvmf_keyring), \ OPT_STRING("tls-key", 0, "STR", &f.tls_key, nvmf_tls_key), \ OPT_STRING("tls-key-identity", 0, "STR", &f.tls_key_identity, nvmf_tls_key_identity), \ - OPT_INT("nr-io-queues", 'i', &c.nr_io_queues, nvmf_nr_io_queues), \ - OPT_INT("nr-write-queues", 'W', &c.nr_write_queues, nvmf_nr_write_queues), \ - OPT_INT("nr-poll-queues", 'P', &c.nr_poll_queues, nvmf_nr_poll_queues), \ - OPT_INT("queue-size", 'Q', &c.queue_size, nvmf_queue_size), \ - OPT_INT("keep-alive-tmo", 'k', &c.keep_alive_tmo, nvmf_keep_alive_tmo), \ - OPT_INT("reconnect-delay", 'c', &c.reconnect_delay, nvmf_reconnect_delay), \ - OPT_INT("ctrl-loss-tmo", 'l', &c.ctrl_loss_tmo, nvmf_ctrl_loss_tmo), \ - OPT_INT("fast_io_fail_tmo", 'F', &c.fast_io_fail_tmo, nvmf_fast_io_fail_tmo),\ - OPT_INT("tos", 'T', &c.tos, nvmf_tos), \ - OPT_INT("tls_key", 0, &c.tls_key, nvmf_tls_key_legacy), \ - OPT_FLAG("duplicate-connect", 'D', &c.duplicate_connect, nvmf_dup_connect), \ - OPT_FLAG("disable-sqflow", 0, &c.disable_sqflow, nvmf_disable_sqflow), \ - OPT_FLAG("hdr-digest", 'g', &c.hdr_digest, nvmf_hdr_digest), \ - OPT_FLAG("data-digest", 'G', &c.data_digest, nvmf_data_digest), \ - OPT_FLAG("tls", 0, &c.tls, nvmf_tls), \ - OPT_FLAG("concat", 0, &c.concat, nvmf_concat), \ + OPT_INT("nr-io-queues", 'i', &f.nr_io_queues, nvmf_nr_io_queues), \ + OPT_INT("nr-write-queues", 'W', &f.nr_write_queues, nvmf_nr_write_queues), \ + OPT_INT("nr-poll-queues", 'P', &f.nr_poll_queues, nvmf_nr_poll_queues), \ + OPT_INT("queue-size", 'Q', &f.queue_size, nvmf_queue_size), \ + OPT_INT("keep-alive-tmo", 'k', &f.keep_alive_tmo, nvmf_keep_alive_tmo), \ + OPT_INT("reconnect-delay", 'c', &f.reconnect_delay, nvmf_reconnect_delay), \ + OPT_INT("ctrl-loss-tmo", 'l', &f.ctrl_loss_tmo, nvmf_ctrl_loss_tmo), \ + OPT_INT("fast_io_fail_tmo", 'F', &f.fast_io_fail_tmo, nvmf_fast_io_fail_tmo),\ + OPT_INT("tos", 'T', &f.tos, nvmf_tos), \ + OPT_INT("tls_key", 0, &f.tls_key_id, nvmf_tls_key_legacy), \ + OPT_FLAG("duplicate-connect", 'D', &f.duplicate_connect, nvmf_dup_connect), \ + OPT_FLAG("disable-sqflow", 0, &f.disable_sqflow, nvmf_disable_sqflow), \ + OPT_FLAG("hdr-digest", 'g', &f.hdr_digest, nvmf_hdr_digest), \ + OPT_FLAG("data-digest", 'G', &f.data_digest, nvmf_data_digest), \ + OPT_FLAG("tls", 0, &f.tls, nvmf_tls), \ + OPT_FLAG("concat", 0, &f.concat, nvmf_concat), \ ##__VA_ARGS__ \ ) +static void nvmf_default_args(struct nvmf_args *fa) +{ + memset(fa, 0, sizeof(*fa)); + fa->tos = -1; + fa->ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO; +} static void save_discovery_log(char *raw, struct nvmf_discovery_log *log) { @@ -174,7 +198,7 @@ static int setup_common_context(struct libnvmf_context *fctx, struct nvmf_args *fa); struct cb_fabrics_data { - struct libnvme_fabrics_config *cfg; + struct nvmf_args *fa; nvme_print_flags_t flags; bool quiet; char *raw; @@ -274,20 +298,49 @@ static void cb_parser_cleanup(struct libnvmf_context *fctx, void *user_data) fclose(cfd->f); } +static int set_fabrics_options(struct libnvmf_context *fctx, + struct nvmf_args *fa) +{ + struct libnvme_fabrics_config *fcfg; + + fcfg = libnvmf_context_get_fabrics_config(fctx); + if (!fcfg) + return -EINVAL; + + libnvme_fabrics_config_set_nr_io_queues(fcfg, fa->nr_io_queues); + libnvme_fabrics_config_set_reconnect_delay(fcfg, fa->reconnect_delay); + libnvme_fabrics_config_set_ctrl_loss_tmo(fcfg, fa->ctrl_loss_tmo); + libnvme_fabrics_config_set_fast_io_fail_tmo(fcfg, fa->fast_io_fail_tmo); + libnvme_fabrics_config_set_keep_alive_tmo(fcfg, fa->keep_alive_tmo); + libnvme_fabrics_config_set_nr_write_queues(fcfg, fa->nr_write_queues); + libnvme_fabrics_config_set_nr_poll_queues(fcfg, fa->nr_poll_queues); + libnvme_fabrics_config_set_tos(fcfg, fa->tos); + libnvme_fabrics_config_set_keyring_id(fcfg, fa->keyring_id); + libnvme_fabrics_config_set_tls_key_id(fcfg, fa->tls_key_id); + libnvme_fabrics_config_set_tls_configured_key_id(fcfg, fa->tls_configured_key_id); + libnvme_fabrics_config_set_duplicate_connect(fcfg, fa->duplicate_connect); + libnvme_fabrics_config_set_disable_sqflow(fcfg, fa->disable_sqflow); + libnvme_fabrics_config_set_hdr_digest(fcfg, fa->hdr_digest); + libnvme_fabrics_config_set_data_digest(fcfg, fa->data_digest); + libnvme_fabrics_config_set_tls(fcfg, fa->tls); + libnvme_fabrics_config_set_concat(fcfg, fa->concat); + + return 0; +} + static int cb_parser_next_line(struct libnvmf_context *fctx, void *user_data) { struct cb_fabrics_data *cfd = user_data; - struct libnvme_fabrics_config cfg; - struct nvmf_args fa = {}; + struct nvmf_args fa; char *ptr, *p, line[4096]; int argc, ret = 0; bool force = false; - NVMF_ARGS(opts, fa, cfg, + NVMF_ARGS(opts, fa, OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"), OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation")); - memcpy(&cfg, cfd->cfg, sizeof(cfg)); + memcpy(&fa, cfd->fa, sizeof(fa)); next: if (fgets(line, sizeof(line), cfd->f) == NULL) return -EOF; @@ -315,7 +368,7 @@ static int cb_parser_next_line(struct libnvmf_context *fctx, void *user_data) if (ret) return ret; - ret = libnvmf_context_set_fabrics_config(fctx, &cfg); + ret = set_fabrics_options(fctx, &fa); if (ret) return ret; @@ -351,7 +404,6 @@ static int setup_common_context(struct libnvmf_context *fctx, static int create_common_context(struct libnvme_global_ctx *ctx, bool persistent, struct nvmf_args *fa, - struct libnvme_fabrics_config *cfg, void *user_data, struct libnvmf_context **fctxp) { struct libnvmf_context *fctx; @@ -372,7 +424,7 @@ static int create_common_context(struct libnvme_global_ctx *ctx, if (err) goto err; - err = libnvmf_context_set_fabrics_config(fctx, cfg); + err = set_fabrics_options(fctx, fa); if (err) goto err; @@ -397,13 +449,12 @@ static int create_common_context(struct libnvme_global_ctx *ctx, static int create_discovery_context(struct libnvme_global_ctx *ctx, bool persistent, const char *device, struct nvmf_args *fa, - struct libnvme_fabrics_config *cfg, void *user_data, struct libnvmf_context **fctxp) { struct libnvmf_context *fctx; int err; - err = create_common_context(ctx, persistent, fa, cfg, user_data, + err = create_common_context(ctx, persistent, fa, user_data, &fctx); if (err) return err; @@ -527,7 +578,6 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect) __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvmf_context struct libnvmf_context *fctx = NULL; int ret; - struct libnvme_fabrics_config cfg; struct nvmf_args fa = { .subsysnqn = NVME_DISC_SUBSYS_NAME }; char *device = NULL; bool force = false; @@ -535,7 +585,7 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect) bool nbft = false, nonbft = false; char *nbft_path = NBFT_SYSFS_PATH; - NVMF_ARGS(opts, fa, cfg, + 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("persistent", 'p', &persistent, "persistent discovery connection"), @@ -548,7 +598,7 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect) OPT_STRING("nbft-path", 0, "STR", &nbft_path, "user-defined path for NBFT tables"), OPT_STRING("context", 0, "STR", &context, nvmf_context)); - libnvmf_default_config(&cfg); + nvmf_default_args(&fa); load_nvme_fabrics_module(); @@ -597,12 +647,12 @@ int fabrics_discovery(const char *desc, int argc, char **argv, bool connect) } struct cb_fabrics_data dld = { - .cfg = &cfg, + .fa = &fa, .flags = flags, .raw = raw, }; ret = create_discovery_context(ctx, persistent, device, &fa, - &cfg, &dld, &fctx); + &dld, &fctx); if (ret) return ret; @@ -643,15 +693,14 @@ int fabrics_connect(const char *desc, int argc, char **argv) __cleanup_nvme_ctrl libnvme_ctrl_t c = NULL; int ret; nvme_print_flags_t flags; - struct libnvme_fabrics_config cfg = { 0 }; struct nvmf_args fa = { 0 }; - NVMF_ARGS(opts, fa, cfg, + NVMF_ARGS(opts, fa, OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file), OPT_FLAG("dump-config", 'O', &dump_config, "Dump JSON configuration to stdout"), OPT_STRING("context", 0, "STR", &context, nvmf_context)); - libnvmf_default_config(&cfg); + nvmf_default_args(&fa); load_nvme_fabrics_module(); @@ -717,8 +766,7 @@ int fabrics_connect(const char *desc, int argc, char **argv) .quiet = dump_config, .raw = raw, }; - ret = create_common_context(ctx, persistent, &fa, - &cfg, &cfd, &fctx); + ret = create_common_context(ctx, persistent, &fa, &cfd, &fctx); if (ret) return ret; @@ -773,7 +821,7 @@ static void nvmf_disconnect_nqn(struct libnvme_global_ctx *ctx, char *nqn) if (strcmp(libnvme_subsystem_get_subsysnqn(s), p)) continue; libnvme_subsystem_for_each_ctrl(s, c) { - if (!libnvme_disconnect_ctrl(c)) + if (!libnvmf_disconnect_ctrl(c)) i++; } } @@ -856,7 +904,7 @@ int fabrics_disconnect(const char *desc, int argc, char **argv) "Did not find device %s\n", p); return -ENODEV; } - ret = libnvme_disconnect_ctrl(c); + ret = libnvmf_disconnect_ctrl(c); if (ret) fprintf(stderr, "Failed to disconnect %s: %s\n", @@ -922,7 +970,7 @@ int fabrics_disconnect_all(const char *desc, int argc, char **argv) else if (!strcmp(libnvme_ctrl_get_transport(c), "pcie")) continue; - if (libnvme_disconnect_ctrl(c)) + if (libnvmf_disconnect_ctrl(c)) fprintf(stderr, "failed to disconnect %s\n", libnvme_ctrl_get_name(c)); @@ -938,18 +986,17 @@ int fabrics_config(const char *desc, int argc, char **argv) bool scan_tree = false, modify_config = false, update_config = false; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; char *config_file = PATH_NVMF_CONFIG; - struct libnvme_fabrics_config cfg; struct nvmf_args fa = { }; int ret; - NVMF_ARGS(opts, fa, cfg, + NVMF_ARGS(opts, fa, OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file), OPT_FLAG("scan", 'R', &scan_tree, "Scan current NVMeoF topology"), OPT_FLAG("modify", 'M', &modify_config, "Modify JSON configuration file"), OPT_FLAG("dump", 'O', &dump_config, "Dump JSON configuration to stdout"), OPT_FLAG("update", 'U', &update_config, "Update JSON configuration file")); - libnvmf_default_config(&cfg); + nvmf_default_args(&fa); ret = argconfig_parse(argc, argv, desc, opts); if (ret) @@ -994,8 +1041,7 @@ int fabrics_config(const char *desc, int argc, char **argv) return -EINVAL; } - ret = create_common_context(ctx, persistent, &fa, - &cfg, NULL, &fctx); + ret = create_common_context(ctx, persistent, &fa, NULL, &fctx); if (ret) return ret; diff --git a/libnvme/examples/discover-loop.c b/libnvme/examples/discover-loop.c index a3151209ad..01bb2408bf 100644 --- a/libnvme/examples/discover-loop.c +++ b/libnvme/examples/discover-loop.c @@ -53,38 +53,45 @@ int main() { struct nvmf_discovery_log *log = NULL; struct libnvme_global_ctx *ctx; + struct libnvmf_context *fctx; libnvme_host_t h; libnvme_ctrl_t c; int ret; - struct libnvme_fabrics_config cfg; struct libnvmf_discovery_args *args; - libnvmf_default_config(&cfg); - ctx = libnvme_create_global_ctx(stdout, LIBNVME_DEFAULT_LOGLEVEL); if (!ctx) return 1; + ret = libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx); + if (ret) + goto free_ctx; + + ret = libnvmf_context_set_connection(fctx, NVME_DISC_SUBSYS_NAME, + "loop", NULL, NULL, NULL, NULL); + if (ret) + goto free_ctx; + ret = libnvme_scan_topology(ctx, NULL, NULL); - if (ret) { - libnvme_free_global_ctx(ctx); - return 1; - } + if (ret) + goto free_fctx; + ret = libnvme_get_host(ctx, NULL, NULL, &h); if (ret) { fprintf(stderr, "Failed to allocated memory\n"); - return 1; + goto free_fctx; } - ret = libnvme_create_ctrl(ctx, NVME_DISC_SUBSYS_NAME, "loop", - NULL, NULL, NULL, NULL, &c); + + ret = libnvmf_create_ctrl(ctx, fctx, &c); if (ret) { fprintf(stderr, "Failed to allocate memory\n"); - return 1; + goto free_fctx; } - ret = libnvmf_add_ctrl(h, c, &cfg); + + ret = libnvmf_add_ctrl(h, c); if (ret) { fprintf(stderr, "no controller found\n"); - return 1; + goto free_fctx; } ret = libnvmf_discovery_args_create(&args); @@ -94,7 +101,7 @@ int main() libnvmf_discovery_args_free(args); } - libnvme_disconnect_ctrl(c); + libnvmf_disconnect_ctrl(c); libnvme_free_ctrl(c); if (ret) @@ -102,7 +109,11 @@ int main() else print_discover_log(log); +free_fctx: + libnvmf_context_free(fctx); +free_ctx: libnvme_free_global_ctx(ctx); free(log); - return 0; + + return ret ? 1 : 0; } diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index d6ef316f3b..4717fbe59a 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -19,17 +19,19 @@ %allowexception; -%rename(global_ctx) libnvme_global_ctx; -%rename(host) libnvme_host; -%rename(ctrl) libnvme_ctrl; -%rename(subsystem) libnvme_subsystem; -%rename(ns) libnvme_ns; +%rename(global_ctx) libnvme_global_ctx; +%rename(host) libnvme_host; +%rename(ctrl) libnvme_ctrl; +%rename(subsystem) libnvme_subsystem; +%rename(ns) libnvme_ns; +%rename(fabrics_context) libnvmf_context; %{ #include #include #include #include "nvme/private.h" + #include "nvme/private-fabrics.h" static int connect_err = 0; static int discover_err = 0; @@ -98,60 +100,6 @@ PyObject *read_hostid(); } } -%typemap(in) struct libnvme_fabrics_config *($*1_type temp){ - Py_ssize_t pos = 0; - PyObject * key,*value; - memset(&temp, 0, sizeof(temp)); - temp.tos = -1; - temp.ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO; - while (PyDict_Next($input, &pos, &key, &value)) { - if (!PyUnicode_CompareWithASCIIString(key, "nr_io_queues")) { - temp.nr_io_queues = PyLong_AsLong(value); - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "reconnect_delay")) { - temp.reconnect_delay = PyLong_AsLong(value); - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "ctrl_loss_tmo")) { - temp.ctrl_loss_tmo = PyLong_AsLong(value); - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "keep_alive_tmo")) { - temp.keep_alive_tmo = PyLong_AsLong(value); - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "nr_write_queues")) { - temp.nr_write_queues = PyLong_AsLong(value); - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "nr_poll_queues")) { - temp.nr_poll_queues = PyLong_AsLong(value); - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "tos")) { - temp.tos = PyLong_AsLong(value); - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "duplicate_connect")) { - temp.duplicate_connect = PyObject_IsTrue(value) ? true : false; - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "disable_sqflow")) { - temp.disable_sqflow = PyObject_IsTrue(value) ? true : false; - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "hdr_digest")) { - temp.hdr_digest = PyObject_IsTrue(value) ? true : false; - continue; - } - if (!PyUnicode_CompareWithASCIIString(key, "data_digest")) { - temp.data_digest = PyObject_IsTrue(value) ? true : false; - continue; - } - } - $1 = &temp; -}; %typemap(out) uint8_t [8] { $result = PyBytes_FromStringAndSize((char *)$1, 8); @@ -484,6 +432,114 @@ struct libnvme_ns { uint8_t uuid[16]; }; +/* + * %rename directives give the %extend methods Python-friendly names while + * using distinct C-level names (fctx_*) that do not collide with the public + * libnvmf_context_* API declarations in fabrics.h. Without this, SWIG would + * emit SWIGINTERN libnvmf_context_set_hostnqn() which clashes with the + * non-static extern of the same name. + */ +%rename(set_hostnqn) libnvmf_context::fctx_set_hostnqn; +%rename(set_connection) libnvmf_context::fctx_set_connection; +%rename(set_persistent) libnvmf_context::fctx_set_persistent; +%rename(set_device) libnvmf_context::fctx_set_device; + +struct libnvmf_context {}; + +%extend libnvmf_context { + libnvmf_context(struct libnvme_global_ctx *ctx) { + struct libnvmf_context *fctx; + int err; + + err = libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx); + if (err) + return NULL; + + return fctx; + } + ~libnvmf_context() { + libnvmf_context_free($self); + } + int fctx_set_hostnqn(const char *hostnqn, const char *hostid = NULL) { + return libnvmf_context_set_hostnqn($self, hostnqn, hostid); + } + int fctx_set_connection(const char *subsysnqn, const char *transport, + const char *traddr = NULL, const char *trsvcid = NULL, + const char *host_traddr = NULL, + const char *host_iface = NULL) { + return libnvmf_context_set_connection($self, subsysnqn, transport, + traddr, trsvcid, + host_traddr, host_iface); + } + int fctx_set_persistent(bool persistent) { + return libnvmf_context_set_persistent($self, persistent); + } + int fctx_set_device(const char *device) { + return libnvmf_context_set_device($self, device); + } + void fctx_set_fabrics_config(PyObject *dict) { + Py_ssize_t pos = 0; + PyObject *key, *value; + + if (!PyDict_Check(dict)) { + PyErr_SetString(PyExc_TypeError, + "set_fabrics_config: argument must be a dict"); + return; + } + + while (PyDict_Next(dict, &pos, &key, &value)) { + if (!PyUnicode_CompareWithASCIIString(key, "nr_io_queues")) { + $self->cfg.nr_io_queues = PyLong_AsLong(value); + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "reconnect_delay")) { + $self->cfg.reconnect_delay = PyLong_AsLong(value); + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "ctrl_loss_tmo")) { + $self->cfg.ctrl_loss_tmo = PyLong_AsLong(value); + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "keep_alive_tmo")) { + $self->cfg.keep_alive_tmo = PyLong_AsLong(value); + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "nr_write_queues")) { + $self->cfg.nr_write_queues = PyLong_AsLong(value); + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "nr_poll_queues")) { + $self->cfg.nr_poll_queues = PyLong_AsLong(value); + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "tos")) { + $self->cfg.tos = PyLong_AsLong(value); + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "duplicate_connect")) { + $self->cfg.duplicate_connect = + PyObject_IsTrue(value) ? true : false; + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "disable_sqflow")) { + $self->cfg.disable_sqflow = + PyObject_IsTrue(value) ? true : false; + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "hdr_digest")) { + $self->cfg.hdr_digest = + PyObject_IsTrue(value) ? true : false; + continue; + } + if (!PyUnicode_CompareWithASCIIString(key, "data_digest")) { + $self->cfg.data_digest = + PyObject_IsTrue(value) ? true : false; + continue; + } + } + } +}; + %extend libnvme_global_ctx { libnvme_global_ctx(const char *config_file = NULL) { struct libnvme_global_ctx *ctx; @@ -670,21 +726,15 @@ struct libnvme_ns { %}; %pythonappend libnvme_ctrl::connect(struct libnvme_host *h, - struct libnvme_fabrics_config *cfg) { + struct libnvmf_context *fctx) { self.__host = h # Keep a reference to parent to ensure ctrl obj gets GCed before host} %pythonappend libnvme_ctrl::init(struct libnvme_host *h, int instance) { self.__host = h # Keep a reference to parent to ensure ctrl obj gets GCed before host} %extend libnvme_ctrl { libnvme_ctrl(struct libnvme_global_ctx *ctx, - const char *subsysnqn, - const char *transport, - const char *traddr = NULL, - const char *host_traddr = NULL, - const char *host_iface = NULL, - const char *trsvcid = NULL) { + struct libnvmf_context *fctx) { struct libnvme_ctrl *c; - if (libnvme_create_ctrl(ctx, subsysnqn, transport, traddr, - host_traddr, host_iface, trsvcid, &c)) + if (libnvmf_create_ctrl(ctx, fctx, &c)) return NULL; return c; } @@ -696,7 +746,7 @@ struct libnvme_ns { } struct libnvme_ctrl* __exit__(PyObject *type, PyObject *value, PyObject *traceback) { if (libnvme_ctrl_get_name($self)) - libnvme_disconnect_ctrl($self); + libnvmf_disconnect_ctrl($self); return $self; } @@ -704,19 +754,18 @@ struct libnvme_ns { return libnvme_init_ctrl(h, $self, instance) == 0; } - void connect(struct libnvme_host *h, - struct libnvme_fabrics_config *cfg = NULL) { + void connect(struct libnvme_host *h) { int ret; const char *dev; dev = libnvme_ctrl_get_name($self); - if (dev && !cfg->duplicate_connect) { + if (dev && $self->cfg.duplicate_connect) { connect_err = -ENVME_CONNECT_ALREADY; return; } Py_BEGIN_ALLOW_THREADS /* Release Python GIL */ - ret = libnvmf_add_ctrl(h, $self, cfg); + ret = libnvmf_add_ctrl(h, $self); Py_END_ALLOW_THREADS /* Reacquire Python GIL */ if (ret) { @@ -740,7 +789,7 @@ struct libnvme_ns { return; } Py_BEGIN_ALLOW_THREADS /* Release Python GIL */ - ret = libnvme_disconnect_ctrl($self); + ret = libnvmf_disconnect_ctrl($self); Py_END_ALLOW_THREADS /* Reacquire Python GIL */ if (ret < 0) connect_err = 2; diff --git a/libnvme/libnvme/tests/create-ctrl-obj.py b/libnvme/libnvme/tests/create-ctrl-obj.py index 6c57d43f5e..9112eae964 100755 --- a/libnvme/libnvme/tests/create-ctrl-obj.py +++ b/libnvme/libnvme/tests/create-ctrl-obj.py @@ -1,15 +1,18 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: LGPL-2.1-or-later -import sys -import pprint + + from libnvme import nvme ctx = nvme.global_ctx() -ctx.log_level('debug') - -host = nvme.host(ctx) -subsysnqn = nvme.NVME_DISC_SUBSYS_NAME -transport = 'loop' -traddr = '127.0.0.1' -trsvcid = '8009' -ctrl = nvme.ctrl(ctx, subsysnqn=subsysnqn, transport=transport, traddr=traddr, trsvcid=trsvcid) +ctx.log_level('debug') + +fctx = nvme.fabrics_context(ctx) +fctx.set_connection( + subsysnqn=nvme.NVME_DISC_SUBSYS_NAME, + transport='loop', + traddr='127.0.0.1', + trsvcid='8009', +) + +ctrl = nvme.ctrl(ctx, fctx) diff --git a/libnvme/libnvme/tests/gc.py b/libnvme/libnvme/tests/gc.py index 74a9dd1a7e..c453fdec93 100755 --- a/libnvme/libnvme/tests/gc.py +++ b/libnvme/libnvme/tests/gc.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: LGPL-2.1-or-later + + import gc -import sys -import pprint from libnvme import nvme ctx = nvme.global_ctx() @@ -12,13 +12,16 @@ host = nvme.host(ctx) print(f'host: {host}') +fctx = nvme.fabrics_context(ctx) +fctx.set_connection( + subsysnqn=nvme.NVME_DISC_SUBSYS_NAME, + transport='loop', +) +print(f'fctx: {fctx}') + ctrls = [] for i in range(10): - ctrl = nvme.ctrl( - ctx, - subsysnqn=nvme.NVME_DISC_SUBSYS_NAME, - transport='loop', - ) + ctrl = nvme.ctrl(ctx, fctx) ctrls.append(ctrl) print(f'ctrl {i}: {ctrl}') diff --git a/libnvme/libnvme/tests/test-objects.py b/libnvme/libnvme/tests/test-objects.py index 0aa427a29e..9fafe0fe00 100644 --- a/libnvme/libnvme/tests/test-objects.py +++ b/libnvme/libnvme/tests/test-objects.py @@ -118,20 +118,26 @@ def tearDown(self): gc.collect() def _make_loop_ctrl(self): - return nvme.ctrl(self.ctx, subsysnqn=self.subsysnqn, transport='loop') + fctx = nvme.fabrics_context(self.ctx) + fctx.set_connection( + subsysnqn=self.subsysnqn, + transport='loop' + ) + return nvme.ctrl(self.ctx, fctx) def test_creation_loop_transport(self): ctrl = self._make_loop_ctrl() self.assertIsNotNone(ctrl) def test_creation_tcp_transport_with_traddr(self): - ctrl = nvme.ctrl( - self.ctx, + fctx = nvme.fabrics_context(self.ctx) + fctx.set_connection( subsysnqn=self.subsysnqn, transport='tcp', traddr='192.168.1.1', - trsvcid='4420', + trsvcid='4420' ) + ctrl = nvme.ctrl(self.ctx, fctx) self.assertIsNotNone(ctrl) def test_transport_property(self): @@ -143,22 +149,24 @@ def test_subsysnqn_property(self): self.assertEqual(ctrl.subsysnqn, self.subsysnqn) def test_traddr_property(self): - ctrl = nvme.ctrl( - self.ctx, + fctx = nvme.fabrics_context(self.ctx) + fctx.set_connection( subsysnqn=self.subsysnqn, transport='tcp', traddr='10.0.0.1', ) + ctrl = nvme.ctrl(self.ctx, fctx) self.assertEqual(ctrl.traddr, '10.0.0.1') def test_trsvcid_property(self): - ctrl = nvme.ctrl( - self.ctx, + fctx = nvme.fabrics_context(self.ctx) + fctx.set_connection( subsysnqn=self.subsysnqn, transport='tcp', traddr='10.0.0.1', trsvcid='8009', ) + ctrl = nvme.ctrl(self.ctx, fctx) self.assertEqual(ctrl.trsvcid, '8009') def test_connected_returns_false_before_connect(self): @@ -175,7 +183,12 @@ def test_str_contains_transport(self): self.assertIn('loop', s) def test_context_manager(self): - with nvme.ctrl(self.ctx, subsysnqn=self.subsysnqn, transport='loop') as c: + fctx = nvme.fabrics_context(self.ctx) + fctx.set_connection( + subsysnqn=self.subsysnqn, + transport='loop' + ) + with nvme.ctrl(self.ctx, fctx) as c: self.assertIsNotNone(c) def test_namespaces_iterator_returns_list(self): @@ -221,11 +234,12 @@ class TestCtrlErrorHandling(unittest.TestCase): def setUp(self): self.ctx = nvme.global_ctx() - self.ctrl = nvme.ctrl( - self.ctx, + fctx = nvme.fabrics_context(self.ctx) + fctx.set_connection( subsysnqn=nvme.NVME_DISC_SUBSYS_NAME, transport='loop', ) + self.ctrl = nvme.ctrl(self.ctx, fctx) def tearDown(self): self.ctrl = None diff --git a/libnvme/src/accessors.ld b/libnvme/src/accessors.ld index 474d8dbf8c..7d00572189 100644 --- a/libnvme/src/accessors.ld +++ b/libnvme/src/accessors.ld @@ -10,145 +10,181 @@ LIBNVME_ACCESSORS_3 { global: - libnvme_path_get_name; - libnvme_path_set_name; - libnvme_path_get_sysfs_dir; - libnvme_path_set_sysfs_dir; - libnvme_path_get_ana_state; - libnvme_path_set_ana_state; - libnvme_path_get_numa_nodes; - libnvme_path_set_numa_nodes; - libnvme_path_get_grpid; - libnvme_path_set_grpid; - libnvme_ns_get_nsid; - libnvme_ns_set_nsid; - libnvme_ns_get_name; - libnvme_ns_set_name; - libnvme_ns_get_sysfs_dir; - libnvme_ns_set_sysfs_dir; - libnvme_ns_get_lba_shift; - libnvme_ns_set_lba_shift; - libnvme_ns_get_lba_size; - libnvme_ns_set_lba_size; - libnvme_ns_get_meta_size; - libnvme_ns_set_meta_size; - libnvme_ns_get_lba_count; - libnvme_ns_set_lba_count; - libnvme_ns_get_lba_util; - libnvme_ns_set_lba_util; - libnvme_ctrl_get_name; - libnvme_ctrl_get_sysfs_dir; + libnvme_ctrl_get_cntlid; + libnvme_ctrl_get_cntrltype; + libnvme_ctrl_get_dctype; + libnvme_ctrl_get_dhchap_ctrl_key; + libnvme_ctrl_get_dhchap_host_key; + libnvme_ctrl_get_discovered; + libnvme_ctrl_get_discovery_ctrl; libnvme_ctrl_get_firmware; + libnvme_ctrl_get_host_iface; + libnvme_ctrl_get_host_traddr; + libnvme_ctrl_get_keyring; libnvme_ctrl_get_model; + libnvme_ctrl_get_name; libnvme_ctrl_get_numa_node; + libnvme_ctrl_get_persistent; + libnvme_ctrl_get_phy_slot; libnvme_ctrl_get_queue_count; libnvme_ctrl_get_serial; libnvme_ctrl_get_sqsize; - libnvme_ctrl_get_transport; libnvme_ctrl_get_subsysnqn; + libnvme_ctrl_get_sysfs_dir; + libnvme_ctrl_get_tls_key; + libnvme_ctrl_get_tls_key_identity; libnvme_ctrl_get_traddr; + libnvme_ctrl_get_transport; libnvme_ctrl_get_trsvcid; - libnvme_ctrl_get_dhchap_host_key; - libnvme_ctrl_set_dhchap_host_key; - libnvme_ctrl_get_dhchap_ctrl_key; + libnvme_ctrl_get_unique_discovery_ctrl; libnvme_ctrl_set_dhchap_ctrl_key; - libnvme_ctrl_get_keyring; + libnvme_ctrl_set_dhchap_host_key; + libnvme_ctrl_set_discovered; + libnvme_ctrl_set_discovery_ctrl; libnvme_ctrl_set_keyring; - libnvme_ctrl_get_tls_key_identity; - libnvme_ctrl_set_tls_key_identity; - libnvme_ctrl_get_tls_key; + libnvme_ctrl_set_persistent; libnvme_ctrl_set_tls_key; - libnvme_ctrl_get_cntrltype; - libnvme_ctrl_get_cntlid; - libnvme_ctrl_get_dctype; - libnvme_ctrl_get_phy_slot; - libnvme_ctrl_get_host_traddr; - libnvme_ctrl_get_host_iface; - libnvme_ctrl_get_discovery_ctrl; - libnvme_ctrl_set_discovery_ctrl; - libnvme_ctrl_get_unique_discovery_ctrl; + libnvme_ctrl_set_tls_key_identity; libnvme_ctrl_set_unique_discovery_ctrl; - libnvme_ctrl_get_discovered; - libnvme_ctrl_set_discovered; - libnvme_ctrl_get_persistent; - libnvme_ctrl_set_persistent; - libnvme_subsystem_get_name; - libnvme_subsystem_get_sysfs_dir; - libnvme_subsystem_get_subsysnqn; - libnvme_subsystem_get_model; - libnvme_subsystem_get_serial; - libnvme_subsystem_get_firmware; - libnvme_subsystem_get_subsystype; - libnvme_subsystem_get_application; - libnvme_subsystem_set_application; - libnvme_subsystem_get_iopolicy; - libnvme_subsystem_set_iopolicy; - libnvme_host_get_hostnqn; - libnvme_host_get_hostid; - libnvme_host_get_dhchap_host_key; - libnvme_host_set_dhchap_host_key; - libnvme_host_get_hostsymname; - libnvme_host_set_hostsymname; - libnvme_host_get_pdc_enabled_valid; - libnvme_host_set_pdc_enabled_valid; libnvme_fabric_options_get_cntlid; - libnvme_fabric_options_set_cntlid; libnvme_fabric_options_get_concat; - libnvme_fabric_options_set_concat; libnvme_fabric_options_get_ctrl_loss_tmo; - libnvme_fabric_options_set_ctrl_loss_tmo; libnvme_fabric_options_get_data_digest; - libnvme_fabric_options_set_data_digest; libnvme_fabric_options_get_dhchap_ctrl_secret; - libnvme_fabric_options_set_dhchap_ctrl_secret; libnvme_fabric_options_get_dhchap_secret; - libnvme_fabric_options_set_dhchap_secret; libnvme_fabric_options_get_disable_sqflow; - libnvme_fabric_options_set_disable_sqflow; libnvme_fabric_options_get_discovery; - libnvme_fabric_options_set_discovery; libnvme_fabric_options_get_duplicate_connect; - libnvme_fabric_options_set_duplicate_connect; libnvme_fabric_options_get_fast_io_fail_tmo; - libnvme_fabric_options_set_fast_io_fail_tmo; libnvme_fabric_options_get_hdr_digest; - libnvme_fabric_options_set_hdr_digest; libnvme_fabric_options_get_host_iface; - libnvme_fabric_options_set_host_iface; libnvme_fabric_options_get_host_traddr; - libnvme_fabric_options_set_host_traddr; libnvme_fabric_options_get_hostid; - libnvme_fabric_options_set_hostid; libnvme_fabric_options_get_hostnqn; - libnvme_fabric_options_set_hostnqn; libnvme_fabric_options_get_instance; - libnvme_fabric_options_set_instance; libnvme_fabric_options_get_keep_alive_tmo; - libnvme_fabric_options_set_keep_alive_tmo; libnvme_fabric_options_get_keyring; - libnvme_fabric_options_set_keyring; libnvme_fabric_options_get_nqn; - libnvme_fabric_options_set_nqn; libnvme_fabric_options_get_nr_io_queues; - libnvme_fabric_options_set_nr_io_queues; libnvme_fabric_options_get_nr_poll_queues; - libnvme_fabric_options_set_nr_poll_queues; libnvme_fabric_options_get_nr_write_queues; - libnvme_fabric_options_set_nr_write_queues; libnvme_fabric_options_get_queue_size; - libnvme_fabric_options_set_queue_size; libnvme_fabric_options_get_reconnect_delay; - libnvme_fabric_options_set_reconnect_delay; libnvme_fabric_options_get_tls; - libnvme_fabric_options_set_tls; libnvme_fabric_options_get_tls_key; - libnvme_fabric_options_set_tls_key; libnvme_fabric_options_get_tos; - libnvme_fabric_options_set_tos; libnvme_fabric_options_get_traddr; - libnvme_fabric_options_set_traddr; libnvme_fabric_options_get_transport; - libnvme_fabric_options_set_transport; libnvme_fabric_options_get_trsvcid; + libnvme_fabric_options_set_cntlid; + libnvme_fabric_options_set_concat; + libnvme_fabric_options_set_ctrl_loss_tmo; + libnvme_fabric_options_set_data_digest; + libnvme_fabric_options_set_dhchap_ctrl_secret; + libnvme_fabric_options_set_dhchap_secret; + libnvme_fabric_options_set_disable_sqflow; + libnvme_fabric_options_set_discovery; + libnvme_fabric_options_set_duplicate_connect; + libnvme_fabric_options_set_fast_io_fail_tmo; + libnvme_fabric_options_set_hdr_digest; + libnvme_fabric_options_set_host_iface; + libnvme_fabric_options_set_host_traddr; + libnvme_fabric_options_set_hostid; + libnvme_fabric_options_set_hostnqn; + libnvme_fabric_options_set_instance; + libnvme_fabric_options_set_keep_alive_tmo; + libnvme_fabric_options_set_keyring; + libnvme_fabric_options_set_nqn; + libnvme_fabric_options_set_nr_io_queues; + libnvme_fabric_options_set_nr_poll_queues; + libnvme_fabric_options_set_nr_write_queues; + libnvme_fabric_options_set_queue_size; + libnvme_fabric_options_set_reconnect_delay; + libnvme_fabric_options_set_tls; + libnvme_fabric_options_set_tls_key; + libnvme_fabric_options_set_tos; + libnvme_fabric_options_set_traddr; + libnvme_fabric_options_set_transport; libnvme_fabric_options_set_trsvcid; + libnvme_fabrics_config_get_concat; + libnvme_fabrics_config_get_ctrl_loss_tmo; + libnvme_fabrics_config_get_data_digest; + libnvme_fabrics_config_get_disable_sqflow; + libnvme_fabrics_config_get_duplicate_connect; + libnvme_fabrics_config_get_fast_io_fail_tmo; + libnvme_fabrics_config_get_hdr_digest; + libnvme_fabrics_config_get_keep_alive_tmo; + libnvme_fabrics_config_get_keyring_id; + libnvme_fabrics_config_get_nr_io_queues; + libnvme_fabrics_config_get_nr_poll_queues; + libnvme_fabrics_config_get_nr_write_queues; + libnvme_fabrics_config_get_queue_size; + libnvme_fabrics_config_get_reconnect_delay; + libnvme_fabrics_config_get_tls; + libnvme_fabrics_config_get_tls_configured_key_id; + libnvme_fabrics_config_get_tls_key_id; + libnvme_fabrics_config_get_tos; + libnvme_fabrics_config_set_concat; + libnvme_fabrics_config_set_ctrl_loss_tmo; + libnvme_fabrics_config_set_data_digest; + libnvme_fabrics_config_set_disable_sqflow; + libnvme_fabrics_config_set_duplicate_connect; + libnvme_fabrics_config_set_fast_io_fail_tmo; + libnvme_fabrics_config_set_hdr_digest; + libnvme_fabrics_config_set_keep_alive_tmo; + libnvme_fabrics_config_set_keyring_id; + libnvme_fabrics_config_set_nr_io_queues; + libnvme_fabrics_config_set_nr_poll_queues; + libnvme_fabrics_config_set_nr_write_queues; + libnvme_fabrics_config_set_queue_size; + libnvme_fabrics_config_set_reconnect_delay; + libnvme_fabrics_config_set_tls; + libnvme_fabrics_config_set_tls_configured_key_id; + libnvme_fabrics_config_set_tls_key_id; + libnvme_fabrics_config_set_tos; + libnvme_host_get_dhchap_host_key; + libnvme_host_get_hostid; + libnvme_host_get_hostnqn; + libnvme_host_get_hostsymname; + libnvme_host_get_pdc_enabled_valid; + libnvme_host_set_dhchap_host_key; + libnvme_host_set_hostsymname; + libnvme_host_set_pdc_enabled_valid; + libnvme_ns_get_lba_count; + libnvme_ns_get_lba_shift; + libnvme_ns_get_lba_size; + libnvme_ns_get_lba_util; + libnvme_ns_get_meta_size; + libnvme_ns_get_name; + libnvme_ns_get_nsid; + libnvme_ns_get_sysfs_dir; + libnvme_ns_set_lba_count; + libnvme_ns_set_lba_shift; + libnvme_ns_set_lba_size; + libnvme_ns_set_lba_util; + libnvme_ns_set_meta_size; + libnvme_ns_set_name; + libnvme_ns_set_nsid; + libnvme_ns_set_sysfs_dir; + libnvme_path_get_ana_state; + libnvme_path_get_grpid; + libnvme_path_get_name; + libnvme_path_get_numa_nodes; + libnvme_path_get_sysfs_dir; + libnvme_path_set_ana_state; + libnvme_path_set_grpid; + libnvme_path_set_name; + libnvme_path_set_numa_nodes; + libnvme_path_set_sysfs_dir; + libnvme_subsystem_get_application; + libnvme_subsystem_get_firmware; + libnvme_subsystem_get_iopolicy; + libnvme_subsystem_get_model; + libnvme_subsystem_get_name; + libnvme_subsystem_get_serial; + libnvme_subsystem_get_subsysnqn; + libnvme_subsystem_get_subsystype; + libnvme_subsystem_get_sysfs_dir; + libnvme_subsystem_set_application; + libnvme_subsystem_set_iopolicy; }; diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 59f5232c51..c197112437 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -4,12 +4,10 @@ LIBNVME_3 { global: libnvme_clear_etdas; libnvme_close; - libnvme_create_ctrl; libnvme_create_global_ctx; libnvme_create_raw_secret; libnvme_ctrl_first_ns; libnvme_ctrl_first_path; - libnvme_ctrl_get_config; libnvme_ctrl_get_phy_slot; libnvme_ctrl_get_src_addr; libnvme_ctrl_get_state; @@ -22,7 +20,6 @@ LIBNVME_3 { libnvme_ctrl_next_path; libnvme_ctrl_release_transport_handle; libnvme_describe_key_serial; - libnvme_disconnect_ctrl; libnvme_dump_config; libnvme_dump_tree; libnvme_errno_to_string; diff --git a/libnvme/src/libnvmf.ld b/libnvme/src/libnvmf.ld index c271e4fb15..f93f21d2b6 100644 --- a/libnvme/src/libnvmf.ld +++ b/libnvme/src/libnvmf.ld @@ -11,6 +11,7 @@ LIBNVMF_3 { libnvmf_connect_ctrl; libnvmf_context_create; libnvmf_context_free; + libnvmf_context_get_fabrics_config; libnvmf_context_set_connection; libnvmf_context_set_crypto; libnvmf_context_set_device; @@ -19,8 +20,12 @@ LIBNVMF_3 { libnvmf_context_set_fabrics_config; libnvmf_context_set_hostnqn; libnvmf_context_set_persistent; - libnvmf_default_config; + libnvmf_create_ctrl; + libnvmf_ctrl_get_fabrics_config; + libnvmf_disconnect_ctrl; libnvmf_discovery; + libnvmf_discovery_args_create; + libnvmf_discovery_args_free; libnvmf_discovery_config_file; libnvmf_discovery_config_json; libnvmf_discovery_nbft; @@ -28,8 +33,6 @@ LIBNVMF_3 { libnvmf_exat_ptr_next; libnvmf_free_uri; libnvmf_get_default_trsvcid; - libnvmf_discovery_args_create; - libnvmf_discovery_args_free; libnvmf_get_discovery_log; libnvmf_is_registration_supported; libnvmf_nbft_free; @@ -41,7 +44,6 @@ LIBNVMF_3 { libnvmf_subtype_str; libnvmf_treq_str; libnvmf_trtype_str; - libnvmf_update_config; local: *; }; diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index bcfc7c8800..d227ed4644 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -50,6 +50,10 @@ if want_fabrics 'nvme/nbft.h', 'nvme/accessors-fabrics.h', ] +else + sources += [ + 'nvme/no-fabrics.c', + ] endif if want_mi diff --git a/libnvme/src/nvme/accessors-fabrics.c b/libnvme/src/nvme/accessors-fabrics.c index 12ad9b71ff..23695d76f9 100644 --- a/libnvme/src/nvme/accessors-fabrics.c +++ b/libnvme/src/nvme/accessors-fabrics.c @@ -48,7 +48,8 @@ __public void libnvmf_discovery_args_set_lsp( p->lsp = lsp; } -__public __u8 libnvmf_discovery_args_get_lsp(const struct libnvmf_discovery_args *p) +__public __u8 libnvmf_discovery_args_get_lsp( + const struct libnvmf_discovery_args *p) { return p->lsp; } diff --git a/libnvme/src/nvme/accessors-fabrics.h b/libnvme/src/nvme/accessors-fabrics.h index 3ff6edef1a..b52458361c 100644 --- a/libnvme/src/nvme/accessors-fabrics.h +++ b/libnvme/src/nvme/accessors-fabrics.h @@ -49,7 +49,8 @@ void libnvmf_discovery_args_set_max_retries( * * Return: The value of the max_retries field. */ -int libnvmf_discovery_args_get_max_retries(const struct libnvmf_discovery_args *p); +int libnvmf_discovery_args_get_max_retries( + const struct libnvmf_discovery_args *p); /** * libnvmf_discovery_args_set_lsp() - Set lsp. diff --git a/libnvme/src/nvme/accessors.c b/libnvme/src/nvme/accessors.c index 20b645984c..76348ce1a3 100644 --- a/libnvme/src/nvme/accessors.c +++ b/libnvme/src/nvme/accessors.c @@ -24,6 +24,244 @@ #include "private.h" #include "compiler-attributes.h" +/**************************************************************************** + * Accessors for: struct libnvme_fabrics_config + ****************************************************************************/ + +__public void libnvme_fabrics_config_set_queue_size( + struct libnvme_fabrics_config *p, + int queue_size) +{ + p->queue_size = queue_size; +} + +__public int libnvme_fabrics_config_get_queue_size( + const struct libnvme_fabrics_config *p) +{ + return p->queue_size; +} + +__public void libnvme_fabrics_config_set_nr_io_queues( + struct libnvme_fabrics_config *p, + int nr_io_queues) +{ + p->nr_io_queues = nr_io_queues; +} + +__public int libnvme_fabrics_config_get_nr_io_queues( + const struct libnvme_fabrics_config *p) +{ + return p->nr_io_queues; +} + +__public void libnvme_fabrics_config_set_reconnect_delay( + struct libnvme_fabrics_config *p, + int reconnect_delay) +{ + p->reconnect_delay = reconnect_delay; +} + +__public int libnvme_fabrics_config_get_reconnect_delay( + const struct libnvme_fabrics_config *p) +{ + return p->reconnect_delay; +} + +__public void libnvme_fabrics_config_set_ctrl_loss_tmo( + struct libnvme_fabrics_config *p, + int ctrl_loss_tmo) +{ + p->ctrl_loss_tmo = ctrl_loss_tmo; +} + +__public int libnvme_fabrics_config_get_ctrl_loss_tmo( + const struct libnvme_fabrics_config *p) +{ + return p->ctrl_loss_tmo; +} + +__public void libnvme_fabrics_config_set_fast_io_fail_tmo( + struct libnvme_fabrics_config *p, + int fast_io_fail_tmo) +{ + p->fast_io_fail_tmo = fast_io_fail_tmo; +} + +__public int libnvme_fabrics_config_get_fast_io_fail_tmo( + const struct libnvme_fabrics_config *p) +{ + return p->fast_io_fail_tmo; +} + +__public void libnvme_fabrics_config_set_keep_alive_tmo( + struct libnvme_fabrics_config *p, + int keep_alive_tmo) +{ + p->keep_alive_tmo = keep_alive_tmo; +} + +__public int libnvme_fabrics_config_get_keep_alive_tmo( + const struct libnvme_fabrics_config *p) +{ + return p->keep_alive_tmo; +} + +__public void libnvme_fabrics_config_set_nr_write_queues( + struct libnvme_fabrics_config *p, + int nr_write_queues) +{ + p->nr_write_queues = nr_write_queues; +} + +__public int libnvme_fabrics_config_get_nr_write_queues( + const struct libnvme_fabrics_config *p) +{ + return p->nr_write_queues; +} + +__public void libnvme_fabrics_config_set_nr_poll_queues( + struct libnvme_fabrics_config *p, + int nr_poll_queues) +{ + p->nr_poll_queues = nr_poll_queues; +} + +__public int libnvme_fabrics_config_get_nr_poll_queues( + const struct libnvme_fabrics_config *p) +{ + return p->nr_poll_queues; +} + +__public void libnvme_fabrics_config_set_tos( + struct libnvme_fabrics_config *p, + int tos) +{ + p->tos = tos; +} + +__public int libnvme_fabrics_config_get_tos( + const struct libnvme_fabrics_config *p) +{ + return p->tos; +} + +__public void libnvme_fabrics_config_set_keyring_id( + struct libnvme_fabrics_config *p, + long keyring_id) +{ + p->keyring_id = keyring_id; +} + +__public long libnvme_fabrics_config_get_keyring_id( + const struct libnvme_fabrics_config *p) +{ + return p->keyring_id; +} + +__public void libnvme_fabrics_config_set_tls_key_id( + struct libnvme_fabrics_config *p, + long tls_key_id) +{ + p->tls_key_id = tls_key_id; +} + +__public long libnvme_fabrics_config_get_tls_key_id( + const struct libnvme_fabrics_config *p) +{ + return p->tls_key_id; +} + +__public void libnvme_fabrics_config_set_tls_configured_key_id( + struct libnvme_fabrics_config *p, + long tls_configured_key_id) +{ + p->tls_configured_key_id = tls_configured_key_id; +} + +__public long libnvme_fabrics_config_get_tls_configured_key_id( + const struct libnvme_fabrics_config *p) +{ + return p->tls_configured_key_id; +} + +__public void libnvme_fabrics_config_set_duplicate_connect( + struct libnvme_fabrics_config *p, + bool duplicate_connect) +{ + p->duplicate_connect = duplicate_connect; +} + +__public bool libnvme_fabrics_config_get_duplicate_connect( + const struct libnvme_fabrics_config *p) +{ + return p->duplicate_connect; +} + +__public void libnvme_fabrics_config_set_disable_sqflow( + struct libnvme_fabrics_config *p, + bool disable_sqflow) +{ + p->disable_sqflow = disable_sqflow; +} + +__public bool libnvme_fabrics_config_get_disable_sqflow( + const struct libnvme_fabrics_config *p) +{ + return p->disable_sqflow; +} + +__public void libnvme_fabrics_config_set_hdr_digest( + struct libnvme_fabrics_config *p, + bool hdr_digest) +{ + p->hdr_digest = hdr_digest; +} + +__public bool libnvme_fabrics_config_get_hdr_digest( + const struct libnvme_fabrics_config *p) +{ + return p->hdr_digest; +} + +__public void libnvme_fabrics_config_set_data_digest( + struct libnvme_fabrics_config *p, + bool data_digest) +{ + p->data_digest = data_digest; +} + +__public bool libnvme_fabrics_config_get_data_digest( + const struct libnvme_fabrics_config *p) +{ + return p->data_digest; +} + +__public void libnvme_fabrics_config_set_tls( + struct libnvme_fabrics_config *p, + bool tls) +{ + p->tls = tls; +} + +__public bool libnvme_fabrics_config_get_tls( + const struct libnvme_fabrics_config *p) +{ + return p->tls; +} + +__public void libnvme_fabrics_config_set_concat( + struct libnvme_fabrics_config *p, + bool concat) +{ + p->concat = concat; +} + +__public bool libnvme_fabrics_config_get_concat( + const struct libnvme_fabrics_config *p) +{ + return p->concat; +} + /**************************************************************************** * Accessors for: struct libnvme_path ****************************************************************************/ diff --git a/libnvme/src/nvme/accessors.h b/libnvme/src/nvme/accessors.h index 94c7f2a725..22fcf1c269 100644 --- a/libnvme/src/nvme/accessors.h +++ b/libnvme/src/nvme/accessors.h @@ -28,6 +28,7 @@ #include /* Forward declarations. These are internal (opaque) structs. */ +struct libnvme_fabrics_config; struct libnvme_path; struct libnvme_ns; struct libnvme_ctrl; @@ -35,6 +36,327 @@ struct libnvme_subsystem; struct libnvme_host; struct libnvme_fabric_options; +/**************************************************************************** + * Accessors for: struct libnvme_fabrics_config + ****************************************************************************/ + +/** + * libnvme_fabrics_config_set_queue_size() - Set queue_size. + * @p: The &struct libnvme_fabrics_config instance to update. + * @queue_size: Value to assign to the queue_size field. + */ +void libnvme_fabrics_config_set_queue_size( + struct libnvme_fabrics_config *p, + int queue_size); + +/** + * libnvme_fabrics_config_get_queue_size() - Get queue_size. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the queue_size field. + */ +int libnvme_fabrics_config_get_queue_size( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_nr_io_queues() - Set nr_io_queues. + * @p: The &struct libnvme_fabrics_config instance to update. + * @nr_io_queues: Value to assign to the nr_io_queues field. + */ +void libnvme_fabrics_config_set_nr_io_queues( + struct libnvme_fabrics_config *p, + int nr_io_queues); + +/** + * libnvme_fabrics_config_get_nr_io_queues() - Get nr_io_queues. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the nr_io_queues field. + */ +int libnvme_fabrics_config_get_nr_io_queues( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_reconnect_delay() - Set reconnect_delay. + * @p: The &struct libnvme_fabrics_config instance to update. + * @reconnect_delay: Value to assign to the reconnect_delay field. + */ +void libnvme_fabrics_config_set_reconnect_delay( + struct libnvme_fabrics_config *p, + int reconnect_delay); + +/** + * libnvme_fabrics_config_get_reconnect_delay() - Get reconnect_delay. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the reconnect_delay field. + */ +int libnvme_fabrics_config_get_reconnect_delay( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_ctrl_loss_tmo() - Set ctrl_loss_tmo. + * @p: The &struct libnvme_fabrics_config instance to update. + * @ctrl_loss_tmo: Value to assign to the ctrl_loss_tmo field. + */ +void libnvme_fabrics_config_set_ctrl_loss_tmo( + struct libnvme_fabrics_config *p, + int ctrl_loss_tmo); + +/** + * libnvme_fabrics_config_get_ctrl_loss_tmo() - Get ctrl_loss_tmo. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the ctrl_loss_tmo field. + */ +int libnvme_fabrics_config_get_ctrl_loss_tmo( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_fast_io_fail_tmo() - Set fast_io_fail_tmo. + * @p: The &struct libnvme_fabrics_config instance to update. + * @fast_io_fail_tmo: Value to assign to the fast_io_fail_tmo field. + */ +void libnvme_fabrics_config_set_fast_io_fail_tmo( + struct libnvme_fabrics_config *p, + int fast_io_fail_tmo); + +/** + * libnvme_fabrics_config_get_fast_io_fail_tmo() - Get fast_io_fail_tmo. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the fast_io_fail_tmo field. + */ +int libnvme_fabrics_config_get_fast_io_fail_tmo( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_keep_alive_tmo() - Set keep_alive_tmo. + * @p: The &struct libnvme_fabrics_config instance to update. + * @keep_alive_tmo: Value to assign to the keep_alive_tmo field. + */ +void libnvme_fabrics_config_set_keep_alive_tmo( + struct libnvme_fabrics_config *p, + int keep_alive_tmo); + +/** + * libnvme_fabrics_config_get_keep_alive_tmo() - Get keep_alive_tmo. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the keep_alive_tmo field. + */ +int libnvme_fabrics_config_get_keep_alive_tmo( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_nr_write_queues() - Set nr_write_queues. + * @p: The &struct libnvme_fabrics_config instance to update. + * @nr_write_queues: Value to assign to the nr_write_queues field. + */ +void libnvme_fabrics_config_set_nr_write_queues( + struct libnvme_fabrics_config *p, + int nr_write_queues); + +/** + * libnvme_fabrics_config_get_nr_write_queues() - Get nr_write_queues. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the nr_write_queues field. + */ +int libnvme_fabrics_config_get_nr_write_queues( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_nr_poll_queues() - Set nr_poll_queues. + * @p: The &struct libnvme_fabrics_config instance to update. + * @nr_poll_queues: Value to assign to the nr_poll_queues field. + */ +void libnvme_fabrics_config_set_nr_poll_queues( + struct libnvme_fabrics_config *p, + int nr_poll_queues); + +/** + * libnvme_fabrics_config_get_nr_poll_queues() - Get nr_poll_queues. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the nr_poll_queues field. + */ +int libnvme_fabrics_config_get_nr_poll_queues( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_tos() - Set tos. + * @p: The &struct libnvme_fabrics_config instance to update. + * @tos: Value to assign to the tos field. + */ +void libnvme_fabrics_config_set_tos(struct libnvme_fabrics_config *p, int tos); + +/** + * libnvme_fabrics_config_get_tos() - Get tos. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the tos field. + */ +int libnvme_fabrics_config_get_tos(const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_keyring_id() - Set keyring_id. + * @p: The &struct libnvme_fabrics_config instance to update. + * @keyring_id: Value to assign to the keyring_id field. + */ +void libnvme_fabrics_config_set_keyring_id( + struct libnvme_fabrics_config *p, + long keyring_id); + +/** + * libnvme_fabrics_config_get_keyring_id() - Get keyring_id. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the keyring_id field. + */ +long libnvme_fabrics_config_get_keyring_id( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_tls_key_id() - Set tls_key_id. + * @p: The &struct libnvme_fabrics_config instance to update. + * @tls_key_id: Value to assign to the tls_key_id field. + */ +void libnvme_fabrics_config_set_tls_key_id( + struct libnvme_fabrics_config *p, + long tls_key_id); + +/** + * libnvme_fabrics_config_get_tls_key_id() - Get tls_key_id. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the tls_key_id field. + */ +long libnvme_fabrics_config_get_tls_key_id( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_tls_configured_key_id() - Set tls_configured_key_id. + * @p: The &struct libnvme_fabrics_config instance to update. + * @tls_configured_key_id: Value to assign to the tls_configured_key_id field. + */ +void libnvme_fabrics_config_set_tls_configured_key_id( + struct libnvme_fabrics_config *p, + long tls_configured_key_id); + +/** + * libnvme_fabrics_config_get_tls_configured_key_id() - Get tls_configured_key_id. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the tls_configured_key_id field. + */ +long libnvme_fabrics_config_get_tls_configured_key_id( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_duplicate_connect() - Set duplicate_connect. + * @p: The &struct libnvme_fabrics_config instance to update. + * @duplicate_connect: Value to assign to the duplicate_connect field. + */ +void libnvme_fabrics_config_set_duplicate_connect( + struct libnvme_fabrics_config *p, + bool duplicate_connect); + +/** + * libnvme_fabrics_config_get_duplicate_connect() - Get duplicate_connect. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the duplicate_connect field. + */ +bool libnvme_fabrics_config_get_duplicate_connect( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_disable_sqflow() - Set disable_sqflow. + * @p: The &struct libnvme_fabrics_config instance to update. + * @disable_sqflow: Value to assign to the disable_sqflow field. + */ +void libnvme_fabrics_config_set_disable_sqflow( + struct libnvme_fabrics_config *p, + bool disable_sqflow); + +/** + * libnvme_fabrics_config_get_disable_sqflow() - Get disable_sqflow. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the disable_sqflow field. + */ +bool libnvme_fabrics_config_get_disable_sqflow( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_hdr_digest() - Set hdr_digest. + * @p: The &struct libnvme_fabrics_config instance to update. + * @hdr_digest: Value to assign to the hdr_digest field. + */ +void libnvme_fabrics_config_set_hdr_digest( + struct libnvme_fabrics_config *p, + bool hdr_digest); + +/** + * libnvme_fabrics_config_get_hdr_digest() - Get hdr_digest. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the hdr_digest field. + */ +bool libnvme_fabrics_config_get_hdr_digest( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_data_digest() - Set data_digest. + * @p: The &struct libnvme_fabrics_config instance to update. + * @data_digest: Value to assign to the data_digest field. + */ +void libnvme_fabrics_config_set_data_digest( + struct libnvme_fabrics_config *p, + bool data_digest); + +/** + * libnvme_fabrics_config_get_data_digest() - Get data_digest. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the data_digest field. + */ +bool libnvme_fabrics_config_get_data_digest( + const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_tls() - Set tls. + * @p: The &struct libnvme_fabrics_config instance to update. + * @tls: Value to assign to the tls field. + */ +void libnvme_fabrics_config_set_tls(struct libnvme_fabrics_config *p, bool tls); + +/** + * libnvme_fabrics_config_get_tls() - Get tls. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the tls field. + */ +bool libnvme_fabrics_config_get_tls(const struct libnvme_fabrics_config *p); + +/** + * libnvme_fabrics_config_set_concat() - Set concat. + * @p: The &struct libnvme_fabrics_config instance to update. + * @concat: Value to assign to the concat field. + */ +void libnvme_fabrics_config_set_concat( + struct libnvme_fabrics_config *p, + bool concat); + +/** + * libnvme_fabrics_config_get_concat() - Get concat. + * @p: The &struct libnvme_fabrics_config instance to query. + * + * Return: The value of the concat field. + */ +bool libnvme_fabrics_config_get_concat(const struct libnvme_fabrics_config *p); + /**************************************************************************** * Accessors for: struct libnvme_path ****************************************************************************/ diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 7c3b9c680f..06beda1fdc 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -196,6 +196,12 @@ __public const char *libnvmf_cms_str(__u8 cm) return arg_str(cms, ARRAY_SIZE(cms), cm); } +void libnvmf_default_config(struct libnvme_fabrics_config *cfg) +{ + cfg->tos = -1; + cfg->ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO; +} + __public int libnvmf_context_create(struct libnvme_global_ctx *ctx, bool (*decide_retry)(struct libnvmf_context *fctx, int err, void *user_data), @@ -215,6 +221,8 @@ __public int libnvmf_context_create(struct libnvme_global_ctx *ctx, fctx->ctx = ctx; + libnvmf_default_config(&fctx->cfg); + fctx->decide_retry = decide_retry; fctx->connected = connected; fctx->already_connected = already_connected; @@ -263,7 +271,24 @@ __public int libnvmf_context_set_discovery_defaults(struct libnvmf_context *fctx __public int libnvmf_context_set_fabrics_config(struct libnvmf_context *fctx, struct libnvme_fabrics_config *cfg) { - fctx->cfg = cfg; + fctx->cfg.queue_size = cfg->queue_size; + fctx->cfg.nr_io_queues = cfg->nr_io_queues; + fctx->cfg.reconnect_delay = cfg->reconnect_delay; + fctx->cfg.ctrl_loss_tmo = cfg->ctrl_loss_tmo; + fctx->cfg.fast_io_fail_tmo = cfg->fast_io_fail_tmo; + fctx->cfg.keep_alive_tmo = cfg->keep_alive_tmo; + fctx->cfg.nr_write_queues = cfg->nr_write_queues; + fctx->cfg.nr_poll_queues = cfg->nr_poll_queues; + fctx->cfg.tos = cfg->tos; + fctx->cfg.keyring_id = cfg->keyring_id; + fctx->cfg.tls_key_id = cfg->tls_key_id; + fctx->cfg.tls_configured_key_id = cfg->tls_configured_key_id; + fctx->cfg.duplicate_connect = cfg->duplicate_connect; + fctx->cfg.disable_sqflow = cfg->disable_sqflow; + fctx->cfg.hdr_digest = cfg->hdr_digest; + fctx->cfg.data_digest = cfg->data_digest; + fctx->cfg.tls = cfg->tls; + fctx->cfg.concat = cfg->concat; return 0; } @@ -361,6 +386,18 @@ __public int libnvmf_context_set_device(struct libnvmf_context *fctx, const char return 0; } +__public struct libnvme_fabrics_config *libnvmf_context_get_fabrics_config( + struct libnvmf_context *fctx) +{ + return &fctx->cfg; +} + +__public struct libnvme_fabrics_config *libnvmf_ctrl_get_fabrics_config( + libnvme_ctrl_t c) +{ + return &c->cfg; +} + /* * Derived from Linux's supported options (the opt_tokens table) * when the mechanism to report supported options was added (f18ee3d988157). @@ -394,10 +431,11 @@ static const struct libnvme_fabric_options default_supported_options = { #define MERGE_CFG_OPTION(c, n, o, d) \ if ((c)->o == d) (c)->o = (n)->o -static struct libnvme_fabrics_config *merge_config(libnvme_ctrl_t c, +static void merge_config(libnvme_ctrl_t c, const struct libnvme_fabrics_config *cfg) { - struct libnvme_fabrics_config *ctrl_cfg = libnvme_ctrl_get_config(c); + struct libnvme_fabrics_config *ctrl_cfg = + libnvmf_ctrl_get_fabrics_config(c); MERGE_CFG_OPTION(ctrl_cfg, cfg, nr_io_queues, 0); MERGE_CFG_OPTION(ctrl_cfg, cfg, nr_write_queues, 0); @@ -409,23 +447,24 @@ static struct libnvme_fabrics_config *merge_config(libnvme_ctrl_t c, NVMF_DEF_CTRL_LOSS_TMO); MERGE_CFG_OPTION(ctrl_cfg, cfg, fast_io_fail_tmo, 0); MERGE_CFG_OPTION(ctrl_cfg, cfg, tos, -1); - MERGE_CFG_OPTION(ctrl_cfg, cfg, keyring, 0); - MERGE_CFG_OPTION(ctrl_cfg, cfg, tls_key, 0); + MERGE_CFG_OPTION(ctrl_cfg, cfg, keyring_id, 0); + MERGE_CFG_OPTION(ctrl_cfg, cfg, tls_key_id, 0); + MERGE_CFG_OPTION(ctrl_cfg, cfg, tls_configured_key_id, 0); MERGE_CFG_OPTION(ctrl_cfg, cfg, duplicate_connect, false); MERGE_CFG_OPTION(ctrl_cfg, cfg, disable_sqflow, false); MERGE_CFG_OPTION(ctrl_cfg, cfg, hdr_digest, false); MERGE_CFG_OPTION(ctrl_cfg, cfg, data_digest, false); MERGE_CFG_OPTION(ctrl_cfg, cfg, tls, false); MERGE_CFG_OPTION(ctrl_cfg, cfg, concat, false); - - return ctrl_cfg; } #define UPDATE_CFG_OPTION(c, n, o, d) \ if ((n)->o != d) (c)->o = (n)->o -__public void libnvmf_update_config(libnvme_ctrl_t c, const struct libnvme_fabrics_config *cfg) +static void update_config(libnvme_ctrl_t c, + const struct libnvme_fabrics_config *cfg) { - struct libnvme_fabrics_config *ctrl_cfg = libnvme_ctrl_get_config(c); + struct libnvme_fabrics_config *ctrl_cfg = + libnvmf_ctrl_get_fabrics_config(c); UPDATE_CFG_OPTION(ctrl_cfg, cfg, nr_io_queues, 0); UPDATE_CFG_OPTION(ctrl_cfg, cfg, nr_write_queues, 0); @@ -437,8 +476,9 @@ __public void libnvmf_update_config(libnvme_ctrl_t c, const struct libnvme_fabri NVMF_DEF_CTRL_LOSS_TMO); UPDATE_CFG_OPTION(ctrl_cfg, cfg, fast_io_fail_tmo, 0); UPDATE_CFG_OPTION(ctrl_cfg, cfg, tos, -1); - UPDATE_CFG_OPTION(ctrl_cfg, cfg, keyring, 0); - UPDATE_CFG_OPTION(ctrl_cfg, cfg, tls_key, 0); + UPDATE_CFG_OPTION(ctrl_cfg, cfg, keyring_id , 0); + UPDATE_CFG_OPTION(ctrl_cfg, cfg, tls_key_id, 0); + UPDATE_CFG_OPTION(ctrl_cfg, cfg, tls_configured_key_id, 0); UPDATE_CFG_OPTION(ctrl_cfg, cfg, duplicate_connect, false); UPDATE_CFG_OPTION(ctrl_cfg, cfg, disable_sqflow, false); UPDATE_CFG_OPTION(ctrl_cfg, cfg, hdr_digest, false); @@ -714,22 +754,27 @@ static int inet_pton_with_scope(struct libnvme_global_ctx *ctx, int af, return ret; } -static bool traddr_is_hostname(struct libnvme_global_ctx *ctx, libnvme_ctrl_t c) +bool traddr_is_hostname(struct libnvme_global_ctx *ctx, + const char *transport, const char *traddr) { struct sockaddr_storage addr; - if (!c->traddr) + if (!traddr || !transport) return false; - if (strcmp(c->transport, "tcp") && strcmp(c->transport, "rdma")) + if (!strcmp(traddr, "none")) return false; - if (inet_pton_with_scope(ctx, AF_UNSPEC, c->traddr, c->trsvcid, &addr) == 0) + if (strcmp(transport, "tcp") && strcmp(transport, "rdma")) return false; + if (inet_pton_with_scope(ctx, AF_UNSPEC, + traddr, NULL, &addr) == 0) /* scope-aware */ + return false; + return true; } static int build_options(libnvme_host_t h, libnvme_ctrl_t c, char **argstr) { - struct libnvme_fabrics_config *cfg = libnvme_ctrl_get_config(c); + struct libnvme_fabrics_config *cfg = libnvmf_ctrl_get_fabrics_config(c); const char *transport = libnvme_ctrl_get_transport(c); const char *hostnqn, *hostid, *hostkey, *ctrlkey = NULL; bool discover = false, discovery_nqn = false; @@ -791,10 +836,10 @@ static int build_options(libnvme_host_t h, libnvme_ctrl_t c, char **argstr) return ret; if (key_id == 0) { - if (cfg->tls_configured_key) - key_id = cfg->tls_configured_key; + if (cfg->tls_configured_key_id) + key_id = cfg->tls_configured_key_id; else - key_id = cfg->tls_key; + key_id = cfg->tls_key_id; } } @@ -1042,17 +1087,19 @@ static const char *lookup_context(struct libnvme_global_ctx *ctx, libnvme_ctrl_t return NULL; } -__public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, - const struct libnvme_fabrics_config *cfg) +__public int libnvmf_create_ctrl(struct libnvme_global_ctx *ctx, + struct libnvmf_context *fctx, libnvme_ctrl_t *cp) +{ + return _libnvme_create_ctrl(ctx, fctx, cp); +} + +__public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c) { libnvme_subsystem_t s; const char *root_app, *app; __cleanup_free char *argstr = NULL; int ret; - /* highest prio have configs from command line */ - cfg = merge_config(c, cfg); - /* apply configuration from config file (JSON) */ s = libnvme_lookup_subsystem(h, NULL, libnvme_ctrl_get_subsysnqn(c)); if (s) { @@ -1070,7 +1117,7 @@ __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, if (fc) { const char *key; - cfg = merge_config(c, libnvme_ctrl_get_config(fc)); + merge_config(c, libnvmf_ctrl_get_fabrics_config(fc)); /* * An authentication key might already been set * in @cfg, so ensure to update @c with the correct @@ -1115,7 +1162,7 @@ __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, } libnvme_ctrl_set_discovered(c, true); - if (traddr_is_hostname(h->ctx, c)) { + if (traddr_is_hostname(h->ctx, c->transport, c->traddr)) { char *traddr = c->traddr; if (hostname2traddr(h->ctx, traddr, &c->traddr)) { @@ -1154,6 +1201,24 @@ __public int libnvmf_connect_ctrl(libnvme_ctrl_t c) return 0; } +__public int libnvmf_disconnect_ctrl(libnvme_ctrl_t c) +{ + struct libnvme_global_ctx *ctx = c->s && c->s->h ? c->s->h->ctx : NULL; + int ret; + + ret = libnvme_set_attr(libnvme_ctrl_get_sysfs_dir(c), + "delete_controller", "1"); + if (ret < 0) { + libnvme_msg(ctx, LIBNVME_LOG_ERR, + "%s: failed to disconnect, error %d\n", c->name, errno); + return ret; + } + libnvme_msg(ctx, LIBNVME_LOG_INFO, "%s: %s disconnected\n", + c->name, c->subsysnqn); + nvme_deconfigure_ctrl(c); + return 0; +} + static void nvmf_update_tls_concat(struct nvmf_disc_log_entry *e, libnvme_ctrl_t c, libnvme_host_t h) { @@ -1185,7 +1250,6 @@ static void nvmf_update_tls_concat(struct nvmf_disc_log_entry *e, static int nvmf_connect_disc_entry(libnvme_host_t h, struct nvmf_disc_log_entry *e, struct libnvmf_context *fctx, - const struct libnvme_fabrics_config *cfg, bool *discover, libnvme_ctrl_t *cp) { libnvme_ctrl_t c; @@ -1278,7 +1342,7 @@ static int nvmf_connect_disc_entry(libnvme_host_t h, /* update tls or concat */ nvmf_update_tls_concat(e, c, h); - ret = libnvmf_add_ctrl(h, c, cfg); + ret = libnvmf_add_ctrl(h, c); if (!ret) { *cp = c; return 0; @@ -1289,7 +1353,7 @@ static int nvmf_connect_disc_entry(libnvme_host_t h, libnvme_msg(h->ctx, LIBNVME_LOG_INFO, "failed to connect controller, " "retry with disabling SQ flow control\n"); c->cfg.disable_sqflow = false; - ret = libnvmf_add_ctrl(h, c, cfg); + ret = libnvmf_add_ctrl(h, c); if (!ret) { *cp = c; return 0; @@ -1958,17 +2022,16 @@ static int setup_connection(struct libnvmf_context *fctx, struct libnvme_host *h } -static int set_discovery_kato(struct libnvmf_context *fctx, - struct libnvme_fabrics_config *cfg) +static int set_discovery_kato(struct libnvmf_context *fctx) { - int tmo = cfg->keep_alive_tmo; + int tmo = fctx->cfg.keep_alive_tmo; /* Set kato to NVMF_DEF_DISC_TMO for persistent controllers */ - if (fctx->persistent && !cfg->keep_alive_tmo) - cfg->keep_alive_tmo = fctx->default_keep_alive_timeout; + if (fctx->persistent && !fctx->cfg.keep_alive_tmo) + fctx->cfg.keep_alive_tmo = fctx->default_keep_alive_timeout; /* Set kato to zero for non-persistent controllers */ - else if (!fctx->persistent && (cfg->keep_alive_tmo > 0)) - cfg->keep_alive_tmo = 0; + else if (!fctx->persistent && (fctx->cfg.keep_alive_tmo > 0)) + fctx->cfg.keep_alive_tmo = 0; return tmo; } @@ -1982,7 +2045,7 @@ static void nvme_parse_tls_args(const char *keyring, const char *tls_key, long id = strtol(keyring, &endptr, 0); if (endptr != keyring) - cfg->keyring = id; + cfg->keyring_id = id; else libnvme_ctrl_set_keyring(c, keyring); } @@ -1995,7 +2058,7 @@ static void nvme_parse_tls_args(const char *keyring, const char *tls_key, long id = strtol(tls_key, &endptr, 0); if (endptr != tls_key) - cfg->tls_key = id; + cfg->tls_key_id = id; else libnvme_ctrl_set_tls_key(c, tls_key); } @@ -2038,7 +2101,7 @@ static int _nvmf_discovery(struct libnvme_global_ctx *ctx, bool discover = false; bool disconnect; libnvme_ctrl_t child = { 0 }; - int tmo = fctx->cfg->keep_alive_tmo; + int tmo = fctx->cfg.keep_alive_tmo; struct libnvmf_context nfctx = *fctx; nfctx.subsysnqn = e->subnqn; @@ -2084,23 +2147,22 @@ static int _nvmf_discovery(struct libnvme_global_ctx *ctx, disconnect = false; } - set_discovery_kato(&nfctx, fctx->cfg); + set_discovery_kato(&nfctx); } else { /* NVME_NQN_NVME */ disconnect = false; } - err = nvmf_connect_disc_entry(h, e, &nfctx, nfctx.cfg, - &discover, &child); + err = nvmf_connect_disc_entry(h, e, &nfctx, &discover, &child); - nfctx.cfg->keep_alive_tmo = tmo; + nfctx.cfg.keep_alive_tmo = tmo; if (!child) { if (discover) _nvmf_discovery(ctx, &nfctx, true, child); if (child && disconnect) { - libnvme_disconnect_ctrl(child); + libnvmf_disconnect_ctrl(child); libnvme_free_ctrl(child); } } else if (err == -ENVME_CONNECT_ALREADY) { @@ -2143,13 +2205,12 @@ static bool is_persistent_discovery_ctrl(libnvme_host_t h, libnvme_ctrl_t c) } static int libnvme_add_ctrl(struct libnvmf_context *fctx, - struct libnvme_host *h, struct libnvme_ctrl *c, - struct libnvme_fabrics_config *cfg) + struct libnvme_host *h, struct libnvme_ctrl *c) { int err; retry: - err = libnvmf_add_ctrl(h, c, cfg); + err = libnvmf_add_ctrl(h, c); if (!err) return 0; if (fctx->decide_retry(fctx, err, fctx->user_data)) @@ -2160,7 +2221,7 @@ static int libnvme_add_ctrl(struct libnvmf_context *fctx, static int __create_discovery_ctrl(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx, libnvme_host_t h, - struct libnvme_fabrics_config *cfg, struct libnvme_ctrl **ctrl) + struct libnvme_ctrl **ctrl) { libnvme_ctrl_t c; int tmo, ret; @@ -2172,7 +2233,7 @@ static int __create_discovery_ctrl(struct libnvme_global_ctx *ctx, libnvme_ctrl_set_discovery_ctrl(c, true); libnvme_ctrl_set_unique_discovery_ctrl(c, strcmp(fctx->subsysnqn, NVME_DISC_SUBSYS_NAME)); - tmo = set_discovery_kato(fctx, cfg); + tmo = set_discovery_kato(fctx); if (libnvme_ctrl_get_unique_discovery_ctrl(c) && fctx->hostkey) { libnvme_ctrl_set_dhchap_host_key(c, fctx->hostkey); @@ -2180,8 +2241,8 @@ static int __create_discovery_ctrl(struct libnvme_global_ctx *ctx, libnvme_ctrl_set_dhchap_ctrl_key(c, fctx->ctrlkey); } - ret = libnvme_add_ctrl(fctx, h, c, cfg); - cfg->keep_alive_tmo = tmo; + ret = libnvme_add_ctrl(fctx, h, c); + fctx->cfg.keep_alive_tmo = tmo; if (ret) { libnvme_free_ctrl(c); return ret; @@ -2193,14 +2254,13 @@ static int __create_discovery_ctrl(struct libnvme_global_ctx *ctx, static int nvmf_create_discovery_ctrl(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx, libnvme_host_t h, - struct libnvme_fabrics_config *cfg, struct libnvme_ctrl **ctrl) { __cleanup_free struct nvme_id_ctrl *id = NULL; struct libnvme_ctrl *c; int ret; - ret = __create_discovery_ctrl(ctx, fctx, h, cfg, &c); + ret = __create_discovery_ctrl(ctx, fctx, h, &c); if (ret) return ret; @@ -2227,7 +2287,7 @@ static int nvmf_create_discovery_ctrl(struct libnvme_global_ctx *ctx, libnvme_msg(ctx, LIBNVME_LOG_ERR, "failed to identify controller, error %s\n", libnvme_strerror(-ret)); - libnvme_disconnect_ctrl(c); + libnvmf_disconnect_ctrl(c); libnvme_free_ctrl(c); return ret; } @@ -2241,11 +2301,11 @@ static int nvmf_create_discovery_ctrl(struct libnvme_global_ctx *ctx, * The subsysnqn is not the well-known name. Prefer the unique * subsysnqn over the well-known one. */ - libnvme_disconnect_ctrl(c); + libnvmf_disconnect_ctrl(c); libnvme_free_ctrl(c); fctx->subsysnqn = id->subnqn; - ret = __create_discovery_ctrl(ctx, fctx, h, cfg, &c); + ret = __create_discovery_ctrl(ctx, fctx, h, &c); if (ret) return ret; @@ -2258,7 +2318,6 @@ int _discovery_config_json(struct libnvme_global_ctx *ctx, bool connect, bool force) { struct libnvmf_context nfctx = *fctx; - struct libnvme_fabrics_config cfg; libnvme_ctrl_t cn; int ret = 0; @@ -2308,8 +2367,6 @@ int _discovery_config_json(struct libnvme_global_ctx *ctx, if (libnvme_ctrl_get_persistent(c)) nfctx.persistent = true; - memcpy(&cfg, fctx->cfg, sizeof(cfg)); - if (!force) { cn = lookup_ctrl(h, &nfctx); if (cn) { @@ -2319,13 +2376,13 @@ int _discovery_config_json(struct libnvme_global_ctx *ctx, } } - ret = nvmf_create_discovery_ctrl(ctx, &nfctx, h, &cfg, &cn); + ret = nvmf_create_discovery_ctrl(ctx, &nfctx, h, &cn); if (ret) return 0; _nvmf_discovery(ctx, &nfctx, connect, cn); if (!(fctx->persistent || is_persistent_discovery_ctrl(h, cn))) - ret = libnvme_disconnect_ctrl(cn); + ret = libnvmf_disconnect_ctrl(cn); libnvme_free_ctrl(cn); return ret; @@ -2472,15 +2529,14 @@ __public int libnvmf_discovery_config_file(struct libnvme_global_ctx *ctx, } } - err = nvmf_create_discovery_ctrl(ctx, &nfctx, h, fctx->cfg, - &c); + err = nvmf_create_discovery_ctrl(ctx, &nfctx, h, &c); if (err) continue; _nvmf_discovery(ctx, &nfctx, connect, c); if (!(nfctx.persistent || is_persistent_discovery_ctrl(h, c))) - err = libnvme_disconnect_ctrl(c); + err = libnvmf_disconnect_ctrl(c); libnvme_free_ctrl(c); } while (!err); @@ -2532,9 +2588,9 @@ __public int libnvmf_config_modify(struct libnvme_global_ctx *ctx, libnvme_ctrl_set_dhchap_ctrl_key(c, fctx->ctrlkey); nvme_parse_tls_args(fctx->keyring, fctx->tls_key, - fctx->tls_key_identity, fctx->cfg, c); + fctx->tls_key_identity, &fctx->cfg, c); - libnvmf_update_config(c, fctx->cfg); + update_config(c, &fctx->cfg); return 0; } @@ -2626,8 +2682,7 @@ static bool validate_uri(struct libnvme_global_ctx *ctx, static int nbft_connect(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx, struct libnvme_host *h, struct nvmf_disc_log_entry *e, - struct nbft_info_subsystem_ns *ss, - struct libnvme_fabrics_config *cfg) + struct nbft_info_subsystem_ns *ss) { libnvme_ctrl_t c; int saved_log_level; @@ -2653,7 +2708,7 @@ static int nbft_connect(struct libnvme_global_ctx *ctx, /* Update tls or concat */ nvmf_update_tls_concat(e, c, h); - ret = libnvmf_add_ctrl(h, c, cfg); + ret = libnvmf_add_ctrl(h, c); /* Resume logging */ if (ss && ss->unavailable && saved_log_level < 1) @@ -2685,8 +2740,7 @@ static int nbft_connect(struct libnvme_global_ctx *ctx, static int nbft_discovery(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx, struct nbft_info_discovery *dd, - struct libnvme_host *h, struct libnvme_ctrl *c, - struct libnvme_fabrics_config *defcfg) + struct libnvme_host *h, struct libnvme_ctrl *c) { struct nvmf_discovery_log *log = NULL; int ret; @@ -2709,7 +2763,7 @@ static int nbft_discovery(struct libnvme_global_ctx *ctx, struct nvmf_disc_log_entry *e = &log->entries[i]; struct libnvmf_context nfctx = *fctx; libnvme_ctrl_t cl; - int tmo = defcfg->keep_alive_tmo; + int tmo = fctx->cfg.keep_alive_tmo; nfctx.subsysnqn = e->subnqn; nfctx.transport = libnvmf_trtype_str(e->trtype); @@ -2733,15 +2787,14 @@ static int nbft_discovery(struct libnvme_global_ctx *ctx, libnvme_ctrl_t child; ret = nvmf_connect_disc_entry(h, e, &nfctx, - defcfg, NULL, &child); + NULL, &child); if (ret) continue; - nbft_discovery(ctx, &nfctx, dd, h, child, defcfg); - libnvme_disconnect_ctrl(child); + nbft_discovery(ctx, &nfctx, dd, h, child); + libnvmf_disconnect_ctrl(child); libnvme_free_ctrl(child); } else { - ret = nbft_connect(ctx, &nfctx, h, e, NULL, - defcfg); + ret = nbft_connect(ctx, &nfctx, h, e, NULL); /* * With TCP/DHCP, it can happen that the OS @@ -2754,8 +2807,7 @@ static int nbft_discovery(struct libnvme_global_ctx *ctx, const char *htradr = nfctx.host_traddr; nfctx.host_traddr = NULL; - ret = nbft_connect(ctx, &nfctx, h, e, NULL, - defcfg); + ret = nbft_connect(ctx, &nfctx, h, e, NULL); if (ret == 0) libnvme_msg(ctx, LIBNVME_LOG_INFO, @@ -2772,7 +2824,7 @@ static int nbft_discovery(struct libnvme_global_ctx *ctx, break; } - defcfg->keep_alive_tmo = tmo; + fctx->cfg.keep_alive_tmo = tmo; } free(log); @@ -2866,8 +2918,7 @@ __public int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, nfctx.trsvcid = (*ss)->trsvcid; nfctx.host_iface = NULL; - rr = nbft_connect(ctx, &nfctx, h, NULL, - *ss, fctx->cfg); + rr = nbft_connect(ctx, &nfctx, h, NULL, *ss); /* * With TCP/DHCP, it can happen that the OS @@ -2880,7 +2931,7 @@ __public int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, nfctx.host_traddr = NULL; rr = nbft_connect(ctx, &nfctx, h, NULL, - *ss, fctx->cfg); + *ss); if (rr == 0) libnvme_msg(ctx, LIBNVME_LOG_INFO, @@ -2962,13 +3013,13 @@ __public int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, if (!c) { ret = nvmf_create_discovery_ctrl(ctx, &nfctx, - h, fctx->cfg, &c); + h, &c); if (ret == -ENVME_CONNECT_ADDRNOTAVAIL && !strcmp(nfctx.transport, "tcp") && strlen(hfi->tcp_info.dhcp_server_ipaddr) > 0) { nfctx.traddr = NULL; ret = nvmf_create_discovery_ctrl(ctx, - &nfctx, h, fctx->cfg, &c); + &nfctx, h, &c); } } else ret = 0; @@ -2980,9 +3031,9 @@ __public int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, goto out_free; } - rr = nbft_discovery(ctx, &nfctx, *dd, h, c, fctx->cfg); + rr = nbft_discovery(ctx, &nfctx, *dd, h, c); if (!persistent) - libnvme_disconnect_ctrl(c); + libnvmf_disconnect_ctrl(c); libnvme_free_ctrl(c); if (rr == -ENOMEM) { ret = rr; @@ -3072,7 +3123,7 @@ __public int libnvmf_discovery(struct libnvme_global_ctx *ctx, struct libnvmf_co } if (!c) { /* No device or non-matching device, create a new controller */ - ret = nvmf_create_discovery_ctrl(ctx, fctx, h, fctx->cfg, &c); + ret = nvmf_create_discovery_ctrl(ctx, fctx, h, &c); if (ret) { if (ret != -ENVME_CONNECT_IGNORED) libnvme_msg(ctx, LIBNVME_LOG_ERR, @@ -3084,7 +3135,7 @@ __public int libnvmf_discovery(struct libnvme_global_ctx *ctx, struct libnvmf_co ret = _nvmf_discovery(ctx, fctx, connect, c); if (!(fctx->persistent || is_persistent_discovery_ctrl(h, c))) - libnvme_disconnect_ctrl(c); + libnvmf_disconnect_ctrl(c); libnvme_free_ctrl(c); return ret; @@ -3105,7 +3156,7 @@ __public int libnvmf_connect(struct libnvme_global_ctx *ctx, struct libnvmf_cont return err; c = lookup_ctrl(h, fctx); - if (c && libnvme_ctrl_get_name(c) && !fctx->cfg->duplicate_connect) { + if (c && libnvme_ctrl_get_name(c) && !fctx->cfg.duplicate_connect) { fctx->already_connected(fctx, h, libnvme_ctrl_get_subsysnqn(c), libnvme_ctrl_get_transport(c), libnvme_ctrl_get_traddr(c), libnvme_ctrl_get_trsvcid(c), fctx->user_data); @@ -3123,7 +3174,7 @@ __public int libnvmf_connect(struct libnvme_global_ctx *ctx, struct libnvmf_cont } nvme_parse_tls_args(fctx->keyring, fctx->tls_key, - fctx->tls_key_identity, fctx->cfg, c); + fctx->tls_key_identity, &fctx->cfg, c); /* * We are connecting to a discovery controller, so let's treat @@ -3132,10 +3183,10 @@ __public int libnvmf_connect(struct libnvme_global_ctx *ctx, struct libnvmf_cont if (!strcmp(fctx->subsysnqn, NVME_DISC_SUBSYS_NAME)) { fctx->persistent = true; - set_discovery_kato(fctx, fctx->cfg); + set_discovery_kato(fctx); } - err = libnvme_add_ctrl(fctx, h, c, fctx->cfg); + err = libnvme_add_ctrl(fctx, h, c); if (err) { libnvme_msg(ctx, LIBNVME_LOG_ERR, "could not add new controller: %s\n", libnvme_strerror(-err)); diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index 302e0a971e..95a9749f9b 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -23,48 +23,13 @@ /* default to 600 seconds of reconnect attempts before giving up */ #define NVMF_DEF_CTRL_LOSS_TMO 600 -/** - * struct libnvme_fabrics_config - Defines all linux nvme fabrics initiator options - * @queue_size: Number of IO queue entries - * @nr_io_queues: Number of controller IO queues to establish - * @reconnect_delay: Time between two consecutive reconnect attempts. - * @ctrl_loss_tmo: Override the default controller reconnect attempt timeout in seconds - * @fast_io_fail_tmo: Set the fast I/O fail timeout in seconds. - * @keep_alive_tmo: Override the default keep-alive-timeout to this value in seconds - * @nr_write_queues: Number of queues to use for exclusively for writing - * @nr_poll_queues: Number of queues to reserve for polling completions - * @tos: Type of service - * @keyring: Keyring to store and lookup keys - * @tls_key: TLS PSK for the connection - * @tls_configured_key: TLS PSK for connect command for the connection - * @duplicate_connect: Allow multiple connections to the same target - * @disable_sqflow: Disable controller sq flow control - * @hdr_digest: Generate/verify header digest (TCP) - * @data_digest: Generate/verify data digest (TCP) - * @tls: Start TLS on the connection (TCP) - * @concat: Enable secure concatenation (TCP) - */ -struct libnvme_fabrics_config { - int queue_size; - int nr_io_queues; - int reconnect_delay; - int ctrl_loss_tmo; - int fast_io_fail_tmo; - int keep_alive_tmo; - int nr_write_queues; - int nr_poll_queues; - int tos; - long keyring; - long tls_key; - long tls_configured_key; - - bool duplicate_connect; - bool disable_sqflow; - bool hdr_digest; - bool data_digest; - bool tls; - bool concat; -}; +/* + * struct libnvmf_context - Opaque context for fabrics operations + * + * Used to manage state and configuration for fabrics discovery and connect + * operations. + */ +struct libnvmf_context; /** * struct libnvme_fabrics_uri - Parsed URI structure @@ -187,30 +152,10 @@ const char *libnvmf_qptype_str(__u8 qptype); */ const char *libnvmf_cms_str(__u8 cms); -/** - * libnvmf_default_config() - Default values for fabrics configuration - * @cfg: config values to set - * - * Initializes @cfg with default values. - */ -void libnvmf_default_config(struct libnvme_fabrics_config *cfg); - -/** - * libnvmf_update_config() - Update fabrics configuration values - * @c: Controller to be modified - * @cfg: Updated configuration values - * - * Updates the values from @c with the configuration values from @cfg; - * all non-default values from @cfg will overwrite the values in @c. - */ -void libnvmf_update_config(libnvme_ctrl_t c, - const struct libnvme_fabrics_config *cfg); - /** * libnvmf_add_ctrl() - Connect a controller and update topology * @h: Host to which the controller should be attached * @c: Controller to be connected - * @cfg: Default configuration for the controller * * Issues a 'connect' command to the NVMe-oF controller and inserts @c * into the topology using @h as parent. @@ -218,8 +163,7 @@ void libnvmf_update_config(libnvme_ctrl_t c, * * Return: 0 on success, or an error code on failure. */ -int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, - const struct libnvme_fabrics_config *cfg); +int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c); /** * libnvmf_connect_ctrl() - Connect a controller @@ -339,13 +283,6 @@ void libnvmf_free_uri(struct libnvme_fabrics_uri *uri); */ const char *libnvmf_get_default_trsvcid(const char *transport, bool discovery_ctrl); -/* - * struct libnvmf_context - Opaque context for fabrics operations - * - * Used to manage state and configuration for fabrics discovery and connect - * operations. - */ -struct libnvmf_context; /** * libnvmf_context_create() - Create a new fabrics context for discovery/connect @@ -419,18 +356,6 @@ int libnvmf_context_set_discovery_cbs(struct libnvmf_context *fctx, int libnvmf_context_set_discovery_defaults(struct libnvmf_context *fctx, int max_discovery_retries, int keep_alive_timeout); -/** - * libnvmf_context_set_fabrics_config() - Set fabrics configuration for context - * @fctx: Fabrics context - * @cfg: Fabrics configuration to apply - * - * Applies the given fabrics configuration to the context. - * - * Return: 0 on success, or a negative error code on failure. - */ -int libnvmf_context_set_fabrics_config(struct libnvmf_context *fctx, - struct libnvme_fabrics_config *cfg); - /** * libnvmf_context_set_connection() - Set connection parameters for context * @fctx: Fabrics context @@ -504,6 +429,25 @@ int libnvmf_context_set_persistent(struct libnvmf_context *fctx, bool persistent */ int libnvmf_context_set_device(struct libnvmf_context *fctx, const char *device); +/** + * libnvmf_context_get_fabrics_config() - Fabrics configuration of a fabrics + * context + * @fctx: Fabrics context + * + * Return: Fabrics configuration of @fctx + */ +struct libnvme_fabrics_config *libnvmf_context_get_fabrics_config( + struct libnvmf_context *fctx); + +/** + * libnvmf_ctrl_get_fabrics_config() - Fabrics configuration of a controller + * @c: Controller instance + * + * Return: Fabrics configuration of @c + */ +struct libnvme_fabrics_config *libnvmf_ctrl_get_fabrics_config( + libnvme_ctrl_t c); + /** * libnvmf_discovery() - Perform fabrics discovery * @ctx: Global context @@ -560,6 +504,19 @@ int libnvmf_discovery_config_file(struct libnvme_global_ctx *ctx, int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx, bool connect, char *nbft_path); +/** + * libnvmf_create_ctrl() - Allocate an unconnected NVMe controller + * @ctx: struct libnvme_global_ctx object + * @fctx: Fabrics context + * @c: @libnvme_ctrl_t object to return + * + * Creates an unconnected controller to be used for libnvme_add_ctrl(). + * + * Return: 0 on success or negative error code otherwise + */ +int libnvmf_create_ctrl(struct libnvme_global_ctx *ctx, + struct libnvmf_context *fctx, libnvme_ctrl_t *c); + /** * libnvmf_connect() - Connect to fabrics subsystem * @ctx: Global context @@ -569,7 +526,18 @@ int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, * * Return: 0 on success, or a negative error code on failure. */ -int libnvmf_connect(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx); +int libnvmf_connect(struct libnvme_global_ctx *ctx, + struct libnvmf_context *fctx); + +/** + * libnvmf_disconnect_ctrl() - Disconnect a controller + * @c: Controller instance + * + * Issues a 'disconnect' fabrics command to @c + * + * Return: 0 on success, -1 on failure. + */ +int libnvmf_disconnect_ctrl(libnvme_ctrl_t c); /** * libnvmf_connect_config_json() - Connect using JSON config diff --git a/libnvme/src/nvme/json.c b/libnvme/src/nvme/json.c index 416476c75c..6d761ca7b1 100644 --- a/libnvme/src/nvme/json.c +++ b/libnvme/src/nvme/json.c @@ -16,6 +16,7 @@ #include "cleanup.h" #include "private.h" +#include "private-fabrics.h" #define JSON_UPDATE_INT_OPTION(c, k, a, o) \ if (!strcmp(# a, k ) && !c->a) c->a = json_object_get_int(o); @@ -25,7 +26,7 @@ static void json_update_attributes(libnvme_ctrl_t c, struct json_object *ctrl_obj) { - struct libnvme_fabrics_config *cfg = libnvme_ctrl_get_config(c); + struct libnvme_fabrics_config *cfg = libnvmf_ctrl_get_fabrics_config(c); json_object_object_foreach(ctrl_obj, key_str, val_obj) { JSON_UPDATE_INT_OPTION(cfg, key_str, @@ -274,7 +275,7 @@ int json_read_config(struct libnvme_global_ctx *ctx, const char *config_file) static void json_update_port(struct json_object *ctrl_array, libnvme_ctrl_t c) { - struct libnvme_fabrics_config *cfg = libnvme_ctrl_get_config(c); + struct libnvme_fabrics_config *cfg = libnvmf_ctrl_get_fabrics_config(c); struct json_object *port_obj = json_object_new_object(); const char *transport, *value; @@ -442,7 +443,7 @@ int json_update_config(struct libnvme_global_ctx *ctx, int fd) static void json_dump_ctrl(struct json_object *ctrl_array, libnvme_ctrl_t c) { - struct libnvme_fabrics_config *cfg = libnvme_ctrl_get_config(c); + struct libnvme_fabrics_config *cfg = libnvmf_ctrl_get_fabrics_config(c); struct json_object *ctrl_obj = json_object_new_object(); const char *name, *transport, *value; diff --git a/libnvme/src/nvme/linux.c b/libnvme/src/nvme/linux.c index 7fbccb4c04..1918f87035 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -1388,7 +1388,7 @@ int __libnvme_import_keys_from_config(libnvme_host_t h, libnvme_ctrl_t c, if (ret) return ret; } else - kr_id = c->cfg.keyring; + kr_id = c->cfg.keyring_id; /* * Fallback to the default keyring. Note this will also add the diff --git a/libnvme/src/nvme/no-fabrics.c b/libnvme/src/nvme/no-fabrics.c new file mode 100644 index 0000000000..0498a9b536 --- /dev/null +++ b/libnvme/src/nvme/no-fabrics.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * This file is part of libnvme. + * Copyright (c) 2026 SUSE Software Solutions + * + * Authors: Daniel Wagner + */ + +#include "private-fabrics.h" + +bool traddr_is_hostname(struct libnvme_global_ctx *ctx, + const char *transport, const char *traddr) +{ + return false; +} + +void libnvmf_default_config(struct libnvme_fabrics_config *cfg) +{ +} diff --git a/libnvme/src/nvme/private-fabrics.h b/libnvme/src/nvme/private-fabrics.h index 891e0be658..5279399707 100644 --- a/libnvme/src/nvme/private-fabrics.h +++ b/libnvme/src/nvme/private-fabrics.h @@ -7,8 +7,68 @@ */ #pragma once +#include #include +#include "nvme/private.h" + +struct libnvmf_context { + struct libnvme_global_ctx *ctx; + + /* common callbacks */ + bool (*decide_retry)(struct libnvmf_context *fctx, int err, + void *user_data); + void (*connected)(struct libnvmf_context *fctx, struct libnvme_ctrl *c, + void *user_data); + void (*already_connected)(struct libnvmf_context *fctx, + struct libnvme_host *host, const char *subsysnqn, + const char *transport, const char *traddr, + const char *trsvcid, void *user_data); + + /* discovery callbacks */ + void (*discovery_log)(struct libnvmf_context *fctx, + bool connect, + struct nvmf_discovery_log *log, + uint64_t numrec, void *user_data); + int (*parser_init)(struct libnvmf_context *fctx, + void *user_data); + void (*parser_cleanup)(struct libnvmf_context *fctx, + void *user_data); + int (*parser_next_line)(struct libnvmf_context *fctx, + void *user_data); + + /* discovery defaults */ + int default_max_discovery_retries; + int default_keep_alive_timeout; + + /* common fabrics configuration */ + const char *device; + bool persistent; + struct libnvme_fabrics_config cfg; + + /* connection configuration */ + const char *subsysnqn; + const char *transport; + const char *traddr; + const char *trsvcid; + const char *host_traddr; + const char *host_iface; + + /* host configuration */ + const char *hostnqn; + const char *hostid; + + /* authentication and transport encryption configuration */ + const char *hostkey; + const char *ctrlkey; + const char *keyring; + char *tls_key; + const char *tls_key_identity; + + void *user_data; +}; + + /** * NVMe-oF private struct definitions. * @@ -22,3 +82,8 @@ struct libnvmf_discovery_args { /*!generate-accessors*/ int max_retries; __u8 lsp; }; + +bool traddr_is_hostname(struct libnvme_global_ctx *ctx, + const char *transport, const char *traddr); + +void libnvmf_default_config(struct libnvme_fabrics_config *cfg); diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index e39e90b455..a1c879f349 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -12,7 +12,8 @@ #include -#include +#include "nvme/nvme-types.h" +#include "nvme/lib-types.h" const char *libnvme_subsys_sysfs_dir(void); const char *libnvme_ctrl_sysfs_dir(void); @@ -80,6 +81,49 @@ struct linux_passthru_cmd64 { #define LIBNVME_URING_CMD_ADMIN _IOWR('N', 0x82, struct libnvme_uring_cmd) #define LIBNVME_URING_CMD_ADMIN_VEC _IOWR('N', 0x83, struct libnvme_uring_cmd) +/** + * struct libnvme_fabrics_config - Defines all linux nvme fabrics initiator options + * @queue_size: Number of IO queue entries + * @nr_io_queues: Number of controller IO queues to establish + * @reconnect_delay: Time between two consecutive reconnect attempts. + * @ctrl_loss_tmo: Override the default controller reconnect attempt timeout in seconds + * @fast_io_fail_tmo: Set the fast I/O fail timeout in seconds. + * @keep_alive_tmo: Override the default keep-alive-timeout to this value in seconds + * @nr_write_queues: Number of queues to use for exclusively for writing + * @nr_poll_queues: Number of queues to reserve for polling completions + * @tos: Type of service + * @keyring_id: Keyring to store and lookup keys + * @tls_key_id: TLS PSK for the connection + * @tls_configured_key_id: TLS PSK for connect command for the connection + * @duplicate_connect: Allow multiple connections to the same target + * @disable_sqflow: Disable controller sq flow control + * @hdr_digest: Generate/verify header digest (TCP) + * @data_digest: Generate/verify data digest (TCP) + * @tls: Start TLS on the connection (TCP) + * @concat: Enable secure concatenation (TCP) + */ +struct libnvme_fabrics_config { //!generate-accessors + int queue_size; + int nr_io_queues; + int reconnect_delay; + int ctrl_loss_tmo; + int fast_io_fail_tmo; + int keep_alive_tmo; + int nr_write_queues; + int nr_poll_queues; + int tos; + long keyring_id; + long tls_key_id; + long tls_configured_key_id; + + bool duplicate_connect; + bool disable_sqflow; + bool hdr_digest; + bool data_digest; + bool tls; + bool concat; +}; + struct libnvme_log { int fd; int level; @@ -302,63 +346,6 @@ struct libnvme_global_ctx { struct io_uring *ring; #endif }; - -struct libnvmf_context { - struct libnvme_global_ctx *ctx; - - /* common callbacks */ - bool (*decide_retry)(struct libnvmf_context *fctx, int err, - void *user_data); - void (*connected)(struct libnvmf_context *fctx, struct libnvme_ctrl *c, - void *user_data); - void (*already_connected)(struct libnvmf_context *fctx, - struct libnvme_host *host, const char *subsysnqn, - const char *transport, const char *traddr, - const char *trsvcid, void *user_data); - - /* discovery callbacks */ - void (*discovery_log)(struct libnvmf_context *fctx, - bool connect, - struct nvmf_discovery_log *log, - uint64_t numrec, void *user_data); - int (*parser_init)(struct libnvmf_context *fctx, - void *user_data); - void (*parser_cleanup)(struct libnvmf_context *fctx, - void *user_data); - int (*parser_next_line)(struct libnvmf_context *fctx, - void *user_data); - - /* discovery defaults */ - int default_max_discovery_retries; - int default_keep_alive_timeout; - - /* common fabrics configuraiton */ - const char *device; - bool persistent; - struct libnvme_fabrics_config *cfg; - - /* connection configuration */ - const char *subsysnqn; - const char *transport; - const char *traddr; - const char *trsvcid; - const char *host_traddr; - const char *host_iface; - - /* host configuration */ - const char *hostnqn; - const char *hostid; - - /* authentication and transport encryption configuration */ - const char *hostkey; - const char *ctrlkey; - const char *keyring; - char *tls_key; - const char *tls_key_identity; - - void *user_data; -}; - int libnvme_set_attr(const char *dir, const char *attr, const char *value); int json_read_config(struct libnvme_global_ctx *ctx, const char *config_file); @@ -379,9 +366,11 @@ struct libnvme_transport_handle *__libnvme_open(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *__libnvme_create_transport_handle( struct libnvme_global_ctx *ctx); +struct libnvmf_context; + int _libnvme_create_ctrl(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx, - libnvme_ctrl_t *cp); + struct libnvme_ctrl **cp); bool _libnvme_ctrl_match_config(struct libnvme_ctrl *c, struct libnvmf_context *fctx); @@ -389,16 +378,18 @@ void *__libnvme_alloc(size_t len); void *__libnvme_realloc(void *p, size_t len); -libnvme_host_t libnvme_lookup_host(struct libnvme_global_ctx *ctx, +void nvme_deconfigure_ctrl(struct libnvme_ctrl *c); + +struct libnvme_host *libnvme_lookup_host(struct libnvme_global_ctx *ctx, const char *hostnqn, const char *hostid); -libnvme_subsystem_t libnvme_lookup_subsystem(struct libnvme_host *h, +struct libnvme_subsystem *libnvme_lookup_subsystem(struct libnvme_host *h, const char *name, const char *subsysnqn); -libnvme_ctrl_t libnvme_lookup_ctrl(libnvme_subsystem_t s, - struct libnvmf_context *fctx, libnvme_ctrl_t p); -libnvme_ctrl_t libnvme_ctrl_find(libnvme_subsystem_t s, +struct libnvme_ctrl * libnvme_lookup_ctrl(struct libnvme_subsystem * s, + struct libnvmf_context *fctx, struct libnvme_ctrl *p); +struct libnvme_ctrl * libnvme_ctrl_find(struct libnvme_subsystem *s, struct libnvmf_context *fctx); -void __libnvme_free_host(libnvme_host_t h); +void __libnvme_free_host(struct libnvme_host * h); #if (LOG_FUNCNAME == 1) #define __libnvme_log_func __func__ @@ -416,8 +407,8 @@ __libnvme_msg(struct libnvme_global_ctx *ctx, int level, #define SECTOR_SIZE 512 #define SECTOR_SHIFT 9 -int __libnvme_import_keys_from_config(libnvme_host_t h, libnvme_ctrl_t c, - long *keyring_id, long *key_id); +int __libnvme_import_keys_from_config(struct libnvme_host *h, + struct libnvme_ctrl *c, long *keyring_id, long *key_id); static inline char *xstrdup(const char *s) { @@ -607,7 +598,7 @@ static inline __u16 nvmf_exat_size(size_t val_len) * * Return: On success 0, else error code. */ -int libnvme_ns_get_transport_handle(libnvme_ns_t n, +int libnvme_ns_get_transport_handle(struct libnvme_ns *n, struct libnvme_transport_handle **hdl); /** @@ -615,7 +606,7 @@ int libnvme_ns_get_transport_handle(libnvme_ns_t n, * @n: Namespace instance * */ -void libnvme_ns_release_transport_handle(libnvme_ns_t n); +void libnvme_ns_release_transport_handle(struct libnvme_ns *n); /** * libnvme_mi_admin_admin_passthru() - Submit an nvme admin passthrough command diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index c7e9e6a883..42d025fcd1 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -34,6 +34,7 @@ #include "cleanup.h" #include "cleanup-linux.h" #include "private.h" +#include "private-fabrics.h" #include "util.h" #include "compiler-attributes.h" @@ -953,12 +954,6 @@ __public const char *libnvme_ctrl_get_state(libnvme_ctrl_t c) return c->state; } -__public struct libnvme_fabrics_config *libnvme_ctrl_get_config( - libnvme_ctrl_t c) -{ - return &c->cfg; -} - __public int libnvme_ctrl_identify(libnvme_ctrl_t c, struct nvme_id_ctrl *id) { struct libnvme_transport_handle *hdl = @@ -1016,24 +1011,6 @@ void nvme_deconfigure_ctrl(libnvme_ctrl_t c) FREE_CTRL_ATTR(c->phy_slot); } -__public int libnvme_disconnect_ctrl(libnvme_ctrl_t c) -{ - struct libnvme_global_ctx *ctx = c->s && c->s->h ? c->s->h->ctx : NULL; - int ret; - - ret = libnvme_set_attr(libnvme_ctrl_get_sysfs_dir(c), - "delete_controller", "1"); - if (ret < 0) { - libnvme_msg(ctx, LIBNVME_LOG_ERR, - "%s: failed to disconnect, error %d\n", c->name, errno); - return ret; - } - libnvme_msg(ctx, LIBNVME_LOG_INFO, "%s: %s disconnected\n", - c->name, c->subsysnqn); - nvme_deconfigure_ctrl(c); - return 0; -} - __public void libnvme_unlink_ctrl(libnvme_ctrl_t c) { list_del_init(&c->entry); @@ -1069,33 +1046,6 @@ __public void libnvme_free_ctrl(libnvme_ctrl_t c) __libnvme_free_ctrl(c); } -static bool traddr_is_hostname(const char *transport, const char *traddr) -{ - - if (!traddr || !transport) - return false; - if (!strcmp(traddr, "none")) - return false; -#ifdef CONFIG_FABRICS - char addrstr[NVMF_TRADDR_SIZE]; - - if (strcmp(transport, "tcp") && - strcmp(transport, "rdma")) - return false; - if (inet_pton(AF_INET, traddr, addrstr) > 0 || - inet_pton(AF_INET6, traddr, addrstr) > 0) - return false; -#endif - return true; -} - -__public void libnvmf_default_config(struct libnvme_fabrics_config *cfg) -{ - memset(cfg, 0, sizeof(*cfg)); - cfg->tos = -1; - cfg->ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO; -} - int _libnvme_create_ctrl(struct libnvme_global_ctx *ctx, struct libnvmf_context *fctx, libnvme_ctrl_t *cp) { @@ -1122,7 +1072,7 @@ int _libnvme_create_ctrl(struct libnvme_global_ctx *ctx, c->ctx = ctx; c->hdl = NULL; - libnvmf_default_config(&c->cfg); + c->cfg = fctx->cfg; list_head_init(&c->namespaces); list_head_init(&c->paths); list_node_init(&c->entry); @@ -1131,7 +1081,7 @@ int _libnvme_create_ctrl(struct libnvme_global_ctx *ctx, if (fctx->traddr) c->traddr = strdup(fctx->traddr); if (fctx->host_traddr) { - if (traddr_is_hostname(fctx->transport, fctx->host_traddr)) + if (traddr_is_hostname(ctx, fctx->transport, fctx->host_traddr)) hostname2traddr(ctx, fctx->host_traddr, &c->host_traddr); if (!c->host_traddr) @@ -1146,24 +1096,6 @@ int _libnvme_create_ctrl(struct libnvme_global_ctx *ctx, return 0; } -__public int libnvme_create_ctrl(struct libnvme_global_ctx *ctx, - const char *subsysnqn, const char *transport, - const char *traddr, const char *host_traddr, - const char *host_iface, const char *trsvcid, - libnvme_ctrl_t *cp) -{ - struct libnvmf_context fctx = { - .transport = transport, - .traddr = traddr, - .host_traddr = host_traddr, - .host_iface = host_iface, - .trsvcid = trsvcid, - .subsysnqn = subsysnqn, - }; - - return _libnvme_create_ctrl(ctx, &fctx, cp); -} - #ifdef CONFIG_FABRICS /** * _tcp_ctrl_match_host_traddr_no_src_addr() - Match host_traddr w/o src_addr @@ -1576,6 +1508,7 @@ libnvme_ctrl_t libnvme_lookup_ctrl(libnvme_subsystem_t s, ctx = s->h ? s->h->ctx : NULL; /* Set the NQN to the subsystem the controller should be created in */ fctx->subsysnqn = s->subsysnqn; + libnvmf_default_config(&fctx->cfg); ret = _libnvme_create_ctrl(ctx, fctx, &c); /* And restore NQN to avoid issues with repetitive calls */ fctx->subsysnqn = subsysnqn; @@ -1763,7 +1696,7 @@ static void libnvme_read_sysfs_tls(struct libnvme_global_ctx *ctx, /* the sysfs entry is not prefixing the id but it's in hex */ key_id = strtol(key, &endptr, 16); if (endptr != key) - c->cfg.tls_key = key_id; + c->cfg.tls_key_id = key_id; free(key); @@ -1774,7 +1707,7 @@ static void libnvme_read_sysfs_tls(struct libnvme_global_ctx *ctx, /* the sysfs entry is not prefixing the id but it's in hex */ key_id = strtol(key, &endptr, 16); if (endptr != key) - c->cfg.tls_configured_key = key_id; + c->cfg.tls_configured_key_id = key_id; free(key); } diff --git a/libnvme/src/nvme/tree.h b/libnvme/src/nvme/tree.h index ecbb05d505..403ad43d58 100644 --- a/libnvme/src/nvme/tree.h +++ b/libnvme/src/nvme/tree.h @@ -304,28 +304,6 @@ bool libnvme_ctrl_match_config(struct libnvme_ctrl *c, const char *transport, const char *subsysnqn, const char *host_traddr, const char *host_iface); -/** - * libnvme_create_ctrl() - Allocate an unconnected NVMe controller - * @ctx: struct libnvme_global_ctx object - * @subsysnqn: Subsystem NQN - * @transport: Transport type - * @traddr: Transport address - * @host_traddr: Host transport address - * @host_iface: Host interface name - * @trsvcid: Transport service ID - * @c: @libnvme_ctrl_t object to return - * - * Creates an unconnected controller to be used for libnvme_add_ctrl(). - * - * Return: 0 on success or negative error code otherwise - */ -int libnvme_create_ctrl(struct libnvme_global_ctx *ctx, - const char *subsysnqn, const char *transport, - const char *traddr, const char *host_traddr, - const char *host_iface, const char *trsvcid, - libnvme_ctrl_t *c); - - /** * libnvme_subsystem_first_ns() - Start namespace iterator * @s: &libnvme_subsystem_t object @@ -758,14 +736,6 @@ libnvme_subsystem_t libnvme_ctrl_get_subsystem(libnvme_ctrl_t c); */ const char *libnvme_ns_head_get_sysfs_dir(libnvme_ns_head_t head); -/** - * libnvme_ctrl_get_config() - Fabrics configuration of a controller - * @c: Controller instance - * - * Return: Fabrics configuration of @c - */ -struct libnvme_fabrics_config *libnvme_ctrl_get_config(libnvme_ctrl_t c); - /** * libnvme_ctrl_identify() - Issues an 'identify controller' command * @c: Controller instance @@ -778,16 +748,6 @@ struct libnvme_fabrics_config *libnvme_ctrl_get_config(libnvme_ctrl_t c); */ int libnvme_ctrl_identify(libnvme_ctrl_t c, struct nvme_id_ctrl *id); -/** - * libnvme_disconnect_ctrl() - Disconnect a controller - * @c: Controller instance - * - * Issues a 'disconnect' fabrics command to @c - * - * Return: 0 on success, -1 on failure. - */ -int libnvme_disconnect_ctrl(libnvme_ctrl_t c); - /** * libnvme_scan_ctrl() - Scan on a controller * @ctx: struct libnvme_global_ctx object diff --git a/libnvme/test/tree.c b/libnvme/test/tree.c index 84778dc548..041c521f99 100644 --- a/libnvme/test/tree.c +++ b/libnvme/test/tree.c @@ -14,6 +14,7 @@ #include #include +#include struct test_data { /* input data */ diff --git a/libnvme/tools/generator/generate-accessors.md b/libnvme/tools/generator/generate-accessors.md index f11ccd9572..ee25f01c7c 100644 --- a/libnvme/tools/generator/generate-accessors.md +++ b/libnvme/tools/generator/generate-accessors.md @@ -29,22 +29,29 @@ Struct inclusion and member behaviour are controlled by **annotations written as ### Struct inclusion — `generate-accessors` -Place the annotation on the same line as the struct's opening brace to opt that struct in to code generation: +Place the annotation on the same line as the struct's opening brace to opt that struct in to code generation. An optional mode qualifier sets the **default behaviour for all members** of that struct: + +| Annotation | Default for all members | +| --------------------------------------- | --------------------------------- | +| `//!generate-accessors` | getter **and** setter (default) | +| `//!generate-accessors:none` | no accessors | +| `//!generate-accessors:readonly` | getter only | +| `//!generate-accessors:writeonly` | setter only | ```c -struct nvme_ctrl { /*!generate-accessors*/ +struct nvme_ctrl { /*!generate-accessors*/ /* both getter and setter */ ... }; -``` -```c -struct nvme_ctrl { //!generate-accessors +struct nvme_ctrl { //!generate-accessors:readonly /* getter only by default */ ... }; ``` Only structs carrying this annotation will have accessors generated. All other structs in the header are ignored. +Individual members can always override the struct-level default using a per-member annotation (see below). + ### Member exclusion — `accessors:none` Place the annotation on a member's declaration line to suppress accessor generation for that member entirely (no setter, no getter): @@ -59,7 +66,7 @@ struct nvme_ctrl { /*!generate-accessors*/ ### Read-only members — `accessors:readonly` -Place the annotation on a member's declaration line to generate only a getter (no setter). This has the same effect as declaring the member `const`, but without changing the type in the struct: +Place the annotation on a member's declaration line to generate only a getter (no setter). This has the same effect as declaring the member `const`, but without changing the type in the struct. Also useful to override a `generate-accessors:writeonly` struct default for individual members: ```c struct nvme_ctrl { /*!generate-accessors*/ @@ -71,17 +78,42 @@ struct nvme_ctrl { /*!generate-accessors*/ Members declared with the `const` qualifier are also automatically read-only. +### Write-only members — `accessors:writeonly` + +Place the annotation on a member's declaration line to generate only a setter (no getter). Useful to override a `generate-accessors:readonly` struct default for individual members: + +```c +struct nvme_ctrl { /*!generate-accessors:readonly*/ + char *name; /* getter only (struct default) */ + char *token; //!accessors:writeonly /* setter only override */ +}; +``` + +### Read-write members — `accessors:readwrite` + +Place the annotation on a member's declaration line to generate both a getter and a setter, overriding a restrictive struct-level default (`none`, `readonly`, or `writeonly`): + +```c +struct nvme_ctrl { /*!generate-accessors:none*/ + char *name; /* no accessors (struct default) */ + char *model; //!accessors:readwrite /* both getter and setter */ + char *firmware; //!accessors:readonly /* getter only */ +}; +``` + ### Annotation summary -| Annotation | Where | Effect | -| --------------------------- | ------------ | ------------------------------- | -| `/*!generate-accessors*/` | struct brace | Include this struct | -| `//!generate-accessors` | struct brace | Include this struct | -| `/*!accessors:none*/` | member line | Skip this member entirely | -| `//!accessors:none` | member line | Skip this member entirely | -| `/*!accessors:readonly*/` | member line | Generate getter only | -| `//!accessors:readonly` | member line | Generate getter only | -| `const` qualifier on member | member type | Generate getter only (built-in) | +| Annotation | Where | Effect | +| --------------------------------------- | ------------ | ------------------------------------------- | +| `//!generate-accessors` | struct brace | Include struct, default: getter + setter | +| `//!generate-accessors:none` | struct brace | Include struct, default: no accessors | +| `//!generate-accessors:readonly` | struct brace | Include struct, default: getter only | +| `//!generate-accessors:writeonly` | struct brace | Include struct, default: setter only | +| `//!accessors:none` | member line | Skip this member entirely | +| `//!accessors:readonly` | member line | Generate getter only | +| `//!accessors:writeonly` | member line | Generate setter only | +| `//!accessors:readwrite` | member line | Generate getter and setter | +| `const` qualifier on member | member type | Suppress setter (built-in, always applies) | ------ @@ -265,8 +297,11 @@ __public const char *person_get_role(const struct person *p) 1. **Dynamic strings** (`char *`) — setters store a `strdup()` copy; passing `NULL` clears the field. 2. **Fixed char arrays** (`char foo[N]`) — setters use `snprintf`, always NUL-terminated. -3. **`const` members** — only a getter is generated, no setter. +3. **`const` members** — only a getter is generated, no setter (applies regardless of any annotation). 4. **`//!accessors:readonly`** — same effect as `const`: getter only. -5. **`//!accessors:none`** — member is completely ignored by the generator. -6. **`--prefix`** — prepended to every function name (e.g. `--prefix nvme_` turns `ctrl_set_name` into `nvme_ctrl_set_name`). -7. **Line length** — generated code is automatically wrapped to stay within the 80-column limit required by `checkpatch.pl`. +5. **`//!accessors:writeonly`** — setter only; getter is suppressed. +6. **`//!accessors:readwrite`** — both getter and setter; overrides a restrictive struct-level default. +7. **`//!accessors:none`** — member is completely ignored by the generator. +8. **Struct-level mode** — the qualifier on `generate-accessors` sets the default for every member in the struct; per-member annotations override the struct default. +9. **`--prefix`** — prepended to every function name (e.g. `--prefix nvme_` turns `ctrl_set_name` into `nvme_ctrl_set_name`). +10. **Line length** — generated code is automatically wrapped to stay within the 80-column limit required by `checkpatch.pl`. diff --git a/libnvme/tools/generator/generate-accessors.py b/libnvme/tools/generator/generate-accessors.py index c0190cf997..3d4470584e 100755 --- a/libnvme/tools/generator/generate-accessors.py +++ b/libnvme/tools/generator/generate-accessors.py @@ -16,9 +16,16 @@ - Does not support typedef struct. - Does not support struct within struct. -Struct inclusion — annotate the opening brace line of the struct: - struct nvme_ctrl { /*!generate-accessors*/ - struct nvme_ctrl { //!generate-accessors +Struct inclusion — annotate the opening brace line of the struct. +The optional mode qualifier sets the default for all members of the struct: + struct nvme_ctrl { /*!generate-accessors*/ — default: both getter and setter + struct nvme_ctrl { //!generate-accessors — default: both getter and setter + struct nvme_ctrl { /*!generate-accessors:none*/ — default: no accessors + struct nvme_ctrl { //!generate-accessors:none — default: no accessors + struct nvme_ctrl { /*!generate-accessors:readonly*/ — default: getter only + struct nvme_ctrl { //!generate-accessors:readonly — default: getter only + struct nvme_ctrl { /*!generate-accessors:writeonly*/ — default: setter only + struct nvme_ctrl { //!generate-accessors:writeonly — default: setter only Member exclusion — annotate the member declaration line: char *model; /*!accessors:none*/ @@ -30,6 +37,16 @@ char *state; /*!accessors:readonly*/ char *state; //!accessors:readonly +Write-only members (setter only, getter suppressed): + - Annotate the member declaration line: + char *state; /*!accessors:writeonly*/ + char *state; //!accessors:writeonly + +Both getter and setter (override a restrictive struct-level default): + - Annotate the member declaration line: + char *state; /*!accessors:readwrite*/ + char *state; //!accessors:readwrite + Example usage: ./generate-accessors.py private.h ./generate-accessors.py --prefix nvme_ private.h @@ -185,12 +202,15 @@ def fits_80_ntabs(n, s): class Member: """Represents one member of a parsed C struct.""" - __slots__ = ('name', 'type', 'is_const', 'is_char_array', 'array_size') + __slots__ = ('name', 'type', 'gen_getter', 'gen_setter', + 'is_char_array', 'array_size') - def __init__(self, name, type_str, is_const, is_char_array, array_size): + def __init__(self, name, type_str, gen_getter, gen_setter, + is_char_array, array_size): self.name = name - self.type = type_str # e.g. "const char *", "int", "__u32" - self.is_const = is_const # True → getter only (no setter generated) + self.type = type_str # e.g. "const char *", "int", "__u32" + self.gen_getter = gen_getter # True → emit getter + self.gen_setter = gen_setter # True → emit setter self.is_char_array = is_char_array self.array_size = array_size # only valid when is_char_array is True @@ -199,9 +219,16 @@ def __init__(self, name, type_str, is_const, is_char_array, array_size): # Parsing # --------------------------------------------------------------------------- -def parse_members(struct_name, raw_body, verbose): +def parse_members(struct_name, raw_body, struct_mode, verbose): """Parse *raw_body* and return a list of Member objects. + *struct_mode* is the default access mode for all members of this struct, + derived from the generate-accessors annotation qualifier: + 'both' — generate getter and setter (default when no qualifier) + 'readonly' — generate getter only + 'writeonly' — generate setter only + 'none' — generate nothing unless a per-member annotation overrides + Annotations are detected on the **raw** (un-stripped) line so that comment masking cannot hide them. Comments are stripped only afterwards, for regex matching. @@ -214,7 +241,18 @@ def parse_members(struct_name, raw_body, verbose): # ---------------------------------------------------------------- if has_annotation(raw_line, 'accessors:none'): continue - readonly = has_annotation(raw_line, 'accessors:readonly') + + if has_annotation(raw_line, 'accessors:readwrite'): + member_mode = 'both' + elif has_annotation(raw_line, 'accessors:readonly'): + member_mode = 'readonly' + elif has_annotation(raw_line, 'accessors:writeonly'): + member_mode = 'writeonly' + else: + member_mode = struct_mode + + gen_getter = member_mode in ('both', 'readonly') + gen_setter = member_mode in ('both', 'writeonly') # ---------------------------------------------------------------- # Strip comments for member-declaration parsing. @@ -229,10 +267,12 @@ def parse_members(struct_name, raw_body, verbose): # --- char array: [const] char name[size]; ----------------------- m = CHAR_ARRAY_RE.match(clean) if m: + is_const_qual = bool(m.group(1)) members.append(Member( name=m.group(2), type_str='const char *', - is_const=readonly or bool(m.group(1)), + gen_getter=gen_getter, + gen_setter=gen_setter and not is_const_qual, is_char_array=True, array_size=m.group(3), )) @@ -257,7 +297,8 @@ def parse_members(struct_name, raw_body, verbose): members.append(Member( name=name, type_str=type_str, - is_const=readonly or is_const_qual, + gen_getter=gen_getter, + gen_setter=gen_setter and not is_const_qual, is_char_array=False, array_size=None, )) @@ -265,6 +306,48 @@ def parse_members(struct_name, raw_body, verbose): return members +_VALID_MODES = frozenset(('both', 'none', 'readonly', 'writeonly')) + + +def parse_struct_annotation(raw_body): + """Return the default mode for a struct from its generate-accessors annotation. + + Recognises both comment styles with an optional mode qualifier: + /*!generate-accessors*/ → 'both' + /*!generate-accessors:none*/ → 'none' + /*!generate-accessors:readonly*/ → 'readonly' + /*!generate-accessors:writeonly*/ → 'writeonly' + //!generate-accessors → 'both' + //!generate-accessors:none → 'none' + //!generate-accessors:readonly → 'readonly' + //!generate-accessors:writeonly → 'writeonly' + + Returns None when the annotation is absent. + Prints a warning and falls back to 'both' for unrecognised qualifiers. + """ + first_token = raw_body.lstrip() + + for pattern in ( + r'/\*!generate-accessors(?::([a-z]+))?\*/', + r'//!generate-accessors(?::([a-z]+))?', + ): + m = re.match(pattern, first_token) + if m: + qualifier = m.group(1) or 'both' + if qualifier not in _VALID_MODES: + print( + f"warning: unknown generate-accessors qualifier " + f"'{qualifier}'; valid values are: " + f"{', '.join(sorted(_VALID_MODES))}. " + f"Defaulting to 'both'.", + file=sys.stderr, + ) + qualifier = 'both' + return qualifier + + return None + + def parse_file(text, verbose): """Return list of (struct_name, [Member]) tuples found in *text*. @@ -278,16 +361,15 @@ def parse_file(text, verbose): struct_name = match.group(1) raw_body = match.group(2) - # The annotation must be the first token after the opening '{'. - first_token = raw_body.lstrip() - if not (first_token.startswith('/*!generate-accessors*/') or - first_token.startswith('//!generate-accessors')): + struct_mode = parse_struct_annotation(raw_body) + if struct_mode is None: continue - members = parse_members(struct_name, raw_body, verbose) + members = parse_members(struct_name, raw_body, struct_mode, verbose) if verbose and members: - print(f"Found struct: {struct_name} ({len(members)} members)") + print(f"Found struct: {struct_name} ({len(members)} members)" + f" [mode: {struct_mode}]") if members: result.append((struct_name, members)) @@ -387,15 +469,16 @@ def generate_hdr(f, prefix, struct_name, members): for member in members: is_dyn_str = (not member.is_char_array and member.type == 'const char *') - if not member.is_const: + if member.gen_setter: if member.is_char_array or is_dyn_str: emit_hdr_setter_str(f, prefix, struct_name, member.name, is_dyn_str) else: emit_hdr_setter_val(f, prefix, struct_name, member.name, member.type) - emit_hdr_getter(f, prefix, struct_name, - member.name, member.type, is_dyn_str) + if member.gen_getter: + emit_hdr_getter(f, prefix, struct_name, + member.name, member.type, is_dyn_str) # --------------------------------------------------------------------------- @@ -489,9 +572,9 @@ def emit_src_getter(f, prefix, sname, mname, mtype): def generate_src(f, prefix, struct_name, members): """Write source implementations for all members of one struct.""" for member in members: - if not member.is_const: - is_dyn_str = (not member.is_char_array and - member.type == 'const char *') + is_dyn_str = (not member.is_char_array and + member.type == 'const char *') + if member.gen_setter: if is_dyn_str: emit_src_setter_dynstr(f, prefix, struct_name, member.name) elif member.is_char_array: @@ -500,7 +583,8 @@ def generate_src(f, prefix, struct_name, members): else: emit_src_setter_val(f, prefix, struct_name, member.name, member.type) - emit_src_getter(f, prefix, struct_name, member.name, member.type) + if member.gen_getter: + emit_src_getter(f, prefix, struct_name, member.name, member.type) # --------------------------------------------------------------------------- @@ -510,8 +594,9 @@ def generate_src(f, prefix, struct_name, members): def generate_ld(f, prefix, struct_name, members): """Write linker version-script entries for all members of one struct.""" for member in members: - f.write(f'\t\t{_get_name(prefix, struct_name, member.name)};\n') - if not member.is_const: + if member.gen_getter: + f.write(f'\t\t{_get_name(prefix, struct_name, member.name)};\n') + if member.gen_setter: f.write(f'\t\t{_set_name(prefix, struct_name, member.name)};\n') diff --git a/libnvme/tools/generator/update-accessors.sh b/libnvme/tools/generator/update-accessors.sh index 25d72a0215..692b65fad4 100755 --- a/libnvme/tools/generator/update-accessors.sh +++ b/libnvme/tools/generator/update-accessors.sh @@ -99,7 +99,7 @@ check_ld_drift() { echo "" if [ -n "$added" ]; then echo " Symbols to ADD (new version section, e.g. _ACCESSORS_X_Y):" - printf '%s\n' "$added" | sed 's/^/ /' + printf '%s\n' "$added" | sed 's/^/\t\t/' | sed 's/$/;/' fi if [ -n "$removed" ]; then echo "" diff --git a/meson.build b/meson.build index 7efa867d47..1699f3e227 100644 --- a/meson.build +++ b/meson.build @@ -54,7 +54,7 @@ want_nvme = get_option('nvme').disabled() == false want_libnvme = get_option('libnvme').disabled() == false want_fabrics = get_option('fabrics').disabled() == false and host_system != 'windows' want_mi = get_option('mi').disabled() == false and host_system != 'windows' -want_json_c = get_option('json-c').disabled() == false and host_system != 'windows' +want_json_c = get_option('json-c').disabled() == false and want_fabrics want_libkmod = get_option('libkmod').disabled() == false and host_system != 'windows' want_tests = get_option('tests') and host_system != 'windows' want_examples = get_option('examples') and host_system != 'windows'