[PATCH 2/2] nvme-multipath: add 'latency' iopolicy
Hannes Reinecke
hare at suse.de
Wed Jul 26 06:23:05 PDT 2023
Add an I/O policy for selecting paths based upon the least latency.
Signed-off-by: Hannes Reinecke <hare at suse.de>
---
drivers/nvme/host/core.c | 1 +
drivers/nvme/host/multipath.c | 19 +++++++++++++++++--
drivers/nvme/host/nvme.h | 5 +++++
3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index b52e9c9bffd6..bd506284af1f 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -397,6 +397,7 @@ void nvme_complete_rq(struct request *req)
trace_nvme_complete_rq(req);
nvme_cleanup_cmd(req);
+ nvme_mpath_complete_request(req);
/*
* Completions of long-running commands should not be able to
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 7813608038bc..8052ba8085f0 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -18,6 +18,7 @@ static const char *nvme_iopolicy_names[] = {
[NVME_IOPOLICY_NUMA] = "numa",
[NVME_IOPOLICY_RR] = "round-robin",
[NVME_IOPOLICY_BW] = "bandwidth",
+ [NVME_IOPOLICY_LAT] = "latency",
[NVME_IOPOLICY_EWMA] = "ewma",
};
@@ -33,6 +34,8 @@ static int nvme_set_iopolicy(const char *val, const struct kernel_param *kp)
iopolicy = NVME_IOPOLICY_RR;
else if (!strncmp(val, "bandwidth", 9))
iopolicy = NVME_IOPOLICY_BW;
+ else if (!strncmp(val, "latency", 7))
+ iopolicy = NVME_IOPOLICY_LAT;
else if (!strncmp(val, "ewma", 4))
iopolicy = NVME_IOPOLICY_EWMA;
else
@@ -49,7 +52,7 @@ static int nvme_get_iopolicy(char *buf, const struct kernel_param *kp)
module_param_call(iopolicy, nvme_set_iopolicy, nvme_get_iopolicy,
&iopolicy, 0644);
MODULE_PARM_DESC(iopolicy,
- "Default multipath I/O policy; 'numa' (default), 'round-robin', 'bandwidth', or 'ewma'");
+ "Default multipath I/O policy; 'numa' (default), 'round-robin', 'bandwidth', 'latency', or 'ewma'");
void nvme_mpath_default_iopolicy(struct nvme_subsystem *subsys)
{
@@ -153,6 +156,17 @@ void nvme_mpath_end_request(struct request *rq)
nvme_req(rq)->start_time);
}
+void nvme_mpath_complete_request(struct request *req)
+{
+ struct nvme_ns *ns = req->q->queuedata;
+
+ if (iopolicy == NVME_IOPOLICY_LAT) {
+ u64 lat = ktime_get_ns() - req->start_time_ns;
+
+ ns->path_weight += lat >> 10;
+ }
+}
+
void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
{
struct nvme_ns *ns;
@@ -267,7 +281,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
if (iopolicy == NVME_IOPOLICY_NUMA)
distance = node_distance(node, ns->ctrl->numa_node);
- else if (iopolicy == NVME_IOPOLICY_BW)
+ else if (iopolicy == NVME_IOPOLICY_LAT ||
+ iopolicy == NVME_IOPOLICY_BW)
distance = ns->path_weight;
else if (iopolicy == NVME_IOPOLICY_EWMA)
distance = nvme_path_ewma(ns);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 4eabb6ee563a..d9e9c1b5236a 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -391,6 +391,7 @@ enum nvme_iopolicy {
NVME_IOPOLICY_NUMA,
NVME_IOPOLICY_RR,
NVME_IOPOLICY_BW,
+ NVME_IOPOLICY_LAT,
NVME_IOPOLICY_EWMA,
};
@@ -904,6 +905,7 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl);
void nvme_mpath_shutdown_disk(struct nvme_ns_head *head);
void nvme_mpath_start_request(struct request *rq);
void nvme_mpath_end_request(struct request *rq);
+void nvme_mpath_complete_request(struct request *rq);
static inline void nvme_trace_bio_complete(struct request *req)
{
@@ -995,6 +997,9 @@ static inline void nvme_mpath_start_request(struct request *rq)
static inline void nvme_mpath_end_request(struct request *rq)
{
}
+static inline void nvme_mpath_complete_request(struct request *rq)
+{
+}
#endif /* CONFIG_NVME_MULTIPATH */
int nvme_revalidate_zones(struct nvme_ns *ns);
--
2.35.3
More information about the Linux-nvme
mailing list