[dm-devel] [PATCH 3/5] multipathd: refresh all priorities if one has changed
Martin Wilck
martin.wilck at suse.com
Wed May 31 16:27:25 UTC 2023
On Wed, 2023-05-24 at 18:21 -0500, Benjamin Marzinski wrote:
> For multipath devices with path group policies other than
> group_by_prio,
> multipathd wasn't updating all the paths' priorities when calling
> need_switch_pathgroup(), even in cases where it likely was necessary.
> When a path just becomes usable again, all paths' priorities get
> updated
> by update_prio(). But if the priority changes on a path that is
> already
> up, the other paths' priorities only get updated if the multipath
> device
> uses the group_by_prio path_grouping_policy, otherwise
> need_switch_pathgroup() is called with refresh set to 0. But if the
> priority of the checked path has changed, then likely so have the
> priorities of other paths. Since the pathgroup's priority is the
> average
> of its paths' priorities, changing the priority of just one path may
> not
> change the average enough to reorder the pathgroups.
>
> Instead, set refresh in need_switch_pathgroup() if the priorty has
> changed to something other than PRIO_UNDEF (which usually means an
> error
> has occured) and the priorities of the other paths haven't already
> been
> updated by update_prio().
>
> Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
> ---
> multipathd/main.c | 35 +++++++++++++++++++++--------------
> 1 file changed, 21 insertions(+), 14 deletions(-)
>
> diff --git a/multipathd/main.c b/multipathd/main.c
> index bdeffe76..e7c272ad 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -2575,20 +2575,27 @@ check_path (struct vectors * vecs, struct
> path * pp, unsigned int ticks)
>
> if (marginal_changed)
> reload_and_sync_map(pp->mpp, vecs, 1);
> - else if (update_prio(pp, new_path_up) &&
> - (pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio) &&
> - pp->mpp->pgfailback == -FAILBACK_IMMEDIATE) {
> - condlog(2, "%s: path priorities changed. reloading",
> - pp->mpp->alias);
> - reload_and_sync_map(pp->mpp, vecs, !new_path_up);
> - } else if (need_switch_pathgroup(pp->mpp, 0)) {
> - if (pp->mpp->pgfailback > 0 &&
> - (new_path_up || pp->mpp->failback_tick <= 0))
> - pp->mpp->failback_tick =
> - pp->mpp->pgfailback + 1;
> - else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE
> ||
> - (chkr_new_path_up &&
> followover_should_failback(pp)))
> - switch_pathgroup(pp->mpp);
> + else {
> + int prio_changed = update_prio(pp, new_path_up);
> + bool need_refresh = (!new_path_up && prio_changed &&
> + pp->priority != PRIO_UNDEF);
> +
I have always found it confusing that we recalculate the priorities in
two functions (update_prio() and need_switch_pathgroup()), passing
boolean flags back and forth. IMO we should move this logic to
update_prio(), so that we don't need to refresh any priorities in
need_switch_pathgroup() any more. after determining the prio of the
"primary" path device, update_prio() has all the information
it needs to figure out whether priorities of other paths must be
refreshed.
That would even make the code easier to understand, IMO.
Regards
Martin
> + if (prio_changed &&
> + pp->mpp->pgpolicyfn == (pgpolicyfn
> *)group_by_prio &&
> + pp->mpp->pgfailback == -FAILBACK_IMMEDIATE) {
> + condlog(2, "%s: path priorities changed.
> reloading",
> + pp->mpp->alias);
> + reload_and_sync_map(pp->mpp, vecs,
> !new_path_up);
> + } else if (need_switch_pathgroup(pp->mpp,
> need_refresh)) {
> + if (pp->mpp->pgfailback > 0 &&
> + (new_path_up || pp->mpp->failback_tick <=
> 0))
> + pp->mpp->failback_tick =
> + pp->mpp->pgfailback + 1;
> + else if (pp->mpp->pgfailback == -
> FAILBACK_IMMEDIATE ||
> + (chkr_new_path_up &&
> + followover_should_failback(pp)))
> + switch_pathgroup(pp->mpp);
> + }
> }
> return 1;
> }
More information about the dm-devel
mailing list