[PATCH v2 3/3] nvme: document the service-time iopolicy sysfs attributes
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Mon Oct 19 01:13:44 PDT 2026
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] nvme-multipath: nvme_failover_req() clears rq bytes before in_flight_size sub
- [High] nvme-multipath: in_flight_size underflow in nvme_mpath_end_request()
- [Low] nvme: missing service-time in sysfs-nvme iopolicy ABI documentation
--
commit 5acf4057a11f40dc3e2cd32f04002286c4084ff4
Author: Guixin Liu <kanie at linux.alibaba.com>
nvme: document the service-time iopolicy sysfs attributes
This commit documents the new in_flight_bytes and relative_throughput sysfs
attributes added for the service-time NVMe multipath I/O policy in
Documentation/ABI/stable/sysfs-nvme.
> diff --git a/Documentation/ABI/stable/sysfs-nvme b/Documentation/ABI/stable/sysfs-nvme
> index a2f5d0710db40..adaf292c8c67b 100644
> --- a/Documentation/ABI/stable/sysfs-nvme
> +++ b/Documentation/ABI/stable/sysfs-nvme
> @@ -326,6 +326,28 @@ Description:
> currently selected path. Returns empty if iopolicy is not
> "numa". Requires CONFIG_NVME_MULTIPATH.
>
> +What: /sys/block/nvmeXcYnZ/in_flight_bytes
> +What: /sys/block/nvmeXcYnZ/relative_throughput
> +Date: October 2026
> +KernelVersion: 7.5
> +Contact: Guixin Liu <kanie at linux.alibaba.com>
> +Description:
> + in_flight_bytes: Shows the number of bytes currently in
> + flight on this path's controller. Returns empty if
> + iopolicy is not "service-time".
> + Requires CONFIG_NVME_MULTIPATH.
[Severity: High]
Can ns->ctrl->in_flight_size permanently leak in-flight bytes when a
request fails over in nvme_failover_req()?
In commit 211891d7cca0 ("nvme-multipath: implement service-time iopolicy"),
nvme_mpath_start_request() adds blk_rq_bytes(rq) to ns->ctrl->in_flight_size
and sets NVME_MPATH_CNT_ACTIVE_BYTES:
drivers/nvme/host/multipath.c:nvme_mpath_start_request() {
...
} else if (iopolicy == NVME_IOPOLICY_ST &&
!(nvme_req(rq)->flags & NVME_MPATH_CNT_ACTIVE_BYTES)) {
atomic64_add(blk_rq_bytes(rq), &ns->ctrl->in_flight_size);
nvme_req(rq)->flags |= NVME_MPATH_CNT_ACTIVE_BYTES;
}
}
When a request fails over (for example, on NVME_SC_ANA_TRANSITION,
NVME_SC_HOST_PATH_ERROR, or a dying queue), __nvme_complete_rq() calls
nvme_failover_req(), which steals the bios from req before calling
nvme_end_req():
drivers/nvme/host/multipath.c:nvme_failover_req() {
...
blk_steal_bios(&ns->head->requeue_list, req);
spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
nvme_req(req)->status = 0;
nvme_end_req(req);
}
Because blk_steal_bios() clears rq->__data_len:
block/blk-mq.c:blk_steal_bios() {
...
rq->__data_len = 0;
}
by the time nvme_end_req() -> __nvme_end_req() -> nvme_mpath_end_request()
runs:
drivers/nvme/host/multipath.c:nvme_mpath_end_request() {
...
if (nvme_req(rq)->flags & NVME_MPATH_CNT_ACTIVE_BYTES) {
atomic64_sub(blk_rq_bytes(rq), &ns->ctrl->in_flight_size);
nvme_req(rq)->flags &= ~NVME_MPATH_CNT_ACTIVE_BYTES;
}
}
blk_rq_bytes(rq) is 0, so the failed-over request's bytes are never
subtracted from ns->ctrl->in_flight_size. When failover occurs without a
controller reset, does ns->ctrl->in_flight_size remain permanently
inflated, skewing nvme_st_compare_load() and the in_flight_bytes sysfs
attribute?
[Severity: High]
Also in nvme_mpath_end_request(), can ns->ctrl->in_flight_size underflow
to a negative value if a requeued request completes after a controller
reset?
When a request started under NVME_IOPOLICY_ST is requeued via
nvme_retry_req() -> blk_mq_requeue_request() (or via BLK_STS_RESOURCE after
nvme_start_request() in nvme_rdma_queue_rq() or nvme_fc_start_fcp_op()),
the request returns to MQ_RQ_IDLE while retaining RQF_DONTPREP and
NVME_MPATH_CNT_ACTIVE_BYTES.
If a controller reset occurs before that request is re-dispatched,
nvme_mpath_init_identify() resets ctrl->in_flight_size to 0:
drivers/nvme/host/multipath.c:nvme_mpath_init_identify() {
...
/* initialize this in the identify path to cover controller resets */
atomic_set(&ctrl->nr_active, 0);
atomic64_set(&ctrl->in_flight_size, 0);
}
When the request is later re-dispatched, nvme_setup_cmd() skips
nvme_clear_nvme_request() because RQF_DONTPREP is set, and
nvme_mpath_start_request() skips atomic64_add() because
NVME_MPATH_CNT_ACTIVE_BYTES is already set. When the request finishes,
nvme_mpath_end_request() unconditionally subtracts blk_rq_bytes(rq) from
ns->ctrl->in_flight_size (unlike nr_active, which uses
atomic_dec_if_positive()), driving ctrl->in_flight_size negative.
In nvme_st_compare_load(), the negative s64 is then assigned to unsigned
size_t:
drivers/nvme/host/multipath.c:nvme_st_compare_load() {
size_t sz1, sz2, st1, st2;
unsigned int tp1 = ns1->ctrl->relative_throughput;
unsigned int tp2 = ns2->ctrl->relative_throughput;
sz1 = atomic64_read(&ns1->ctrl->in_flight_size);
sz2 = atomic64_read(&ns2->ctrl->in_flight_size);
Would this wrap sz1 or sz2 to near SIZE_MAX, causing
nvme_service_time_path() to avoid that controller's path while reporting a
negative value in in_flight_bytes?
> +
> + relative_throughput: Shows or sets the relative
> + throughput weight of this path, which the "service-time"
> + iopolicy uses to estimate the path service time as
> + in_flight_bytes / relative_throughput. The value is an
> + integer in the range 0-100 and defaults to 1; assign
> + higher values to faster paths. A path with a value of 0
> + is only selected when no path with a positive value is
> + available. Reading returns empty if iopolicy is not
> + "service-time"; writing is accepted regardless of the
> + active policy. Requires CONFIG_NVME_MULTIPATH.
> +
> What: /sys/block/nvmeXnY/delayed_removal_secs
> Date: May 2025
> KernelVersion: 6.16
[Severity: Low]
In the same file (Documentation/ABI/stable/sysfs-nvme), the entry for
/sys/class/nvme-subsystem/nvme-subsysX/iopolicy still lists only the three
previous policies:
What: /sys/class/nvme-subsystem/nvme-subsysX/iopolicy
...
Description:
Shows or sets the multipath I/O path selection policy for
this subsystem. Accepted values: "numa", "round-robin",
"queue-depth". Changing the policy clears all current path
selections. Only available when CONFIG_NVME_MULTIPATH is
enabled.
Should "service-time" also be added to the accepted values for
/sys/class/nvme-subsystem/nvme-subsysX/iopolicy?
هایی
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019075607.808947-1-kanie@linux.alibaba.com?part=3
More information about the Linux-nvme
mailing list