Re: [PATCH v6 03/27] libmultipath: Add path selection support
[email protected] Wed, 29 Jul 2026 11:33:19 +0000
| Newsgroups | org.kernel.vger.linux-scsi |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: New issues: - [High] Round-robin path selection behaves as reverse round-robin for non-optimized paths due to a missing loop break. - [High] Unsafe and logically flawed use of `list_is_singular` on an RCU-protected list routes I/O to a removed device. Pre-existing issues: - [High] mpath_head_uninit() blocks indefinitely waiting for user-space to close the block device. -- --- Patch [3]: [PATCH v6 03/27] libmultipath: Add path selection support --- commit 70a41be1b0a598af8cbd34732b889f79118d17ac Author: John Garry <[email protected]> libmultipath: Add path selection support This commit adds code for path selection support in libmultipath. It abstracts NVMe ANA into mpath_access_state to allow SCSI ALUA usage and adds round-robin, NUMA, and queue-depth selection modes. It also introduces functions to set and get the default I/O policy. > diff --git a/lib/multipath.c b/lib/multipath.c > index 1cf20b0f62d07..26714116023a3 100644 > --- a/lib/multipath.c > +++ b/lib/multipath.c [ ... ] > @@ -7,8 +7,245 @@ > +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: High] Does using list_is_singular() here on an SRCU-protected list introduce a data race on head->prev? Additionally, if old is concurrently removed and exactly one other active device remains in the list, list_is_singular() evaluates to true. Will this cause the function to return the unlinked old path instead of the valid active 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)) { > + > + if (mpath_path_is_disabled(mpath_head, mpath_device)) > + continue; > + if (mpath_device->access_state == MPATH_STATE_OPTIMIZED) { > + found = mpath_device; > + goto out; > + } > + if (mpath_device->access_state == MPATH_STATE_NONOPTIMIZED) > + found = mpath_device; [Severity: High] For the MPATH_STATE_NONOPTIMIZED case, found is overwritten unconditionally. Because there is no loop break or check like if (!found), will this evaluate multiple non-optimized paths and incorrectly select the last available one rather than the next available one? > + } [ ... ] [Severity: High] This is a pre-existing issue, but I noticed a potential problem during teardown in mpath_head_uninit(): lib/multipath.c:mpath_head_uninit() { ... if (!refcount_dec_and_test(refcount)) wait_var_event(refcount, !refcount_read(refcount)); } Since a reference is taken for every user-space open, can wait_var_event() block indefinitely if a user process holds the device open while the driver is unbound or the device is hot-unplugged? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=3