Message ID | 1649910461-25263-4-git-send-email-bmarzins@redhat.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
Delegated to: | christophe varoqui |
Headers | show |
Series | Add protocol specific config subsection | expand |
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@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; -- dm-devel mailing list dm-devel@redhat.com https://listman.redhat.com/mailman/listinfo/dm-devel
On Thu, 2022-04-14 at 09:27 +0200, Martin Wilck wrote: > 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@redhat.com> > > Looks good, just a minor nit below. As this is really minor and I'm going to be out of office next week: Reviewed-by: Martin Wilck <mwilck@suse.com> ... and I'm going to push this series to my "queue" branch. Perhaps you want to send an add-on patch with a symbolic value later. Regards Martin -- dm-devel mailing list dm-devel@redhat.com https://listman.redhat.com/mailman/listinfo/dm-devel
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; + 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;
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@redhat.com> --- libmultipath/config.c | 83 ++++++++++++++++++++++++++++++++++++ libmultipath/config.h | 10 +++++ libmultipath/dict.c | 99 +++++++++++++++++++++++++++++++++++++++++++ libmultipath/print.c | 50 ++++++++++++++++++++++ 4 files changed, 242 insertions(+)