[dm-devel] [PATCH V2 01/11] libmultipath: add group_by_tpg path_grouping_policy

Martin Wilck martin.wilck at suse.com
Wed Jun 7 18:31:19 UTC 2023


On Tue, 2023-06-06 at 15:13 -0500, Benjamin Marzinski wrote:
> When we group paths by prio and the priority changes, paths can end
> up
> temporarily in the wrong path groups.  This usually happens when some
> paths are down, so their priority can't be updated. To avoid this for
> ALUA paths, group them by their target port group instead. The path
> groups chosen by this policy won't always match with those chosen by
> group_by_prio, since it is possible for multiple ALUA target port
> groups to have the same priority.
> 
> Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
> ---
>  libmultipath/discovery.c         |  1 +
>  libmultipath/pgpolicies.c        | 19 +++++++++++++++++++
>  libmultipath/pgpolicies.h        |  4 +++-
>  libmultipath/prioritizers/alua.c |  1 +
>  libmultipath/propsel.c           | 27 +++++++++++++++++++++++++--
>  libmultipath/structs.c           |  1 +
>  libmultipath/structs.h           |  3 +++
>  multipath/main.c                 |  1 +
>  multipath/multipath.conf.5       |  4 ++++
>  9 files changed, 58 insertions(+), 3 deletions(-)
> 
> diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
> index 6865cd92..2dcafe5d 100644
> --- a/libmultipath/discovery.c
> +++ b/libmultipath/discovery.c
> @@ -1051,6 +1051,7 @@ detect_alua(struct path * pp)
>                 return;
>         }
>         pp->tpgs = tpgs;
> +       pp->tpg_id = ret;
>  }
>  
>  int path_get_tpgs(struct path *pp)
> diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
> index 10b44d37..e14da8cc 100644
> --- a/libmultipath/pgpolicies.c
> +++ b/libmultipath/pgpolicies.c
> @@ -25,6 +25,8 @@ int get_pgpolicy_id(char * str)
>                 return GROUP_BY_PRIO;
>         if (0 == strncmp(str, "group_by_node_name", 18))
>                 return GROUP_BY_NODE_NAME;
> +       if (0 == strncmp(str, "group_by_tpg", 12))
> +               return GROUP_BY_TPG;
>  
>         return IOPOLICY_UNDEF;
>  }
> @@ -49,6 +51,9 @@ int get_pgpolicy_name(char * buff, int len, int id)
>         case GROUP_BY_NODE_NAME:
>                 s = "group_by_node_name";
>                 break;
> +       case GROUP_BY_TPG:
> +               s = "group_by_tpg";
> +               break;
>         default:
>                 s = "undefined";
>                 break;
> @@ -191,6 +196,12 @@ prios_match(struct path *pp1, struct path *pp2)
>         return (pp1->priority == pp2->priority);
>  }
>  
> +bool
> +tpg_match(struct path *pp1, struct path *pp2)
> +{
> +       return (pp1->tpg_id == pp2->tpg_id);
> +}
> +
>  int group_by_match(struct multipath * mp, vector paths,
>                    bool (*path_match_fn)(struct path *, struct path
> *))
>  {
> @@ -279,6 +290,14 @@ int group_by_prio(struct multipath *mp, vector
> paths)
>         return group_by_match(mp, paths, prios_match);
>  }
>  
> +/*
> + * One path group per alua target port group present in the path
> vector
> + */
> +int group_by_tpg(struct multipath *mp, vector paths)
> +{
> +       return group_by_match(mp, paths, tpg_match);
> +}
> +
>  int one_path_per_group(struct multipath *mp, vector paths)
>  {
>         int i;
> diff --git a/libmultipath/pgpolicies.h b/libmultipath/pgpolicies.h
> index 15927610..d3ab2f35 100644
> --- a/libmultipath/pgpolicies.h
> +++ b/libmultipath/pgpolicies.h
> @@ -16,7 +16,8 @@ enum iopolicies {
>         MULTIBUS,
>         GROUP_BY_SERIAL,
>         GROUP_BY_PRIO,
> -       GROUP_BY_NODE_NAME
> +       GROUP_BY_NODE_NAME,
> +       GROUP_BY_TPG,
>  };
>  
>  int get_pgpolicy_id(char *);
> @@ -30,5 +31,6 @@ int one_group(struct multipath *, vector);
>  int group_by_serial(struct multipath *, vector);
>  int group_by_prio(struct multipath *, vector);
>  int group_by_node_name(struct multipath *, vector);
> +int group_by_tpg(struct multipath *, vector);
>  
>  #endif
> diff --git a/libmultipath/prioritizers/alua.c
> b/libmultipath/prioritizers/alua.c
> index 0ab06e2b..4888a974 100644
> --- a/libmultipath/prioritizers/alua.c
> +++ b/libmultipath/prioritizers/alua.c
> @@ -65,6 +65,7 @@ get_alua_info(struct path * pp, unsigned int
> timeout)
>                         return -ALUA_PRIO_NOT_SUPPORTED;
>                 return -ALUA_PRIO_RTPG_FAILED;
>         }
> +       pp->tpg_id = tpg;
>         condlog(3, "%s: reported target port group is %i", pp->dev,


I still think that we should log a change here. Perhaps we should keep
the existing condlog() and just use prio 2 if the tpg_id changed, and
prio 4 if it didn't (the current 3 clutters the logs quite a bit).

Regards
Martin



> tpg);
>         rc = get_asymmetric_access_state(pp, tpg, timeout);
>         if (rc < 0) {
> diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
> index a25cc921..841fa247 100644
> --- a/libmultipath/propsel.c
> +++ b/libmultipath/propsel.c
> @@ -35,7 +35,8 @@ pgpolicyfn *pgpolicies[] = {
>         one_group,
>         group_by_serial,
>         group_by_prio,
> -       group_by_node_name
> +       group_by_node_name,
> +       group_by_tpg,
>  };
>  
>  #define do_set(var, src, dest,
> msg)                                    \
> @@ -249,10 +250,26 @@ out:
>         return 0;
>  }
>  
> +static bool
> +verify_alua_prio(struct multipath *mp)
> +{
> +       int i;
> +       struct path *pp;
> +
> +       vector_foreach_slot(mp->paths, pp, i) {
> +               const char *name = prio_name(&pp->prio);
> +               if (strncmp(name, PRIO_ALUA, PRIO_NAME_LEN) &&
> +                   strncmp(name, PRIO_SYSFS, PRIO_NAME_LEN))
> +                        return false;
> +       }
> +       return true;
> +}
> +
>  int select_pgpolicy(struct config *conf, struct multipath * mp)
>  {
>         const char *origin;
>         char buff[POLICY_NAME_SIZE];
> +       int log_prio = 3;
>  
>         if (conf->pgpolicy_flag > 0) {
>                 mp->pgpolicy = conf->pgpolicy_flag;
> @@ -265,9 +282,15 @@ int select_pgpolicy(struct config *conf, struct
> multipath * mp)
>         mp_set_conf(pgpolicy);
>         mp_set_default(pgpolicy, DEFAULT_PGPOLICY);
>  out:
> +       if (mp->pgpolicy == GROUP_BY_TPG && !verify_alua_prio(mp)) {
> +               mp->pgpolicy = DEFAULT_PGPOLICY;
> +               origin = "(setting: emergency fallback - not all
> paths use alua prio)";
> +               log_prio = 1;
> +       }
>         mp->pgpolicyfn = pgpolicies[mp->pgpolicy];
>         get_pgpolicy_name(buff, POLICY_NAME_SIZE, mp->pgpolicy);
> -       condlog(3, "%s: path_grouping_policy = %s %s", mp->alias,
> buff, origin);
> +       condlog(log_prio, "%s: path_grouping_policy = %s %s", mp-
> >alias, buff,
> +               origin);
>         return 0;
>  }
>  
> diff --git a/libmultipath/structs.c b/libmultipath/structs.c
> index 87e84d5d..39504dca 100644
> --- a/libmultipath/structs.c
> +++ b/libmultipath/structs.c
> @@ -125,6 +125,7 @@ alloc_path (void)
>                 pp->sg_id.proto_id = PROTOCOL_UNSET;
>                 pp->fd = -1;
>                 pp->tpgs = TPGS_UNDEF;
> +               pp->tpg_id = GROUP_ID_UNDEF;
>                 pp->priority = PRIO_UNDEF;
>                 pp->checkint = CHECKINT_UNDEF;
>                 checker_clear(&pp->checker);
> diff --git a/libmultipath/structs.h b/libmultipath/structs.h
> index a1208751..0eea19b4 100644
> --- a/libmultipath/structs.h
> +++ b/libmultipath/structs.h
> @@ -317,6 +317,8 @@ struct hd_geometry {
>  };
>  #endif
>  
> +#define GROUP_ID_UNDEF -1
> +
>  struct path {
>         char dev[FILE_NAME_SIZE];
>         char dev_t[BLK_DEV_SIZE];
> @@ -372,6 +374,7 @@ struct path {
>         /* configlet pointers */
>         vector hwe;
>         struct gen_path generic_path;
> +       int tpg_id;
>  };
>  
>  typedef int (pgpolicyfn) (struct multipath *, vector);
> diff --git a/multipath/main.c b/multipath/main.c
> index 90f940f1..b78f3162 100644
> --- a/multipath/main.c
> +++ b/multipath/main.c
> @@ -157,6 +157,7 @@ usage (char * progname)
>                 "          . group_by_serial     one priority group
> per serial\n"
>                 "          . group_by_prio       one priority group
> per priority lvl\n"
>                 "          . group_by_node_name  one priority group
> per target node\n"
> +               "          . group_by_tpg        one priority group
> per ALUA target port group\n"
>                 "  -v lvl  verbosity level:\n"
>                 "          . 0 no output\n"
>                 "          . 1 print created devmap names only\n"
> diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
> index b4dccd1b..b65a543d 100644
> --- a/multipath/multipath.conf.5
> +++ b/multipath/multipath.conf.5
> @@ -233,6 +233,10 @@ per-multipath option in the configuration file.
>  One priority group per target node name. Target node names are
> fetched
>  in \fI/sys/class/fc_transport/target*/node_name\fR.
>  .TP
> +.I group_by_tpg
> +One priority group per ALUA target port group. In order to use this
> policy,
> +all paths in the multipath device must have \fIprio\fR set to
> \fBalua\fR.
> +.TP
>  The default is: \fBfailover\fR
>  .RE
>  .



More information about the dm-devel mailing list