From 0aa7744a7ca960d068ee9c8516ef65ffa8480b24 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Apr 2026 11:35:38 +0000 Subject: [PATCH 01/17] generate-accessors: extend struct annotation with default mode qualifier Extend the !generate-accessors annotation so callers can set a struct-level default for accessor generation: struct foo { //!generate-accessors - both get+set (unchanged) struct foo { //!generate-accessors:none - no accessors by default struct foo { //!generate-accessors:readonly - getter only by default struct foo { //!generate-accessors:writeonly - setter only by default Add two new per-member annotations to complement the new struct-level defaults when individual members need to override them: //!accessors:writeonly - setter only for this member //!accessors:readwrite - both getter and setter for this member Internally, replace Member.is_const with explicit gen_getter/gen_setter flags and add parse_struct_annotation() to extract the mode qualifier. Update generate-accessors.md with the full annotation table. Signed-off-by: Daniel Wagner --- libnvme/tools/generator/generate-accessors.md | 73 +++++++--- libnvme/tools/generator/generate-accessors.py | 137 ++++++++++++++---- 2 files changed, 165 insertions(+), 45 deletions(-) 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') From 185a61ee7bfcec623702d94824a61d5db7634c45 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Thu, 16 Apr 2026 10:50:38 +0200 Subject: [PATCH 02/17] build: make json-c dependent on fabrics The JSON code is used for reading and writing the configuration files used by the fabrics code. Therefore, it does not make sense to enable JSON without fabrics. This simplifies the core dependencies so the JSON- related code can safely assume fabrics is enabled. Signed-off-by: Daniel Wagner --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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' From d2b92f008be5deff35875617caf3faeb64e18946 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 12:35:33 +0200 Subject: [PATCH 03/17] tree: use traddr_is_hostname from fabrics This function exists in two files with slightly different implementations. Use a single shared implementation instead. Signed-off-by: Daniel Wagner --- libnvme/src/meson.build | 4 ++++ libnvme/src/nvme/fabrics.c | 15 ++++++++++----- libnvme/src/nvme/no-fabrics.c | 15 +++++++++++++++ libnvme/src/nvme/private-fabrics.h | 3 +++ libnvme/src/nvme/tree.c | 23 ++--------------------- 5 files changed, 34 insertions(+), 26 deletions(-) create mode 100644 libnvme/src/nvme/no-fabrics.c 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/fabrics.c b/libnvme/src/nvme/fabrics.c index 7c3b9c680f..d09923ec4a 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -714,16 +714,21 @@ 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; } @@ -1115,7 +1120,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)) { diff --git a/libnvme/src/nvme/no-fabrics.c b/libnvme/src/nvme/no-fabrics.c new file mode 100644 index 0000000000..c2edcaf61b --- /dev/null +++ b/libnvme/src/nvme/no-fabrics.c @@ -0,0 +1,15 @@ +// 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; +} diff --git a/libnvme/src/nvme/private-fabrics.h b/libnvme/src/nvme/private-fabrics.h index 891e0be658..84f22effe1 100644 --- a/libnvme/src/nvme/private-fabrics.h +++ b/libnvme/src/nvme/private-fabrics.h @@ -22,3 +22,6 @@ 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); diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index c7e9e6a883..3ce02f24c0 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" @@ -1069,26 +1070,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)); @@ -1131,7 +1112,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) From 96ad7426073fdb5ca4604a6346b8ad492bd58aa1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Apr 2026 15:41:12 +0200 Subject: [PATCH 04/17] fabrics: move libnvmf_context to private-fabrics header Prepare the stage for generating getter/setters for libnvmf_context. For this, the struct needs to be in the private-fabrics header so the getter/setters are placed in the correct header file. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/json.c | 1 + libnvme/src/nvme/private-fabrics.h | 57 ++++++++++++++++++++++++++++++ libnvme/src/nvme/private.h | 57 ------------------------------ libnvme/test/tree.c | 1 + 4 files changed, 59 insertions(+), 57 deletions(-) diff --git a/libnvme/src/nvme/json.c b/libnvme/src/nvme/json.c index 416476c75c..ec42c23ecf 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); diff --git a/libnvme/src/nvme/private-fabrics.h b/libnvme/src/nvme/private-fabrics.h index 84f22effe1..7f8192e552 100644 --- a/libnvme/src/nvme/private-fabrics.h +++ b/libnvme/src/nvme/private-fabrics.h @@ -9,6 +9,63 @@ #include +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; +}; + + /** * NVMe-oF private struct definitions. * diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index e39e90b455..16fb07325f 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -302,63 +302,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); 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 */ From 94376caf5977c4fd56508ead1bbd11dec4ad6c0a Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Apr 2026 10:17:47 +0200 Subject: [PATCH 05/17] fabrics: don't return config from merge_config merge_config merges libnvme_fabrics_config into the controller object from the first argument. There is no need to return the config, and there is no user for it. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/fabrics.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index d09923ec4a..dbf7a6b73c 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -394,7 +394,7 @@ 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); @@ -417,8 +417,6 @@ static struct libnvme_fabrics_config *merge_config(libnvme_ctrl_t c, 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) \ @@ -1056,7 +1054,7 @@ __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, int ret; /* highest prio have configs from command line */ - cfg = merge_config(c, cfg); + merge_config(c, cfg); /* apply configuration from config file (JSON) */ s = libnvme_lookup_subsystem(h, NULL, libnvme_ctrl_get_subsysnqn(c)); @@ -1075,7 +1073,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, libnvme_ctrl_get_config(fc)); /* * An authentication key might already been set * in @cfg, so ensure to update @c with the correct From 96e369df4bcef278ed8d8c0791cd439d6b5e34fc Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Apr 2026 09:09:40 +0000 Subject: [PATCH 06/17] libnvme: update Python binding to use libnvmf_context Teach the Python binding about libnvmf_context so that libnvme_fabric_options can eventually be retired. Signed-off-by: Daniel Wagner --- libnvme/libnvme/nvme.i | 194 ++++++++++++++++++++++++++++------------- 1 file changed, 132 insertions(+), 62 deletions(-) diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index d6ef316f3b..a4f092a17b 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,127 @@ 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; +%rename(set_fabrics_config) libnvmf_context::fctx_set_fabrics_config; + +struct libnvmf_context {}; + +%extend libnvmf_context { + libnvmf_context(struct libnvme_global_ctx *ctx) { + struct libnvmf_context *fctx; + struct libnvme_fabrics_config *cfg; + int err; + + err = libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx); + if (err) + return NULL; + + cfg = calloc(1, sizeof(*cfg)); + if (!cfg) { + libnvmf_context_free(fctx); + return NULL; + } + libnvmf_default_config(cfg); + libnvmf_context_set_fabrics_config(fctx, cfg); + + return fctx; + } + ~libnvmf_context() { + free($self->cfg); + 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 (!$self->cfg) + return; + 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,7 +739,7 @@ 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} @@ -705,12 +774,13 @@ struct libnvme_ns { } void connect(struct libnvme_host *h, - struct libnvme_fabrics_config *cfg = NULL) { + struct libnvmf_context *fctx = NULL) { int ret; const char *dev; + const struct libnvme_fabrics_config *cfg = fctx ? fctx->cfg : NULL; dev = libnvme_ctrl_get_name($self); - if (dev && !cfg->duplicate_connect) { + if (dev && !(cfg && cfg->duplicate_connect)) { connect_err = -ENVME_CONNECT_ALREADY; return; } From b23b99a85c2af46466b99683a296f041f5ebe6a5 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Apr 2026 17:17:57 +0200 Subject: [PATCH 07/17] libnvme: embed libnvme_fabrics_config in libnvmf_context libnvme_fabrics_config is going to be removed from the API. The first step is to let libnvmf_context own the configuration, coupling the fabrics config lifetime to the context object. Signed-off-by: Daniel Wagner --- libnvme/libnvme/nvme.i | 38 ++++----- libnvme/src/nvme/fabrics.c | 119 +++++++++++++++-------------- libnvme/src/nvme/private-fabrics.h | 3 +- 3 files changed, 78 insertions(+), 82 deletions(-) diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index a4f092a17b..72cf07775e 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -450,25 +450,19 @@ struct libnvmf_context {}; %extend libnvmf_context { libnvmf_context(struct libnvme_global_ctx *ctx) { struct libnvmf_context *fctx; - struct libnvme_fabrics_config *cfg; + struct libnvme_fabrics_config cfg = {}; int err; err = libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx); if (err) return NULL; - cfg = calloc(1, sizeof(*cfg)); - if (!cfg) { - libnvmf_context_free(fctx); - return NULL; - } - libnvmf_default_config(cfg); - libnvmf_context_set_fabrics_config(fctx, cfg); + libnvmf_default_config(&cfg); + libnvmf_context_set_fabrics_config(fctx, &cfg); return fctx; } ~libnvmf_context() { - free($self->cfg); libnvmf_context_free($self); } int fctx_set_hostnqn(const char *hostnqn, const char *hostid = NULL) { @@ -492,8 +486,6 @@ struct libnvmf_context {}; Py_ssize_t pos = 0; PyObject *key, *value; - if (!$self->cfg) - return; if (!PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, "set_fabrics_config: argument must be a dict"); @@ -502,50 +494,50 @@ struct libnvmf_context {}; while (PyDict_Next(dict, &pos, &key, &value)) { if (!PyUnicode_CompareWithASCIIString(key, "nr_io_queues")) { - $self->cfg->nr_io_queues = PyLong_AsLong(value); + $self->cfg.nr_io_queues = PyLong_AsLong(value); continue; } if (!PyUnicode_CompareWithASCIIString(key, "reconnect_delay")) { - $self->cfg->reconnect_delay = PyLong_AsLong(value); + $self->cfg.reconnect_delay = PyLong_AsLong(value); continue; } if (!PyUnicode_CompareWithASCIIString(key, "ctrl_loss_tmo")) { - $self->cfg->ctrl_loss_tmo = PyLong_AsLong(value); + $self->cfg.ctrl_loss_tmo = PyLong_AsLong(value); continue; } if (!PyUnicode_CompareWithASCIIString(key, "keep_alive_tmo")) { - $self->cfg->keep_alive_tmo = PyLong_AsLong(value); + $self->cfg.keep_alive_tmo = PyLong_AsLong(value); continue; } if (!PyUnicode_CompareWithASCIIString(key, "nr_write_queues")) { - $self->cfg->nr_write_queues = PyLong_AsLong(value); + $self->cfg.nr_write_queues = PyLong_AsLong(value); continue; } if (!PyUnicode_CompareWithASCIIString(key, "nr_poll_queues")) { - $self->cfg->nr_poll_queues = PyLong_AsLong(value); + $self->cfg.nr_poll_queues = PyLong_AsLong(value); continue; } if (!PyUnicode_CompareWithASCIIString(key, "tos")) { - $self->cfg->tos = PyLong_AsLong(value); + $self->cfg.tos = PyLong_AsLong(value); continue; } if (!PyUnicode_CompareWithASCIIString(key, "duplicate_connect")) { - $self->cfg->duplicate_connect = + $self->cfg.duplicate_connect = PyObject_IsTrue(value) ? true : false; continue; } if (!PyUnicode_CompareWithASCIIString(key, "disable_sqflow")) { - $self->cfg->disable_sqflow = + $self->cfg.disable_sqflow = PyObject_IsTrue(value) ? true : false; continue; } if (!PyUnicode_CompareWithASCIIString(key, "hdr_digest")) { - $self->cfg->hdr_digest = + $self->cfg.hdr_digest = PyObject_IsTrue(value) ? true : false; continue; } if (!PyUnicode_CompareWithASCIIString(key, "data_digest")) { - $self->cfg->data_digest = + $self->cfg.data_digest = PyObject_IsTrue(value) ? true : false; continue; } @@ -777,7 +769,7 @@ struct libnvmf_context {}; struct libnvmf_context *fctx = NULL) { int ret; const char *dev; - const struct libnvme_fabrics_config *cfg = fctx ? fctx->cfg : NULL; + const struct libnvme_fabrics_config *cfg = fctx ? &fctx->cfg : NULL; dev = libnvme_ctrl_get_name($self); if (dev && !(cfg && cfg->duplicate_connect)) { diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index dbf7a6b73c..41867c27f6 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -263,7 +263,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 = cfg->keyring; + fctx->cfg.tls_key = cfg->tls_key; + fctx->cfg.tls_configured_key = cfg->tls_configured_key; + 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; } @@ -1188,7 +1205,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; @@ -1281,7 +1297,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, &fctx->cfg); if (!ret) { *cp = c; return 0; @@ -1292,7 +1308,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, &fctx->cfg); if (!ret) { *cp = c; return 0; @@ -1961,17 +1977,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; } @@ -2041,7 +2056,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; @@ -2087,16 +2102,15 @@ 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) @@ -2146,13 +2160,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, &fctx->cfg); if (!err) return 0; if (fctx->decide_retry(fctx, err, fctx->user_data)) @@ -2163,7 +2176,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; @@ -2175,7 +2188,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); @@ -2183,8 +2196,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; @@ -2196,14 +2209,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; @@ -2248,7 +2260,7 @@ static int nvmf_create_discovery_ctrl(struct libnvme_global_ctx *ctx, 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; @@ -2261,7 +2273,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; @@ -2311,8 +2322,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) { @@ -2322,7 +2331,7 @@ 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; @@ -2475,8 +2484,7 @@ __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; @@ -2535,9 +2543,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); + libnvmf_update_config(c, &fctx->cfg); return 0; } @@ -2629,8 +2637,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; @@ -2656,7 +2663,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, &fctx->cfg); /* Resume logging */ if (ss && ss->unavailable && saved_log_level < 1) @@ -2688,8 +2695,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; @@ -2712,7 +2718,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); @@ -2736,15 +2742,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); + nbft_discovery(ctx, &nfctx, dd, h, child); libnvme_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 @@ -2757,8 +2762,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, @@ -2775,7 +2779,7 @@ static int nbft_discovery(struct libnvme_global_ctx *ctx, break; } - defcfg->keep_alive_tmo = tmo; + fctx->cfg.keep_alive_tmo = tmo; } free(log); @@ -2869,8 +2873,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 @@ -2883,7 +2886,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, @@ -2965,13 +2968,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; @@ -2983,7 +2986,7 @@ __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); libnvme_free_ctrl(c); @@ -3075,7 +3078,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, @@ -3108,7 +3111,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); @@ -3126,7 +3129,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 @@ -3135,10 +3138,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/private-fabrics.h b/libnvme/src/nvme/private-fabrics.h index 7f8192e552..2247312854 100644 --- a/libnvme/src/nvme/private-fabrics.h +++ b/libnvme/src/nvme/private-fabrics.h @@ -7,6 +7,7 @@ */ #pragma once +#include #include struct libnvmf_context { @@ -41,7 +42,7 @@ struct libnvmf_context { /* common fabrics configuraiton */ const char *device; bool persistent; - struct libnvme_fabrics_config *cfg; + struct libnvme_fabrics_config cfg; /* connection configuration */ const char *subsysnqn; From 128aac4f2f5bdd826913622e745a0c8e4b1a889a Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Apr 2026 17:56:28 +0200 Subject: [PATCH 08/17] fabrics: replace fabrics options with fabrics context Retire the libnvme_fabrics_options type from the public API as any modification is breaking ABI. The libnvmf_context has been introduced as replacement, with an extendable getter/setter API. Signed-off-by: Daniel Wagner --- libnvme/examples/discover-loop.c | 31 +++++++++++++++++++------------ libnvme/libnvme/nvme.i | 5 ++--- libnvme/src/nvme/fabrics.c | 12 ++++++------ libnvme/src/nvme/fabrics.h | 19 ++++++++++--------- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/libnvme/examples/discover-loop.c b/libnvme/examples/discover-loop.c index a3151209ad..0a303bddb7 100644 --- a/libnvme/examples/discover-loop.c +++ b/libnvme/examples/discover-loop.c @@ -53,38 +53,41 @@ 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 = 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); 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, fctx); if (ret) { fprintf(stderr, "no controller found\n"); - return 1; + goto free_fctx; } ret = libnvmf_discovery_args_create(&args); @@ -102,7 +105,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 72cf07775e..6c508c7917 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -769,16 +769,15 @@ struct libnvmf_context {}; struct libnvmf_context *fctx = NULL) { int ret; const char *dev; - const struct libnvme_fabrics_config *cfg = fctx ? &fctx->cfg : NULL; dev = libnvme_ctrl_get_name($self); - if (dev && !(cfg && cfg->duplicate_connect)) { + if (dev && !(fctx && fctx->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, fctx); Py_END_ALLOW_THREADS /* Reacquire Python GIL */ if (ret) { diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 41867c27f6..9217d69856 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -1063,7 +1063,7 @@ static const char *lookup_context(struct libnvme_global_ctx *ctx, libnvme_ctrl_t } __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, - const struct libnvme_fabrics_config *cfg) + const struct libnvmf_context *fctx) { libnvme_subsystem_t s; const char *root_app, *app; @@ -1071,7 +1071,7 @@ __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, int ret; /* highest prio have configs from command line */ - merge_config(c, cfg); + merge_config(c, &fctx->cfg); /* apply configuration from config file (JSON) */ s = libnvme_lookup_subsystem(h, NULL, libnvme_ctrl_get_subsysnqn(c)); @@ -1297,7 +1297,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, &fctx->cfg); + ret = libnvmf_add_ctrl(h, c, fctx); if (!ret) { *cp = c; return 0; @@ -1308,7 +1308,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, &fctx->cfg); + ret = libnvmf_add_ctrl(h, c, fctx); if (!ret) { *cp = c; return 0; @@ -2165,7 +2165,7 @@ static int libnvme_add_ctrl(struct libnvmf_context *fctx, int err; retry: - err = libnvmf_add_ctrl(h, c, &fctx->cfg); + err = libnvmf_add_ctrl(h, c, fctx); if (!err) return 0; if (fctx->decide_retry(fctx, err, fctx->user_data)) @@ -2663,7 +2663,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, &fctx->cfg); + ret = libnvmf_add_ctrl(h, c, fctx); /* Resume logging */ if (ss && ss->unavailable && saved_log_level < 1) diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index 302e0a971e..743c73e4a0 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -23,6 +23,14 @@ /* default to 600 seconds of reconnect attempts before giving up */ #define NVMF_DEF_CTRL_LOSS_TMO 600 +/* + * 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_config - Defines all linux nvme fabrics initiator options * @queue_size: Number of IO queue entries @@ -210,7 +218,7 @@ void libnvmf_update_config(libnvme_ctrl_t c, * 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 + * @fctx: Fabrics context * * Issues a 'connect' command to the NVMe-oF controller and inserts @c * into the topology using @h as parent. @@ -219,7 +227,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); + const struct libnvmf_context *fctx); /** * libnvmf_connect_ctrl() - Connect a controller @@ -339,13 +347,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 From e866ec2cd7b10a551ea2cd8a4edc6b6b55f88d95 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 11:39:30 +0200 Subject: [PATCH 09/17] fabrics: move connect/disconnect to fabrics API The connect and disconnect functions belong to the fabrics API. Move them there. While at it, also move libnvme_ctrl_get_config to the fabrics.h header, since it returns the fabrics configuration. Signed-off-by: Daniel Wagner --- fabrics.c | 6 +-- libnvme/examples/discover-loop.c | 4 +- libnvme/libnvme/nvme.i | 6 +-- libnvme/src/libnvme.ld | 3 -- libnvme/src/libnvmf.ld | 7 +++- libnvme/src/nvme/fabrics.c | 66 ++++++++++++++++++++++++++------ libnvme/src/nvme/fabrics.h | 42 +++++++++++++++++++- libnvme/src/nvme/json.c | 6 +-- libnvme/src/nvme/private.h | 2 + libnvme/src/nvme/tree.c | 42 -------------------- libnvme/src/nvme/tree.h | 40 ------------------- 11 files changed, 113 insertions(+), 111 deletions(-) diff --git a/fabrics.c b/fabrics.c index e32b5fdbaf..6bd1664af3 100644 --- a/fabrics.c +++ b/fabrics.c @@ -773,7 +773,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 +856,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 +922,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)); diff --git a/libnvme/examples/discover-loop.c b/libnvme/examples/discover-loop.c index 0a303bddb7..bbf5500387 100644 --- a/libnvme/examples/discover-loop.c +++ b/libnvme/examples/discover-loop.c @@ -77,7 +77,7 @@ int main() goto free_fctx; } - ret = libnvme_create_ctrl(ctx, NVME_DISC_SUBSYS_NAME, "loop", + ret = libnvmf_create_ctrl(ctx, NVME_DISC_SUBSYS_NAME, "loop", NULL, NULL, NULL, NULL, &c); if (ret) { fprintf(stderr, "Failed to allocate memory\n"); @@ -97,7 +97,7 @@ int main() libnvmf_discovery_args_free(args); } - libnvme_disconnect_ctrl(c); + libnvmf_disconnect_ctrl(c); libnvme_free_ctrl(c); if (ret) diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index 6c508c7917..626e89c99a 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -744,7 +744,7 @@ struct libnvmf_context {}; const char *host_iface = NULL, const char *trsvcid = NULL) { struct libnvme_ctrl *c; - if (libnvme_create_ctrl(ctx, subsysnqn, transport, traddr, + if (libnvmf_create_ctrl(ctx, subsysnqn, transport, traddr, host_traddr, host_iface, trsvcid, &c)) return NULL; return c; @@ -757,7 +757,7 @@ struct libnvmf_context {}; } 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; } @@ -801,7 +801,7 @@ struct libnvmf_context {}; 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/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..ddb806ffa3 100644 --- a/libnvme/src/libnvmf.ld +++ b/libnvme/src/libnvmf.ld @@ -19,8 +19,13 @@ LIBNVMF_3 { libnvmf_context_set_fabrics_config; libnvmf_context_set_hostnqn; libnvmf_context_set_persistent; + libnvmf_create_ctrl; + libnvmf_ctrl_get_config; libnvmf_default_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; diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 9217d69856..1f06c2db4a 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -378,6 +378,12 @@ __public int libnvmf_context_set_device(struct libnvmf_context *fctx, const char return 0; } +__public struct libnvme_fabrics_config *libnvmf_ctrl_get_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). @@ -414,7 +420,7 @@ static const struct libnvme_fabric_options default_supported_options = { 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_config(c); MERGE_CFG_OPTION(ctrl_cfg, cfg, nr_io_queues, 0); MERGE_CFG_OPTION(ctrl_cfg, cfg, nr_write_queues, 0); @@ -440,7 +446,7 @@ static void merge_config(libnvme_ctrl_t c, if ((n)->o != d) (c)->o = (n)->o __public void libnvmf_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_config(c); UPDATE_CFG_OPTION(ctrl_cfg, cfg, nr_io_queues, 0); UPDATE_CFG_OPTION(ctrl_cfg, cfg, nr_write_queues, 0); @@ -749,7 +755,7 @@ bool traddr_is_hostname(struct libnvme_global_ctx *ctx, 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_config(c); const char *transport = libnvme_ctrl_get_transport(c); const char *hostnqn, *hostid, *hostkey, *ctrlkey = NULL; bool discover = false, discovery_nqn = false; @@ -1062,6 +1068,24 @@ static const char *lookup_context(struct libnvme_global_ctx *ctx, libnvme_ctrl_t return NULL; } +__public int libnvmf_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); +} + __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, const struct libnvmf_context *fctx) { @@ -1090,7 +1114,7 @@ __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c, if (fc) { const char *key; - merge_config(c, libnvme_ctrl_get_config(fc)); + merge_config(c, libnvmf_ctrl_get_config(fc)); /* * An authentication key might already been set * in @cfg, so ensure to update @c with the correct @@ -1174,6 +1198,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) { @@ -2117,7 +2159,7 @@ static int _nvmf_discovery(struct libnvme_global_ctx *ctx, _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) { @@ -2242,7 +2284,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; } @@ -2256,7 +2298,7 @@ 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; @@ -2337,7 +2379,7 @@ int _discovery_config_json(struct libnvme_global_ctx *ctx, _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; @@ -2491,7 +2533,7 @@ __public int libnvmf_discovery_config_file(struct libnvme_global_ctx *ctx, _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); @@ -2746,7 +2788,7 @@ static int nbft_discovery(struct libnvme_global_ctx *ctx, if (ret) continue; nbft_discovery(ctx, &nfctx, dd, h, child); - libnvme_disconnect_ctrl(child); + libnvmf_disconnect_ctrl(child); libnvme_free_ctrl(child); } else { ret = nbft_connect(ctx, &nfctx, h, e, NULL); @@ -2988,7 +3030,7 @@ __public int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, 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; @@ -3090,7 +3132,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; diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index 743c73e4a0..7b32ec400a 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -505,6 +505,14 @@ int libnvmf_context_set_persistent(struct libnvmf_context *fctx, bool persistent */ int libnvmf_context_set_device(struct libnvmf_context *fctx, const char *device); +/** + * libnvmf_ctrl_get_config() - Fabrics configuration of a controller + * @c: Controller instance + * + * Return: Fabrics configuration of @c + */ +struct libnvme_fabrics_config *libnvmf_ctrl_get_config(libnvme_ctrl_t c); + /** * libnvmf_discovery() - Perform fabrics discovery * @ctx: Global context @@ -561,6 +569,27 @@ 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 + * @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 libnvmf_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); + /** * libnvmf_connect() - Connect to fabrics subsystem * @ctx: Global context @@ -570,7 +599,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 ec42c23ecf..2c4da15c32 100644 --- a/libnvme/src/nvme/json.c +++ b/libnvme/src/nvme/json.c @@ -26,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_config(c); json_object_object_foreach(ctrl_obj, key_str, val_obj) { JSON_UPDATE_INT_OPTION(cfg, key_str, @@ -275,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_config(c); struct json_object *port_obj = json_object_new_object(); const char *transport, *value; @@ -443,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_config(c); struct json_object *ctrl_obj = json_object_new_object(); const char *name, *transport, *value; diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index 16fb07325f..923920d672 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -332,6 +332,8 @@ void *__libnvme_alloc(size_t len); void *__libnvme_realloc(void *p, size_t len); +void nvme_deconfigure_ctrl(libnvme_ctrl_t c); + libnvme_host_t libnvme_lookup_host(struct libnvme_global_ctx *ctx, const char *hostnqn, const char *hostid); libnvme_subsystem_t libnvme_lookup_subsystem(struct libnvme_host *h, diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index 3ce02f24c0..4ad6e0cf2c 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -954,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 = @@ -1017,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); @@ -1127,24 +1103,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 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 From ba82e9148a68457ba888c111d14629773e5710b1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Apr 2026 18:24:51 +0200 Subject: [PATCH 10/17] fabrics: add _id postfix to TLS keys in libnvme_fabrics_options There are two types of keys used: one is the string representation and the other is the actual key ID used by the kernel. Add a postfix to the kernel types so it is clear which is being used. Signed-off-by: Daniel Wagner --- fabrics.c | 2 +- libnvme/src/nvme/fabrics.c | 24 ++++++++++++------------ libnvme/src/nvme/fabrics.h | 12 ++++++------ libnvme/src/nvme/linux.c | 2 +- libnvme/src/nvme/tree.c | 4 ++-- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/fabrics.c b/fabrics.c index 6bd1664af3..b20727bcd8 100644 --- a/fabrics.c +++ b/fabrics.c @@ -136,7 +136,7 @@ struct nvmf_args { 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_INT("tls_key", 0, &c.tls_key_id, 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), \ diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 1f06c2db4a..9c9a4bb0ca 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -272,9 +272,9 @@ __public int libnvmf_context_set_fabrics_config(struct libnvmf_context *fctx, 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 = cfg->keyring; - fctx->cfg.tls_key = cfg->tls_key; - fctx->cfg.tls_configured_key = cfg->tls_configured_key; + 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; @@ -432,8 +432,8 @@ static void 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, duplicate_connect, false); MERGE_CFG_OPTION(ctrl_cfg, cfg, disable_sqflow, false); MERGE_CFG_OPTION(ctrl_cfg, cfg, hdr_digest, false); @@ -458,8 +458,8 @@ __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, duplicate_connect, false); UPDATE_CFG_OPTION(ctrl_cfg, cfg, disable_sqflow, false); UPDATE_CFG_OPTION(ctrl_cfg, cfg, hdr_digest, false); @@ -817,10 +817,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; } } @@ -2042,7 +2042,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); } @@ -2055,7 +2055,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); } diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index 7b32ec400a..34e5759a14 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -42,9 +42,9 @@ struct libnvmf_context; * @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 + * @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) @@ -62,9 +62,9 @@ struct libnvme_fabrics_config { int nr_write_queues; int nr_poll_queues; int tos; - long keyring; - long tls_key; - long tls_configured_key; + long keyring_id; + long tls_key_id; + long tls_configured_key_id; bool duplicate_connect; bool disable_sqflow; 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/tree.c b/libnvme/src/nvme/tree.c index 4ad6e0cf2c..804ae948f8 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -1702,7 +1702,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); @@ -1713,7 +1713,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); } From 1a6966de0796cad36d6e2541c232c4fc8b39ceda Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 10 Apr 2026 18:30:57 +0200 Subject: [PATCH 11/17] fabrics: add missing common arguments to nvmf_args libnvme_fabrics_config is going to be removed from the library API. Add the missing common command-line options to nvmf_args and introduce a central function that sets fabrics options in nvmf_context. This reduces the usage of libnvme_fabrics_options to a single place. Signed-off-by: Daniel Wagner --- fabrics.c | 127 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 42 deletions(-) diff --git a/fabrics.c b/fabrics.c index b20727bcd8..f92f2e64ad 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_id, 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,46 @@ 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.queue_size = fa->queue_size; + fcfg.nr_io_queues = fa->nr_io_queues; + fcfg.reconnect_delay = fa->reconnect_delay; + fcfg.ctrl_loss_tmo = fa->ctrl_loss_tmo; + fcfg.fast_io_fail_tmo = fa->fast_io_fail_tmo; + fcfg.keep_alive_tmo = fa->keep_alive_tmo; + fcfg.nr_write_queues = fa->nr_write_queues; + fcfg.nr_poll_queues = fa->nr_poll_queues; + fcfg.tos = fa->tos; + fcfg.keyring_id = fa->keyring_id; + fcfg.tls_key_id = fa->tls_key_id; + fcfg.tls_configured_key_id = fa->tls_configured_key_id; + fcfg.duplicate_connect = fa->duplicate_connect; + fcfg.disable_sqflow = fa->disable_sqflow; + fcfg.hdr_digest = fa->hdr_digest; + fcfg.data_digest = fa->data_digest; + fcfg.tls = fa->tls; + fcfg.concat = fa->concat; + + return libnvmf_context_set_fabrics_config(fctx, &fcfg); +} + 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 +365,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 +401,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 +421,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 +446,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 +575,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 +582,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 +595,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 +644,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 +690,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 +763,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; @@ -938,18 +983,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 +1038,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; From 6b42360214b86aa6fd0b4b2932d89b6e0d4f8775 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 13:32:52 +0200 Subject: [PATCH 12/17] fabrics: use context at controller creation time The controller is created from the provided fabrics context, which contains all the information required to fully construct it. The libnvmf_add_ctrl function should only perform the connect call. Signed-off-by: Daniel Wagner --- libnvme/examples/discover-loop.c | 10 +++++-- libnvme/libnvme/nvme.i | 17 ++++------- libnvme/libnvme/tests/create-ctrl-obj.py | 23 ++++++++------- libnvme/libnvme/tests/gc.py | 17 ++++++----- libnvme/libnvme/tests/test-objects.py | 36 ++++++++++++++++-------- libnvme/src/nvme/fabrics.c | 34 +++++++--------------- libnvme/src/nvme/fabrics.h | 16 ++--------- libnvme/src/nvme/no-fabrics.c | 3 ++ libnvme/src/nvme/tree.c | 4 +-- 9 files changed, 78 insertions(+), 82 deletions(-) diff --git a/libnvme/examples/discover-loop.c b/libnvme/examples/discover-loop.c index bbf5500387..01bb2408bf 100644 --- a/libnvme/examples/discover-loop.c +++ b/libnvme/examples/discover-loop.c @@ -67,6 +67,11 @@ int main() 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) goto free_fctx; @@ -77,14 +82,13 @@ int main() goto free_fctx; } - ret = libnvmf_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"); goto free_fctx; } - ret = libnvmf_add_ctrl(h, c, fctx); + ret = libnvmf_add_ctrl(h, c); if (ret) { fprintf(stderr, "no controller found\n"); goto free_fctx; diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index 626e89c99a..2f4b262619 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -737,15 +737,9 @@ struct libnvmf_context {}; 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 (libnvmf_create_ctrl(ctx, subsysnqn, transport, traddr, - host_traddr, host_iface, trsvcid, &c)) + if (libnvmf_create_ctrl(ctx, fctx, &c)) return NULL; return c; } @@ -765,19 +759,18 @@ struct libnvmf_context {}; return libnvme_init_ctrl(h, $self, instance) == 0; } - void connect(struct libnvme_host *h, - struct libnvmf_context *fctx = NULL) { + void connect(struct libnvme_host *h) { int ret; const char *dev; dev = libnvme_ctrl_get_name($self); - if (dev && !(fctx && fctx->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, fctx); + ret = libnvmf_add_ctrl(h, $self); Py_END_ALLOW_THREADS /* Reacquire Python GIL */ if (ret) { 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/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 9c9a4bb0ca..57697c0811 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -215,6 +215,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; @@ -1069,34 +1071,18 @@ static const char *lookup_context(struct libnvme_global_ctx *ctx, libnvme_ctrl_t } __public int libnvmf_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); + 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, - const struct libnvmf_context *fctx) +__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 */ - merge_config(c, &fctx->cfg); - /* apply configuration from config file (JSON) */ s = libnvme_lookup_subsystem(h, NULL, libnvme_ctrl_get_subsysnqn(c)); if (s) { @@ -1339,7 +1325,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, fctx); + ret = libnvmf_add_ctrl(h, c); if (!ret) { *cp = c; return 0; @@ -1350,7 +1336,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, fctx); + ret = libnvmf_add_ctrl(h, c); if (!ret) { *cp = c; return 0; @@ -2207,7 +2193,7 @@ static int libnvme_add_ctrl(struct libnvmf_context *fctx, int err; retry: - err = libnvmf_add_ctrl(h, c, fctx); + err = libnvmf_add_ctrl(h, c); if (!err) return 0; if (fctx->decide_retry(fctx, err, fctx->user_data)) @@ -2705,7 +2691,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, fctx); + ret = libnvmf_add_ctrl(h, c); /* Resume logging */ if (ss && ss->unavailable && saved_log_level < 1) diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index 34e5759a14..f8d4c4f103 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -218,7 +218,6 @@ void libnvmf_update_config(libnvme_ctrl_t c, * libnvmf_add_ctrl() - Connect a controller and update topology * @h: Host to which the controller should be attached * @c: Controller to be connected - * @fctx: Fabrics context * * Issues a 'connect' command to the NVMe-oF controller and inserts @c * into the topology using @h as parent. @@ -226,8 +225,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 libnvmf_context *fctx); +int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c); /** * libnvmf_connect_ctrl() - Connect a controller @@ -572,12 +570,7 @@ int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, /** * libnvmf_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 + * @fctx: Fabrics context * @c: @libnvme_ctrl_t object to return * * Creates an unconnected controller to be used for libnvme_add_ctrl(). @@ -585,10 +578,7 @@ int libnvmf_discovery_nbft(struct libnvme_global_ctx *ctx, * Return: 0 on success or negative error code otherwise */ int libnvmf_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); + struct libnvmf_context *fctx, libnvme_ctrl_t *c); /** * libnvmf_connect() - Connect to fabrics subsystem diff --git a/libnvme/src/nvme/no-fabrics.c b/libnvme/src/nvme/no-fabrics.c index c2edcaf61b..1ca6cb358c 100644 --- a/libnvme/src/nvme/no-fabrics.c +++ b/libnvme/src/nvme/no-fabrics.c @@ -13,3 +13,6 @@ bool traddr_is_hostname(struct libnvme_global_ctx *ctx, { return false; } +__public void libnvmf_default_config(struct libnvme_fabrics_config *cfg) +{ +} diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index 804ae948f8..2abce54e67 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -1048,7 +1048,6 @@ __public void libnvme_free_ctrl(libnvme_ctrl_t c) __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; } @@ -1079,7 +1078,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); @@ -1515,6 +1514,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; From 04867ffd6d5165db0b17f32af03562f6bf83c5f5 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 15:58:11 +0200 Subject: [PATCH 13/17] private: replace typedefs with direct definitions The typedefs are defined in the public fabrics.h. Minimize the dependency on fabrics in the private.h header by using the concrete types for the argument types. This prepares the stage to drop the include. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/private.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index 923920d672..06120fb042 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -324,7 +324,7 @@ struct libnvme_transport_handle *__libnvme_create_transport_handle( 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); @@ -332,18 +332,18 @@ void *__libnvme_alloc(size_t len); void *__libnvme_realloc(void *p, size_t len); -void nvme_deconfigure_ctrl(libnvme_ctrl_t c); +void nvme_deconfigure_ctrl(struct libnvme_ctrl *c); -libnvme_host_t libnvme_lookup_host(struct libnvme_global_ctx *ctx, +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__ @@ -361,8 +361,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) { @@ -552,7 +552,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); /** @@ -560,7 +560,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 From 77ce168d3dec03706ce1cc2a2ee31dfdd74c0d65 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 16:15:06 +0200 Subject: [PATCH 14/17] generate-accessors: output added list with correct formatting Simplify maintainers' workflow by printing the symbols to add in the correct format so they can be copied and pasted directly. Signed-off-by: Daniel Wagner --- libnvme/tools/generator/update-accessors.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 "" From 2caa2a10fb3bdbbbb6ba3c9ec539a90c910424e5 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 16:43:19 +0200 Subject: [PATCH 15/17] fabrics: retire libnvme_fabrics_config from public API Retire struct libnvme_fabrics_config from the public API and replace it with an anonymous struct accessed via getter/setters. This makes it possible to extend the API without breaking the ABI. Signed-off-by: Daniel Wagner --- fabrics.c | 47 ++-- libnvme/libnvme/nvme.i | 5 - libnvme/src/accessors.ld | 230 +++++++++++-------- libnvme/src/libnvmf.ld | 5 +- libnvme/src/nvme/accessors-fabrics.c | 3 +- libnvme/src/nvme/accessors-fabrics.h | 3 +- libnvme/src/nvme/accessors.c | 238 ++++++++++++++++++++ libnvme/src/nvme/accessors.h | 322 +++++++++++++++++++++++++++ libnvme/src/nvme/fabrics.c | 29 ++- libnvme/src/nvme/fabrics.h | 89 ++------ libnvme/src/nvme/json.c | 6 +- libnvme/src/nvme/no-fabrics.c | 3 +- libnvme/src/nvme/private-fabrics.h | 4 + libnvme/src/nvme/private.h | 48 +++- libnvme/src/nvme/tree.c | 6 - 15 files changed, 815 insertions(+), 223 deletions(-) diff --git a/fabrics.c b/fabrics.c index f92f2e64ad..5c0617c701 100644 --- a/fabrics.c +++ b/fabrics.c @@ -301,28 +301,31 @@ static void cb_parser_cleanup(struct libnvmf_context *fctx, void *user_data) static int set_fabrics_options(struct libnvmf_context *fctx, struct nvmf_args *fa) { - struct libnvme_fabrics_config fcfg; - - fcfg.queue_size = fa->queue_size; - fcfg.nr_io_queues = fa->nr_io_queues; - fcfg.reconnect_delay = fa->reconnect_delay; - fcfg.ctrl_loss_tmo = fa->ctrl_loss_tmo; - fcfg.fast_io_fail_tmo = fa->fast_io_fail_tmo; - fcfg.keep_alive_tmo = fa->keep_alive_tmo; - fcfg.nr_write_queues = fa->nr_write_queues; - fcfg.nr_poll_queues = fa->nr_poll_queues; - fcfg.tos = fa->tos; - fcfg.keyring_id = fa->keyring_id; - fcfg.tls_key_id = fa->tls_key_id; - fcfg.tls_configured_key_id = fa->tls_configured_key_id; - fcfg.duplicate_connect = fa->duplicate_connect; - fcfg.disable_sqflow = fa->disable_sqflow; - fcfg.hdr_digest = fa->hdr_digest; - fcfg.data_digest = fa->data_digest; - fcfg.tls = fa->tls; - fcfg.concat = fa->concat; - - return libnvmf_context_set_fabrics_config(fctx, &fcfg); + 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) diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index 2f4b262619..4717fbe59a 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -443,23 +443,18 @@ struct libnvme_ns { %rename(set_connection) libnvmf_context::fctx_set_connection; %rename(set_persistent) libnvmf_context::fctx_set_persistent; %rename(set_device) libnvmf_context::fctx_set_device; -%rename(set_fabrics_config) libnvmf_context::fctx_set_fabrics_config; struct libnvmf_context {}; %extend libnvmf_context { libnvmf_context(struct libnvme_global_ctx *ctx) { struct libnvmf_context *fctx; - struct libnvme_fabrics_config cfg = {}; int err; err = libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx); if (err) return NULL; - libnvmf_default_config(&cfg); - libnvmf_context_set_fabrics_config(fctx, &cfg); - return fctx; } ~libnvmf_context() { 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/libnvmf.ld b/libnvme/src/libnvmf.ld index ddb806ffa3..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; @@ -20,8 +21,7 @@ LIBNVMF_3 { libnvmf_context_set_hostnqn; libnvmf_context_set_persistent; libnvmf_create_ctrl; - libnvmf_ctrl_get_config; - libnvmf_default_config; + libnvmf_ctrl_get_fabrics_config; libnvmf_disconnect_ctrl; libnvmf_discovery; libnvmf_discovery_args_create; @@ -44,7 +44,6 @@ LIBNVMF_3 { libnvmf_subtype_str; libnvmf_treq_str; libnvmf_trtype_str; - libnvmf_update_config; local: *; }; 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 57697c0811..b3b98a1454 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), @@ -380,7 +386,13 @@ __public int libnvmf_context_set_device(struct libnvmf_context *fctx, const char return 0; } -__public struct libnvme_fabrics_config *libnvmf_ctrl_get_config( +__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; @@ -422,7 +434,8 @@ static const struct libnvme_fabric_options default_supported_options = { static void merge_config(libnvme_ctrl_t c, const struct libnvme_fabrics_config *cfg) { - struct libnvme_fabrics_config *ctrl_cfg = libnvmf_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); @@ -446,9 +459,11 @@ static void merge_config(libnvme_ctrl_t c, #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 = libnvmf_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); @@ -757,7 +772,7 @@ bool traddr_is_hostname(struct libnvme_global_ctx *ctx, static int build_options(libnvme_host_t h, libnvme_ctrl_t c, char **argstr) { - struct libnvme_fabrics_config *cfg = libnvmf_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; @@ -1100,7 +1115,7 @@ __public int libnvmf_add_ctrl(libnvme_host_t h, libnvme_ctrl_t c) if (fc) { const char *key; - merge_config(c, libnvmf_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 @@ -2573,7 +2588,7 @@ __public int libnvmf_config_modify(struct libnvme_global_ctx *ctx, nvme_parse_tls_args(fctx->keyring, fctx->tls_key, fctx->tls_key_identity, &fctx->cfg, c); - libnvmf_update_config(c, &fctx->cfg); + update_config(c, &fctx->cfg); return 0; } diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index f8d4c4f103..95a9749f9b 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -31,49 +31,6 @@ */ struct libnvmf_context; -/** - * 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 { - 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_fabrics_uri - Parsed URI structure * @scheme: Scheme name (typically 'nvme') @@ -195,25 +152,6 @@ 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 @@ -418,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,12 +430,23 @@ int libnvmf_context_set_persistent(struct libnvmf_context *fctx, bool persistent int libnvmf_context_set_device(struct libnvmf_context *fctx, const char *device); /** - * libnvmf_ctrl_get_config() - Fabrics configuration of a controller + * 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_config(libnvme_ctrl_t c); +struct libnvme_fabrics_config *libnvmf_ctrl_get_fabrics_config( + libnvme_ctrl_t c); /** * libnvmf_discovery() - Perform fabrics discovery diff --git a/libnvme/src/nvme/json.c b/libnvme/src/nvme/json.c index 2c4da15c32..6d761ca7b1 100644 --- a/libnvme/src/nvme/json.c +++ b/libnvme/src/nvme/json.c @@ -26,7 +26,7 @@ static void json_update_attributes(libnvme_ctrl_t c, struct json_object *ctrl_obj) { - struct libnvme_fabrics_config *cfg = libnvmf_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, @@ -275,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 = libnvmf_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; @@ -443,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 = libnvmf_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/no-fabrics.c b/libnvme/src/nvme/no-fabrics.c index 1ca6cb358c..0498a9b536 100644 --- a/libnvme/src/nvme/no-fabrics.c +++ b/libnvme/src/nvme/no-fabrics.c @@ -13,6 +13,7 @@ bool traddr_is_hostname(struct libnvme_global_ctx *ctx, { return false; } -__public void libnvmf_default_config(struct libnvme_fabrics_config *cfg) + +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 2247312854..15162e9fe6 100644 --- a/libnvme/src/nvme/private-fabrics.h +++ b/libnvme/src/nvme/private-fabrics.h @@ -10,6 +10,8 @@ #include #include +#include "nvme/private.h" + struct libnvmf_context { struct libnvme_global_ctx *ctx; @@ -83,3 +85,5 @@ struct libnvmf_discovery_args { /*!generate-accessors*/ 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 06120fb042..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; @@ -322,6 +366,8 @@ 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, struct libnvme_ctrl **cp); diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index 2abce54e67..42d025fcd1 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -1046,12 +1046,6 @@ __public void libnvme_free_ctrl(libnvme_ctrl_t c) __libnvme_free_ctrl(c); } -__public void libnvmf_default_config(struct libnvme_fabrics_config *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) { From faa7749876a599fca6e030e55fa054744c991087 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 19:46:31 +0200 Subject: [PATCH 16/17] fabrics: add tls_configured_key to merge/update logic The tls_configured_key_id should also be handled by the merge/update logic. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/fabrics.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index b3b98a1454..06beda1fdc 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -449,6 +449,7 @@ static void merge_config(libnvme_ctrl_t c, MERGE_CFG_OPTION(ctrl_cfg, cfg, tos, -1); 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); @@ -477,6 +478,7 @@ static void update_config(libnvme_ctrl_t c, UPDATE_CFG_OPTION(ctrl_cfg, cfg, tos, -1); 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); From 8cf38754e26a7d0234a361de0b10e06343c4f5e1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 15 Apr 2026 20:13:54 +0200 Subject: [PATCH 17/17] private-fabrics: fix spelling in comment Copolit insist on correct spelling. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/private-fabrics.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnvme/src/nvme/private-fabrics.h b/libnvme/src/nvme/private-fabrics.h index 15162e9fe6..5279399707 100644 --- a/libnvme/src/nvme/private-fabrics.h +++ b/libnvme/src/nvme/private-fabrics.h @@ -41,7 +41,7 @@ struct libnvmf_context { int default_max_discovery_retries; int default_keep_alive_timeout; - /* common fabrics configuraiton */ + /* common fabrics configuration */ const char *device; bool persistent; struct libnvme_fabrics_config cfg;