[PATCH 3/3] nvme-multipath: add "use_nonoptimized" module option

Ewan D. Milne
2023-09-25T16:33:09Z

Setting nvme_core.use_nonoptimized=true will cause the path
selector to treat optimized and nonoptimized paths equally.

This is because although an NVMe fabrics target device may report
an unoptimized ANA state, it is possible that other factors such
as fabric latency are a large factor in the I/O service time. And,
throughput may improve overall if nonoptimized ports are also used.

Signed-off-by: Ewan D. Milne <emilne@redhat.com>
---
drivers/nvme/host/multipath.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index deea7fd4aa95..f640b8ad934b 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -13,6 +13,10 @@ bool multipath = true;
module_param(multipath, bool, 0444);
MODULE_PARM_DESC(multipath,
"turn on native support for multiple controllers per subsystem");
+bool use_nonoptimized = false;
+module_param(use_nonoptimized, bool, 0644);
+MODULE_PARM_DESC(use_nonoptimized,
+ "Use ANA nonoptimized paths as well as optimized paths for I/O");

static const char *nvme_iopolicy_names[] = {
[NVME_IOPOLICY_NUMA] = "numa",
@@ -272,7 +276,10 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
}
}

- if (!found)
+ /*
+ * If fallback_distance was set, fallback must also be set
+ */
+ if (!found || (use_nonoptimized && (fallback_distance < found_distance)))
found = fallback;
if (found)
rcu_assign_pointer(head->current_path[node], found);
@@ -310,8 +317,12 @@ static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head,
found = ns;
goto out;
}
- if (ns->ana_state == NVME_ANA_NONOPTIMIZED)
+ if (ns->ana_state == NVME_ANA_NONOPTIMIZED) {
found = ns;
+ if (use_nonoptimized)
+ goto out;
+ }
+
}

/*
@@ -321,7 +332,7 @@ static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head,
* - no other usable path found and current is usable.
*/
if (!nvme_path_is_disabled(old) &&
- (old->ana_state == NVME_ANA_OPTIMIZED ||
+ (old->ana_state == NVME_ANA_OPTIMIZED || use_nonoptimized ||
(!found && old->ana_state == NVME_ANA_NONOPTIMIZED)))
return old;

@@ -364,6 +375,11 @@ static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head,
}
}

+ /*
+ * If min_depth_nonopt was set, best_nonopt must also be set
+ */
+ if (use_nonoptimized && (min_depth_nonopt < min_depth_opt))
+ return best_nonopt;
return best_opt ? best_opt : best_nonopt;
}

--
2.20.1