@@ -22,13 +22,14 @@
BUILDDIRS = multipath multipathd kpartx cciss_id path_priority/pp_alua \
path_priority/pp_emc path_priority/pp_hds_modular \
path_priority/pp_netapp path_priority/pp_rdac \
- path_priority/pp_tpc path_priority/pp_hp_sw
+ path_priority/pp_tpc path_priority/pp_hp_sw \
+ path_priority/pp_weighted
ALLDIRS = multipath multipathd kpartx cciss_id path_priority/pp_alua \
path_priority/pp_emc path_priority/pp_hds_modular \
path_priority/pp_netapp path_priority/pp_rdac \
path_priority/pp_hp_sw path_priority/pp_tpc \
- libmultipath libcheckers
+ path_priority/pp_weighted libmultipath libcheckers
VERSION = $(shell basename ${PWD} | cut -d'-' -f3)
@@ -302,6 +302,17 @@
# path_grouping_policy multibus
#
# #
+# # name : prio_callout
+# # scope : multipath
+# # desc : the program and args to callout to obtain a path
+# # weight. Weights are summed for each path group to
+# # determine the next PG to use case of failure.
+# # "none" is a valid value.
+# # default : no callout, all paths equals
+# #
+# prio_callout "/sbin/mpath_prio_balance_units %d"
+#
+# #
# # name : path_selector
# # desc : the path selector algorithm to use for this mpath
# # these algo are offered by the kernel mpath target
@@ -189,6 +189,18 @@
snprintf(p, len, "%s", pp->dev_t);
p += len - 1;
break;
+ case 'h':
+ if (pp->sg_id.host_no < 0)
+ len = snprintf(p, myfree, "#:#:#:#");
+ else
+ len = snprintf(p, myfree, "%d:%d:%d:%d",
+ pp->sg_id.host_no, pp->sg_id.channel,
+ pp->sg_id.scsi_id, pp->sg_id.lun);
+ myfree -= (len + 1);
+ if (myfree < 2)
+ return 1;
+ p += len;
+ break;
default:
break;
}
@@ -219,6 +219,9 @@
if (mpe->alias)
FREE(mpe->alias);
+ if (mpe->getprio)
+ FREE(mpe->getprio);
+
FREE(mpe);
}
@@ -39,6 +39,7 @@
char * alias;
char * getuid;
char * selector;
+ char * getprio;
int pgpolicy;
int pgfailback;
@@ -731,7 +731,7 @@
}
static int
-prio_callout_handler(vector strvec)
+hw_prio_callout_handler(vector strvec)
{
struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
@@ -999,6 +999,28 @@
}
static int
+mp_prio_callout_handler(vector strvec)
+{
+ struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable);
+
+ if (!mpe)
+ return 1;
+
+ mpe->getprio = set_value(strvec);
+
+ if (!mpe->getprio)
+ return 1;
+
+ if (strlen(mpe->getprio) == 4 && !strcmp(mpe->getprio, "none")) {
+ FREE(mpe->getprio);
+ mpe->getprio = NULL;
+ return 0;
+ }
+
+ return push_callout(mpe->getprio);
+}
+
+static int
mp_failback_handler(vector strvec)
{
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable);
@@ -1327,6 +1349,26 @@
}
static int
+snprint_mp_prio_callout (char * buff, int len, void * data)
+{
+ struct mpentry * mpe = (struct mpentry *)data;
+
+ if (!conf->getprio && !mpe->getprio)
+ return 0;
+ if (!conf->getprio && mpe->getprio)
+ return snprintf(buff, len, "%s", mpe->getprio);
+ if (conf->getprio && !mpe->getprio)
+ return snprintf(buff, len, "none");
+
+ /* conf->getprio && mpe->getprio */
+ if (strlen(mpe->getprio) == strlen(conf->getprio) &&
+ !strcmp(mpe->getprio, conf->getprio))
+ return 0;
+
+ return snprintf(buff, len, "%s", mpe->getprio);
+}
+
+static int
snprint_mp_rr_weight (char * buff, int len, void * data)
{
struct mpentry * mpe = (struct mpentry *)data;
@@ -2016,7 +2058,7 @@
install_keyword("path_checker", &hw_path_checker_handler, &snprint_hw_path_checker);
install_keyword("features", &hw_features_handler, &snprint_hw_features);
install_keyword("hardware_handler", &hw_handler_handler, &snprint_hw_hardware_handler);
- install_keyword("prio_callout", &prio_callout_handler, &snprint_hw_prio_callout);
+ install_keyword("prio_callout", &hw_prio_callout_handler, &snprint_hw_prio_callout);
install_keyword("failback", &hw_failback_handler, &snprint_hw_failback);
install_keyword("rr_weight", &hw_weight_handler, &snprint_hw_rr_weight);
install_keyword("no_path_retry", &hw_no_path_retry_handler, &snprint_hw_no_path_retry);
@@ -2033,6 +2075,7 @@
install_keyword("path_grouping_policy", &mp_pgpolicy_handler, &snprint_mp_path_grouping_policy);
install_keyword("path_selector", &mp_selector_handler, &snprint_mp_selector);
install_keyword("failback", &mp_failback_handler, &snprint_mp_failback);
+ install_keyword("prio_callout", &mp_prio_callout_handler, &snprint_mp_prio_callout);
install_keyword("rr_weight", &mp_weight_handler, &snprint_mp_rr_weight);
install_keyword("no_path_retry", &mp_no_path_retry_handler, &snprint_mp_no_path_retry);
install_keyword("rr_min_io", &mp_minio_handler, &snprint_mp_rr_min_io);
@@ -259,6 +259,16 @@
extern int
select_getprio (struct path * pp)
{
+ struct mpentry * mpe;
+
+ if ((mpe = find_mpe(pp->wwid))) {
+ if (mpe->getprio) {
+ pp->getprio = mpe->getprio;
+ condlog(3, "%s: getprio = %s (LUN setting)",
+ pp->dev, pp->getprio);
+ return 0;
+ }
+ }
if (pp->hwe && pp->hwe->getprio) {
pp->getprio = pp->hwe->getprio;
condlog(3, "%s: getprio = %s (controller setting)",
@@ -55,7 +55,7 @@
rm $(DESTDIR)$(bindir)/mpath_wait
rm $(DESTDIR)$(bindir)/mpath_ctl
rm $(DESTDIR)$(mandir)/$(EXEC).8
- rm $(DESTDIR)$(mandir)/$(EXEC).conf.5
+ rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5
clean:
$(MAKE) -C $(multipathdir) clean
@@ -143,6 +143,18 @@
.B mpath_prio_hds_modular %b
Generate the path priority for Hitachi HDS Modular storage arrays.
.TP
+.B mpath_prio_weighted %n|%h <regex1> <prio1> [<regex2> <prio2>] ...
+Generate a path priority based on the matching either the device name \fI%n\fR
+or the H:B:T:L \fI%h\fR of the devices against a series of regular expressions.
+\fIWARNING:\fR Both the device name and the H:B:T:L of a device can change when
+the node is rebooted, or the device driver is reloaded. If you use this callout
+it may be necessary to manually edit your regular expressions whenever either
+of these events occurs.
+\fINOTE:\fR The regular expression must match the complete device name or
+H:B:T:L. For instance a regular expression of \fIsda\fR will only match a
+device named sda, not sdaa, sdab, etc. To match all of them, you would need to
+use the regular expression \fIsda.*\fR
+.TP
Default value is \fBnone\fR.
.RE
.TP
@@ -343,6 +355,8 @@
.TP 18
.B path_grouping_policy
.TP
+.B prio_callout
+.TP
.B path_selector
.TP
.B failback
@@ -29,8 +29,7 @@
teardown_slaves()
{
-pwd=`pwd`
-cd $1;
+pushd $1 > /dev/null
if [ -d "slaves" ]; then
for slave in slaves/*;
do
@@ -55,7 +54,7 @@
exit 1
fi
fi
-cd $pwd
+popd > /dev/null
}
#