[PATCH v2 3/3] nvme: document the service-time iopolicy sysfs attributes
Guixin Liu
kanie at linux.alibaba.com
Mon Oct 19 04:13:21 PDT 2026
在 2026/10/19 16:13, sashiko-bot at kernel.org 写道:
> 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?
Right, fixed in v3.
>
> [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?
Yes, fixed in v3.
>> +
>> + 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?
>
> هایی
Sure, changed in v3.
More information about the Linux-nvme
mailing list