From: sashiko-bot@kernel.org
To: "John Garry" <john.g.garry@oracle.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH v8 03/27] libmultipath: Add path selection support
Date: Mon, 07 Sep 2026 11:09:26 +0000 [thread overview]
Message-ID: <20260907110926.ED4271F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260907105021.1763236-4-john.g.garry@oracle.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
New issues:
- [High] Infinite loop in `mpath_round_robin_path()` if the current round-robin path is concurrently removed from the device list, causing an SRCU deadlock.
- [High] `mpath_round_robin_path` fast-path incorrectly returns an unlinked path, breaking failover.
- [Medium] Calling `list_is_singular()` on an RCU-protected list without holding the update lock causes a data race on `head->prev`.
- [Medium] Path selection functions bypass the `.is_optimized` callback, violating the API contract and causing inconsistent path evaluation.
- [Low] Missing bounds check on iopolicy index in `mpath_get_iopolicy`.
Pre-existing issues:
- [Medium] `mpath_device_set_live()` silently swallows setup failures, leaving the driver unaware of the aborted initialization.
--
commit 59f56cbf3b60a1ec3a1336f453b4cd772a005e7b
Author: John Garry <john.garry@linux.dev>
libmultipath: Add path selection support
This commit adds path selection support to libmultipath, providing
round-robin, NUMA, and queue-depth selection modes similar to NVMe. It also
abstracts NVMe ANA into enum mpath_access_state to allow SCSI ALUA usage
and introduces iopolicy management functions.
> diff --git a/lib/multipath.c b/lib/multipath.c
> index 574868ce53381..3541357d07f8d 100644
> --- a/lib/multipath.c
> +++ b/lib/multipath.c
> @@ -7,8 +7,245 @@
[ ... ]
> +int mpath_get_iopolicy(char *buf, int iopolicy)
> +{
> + return sprintf(buf, "%s\n", mpath_iopolicy_names[iopolicy]);
> +}
[Severity: Low]
Does this code overflow mpath_iopolicy_names[] if a caller provides an
uninitialized or out-of-bounds iopolicy value?
[ ... ]
> +static struct mpath_device *__mpath_find_path(struct mpath_head *mpath_head,
> + int node)
> +{
> + int found_distance = INT_MAX, fallback_distance = INT_MAX, distance;
> + struct mpath_device *found = NULL, *fallback = NULL, *mpath_device;
> +
> + list_for_each_entry_srcu(mpath_device, &mpath_head->dev_list, siblings,
> + srcu_read_lock_held(&mpath_head->srcu)) {
> + if (mpath_path_is_disabled(mpath_head, mpath_device))
> + continue;
[ ... ]
> + switch(mpath_device->access_state) {
> + case MPATH_STATE_OPTIMIZED:
[Severity: Medium]
Does this code bypass the driver's dynamic state evaluation by accessing
access_state directly instead of invoking the provided
mpath_path_is_optimized() callback wrapper?
If a driver like SCSI ALUA dynamically changes state, this will read
stale data.
> + if (distance < found_distance) {
> + found_distance = distance;
> + found = mpath_device;
> + }
> + break;
[ ... ]
> +static struct mpath_device *mpath_round_robin_path(
> + struct mpath_head *mpath_head)
> +{
> + struct mpath_device *mpath_device, *found = NULL;
> + int node = numa_node_id();
> + enum mpath_access_state access_state_old;
> + struct mpath_device *old =
> + srcu_dereference(mpath_head->current_path[node],
> + &mpath_head->srcu);
> +
> + if (unlikely(!old))
> + return __mpath_find_path(mpath_head, node);
> +
> + if (list_is_singular(&mpath_head->dev_list)) {
[Severity: Medium]
Calling list_is_singular() on an RCU-protected list without holding the
update lock causes a data race on head->prev. In RCU-protected lists,
only next pointers are safely updated for lockless readers.
[Severity: High]
Does this fast-path blindly return old without verifying if it is actually
the element present in the singular list?
If the previously cached old path was concurrently removed from dev_list
and exactly one valid path remains, list_is_singular() evaluates to true,
causing the function to incorrectly return the unlinked path instead of
the remaining valid path.
> + if (mpath_path_is_disabled(mpath_head, old))
> + return NULL;
> + return old;
> + }
> +
> + for (mpath_device = mpath_next_dev(mpath_head, old);
> + mpath_device && mpath_device != old;
> + mpath_device = mpath_next_dev(mpath_head, mpath_device)) {
[Severity: High]
Can this loop spin infinitely if old is concurrently removed from the
RCU-protected list?
The loop relies on reaching old again to terminate. If a concurrent writer
unlinks old using list_del_rcu(), it is removed from the circular list but
its next pointer remains intact. mpath_next_dev() follows old->next into
the remaining list elements, wrapping around and circling the remaining
elements indefinitely without ever evaluating mpath_device == old.
If all remaining paths are non-optimized or disabled, the loop never hits
the break condition, spinning forever under the SRCU read lock and stalling
any writer.
> +
> + if (mpath_path_is_disabled(mpath_head, mpath_device))
> + continue;
> + if (mpath_device->access_state == MPATH_STATE_OPTIMIZED) {
[Severity: Medium]
Similar to __mpath_find_path(), does this bypass the driver's dynamic state
evaluation by accessing access_state directly rather than calling the
mpath_path_is_optimized() callback wrapper?
> + found = mpath_device;
> + goto out;
> + }
> + if (mpath_device->access_state == MPATH_STATE_NONOPTIMIZED)
> + found = mpath_device;
> + }
[ ... ]
> @@ -133,6 +371,19 @@ void mpath_device_set_live(struct mpath_device *mpath_device)
> }
> queue_work(mpath_wq, &mpath_head->partition_scan_work);
> }
[Severity: Medium]
This is a pre-existing issue, but does mpath_device_set_live() silently
swallow setup failures earlier in this function?
If device_add_disk() fails, for example due to memory exhaustion, the
function clears the MPATH_HEAD_DISK_LIVE flag and returns early, masking
the failure from the caller and leaving the driver unaware of the aborted
initialization.
> +
> + mutex_lock(&mpath_head->lock);
> + if (mpath_path_is_optimized(mpath_head, mpath_device)) {
> + int node, srcu_idx;
> +
> + srcu_idx = srcu_read_lock(&mpath_head->srcu);
> + for_each_online_node(node)
> + __mpath_find_path(mpath_head, node);
> + srcu_read_unlock(&mpath_head->srcu, srcu_idx);
> + }
> + mutex_unlock(&mpath_head->lock);
> +
> + mpath_synchronize(mpath_head);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260907105021.1763236-1-john.g.garry@oracle.com?part=3
next prev parent reply other threads:[~2026-09-07 11:09 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 10:49 [PATCH v8 00/27] Native SCSI Multipath support John Garry
2026-09-07 10:49 ` [PATCH v8 01/27] libmultipath: Add initial framework John Garry
2026-09-07 10:49 ` [PATCH v8 02/27] libmultipath: Add basic gendisk support John Garry
2026-09-07 10:49 ` [PATCH v8 03/27] libmultipath: Add path selection support John Garry
2026-09-07 11:09 ` sashiko-bot [this message]
2026-09-07 12:00 ` John Garry
2026-09-07 10:49 ` [PATCH v8 04/27] libmultipath: Add bio handling John Garry
2026-09-07 10:49 ` [PATCH v8 05/27] libmultipath: Add support for mpath_device management John Garry
2026-09-07 10:50 ` [PATCH v8 06/27] libmultipath: Add delayed removal support John Garry
2026-09-07 11:23 ` sashiko-bot
2026-09-07 12:01 ` John Garry
2026-09-07 10:50 ` [PATCH v8 07/27] libmultipath: Add sysfs helpers John Garry
2026-09-07 10:50 ` [PATCH v8 08/27] libmultipath: Add support for block device IOCTL John Garry
2026-09-07 10:50 ` [PATCH v8 09/27] libmultipath: Add mpath_bdev_getgeo() John Garry
2026-09-07 10:50 ` [PATCH v8 10/27] libmultipath: Add mpath_bdev_get_unique_id() John Garry
2026-09-07 10:50 ` [PATCH v8 11/27] scsi-multipath: introduce basic SCSI device support John Garry
2026-09-07 11:33 ` sashiko-bot
2026-09-07 12:06 ` John Garry
2026-09-07 10:50 ` [PATCH v8 12/27] scsi-multipath: introduce scsi_device head structure John Garry
2026-09-07 10:50 ` [PATCH v8 13/27] scsi-multipath: provide sysfs link from to scsi_device John Garry
2026-09-07 10:50 ` [PATCH v8 14/27] scsi-multipath: support iopolicy John Garry
2026-09-07 10:50 ` [PATCH v8 15/27] scsi-multipath: clone each bio John Garry
2026-09-07 11:45 ` sashiko-bot
2026-09-07 12:08 ` John Garry
2026-09-07 10:50 ` [PATCH v8 16/27] scsi-multipath: clear path when device is blocked John Garry
2026-09-07 11:49 ` sashiko-bot
2026-09-07 12:08 ` John Garry
2026-09-07 10:50 ` [PATCH v8 17/27] scsi-multipath: revalidate paths upon device unblock John Garry
2026-09-07 11:56 ` sashiko-bot
2026-09-07 12:10 ` John Garry
2026-09-07 10:50 ` [PATCH v8 18/27] scsi-multipath: failover handling John Garry
2026-09-07 12:02 ` sashiko-bot
2026-09-07 12:13 ` John Garry
2026-09-07 10:50 ` [PATCH v8 19/27] scsi-multipath: provide callbacks for path state John Garry
2026-09-07 12:03 ` sashiko-bot
2026-09-07 12:14 ` John Garry
2026-09-07 10:50 ` [PATCH v8 20/27] scsi-multipath: add scsi_mpath_{start,end}_request() John Garry
2026-09-07 12:09 ` sashiko-bot
2026-09-07 12:22 ` John Garry
2026-09-07 10:50 ` [PATCH v8 21/27] scsi-multipath: add delayed disk removal support John Garry
2026-09-07 10:50 ` [PATCH v8 22/27] scsi: sd: add multipath disk class John Garry
2026-09-07 10:50 ` [PATCH v8 23/27] scsi: sd: add multipath disk attr groups John Garry
2026-09-07 10:50 ` [PATCH v8 24/27] scsi: sd: support multipath disk John Garry
2026-09-07 12:25 ` sashiko-bot
2026-09-07 12:34 ` John Garry
2026-09-07 10:50 ` [PATCH v8 25/27] scsi: sd: add mpath_dev file John Garry
2026-09-07 10:50 ` [PATCH v8 26/27] scsi: sd: add mpath_numa_nodes dev attribute John Garry
2026-09-07 10:50 ` [PATCH v8 27/27] scsi: sd: add mpath_queue_depth " John Garry
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260907110926.ED4271F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=john.g.garry@oracle.com \
--cc=linux-scsi@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox