On Mon, 2025-12-01 at 22:02 -0500, Benjamin Marzinski wrote:
> When libmpathpersist notifies multipathd that a key has been
> registered,
> cli_setprstatus() calls pr_register_active_paths() with a flag to let
> it
> know that the paths are likely already registered, and it can skip
> re-registering them, as long as the number of active paths matches
> the
> number of registered keys. This shortcut can fail, causing multipathd
> to
> not register needed paths, if either a path becomes usable and
> another
> becomes unusable while libmpathpersist is running or if there already
> were registered keys for I_T Nexus's that don't correspond to path
> devices.
>
> To make this shortcut work in cases like that, this commit adds a new
> multipathd command "setprstatus map <map> pathlist <pathlist>", where
> <pathlist> is a quoted, comma separated list of scsi path devices.
> libmpathpersist will send out the list of paths it registered the key
> on. pr_register_active_paths() will skip calling
> mpath_pr_event_handle()
> for paths on that list.
>
> In order to deal with the possiblity of a preempt occuring while
> libmpathpersist was running, the code still needs to check that it
> has
> the expected number of keys.
>
> Fixes: f7d6cd17 ("multipathd: Fix race while registering PR key")
> Signed-off-by: Benjamin Marzinski <[email protected]>
> ---
> libmpathpersist/mpath_persist_int.c | 6 +--
> libmpathpersist/mpath_updatepr.c | 48 +++++++++++++++++------
> libmpathpersist/mpathpr.h | 4 +-
> multipathd/callbacks.c | 1 +
> multipathd/cli.c | 1 +
> multipathd/cli.h | 2 +
> multipathd/cli_handlers.c | 39 ++++++++++++++++--
> multipathd/main.c | 61 +++++++++++++++++++--------
> --
> multipathd/main.h | 3 +-
> multipathd/multipathd.8.in | 6 +++
> 10 files changed, 132 insertions(+), 39 deletions(-)
>
>
> diff --git a/multipathd/main.c b/multipathd/main.c
> index a7650639..2cd5c952 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -630,28 +630,49 @@ flush_map_nopaths(struct multipath *mpp, struct
> vectors *vecs) {
> return true;
> }
>
> -void pr_register_active_paths(struct multipath *mpp, bool
> check_nr_active)
> +/*
> + * If reg_paths in non-NULL, it is a vector of paths that
> libmpathpersist
> + * registered. If the number of registered keys is smaller than the
> number
> + * of registered paths, then likely a preempt that occurred while
> + * libmpathpersist was registering the key. As long as there are
> still some
> + * registered keys, treat the preempt as happening first, and make
> sure to
> + * register keys on all the paths. If the number of registered keys
> is at
> + * least as large as the number of registered paths, then no preempt
> happened,
> + * and multipathd does not need to re-register the paths that
> libmpathpersist
> + * handled
> + */
> +void pr_register_active_paths(struct multipath *mpp,
> + const struct vector_s *reg_paths)
> {
> - unsigned int i, j, nr_keys = 0;
> - unsigned int nr_active = 0;
> + unsigned int i, j, k, nr_keys = 0;
> + unsigned int wanted_nr = VECTOR_SIZE(reg_paths);
> struct path *pp;
> struct pathgroup *pgp;
> -
> - if (check_nr_active) {
> - nr_active = count_active_paths(mpp);
> - if (!nr_active)
> - return;
> - }
> + char *pathname;
>
> vector_foreach_slot (mpp->pg, pgp, i) {
> vector_foreach_slot (pgp->paths, pp, j) {
> if (mpp->prflag == PR_UNSET)
> return;
> - if (pp->state == PATH_UP || pp->state ==
> PATH_GHOST) {
> - nr_keys = mpath_pr_event_handle(pp,
> nr_keys, nr_active);
> - if (check_nr_active && nr_keys ==
> nr_active)
> - return;
> + if (pp->state != PATH_UP && pp->state !=
> PATH_GHOST)
> + continue;
> + if (wanted_nr && nr_keys) {
> + vector_foreach_slot(reg_paths,
> pathname, k) {
> + if (strcmp(pp->dev,
> pathname) == 0 ||
> + strcmp(pp->dev_t,
> pathname) == 0) {
> + goto skip;
> + }
> + }
> + }
> + nr_keys = mpath_pr_event_handle(pp, nr_keys,
> wanted_nr);
> + if (nr_keys && nr_keys < wanted_nr) {
> + /*
> + * Incorrect number of registered
> keys. Need
> + * to register all devices
> + */
> + wanted_nr = 0;
> }
> +skip:
This fails on Debian Sid with this error messsage:
main.c:677:3: error: label at end of compound statement is a C23
extension [-Werror,-Wc23-extensions]
677 | }
|
[1]
https://github.com/openSUSE/multipath-tools/actions/runs/20031717354/job/57442300023
Martin