/
githubmirror
/
nvme-cli
Обзор
Документация
Войти
/
githubmirror
/
nvme-cli
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
libnvme/src/nvme/config.c
356 строк
9 KB
Martin Belanger
nvme: redesign --persistent, remove --epcsd/--no-epcsd
10 авг 2026, 19:27
10 авг 2026, 19:27
745ada2
Код
Авторство
О чём код?
// SPDX-License-Identifier: LGPL-2.1-or-later /* * This file is part of libnvme. * Copyright (c) 2026, Dell Technologies Inc. or its subsidiaries. * * Authors: Martin Belanger <Martin.Belanger@dell.com> */ /* * Public API for NVMe-oF connection configuration. * * Parsing and cascade resolution are internal implementation details. * Files, sections, and drop-ins are not exposed through this interface; * consumers access only the resolved connection list. */ #include <errno.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ccan/list/list.h> #include <compiler-attributes.h> #include <parse-util.h> #include <nvme/config.h> #include <nvme/fabrics.h> #include <nvme/tid.h> #include "config-ini.h" #include "private-fabrics.h" __shr_public int libnvmf_config_read(struct libnvme_global_ctx *ctx, const char *file, struct libnvmf_config **out) { if (!out) return -EINVAL; *out = NULL; if (!ctx) return -EINVAL; return libnvmf_config_load(ctx, file ? file : CONFIG_MAIN_PATH, out); } __shr_public int libnvmf_config_validate(struct libnvme_global_ctx *ctx, const char *file) { struct libnvmf_config *config; int err; if (!ctx) return -EINVAL; err = libnvmf_config_load(ctx, file ? file : CONFIG_MAIN_PATH, &config); libnvmf_config_free(config); return err; } __shr_public void libnvmf_config_conn_for_each( const struct libnvmf_config *config, void (*callback)(const struct libnvmf_config_conn *conn, void *user_data), void *user_data) { const struct libnvmf_config_conn *conn; if (!config || !callback) return; list_for_each(&config->conns, conn, entry) callback(conn, user_data); } __shr_public bool libnvmf_config_conn_is_dc( const struct libnvmf_config_conn *conn) { return conn && conn->is_dc; } __shr_public const char *libnvmf_config_conn_get_transport( const struct libnvmf_config_conn *conn) { return conn ? conn->transport : NULL; } __shr_public const char *libnvmf_config_conn_get_traddr( const struct libnvmf_config_conn *conn) { return conn ? conn->traddr : NULL; } __shr_public const char *libnvmf_config_conn_get_trsvcid( const struct libnvmf_config_conn *conn) { return conn ? conn->trsvcid : NULL; } __shr_public const char *libnvmf_config_conn_get_subsysnqn( const struct libnvmf_config_conn *conn) { return conn ? conn->subsysnqn : NULL; } __shr_public const char *libnvmf_config_conn_get_host_traddr( const struct libnvmf_config_conn *conn) { return conn ? conn->host_traddr : NULL; } __shr_public const char *libnvmf_config_conn_get_host_iface( const struct libnvmf_config_conn *conn) { return conn ? conn->host_iface : NULL; } __shr_public const char *libnvmf_config_conn_get_hostnqn( const struct libnvmf_config_conn *conn) { return conn ? conn->hostnqn : NULL; } __shr_public const char *libnvmf_config_conn_get_hostid( const struct libnvmf_config_conn *conn) { return conn ? conn->hostid : NULL; } __shr_public const struct libnvmf_params *libnvmf_config_conn_get_params( const struct libnvmf_config_conn *conn) { return conn ? conn->params : NULL; } __shr_public const char *libnvmf_config_conn_get_hostsymname( const struct libnvmf_config_conn *conn) { return conn ? conn->hostsymname : NULL; } __shr_public const char *libnvmf_config_conn_get_source( const struct libnvmf_config_conn *conn) { return conn ? conn->source : NULL; } __shr_public const struct libnvmf_params *libnvmf_config_resolve_discovered( const struct libnvmf_config *config, const struct libnvmf_config_conn *via_dc, bool is_dc) { if (!config) return NULL; if (via_dc) return is_dc ? via_dc->dlp_dc_params : via_dc->dlp_ioc_params; return is_dc ? config->top_dc_params : config->top_ioc_params; } struct emit_state { void (*callback)(const char *arg, void *user_data); void *user_data; int err; }; static void emit_arg(struct emit_state *state, const char *key, const char *value) { char *arg; int len; if (state->err) return; if (value) len = asprintf(&arg, "--%s=%s", key, value); else len = asprintf(&arg, "--%s", key); if (len < 0) { state->err = -ENOMEM; return; } state->callback(arg, state->user_data); free(arg); } static void emit_tid_arg(struct emit_state *state, const char *key, const char *value) { if (value) emit_arg(state, key, value); } static void emit_param(const char *key, const char *value, void *user_data) { struct emit_state *state = user_data; const struct libnvmf_key *k; /* A reset parameter is not emitted: the kernel default applies. */ if (state->err || !*value) return; k = libnvmf_key_lookup(key); if (!k) return; if (k->type == LIBNVMF_KEY_BOOL) { bool set; if (shr_parse_bool(value, &set) || !set) return; emit_arg(state, key, NULL); return; } emit_arg(state, key, value); } __shr_public int libnvmf_connect_args_emit(const struct libnvmf_tid *tid, const struct libnvmf_params *params, void (*callback)(const char *arg, void *user_data), void *user_data) { struct emit_state state = { .callback = callback, .user_data = user_data, }; if (!callback) return -EINVAL; if (tid) { emit_tid_arg(&state, "transport", libnvmf_tid_get_transport(tid)); emit_tid_arg(&state, "traddr", libnvmf_tid_get_traddr(tid)); emit_tid_arg(&state, "trsvcid", libnvmf_tid_get_trsvcid(tid)); emit_tid_arg(&state, "nqn", libnvmf_tid_get_subsysnqn(tid)); emit_tid_arg(&state, "host-traddr", libnvmf_tid_get_host_traddr(tid)); emit_tid_arg(&state, "host-iface", libnvmf_tid_get_host_iface(tid)); emit_tid_arg(&state, "hostnqn", libnvmf_tid_get_hostnqn(tid)); emit_tid_arg(&state, "hostid", libnvmf_tid_get_hostid(tid)); } if (params) libnvmf_params_for_each(params, emit_param, &state); return state.err; } struct apply_state { struct libnvmf_context *fctx; }; static void apply_param(const char *key, const char *value, void *user_data) { struct apply_state *state = user_data; struct libnvmf_context *fctx = state->fctx; struct libnvme_fabrics_config *cfg = &fctx->ctrl_params.cfg; bool bval; /* An explicit reset (the empty string) is left unapplied -- @cfg * keeps whatever it already had. That's usually zero; a couple of * fields get a library-chosen default from libnvmf_default_config() * instead, not anything from the kernel. */ if (!*value) return; /* base 0 matches check_int()'s parsing in config-ini.c. */ if (!strcmp(key, "nr-io-queues")) cfg->nr_io_queues = strtol(value, NULL, 0); else if (!strcmp(key, "nr-write-queues")) cfg->nr_write_queues = strtol(value, NULL, 0); else if (!strcmp(key, "nr-poll-queues")) cfg->nr_poll_queues = strtol(value, NULL, 0); else if (!strcmp(key, "queue-size")) cfg->queue_size = strtol(value, NULL, 0); else if (!strcmp(key, "keep-alive-tmo")) /* Applied verbatim; set_discovery_kato() may still * override it at connect time for persistent discovery * controllers. */ cfg->keep_alive_tmo = strtol(value, NULL, 0); else if (!strcmp(key, "reconnect-delay")) cfg->reconnect_delay = strtol(value, NULL, 0); else if (!strcmp(key, "ctrl-loss-tmo")) cfg->ctrl_loss_tmo = strtol(value, NULL, 0); else if (!strcmp(key, "fast-io-fail-tmo")) cfg->fast_io_fail_tmo = strtol(value, NULL, 0); else if (!strcmp(key, "tos")) cfg->tos = strtol(value, NULL, 0); else if (!strcmp(key, "duplicate-connect")) { if (!shr_parse_bool(value, &bval)) cfg->duplicate_connect = bval; } else if (!strcmp(key, "disable-sqflow")) { if (!shr_parse_bool(value, &bval)) cfg->disable_sqflow = bval; } else if (!strcmp(key, "hdr-digest")) { if (!shr_parse_bool(value, &bval)) cfg->hdr_digest = bval; } else if (!strcmp(key, "data-digest")) { if (!shr_parse_bool(value, &bval)) cfg->data_digest = bval; } else if (!strcmp(key, "tls")) { if (!shr_parse_bool(value, &bval)) cfg->tls = bval; } else if (!strcmp(key, "concat")) { if (!shr_parse_bool(value, &bval)) cfg->concat = bval; } else if (!strcmp(key, "persistent")) { libnvmf_context_set_persistent(fctx, value); } /* Identity/addressing and crypto keys never reach here -- only * tunable keys are handled in this loop. Crypto keys are read * directly in libnvmf_context_apply_params(), via * libnvmf_config_conn_get_params(). */ } /* Same "an explicit reset is left unapplied" rule apply_param() uses for * the tunable keys, applied here to a direct libnvmf_params_get() lookup. */ static const char *get_param_nonempty(const struct libnvmf_params *params, const char *key) { const char *value = libnvmf_params_get(params, key); return (value && *value) ? value : NULL; } __shr_public int libnvmf_context_apply_params(struct libnvmf_context *fctx, const struct libnvmf_params *params) { struct apply_state state = { .fctx = fctx }; const char *hostkey, *ctrlkey, *keyring, *tls_key, *tls_key_identity; if (!fctx || !params) return -EINVAL; libnvmf_params_for_each(params, apply_param, &state); hostkey = get_param_nonempty(params, "dhchap-secret"); ctrlkey = get_param_nonempty(params, "dhchap-ctrl-secret"); keyring = get_param_nonempty(params, "keyring"); tls_key = get_param_nonempty(params, "tls-key"); tls_key_identity = get_param_nonempty(params, "tls-key-identity"); if (hostkey || ctrlkey || keyring || tls_key || tls_key_identity) return libnvmf_context_set_crypto(fctx, hostkey, ctrlkey, keyring, tls_key, tls_key_identity); return 0; }