summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@fedoraproject.org>2009-11-17 06:33:04 +0000
committerBenjamin Marzinski <bmarzins@fedoraproject.org>2009-11-17 06:33:04 +0000
commit803929adb51de2e33cc4bc59b22e2fc29233016c (patch)
tree2a9dd02196fe82e0a825c0c0c21d230fd7247f82
parente3b500920bcc632bb5061d679731e25ec0ad57a7 (diff)
downloaddevice-mapper-multipath-803929adb51de2e33cc4bc59b22e2fc29233016c.tar.gz
device-mapper-multipath-803929adb51de2e33cc4bc59b22e2fc29233016c.tar.xz
device-mapper-multipath-803929adb51de2e33cc4bc59b22e2fc29233016c.zip
- Add 0002-for-upstream-add-tmo-config-options.patchdevice-mapper-multipath-0_4_9-11_fc13
Add fail_io_fail_tmo and dev_loss_tmo multipath.conf options - Add 0013-RH-add-weighted_prio-prioritizer.patch - Add 0014-RH-add-hp_tur-checker.patch - Add 0015-RH-add-multipathd-count-paths-cmd.patch - rename multipath.conf.redhat to multipath.conf, and remove the default blacklist
-rw-r--r--0002-for-upstream-add-tmo-config-options.patch511
-rw-r--r--0013-RH-add-weighted_prio-prioritizer.patch533
-rw-r--r--0014-RH-add-hp_tur-checker.patch207
-rw-r--r--0015-RH-add-multipathd-count-paths-cmd.patch150
-rw-r--r--device-mapper-multipath.spec23
-rw-r--r--multipath.conf (renamed from multipath.conf.redhat)7
6 files changed, 1421 insertions, 10 deletions
diff --git a/0002-for-upstream-add-tmo-config-options.patch b/0002-for-upstream-add-tmo-config-options.patch
new file mode 100644
index 0000000..dba3659
--- /dev/null
+++ b/0002-for-upstream-add-tmo-config-options.patch
@@ -0,0 +1,511 @@
+---
+ libmultipath/config.h | 4 +
+ libmultipath/configure.c | 3 +
+ libmultipath/dict.c | 102 +++++++++++++++++++++++++++++++++++++++++++++
+ libmultipath/discovery.c | 37 ++++++++++++++++
+ libmultipath/discovery.h | 1
+ libmultipath/propsel.c | 42 ++++++++++++++++++
+ libmultipath/propsel.h | 2
+ libmultipath/structs.h | 2
+ libmultipath/sysfs.c | 56 ++++++++++++++++++++++++
+ libmultipath/sysfs.h | 3 -
+ multipath.conf.annotated | 38 ++++++++++++++++
+ multipath/multipath.conf.5 | 15 ++++++
+ 12 files changed, 303 insertions(+), 2 deletions(-)
+
+Index: multipath-tools-091020/multipath.conf.annotated
+===================================================================
+--- multipath-tools-091020.orig/multipath.conf.annotated
++++ multipath-tools-091020/multipath.conf.annotated
+@@ -191,6 +191,25 @@
+ # # default : determined by the process
+ # gid disk
+ #
++# #
++# # name : fast_io_fail_tmo
++# # scope : multipath & multipathd
++# # desc : The number of seconds the scsi layer will wait after a
++# # problem has been detected on a FC remote port before failing
++# # IO to devices on that remote port.
++# # values : off | n >= 0 (smaller than dev_loss_tmo)
++# # default : determined by the OS
++# fast_io_fail_tmo 5
++#
++# #
++# # name : dev_loss_tmo
++# # scope : multipath & multipathd
++# # desc : The number of seconds the scsi layer will wait after a
++# # problem has been detected on a FC remote port before
++# # removing it from the system.
++# # values : n > 0
++# # default : determined by the OS
++# dev_loss_tmo 600
+ #}
+ #
+ ##
+@@ -504,7 +523,6 @@
+ # # desc : If set to "yes", multipathd will disable queueing
+ # # when the last path to a device has been deleted.
+ # # values : yes|no
+-# # default : no
+ # #
+ # flush_on_last_del yes
+ #
+@@ -514,6 +532,24 @@
+ # # desc : product strings to blacklist for this vendor
+ # #
+ # product_blacklist LUN_Z
++#
++# #
++# # name : fast_io_fail_tmo
++# # scope : multipath & multipathd
++# # desc : The number of seconds the scsi layer will wait after
++# # a problem has been detected on a FC remote port
++# # before failing IO to devices on that remote port.
++# # values : off | n >= 0 (smaller than dev_loss_tmo)
++# fast_io_fail_tmo 5
++#
++# #
++# # name : dev_loss_tmo
++# # scope : multipath & multipathd
++# # desc : The number of seconds the scsi layer will wait after
++# # a problem has been detected on a FC remote port
++# # before removing it from the system.
++# # values : n > 0
++# dev_loss_tmo 600
+ # }
+ # device {
+ # vendor "COMPAQ "
+Index: multipath-tools-091020/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools-091020.orig/multipath/multipath.conf.5
++++ multipath-tools-091020/multipath/multipath.conf.5
+@@ -240,6 +240,17 @@ this to the system limit from /proc/sys/
+ maximum number of open fds is taken from the calling process. It is usually
+ 1024. To be safe, this should be set to the maximum number of paths plus 32,
+ if that number is greated than 1024.
++.TP
++.B fast_io_fail_tmo
++Specify the number of seconds the scsi layer will wait after a problem has been
++detected on a FC remote port before failing IO to devices on that remote port.
++This should be smaller than dev_loss_tmo. Setting this to
++.I off
++will disable the timeout.
++.TP
++.B dev_loss_tmo
++Specify the number of seconds the scsi layer will wait after a problem has
++been detected on a FC remote port before removing it from the system.
+ .
+ .SH "blacklist section"
+ The
+@@ -384,6 +395,10 @@ section:
+ .B no_path_retry
+ .TP
+ .B rr_min_io
++.TP
++.B fast_io_fail_tmo
++.TP
++.B dev_loss_tmo
+ .RE
+ .PD
+ .LP
+Index: multipath-tools-091020/libmultipath/dict.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/dict.c
++++ multipath-tools-091020/libmultipath/dict.c
+@@ -37,6 +37,35 @@ polling_interval_handler(vector strvec)
+ }
+
+ static int
++def_fast_io_fail_handler(vector strvec)
++{
++ char * buff;
++
++ buff = set_value(strvec);
++ if (strlen(buff) == 3 && !strcmp(buff, "off"))
++ conf->fast_io_fail = -1;
++ else if (sscanf(buff, "%d", &conf->fast_io_fail) != 1 ||
++ conf->fast_io_fail < -1)
++ conf->fast_io_fail = 0;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
++def_dev_loss_handler(vector strvec)
++{
++ char * buff;
++
++ buff = set_value(strvec);
++ if (sscanf(buff, "%u", &conf->dev_loss) != 1)
++ conf->dev_loss = 0;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
+ verbosity_handler(vector strvec)
+ {
+ char * buff;
+@@ -628,6 +657,37 @@ bl_product_handler(vector strvec)
+ }
+
+ static int
++hw_fast_io_fail_handler(vector strvec)
++{
++ char * buff;
++ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
++
++ buff = set_value(strvec);
++ if (strlen(buff) == 3 && !strcmp(buff, "off"))
++ hwe->fast_io_fail = -1;
++ else if (sscanf(buff, "%d", &hwe->fast_io_fail) != 1 ||
++ hwe->fast_io_fail < -1)
++ hwe->fast_io_fail = 0;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
++hw_dev_loss_handler(vector strvec)
++{
++ char * buff;
++ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
++
++ buff = set_value(strvec);
++ if (sscanf(buff, "%u", &hwe->dev_loss) != 1)
++ hwe->dev_loss = 0;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
+ hw_pgpolicy_handler(vector strvec)
+ {
+ char * buff;
+@@ -1390,6 +1450,26 @@ snprint_mp_flush_on_last_del (char * buf
+ }
+
+ static int
++snprint_hw_fast_io_fail(char * buff, int len, void * data)
++{
++ struct hwentry * hwe = (struct hwentry *)data;
++ if (!hwe->fast_io_fail)
++ return 0;
++ if (hwe->fast_io_fail == -1)
++ return snprintf(buff, len, "off");
++ return snprintf(buff, len, "%d", hwe->fast_io_fail);
++}
++
++static int
++snprint_hw_dev_loss(char * buff, int len, void * data)
++{
++ struct hwentry * hwe = (struct hwentry *)data;
++ if (!hwe->dev_loss)
++ return 0;
++ return snprintf(buff, len, "%u", hwe->dev_loss);
++}
++
++static int
+ snprint_hw_vendor (char * buff, int len, void * data)
+ {
+ struct hwentry * hwe = (struct hwentry *)data;
+@@ -1640,6 +1720,24 @@ snprint_def_polling_interval (char * buf
+ }
+
+ static int
++snprint_def_fast_io_fail(char * buff, int len, void * data)
++{
++ if (!conf->fast_io_fail)
++ return 0;
++ if (conf->fast_io_fail == -1)
++ return snprintf(buff, len, "off");
++ return snprintf(buff, len, "%d", conf->fast_io_fail);
++}
++
++static int
++snprint_def_dev_loss(char * buff, int len, void * data)
++{
++ if (!conf->dev_loss)
++ return 0;
++ return snprintf(buff, len, "%u", conf->dev_loss);
++}
++
++static int
+ snprint_def_verbosity (char * buff, int len, void * data)
+ {
+ if (conf->checkint == DEFAULT_VERBOSITY)
+@@ -1937,6 +2035,8 @@ init_keywords(void)
+ install_keyword("mode", &def_mode_handler, &snprint_def_mode);
+ install_keyword("uid", &def_uid_handler, &snprint_def_uid);
+ install_keyword("gid", &def_gid_handler, &snprint_def_gid);
++ install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
++ install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
+ __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
+ __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
+ __deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
+@@ -1991,6 +2091,8 @@ init_keywords(void)
+ install_keyword("rr_min_io", &hw_minio_handler, &snprint_hw_rr_min_io);
+ install_keyword("pg_timeout", &hw_pg_timeout_handler, &snprint_hw_pg_timeout);
+ install_keyword("flush_on_last_del", &hw_flush_on_last_del_handler, &snprint_hw_flush_on_last_del);
++ install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail);
++ install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss);
+ install_sublevel_end();
+
+ install_keyword_root("multipaths", &multipaths_handler);
+Index: multipath-tools-091020/libmultipath/config.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/config.h
++++ multipath-tools-091020/libmultipath/config.h
+@@ -31,6 +31,8 @@ struct hwentry {
+ int minio;
+ int pg_timeout;
+ int flush_on_last_del;
++ int fast_io_fail;
++ unsigned int dev_loss;
+ char * bl_product;
+ };
+
+@@ -75,6 +77,8 @@ struct config {
+ int daemon;
+ int flush_on_last_del;
+ int attribute_flags;
++ int fast_io_fail;
++ unsigned int dev_loss;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+Index: multipath-tools-091020/libmultipath/propsel.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/propsel.c
++++ multipath-tools-091020/libmultipath/propsel.c
+@@ -428,6 +428,48 @@ select_pg_timeout(struct multipath *mp)
+ }
+
+ extern int
++select_fast_io_fail(struct multipath *mp)
++{
++ if (mp->hwe && mp->hwe->fast_io_fail) {
++ mp->fast_io_fail = mp->hwe->fast_io_fail;
++ if (mp->fast_io_fail == -1)
++ condlog(3, "%s: fast_io_fail_tmo = off (controller default)", mp->alias);
++ else
++ condlog(3, "%s: fast_io_fail_tmo = %d (controller default)", mp->alias, mp->fast_io_fail);
++ return 0;
++ }
++ if (conf->fast_io_fail) {
++ mp->fast_io_fail = conf->fast_io_fail;
++ if (mp->fast_io_fail == -1)
++ condlog(3, "%s: fast_io_fail_tmo = off (config file default)", mp->alias);
++ else
++ condlog(3, "%s: fast_io_fail_tmo = %d (config file default)", mp->alias, mp->fast_io_fail);
++ return 0;
++ }
++ mp->fast_io_fail = 0;
++ return 0;
++}
++
++extern int
++select_dev_loss(struct multipath *mp)
++{
++ if (mp->hwe && mp->hwe->dev_loss) {
++ mp->dev_loss = mp->hwe->dev_loss;
++ condlog(3, "%s: dev_loss_tmo = %u (controller default)",
++ mp->alias, mp->dev_loss);
++ return 0;
++ }
++ if (conf->dev_loss) {
++ mp->dev_loss = conf->dev_loss;
++ condlog(3, "%s: dev_loss_tmo = %u (config file default)",
++ mp->alias, mp->dev_loss);
++ return 0;
++ }
++ mp->dev_loss = 0;
++ return 0;
++}
++
++extern int
+ select_flush_on_last_del(struct multipath *mp)
+ {
+ if (mp->flush_on_last_del == FLUSH_IN_PROGRESS)
+Index: multipath-tools-091020/libmultipath/structs.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/structs.h
++++ multipath-tools-091020/libmultipath/structs.h
+@@ -166,6 +166,8 @@ struct multipath {
+ int pg_timeout;
+ int flush_on_last_del;
+ int attribute_flags;
++ int fast_io_fail;
++ unsigned int dev_loss;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+Index: multipath-tools-091020/libmultipath/configure.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/configure.c
++++ multipath-tools-091020/libmultipath/configure.c
+@@ -70,7 +70,10 @@ setup_map (struct multipath * mpp)
+ select_mode(mpp);
+ select_uid(mpp);
+ select_gid(mpp);
++ select_fast_io_fail(mpp);
++ select_dev_loss(mpp);
+
++ sysfs_set_scsi_tmo(mpp);
+ /*
+ * assign paths to path groups -- start with no groups and all paths
+ * in mpp->paths
+Index: multipath-tools-091020/libmultipath/discovery.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/discovery.c
++++ multipath-tools-091020/libmultipath/discovery.c
+@@ -204,6 +204,43 @@ sysfs_get_fc_nodename (struct sysfs_devi
+ return 1;
+ }
+
++int
++sysfs_set_scsi_tmo (struct multipath *mpp)
++{
++ char attr_path[SYSFS_PATH_SIZE];
++ struct path *pp;
++ int i;
++ char value[11];
++
++ if (!mpp->dev_loss && !mpp->fast_io_fail)
++ return 0;
++ vector_foreach_slot(mpp->paths, pp, i) {
++ if (safe_snprintf(attr_path, SYSFS_PATH_SIZE,
++ "/class/fc_remote_ports/rport-%d:%d-%d",
++ pp->sg_id.host_no, pp->sg_id.channel,
++ pp->sg_id.scsi_id)) {
++ condlog(0, "attr_path '/class/fc_remote_ports/rport-%d:%d-%d' too large", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id);
++ return 1;
++ }
++ if (mpp->dev_loss){
++ snprintf(value, 11, "%u", mpp->dev_loss);
++ if (sysfs_attr_set_value(attr_path, "dev_loss_tmo",
++ value))
++ return 1;
++ }
++ if (mpp->fast_io_fail){
++ if (mpp->fast_io_fail == -1)
++ sprintf(value, "off");
++ else
++ snprintf(value, 11, "%u", mpp->fast_io_fail);
++ if (sysfs_attr_set_value(attr_path, "fast_io_fail",
++ value))
++ return 1;
++ }
++ }
++ return 0;
++}
++
+ static int
+ opennode (char * dev, int mode)
+ {
+Index: multipath-tools-091020/libmultipath/propsel.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/propsel.h
++++ multipath-tools-091020/libmultipath/propsel.h
+@@ -15,3 +15,5 @@ int select_minio(struct multipath *mp);
+ int select_mode(struct multipath *mp);
+ int select_uid(struct multipath *mp);
+ int select_gid(struct multipath *mp);
++int select_fast_io_fail(struct multipath *mp);
++int select_dev_loss(struct multipath *mp);
+Index: multipath-tools-091020/libmultipath/discovery.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/discovery.h
++++ multipath-tools-091020/libmultipath/discovery.h
+@@ -33,6 +33,7 @@ int path_offline (struct path *);
+ int pathinfo (struct path *, vector hwtable, int mask);
+ struct path * store_pathinfo (vector pathvec, vector hwtable,
+ char * devname, int flag);
++int sysfs_set_scsi_tmo (struct multipath *mpp);
+
+ /*
+ * discovery bitmask
+Index: multipath-tools-091020/libmultipath/sysfs.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/sysfs.c
++++ multipath-tools-091020/libmultipath/sysfs.c
+@@ -356,6 +356,62 @@ void sysfs_device_put(struct sysfs_devic
+ return;
+ }
+
++int
++sysfs_attr_set_value(const char *devpath, const char *attr_name,
++ const char *value)
++{
++ char path_full[PATH_SIZE];
++ int sysfs_len;
++ struct stat statbuf;
++ int fd, value_len, ret = -1;
++
++ dbg("open '%s'/'%s'", devpath, attr_name);
++ sysfs_len = snprintf(path_full, PATH_SIZE, "%s%s/%s", sysfs_path,
++ devpath, attr_name);
++ if (sysfs_len >= PATH_SIZE || sysfs_len < 0) {
++ if (sysfs_len < 0)
++ dbg("cannot copy sysfs path %s%s/%s : %s", sysfs_path,
++ devpath, attr_name, strerror(errno));
++ else
++ dbg("sysfs_path %s%s/%s too large", sysfs_path,
++ devpath, attr_name);
++ goto out;
++ }
++
++ if (stat(path_full, &statbuf) != 0) {
++ dbg("stat '%s' failed: %s" path_full, strerror(errno));
++ goto out;
++ }
++
++ /* skip directories */
++ if (S_ISDIR(statbuf.st_mode))
++ goto out;
++
++ if ((statbuf.st_mode & S_IWUSR) == 0)
++ goto out;
++
++ fd = open(path_full, O_WRONLY);
++ if (fd < 0) {
++ dbg("attribute '%s' can not be opened: %s",
++ path_full, strerror(errno));
++ goto out;
++ }
++ value_len = strlen(value) + 1;
++ ret = write(fd, value, value_len);
++ if (ret == value_len)
++ ret = 0;
++ else if (ret < 0)
++ dbg("write to %s failed: %s", path_full, strerror(errno));
++ else {
++ dbg("tried to write %d to %s. Wrote %d\n", value_len,
++ path_full, ret);
++ ret = -1;
++ }
++out:
++ return ret;
++}
++
++
+ char *sysfs_attr_get_value(const char *devpath, const char *attr_name)
+ {
+ char path_full[PATH_SIZE];
+Index: multipath-tools-091020/libmultipath/sysfs.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/sysfs.h
++++ multipath-tools-091020/libmultipath/sysfs.h
+@@ -22,5 +22,6 @@ void sysfs_device_put(struct sysfs_devic
+ char *sysfs_attr_get_value(const char *devpath, const char *attr_name);
+ int sysfs_resolve_link(char *path, size_t size);
+ int sysfs_get_size (struct sysfs_device * dev, unsigned long long * size);
+-
++int sysfs_attr_set_value(const char *devpath, const char *attr_name,
++ const char *value);
+ #endif
diff --git a/0013-RH-add-weighted_prio-prioritizer.patch b/0013-RH-add-weighted_prio-prioritizer.patch
new file mode 100644
index 0000000..2d2fc2f
--- /dev/null
+++ b/0013-RH-add-weighted_prio-prioritizer.patch
@@ -0,0 +1,533 @@
+Index: multipath-tools-091020/libmultipath/config.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/config.c
++++ multipath-tools-091020/libmultipath/config.c
+@@ -156,6 +156,9 @@ free_hwe (struct hwentry * hwe)
+ if (hwe->prio_name)
+ FREE(hwe->prio_name);
+
++ if (hwe->prio_args)
++ FREE(hwe->prio_args);
++
+ if (hwe->bl_product)
+ FREE(hwe->bl_product);
+
+@@ -195,6 +198,12 @@ free_mpe (struct mpentry * mpe)
+ if (mpe->alias)
+ FREE(mpe->alias);
+
++ if (mpe->prio_name)
++ FREE(mpe->prio_name);
++
++ if (mpe->prio_args)
++ FREE(mpe->prio_args);
++
+ FREE(mpe);
+ }
+
+@@ -279,6 +288,7 @@ merge_hwe (struct hwentry * hwe1, struct
+ merge_str(selector);
+ merge_str(checker_name);
+ merge_str(prio_name);
++ merge_str(prio_args);
+ merge_str(bl_product);
+ merge_num(pgpolicy);
+ merge_num(pgfailback);
+Index: multipath-tools-091020/libmultipath/config.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/config.h
++++ multipath-tools-091020/libmultipath/config.h
+@@ -24,6 +24,7 @@ struct hwentry {
+ char * selector;
+ char * checker_name;
+ char * prio_name;
++ char * prio_args;
+
+ int pgpolicy;
+ int pgfailback;
+@@ -42,6 +43,8 @@ struct mpentry {
+ char * alias;
+ char * getuid;
+ char * selector;
++ char * prio_name;
++ char * prio_args;
+
+ int pgpolicy;
+ int pgfailback;
+@@ -95,6 +98,7 @@ struct config {
+ char * hwhandler;
+ char * bindings_file;
+ char * prio_name;
++ char * prio_args;
+ char * checker_name;
+
+ vector keywords;
+Index: multipath-tools-091020/libmultipath/dict.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/dict.c
++++ multipath-tools-091020/libmultipath/dict.c
+@@ -139,11 +139,23 @@ def_getuid_callout_handler(vector strvec
+ static int
+ def_prio_handler(vector strvec)
+ {
+- conf->prio_name = set_value(strvec);
++ char *name, *args;
+
+- if (!conf->prio_name)
++ name = set_value(strvec);
++ if (!name)
+ return 1;
+
++ args = strpbrk(name, " \t");
++ if (args) {
++ *args = 0;
++ while(*++args && isblank(*args)); /* Do nothing */
++ }
++
++ conf->prio_name = STRDUP(name);
++ if (args && *args)
++ conf->prio_args = STRDUP(args);
++
++ FREE(name);
+ return 0;
+ }
+
+@@ -806,16 +818,27 @@ hw_handler_handler(vector strvec)
+ static int
+ hw_prio_handler(vector strvec)
+ {
++ char *name, *args;
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+
+ if (!hwe)
+ return 1;
+
+- hwe->prio_name = set_value(strvec);
+-
+- if (!hwe->prio_name)
++ name = set_value(strvec);
++ if (!name)
+ return 1;
+
++ args = strpbrk(name, " \t");
++ if (args) {
++ *args = 0;
++ while(*++args && isblank(*args)); /* Do nothing */
++ }
++
++ hwe->prio_name = STRDUP(name);
++ if (args && *args)
++ hwe->prio_args = STRDUP(args);
++
++ FREE(name);
+ return 0;
+ }
+
+@@ -1293,6 +1316,33 @@ mp_flush_on_last_del_handler(vector strv
+ return 0;
+ }
+
++static int
++mp_prio_handler(vector strvec)
++{
++ char *name, *args;
++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
++
++ if (!mpe)
++ return 1;
++
++ name = set_value(strvec);
++ if (!name)
++ return 1;
++
++ args = strpbrk(name, " \t");
++ if (args) {
++ *args = 0;
++ while(*++args && isblank(*args)); /* Do nothing */
++ }
++
++ mpe->prio_name = STRDUP(name);
++ if (args && *args)
++ mpe->prio_args = STRDUP(args);
++
++ FREE(name);
++ return 0;
++}
++
+ /*
+ * config file keywords printing
+ */
+@@ -1472,6 +1522,20 @@ snprint_mp_flush_on_last_del (char * buf
+ }
+
+ static int
++snprint_mp_prio (char * buff, int len, void * data)
++{
++ struct mpentry * mpe = (struct mpentry *)data;
++
++ if (!mpe->prio_name)
++ return 0;
++ if (!strcmp(mpe->prio_name, conf->prio_name) && !mpe->prio_args)
++ return 0;
++ if (!mpe->prio_args)
++ return snprintf(buff, len, "%s", mpe->prio_name);
++ return snprintf(buff, len, "%s %s", mpe->prio_name, mpe->prio_args);
++}
++
++static int
+ snprint_hw_fast_io_fail(char * buff, int len, void * data)
+ {
+ struct hwentry * hwe = (struct hwentry *)data;
+@@ -1545,10 +1609,11 @@ snprint_hw_prio (char * buff, int len, v
+
+ if (!hwe->prio_name)
+ return 0;
+- if (!strcmp(hwe->prio_name, conf->prio_name))
++ if (!strcmp(hwe->prio_name, conf->prio_name) && !hwe->prio_args)
+ return 0;
+-
+- return snprintf(buff, len, "%s", hwe->prio_name);
++ if (!hwe->prio_args)
++ return snprintf(buff, len, "%s", hwe->prio_name);
++ return snprintf(buff, len, "%s %s", hwe->prio_name, hwe->prio_args);
+ }
+
+ static int
+@@ -1837,10 +1902,14 @@ snprint_def_prio (char * buff, int len,
+ return 0;
+
+ if (strlen(conf->prio_name) == strlen(DEFAULT_PRIO) &&
+- !strcmp(conf->prio_name, DEFAULT_PRIO))
++ !strcmp(conf->prio_name, DEFAULT_PRIO) && !conf->prio_args)
+ return 0;
+-
+- return snprintf(buff, len, "%s", conf->prio_name);
++
++ if (!conf->prio_args)
++ return snprintf(buff, len, "%s", conf->prio_name);
++ else
++ return snprintf(buff, len, "%s %s", conf->prio_name,
++ conf->prio_args);
+ }
+
+ static int
+@@ -2146,5 +2215,6 @@ init_keywords(void)
+ install_keyword("mode", &mp_mode_handler, &snprint_mp_mode);
+ install_keyword("uid", &mp_uid_handler, &snprint_mp_uid);
+ install_keyword("gid", &mp_gid_handler, &snprint_mp_gid);
++ install_keyword("prio", &mp_prio_handler, &snprint_mp_prio);
+ install_sublevel_end();
+ }
+Index: multipath-tools-091020/libmultipath/discovery.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/discovery.c
++++ multipath-tools-091020/libmultipath/discovery.c
+@@ -800,30 +800,6 @@ get_state (struct path * pp, int daemon)
+ }
+
+ static int
+-get_prio (struct path * pp)
+-{
+- if (!pp)
+- return 0;
+-
+- if (!pp->prio) {
+- select_prio(pp);
+- if (!pp->prio) {
+- condlog(3, "%s: no prio selected", pp->dev);
+- return 1;
+- }
+- }
+- pp->priority = prio_getprio(pp->prio, pp);
+- if (pp->priority < 0) {
+- condlog(3, "%s: %s prio error", pp->dev, prio_name(pp->prio));
+- pp->priority = PRIO_UNDEF;
+- return 1;
+- }
+- condlog(3, "%s: %s prio = %u",
+- pp->dev, prio_name(pp->prio), pp->priority);
+- return 0;
+-}
+-
+-static int
+ get_uid (struct path * pp)
+ {
+ char buff[CALLOUT_MAX_SIZE];
+@@ -850,6 +826,32 @@ get_uid (struct path * pp)
+ return 0;
+ }
+
++static int
++get_prio (struct path * pp)
++{
++ if (!pp)
++ return 0;
++
++ if (!pp->prio) {
++ if (!strlen(pp->wwid))
++ get_uid(pp);
++ select_prio(pp);
++ if (!pp->prio) {
++ condlog(3, "%s: no prio selected", pp->dev);
++ return 1;
++ }
++ }
++ pp->priority = prio_getprio(pp->prio, pp);
++ if (pp->priority < 0) {
++ condlog(3, "%s: %s prio error", pp->dev, prio_name(pp->prio));
++ pp->priority = PRIO_UNDEF;
++ return 1;
++ }
++ condlog(3, "%s: %s prio = %u",
++ pp->dev, prio_name(pp->prio), pp->priority);
++ return 0;
++}
++
+ extern int
+ pathinfo (struct path *pp, vector hwtable, int mask)
+ {
+@@ -887,6 +889,9 @@ pathinfo (struct path *pp, vector hwtabl
+ goto blank;
+ }
+
++ if (mask & DI_WWID && !strlen(pp->wwid))
++ get_uid(pp);
++
+ /*
+ * Retrieve path priority, even for PATH_DOWN paths if it has never
+ * been successfully obtained before.
+@@ -895,9 +900,6 @@ pathinfo (struct path *pp, vector hwtabl
+ (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF))
+ get_prio(pp);
+
+- if (mask & DI_WWID && !strlen(pp->wwid))
+- get_uid(pp);
+-
+ return 0;
+
+ blank:
+Index: multipath-tools-091020/libmultipath/prio.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/prio.h
++++ multipath-tools-091020/libmultipath/prio.h
+@@ -24,6 +24,7 @@
+ #define PRIO_NETAPP "netapp"
+ #define PRIO_RANDOM "random"
+ #define PRIO_RDAC "rdac"
++#define PRIO_WEIGHTED "weighted"
+
+ /*
+ * Value used to mark the fact prio was not defined
+Index: multipath-tools-091020/libmultipath/prioritizers/Makefile
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/prioritizers/Makefile
++++ multipath-tools-091020/libmultipath/prioritizers/Makefile
+@@ -13,7 +13,8 @@ LIBS = \
+ libprioalua.so \
+ libpriotpg_pref.so \
+ libprionetapp.so \
+- libpriohds.so
++ libpriohds.so \
++ libprioweighted.so \
+
+ CFLAGS += -I..
+
+Index: multipath-tools-091020/libmultipath/prioritizers/weighted.c
+===================================================================
+--- /dev/null
++++ multipath-tools-091020/libmultipath/prioritizers/weighted.c
+@@ -0,0 +1,139 @@
++/******************************************************************************
++*******************************************************************************
++**
++** Copyright (C) 2009 Red Hat, Inc. All rights reserved.
++**
++** This copyrighted material is made available to anyone wishing to use,
++** modify, copy, or redistribute it subject to the terms and conditions
++** of the GNU General Public License v.2.
++**
++*******************************************************************************
++******************************************************************************/
++
++/* This prioritizer is based on a path's device name or its H:T:B:L. Both of
++ * these can change when the node is rebooted, and can differ from node to
++ * node. (i.e. there is no guarantee that sda will point to the same device
++ * after a reboot) If you use this prioritizer, it may be necessary to
++ * manually edit /etc/multipath.conf after any reboot
++ *
++ * Format:
++ * prio "weighted hbtl <regex> <prio> [<regex> <prio>]
++ * prio "weighted devname <regex> <prio> [<regex> <prio>]
++ *
++ * Examples:
++ * prio "weighted hbtl 4:* 2 3:.:.:. 1"
++ * prio "weighted devname sda 2 sde 1"
++ *
++ */
++
++#include <string.h>
++#include <prio.h>
++#include <debug.h>
++#include <regex.h>
++
++#include "weighted.h"
++
++#define DEFAULT_WEIGHTED_PRIO 0
++
++#define pp_weighted_log(prio, fmt, args...) \
++ condlog(prio, "%s: weighted prio: " fmt, dev, ##args)
++
++static char *
++next_str(char **str)
++{
++ char *next;
++
++ do {
++ next = strsep(str, " \t");
++ } while (next && strcmp(next, "") == 0);
++ return next;
++}
++
++
++static int
++match (char *dev, char *target, char *regex_str, char *prio_str,
++ unsigned int *prio)
++{
++
++ regex_t regex;
++ int err, ret = 0;
++ char *errbuf;
++ size_t errbuf_size;
++ unsigned int prio_match;
++
++ if (sscanf(prio_str, "%u", &prio_match) != 1) {
++ condlog(0, "%s: weighted prio: invalid prio '%s'", dev,
++ prio_str);
++ return 0;
++ }
++ err = regcomp(&regex, regex_str, REG_EXTENDED|REG_NOSUB);
++ if (err) {
++ errbuf_size = regerror(err, &regex, NULL, 0);
++ errbuf = malloc(errbuf_size);
++ regerror(err, &regex, errbuf, errbuf_size);
++ condlog(0, "%s: weighted prio: cannot compile regex '%s' : %s",
++ dev, regex_str, errbuf);
++ free(errbuf);
++ return 0;
++ }
++ if (regexec(&regex, target, 0, NULL, 0) == 0) {
++ *prio = prio_match;
++ ret = 1;
++ }
++
++ regfree(&regex);
++ return ret;
++}
++
++int
++prio_weighted(struct path * pp)
++{
++ char target[FILE_NAME_SIZE];
++ char *buff, *args, *ptr, *prio_str;
++ unsigned int prio = DEFAULT_WEIGHTED_PRIO;
++ char *regex_str = NULL;
++ int regex_size = 0;
++
++ if (!pp->prio_args)
++ return DEFAULT_WEIGHTED_PRIO;
++ buff = args = strdup(pp->prio_args);
++ ptr = next_str(&args);
++
++ if (strcasecmp(ptr, "hbtl") == 0)
++ sprintf(target, "%d:%d:%d:%d", pp->sg_id.host_no,
++ pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun);
++ else if (strcasecmp(ptr, "devname") == 0)
++ strcpy(target, pp->dev);
++ else {
++ condlog(0, "%s: weighted prio: invalid argument. Want 'hbtl' or 'devname'. Got '%s'", pp->dev, ptr);
++ goto out;
++ }
++
++ while ((ptr = next_str(&args)) != NULL) {
++
++ prio_str = next_str(&args);
++ if (!prio_str) {
++ condlog(0, "%s weighted prio: missing prio for regex '%s'", pp->dev, ptr);
++ goto out;
++ }
++ if (!regex_str || regex_size < strlen(ptr) + 3){
++ regex_size = strlen(ptr) + 3;
++ regex_str = realloc(regex_str, regex_size);
++ }
++ sprintf(regex_str, "%s%s%s", (ptr[0] == '^')? "" : "^",
++ ptr, (ptr[strlen(ptr)-1] == '$')? "" : "$");
++ if (match(pp->dev, target, regex_str, prio_str, &prio))
++ break;
++ }
++out:
++ free(buff);
++ if (regex_str)
++ free(regex_str);
++ return prio;
++}
++
++int
++getprio(struct path * pp)
++{
++ return prio_weighted(pp);
++}
+Index: multipath-tools-091020/libmultipath/propsel.c
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/propsel.c
++++ multipath-tools-091020/libmultipath/propsel.c
+@@ -312,14 +312,25 @@ select_getuid (struct path * pp)
+ extern int
+ select_prio (struct path * pp)
+ {
++ struct mpentry * mpe;
++
++ if ((mpe = find_mpe(pp->wwid)) && mpe->prio_name) {
++ pp->prio = prio_lookup(mpe->prio_name);
++ pp->prio_args = mpe->prio_args;
++ condlog(3, "%s: prio = %s (LUN setting)",
++ pp->dev, mpe->prio_name);
++ return 0;
++ }
+ if (pp->hwe && pp->hwe->prio_name) {
+ pp->prio = prio_lookup(pp->hwe->prio_name);
++ pp->prio_args = pp->hwe->prio_args;
+ condlog(3, "%s: prio = %s (controller setting)",
+ pp->dev, pp->hwe->prio_name);
+ return 0;
+ }
+ if (conf->prio_name) {
+ pp->prio = prio_lookup(conf->prio_name);
++ pp->prio_args = conf->prio_args;
+ condlog(3, "%s: prio = %s (config file default)",
+ pp->dev, conf->prio_name);
+ return 0;
+Index: multipath-tools-091020/libmultipath/structs.h
+===================================================================
+--- multipath-tools-091020.orig/libmultipath/structs.h
++++ multipath-tools-091020/libmultipath/structs.h
+@@ -142,6 +142,7 @@ struct path {
+ int priority;
+ int pgindex;
+ char * getuid;
++ char * prio_args;
+ struct prio * prio;
+ struct checker checker;
+ struct multipath * mpp;
+Index: multipath-tools-091020/libmultipath/prioritizers/weighted.h
+===================================================================
+--- /dev/null
++++ multipath-tools-091020/libmultipath/prioritizers/weighted.h
+@@ -0,0 +1,8 @@
++#ifndef _WEIGHTED_H
++#define _WEIGHTED_H
++
++#define PRIO_WEIGHTED "weighted"
++
++int prio_weighted(struct path *pp);
++
++#endif
diff --git a/0014-RH-add-hp_tur-checker.patch b/0014-RH-add-hp_tur-checker.patch
new file mode 100644
index 0000000..36bf136
--- /dev/null
+++ b/0014-RH-add-hp_tur-checker.patch
@@ -0,0 +1,207 @@
+---
+ libmultipath/checkers.h | 3 +
+ libmultipath/checkers/Makefile | 4 +
+ libmultipath/checkers/tur.c | 110 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 117 insertions(+)
+
+Index: multipath-tools/libmultipath/checkers.h
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers.h
++++ multipath-tools/libmultipath/checkers.h
+@@ -60,6 +60,7 @@ enum path_check_state {
+
+ #define DIRECTIO "directio"
+ #define TUR "tur"
++#define HP_TUR "hp_tur"
+ #define HP_SW "hp_sw"
+ #define RDAC "rdac"
+ #define EMC_CLARIION "emc_clariion"
+@@ -91,6 +92,7 @@ enum path_check_state {
+ #define CHECKER_MSG_LEN 256
+ #define CHECKER_DEV_LEN 256
+ #define LIB_CHECKER_NAMELEN 256
++#define WWID_SIZE 128
+
+ struct checker {
+ struct list_head node;
+@@ -99,6 +101,7 @@ struct checker {
+ int disable;
+ char name[CHECKER_NAME_LEN];
+ char message[CHECKER_MSG_LEN]; /* comm with callers */
++ char wwid[WWID_SIZE]; /* LUN wwid */
+ void * context; /* store for persistent data */
+ void ** mpcontext; /* store for persistent data shared
+ multipath-wide. Use MALLOC if
+Index: multipath-tools/libmultipath/checkers/Makefile
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers/Makefile
++++ multipath-tools/libmultipath/checkers/Makefile
+@@ -8,6 +8,7 @@ LIBS= \
+ libcheckcciss_tur.so \
+ libcheckreadsector0.so \
+ libchecktur.so \
++ libcheckhp_tur.so \
+ libcheckdirectio.so \
+ libcheckemc_clariion.so \
+ libcheckhp_sw.so \
+@@ -23,6 +24,9 @@ libcheckdirectio.so: libsg.o directio.o
+ libcheck%.so: libsg.o %.o
+ $(CC) $(SHARED_FLAGS) -o $@ $^
+
++hp_tur.o: tur.c
++ $(CC) $(CFLAGS) -DCHECK_WWID -c -o $@ $<
++
+ install:
+ $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir)
+
+Index: multipath-tools/libmultipath/checkers/tur.c
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers/tur.c
++++ multipath-tools/libmultipath/checkers/tur.c
+@@ -15,14 +15,101 @@
+
+ #include "checkers.h"
+
++#include "../libmultipath/debug.h"
+ #include "../libmultipath/sg_include.h"
+
+ #define TUR_CMD_LEN 6
+ #define HEAVY_CHECK_COUNT 10
+
++#ifdef CHECK_WWID
++#define MSG_TUR_UP "HP tur checker reports path is up"
++#define MSG_TUR_DOWN "HP tur checker reports path is down"
++#define MSG_TUR_GHOST "HP tur checker reports path is in standby state"
++#define EVPD 0x01
++#define PAGE_83 0x83
++#define INQUIRY_CMD 0x12
++#define INQUIRY_CMDLEN 6
++#define SCSI_INQ_BUFF_LEN 96
++#else
+ #define MSG_TUR_UP "tur checker reports path is up"
+ #define MSG_TUR_DOWN "tur checker reports path is down"
+ #define MSG_TUR_GHOST "tur checker reports path is in standby state"
++#endif
++
++#ifdef CHECK_WWID
++static int
++do_inq(struct checker * c, char * wwid)
++{
++ int ret = -1;
++ unsigned char inq_cmd[INQUIRY_CMDLEN] =
++ {INQUIRY_CMD, EVPD, PAGE_83, 0, SCSI_INQ_BUFF_LEN, 0 };
++ unsigned char sense_buffer[32];
++ unsigned char resp_buffer[SCSI_INQ_BUFF_LEN];
++ char *pbuff;
++
++ int m,k;
++ int retry_tur = 5;
++ struct sg_io_hdr io_hdr;
++
++retry:
++ memset(resp_buffer, 0, sizeof(resp_buffer));
++ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
++
++ io_hdr.interface_id = 'S';
++ io_hdr.cmd_len = sizeof(inq_cmd);
++ io_hdr.mx_sb_len = sizeof(sense_buffer);
++ io_hdr.dxfer_direction = -3; // Data transfer from the device.
++ io_hdr.dxfer_len = sizeof(resp_buffer);
++ io_hdr.dxferp = (unsigned char *)resp_buffer;
++ io_hdr.cmdp = inq_cmd;
++ io_hdr.sbp = sense_buffer;
++ io_hdr.timeout = 60; // IOCTL timeout value.
++
++ if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
++ condlog(0, "SG_IO ioctl failed: %s", strerror(errno));
++ return ret;
++ }
++ if (io_hdr.info & SG_INFO_OK_MASK){
++ int key = 0, asc, ascq;
++
++ if (io_hdr.host_status == DID_BUS_BUSY ||
++ io_hdr.host_status == DID_ERROR ||
++ io_hdr.host_status == DID_TRANSPORT_DISRUPTED) {
++ if (--retry_tur)
++ goto retry;
++ }
++ if (io_hdr.sb_len_wr > 3) {
++ if (io_hdr.sbp[0] == 0x72 || io_hdr.sbp[0] == 0x73) {
++ key = io_hdr.sbp[1] & 0x0f;
++ asc = io_hdr.sbp[2];
++ ascq = io_hdr.sbp[3];
++ } else if (io_hdr.sb_len_wr > 13 &&
++ ((io_hdr.sbp[0] & 0x7f) == 0x70 ||
++ (io_hdr.sbp[0] & 0x7f) == 0x71)) {
++ key = io_hdr.sbp[2] & 0x0f;
++ asc = io_hdr.sbp[12];
++ ascq = io_hdr.sbp[13];
++ }
++ }
++ if (key == 0x6) {
++ /* Unit Attention, retry */
++ if (--retry_tur)
++ goto retry;
++ }
++ return ret;
++ }
++
++ pbuff = (char *) resp_buffer;
++
++ wwid[0] = '3';
++ for (m = 8, k = 1; m < 11; ++m, k+=2)
++ sprintf(&wwid[k], "%02x", (unsigned int)pbuff[m] & 0xff);
++ for (m = 11; m < 24; ++m, k+=2)
++ sprintf(&wwid[k], "%02x", (unsigned int)pbuff[m] & 0xff);
++
++ return (ret = 0);
++}
++#endif
+
+ struct tur_checker_context {
+ void * dummy;
+@@ -30,6 +117,9 @@ struct tur_checker_context {
+
+ int libcheck_init (struct checker * c)
+ {
++#ifdef CHECK_WWID
++ memset(c->wwid, 0, WWID_SIZE);
++#endif
+ return 0;
+ }
+
+@@ -45,6 +135,9 @@ libcheck_check (struct checker * c)
+ unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
+ unsigned char sense_buffer[32];
+ int retry_tur = 5;
++#ifdef CHECK_WWID
++ char wwid[WWID_SIZE];
++#endif
+
+ retry:
+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
+@@ -110,6 +203,24 @@ libcheck_check (struct checker * c)
+ MSG(c, MSG_TUR_DOWN);
+ return PATH_DOWN;
+ }
++#ifdef CHECK_WWID
++ if (!do_inq(c, wwid)) {
++
++ if(!strcmp(c->wwid, "\0")) {
++ strcpy(c->wwid, wwid);
++ goto up;
++ }
++
++ if (strcmp(c->wwid , wwid)) {
++ condlog(0,
++ "hp_tur: Lun collided. new_wwid %s old_wwid %s",
++ wwid, c->wwid);
++ MSG(c, MSG_TUR_DOWN);
++ return PATH_DOWN;
++ }
++ }
++up:
++#endif
+ MSG(c, MSG_TUR_UP);
+ return PATH_UP;
+ }
diff --git a/0015-RH-add-multipathd-count-paths-cmd.patch b/0015-RH-add-multipathd-count-paths-cmd.patch
new file mode 100644
index 0000000..87826ef
--- /dev/null
+++ b/0015-RH-add-multipathd-count-paths-cmd.patch
@@ -0,0 +1,150 @@
+Index: multipath-tools/libmultipath/uevent.c
+===================================================================
+--- multipath-tools.orig/libmultipath/uevent.c
++++ multipath-tools/libmultipath/uevent.c
+@@ -52,6 +52,12 @@ pthread_mutex_t uevc_lock, *uevc_lockp =
+ pthread_cond_t uev_cond, *uev_condp = &uev_cond;
+ uev_trigger *my_uev_trigger;
+ void * my_trigger_data;
++int servicing_uev;
++
++int is_uevent_busy(void)
++{
++ return (uevqhp != NULL || servicing_uev);
++}
+
+ static struct uevent * alloc_uevent (void)
+ {
+@@ -96,7 +102,9 @@ uevq_thread(void * et)
+
+ while (1) {
+ pthread_mutex_lock(uevc_lockp);
++ servicing_uev = 0;
+ pthread_cond_wait(uev_condp, uevc_lockp);
++ servicing_uev = 1;
+ pthread_mutex_unlock(uevc_lockp);
+
+ service_uevq();
+Index: multipath-tools/libmultipath/uevent.h
+===================================================================
+--- multipath-tools.orig/libmultipath/uevent.h
++++ multipath-tools/libmultipath/uevent.h
+@@ -17,3 +17,4 @@ struct uevent {
+
+ int uevent_listen(int (*store_uev)(struct uevent *, void * trigger_data),
+ void * trigger_data);
++int is_uevent_busy(void);
+Index: multipath-tools/multipathd/cli.c
+===================================================================
+--- multipath-tools.orig/multipathd/cli.c
++++ multipath-tools/multipathd/cli.c
+@@ -174,6 +174,7 @@ load_keys (void)
+ r += add_key(keys, "devices", DEVICES, 0);
+ r += add_key(keys, "format", FMT, 1);
+ r += add_key(keys, "wildcards", WILDCARDS, 0);
++ r += add_key(keys, "count", COUNT, 0);
+ r += add_key(keys, "quit", QUIT, 0);
+ r += add_key(keys, "exit", QUIT, 0);
+
+@@ -443,6 +444,7 @@ cli_init (void) {
+ add_handler(RESTOREQ+MAPS, NULL);
+ add_handler(REINSTATE+PATH, NULL);
+ add_handler(FAIL+PATH, NULL);
++ add_handler(COUNT+PATHS, NULL);
+ add_handler(QUIT, NULL);
+
+ return 0;
+Index: multipath-tools/multipathd/cli_handlers.h
+===================================================================
+--- multipath-tools.orig/multipathd/cli_handlers.h
++++ multipath-tools/multipathd/cli_handlers.h
+@@ -25,5 +25,6 @@ int cli_restore_all_queueing(void * v, c
+ int cli_suspend(void * v, char ** reply, int * len, void * data);
+ int cli_resume(void * v, char ** reply, int * len, void * data);
+ int cli_reinstate(void * v, char ** reply, int * len, void * data);
++int cli_count_paths(void * v, char ** reply, int * len, void * data);
+ int cli_fail(void * v, char ** reply, int * len, void * data);
+ int cli_quit(void * v, char ** reply, int * len, void * data);
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -768,6 +768,7 @@ uxlsnrloop (void * ap)
+ set_handler_callback(RESTOREQ+MAP, cli_restore_queueing);
+ set_handler_callback(DISABLEQ+MAPS, cli_disable_all_queueing);
+ set_handler_callback(RESTOREQ+MAPS, cli_restore_all_queueing);
++ set_handler_callback(COUNT+PATHS, cli_count_paths);
+ set_handler_callback(QUIT, cli_quit);
+
+ umask(077);
+Index: multipath-tools/multipathd/cli.h
+===================================================================
+--- multipath-tools.orig/multipathd/cli.h
++++ multipath-tools/multipathd/cli.h
+@@ -23,6 +23,7 @@ enum {
+ __BLACKLIST,
+ __DEVICES,
+ __FMT,
++ __COUNT,
+ __WILDCARDS,
+ __QUIT,
+ };
+@@ -51,6 +52,7 @@ enum {
+ #define BLACKLIST (1 << __BLACKLIST)
+ #define DEVICES (1 << __DEVICES)
+ #define FMT (1 << __FMT)
++#define COUNT (1 << __COUNT)
+ #define WILDCARDS (1 << __WILDCARDS)
+ #define QUIT (1 << __QUIT)
+
+Index: multipath-tools/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools.orig/multipathd/cli_handlers.c
++++ multipath-tools/multipathd/cli_handlers.c
+@@ -18,6 +18,29 @@
+
+ #include "main.h"
+ #include "cli.h"
++#include "uevent.h"
++
++int
++count_paths(char **r, int *l, struct vectors *vecs)
++{
++ int i, len;
++ struct path *pp;
++ char * reply;
++ unsigned int maxlen = INITIAL_REPLY_LEN;
++ int monitored_count = 0;
++
++ reply = MALLOC(maxlen);
++ if (!reply)
++ return 1;
++ vector_foreach_slot(vecs->pathvec, pp, i)
++ if (pp->fd != -1)
++ monitored_count++;
++ len = sprintf(reply, "Paths: %d\nBusy: %s\n", monitored_count,
++ is_uevent_busy()? "True" : "False");
++ *r = reply;
++ *l = len + 1;
++ return 0;
++}
+
+ int
+ show_paths (char ** r, int * len, struct vectors * vecs, char * style)
+@@ -176,6 +199,16 @@ cli_list_config (void * v, char ** reply
+ }
+
+ int
++cli_count_paths (void * v, char ** reply, int * len, void * data)
++{
++ struct vectors * vecs = (struct vectors *)data;
++
++ condlog(3, "count paths (operator)");
++
++ return count_paths(reply, len, vecs);
++}
++
++int
+ cli_list_paths (void * v, char ** reply, int * len, void * data)
+ {
+ struct vectors * vecs = (struct vectors *)data;
diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec
index 83d760b..f97e3af 100644
--- a/device-mapper-multipath.spec
+++ b/device-mapper-multipath.spec
@@ -1,15 +1,16 @@
Summary: Tools to manage multipath devices using device-mapper
Name: device-mapper-multipath
Version: 0.4.9
-Release: 10%{?dist}
+Release: 11%{?dist}
License: GPL+
Group: System Environment/Base
URL: http://christophe.varoqui.free.fr/
Source0: multipath-tools-091027.tar.gz
-Source1: multipath.conf.redhat
+Source1: multipath.conf
# patch that should go upstream
Patch1: 0001-for-upstream-add-tpg_pref-prioritizer.patch
+Patch2: 0002-for-upstream-add-tmo-config-options.patch
# local patches
Patch1001: 0001-RH-queue-without-daemon.patch
Patch1002: 0002-RH-path-checker.patch
@@ -23,6 +24,9 @@ Patch1009: 0009-RH-multipathd-blacklist-all-by-default.patch
Patch1010: 0010-RH-multipath-rules-udev-changes.patch
Patch1011: 0011-RH-fix-init-script-LSB-headers.patch
Patch1012: 0012-RH-explicitly-disable-dm-udev-sync-support-in-kpartx.patch
+Patch1013: 0013-RH-add-weighted_prio-prioritizer.patch
+Patch1014: 0014-RH-add-hp_tur-checker.patch
+Patch1015: 0015-RH-add-multipathd-count-paths-cmd.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
@@ -67,6 +71,7 @@ kpartx manages partition creation and removal for device-mapper devices.
%prep
%setup -q -n multipath-tools
%patch1 -p1
+%patch2 -p1
%patch1001 -p1
%patch1002 -p1
%patch1003 -p1
@@ -79,6 +84,9 @@ kpartx manages partition creation and removal for device-mapper devices.
%patch1010 -p1
%patch1011 -p1
%patch1012 -p1
+%patch1013 -p1
+%patch1014 -p1
+%patch1015 -p1
cp %{SOURCE1} .
%build
@@ -136,7 +144,7 @@ fi
%{_mandir}/man8/multipathd.8.gz
%config /etc/udev/rules.d/40-multipath.rules
%doc AUTHOR COPYING FAQ
-%doc multipath.conf.redhat multipath.conf.annotated
+%doc multipath.conf multipath.conf.annotated
%doc multipath.conf.defaults multipath.conf.synthetic
%dir /etc/multipath
@@ -157,6 +165,15 @@ fi
%{_mandir}/man8/kpartx.8.gz
%changelog
+* Mon Nov 16 2009 Benjamin Marzinski <bmarzins@redhat.com> -0.4.9-11
+- Add 0002-for-upstream-add-tmo-config-options.patch
+ * Add fail_io_fail_tmo and dev_loss_tmo multipath.conf options
+- Add 0013-RH-add-weighted_prio-prioritizer.patch
+- Add 0014-RH-add-hp_tur-checker.patch
+- Add 0015-RH-add-multipathd-count-paths-cmd.patch
+- rename multipath.conf.redhat to multipath.conf, and remove the default
+ blacklist.
+
* Tue Oct 27 2009 Fabio M. Di Nitto <fdinitto@redhat.com> - 0.4.9-10
- Updated to latest upstream 0.4.9 code : multipath-tools-091027.tar.gz
(git commit id: a946bd4e2a529e5fba9c9547d03d3f91806618a3)
diff --git a/multipath.conf.redhat b/multipath.conf
index 312915a..6bbeadb 100644
--- a/multipath.conf.redhat
+++ b/multipath.conf
@@ -5,13 +5,6 @@
# For a list of configuration options with descriptions, see
# /usr/share/doc/device-mapper-multipath-0.4.9/multipath.conf.annotated
-
-# Blacklist all devices by default. Remove this to enable multipathing
-# on the default devices.
-blacklist {
- devnode "*"
-}
-
## By default, devices with vendor = "IBM" and product = "S/390.*" are
## blacklisted. To enable mulitpathing on these devies, uncomment the
## following lines.