[PATH libnvme v1 2/2] fabrics: Do not pass disable_sqflow if not supported
Daniel Wagner
dwagner at suse.de
Tue Jul 25 01:41:37 PDT 2023
Only retry a connect attempt with disable_sqflow if the kernel
actually supports this option.
Reported-by: Sagi Grimberg <sagi at grimberg.me>
Signed-off-by: Daniel Wagner <dwagner at suse.de>
---
src/nvme/fabrics.c | 85 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c
index 2f26c2b7f39a..e2953e7ef2a4 100644
--- a/src/nvme/fabrics.c
+++ b/src/nvme/fabrics.c
@@ -227,6 +227,32 @@ static const struct nvme_fabric_options default_options = {
.trsvcid = true,
};
+static const char *default_options_strings[] =
+{
+ "ctrl_loss_tmo",
+ "data_digest",
+ "disable_sqflow",
+ "discovery",
+ "duplicate_connect",
+ "fast_io_fail_tmo",
+ "hdr_digest",
+ "host_iface",
+ "host_traddr",
+ "hostid",
+ "hostnqn",
+ "keep_alive_tmo",
+ "nqn",
+ "nr_io_queues",
+ "nr_poll_queues",
+ "nr_write_queues",
+ "queue_size",
+ "reconnect_delay",
+ "tos",
+ "traddr",
+ "transport",
+ "trsvcid",
+};
+
void nvmf_default_config(struct nvme_fabrics_config *cfg)
{
memset(cfg, 0, sizeof(*cfg));
@@ -652,6 +678,62 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr)
continue; \
}
+static bool nvme_check_default_option(const char *opt)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(default_options_strings); i++) {
+ if (!strcmp(opt, default_options_strings[i]))
+ return true;
+ }
+ return false;
+}
+
+static bool nvmf_check_option(const char *opt)
+{
+ char buf[0x1000], *options, *p, *v;
+ ssize_t len;
+ int fd;
+ bool supported = false;
+
+ fd = open(nvmf_dev, O_RDONLY);
+ if (fd < 0)
+ return false;
+
+ len = read(fd, buf, sizeof(buf) - 1);
+ if (len < 0) {
+ if (errno == EINVAL) {
+ /*
+ * Older Linux kernels don't allow reading from nvmf_dev
+ * to get supported options, so use a default set
+ */
+ supported = nvme_check_default_option(opt);
+ }
+
+ goto out_close;
+ }
+
+ buf[len] = '\0';
+ options = buf;
+ while ((p = strsep(&options, ",\n")) != NULL) {
+ if (!*p)
+ continue;
+ v = strsep(&p, "= ");
+ if (!v)
+ continue;
+
+ if (strcmp(opt, v))
+ continue;
+
+ supported = true;
+ break;
+ }
+
+out_close:
+ close(fd);
+ return supported;
+}
+
static int nvmf_read_options(nvme_root_t r)
{
char buf[0x1000], *options, *p, *v;
@@ -1038,7 +1120,8 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h,
if (!ret)
return c;
- if (errno == EINVAL && c->cfg.disable_sqflow) {
+ if (errno == EINVAL && c->cfg.disable_sqflow &&
+ nvmf_check_option("disable_sqflow")) {
errno = 0;
/* disable_sqflow is unrecognized option on older kernels */
nvme_msg(h->r, LOG_INFO, "failed to connect controller, "
--
2.41.0
More information about the Linux-nvme
mailing list