diff --git a/.gitignore b/.gitignore index b2931c7..441fe03 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/nvme-cli-2.4.tar.gz +SOURCES/nvme-cli-2.6.tar.gz diff --git a/.nvme-cli.metadata b/.nvme-cli.metadata index 655c240..d9f8a67 100644 --- a/.nvme-cli.metadata +++ b/.nvme-cli.metadata @@ -1 +1 @@ -6583ee6fa9f715cbff11dd40aae7417e9e791691 SOURCES/nvme-cli-2.4.tar.gz +01d2a5755d0d251eafeeefad27e739353f9e0f12 SOURCES/nvme-cli-2.6.tar.gz diff --git a/SOURCES/0001-nbft-make-lookup_ctrl-function-public.patch b/SOURCES/0001-nbft-make-lookup_ctrl-function-public.patch deleted file mode 100644 index b0ff508..0000000 --- a/SOURCES/0001-nbft-make-lookup_ctrl-function-public.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 34c197e0ac2d57734ab775f00b2d0758aca7b82f Mon Sep 17 00:00:00 2001 -From: John Meneghini -Date: Fri, 14 Apr 2023 10:53:58 -0400 -Subject: [PATCH] nbft: make lookup_ctrl function public - -To prepare for the addition of nbft functionality fixup the fabrics -declarations. - -Signed-off-by: John Meneghini ---- - fabrics.c | 12 ++---------- - fabrics.h | 10 ++++++++++ - 2 files changed, 12 insertions(+), 10 deletions(-) - -diff --git a/fabrics.c b/fabrics.c -index f8078e59..80827b16 100644 ---- a/fabrics.c -+++ b/fabrics.c -@@ -43,6 +43,7 @@ - #include "libnvme.h" - #include "nvme-print.h" - #include "nvme-print-json.h" -+#include "fabrics.h" - - #define PATH_NVMF_DISC SYSCONFDIR "/nvme/discovery.conf" - #define PATH_NVMF_CONFIG SYSCONFDIR "/nvme/config.json" -@@ -110,15 +111,6 @@ static const char *nvmf_config_file = "Use specified JSON configuration file or - OPT_FLAG("data-digest", 'G', &c.data_digest, nvmf_data_digest), \ - OPT_FLAG("tls", 0, &c.tls, nvmf_tls) \ - --struct tr_config { -- const char *subsysnqn; -- const char *transport; -- const char *traddr; -- const char *host_traddr; -- const char *host_iface; -- const char *trsvcid; --}; -- - /* - * Compare two C strings and handle NULL pointers gracefully. - * If either of the two strings is NULL, return 0 -@@ -202,7 +194,7 @@ static nvme_ctrl_t lookup_discovery_ctrl(nvme_root_t r, struct tr_config *trcfg) - return __lookup_ctrl(r, trcfg, disc_ctrl_config_match); - } - --static nvme_ctrl_t lookup_ctrl(nvme_root_t r, struct tr_config *trcfg) -+nvme_ctrl_t lookup_ctrl(nvme_root_t r, struct tr_config *trcfg) - { - return __lookup_ctrl(r, trcfg, ctrl_config_match); - } -diff --git a/fabrics.h b/fabrics.h -index d1e16fc5..02cebf5d 100644 ---- a/fabrics.h -+++ b/fabrics.h -@@ -2,6 +2,16 @@ - #ifndef _FABRICS_H - #define _FABRICS_H - -+struct tr_config { -+ const char *subsysnqn; -+ const char *transport; -+ const char *traddr; -+ const char *host_traddr; -+ const char *host_iface; -+ const char *trsvcid; -+}; -+ -+extern nvme_ctrl_t lookup_ctrl(nvme_root_t r, struct tr_config *trcfg); - extern int nvmf_discover(const char *desc, int argc, char **argv, bool connect); - extern int nvmf_connect(const char *desc, int argc, char **argv); - extern int nvmf_disconnect(const char *desc, int argc, char **argv); --- -2.39.1 - diff --git a/SOURCES/0001-udev-rules-set-ctrl_loss_tmo-to-1-for-ONTAP-NVMe-TCP.patch b/SOURCES/0001-udev-rules-set-ctrl_loss_tmo-to-1-for-ONTAP-NVMe-TCP.patch new file mode 100644 index 0000000..327cc85 --- /dev/null +++ b/SOURCES/0001-udev-rules-set-ctrl_loss_tmo-to-1-for-ONTAP-NVMe-TCP.patch @@ -0,0 +1,29 @@ +From 0782167f3a6709df232b746cdfa2a036c6207f7f Mon Sep 17 00:00:00 2001 +From: Martin George +Date: Tue, 3 Oct 2023 16:05:23 +0530 +Subject: [PATCH] udev-rules: set ctrl_loss_tmo to -1 for ONTAP NVMe/TCP + +Setting ctrl_loss_tmo to -1 for ONTAP NVMe/TCP controllers would enable +indefinite reconnect attempts during a path loss and help avoid purging +the path on the host, which otherwise may lead to mounted fs read-only +behavior. So add a rule towards enabling the same. + +Signed-off-by: Martin George +--- + nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in b/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in +index 299fe2251418..99b6a8ba0bf8 100644 +--- a/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in ++++ b/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in +@@ -1,3 +1,6 @@ + # Enable round-robin for NetApp ONTAP and NetApp E-Series + ACTION=="add", SUBSYSTEM=="nvme-subsystem", ATTR{subsystype}=="nvm", ATTR{model}=="NetApp ONTAP Controller", ATTR{iopolicy}="round-robin" + ACTION=="add", SUBSYSTEM=="nvme-subsystem", ATTR{subsystype}=="nvm", ATTR{model}=="NetApp E-Series", ATTR{iopolicy}="round-robin" ++ ++# Set ctrl_loss_tmo to -1 for NetApp ONTAP NVMe/TCP ++ACTION!="remove", SUBSYSTEM=="nvme", KERNEL=="nvme*", ATTR{transport}=="tcp", ATTR{model}=="NetApp ONTAP Controller", ATTR{ctrl_loss_tmo}="-1" +-- +2.39.3 + diff --git a/SOURCES/0002-nbft-added-NBFT-v1.0-table-support.patch b/SOURCES/0002-nbft-added-NBFT-v1.0-table-support.patch deleted file mode 100644 index 8c7dcb0..0000000 --- a/SOURCES/0002-nbft-added-NBFT-v1.0-table-support.patch +++ /dev/null @@ -1,451 +0,0 @@ -From a71a08532b5f06ee19ee2ff118a23cec4ecb6719 Mon Sep 17 00:00:00 2001 -From: Stuart Hayes -Date: Wed, 15 Jun 2022 11:42:50 -0500 -Subject: [PATCH] nbft: added NBFT v1.0 table support - -Added support for parsing the contents of the NBFT table (per NVMe-oF -boot specification v1.0) with the connect-all and discover commands. - -nvme discover/connect-all --nbft ignore /etc/nvme config and use NBFT tables -nvme discover/connect-all --no-nbft ignore NBFT tables and use /etc/nvme config -nvme discover/connect-all --nbft-path= user-defined path for NBFT tables - -Signed-off-by: Stuart Hayes -Signed-off-by: Martin Belanger - -Use the new nbft public API. - -Signed-off-by: Tomas Bzatek -Signed-off-by: Martin Wilck -Signed-off-by: John Meneghini ---- - Documentation/nvme-connect-all.txt | 25 ++++ - Documentation/nvme-discover.txt | 27 +++- - fabrics.c | 17 +++ - meson.build | 1 + - nbft.c | 202 +++++++++++++++++++++++++++++ - nbft.h | 19 +++ - 6 files changed, 290 insertions(+), 1 deletion(-) - create mode 100644 nbft.c - create mode 100644 nbft.h - -diff --git a/Documentation/nvme-connect-all.txt b/Documentation/nvme-connect-all.txt -index 44bb4f94..cbb7ca6c 100644 ---- a/Documentation/nvme-connect-all.txt -+++ b/Documentation/nvme-connect-all.txt -@@ -35,6 +35,9 @@ SYNOPSIS - [--tls ] - [--quiet | -S] - [--dump-config | -O] -+ [--nbft] -+ [--no-nbft] -+ [--nbft-path=] - - DESCRIPTION - ----------- -@@ -198,6 +201,16 @@ OPTIONS - --dump-config:: - Print out resulting JSON configuration file to stdout. - -+--nbft:: -+ Only look at NBFT tables -+ -+--no-nbft:: -+ Do not look at NBFT tables -+ -+--nbft-path=:: -+ Use a user-defined path to the NBFT tables -+ -+ - - EXAMPLES - -------- -@@ -210,6 +223,18 @@ the RDMA network. Port 4420 is used by default: - --hostnqn=host1-rogue-nqn - ------------ - + -+* Issue a 'nvme connect-all' command using the default system defined NBFT tables: -++ -+----------- -+# nvme connect-all --nbft -+------------ -++ -+* Issue a 'nvme connect-all' command with a user-defined path for the NBFT table: -++ -+----------- -+# nvme connet-all --nbft-path=/sys/firmware/acpi/tables/NBFT1 -+------------ -++ - * Issue a 'nvme connect-all' command using a @SYSCONFDIR@/nvme/discovery.conf file: - + - ----------- -diff --git a/Documentation/nvme-discover.txt b/Documentation/nvme-discover.txt -index d4df75c2..b040c688 100644 ---- a/Documentation/nvme-discover.txt -+++ b/Documentation/nvme-discover.txt -@@ -37,6 +37,9 @@ SYNOPSIS - [--dump-config | -O] - [--output-format= | -o ] - [--force] -+ [--nbft] -+ [--no-nbft] -+ [--nbft-path=] - - DESCRIPTION - ----------- -@@ -68,7 +71,7 @@ Note that the base NVMe specification defines the NQN (NVMe Qualified - Name) format which an NVMe endpoint (device, subsystem, etc) must - follow to guarantee a unique name under the NVMe standard. - In particular, the Host NQN uniquely identifies the NVMe Host, and --may be used by the the Discovery Controller to control what NVMe Target -+may be used by the Discovery Controller to control what NVMe Target - resources are allocated to the NVMe Host for a connection. - - A Discovery Controller has it's own NQN defined in the NVMe-over-Fabrics -@@ -229,6 +232,16 @@ OPTIONS - Combined with --persistent flag, always create new - persistent discovery connection. - -+--nbft:: -+ Only look at NBFT tables -+ -+--no-nbft:: -+ Do not look at NBFT tables -+ -+--nbft-path=:: -+ Use a user-defined path to the NBFT tables -+ -+ - EXAMPLES - -------- - * Query the Discover Controller with IP4 address 192.168.1.3 for all -@@ -240,6 +253,18 @@ Port 4420 is used by default: - --hostnqn=host1-rogue-nqn - ------------ - + -+* Issue a 'nvme discover' command using the default system defined NBFT tables: -++ -+----------- -+# nvme discover --nbft -+------------ -++ -+* Issue a 'nvme discover' command with a user-defined path for the NBFT table: -++ -+----------- -+# nvme discover --nbft-path=/sys/firmware/acpi/tables/NBFT1 -+------------ -++ - * Issue a 'nvme discover' command using a @SYSCONFDIR@/nvme/discovery.conf file: - + - ----------- -diff --git a/fabrics.c b/fabrics.c -index 80827b16..0edbd299 100644 ---- a/fabrics.c -+++ b/fabrics.c -@@ -40,6 +40,7 @@ - - #include "common.h" - #include "nvme.h" -+#include "nbft.h" - #include "libnvme.h" - #include "nvme-print.h" - #include "nvme-print-json.h" -@@ -710,6 +711,7 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) - { - char *subsysnqn = NVME_DISC_SUBSYS_NAME; - char *hostnqn = NULL, *hostid = NULL, *hostkey = NULL; -+ char *hostnqn_arg, *hostid_arg; - char *transport = NULL, *traddr = NULL, *trsvcid = NULL; - char *config_file = PATH_NVMF_CONFIG; - char *hnqn = NULL, *hid = NULL; -@@ -724,6 +726,8 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) - char *device = NULL; - bool force = false; - bool json_config = false; -+ bool nbft = false, nonbft = false; -+ char *nbft_path = NBFT_SYSFS_PATH; - - OPT_ARGS(opts) = { - OPT_STRING("device", 'd', "DEV", &device, "use existing discovery controller device"), -@@ -736,6 +740,9 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) - OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"), - OPT_FLAG("dump-config", 'O', &dump_config, "Dump configuration file to stdout"), - OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"), -+ OPT_FLAG("nbft", 0, &nbft, "Only look at NBFT tables"), -+ OPT_FLAG("no-nbft", 0, &nonbft, "Do not look at NBFT tables"), -+ OPT_STRING("nbft-path", 0, "STR", &nbft_path, "user-defined path for NBFT tables"), - OPT_END() - }; - -@@ -768,6 +775,8 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) - if (!nvme_read_config(r, config_file)) - json_config = true; - -+ hostnqn_arg = hostnqn; -+ hostid_arg = hostid; - if (!hostnqn) - hostnqn = hnqn = nvmf_hostnqn_from_file(); - if (!hostnqn) -@@ -789,6 +798,14 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) - nvme_host_set_dhchap_key(h, hostkey); - - if (!device && !transport && !traddr) { -+ if (!nonbft) -+ discover_from_nbft(r, hostnqn_arg, hostid_arg, -+ hostnqn, hostid, desc, connect, -+ &cfg, nbft_path, flags, verbose); -+ -+ if (nbft) -+ goto out_free; -+ - if (json_config) - ret = discover_from_json_config_file(r, h, desc, - connect, &cfg, -diff --git a/meson.build b/meson.build -index 43ce5f9b..7ec357a9 100644 ---- a/meson.build -+++ b/meson.build -@@ -240,6 +240,7 @@ incdir = include_directories(['ccan']) - - ################################################################################ - sources = [ -+ 'nbft.c', - 'fabrics.c', - 'nvme.c', - 'nvme-models.c', -diff --git a/nbft.c b/nbft.c -new file mode 100644 -index 00000000..14347287 ---- /dev/null -+++ b/nbft.c -@@ -0,0 +1,202 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+#include -+#include -+#include -+ -+#include "nvme.h" -+#include "nbft.h" -+#include "libnvme.h" -+#include "fabrics.h" -+ -+#define NBFT_SYSFS_FILENAME "NBFT*" -+ -+static void print_connect_msg(nvme_ctrl_t c) -+{ -+ printf("device: %s\n", nvme_ctrl_get_name(c)); -+} -+ -+static void json_connect_msg(nvme_ctrl_t c) -+{ -+ struct json_object *root; -+ -+ root = json_create_object(); -+ json_object_add_value_string(root, "device", nvme_ctrl_get_name(c)); -+ -+ json_print_object(root, NULL); -+ printf("\n"); -+ json_free_object(root); -+} -+ -+int nbft_filter(const struct dirent *dent) -+{ -+ return !fnmatch(NBFT_SYSFS_FILENAME, dent->d_name, FNM_PATHNAME); -+} -+ -+int read_nbft_files(struct list_head *nbft_list, char *path) -+{ -+ struct dirent **dent; -+ char filename[PATH_MAX]; -+ int i, count, ret; -+ struct nbft_file_entry *entry; -+ struct nbft_info *nbft; -+ -+ count = scandir(path, &dent, nbft_filter, NULL); -+ if (count < 0) { -+ fprintf(stderr, "Failed to open %s.\n", path); -+ return -1; -+ } -+ -+ for (i = 0; i < count; i++) { -+ snprintf(filename, sizeof(filename), "%s/%s", path, dent[i]->d_name); -+ ret = nvme_nbft_read(&nbft, filename); -+ if (!ret) { -+ entry = calloc(1, sizeof(*entry)); -+ entry->nbft = nbft; -+ list_add_tail(nbft_list, &entry->node); -+ } -+ free(dent[i]); -+ } -+ free(dent); -+ return 0; -+} -+ -+void free_nbfts(struct list_head *nbft_list) -+{ -+ struct nbft_file_entry *entry; -+ -+ while ((entry = list_pop(nbft_list, struct nbft_file_entry, node))) { -+ nvme_nbft_free(entry->nbft); -+ free(entry); -+ } -+} -+ -+int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, -+ char *hostnqn_sys, char *hostid_sys, -+ const char *desc, bool connect, -+ const struct nvme_fabrics_config *cfg, char *nbft_path, -+ enum nvme_print_flags flags, bool verbose) -+{ -+ char *hostnqn = NULL, *hostid = NULL, *host_traddr = NULL; -+ nvme_host_t h; -+ nvme_ctrl_t c; -+ int ret, i; -+ struct list_head nbft_list; -+ struct nbft_file_entry *entry; -+ struct nbft_info_subsystem_ns **ss; -+ struct nbft_info_hfi *hfi; -+ -+ if (!connect) -+ /* to do: print discovery-type info from NBFT tables */ -+ return 0; -+ -+ list_head_init(&nbft_list); -+ ret = read_nbft_files(&nbft_list, nbft_path); -+ if (ret) -+ goto out_free_2; -+ -+ list_for_each(&nbft_list, entry, node) -+ for (ss = entry->nbft->subsystem_ns_list; ss && *ss; ss++) -+ for (i = 0; i < (*ss)->num_hfis; i++) { -+ nvme_ctrl_t cl; -+ -+ hfi = (*ss)->hfis[i]; -+ if (hostnqn_arg) -+ hostnqn = hostnqn_arg; -+ else { -+ hostnqn = entry->nbft->host.nqn; -+ if (!hostnqn) -+ hostnqn = hostnqn_sys; -+ } -+ -+ if (hostid_arg) -+ hostid = hostid_arg; -+ else if (*entry->nbft->host.id) { -+ hostid = (char *)util_uuid_to_string(entry->nbft->host.id); -+ if (!hostid) -+ hostid = hostid_sys; -+ } -+ -+ h = nvme_lookup_host(r, hostnqn, hostid); -+ if (!h) { -+ errno = ENOMEM; -+ goto out_free; -+ } -+ -+ if (!cfg->host_traddr) { -+ host_traddr = NULL; -+ if (!strncmp((*ss)->transport, "tcp", 3)) -+ host_traddr = hfi->tcp_info.ipaddr; -+ } -+ -+ struct tr_config trcfg = { -+ .subsysnqn = (*ss)->subsys_nqn, -+ .transport = (*ss)->transport, -+ .traddr = (*ss)->traddr, -+ .host_traddr = host_traddr, -+ .host_iface = NULL, -+ .trsvcid = (*ss)->trsvcid, -+ }; -+ -+ /* Already connected ? */ -+ cl = lookup_ctrl(r, &trcfg); -+ if (cl && nvme_ctrl_get_name(cl)) -+ continue; -+ -+ c = nvme_create_ctrl(r, (*ss)->subsys_nqn, (*ss)->transport, -+ (*ss)->traddr, host_traddr, NULL, -+ (*ss)->trsvcid); -+ if (!c) { -+ errno = ENOMEM; -+ goto out_free; -+ } -+ -+ errno = 0; -+ ret = nvmf_add_ctrl(h, c, cfg); -+ -+ /* -+ * With TCP/DHCP, it can happen that the OS -+ * obtains a different local IP address than the -+ * firmware had. Retry without host_traddr. -+ */ -+ if (ret == -1 && errno == ENVME_CONNECT_WRITE && -+ !strcmp((*ss)->transport, "tcp") && -+ strlen(hfi->tcp_info.dhcp_server_ipaddr) > 0) { -+ nvme_free_ctrl(c); -+ -+ trcfg.host_traddr = NULL; -+ cl = lookup_ctrl(r, &trcfg); -+ if (cl && nvme_ctrl_get_name(cl)) -+ continue; -+ -+ c = nvme_create_ctrl(r, (*ss)->subsys_nqn, (*ss)->transport, -+ (*ss)->traddr, -+ NULL, NULL, (*ss)->trsvcid); -+ if (!c) { -+ errno = ENOMEM; -+ goto out_free; -+ } -+ errno = 0; -+ ret = nvmf_add_ctrl(h, c, cfg); -+ if (ret == 0 && verbose >= 1) -+ fprintf(stderr, -+ "connect with host_traddr=\"%s\" failed, success after omitting host_traddr\n", -+ host_traddr); -+ } -+ -+ if (ret) -+ fprintf(stderr, "no controller found\n"); -+ else { -+ if (flags == NORMAL) -+ print_connect_msg(c); -+ else if (flags == JSON) -+ json_connect_msg(c); -+ } -+out_free: -+ if (errno == ENOMEM) -+ goto out_free_2; -+ } -+out_free_2: -+ free_nbfts(&nbft_list); -+ return errno; -+} -diff --git a/nbft.h b/nbft.h -new file mode 100644 -index 00000000..0e09733f ---- /dev/null -+++ b/nbft.h -@@ -0,0 +1,19 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include -+ -+#define NBFT_SYSFS_PATH "/sys/firmware/acpi/tables" -+ -+struct nbft_file_entry { -+ struct list_node node; -+ struct nbft_info *nbft; -+}; -+ -+int read_nbft_files(struct list_head *nbft_list, char *path); -+void free_nbfts(struct list_head *nbft_list); -+ -+extern int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, -+ char *hostnqn_sys, char *hostid_sys, -+ const char *desc, bool connect, -+ const struct nvme_fabrics_config *cfg, char *nbft_path, -+ enum nvme_print_flags flags, bool verbose); --- -2.39.1 - diff --git a/SOURCES/0002-udev-rules-rename-netapp-udev-rule.patch b/SOURCES/0002-udev-rules-rename-netapp-udev-rule.patch new file mode 100644 index 0000000..33650fb --- /dev/null +++ b/SOURCES/0002-udev-rules-rename-netapp-udev-rule.patch @@ -0,0 +1,50 @@ +From 748a9ac050fb443b1204d06ce3b5b129b6a8afe2 Mon Sep 17 00:00:00 2001 +From: Martin George +Date: Thu, 5 Oct 2023 12:12:46 +0530 +Subject: [PATCH] udev-rules: rename netapp udev rule + +Rename 71-nvmf-iopolicy-netapp.rules.in to 71-nvmf-netapp.rules.in +so as to make the name generic, since this not only sets the +iopolicy here but also modifies the ctrl_loss_tmo. + +Signed-off-by: Martin George +--- + meson.build | 2 +- + nvme.spec.in | 2 +- + ...71-nvmf-iopolicy-netapp.rules.in => 71-nvmf-netapp.rules.in} | 0 + 3 files changed, 2 insertions(+), 2 deletions(-) + rename nvmf-autoconnect/udev-rules/{71-nvmf-iopolicy-netapp.rules.in => 71-nvmf-netapp.rules.in} (100%) + +diff --git a/meson.build b/meson.build +index 3d3fb08541ff..310ba1f83400 100644 +--- a/meson.build ++++ b/meson.build +@@ -236,7 +236,7 @@ endforeach + + udev_files = [ + '70-nvmf-autoconnect.rules', +- '71-nvmf-iopolicy-netapp.rules', ++ '71-nvmf-netapp.rules', + ] + + foreach file : udev_files +diff --git a/nvme.spec.in b/nvme.spec.in +index fe4675a7bb0b..3eab9ff030ff 100644 +--- a/nvme.spec.in ++++ b/nvme.spec.in +@@ -31,7 +31,7 @@ touch %{buildroot}@SYSCONFDIR@/nvme/hostid + @SYSCONFDIR@/nvme/discovery.conf + %ghost @SYSCONFDIR@/nvme/config.json + @UDEVRULESDIR@/70-nvmf-autoconnect.rules +-@UDEVRULESDIR@/71-nvmf-iopolicy-netapp.rules ++@UDEVRULESDIR@/71-nvmf-netapp.rules + @DRACUTRILESDIR@/70-nvmf-autoconnect.conf + @SYSTEMDDIR@/nvmf-connect@.service + @SYSTEMDDIR@/nvmefc-boot-connections.service +diff --git a/nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in b/nvmf-autoconnect/udev-rules/71-nvmf-netapp.rules.in +similarity index 100% +rename from nvmf-autoconnect/udev-rules/71-nvmf-iopolicy-netapp.rules.in +rename to nvmf-autoconnect/udev-rules/71-nvmf-netapp.rules.in +-- +2.39.3 + diff --git a/SOURCES/0003-Revert-fabrics-Use-corresponding-hostid-when-hostnqn.patch b/SOURCES/0003-Revert-fabrics-Use-corresponding-hostid-when-hostnqn.patch new file mode 100644 index 0000000..fbb6d05 --- /dev/null +++ b/SOURCES/0003-Revert-fabrics-Use-corresponding-hostid-when-hostnqn.patch @@ -0,0 +1,92 @@ +From 5f872e9c1689078bf2c4e33108c1514da1a91497 Mon Sep 17 00:00:00 2001 +From: Maurizio Lombardi +Date: Mon, 13 Nov 2023 10:49:35 +0100 +Subject: [PATCH] Revert "fabrics: Use corresponding hostid when hostnqn is + generated" + +This reverts commit 7d1c18f581e489e0cedfd9991bc97a2f8239cf82. +--- + fabrics.c | 47 ++--------------------------------------------- + 1 file changed, 2 insertions(+), 45 deletions(-) + +diff --git a/fabrics.c b/fabrics.c +index 57ca927fce9a..f4fb63f0c555 100644 +--- a/fabrics.c ++++ b/fabrics.c +@@ -616,43 +616,6 @@ static int nvme_read_volatile_config(nvme_root_t r) + return ret; + } + +-char *nvmf_hostid_from_hostnqn(const char *hostnqn) +-{ +- const char *uuid; +- +- if (!hostnqn) +- return NULL; +- +- uuid = strstr(hostnqn, "uuid:"); +- if (!uuid) +- return NULL; +- +- return strdup(uuid + strlen("uuid:")); +-} +- +-void nvmf_check_hostid_and_hostnqn(const char *hostid, const char *hostnqn) +-{ +- char *hostid_from_file, *hostid_from_hostnqn; +- +- if (!hostid) +- return; +- +- hostid_from_file = nvmf_hostid_from_file(); +- if (hostid_from_file && strcmp(hostid_from_file, hostid)) { +- fprintf(stderr, "warning: use generated hostid instead of hostid file\n"); +- free(hostid_from_file); +- } +- +- if (!hostnqn) +- return; +- +- hostid_from_hostnqn = nvmf_hostid_from_hostnqn(hostnqn); +- if (hostid_from_hostnqn && strcmp(hostid_from_hostnqn, hostid)) { +- fprintf(stderr, "warning: use hostid which does not match uuid in hostnqn\n"); +- free(hostid_from_hostnqn); +- } +-} +- + int nvmf_discover(const char *desc, int argc, char **argv, bool connect) + { + char *subsysnqn = NVME_DISC_SUBSYS_NAME; +@@ -729,13 +692,10 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) + hostid_arg = hostid; + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_from_file(); +- if (!hostnqn) { ++ if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_generate(); +- hostid = hid = nvmf_hostid_from_hostnqn(hostnqn); +- } + if (!hostid) + hostid = hid = nvmf_hostid_from_file(); +- nvmf_check_hostid_and_hostnqn(hostid, hostnqn); + h = nvme_lookup_host(r, hostnqn, hostid); + if (!h) { + ret = ENOMEM; +@@ -946,13 +906,10 @@ int nvmf_connect(const char *desc, int argc, char **argv) + + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_from_file(); +- if (!hostnqn) { ++ if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_generate(); +- hostid = hid = nvmf_hostid_from_hostnqn(hostnqn); +- } + if (!hostid) + hostid = hid = nvmf_hostid_from_file(); +- nvmf_check_hostid_and_hostnqn(hostid, hostnqn); + h = nvme_lookup_host(r, hostnqn, hostid); + if (!h) { + errno = ENOMEM; +-- +2.39.3 + diff --git a/SOURCES/0003-nbft-add-the-nbft-show-plugin.patch b/SOURCES/0003-nbft-add-the-nbft-show-plugin.patch deleted file mode 100644 index 8ce3ad6..0000000 --- a/SOURCES/0003-nbft-add-the-nbft-show-plugin.patch +++ /dev/null @@ -1,640 +0,0 @@ -From 23daeedc53be9b5225cc6806434888c0a7a8e9bf Mon Sep 17 00:00:00 2001 -From: Stuart Hayes -Date: Fri, 14 Apr 2023 22:01:07 -0400 -Subject: [PATCH] nbft: add the nbft show plugin - -Display contents of the ACPI NBFT files. - -Usage: nvme nbft show [OPTIONS] - -Options: - [ --output-format=, -o ] --- Output format: normal|json - [ --subsystem, -s ] --- show NBFT subsystems - [ --hfi, -H ] --- show NBFT HFIs - [ --discovery, -d ] --- show NBFT discovery controllers - [ --nbft-path= ] --- user-defined path for NBFT tables - -Signed-off-by: Stuart Hayes -Signed-off-by: Martin Wilck -Signed-off-by: John Meneghini ---- - plugins/meson.build | 1 + - plugins/nbft/nbft-plugin.c | 568 +++++++++++++++++++++++++++++++++++++ - plugins/nbft/nbft-plugin.h | 18 ++ - 3 files changed, 587 insertions(+) - create mode 100644 plugins/nbft/nbft-plugin.c - create mode 100644 plugins/nbft/nbft-plugin.h - -diff --git a/plugins/meson.build b/plugins/meson.build -index 2cf2486f..38b7cded 100644 ---- a/plugins/meson.build -+++ b/plugins/meson.build -@@ -12,6 +12,7 @@ if json_c_dep.found() - 'plugins/intel/intel-nvme.c', - 'plugins/memblaze/memblaze-nvme.c', - 'plugins/micron/micron-nvme.c', -+ 'plugins/nbft/nbft-plugin.c', - 'plugins/netapp/netapp-nvme.c', - 'plugins/nvidia/nvidia-nvme.c', - 'plugins/scaleflux/sfx-nvme.c', -diff --git a/plugins/nbft/nbft-plugin.c b/plugins/nbft/nbft-plugin.c -new file mode 100644 -index 00000000..6ae2525a ---- /dev/null -+++ b/plugins/nbft/nbft-plugin.c -@@ -0,0 +1,568 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+#include -+#include -+#include -+ -+#include "nvme-print.h" -+#include "nvme.h" -+#include "nbft.h" -+#include "libnvme.h" -+#include "fabrics.h" -+ -+#define CREATE_CMD -+#include "nbft-plugin.h" -+ -+static const char dash[100] = {[0 ... 98] = '-', [99] = '\0'}; -+ -+#define PCI_SEGMENT(sbdf) ((sbdf & 0xffff0000) >> 16) -+#define PCI_BUS(sbdf) ((sbdf & 0x0000ff00) >> 8) -+#define PCI_DEV(sbdf) ((sbdf & 0x000000f8) >> 3) -+#define PCI_FUNC(sbdf) ((sbdf & 0x00000007) >> 0) -+ -+static const char *pci_sbdf_to_string(__u16 pci_sbdf) -+{ -+ static char pcidev[13]; -+ -+ snprintf(pcidev, sizeof(pcidev), "%x:%x:%x.%x", -+ PCI_SEGMENT(pci_sbdf), -+ PCI_BUS(pci_sbdf), -+ PCI_DEV(pci_sbdf), -+ PCI_FUNC(pci_sbdf)); -+ return pcidev; -+} -+ -+static char *mac_addr_to_string(unsigned char mac_addr[6]) -+{ -+ static char mac_string[18]; -+ -+ snprintf(mac_string, sizeof(mac_string), "%02x:%02x:%02x:%02x:%02x:%02x", -+ mac_addr[0], -+ mac_addr[1], -+ mac_addr[2], -+ mac_addr[3], -+ mac_addr[4], -+ mac_addr[5]); -+ return mac_string; -+} -+ -+static json_object *hfi_to_json(struct nbft_info_hfi *hfi) -+{ -+ struct json_object *hfi_json; -+ -+ hfi_json = json_create_object(); -+ if (!hfi_json) -+ return NULL; -+ -+ if (json_object_add_value_int(hfi_json, "index", hfi->index) -+ || json_object_add_value_string(hfi_json, "transport", hfi->transport)) -+ goto fail; -+ -+ if (strcmp(hfi->transport, "tcp") == 0) { -+ if (json_object_add_value_string(hfi_json, "pcidev", -+ pci_sbdf_to_string(hfi->tcp_info.pci_sbdf)) -+ || json_object_add_value_string(hfi_json, "mac_addr", -+ mac_addr_to_string(hfi->tcp_info.mac_addr)) -+ || json_object_add_value_int(hfi_json, "vlan", -+ hfi->tcp_info.vlan) -+ || json_object_add_value_int(hfi_json, "ip_origin", -+ hfi->tcp_info.ip_origin) -+ || json_object_add_value_string(hfi_json, "ipaddr", -+ hfi->tcp_info.ipaddr) -+ || json_object_add_value_int(hfi_json, "subnet_mask_prefix", -+ hfi->tcp_info.subnet_mask_prefix) -+ || json_object_add_value_string(hfi_json, "gateway_ipaddr", -+ hfi->tcp_info.gateway_ipaddr) -+ || json_object_add_value_int(hfi_json, "route_metric", -+ hfi->tcp_info.route_metric) -+ || json_object_add_value_string(hfi_json, "primary_dns_ipaddr", -+ hfi->tcp_info.primary_dns_ipaddr) -+ || json_object_add_value_string(hfi_json, "secondary_dns_ipaddr", -+ hfi->tcp_info.secondary_dns_ipaddr) -+ || json_object_add_value_string(hfi_json, "dhcp_server_ipaddr", -+ hfi->tcp_info.dhcp_server_ipaddr) -+ || (hfi->tcp_info.host_name -+ && json_object_add_value_string(hfi_json, "host_name", -+ hfi->tcp_info.host_name)) -+ || json_object_add_value_int(hfi_json, "this_hfi_is_default_route", -+ hfi->tcp_info.this_hfi_is_default_route) -+ || json_object_add_value_int(hfi_json, "dhcp_override", -+ hfi->tcp_info.dhcp_override)) -+ goto fail; -+ else -+ return hfi_json; -+ } -+fail: -+ json_free_object(hfi_json); -+ return NULL; -+} -+ -+static json_object *ssns_to_json(struct nbft_info_subsystem_ns *ss) -+{ -+ struct json_object *ss_json; -+ struct json_object *hfi_array_json; -+ char json_str[40]; -+ char *json_str_p; -+ int i; -+ -+ ss_json = json_create_object(); -+ if (!ss_json) -+ return NULL; -+ -+ hfi_array_json = json_create_array(); -+ if (!hfi_array_json) -+ goto fail; -+ -+ for (i = 0; i < ss->num_hfis; i++) -+ if (json_array_add_value_object(hfi_array_json, -+ json_object_new_int(ss->hfis[i]->index))) -+ goto fail; -+ -+ if (json_object_add_value_int(ss_json, "index", ss->index) -+ || json_object_add_value_int(ss_json, "num_hfis", ss->num_hfis) -+ || json_object_object_add(ss_json, "hfis", hfi_array_json) -+ || json_object_add_value_string(ss_json, "transport", ss->transport) -+ || json_object_add_value_string(ss_json, "traddr", ss->traddr) -+ || json_object_add_value_string(ss_json, "trsvcid", ss->trsvcid) -+ || json_object_add_value_int(ss_json, "subsys_port_id", ss->subsys_port_id) -+ || json_object_add_value_int(ss_json, "nsid", ss->nsid)) -+ goto fail; -+ -+ memset(json_str, 0, sizeof(json_str)); -+ json_str_p = json_str; -+ -+ switch (ss->nid_type) { -+ case NBFT_INFO_NID_TYPE_EUI64: -+ if (json_object_add_value_string(ss_json, "nid_type", "eui64")) -+ goto fail; -+ for (i = 0; i < 8; i++) -+ json_str_p += sprintf(json_str_p, "%02x", ss->nid[i]); -+ break; -+ -+ case NBFT_INFO_NID_TYPE_NGUID: -+ if (json_object_add_value_string(ss_json, "nid_type", "nguid")) -+ goto fail; -+ for (i = 0; i < 16; i++) -+ json_str_p += sprintf(json_str_p, "%02x", ss->nid[i]); -+ break; -+ -+ case NBFT_INFO_NID_TYPE_NS_UUID: -+ if (json_object_add_value_string(ss_json, "nid_type", "uuid")) -+ goto fail; -+ nvme_uuid_to_string(ss->nid, json_str); -+ break; -+ -+ default: -+ break; -+ } -+ if (json_object_add_value_string(ss_json, "nid", json_str)) -+ goto fail; -+ -+ if ((ss->subsys_nqn -+ && json_object_add_value_string(ss_json, "subsys_nqn", ss->subsys_nqn)) -+ || json_object_add_value_int(ss_json, "controller_id", ss->controller_id) -+ || json_object_add_value_int(ss_json, "asqsz", ss->asqsz) -+ || (ss->dhcp_root_path_string -+ && json_object_add_value_string(ss_json, "dhcp_root_path_string", -+ ss->dhcp_root_path_string)) -+ || json_object_add_value_int(ss_json, "pdu_header_digest_required", -+ ss->pdu_header_digest_required) -+ || json_object_add_value_int(ss_json, "data_digest_required", -+ ss->data_digest_required)) -+ goto fail; -+ -+ return ss_json; -+fail: -+ json_free_object(ss_json); -+ return NULL; -+} -+ -+static json_object *discovery_to_json(struct nbft_info_discovery *disc) -+{ -+ struct json_object *disc_json; -+ -+ disc_json = json_create_object(); -+ if (!disc_json) -+ return NULL; -+ -+ if (json_object_add_value_int(disc_json, "index", disc->index) -+ || (disc->security -+ && json_object_add_value_int(disc_json, "security", disc->security->index)) -+ || (disc->hfi -+ && json_object_add_value_int(disc_json, "hfi", disc->hfi->index)) -+ || (disc->uri -+ && json_object_add_value_string(disc_json, "uri", disc->uri)) -+ || (disc->nqn -+ && json_object_add_value_string(disc_json, "nqn", disc->nqn))) { -+ json_free_object(disc_json); -+ return NULL; -+ } else -+ return disc_json; -+} -+ -+static const char *primary_admin_host_flag_to_str(unsigned int primary) -+{ -+ static const char * const str[] = { -+ [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_NOT_INDICATED] = "not indicated", -+ [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_UNSELECTED] = "unselected", -+ [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_SELECTED] = "selected", -+ [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_RESERVED] = "reserved", -+ }; -+ -+ if (primary > NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_RESERVED) -+ return "INVALID"; -+ return str[primary]; -+} -+ -+static struct json_object *nbft_to_json(struct nbft_info *nbft, bool show_subsys, -+ bool show_hfi, bool show_discovery) -+{ -+ struct json_object *nbft_json, *host_json; -+ -+ nbft_json = json_create_object(); -+ if (!nbft_json) -+ return NULL; -+ -+ if (json_object_add_value_string(nbft_json, "filename", nbft->filename)) -+ goto fail; -+ -+ host_json = json_create_object(); -+ if (!host_json) -+ goto fail; -+ if ((nbft->host.nqn -+ && json_object_add_value_string(host_json, "nqn", nbft->host.nqn)) -+ || (nbft->host.id -+ && json_object_add_value_string(host_json, "id", -+ util_uuid_to_string(nbft->host.id)))) -+ goto fail; -+ json_object_add_value_int(host_json, "host_id_configured", -+ nbft->host.host_id_configured); -+ json_object_add_value_int(host_json, "host_nqn_configured", -+ nbft->host.host_nqn_configured); -+ json_object_add_value_string(host_json, "primary_admin_host_flag", -+ primary_admin_host_flag_to_str(nbft->host.primary)); -+ if (json_object_object_add(nbft_json, "host", host_json)) { -+ json_free_object(host_json); -+ goto fail; -+ } -+ -+ if (show_subsys) { -+ struct json_object *subsys_array_json, *subsys_json; -+ struct nbft_info_subsystem_ns **ss; -+ -+ subsys_array_json = json_create_array(); -+ if (!subsys_array_json) -+ goto fail; -+ for (ss = nbft->subsystem_ns_list; ss && *ss; ss++) { -+ subsys_json = ssns_to_json(*ss); -+ if (!subsys_json) -+ goto fail; -+ if (json_object_array_add(subsys_array_json, subsys_json)) { -+ json_free_object(subsys_json); -+ goto fail; -+ } -+ } -+ if (json_object_object_add(nbft_json, "subsystem", subsys_array_json)) { -+ json_free_object(subsys_array_json); -+ goto fail; -+ } -+ } -+ if (show_hfi) { -+ struct json_object *hfi_array_json, *hfi_json; -+ struct nbft_info_hfi **hfi; -+ -+ hfi_array_json = json_create_array(); -+ if (!hfi_array_json) -+ goto fail; -+ for (hfi = nbft->hfi_list; hfi && *hfi; hfi++) { -+ hfi_json = hfi_to_json(*hfi); -+ if (!hfi_json) -+ goto fail; -+ if (json_object_array_add(hfi_array_json, hfi_json)) { -+ json_free_object(hfi_json); -+ goto fail; -+ } -+ } -+ if (json_object_object_add(nbft_json, "hfi", hfi_array_json)) { -+ json_free_object(hfi_array_json); -+ goto fail; -+ } -+ } -+ if (show_discovery) { -+ struct json_object *discovery_array_json, *discovery_json; -+ struct nbft_info_discovery **disc; -+ -+ discovery_array_json = json_create_array(); -+ if (!discovery_array_json) -+ goto fail; -+ for (disc = nbft->discovery_list; disc && *disc; disc++) { -+ discovery_json = discovery_to_json(*disc); -+ if (!discovery_json) -+ goto fail; -+ if (json_object_array_add(discovery_array_json, discovery_json)) { -+ json_free_object(discovery_json); -+ goto fail; -+ } -+ } -+ if (json_object_object_add(nbft_json, "discovery", discovery_array_json)) { -+ json_free_object(discovery_array_json); -+ goto fail; -+ } -+ } -+ return nbft_json; -+fail: -+ json_free_object(nbft_json); -+ return NULL; -+} -+ -+static int json_show_nbfts(struct list_head *nbft_list, bool show_subsys, -+ bool show_hfi, bool show_discovery) -+{ -+ struct json_object *nbft_json_array, *nbft_json; -+ struct nbft_file_entry *entry; -+ -+ nbft_json_array = json_create_array(); -+ if (!nbft_json_array) -+ return ENOMEM; -+ -+ list_for_each(nbft_list, entry, node) { -+ nbft_json = nbft_to_json(entry->nbft, show_subsys, show_hfi, show_discovery); -+ if (!nbft_json) -+ goto fail; -+ if (json_object_array_add(nbft_json_array, nbft_json)) { -+ json_free_object(nbft_json); -+ goto fail; -+ } -+ } -+ -+ json_print_object(nbft_json_array, NULL); -+ printf("\n"); -+ json_free_object(nbft_json_array); -+ return 0; -+fail: -+ json_free_object(nbft_json_array); -+ return ENOMEM; -+} -+ -+static void print_nbft_hfi_info(struct nbft_info *nbft) -+{ -+ struct nbft_info_hfi **hfi; -+ unsigned int ip_width = 8, gw_width = 8, dns_width = 8; -+ -+ hfi = nbft->hfi_list; -+ if (!hfi || !*hfi) -+ return; -+ -+ for (; *hfi; hfi++) { -+ unsigned int len; -+ -+ len = strlen((*hfi)->tcp_info.ipaddr); -+ if (len > ip_width) -+ ip_width = len; -+ len = strlen((*hfi)->tcp_info.gateway_ipaddr); -+ if (len > gw_width) -+ gw_width = len; -+ len = strlen((*hfi)->tcp_info.primary_dns_ipaddr); -+ if (len > dns_width) -+ dns_width = len; -+ } -+ -+ printf("\nNBFT HFIs:\n\n"); -+ printf("%-3.3s|%-4.4s|%-10.10s|%-17.17s|%-4.4s|%-*.*s|%-4.4s|%-*.*s|%-*.*s\n", -+ "Idx", "Trsp", "PCI Addr", "MAC Addr", "DHCP", -+ ip_width, ip_width, "IP Addr", "Mask", -+ gw_width, gw_width, "Gateway", dns_width, dns_width, "DNS"); -+ printf("%-.3s+%-.4s+%-.10s+%-.17s+%-.4s+%-.*s+%-.4s+%-.*s+%-.*s\n", -+ dash, dash, dash, dash, dash, ip_width, dash, dash, -+ gw_width, dash, dns_width, dash); -+ for (hfi = nbft->hfi_list; *hfi; hfi++) -+ printf("%-3d|%-4.4s|%-10.10s|%-17.17s|%-4.4s|%-*.*s|%-4d|%-*.*s|%-*.*s\n", -+ (*hfi)->index, -+ (*hfi)->transport, -+ pci_sbdf_to_string((*hfi)->tcp_info.pci_sbdf), -+ mac_addr_to_string((*hfi)->tcp_info.mac_addr), -+ (*hfi)->tcp_info.dhcp_override ? "yes" : "no", -+ ip_width, ip_width, (*hfi)->tcp_info.ipaddr, -+ (*hfi)->tcp_info.subnet_mask_prefix, -+ gw_width, gw_width, (*hfi)->tcp_info.gateway_ipaddr, -+ dns_width, dns_width, (*hfi)->tcp_info.primary_dns_ipaddr); -+} -+ -+static void print_nbft_discovery_info(struct nbft_info *nbft) -+{ -+ struct nbft_info_discovery **disc; -+ unsigned int nqn_width = 20, uri_width = 12; -+ -+ disc = nbft->discovery_list; -+ if (!disc || !*disc) -+ return; -+ -+ for (; *disc; disc++) { -+ size_t len; -+ -+ len = strlen((*disc)->uri); -+ if (len > uri_width) -+ uri_width = len; -+ len = strlen((*disc)->nqn); -+ if (len > nqn_width) -+ nqn_width = len; -+ } -+ -+ printf("\nNBFT Discovery Controllers:\n\n"); -+ printf("%-3.3s|%-*.*s|%-*.*s\n", "Idx", uri_width, uri_width, "URI", -+ nqn_width, nqn_width, "NQN"); -+ printf("%-.3s+%-.*s+%-.*s\n", dash, uri_width, dash, nqn_width, dash); -+ for (disc = nbft->discovery_list; *disc; disc++) -+ printf("%-3d|%-*.*s|%-*.*s\n", (*disc)->index, -+ uri_width, uri_width, (*disc)->uri, -+ nqn_width, nqn_width, (*disc)->nqn); -+} -+ -+#define HFIS_LEN 20 -+static size_t print_hfis(const struct nbft_info_subsystem_ns *ss, char buf[HFIS_LEN]) -+{ -+ char hfi_buf[HFIS_LEN]; -+ size_t len, ofs; -+ int i; -+ -+ len = snprintf(hfi_buf, sizeof(hfi_buf), "%d", ss->hfis[0]->index); -+ for (i = 1; i < ss->num_hfis; i++) { -+ ofs = len; -+ len += snprintf(hfi_buf + ofs, sizeof(hfi_buf) - ofs, ",%d", -+ ss->hfis[i]->index); -+ /* -+ * If the list doesn't fit in HFIS_LEN characters, -+ * truncate and end with "..." -+ */ -+ if (len >= sizeof(hfi_buf)) { -+ while (ofs < sizeof(hfi_buf) - 1) -+ hfi_buf[ofs++] = '.'; -+ hfi_buf[ofs] = '\0'; -+ len = sizeof(hfi_buf) - 1; -+ break; -+ } -+ } -+ if (buf) -+ memcpy(buf, hfi_buf, len + 1); -+ return len; -+} -+ -+ -+static void print_nbft_subsys_info(struct nbft_info *nbft) -+{ -+ struct nbft_info_subsystem_ns **ss; -+ unsigned int nqn_width = 20, adr_width = 8, hfi_width = 4; -+ -+ ss = nbft->subsystem_ns_list; -+ if (!ss || !*ss) -+ return; -+ for (; *ss; ss++) { -+ size_t len; -+ -+ len = strlen((*ss)->subsys_nqn); -+ if (len > nqn_width) -+ nqn_width = len; -+ len = strlen((*ss)->traddr); -+ if (len > adr_width) -+ adr_width = len; -+ len = print_hfis(*ss, NULL); -+ if (len > hfi_width) -+ hfi_width = len; -+ } -+ -+ printf("\nNBFT Subsystems:\n\n"); -+ printf("%-3.3s|%-*.*s|%-4.4s|%-*.*s|%-5.5s|%-*.*s\n", -+ "Idx", nqn_width, nqn_width, "NQN", -+ "Trsp", adr_width, adr_width, "Address", "SvcId", hfi_width, hfi_width, "HFIs"); -+ printf("%-.3s+%-.*s+%-.4s+%-.*s+%-.5s+%-.*s\n", -+ dash, nqn_width, dash, dash, adr_width, dash, dash, hfi_width, dash); -+ for (ss = nbft->subsystem_ns_list; *ss; ss++) { -+ char hfi_buf[HFIS_LEN]; -+ -+ print_hfis(*ss, hfi_buf); -+ printf("%-3d|%-*.*s|%-4.4s|%-*.*s|%-5.5s|%-*.*s\n", -+ (*ss)->index, nqn_width, nqn_width, (*ss)->subsys_nqn, -+ (*ss)->transport, adr_width, adr_width, (*ss)->traddr, -+ (*ss)->trsvcid, hfi_width, hfi_width, hfi_buf); -+ } -+} -+ -+static void normal_show_nbft(struct nbft_info *nbft, bool show_subsys, -+ bool show_hfi, bool show_discovery) -+{ -+ printf("%s:\n", nbft->filename); -+ if ((!nbft->hfi_list || !*nbft->hfi_list) && -+ (!nbft->security_list || !*nbft->security_list) && -+ (!nbft->discovery_list || !*nbft->discovery_list) && -+ (!nbft->subsystem_ns_list || !*nbft->subsystem_ns_list)) -+ printf("(empty)\n"); -+ else { -+ if (show_subsys) -+ print_nbft_subsys_info(nbft); -+ if (show_hfi) -+ print_nbft_hfi_info(nbft); -+ if (show_discovery) -+ print_nbft_discovery_info(nbft); -+ } -+} -+ -+static void normal_show_nbfts(struct list_head *nbft_list, bool show_subsys, -+ bool show_hfi, bool show_discovery) -+{ -+ bool not_first = false; -+ struct nbft_file_entry *entry; -+ -+ list_for_each(nbft_list, entry, node) { -+ if (not_first) -+ printf("\n"); -+ normal_show_nbft(entry->nbft, show_subsys, show_hfi, show_discovery); -+ not_first = true; -+ } -+} -+ -+int show_nbft(int argc, char **argv, struct command *cmd, struct plugin *plugin) -+{ -+ const char *desc = "Display contents of the ACPI NBFT files."; -+ struct list_head nbft_list; -+ char *format = "normal"; -+ char *nbft_path = NBFT_SYSFS_PATH; -+ enum nvme_print_flags flags = -1; -+ int ret; -+ bool show_subsys = false, show_hfi = false, show_discovery = false; -+ -+ OPT_ARGS(opts) = { -+ OPT_FMT("output-format", 'o', &format, "Output format: normal|json"), -+ OPT_FLAG("subsystem", 's', &show_subsys, "show NBFT subsystems"), -+ OPT_FLAG("hfi", 'H', &show_hfi, "show NBFT HFIs"), -+ OPT_FLAG("discovery", 'd', &show_discovery, "show NBFT discovery controllers"), -+ OPT_STRING("nbft-path", 0, "STR", &nbft_path, "user-defined path for NBFT tables"), -+ OPT_END() -+ }; -+ -+ ret = argconfig_parse(argc, argv, desc, opts); -+ if (ret) -+ return ret; -+ -+ if (!(show_subsys || show_hfi || show_discovery)) -+ show_subsys = show_hfi = show_discovery = true; -+ -+ if (!strcmp(format, "")) -+ flags = -1; -+ else if (!strcmp(format, "normal")) -+ flags = NORMAL; -+ else if (!strcmp(format, "json")) -+ flags = JSON; -+ else -+ return EINVAL; -+ -+ list_head_init(&nbft_list); -+ ret = read_nbft_files(&nbft_list, nbft_path); -+ if (!ret) { -+ if (flags == NORMAL) -+ normal_show_nbfts(&nbft_list, show_subsys, show_hfi, show_discovery); -+ else if (flags == JSON) -+ ret = json_show_nbfts(&nbft_list, show_subsys, show_hfi, show_discovery); -+ free_nbfts(&nbft_list); -+ } -+ return ret; -+} -diff --git a/plugins/nbft/nbft-plugin.h b/plugins/nbft/nbft-plugin.h -new file mode 100644 -index 00000000..018349d9 ---- /dev/null -+++ b/plugins/nbft/nbft-plugin.h -@@ -0,0 +1,18 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+#undef CMD_INC_FILE -+#define CMD_INC_FILE plugins/nbft/nbft-plugin -+ -+#if !defined(NBFT) || defined(CMD_HEADER_MULTI_READ) -+#define NBFT -+ -+#include "cmd.h" -+ -+PLUGIN(NAME("nbft", "ACPI NBFT table extensions", NVME_VERSION), -+ COMMAND_LIST( -+ ENTRY("show", "Show contents of ACPI NBFT tables", show_nbft) -+ ) -+); -+ -+#endif -+ -+#include "define_cmd.h" --- -2.39.1 - diff --git a/SOURCES/0004-Revert-nvme-Masks-SSTAT-in-sanize-log-output.patch b/SOURCES/0004-Revert-nvme-Masks-SSTAT-in-sanize-log-output.patch deleted file mode 100644 index 07902b4..0000000 --- a/SOURCES/0004-Revert-nvme-Masks-SSTAT-in-sanize-log-output.patch +++ /dev/null @@ -1,35 +0,0 @@ -From e1afeffcbb78e252bbb0d21d2f4ed0fffeb59105 Mon Sep 17 00:00:00 2001 -From: Maurizio Lombardi -Date: Tue, 23 May 2023 15:08:40 +0200 -Subject: [PATCH] Revert "nvme: Masks SSTAT in sanize-log output" - -The NVME_SANITIZE_SSTAT_STATUS_MASK is used to mask the -3 least significant bits (representing the status of the most recent -sanitize operation) of the SSTAT field. - -The SSTAT field is 16 bits wide and contains other information too, such -as the Global Data Erased bit and the number of completed passes. - -Revert this commit so nvme-cli will print the entire SSTAT field - -This reverts commit 7092ff55c5d9017231a68fa4dbb9a37b42d61d61. ---- - nvme-print.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nvme-print.c b/nvme-print.c -index c989435d..735ec193 100644 ---- a/nvme-print.c -+++ b/nvme-print.c -@@ -4423,7 +4423,7 @@ void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, - printf("\n"); - - printf("Sanitize Status (SSTAT) : %#x\n", -- le16_to_cpu(sanitize->sstat) & NVME_SANITIZE_SSTAT_STATUS_MASK); -+ le16_to_cpu(sanitize->sstat)); - if (human) - nvme_show_sanitize_log_sstat(le16_to_cpu(sanitize->sstat)); - --- -2.39.3 - diff --git a/SOURCES/0004-nvme-Fixed-segmentation-fault-when-getting-host-init.patch b/SOURCES/0004-nvme-Fixed-segmentation-fault-when-getting-host-init.patch new file mode 100644 index 0000000..0029be0 --- /dev/null +++ b/SOURCES/0004-nvme-Fixed-segmentation-fault-when-getting-host-init.patch @@ -0,0 +1,29 @@ +From 2f30d87d5c258fd97f78b0705bb92519d8a2498d Mon Sep 17 00:00:00 2001 +From: "da Cunha, Leonardo" +Date: Wed, 11 Oct 2023 09:01:44 -0700 +Subject: [PATCH] nvme: Fixed segmentation fault when getting host initiated + telemetry + +Signed-off-by: leonardo.da.cunha +--- + nvme.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/nvme.c b/nvme.c +index b9e56a48f0a5..73d74afdfd73 100644 +--- a/nvme.c ++++ b/nvme.c +@@ -851,6 +851,10 @@ static int __get_telemetry_log_host(struct nvme_dev *dev, + _cleanup_free_ struct nvme_telemetry_log *log = NULL; + int err; + ++ log = nvme_alloc(sizeof(*log)); ++ if (!log) ++ return -errno; ++ + err = nvme_cli_get_log_telemetry_host(dev, 0, + NVME_LOG_TELEM_BLOCK_SIZE, + log); +-- +2.39.3 + diff --git a/SOURCES/0005-util-Fix-suffix_si_parse-to-parse-no-decimal-point-b.patch b/SOURCES/0005-util-Fix-suffix_si_parse-to-parse-no-decimal-point-b.patch deleted file mode 100644 index fc1fb45..0000000 --- a/SOURCES/0005-util-Fix-suffix_si_parse-to-parse-no-decimal-point-b.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 94d6c2b5088292e101da3e1d078e155a5af32f56 Mon Sep 17 00:00:00 2001 -From: Tokunori Ikegami -Date: Sun, 14 May 2023 17:39:00 +0900 -Subject: [PATCH] util: Fix suffix_si_parse to parse no decimal point but - suffix value correctly - -For example create-ns command --ncap-si paramter value 800G parsed to 0 as invalid value. - -Signed-off-by: Tokunori Ikegami ---- - unit/test-suffix-si-parse.c | 6 +++++ - util/suffix.c | 50 +++++++++++++++++++++++++++---------- - 2 files changed, 43 insertions(+), 13 deletions(-) - -diff --git a/unit/test-suffix-si-parse.c b/unit/test-suffix-si-parse.c -index bc924552..54cff0e6 100644 ---- a/unit/test-suffix-si-parse.c -+++ b/unit/test-suffix-si-parse.c -@@ -43,6 +43,12 @@ static struct tonum_test tonum_tests[] = { - { "2,33", 0, -EINVAL }, - { "3..3", 0, -EINVAL }, - { "123.12MM", 0, -EINVAL }, -+ { "800G", 800000000000, 0 }, -+ { "800GG", 0, -EINVAL }, -+ { "800G800", 0, -EINVAL }, -+ { "800.0G", 800000000000, 0 }, -+ { "800.G", 0, -EINVAL }, -+ { "800.", 0, -EINVAL }, - }; - - void tonum_test(struct tonum_test *test) -diff --git a/util/suffix.c b/util/suffix.c -index 8ed080d4..f010f3b6 100644 ---- a/util/suffix.c -+++ b/util/suffix.c -@@ -40,6 +40,7 @@ - #include - #include - #include -+#include - - static struct si_suffix { - long double magnitude; -@@ -68,11 +69,26 @@ const char *suffix_si_get(double *value) - return suffix; - } - -+static bool suffix_si_check(const char val) -+{ -+ int i; -+ struct si_suffix *s; -+ -+ for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) { -+ s = &si_suffixes[i]; -+ -+ if (val == *s->suffix) -+ return true; -+ } -+ -+ return false; -+} -+ - int suffix_si_parse(const char *str, char **endptr, uint64_t *val) - { -- unsigned long long num, frac; -+ unsigned long long num, frac = 0; - char *sep, *tmp; -- int frac_len, len, i; -+ int frac_len = 0, len, i; - - num = strtoull(str, endptr, 0); - if (str == *endptr || -@@ -93,23 +109,31 @@ int suffix_si_parse(const char *str, char **endptr, uint64_t *val) - len = 0; - - for (i = 0; i < len; i++) { -+ if (suffix_si_check((*endptr)[i])) -+ break; - if (((*endptr)[i] == '\0') || (*endptr)[i] != sep[i]) - return -EINVAL; - } -- *endptr += len; -- tmp = *endptr; - -- /* extract the digits after decimal point */ -- frac = strtoull(tmp, endptr, 0); -- if (tmp == *endptr || -- ((frac == ULLONG_MAX) && errno == ERANGE)) -- return -EINVAL; -+ if (suffix_si_check((*endptr)[i])) { -+ if ((*endptr)[i + 1] != '\0') -+ return -EINVAL; -+ } else { -+ *endptr += len; -+ tmp = *endptr; -+ -+ /* extract the digits after decimal point */ -+ frac = strtoull(tmp, endptr, 0); -+ if (tmp == *endptr || -+ ((frac == ULLONG_MAX) && errno == ERANGE)) -+ return -EINVAL; - -- /* test that we have max one character as suffix */ -- if ((*endptr)[0] != '\0' && (*endptr)[1] != '\0') -- return -EINVAL; -+ /* test that we have max one character as suffix */ -+ if ((*endptr)[0] != '\0' && (*endptr)[1] != '\0') -+ return -EINVAL; - -- frac_len = *endptr - tmp; -+ frac_len = *endptr - tmp; -+ } - - for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) { - struct si_suffix *s = &si_suffixes[i]; --- -2.39.3 - diff --git a/SPECS/nvme-cli.spec b/SPECS/nvme-cli.spec index 0779012..f51199a 100644 --- a/SPECS/nvme-cli.spec +++ b/SPECS/nvme-cli.spec @@ -2,19 +2,18 @@ #%%global shortcommit0 %%(c=%%{commit0}; echo ${c:0:7}) Name: nvme-cli -Version: 2.4 -Release: 10%{?dist} +Version: 2.6 +Release: 5%{?dist} Summary: NVMe management command line interface -License: GPLv2+ +License: GPL-2.0-only URL: https://github.com/linux-nvme/nvme-cli Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz -Patch0: 0001-nbft-make-lookup_ctrl-function-public.patch -Patch1: 0002-nbft-added-NBFT-v1.0-table-support.patch -Patch2: 0003-nbft-add-the-nbft-show-plugin.patch -Patch3: 0004-Revert-nvme-Masks-SSTAT-in-sanize-log-output.patch -Patch4: 0005-util-Fix-suffix_si_parse-to-parse-no-decimal-point-b.patch +Patch0: 0001-udev-rules-set-ctrl_loss_tmo-to-1-for-ONTAP-NVMe-TCP.patch +Patch1: 0002-udev-rules-rename-netapp-udev-rule.patch +Patch2: 0003-Revert-fabrics-Use-corresponding-hostid-when-hostnqn.patch +Patch3: 0004-nvme-Fixed-segmentation-fault-when-getting-host-init.patch BuildRequires: meson >= 0.50.0 BuildRequires: gcc gcc-c++ @@ -22,7 +21,7 @@ BuildRequires: libuuid-devel BuildRequires: systemd-devel BuildRequires: systemd-rpm-macros BuildRequires: zlib-devel -BuildRequires: libnvme-devel >= 1.4-5 +BuildRequires: libnvme-devel >= 1.6-1 BuildRequires: json-c-devel >= 0.14 BuildRequires: asciidoc BuildRequires: xmlto @@ -40,7 +39,6 @@ nvme-cli provides NVM-Express user space tooling for Linux. %patch1 -p1 %patch2 -p1 %patch3 -p1 -%patch4 -p1 %build %meson -Dudevrulesdir=%{_udevrulesdir} -Dsystemddir=%{_unitdir} -Ddocs=all -Ddocs-build=true -Dhtmldir=%{_pkgdocdir} @@ -72,7 +70,7 @@ rm -rf %{buildroot}%{_pkgdocdir}/nvme %{_unitdir}/nvmf-connect.target %{_unitdir}/nvmf-connect@.service %{_udevrulesdir}/70-nvmf-autoconnect.rules -%{_udevrulesdir}/71-nvmf-iopolicy-netapp.rules +%{_udevrulesdir}/71-nvmf-netapp.rules # Do not install the dracut rule yet. See rhbz 1742764 # Is this still true? Now that we support nvme-of boot, do we want to install this file? # /usr/lib/dracut/dracut.conf.d/70-nvmf-autoconnect.conf @@ -96,6 +94,21 @@ if [ $1 -eq 1 ] || [ $1 -eq 2 ]; then fi %changelog +* Thu Feb 22 2024 Maurizio Lombardi - 2.6-5 +- Fix for RHEL-13107 + +* Mon Nov 13 2023 Maurizio Lombardi - 2.6-4 +- Fix for RHEL-16216 (revert 1:1 mapping between hostnqn and hostid) + +* Wed Nov 08 2023 Maurizio Lombardi - 2.6-3 +- Fixes for RHEL-12566 + +* Mon Nov 06 2023 Maurizio Lombardi - 2.6-2 +- Rebuild for side-tag + +* Tue Oct 31 2023 Maurizio Lombardi - 2.6-1 +- Update to version 2.6 + * Mon Aug 21 2023 John Meneghini - 2.4-10 - JIRA: https://issues.redhat.com/browse/RHEL-1492