<div dir="ltr">I have no strong opinion on this one : I feel like the complexity of the parameter inheritance system is already quite complicated ... but this addition of a new layer would likely and safely be ignored by users who don't need it. Those who need it are surely ready to pay the price.<div><br></div><div>Does someone have objection to my applying this patch ?</div><div><br></div><div>Best regards,</div><div>Christophe</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 19, 2014 at 7:17 AM, Benjamin Marzinski <span dir="ltr"><<a href="mailto:bmarzins@redhat.com" target="_blank">bmarzins@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Sometimes users want to be able to set a configuration value for all their<br>
devices (for instance, they may want all devices to set no_path_retry to<br>
fail). The builtin device configurations make this tricky, since users need<br>
to change each device configuration individually. To avoid that, this patch<br>
adds a new section to multipath.conf, "overrides". This section has all of<br>
the attributes that are in both the devices and defaults section.<br>
Attributes set in the overrides section have a higher priority that those<br>
in the devices section. With this section added, the multipath<br>
configuration order now goes:<br>
<br>
multipaths > overrides > devices > defaults<br>
<br>
I also made want_user_friendly_names print out where the configuration came<br>
from, and I made made select_hwhandler and select_selector always strdup<br>
the string, instead of only on the defaults. Since multipathd will update<br>
the device strings from the kernel anyway, the old way just added<br>
complexity without saving any memory.<br>
<br>
To store the overrides configuration, I used a hwentry structure. We may<br>
want to make a new overrides structure, so that we set any of the defaults<br>
values in overrides. That way, users could skip using defaults and just<br>
use overrides if they wanted. However, this would take some additional<br>
changes to make sure that all the defaults options can undefined, which<br>
they can't currently be.<br>
<br>
Signed-off-by: Benjamin Marzinski <<a href="mailto:bmarzins@redhat.com">bmarzins@redhat.com</a>><br>
---<br>
libmultipath/config.c | 1 +<br>
libmultipath/config.h | 1 +<br>
libmultipath/dict.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++<br>
libmultipath/print.c | 30 ++++++++++++++<br>
libmultipath/print.h | 1 +<br>
libmultipath/propsel.c | 55 +++++++++++++++++++++-----<br>
libmultipath/structs.c | 9 +----<br>
multipath.conf.annotated | 18 ++++++++-<br>
multipath.conf.defaults | 2 +<br>
multipath.conf.synthetic | 3 ++<br>
multipath/main.c | 6 +++<br>
multipath/multipath.conf.5 | 57 +++++++++++++++++++++++++++<br>
multipathd/cli_handlers.c | 10 +++++<br>
13 files changed, 273 insertions(+), 18 deletions(-)<br>
<br>
diff --git a/libmultipath/config.c b/libmultipath/config.c<br>
index bfd8ee8..7f7bd5a 100644<br>
--- a/libmultipath/config.c<br>
+++ b/libmultipath/config.c<br>
@@ -523,6 +523,7 @@ free_config (struct config * conf)<br>
<br>
free_mptable(conf->mptable);<br>
free_hwtable(conf->hwtable);<br>
+ free_hwe(conf->overrides);<br>
free_keywords(conf->keywords);<br>
FREE(conf);<br>
}<br>
diff --git a/libmultipath/config.h b/libmultipath/config.h<br>
index c57ab31..ef1d7c3 100644<br>
--- a/libmultipath/config.h<br>
+++ b/libmultipath/config.h<br>
@@ -145,6 +145,7 @@ struct config {<br>
vector keywords;<br>
vector mptable;<br>
vector hwtable;<br>
+ struct hwentry *overrides;<br>
<br>
vector blist_devnode;<br>
vector blist_wwid;<br>
diff --git a/libmultipath/dict.c b/libmultipath/dict.c<br>
index 98cbe48..737c9b0 100644<br>
--- a/libmultipath/dict.c<br>
+++ b/libmultipath/dict.c<br>
@@ -181,6 +181,22 @@ snprint_hw_ ## option (char * buff, int len, void * data) \<br>
return function (buff, len, &hwe->option); \<br>
}<br>
<br>
+#define declare_ovr_handler(option, function) \<br>
+static int \<br>
+ovr_ ## option ## _handler (vector strvec) \<br>
+{ \<br>
+ if (!conf->overrides) \<br>
+ return 1; \<br>
+ return function (strvec, &conf->overrides->option); \<br>
+}<br>
+<br>
+#define declare_ovr_snprint(option, function) \<br>
+static int \<br>
+snprint_ovr_ ## option (char * buff, int len, void * data) \<br>
+{ \<br>
+ return function (buff, len, &conf->overrides->option); \<br>
+}<br>
+<br>
#define declare_mp_handler(option, function) \<br>
static int \<br>
mp_ ## option ## _handler (vector strvec) \<br>
@@ -218,21 +234,29 @@ declare_def_handler(selector, set_str)<br>
declare_def_snprint_defstr(selector, print_str, DEFAULT_SELECTOR)<br>
declare_hw_handler(selector, set_str)<br>
declare_hw_snprint(selector, print_str)<br>
+declare_ovr_handler(selector, set_str)<br>
+declare_ovr_snprint(selector, print_str)<br>
declare_mp_handler(selector, set_str)<br>
declare_mp_snprint(selector, print_str)<br>
<br>
declare_def_handler(uid_attribute, set_str)<br>
declare_def_snprint_defstr(uid_attribute, print_str, DEFAULT_UID_ATTRIBUTE)<br>
+declare_ovr_handler(uid_attribute, set_str)<br>
+declare_ovr_snprint(uid_attribute, print_str)<br>
declare_hw_handler(uid_attribute, set_str)<br>
declare_hw_snprint(uid_attribute, print_str)<br>
<br>
declare_def_handler(getuid, set_str)<br>
declare_def_snprint(getuid, print_str)<br>
+declare_ovr_handler(getuid, set_str)<br>
+declare_ovr_snprint(getuid, print_str)<br>
declare_hw_handler(getuid, set_str)<br>
declare_hw_snprint(getuid, print_str)<br>
<br>
declare_def_handler(prio_name, set_str)<br>
declare_def_snprint_defstr(prio_name, print_str, DEFAULT_PRIO)<br>
+declare_ovr_handler(prio_name, set_str)<br>
+declare_ovr_snprint(prio_name, print_str)<br>
declare_hw_handler(prio_name, set_str)<br>
declare_hw_snprint(prio_name, print_str)<br>
declare_mp_handler(prio_name, set_str)<br>
@@ -240,11 +264,15 @@ declare_mp_snprint(prio_name, print_str)<br>
<br>
declare_def_handler(alias_prefix, set_str)<br>
declare_def_snprint_defstr(alias_prefix, print_str, DEFAULT_ALIAS_PREFIX)<br>
+declare_ovr_handler(alias_prefix, set_str)<br>
+declare_ovr_snprint(alias_prefix, print_str)<br>
declare_hw_handler(alias_prefix, set_str)<br>
declare_hw_snprint(alias_prefix, print_str)<br>
<br>
declare_def_handler(prio_args, set_str)<br>
declare_def_snprint_defstr(prio_args, print_str, DEFAULT_PRIO_ARGS)<br>
+declare_ovr_handler(prio_args, set_str)<br>
+declare_ovr_snprint(prio_args, print_str)<br>
declare_hw_handler(prio_args, set_str)<br>
declare_hw_snprint(prio_args, print_str)<br>
declare_mp_handler(prio_args, set_str)<br>
@@ -252,6 +280,8 @@ declare_mp_snprint(prio_args, print_str)<br>
<br>
declare_def_handler(features, set_str)<br>
declare_def_snprint_defstr(features, print_str, DEFAULT_FEATURES)<br>
+declare_ovr_handler(features, set_str)<br>
+declare_ovr_snprint(features, print_str)<br>
declare_hw_handler(features, set_str)<br>
declare_hw_snprint(features, print_str)<br>
declare_mp_handler(features, set_str)<br>
@@ -259,11 +289,15 @@ declare_mp_snprint(features, print_str)<br>
<br>
declare_def_handler(checker_name, set_str)<br>
declare_def_snprint_defstr(checker_name, print_str, DEFAULT_CHECKER)<br>
+declare_ovr_handler(checker_name, set_str)<br>
+declare_ovr_snprint(checker_name, print_str)<br>
declare_hw_handler(checker_name, set_str)<br>
declare_hw_snprint(checker_name, print_str)<br>
<br>
declare_def_handler(minio, set_int)<br>
declare_def_snprint_defint(minio, print_int, DEFAULT_MINIO)<br>
+declare_ovr_handler(minio, set_int)<br>
+declare_ovr_snprint(minio, print_nonzero)<br>
declare_hw_handler(minio, set_int)<br>
declare_hw_snprint(minio, print_nonzero)<br>
declare_mp_handler(minio, set_int)<br>
@@ -271,6 +305,8 @@ declare_mp_snprint(minio, print_nonzero)<br>
<br>
declare_def_handler(minio_rq, set_int)<br>
declare_def_snprint_defint(minio_rq, print_int, DEFAULT_MINIO_RQ)<br>
+declare_ovr_handler(minio_rq, set_int)<br>
+declare_ovr_snprint(minio_rq, print_nonzero)<br>
declare_hw_handler(minio_rq, set_int)<br>
declare_hw_snprint(minio_rq, print_nonzero)<br>
declare_mp_handler(minio_rq, set_int)<br>
@@ -296,6 +332,8 @@ declare_def_snprint(checker_timeout, print_nonzero)<br>
<br>
declare_def_handler(flush_on_last_del, set_yes_no_undef)<br>
declare_def_snprint_defint(flush_on_last_del, print_yes_no_undef, YNU_NO)<br>
+declare_ovr_handler(flush_on_last_del, set_yes_no_undef)<br>
+declare_ovr_snprint(flush_on_last_del, print_yes_no_undef)<br>
declare_hw_handler(flush_on_last_del, set_yes_no_undef)<br>
declare_hw_snprint(flush_on_last_del, print_yes_no_undef)<br>
declare_mp_handler(flush_on_last_del, set_yes_no_undef)<br>
@@ -303,6 +341,8 @@ declare_mp_snprint(flush_on_last_del, print_yes_no_undef)<br>
<br>
declare_def_handler(user_friendly_names, set_yes_no_undef)<br>
declare_def_snprint_defint(user_friendly_names, print_yes_no_undef, YNU_NO)<br>
+declare_ovr_handler(user_friendly_names, set_yes_no_undef)<br>
+declare_ovr_snprint(user_friendly_names, print_yes_no_undef)<br>
declare_hw_handler(user_friendly_names, set_yes_no_undef)<br>
declare_hw_snprint(user_friendly_names, print_yes_no_undef)<br>
declare_mp_handler(user_friendly_names, set_yes_no_undef)<br>
@@ -316,11 +356,15 @@ declare_def_snprint(wwids_file, print_str)<br>
<br>
declare_def_handler(retain_hwhandler, set_yes_no_undef)<br>
declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef, YNU_NO)<br>
+declare_ovr_handler(retain_hwhandler, set_yes_no_undef)<br>
+declare_ovr_snprint(retain_hwhandler, print_yes_no_undef)<br>
declare_hw_handler(retain_hwhandler, set_yes_no_undef)<br>
declare_hw_snprint(retain_hwhandler, print_yes_no_undef)<br>
<br>
declare_def_handler(detect_prio, set_yes_no_undef)<br>
declare_def_snprint_defint(detect_prio, print_yes_no_undef, YNU_NO)<br>
+declare_ovr_handler(detect_prio, set_yes_no_undef)<br>
+declare_ovr_snprint(detect_prio, print_yes_no_undef)<br>
declare_hw_handler(detect_prio, set_yes_no_undef)<br>
declare_hw_snprint(detect_prio, print_yes_no_undef)<br>
<br>
@@ -512,6 +556,8 @@ print_fast_io_fail(char * buff, int len, void *ptr)<br>
<br>
declare_def_handler(fast_io_fail, set_fast_io_fail)<br>
declare_def_snprint(fast_io_fail, print_fast_io_fail)<br>
+declare_ovr_handler(fast_io_fail, set_fast_io_fail)<br>
+declare_ovr_snprint(fast_io_fail, print_fast_io_fail)<br>
declare_hw_handler(fast_io_fail, set_fast_io_fail)<br>
declare_hw_snprint(fast_io_fail, print_fast_io_fail)<br>
<br>
@@ -548,6 +594,8 @@ print_dev_loss(char * buff, int len, void *ptr)<br>
<br>
declare_def_handler(dev_loss, set_dev_loss)<br>
declare_def_snprint(dev_loss, print_dev_loss)<br>
+declare_ovr_handler(dev_loss, set_dev_loss)<br>
+declare_ovr_snprint(dev_loss, print_dev_loss)<br>
declare_hw_handler(dev_loss, set_dev_loss)<br>
declare_hw_snprint(dev_loss, print_dev_loss)<br>
<br>
@@ -583,6 +631,8 @@ print_pgpolicy(char * buff, int len, void *ptr)<br>
<br>
declare_def_handler(pgpolicy, set_pgpolicy)<br>
declare_def_snprint_defint(pgpolicy, print_pgpolicy, DEFAULT_PGPOLICY)<br>
+declare_ovr_handler(pgpolicy, set_pgpolicy)<br>
+declare_ovr_snprint(pgpolicy, print_pgpolicy)<br>
declare_hw_handler(pgpolicy, set_pgpolicy)<br>
declare_hw_snprint(pgpolicy, print_pgpolicy)<br>
declare_mp_handler(pgpolicy, set_pgpolicy)<br>
@@ -700,6 +750,8 @@ print_rr_weight (char * buff, int len, void *ptr)<br>
<br>
declare_def_handler(rr_weight, set_rr_weight)<br>
declare_def_snprint_defint(rr_weight, print_rr_weight, RR_WEIGHT_NONE)<br>
+declare_ovr_handler(rr_weight, set_rr_weight)<br>
+declare_ovr_snprint(rr_weight, print_rr_weight)<br>
declare_hw_handler(rr_weight, set_rr_weight)<br>
declare_hw_snprint(rr_weight, print_rr_weight)<br>
declare_mp_handler(rr_weight, set_rr_weight)<br>
@@ -748,6 +800,8 @@ print_pgfailback (char * buff, int len, void *ptr)<br>
<br>
declare_def_handler(pgfailback, set_pgfailback)<br>
declare_def_snprint_defint(pgfailback, print_pgfailback, DEFAULT_FAILBACK)<br>
+declare_ovr_handler(pgfailback, set_pgfailback)<br>
+declare_ovr_snprint(pgfailback, print_pgfailback)<br>
declare_hw_handler(pgfailback, set_pgfailback)<br>
declare_hw_snprint(pgfailback, print_pgfailback)<br>
declare_mp_handler(pgfailback, set_pgfailback)<br>
@@ -793,6 +847,8 @@ print_no_path_retry(char * buff, int len, void *ptr)<br>
<br>
declare_def_handler(no_path_retry, set_no_path_retry)<br>
declare_def_snprint(no_path_retry, print_no_path_retry)<br>
+declare_ovr_handler(no_path_retry, set_no_path_retry)<br>
+declare_ovr_snprint(no_path_retry, print_no_path_retry)<br>
declare_hw_handler(no_path_retry, set_no_path_retry)<br>
declare_hw_snprint(no_path_retry, print_no_path_retry)<br>
declare_mp_handler(no_path_retry, set_no_path_retry)<br>
@@ -1061,6 +1117,25 @@ declare_hw_handler(hwhandler, set_str)<br>
declare_hw_snprint(hwhandler, print_str)<br>
<br>
/*<br>
+ * overrides handlers<br>
+ */<br>
+static int<br>
+overrides_handler(vector strvec)<br>
+{<br>
+ struct hwentry * overrides;<br>
+<br>
+ overrides = alloc_hwe();<br>
+<br>
+ if (!overrides)<br>
+ return 1;<br>
+<br>
+ conf->overrides = overrides;<br>
+ return 0;<br>
+}<br>
+<br>
+<br>
+<br>
+/*<br>
* multipaths block handlers<br>
*/<br>
static int<br>
@@ -1236,6 +1311,29 @@ init_keywords(void)<br>
install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_hw_detect_prio);<br>
install_sublevel_end();<br>
<br>
+ install_keyword_root("overrides", &overrides_handler);<br>
+ install_keyword("path_grouping_policy", &ovr_pgpolicy_handler, &snprint_ovr_pgpolicy);<br>
+ install_keyword("uid_attribute", &ovr_uid_attribute_handler, &snprint_ovr_uid_attribute);<br>
+ install_keyword("getuid_callout", &ovr_getuid_handler, &snprint_ovr_getuid);<br>
+ install_keyword("path_selector", &ovr_selector_handler, &snprint_ovr_selector);<br>
+ install_keyword("path_checker", &ovr_checker_name_handler, &snprint_ovr_checker_name);<br>
+ install_keyword("checker", &ovr_checker_name_handler, NULL);<br>
+ install_keyword("alias_prefix", &ovr_alias_prefix_handler, &snprint_ovr_alias_prefix);<br>
+ install_keyword("features", &ovr_features_handler, &snprint_ovr_features);<br>
+ install_keyword("prio", &ovr_prio_name_handler, &snprint_ovr_prio_name);<br>
+ install_keyword("prio_args", &ovr_prio_args_handler, &snprint_ovr_prio_args);<br>
+ install_keyword("failback", &ovr_pgfailback_handler, &snprint_ovr_pgfailback);<br>
+ install_keyword("rr_weight", &ovr_rr_weight_handler, &snprint_ovr_rr_weight);<br>
+ install_keyword("no_path_retry", &ovr_no_path_retry_handler, &snprint_ovr_no_path_retry);<br>
+ install_keyword("rr_min_io", &ovr_minio_handler, &snprint_ovr_minio);<br>
+ install_keyword("rr_min_io_rq", &ovr_minio_rq_handler, &snprint_ovr_minio_rq);<br>
+ install_keyword("flush_on_last_del", &ovr_flush_on_last_del_handler, &snprint_ovr_flush_on_last_del);<br>
+ install_keyword("fast_io_fail_tmo", &ovr_fast_io_fail_handler, &snprint_ovr_fast_io_fail);<br>
+ install_keyword("dev_loss_tmo", &ovr_dev_loss_handler, &snprint_ovr_dev_loss);<br>
+ install_keyword("user_friendly_names", &ovr_user_friendly_names_handler, &snprint_ovr_user_friendly_names);<br>
+ install_keyword("retain_attached_hw_handler", &ovr_retain_hwhandler_handler, &snprint_ovr_retain_hwhandler);<br>
+ install_keyword("detect_prio", &ovr_detect_prio_handler, &snprint_ovr_detect_prio);<br>
+<br>
install_keyword_root("multipaths", &multipaths_handler);<br>
install_keyword_multi("multipath", &multipath_handler, NULL);<br>
install_sublevel();<br>
diff --git a/libmultipath/print.c b/libmultipath/print.c<br>
index 383eae4..ade3841 100644<br>
--- a/libmultipath/print.c<br>
+++ b/libmultipath/print.c<br>
@@ -1080,6 +1080,36 @@ snprint_mptable (char * buff, int len, vector mptable)<br>
}<br>
<br>
extern int<br>
+snprint_overrides (char * buff, int len, struct hwentry *overrides)<br>
+{<br>
+ int fwd = 0;<br>
+ int i;<br>
+ struct keyword *rootkw;<br>
+ struct keyword *kw;<br>
+<br>
+ rootkw = find_keyword(NULL, "overrides");<br>
+ if (!rootkw)<br>
+ return 0;<br>
+<br>
+ fwd += snprintf(buff + fwd, len - fwd, "overrides {\n");<br>
+ if (fwd > len)<br>
+ return len;<br>
+ if (!overrides)<br>
+ goto out;<br>
+ iterate_sub_keywords(rootkw, kw, i) {<br>
+ fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",<br>
+ kw, NULL);<br>
+ if (fwd > len)<br>
+ return len;<br>
+ }<br>
+out:<br>
+ fwd += snprintf(buff + fwd, len - fwd, "}\n");<br>
+ if (fwd > len)<br>
+ return len;<br>
+ return fwd;<br>
+}<br>
+<br>
+extern int<br>
snprint_defaults (char * buff, int len)<br>
{<br>
int fwd = 0;<br>
diff --git a/libmultipath/print.h b/libmultipath/print.h<br>
index aef182b..a3c3319 100644<br>
--- a/libmultipath/print.h<br>
+++ b/libmultipath/print.h<br>
@@ -50,6 +50,7 @@ int snprint_status (char *, int, struct vectors *);<br>
int snprint_devices (char *, int, struct vectors *);<br>
int snprint_hwtable (char *, int, vector);<br>
int snprint_mptable (char *, int, vector);<br>
+int snprint_overrides (char *, int, struct hwentry *);<br>
<br>
void print_multipath_topology (struct multipath * mpp, int verbosity);<br>
void print_path (struct path * pp, char * style);<br>
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c<br>
index f2ab7d2..440802c 100644<br>
--- a/libmultipath/propsel.c<br>
+++ b/libmultipath/propsel.c<br>
@@ -48,6 +48,8 @@ do { \<br>
do_set(var, mp->mpe, mp->var, "(LUN setting)")<br>
#define mp_set_hwe(var) \<br>
do_set(var, mp->hwe, mp->var, "(controller setting)")<br>
+#define mp_set_ovr(var) \<br>
+do_set(var, conf->overrides, mp->var, "(overrides setting)")<br>
#define mp_set_conf(var) \<br>
do_set(var, conf, mp->var, "(config file default)")<br>
#define mp_set_default(var, value) \<br>
@@ -59,6 +61,8 @@ do_set(var, mpe, pp->var, "(LUN setting)")<br>
do_set(var, pp->hwe, pp->var, "(controller setting)")<br>
#define pp_set_conf(var) \<br>
do_set(var, conf, pp->var, "(config file default)")<br>
+#define pp_set_ovr(var) \<br>
+do_set(var, conf->overrides, pp->var, "(overrides setting)")<br>
#define pp_set_default(var, value) \<br>
do_default(pp->var, value)<br>
<br>
@@ -130,6 +134,7 @@ select_rr_weight (struct multipath * mp)<br>
char *origin, buff[13];<br>
<br>
mp_set_mpe(rr_weight);<br>
+ mp_set_ovr(rr_weight);<br>
mp_set_hwe(rr_weight);<br>
mp_set_conf(rr_weight);<br>
mp_set_default(rr_weight, RR_WEIGHT_NONE);<br>
@@ -145,6 +150,7 @@ select_pgfailback (struct multipath * mp)<br>
char *origin, buff[13];<br>
<br>
mp_set_mpe(pgfailback);<br>
+ mp_set_ovr(pgfailback);<br>
mp_set_hwe(pgfailback);<br>
mp_set_conf(pgfailback);<br>
mp_set_default(pgfailback, DEFAULT_FAILBACK);<br>
@@ -165,6 +171,7 @@ select_pgpolicy (struct multipath * mp)<br>
goto out;<br>
}<br>
mp_set_mpe(pgpolicy);<br>
+ mp_set_ovr(pgpolicy);<br>
mp_set_hwe(pgpolicy);<br>
mp_set_conf(pgpolicy);<br>
mp_set_default(pgpolicy, DEFAULT_PGPOLICY);<br>
@@ -181,10 +188,12 @@ select_selector (struct multipath * mp)<br>
char *origin;<br>
<br>
mp_set_mpe(selector);<br>
+ mp_set_ovr(selector);<br>
mp_set_hwe(selector);<br>
mp_set_conf(selector);<br>
- mp_set_default(selector, set_default(DEFAULT_SELECTOR));<br>
+ mp_set_default(selector, DEFAULT_SELECTOR);<br>
out:<br>
+ mp->selector = STRDUP(mp->selector);<br>
condlog(3, "%s: path_selector = \"%s\" %s", mp->alias, mp->selector,<br>
origin);<br>
return 0;<br>
@@ -195,6 +204,7 @@ select_alias_prefix (struct multipath * mp)<br>
{<br>
char *origin;<br>
<br>
+ mp_set_ovr(alias_prefix);<br>
mp_set_hwe(alias_prefix);<br>
mp_set_conf(alias_prefix);<br>
mp_set_default(alias_prefix, DEFAULT_ALIAS_PREFIX);<br>
@@ -206,19 +216,30 @@ out:<br>
static int<br>
want_user_friendly_names(struct multipath * mp)<br>
{<br>
- if (mp->mpe &&<br>
- mp->mpe->user_friendly_names != USER_FRIENDLY_NAMES_UNDEF)<br>
- return (mp->mpe->user_friendly_names == USER_FRIENDLY_NAMES_ON);<br>
- if (mp->hwe &&<br>
- mp->hwe->user_friendly_names != USER_FRIENDLY_NAMES_UNDEF)<br>
- return (mp->hwe->user_friendly_names == USER_FRIENDLY_NAMES_ON);<br>
- return (conf->user_friendly_names == USER_FRIENDLY_NAMES_ON);<br>
+<br>
+ char *origin;<br>
+ int user_friendly_names;<br>
+<br>
+ do_set(user_friendly_names, mp->mpe, user_friendly_names,<br>
+ "(LUN setting)");<br>
+ do_set(user_friendly_names, conf->overrides, user_friendly_names,<br>
+ "(overrides setting)");<br>
+ do_set(user_friendly_names, mp->hwe, user_friendly_names,<br>
+ "(controller setting)");<br>
+ do_set(user_friendly_names, conf, user_friendly_names,<br>
+ "(config file setting)");<br>
+ do_default(user_friendly_names, USER_FRIENDLY_NAMES_OFF);<br>
+out:<br>
+ condlog(3, "%s: user_friendly_names = %s %s", mp->wwid,<br>
+ (user_friendly_names == USER_FRIENDLY_NAMES_ON)? "yes" : "no",<br>
+ origin);<br>
+ return (user_friendly_names == USER_FRIENDLY_NAMES_ON);<br>
}<br>
<br>
extern int<br>
select_alias (struct multipath * mp)<br>
{<br>
- char *origin;<br>
+ char *origin = NULL;<br>
<br>
if (mp->mpe && mp->mpe->alias) {<br>
mp->alias = STRDUP(mp->mpe->alias);<br>
@@ -261,6 +282,7 @@ select_features (struct multipath * mp)<br>
char *origin;<br>
<br>
mp_set_mpe(features);<br>
+ mp_set_ovr(features);<br>
mp_set_hwe(features);<br>
mp_set_conf(features);<br>
mp_set_default(features, DEFAULT_FEATURES);<br>
@@ -287,8 +309,9 @@ select_hwhandler (struct multipath * mp)<br>
<br>
mp_set_hwe(hwhandler);<br>
mp_set_conf(hwhandler);<br>
- mp_set_default(hwhandler, set_default(DEFAULT_HWHANDLER));<br>
+ mp_set_default(hwhandler, DEFAULT_HWHANDLER);<br>
out:<br>
+ mp->hwhandler = STRDUP(mp->hwhandler);<br>
condlog(3, "%s: hardware_handler = \"%s\" %s", mp->alias, mp->hwhandler,<br>
origin);<br>
return 0;<br>
@@ -300,6 +323,7 @@ select_checker(struct path *pp)<br>
char *origin, *checker_name;<br>
struct checker * c = &pp->checker;<br>
<br>
+ do_set(checker_name, conf->overrides, checker_name, "(overrides setting)");<br>
do_set(checker_name, pp->hwe, checker_name, "(controller setting)");<br>
do_set(checker_name, conf, checker_name, "(config file setting)");<br>
do_default(checker_name, DEFAULT_CHECKER);<br>
@@ -327,6 +351,8 @@ select_getuid (struct path * pp)<br>
{<br>
char *origin;<br>
<br>
+ pp_set_ovr(uid_attribute);<br>
+ pp_set_ovr(getuid);<br>
pp_set_hwe(uid_attribute);<br>
pp_set_hwe(getuid);<br>
pp_set_conf(uid_attribute);<br>
@@ -383,6 +409,7 @@ select_prio (struct path * pp)<br>
}<br>
mpe = find_mpe(pp->wwid);<br>
set_prio(mpe, "(LUN setting)");<br>
+ set_prio(conf->overrides, "(overrides setting)");<br>
set_prio(pp->hwe, "controller setting)");<br>
set_prio(conf, "(config file default)");<br>
prio_get(p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);<br>
@@ -405,6 +432,7 @@ select_no_path_retry(struct multipath *mp)<br>
return 0;<br>
}<br>
mp_set_mpe(no_path_retry);<br>
+ mp_set_ovr(no_path_retry);<br>
mp_set_hwe(no_path_retry);<br>
mp_set_conf(no_path_retry);<br>
out:<br>
@@ -427,6 +455,7 @@ select_minio_rq (struct multipath * mp)<br>
char *origin;<br>
<br>
do_set(minio_rq, mp->mpe, mp->minio, "(LUN setting)");<br>
+ do_set(minio_rq, conf->overrides, mp->minio, "(overrides setting)");<br>
do_set(minio_rq, mp->hwe, mp->minio, "(controller setting)");<br>
do_set(minio_rq, conf, mp->minio, "(config file setting)");<br>
do_default(mp->minio, DEFAULT_MINIO_RQ);<br>
@@ -441,6 +470,7 @@ select_minio_bio (struct multipath * mp)<br>
char *origin;<br>
<br>
mp_set_mpe(minio);<br>
+ mp_set_ovr(minio);<br>
mp_set_hwe(minio);<br>
mp_set_conf(minio);<br>
mp_set_default(minio, DEFAULT_MINIO);<br>
@@ -465,6 +495,7 @@ select_fast_io_fail(struct multipath *mp)<br>
{<br>
char *origin, buff[12];<br>
<br>
+ mp_set_ovr(fast_io_fail);<br>
mp_set_hwe(fast_io_fail);<br>
mp_set_conf(fast_io_fail);<br>
mp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL);<br>
@@ -479,6 +510,7 @@ select_dev_loss(struct multipath *mp)<br>
{<br>
char *origin, buff[12];<br>
<br>
+ mp_set_ovr(dev_loss);<br>
mp_set_hwe(dev_loss);<br>
mp_set_conf(dev_loss);<br>
mp->dev_loss = 0;<br>
@@ -497,6 +529,7 @@ select_flush_on_last_del(struct multipath *mp)<br>
if (mp->flush_on_last_del == FLUSH_IN_PROGRESS)<br>
return 0;<br>
mp_set_mpe(flush_on_last_del);<br>
+ mp_set_ovr(flush_on_last_del);<br>
mp_set_hwe(flush_on_last_del);<br>
mp_set_conf(flush_on_last_del);<br>
mp_set_default(flush_on_last_del, FLUSH_DISABLED);<br>
@@ -532,6 +565,7 @@ select_retain_hwhandler (struct multipath * mp)<br>
origin = "(requires kernel version >= 1.5.0)";<br>
goto out;<br>
}<br>
+ mp_set_ovr(retain_hwhandler);<br>
mp_set_hwe(retain_hwhandler);<br>
mp_set_conf(retain_hwhandler);<br>
mp_set_default(retain_hwhandler, DEFAULT_RETAIN_HWHANDLER);<br>
@@ -547,6 +581,7 @@ select_detect_prio (struct path * pp)<br>
{<br>
char *origin;<br>
<br>
+ pp_set_ovr(detect_prio);<br>
pp_set_hwe(detect_prio);<br>
pp_set_conf(detect_prio);<br>
pp_set_default(detect_prio, DEFAULT_DETECT_PRIO);<br>
diff --git a/libmultipath/structs.c b/libmultipath/structs.c<br>
index 30d247d..0538327 100644<br>
--- a/libmultipath/structs.c<br>
+++ b/libmultipath/structs.c<br>
@@ -206,10 +206,7 @@ free_multipath_attributes (struct multipath * mpp)<br>
if (!mpp)<br>
return;<br>
<br>
- if (mpp->selector &&<br>
- mpp->selector != conf->selector &&<br>
- (!mpp->mpe || (mpp->mpe && mpp->selector != mpp->mpe->selector)) &&<br>
- (!mpp->hwe || (mpp->hwe && mpp->selector != mpp->hwe->selector))) {<br>
+ if (mpp->selector) {<br>
FREE(mpp->selector);<br>
mpp->selector = NULL;<br>
}<br>
@@ -219,9 +216,7 @@ free_multipath_attributes (struct multipath * mpp)<br>
mpp->features = NULL;<br>
}<br>
<br>
- if (mpp->hwhandler &&<br>
- mpp->hwhandler != conf->hwhandler &&<br>
- (!mpp->hwe || (mpp->hwe && mpp->hwhandler != mpp->hwe->hwhandler))) {<br>
+ if (mpp->hwhandler) {<br>
FREE(mpp->hwhandler);<br>
mpp->hwhandler = NULL;<br>
}<br>
diff --git a/multipath.conf.annotated b/multipath.conf.annotated<br>
index 0af1d4c..71afc0a 100644<br>
--- a/multipath.conf.annotated<br>
+++ b/multipath.conf.annotated<br>
@@ -485,7 +485,8 @@<br>
## scope : multipath & multipathd<br>
## desc : list of per storage controller settings<br>
## overrides default settings (device_maps block)<br>
-## overriden by per multipath settings (multipaths block)<br>
+## overriden by per multipath settings (multipaths block)<br>
+## and the overrides settings (overrides block)<br>
##<br>
#devices {<br>
# #<br>
@@ -651,3 +652,18 @@<br>
# rr_weight priorities<br>
# }<br>
#}<br>
+#<br>
+##<br>
+## name : devices<br>
+## scope : multipath & multipathd<br>
+## desc : list of settings to override all hadware settings for all devices<br>
+## overrides default settings (device_maps block)<br>
+## and per device type settings (devices block)<br>
+## overriden by per multipath settings (multipaths block)<br>
+##<br>
+# attributes and values are identical to the device block<br>
+#<br>
+#overrides {<br>
+# dev_loss_tmo 60<br>
+# no_path_retry fail<br>
+#}<br>
diff --git a/multipath.conf.defaults b/multipath.conf.defaults<br>
index 654be97..1c65e02 100644<br>
--- a/multipath.conf.defaults<br>
+++ b/multipath.conf.defaults<br>
@@ -912,3 +912,5 @@<br>
#}<br>
#multipaths {<br>
#}<br>
+#overrides {<br>
+#}<br>
diff --git a/multipath.conf.synthetic b/multipath.conf.synthetic<br>
index bda1b75..f7b9b8a 100644<br>
--- a/multipath.conf.synthetic<br>
+++ b/multipath.conf.synthetic<br>
@@ -72,3 +72,6 @@<br>
# path_grouping_policy multibus<br>
# }<br>
#}<br>
+#overrides {<br>
+# no_path_retry fail<br>
+#}<br>
diff --git a/multipath/main.c b/multipath/main.c<br>
index fd6262f..ea453b4 100644<br>
--- a/multipath/main.c<br>
+++ b/multipath/main.c<br>
@@ -405,6 +405,12 @@ dump_config (void)<br>
reply = REALLOC(reply, maxlen *= 2);<br>
continue;<br>
}<br>
+ c += snprint_overrides(c, reply + maxlen - c, conf->overrides);<br>
+ again = ((c - reply) == maxlen);<br>
+ if (again) {<br>
+ reply = REALLOC(reply, maxlen *= 2);<br>
+ continue;<br>
+ }<br>
c += snprint_mptable(c, reply + maxlen - c, conf->mptable);<br>
again = ((c - reply) == maxlen);<br>
if (again)<br>
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5<br>
index cadb34d..b823990 100644<br>
--- a/multipath/multipath.conf.5<br>
+++ b/multipath/multipath.conf.5<br>
@@ -61,6 +61,10 @@ the udev attribute given by the<br>
.TP<br>
.B devices<br>
This section defines the device-specific settings.<br>
+.TP<br>
+.B overrides<br>
+This section defines values for attributes that should override the<br>
+device-specific settings for all devices.<br>
.RE<br>
.LP<br>
.SH "defaults section"<br>
@@ -629,6 +633,59 @@ section:<br>
.RE<br>
.PD<br>
.LP<br>
+.SH "overrides section"<br>
+The overrides section recognizes the following optional attributes; if not set<br>
+the values are taken from the<br>
+.I devices<br>
+or<br>
+.I defaults<br>
+sections:<br>
+.sp 1<br>
+.PD .1v<br>
+.RS<br>
+.TP 18<br>
+.B path_grouping_policy<br>
+.TP<br>
+.B uid_attribute<br>
+.TP<br>
+.B getuid_callout<br>
+.TP<br>
+.B path_selector<br>
+.TP<br>
+.B path_checker<br>
+.TP<br>
+.B alias_prefix<br>
+.TP<br>
+.B features<br>
+.TP<br>
+.B prio<br>
+.TP<br>
+.B prio_args<br>
+.TP<br>
+.B failback<br>
+.TP<br>
+.B rr_weight<br>
+.TP<br>
+.B no_path_retry<br>
+.TP<br>
+.B rr_min_io<br>
+.TP<br>
+.B rr_min_io_rq<br>
+.TP<br>
+.B flush_on_last_del<br>
+.TP<br>
+.B fast_io_fail_tmo<br>
+.TP<br>
+.B dev_loss_tmo<br>
+.TP<br>
+.B user_friendly_names<br>
+.TP<br>
+.B retain_attached_hw_handler<br>
+.TP<br>
+.B detect_prio<br>
+.RE<br>
+.PD<br>
+.LP<br>
.SH "KNOWN ISSUES"<br>
The usage of<br>
.B queue_if_no_path<br>
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c<br>
index b086340..0ce1408 100644<br>
--- a/multipathd/cli_handlers.c<br>
+++ b/multipathd/cli_handlers.c<br>
@@ -190,6 +190,16 @@ show_config (char ** r, int * len)<br>
maxlen *= 2;<br>
continue;<br>
}<br>
+ c += snprint_overrides(c, reply + maxlen - c, conf->overrides);<br>
+ again = ((c - reply) == maxlen);<br>
+ if (again) {<br>
+ reply = REALLOC(reply, maxlen * 2);<br>
+ if (!reply)<br>
+ return 1;<br>
+ memset(reply + maxlen, 0, maxlen);<br>
+ maxlen *= 2;<br>
+ continue;<br>
+ }<br>
c += snprint_mptable(c, reply + maxlen - c, conf->mptable);<br>
again = ((c - reply) == maxlen);<br>
REALLOC_REPLY(reply, again, maxlen);<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.3.1<br>
<br>
</font></span></blockquote></div><br></div>