[dm-devel] [PATCH v2 3/7] libmultipath: add a protocol subsection to multipath.conf

Martin Wilck martin.wilck at suse.com
Thu Apr 14 07:27:59 UTC 2022


On Wed, 2022-04-13 at 23:27 -0500, Benjamin Marzinski wrote:
> Some storage arrays can be accessed using multiple protocols at the
> same
> time.  In these cases, users may want to set path attributes
> differently, depending on the protocol that the path is using. To
> allow
> this, add a protocol subsection to the overrides section in
> multipath.conf, which allows select path-specific options to be set.
> This commit simply adds the subsection, and handles merging matching
> entries. Future patches will make use of the section.
> 
> Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>

Looks good, just a minor nit below.

> ---
>  libmultipath/config.c | 83 ++++++++++++++++++++++++++++++++++++
>  libmultipath/config.h | 10 +++++
>  libmultipath/dict.c   | 99
> +++++++++++++++++++++++++++++++++++++++++++
>  libmultipath/print.c  | 50 ++++++++++++++++++++++
>  4 files changed, 242 insertions(+)
> 
> diff --git a/libmultipath/config.c b/libmultipath/config.c
> index 612941b8..5fe71562 100644
> --- a/libmultipath/config.c
> +++ b/libmultipath/config.c
> @@ -237,6 +237,18 @@ const char *get_mpe_wwid(const struct _vector
> *mptable, const char *alias)
>         return NULL;
>  }
>  
> +static void
> +free_pctable (vector pctable)
> +{
> +       int i;
> +       struct pcentry *pce;
> +
> +       vector_foreach_slot(pctable, pce, i)
> +               free(pce);
> +
> +       vector_free(pctable);
> +}
> +
>  void
>  free_hwe (struct hwentry * hwe)
>  {
> @@ -282,6 +294,9 @@ free_hwe (struct hwentry * hwe)
>         if (hwe->bl_product)
>                 free(hwe->bl_product);
>  
> +       if (hwe->pctable)
> +               free_pctable(hwe->pctable);
> +
>         free(hwe);
>  }
>  
> @@ -363,6 +378,15 @@ alloc_hwe (void)
>         return hwe;
>  }
>  
> +struct pcentry *
> +alloc_pce (void)
> +{
> +       struct pcentry *pce = (struct pcentry *)
> +                               calloc(1, sizeof(struct pcentry));
> +       pce->type = -1;


Use a symbolic value, like PCE_INVALID?

> +       return pce;
> +}
> +
>  static char *
>  set_param_str(const char * str)
>  {
> @@ -396,6 +420,13 @@ set_param_str(const char * str)
>         if (!dst->s && src->s) \
>                 dst->s = src->s
>  
> +static void
> +merge_pce(struct pcentry *dst, struct pcentry *src)
> +{
> +       merge_num(fast_io_fail);
> +       merge_num(dev_loss);
> +       merge_num(eh_deadline);
> +}
>  
>  static void
>  merge_hwe (struct hwentry * dst, struct hwentry * src)
> @@ -602,6 +633,51 @@ out:
>         return 1;
>  }
>  
> +static void
> +validate_pctable(struct hwentry *ovr, int idx, const char
> *table_desc)
> +{
> +       struct pcentry *pce;
> +
> +       if (!ovr || !ovr->pctable)
> +               return;
> +
> +       vector_foreach_slot_after(ovr->pctable, pce, idx) {
> +               if (pce->type < 0) {
> +                       condlog(0, "protocol section in %s missing
> type",
> +                               table_desc);
> +                       vector_del_slot(ovr->pctable, idx--);
> +                       free(pce);
> +               }
> +       }
> +
> +       if (VECTOR_SIZE(ovr->pctable) == 0) {
> +               vector_free(ovr->pctable);
> +               ovr->pctable = NULL;
> +       }
> +}
> +
> +static void
> +merge_pctable(struct hwentry *ovr)
> +{
> +       struct pcentry *pce1, *pce2;
> +       int i, j;
> +
> +       if (!ovr || !ovr->pctable)
> +               return;
> +
> +       vector_foreach_slot(ovr->pctable, pce1, i) {
> +               j = i + 1;
> +               vector_foreach_slot_after(ovr->pctable, pce2, j) {
> +                       if (pce1->type != pce2->type)
> +                               continue;
> +                       merge_pce(pce2,pce1);
> +                       vector_del_slot(ovr->pctable, i--);
> +                       free(pce1);
> +                       break;
> +               }
> +       }
> +}
> +
>  static void
>  factorize_hwtable (vector hw, int n, const char *table_desc)
>  {
> @@ -750,6 +826,7 @@ process_config_dir(struct config *conf, char
> *dir)
>         int i, n;
>         char path[LINE_MAX];
>         int old_hwtable_size;
> +       int old_pctable_size = 0;
>  
>         if (dir[0] != '/') {
>                 condlog(1, "config_dir '%s' must be a fully qualified
> path",
> @@ -776,11 +853,15 @@ process_config_dir(struct config *conf, char
> *dir)
>                         continue;
>  
>                 old_hwtable_size = VECTOR_SIZE(conf->hwtable);
> +               old_pctable_size = conf->overrides ?
> +                                  VECTOR_SIZE(conf->overrides-
> >pctable) : 0;
>                 snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]-
> >d_name);
>                 path[LINE_MAX-1] = '\0';
>                 process_file(conf, path);
>                 factorize_hwtable(conf->hwtable, old_hwtable_size,
>                                   namelist[i]->d_name);
> +               validate_pctable(conf->overrides, old_pctable_size,
> +                                namelist[i]->d_name);
>         }
>         pthread_cleanup_pop(1);
>  }
> @@ -888,6 +969,7 @@ int _init_config (const char *file, struct config
> *conf)
>                         goto out;
>                 }
>                 factorize_hwtable(conf->hwtable,
> builtin_hwtable_size, file);
> +               validate_pctable(conf->overrides, 0, file);
>         }
>  
>         conf->processed_main_config = 1;
> @@ -988,6 +1070,7 @@ int _init_config (const char *file, struct
> config *conf)
>                         goto out;
>         }
>  
> +       merge_pctable(conf->overrides);
>         merge_mptable(conf->mptable);
>         merge_blacklist(conf->blist_devnode);
>         merge_blacklist(conf->blist_property);
> diff --git a/libmultipath/config.h b/libmultipath/config.h
> index c73389b5..b7bca9a8 100644
> --- a/libmultipath/config.h
> +++ b/libmultipath/config.h
> @@ -40,6 +40,13 @@ enum force_reload_types {
>         FORCE_RELOAD_WEAK,
>  };
>  
> +struct pcentry {
> +       int type;
> +       int fast_io_fail;
> +       unsigned int dev_loss;
> +       int eh_deadline;
> +};
> +
>  struct hwentry {
>         char * vendor;
>         char * product;
> @@ -85,6 +92,8 @@ struct hwentry {
>         int vpd_vendor_id;
>         int recheck_wwid;
>         char * bl_product;
> +
> +       vector pctable;
>  };
>  
>  struct mpentry {
> @@ -284,6 +293,7 @@ const char *get_mpe_wwid (const struct _vector
> *mptable, const char *alias);
>  
>  struct hwentry * alloc_hwe (void);
>  struct mpentry * alloc_mpe (void);
> +struct pcentry * alloc_pce (void);
>  
>  void free_hwe (struct hwentry * hwe);
>  void free_hwtable (vector hwtable);
> diff --git a/libmultipath/dict.c b/libmultipath/dict.c
> index 26cbe785..8e11fd70 100644
> --- a/libmultipath/dict.c
> +++ b/libmultipath/dict.c
> @@ -417,6 +417,29 @@ snprint_mp_ ## option (struct config *conf,
> struct strbuf *buff,   \
>         return function(buff, mpe-
> >option);                             \
>  }
>  
> +#define declare_pc_handler(option,
> function)                           \
> +static
> int                                                             \
> +pc_ ## option ## _handler (struct config *conf, vector
> strvec,         \
> +                          const char *file, int
> line_nr)               \
> +{                                                                   
>    \
> +       struct pcentry
> *pce;                                            \
> +       if (!conf->overrides || !conf->overrides-
> >pctable)              \
> +               return
> 1;                                               \
> +       pce = VECTOR_LAST_SLOT(conf->overrides-
> >pctable);               \
> +       if
> (!pce)                                                       \
> +               return
> 1;                                               \
> +       return function (strvec, &pce->option, file,
> line_nr);          \
> +}
> +
> +#define declare_pc_snprint(option,
> function)                           \
> +static
> int                                                             \
> +snprint_pc_ ## option (struct config *conf, struct strbuf
> *buff,       \
> +                      const void
> *data)                                \
> +{                                                                   
>    \
> +       const struct pcentry *pce  = (const struct pcentry
> *)data;      \
> +       return function(buff, pce-
> >option);                             \
> +}
> +
>  static int checkint_handler(struct config *conf, vector strvec,
>                             const char *file, int line_nr)
>  {
> @@ -1046,6 +1069,8 @@ declare_ovr_handler(fast_io_fail,
> set_undef_off_zero)
>  declare_ovr_snprint(fast_io_fail, print_undef_off_zero)
>  declare_hw_handler(fast_io_fail, set_undef_off_zero)
>  declare_hw_snprint(fast_io_fail, print_undef_off_zero)
> +declare_pc_handler(fast_io_fail, set_undef_off_zero)
> +declare_pc_snprint(fast_io_fail, print_undef_off_zero)
>  
>  static int
>  set_dev_loss(vector strvec, void *ptr, const char *file, int
> line_nr)
> @@ -1083,6 +1108,8 @@ declare_ovr_handler(dev_loss, set_dev_loss)
>  declare_ovr_snprint(dev_loss, print_dev_loss)
>  declare_hw_handler(dev_loss, set_dev_loss)
>  declare_hw_snprint(dev_loss, print_dev_loss)
> +declare_pc_handler(dev_loss, set_dev_loss)
> +declare_pc_snprint(dev_loss, print_dev_loss)
>  
>  declare_def_handler(eh_deadline, set_undef_off_zero)
>  declare_def_snprint(eh_deadline, print_undef_off_zero)
> @@ -1090,6 +1117,8 @@ declare_ovr_handler(eh_deadline,
> set_undef_off_zero)
>  declare_ovr_snprint(eh_deadline, print_undef_off_zero)
>  declare_hw_handler(eh_deadline, set_undef_off_zero)
>  declare_hw_snprint(eh_deadline, print_undef_off_zero)
> +declare_pc_handler(eh_deadline, set_undef_off_zero)
> +declare_pc_snprint(eh_deadline, print_undef_off_zero)
>  
>  static int
>  set_pgpolicy(vector strvec, void *ptr, const char *file, int
> line_nr)
> @@ -1897,6 +1926,69 @@ declare_mp_snprint(wwid, print_str)
>  declare_mp_handler(alias, set_str_noslash)
>  declare_mp_snprint(alias, print_str)
>  
> +
> +static int
> +protocol_handler(struct config *conf, vector strvec, const char
> *file,
> +               int line_nr)
> +{
> +       struct pcentry *pce;
> +
> +       if (!conf->overrides)
> +               return 1;
> +
> +       if (!conf->overrides->pctable &&
> +           !(conf->overrides->pctable = vector_alloc()))
> +               return 1;
> +
> +       if (!(pce = alloc_pce()))
> +               return 1;
> +
> +       if (!vector_alloc_slot(conf->overrides->pctable)) {
> +               free(pce);
> +               return 1;
> +       }
> +       vector_set_slot(conf->overrides->pctable, pce);
> +
> +       return 0;
> +}
> +
> +static int
> +set_protocol_type(vector strvec, void *ptr, const char *file, int
> line_nr)
> +{
> +       int *int_ptr = (int *)ptr;
> +       char *buff;
> +       int i;
> +
> +       buff = set_value(strvec);
> +
> +       if (!buff)
> +               return 1;
> +
> +       for (i = 0; i <= LAST_BUS_PROTOCOL_ID; i++) {
> +               if (protocol_name[i] && !strcmp(buff,
> protocol_name[i])) {
> +                       *int_ptr = i;
> +                       break;
> +               }
> +       }
> +       if (i > LAST_BUS_PROTOCOL_ID)
> +               condlog(1, "%s line %d, invalid value for type:
> \"%s\"",
> +                       file, line_nr, buff);
> +
> +       free(buff);
> +       return 0;
> +}
> +
> +static int
> +print_protocol_type(struct strbuf *buff, int type)
> +{
> +       if (type < 0)
> +               return 0;
> +       return append_strbuf_quoted(buff, protocol_name[type]);
> +}
> +
> +declare_pc_handler(type, set_protocol_type)
> +declare_pc_snprint(type, print_protocol_type)
> +
>  /*
>   * deprecated handlers
>   */
> @@ -2138,6 +2230,13 @@ init_keywords(vector keywords)
>         install_keyword("ghost_delay", &ovr_ghost_delay_handler,
> &snprint_ovr_ghost_delay);
>         install_keyword("all_tg_pt", &ovr_all_tg_pt_handler,
> &snprint_ovr_all_tg_pt);
>         install_keyword("recheck_wwid", &ovr_recheck_wwid_handler,
> &snprint_ovr_recheck_wwid);
> +       install_keyword_multi("protocol", &protocol_handler, NULL);
> +       install_sublevel();
> +       install_keyword("type", &pc_type_handler, &snprint_pc_type);
> +       install_keyword("fast_io_fail_tmo", &pc_fast_io_fail_handler,
> &snprint_pc_fast_io_fail);
> +       install_keyword("dev_loss_tmo", &pc_dev_loss_handler,
> &snprint_pc_dev_loss);
> +       install_keyword("eh_deadline", &pc_eh_deadline_handler,
> &snprint_pc_eh_deadline);
> +       install_sublevel_end();
>  
>         install_keyword_root("multipaths", &multipaths_handler);
>         install_keyword_multi("multipath", &multipath_handler, NULL);
> diff --git a/libmultipath/print.c b/libmultipath/print.c
> index 27c2cf1a..68a793e7 100644
> --- a/libmultipath/print.c
> +++ b/libmultipath/print.c
> @@ -1406,6 +1406,52 @@ int snprint_multipath_topology_json (struct
> strbuf *buff,
>         return get_strbuf_len(buff) - initial_len;
>  }
>  
> +static int
> +snprint_pcentry (const struct config *conf, struct strbuf *buff,
> +                const struct pcentry *pce)
> +{
> +       int i, rc;
> +       struct keyword *kw;
> +       struct keyword * rootkw;
> +       size_t initial_len = get_strbuf_len(buff);
> +
> +       rootkw = find_keyword(conf->keywords, NULL, "overrides");
> +       assert(rootkw && rootkw->sub);
> +       rootkw = find_keyword(conf->keywords, rootkw->sub,
> "protocol");
> +       assert(rootkw);
> +
> +       if ((rc = append_strbuf_str(buff, "\tprotocol {\n")) < 0)
> +               return rc;
> +
> +       iterate_sub_keywords(rootkw, kw, i) {
> +               if ((rc = snprint_keyword(buff, "\t\t%k %v\n", kw,
> pce)) < 0)
> +                       return rc;
> +       }
> +
> +       if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
> +               return rc;
> +       return get_strbuf_len(buff) - initial_len;
> +}
> +
> +static int
> +snprint_pctable (const struct config *conf, struct strbuf *buff,
> +                const struct _vector *pctable)
> +{
> +       int i, rc;
> +       struct pcentry *pce;
> +       struct keyword * rootkw;
> +       size_t initial_len = get_strbuf_len(buff);
> +
> +       rootkw = find_keyword(conf->keywords, NULL, "overrides");
> +       assert(rootkw);
> +
> +       vector_foreach_slot(pctable, pce, i) {
> +               if ((rc = snprint_pcentry(conf, buff, pce)) < 0)
> +                       return rc;
> +       }
> +       return get_strbuf_len(buff) - initial_len;
> +}
> +
>  static int
>  snprint_hwentry (const struct config *conf,
>                  struct strbuf *buff, const struct hwentry * hwe)
> @@ -1560,6 +1606,10 @@ static int snprint_overrides(const struct
> config *conf, struct strbuf *buff,
>                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw,
> NULL)) < 0)
>                         return rc;
>         }
> +
> +       if (overrides->pctable &&
> +           (rc = snprint_pctable(conf, buff, overrides->pctable)) <
> 0)
> +               return rc;
>  out:
>         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
>                 return rc;



More information about the dm-devel mailing list