[RFC PATCHv3 4/6] nvme: add sysfs attribute adp_weight_timeout
Hannes Reinecke
hare at suse.de
Mon Oct 27 04:54:50 PDT 2025
On 10/27/25 10:29, Nilay Shroff wrote:
> By default, the adaptive I/O policy accumulates latency samples over a
> 15-second window. When this window expires, the driver computes the
> average latency and updates the smoothed (EWMA) latency value. The
> path weight is then recalculated based on this data.
>
> A 15-second window provides a good balance for most workloads, as it
> helps smooth out transient latency spikes and produces a more stable
> path weight profile. However, some workloads may benefit from faster
> or slower adaptation to changing latency conditions.
>
> This commit introduces a new sysfs attribute, adp_weight_timeout,
> which allows users to configure the path weight calculation interval
> based on their workload requirements.
>
> Signed-off-by: Nilay Shroff <nilay at linux.ibm.com>
> ---
> drivers/nvme/host/core.c | 6 ++++++
> drivers/nvme/host/multipath.c | 38 +++++++++++++++++++++++++++++++++--
> drivers/nvme/host/nvme.h | 4 +++-
> drivers/nvme/host/sysfs.c | 1 +
> 4 files changed, 46 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index ab09b9724674..f48c6bc25055 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -3248,6 +3248,12 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
> * used while adding latency sample for adaptive iopolicy.
> */
> subsys->adp_ewma_shift = NVME_DEFAULT_ADP_EWMA_SHIFT;
> + /*
> + * Path weight calculation timeout interval used for adaptive iopolicy.
> + * The default value of this paremeter is set to 15 seconds. However, it
> + * could be also changed through sysfs.
> + */
> + subsys->adp_weight_timeout = NVME_DEFAULT_ADP_WEIGHT_TIMEOUT;
> #endif
> subsys->dev.class = &nvme_subsys_class;
> subsys->dev.release = nvme_release_subsystem;
> diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
> index 95407c0f2f4b..d4df01511ee9 100644
> --- a/drivers/nvme/host/multipath.c
> +++ b/drivers/nvme/host/multipath.c
> @@ -362,8 +362,11 @@ static void nvme_mpath_add_sample(struct request *rq, struct nvme_ns *ns)
> stat->batch_count++;
> stat->nr_samples++;
>
> - if (now > stat->last_weight_ts &&
> - (now - stat->last_weight_ts) >= NVME_DEFAULT_ADP_WEIGHT_TIMEOUT) {
> + if (now > stat->last_weight_ts) {
> + u64 timeout = READ_ONCE(head->subsys->adp_weight_timeout);
> +
> + if ((now - stat->last_weight_ts) < timeout)
> + return;
>
> stat->last_weight_ts = now;
>
> @@ -1495,6 +1498,37 @@ static ssize_t nvme_subsys_adp_ewma_shift_store(struct device *dev,
> SUBSYS_ATTR_RW(adp_ewma_shift, 0644, nvme_subsys_adp_ewma_shift_show,
> nvme_subsys_adp_ewma_shift_store);
>
> +static ssize_t nvme_subsys_adp_weight_timeout_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct nvme_subsystem *subsys =
> + container_of(dev, struct nvme_subsystem, dev);
> +
> + return sysfs_emit(buf, "%llu\n",
> + div_u64(READ_ONCE(subsys->adp_weight_timeout), NSEC_PER_SEC));
> +}
> +
> +static ssize_t nvme_subsys_adp_weight_timeout_store(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t count)
> +{
> + int timeout, err;
> + struct nvme_subsystem *subsys =
> + container_of(dev, struct nvme_subsystem, dev);
> +
> + err = kstrtoint(buf, 0, &timeout);
> + if (err)
> + return -EINVAL;
> +
> + if (timeout <= 0)
> + return -EINVAL;
> +
> + WRITE_ONCE(subsys->adp_weight_timeout, timeout * NSEC_PER_SEC);
> + return count;
> +}
> +
> +SUBSYS_ATTR_RW(adp_weight_timeout, 0644, nvme_subsys_adp_weight_timeout_show,
> + nvme_subsys_adp_weight_timeout_store);
> +
> static ssize_t ana_grpid_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
> index 9f5b233c747a..2e58d4d6902a 100644
> --- a/drivers/nvme/host/nvme.h
> +++ b/drivers/nvme/host/nvme.h
> @@ -450,7 +450,8 @@ struct nvme_subsystem {
> struct ida ns_ida;
> #ifdef CONFIG_NVME_MULTIPATH
> enum nvme_iopolicy iopolicy;
> - int adp_ewma_shift; /* used for adaptive iopolicy */
> + int adp_ewma_shift; /* used for adaptive iopolicy */
> + u64 adp_weight_timeout; /* used for adaptive iopolicy */
> #endif
> };
>
> @@ -1045,6 +1046,7 @@ extern struct device_attribute dev_attr_numa_nodes;
> extern struct device_attribute dev_attr_delayed_removal_secs;
> extern struct device_attribute subsys_attr_iopolicy;
> extern struct device_attribute subsys_attr_adp_ewma_shift;
> +extern struct device_attribute subsys_attr_adp_weight_timeout;
>
> static inline bool nvme_disk_is_ns_head(struct gendisk *disk)
> {
> diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
> index cf9711961b00..18d7eddd477a 100644
> --- a/drivers/nvme/host/sysfs.c
> +++ b/drivers/nvme/host/sysfs.c
> @@ -918,6 +918,7 @@ static struct attribute *nvme_subsys_attrs[] = {
> #ifdef CONFIG_NVME_MULTIPATH
> &subsys_attr_iopolicy.attr,
> &subsys_attr_adp_ewma_shift.attr,
> + &subsys_attr_adp_weight_timeout.attr,
> #endif
> NULL,
> };
Similar comment: can we please move it to debugfs?
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare at suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
More information about the Linux-nvme
mailing list