[PATCHv6 0/8] nvme-multipath: introduce latency I/O policy

Nilay Shroff nilay at linux.ibm.com
Wed May 20 11:20:56 PDT 2026


Hi,

This series introduces a new latency I/O policy for NVMe native
multipath. Existing policies such as numa, round-robin, and queue-depth
are static and do not adapt to real-time transport performance. The numa
selects the path closest to the NUMA node of the current CPU, optimizing
memory and path locality, but ignores actual path performance. The
round-robin distributes I/O evenly across all paths, providing fairness
but not performance awareness. The queue-depth reacts to instantaneous
queue occupancy, avoiding heavily loaded paths, but does not account for
actual latency, throughput, or link speed.

The new latency policy addresses these gaps selecting paths dynamically
based on measured I/O latency for both PCIe and fabrics. Latency is
derived by passively sampling I/O completions. Each path is assigned a
weight proportional to its latency score, and I/Os are then forwarded
accordingly. As condition changes (e.g. latency spikes, bandwidth
differences), path weights are updated, automatically steering traffic
toward better-performing paths.

Early results show reduced tail latency under mixed workloads and
improved throughput by exploiting higher-speed links more effectively.
For example, with NVMf/TCP using two paths (one throttled with ~30 ms
delay), fio results with random read/write/rw workloads (direct I/O)
showed:

        numa         round-robin   queue-depth  adaptive
        -----------  -----------   -----------  ---------
READ:   50.0 MiB/s   105 MiB/s     230 MiB/s    350 MiB/s
WRITE:  65.9 MiB/s   125 MiB/s     385 MiB/s    446 MiB/s
RW:     R:30.6 MiB/s R:56.5 MiB/s  R:122 MiB/s  R:175 MiB/s
        W:30.7 MiB/s W:56.5 MiB/s  W:122 MiB/s  W:175 MiB/s

This pathcset includes totla 8 patches:
[PATCH 1/8] block: expose blk_stat_{enable,disable}_accounting()
  - Make blk_stat APIs available to block drivers.
  - Needed for per-path latency measurement.

[PATCH 2/8] nvme-multipath: pass I/O type to nvme_find_path()
  - This is the prep patch which updates nvme_find_path() signature
    
[PATCH 3/8] nvme-multipath: add latency I/O policy
  - Implement path scoring based on latency (EWMA).
  - Distribute I/O proportionally to per-path weights.

[PATCH 4/8] nvme: add generic debugfs support
  - Introduce generic debugfs support for NVMe module

[PATCH 5/8] nvme-multipath: add debugfs attribute latency_ewma_shift
  - Adds a debugfs attribute to control ewma shift

[PATCH 6/8] nvme-multipath: add debugfs attribute latency_batch_timeout
  - Adds a debugfs attribute to control latency batch window interval 

[PATCH 7/8] nvme-multipath: add debugfs attribute latency_stat
  - Add “latency_stat” under per-path and head debugfs directories to
    expose latency policy state and statistics.

[PATCH 8/8] nvme-multipath: add documentation for latency I/O policy
  - Includes documentation for latency I/O multipath policy.

LSFMM discussion:
=================
During lsfmm 2026, it was decided to rename this I/O policy from
"adaptive" to "latency". This series reflects that rename.

The discussion at lsfmm also focused extensively on the latency
measurement model, including whether latency should be tracked
per-CPU or per-NUMA, and whether separate I/O-size buckets should
be maintained for different request sizes.

After detailed discussion and evaluation of throughput results, the
consensus was to initially measure I/O completion latency on a
per-CPU basis. The available performance data showed that the
per-CPU implementation already provides sufficient averaging across
CPUs while keeping the design relatively simple.

The use of additional I/O-size buckets did not demonstrate meaningful
throughput improvement in the general case and would introduce extra
complexity into the fast path and accounting logic. As a result, the
consensus was to avoid I/O-size bucketing for now and keep the policy
focused on per-CPU latency measurement.

If future real-world workloads demonstrate a clear benefit from
I/O-size-aware latency accounting, the policy can be extended later
to support it.

As ususal, feedback and suggestions are most welcome!

Thanks!

Changes from v5:
  - Rename the policy from "adaptive" to "latency". The entire series
    updates policy names, function names, and variable names accordingly,
    without introducing any functional changes. (lsfmm discussion)
  - The second patch is now splitted into two patches:
    Patch #2: prep patch where we pass op_type to nvme_find_path()
    Patch #3: core patch which introduces latency I/O policy 
    (Sagi)
  - Rename ewma_update() to calc_ewma_update() (Sagi)
Link to v5: https://lore.kernel.org/all/20251105103347.86059-1-nilay@linux.ibm.com/

Changes from v4:
  - Added patch #7 which includes the documentation for adaptive I/O
    policy. (Guixin Liu)
Link to v4: https://lore.kernel.org/all/20251104104533.138481-1-nilay@linux.ibm.com/    

Changes from v3:
  - Update the adaptive APIs name (which actually enable/disable
    adaptive policy) to reflect the actual work it does. Also removed
    the misleading use of "current_path" from the adaptive policy code
    (Hannes Reinecke)
  - Move adaptive_ewma_shift and adaptive_weight_timeout attributes from
    sysfs to debugfs (Hannes Reinecke)
Link to v3: https://lore.kernel.org/all/20251027092949.961287-1-nilay@linux.ibm.com/

Changes from v2:
  - Addede a new patch to allow user to configure EWMA shift
    through sysfs (Hannes Reinecke)
  - Added a new patch to allow user to configure path weight
    calculation timeout (Hannes Reinecke)
  - Distinguish between read/write and other commands (e.g.
    admin comamnd) and calculate path weight for other commands
    which is separate from read/write weight. (Hannes Reinecke)
  - Normalize per-path weight in the range from 0-128 instead
    of 0-100 (Hannes Reinecke)
  - Restructure and optimize adaptive I/O forwarding code to use
    one loop instead of two (Hannes Reinecke)
Link to v2: https://lore.kernel.org/all/20251009100608.1699550-1-nilay@linux.ibm.com/

Changes from v1:
  - Ensure that the completion of I/O occurs on the same CPU as the
    submitting I/O CPU (Hannes Reinecke)
  - Remove adapter link speed from the path weight calculation
    (Hannes Reinecke)
  - Add adaptive I/O stat under debugfs instead of current sysfs
    (Hannes Reinecke)
  - Move path weight calculation to a workqueue from IO completion
    code path
Link to v1: https://lore.kernel.org/all/20250921111234.863853-1-nilay@linux.ibm.com/

Nilay Shroff (8):
  block: expose blk_stat_{enable,disable}_accounting() to drivers
  nvme-multipath: pass I/O type to nvme_find_path()
  nvme-multipath: add support for latency I/O policy
  nvme: add generic debugfs support
  nvme-multipath: add debugfs attribute latency_ewma_shift
  nvme-multipath: add debugfs attribute latency_batch_timeout
  nvme-multipath: add debugfs attribute latency_stat
  nvme-multipath: add documentation for latency I/O policy

 Documentation/admin-guide/nvme-multipath.rst |  19 +
 block/blk-stat.h                             |   4 -
 drivers/nvme/host/Makefile                   |   2 +-
 drivers/nvme/host/core.c                     |  21 +-
 drivers/nvme/host/debugfs.c                  | 345 ++++++++++++++
 drivers/nvme/host/ioctl.c                    |  38 +-
 drivers/nvme/host/multipath.c                | 446 ++++++++++++++++++-
 drivers/nvme/host/nvme.h                     |  84 +++-
 drivers/nvme/host/pr.c                       |   6 +-
 drivers/nvme/host/sysfs.c                    |   2 +-
 include/linux/blk-mq.h                       |   4 +
 11 files changed, 941 insertions(+), 30 deletions(-)
 create mode 100644 drivers/nvme/host/debugfs.c

-- 
2.53.0




More information about the Linux-nvme mailing list