[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