From aba856f28c21347a5ef6ab0ec2813b860261db1c Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 25 Jul 2013 10:15:48 -0500 Subject: [PATCH] device-mapper-multipath-0.4.9-55 Modify 0015-RH-fix-output-buffer.patch * Fix memory leak Add 0048-RH-print-defaults.patch Add 0049-RH-remove-ID_FS_TYPE.patch * remove ID_FS_TYPE udev enviroment variable for multipath devices Add 0051-UP-fix-cli-resize.patch * check before dereferencing variables Add 0052-RH-fix-bad-derefs.patch * setup multipath free the multipath device when it fails, so don't keep using it. Add 0053-UP-fix-failback.patch * setting failback in the devices section was broken Add 0054-UP-keep-udev-ref.patch * multipathd needs to keep the same udev object across reconfigures Add 0055-UP-handle-quiesced-paths.patch * quiesced paths should be treated as down Add 0056-UP-alua-prio-fix.patch * Don't count the preferred bit for paths that are active/optimized Add 0057-UP-fix-tmo.patch * Cleanup how multipath sets dev_loss_tmo and fast_io_fail_tmo. Also make multipath get changing values directly from sysfs, instead of from udev, which caches them. Add 0058-UP-fix-failback.patch * make failback print the default value when you show configs. Add 0059-UP-flush-failure-queueing.patch * If you can't flush a multipath device, restore the queue_if_no_paths value Add 0060-UP-uevent-loop-udev.patch * make ueventloop grab it's own udev reference, since it is cancelled asychnrously. --- 0015-RH-fix-output-buffer.patch | 8 +- 0048-RH-print-defaults.patch | 25 ++ 0049-RH-remove-ID_FS_TYPE.patch | 17 ++ 0051-UP-fix-cli-resize.patch | 23 ++ 0052-RH-fix-bad-derefs.patch | 54 +++++ 0053-UP-fix-failback.patch | 23 ++ 0054-UP-keep-udev-ref.patch | 308 +++++++++++++++++++++++++ 0055-UP-handle-quiesced-paths.patch | 16 ++ 0056-UP-alua-prio-fix.patch | 17 ++ 0057-UP-fix-tmo.patch | 329 +++++++++++++++++++++++++++ 0058-UP-fix-failback.patch | 17 ++ 0059-UP-flush-failure-queueing.patch | 71 ++++++ 0060-UP-uevent-loop-udev.patch | 127 +++++++++++ device-mapper-multipath.spec | 62 ++++- 14 files changed, 1093 insertions(+), 4 deletions(-) create mode 100644 0048-RH-print-defaults.patch create mode 100644 0049-RH-remove-ID_FS_TYPE.patch create mode 100644 0051-UP-fix-cli-resize.patch create mode 100644 0052-RH-fix-bad-derefs.patch create mode 100644 0053-UP-fix-failback.patch create mode 100644 0054-UP-keep-udev-ref.patch create mode 100644 0055-UP-handle-quiesced-paths.patch create mode 100644 0056-UP-alua-prio-fix.patch create mode 100644 0057-UP-fix-tmo.patch create mode 100644 0058-UP-fix-failback.patch create mode 100644 0059-UP-flush-failure-queueing.patch create mode 100644 0060-UP-uevent-loop-udev.patch diff --git a/0015-RH-fix-output-buffer.patch b/0015-RH-fix-output-buffer.patch index 1a915f2..ffbbaad 100644 --- a/0015-RH-fix-output-buffer.patch +++ b/0015-RH-fix-output-buffer.patch @@ -1,6 +1,6 @@ --- - libmultipath/print.c | 30 ++++++++++++++++++++++++++---- - 1 file changed, 26 insertions(+), 4 deletions(-) + libmultipath/print.c | 31 +++++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) Index: multipath-tools-130222/libmultipath/print.c =================================================================== @@ -23,7 +23,7 @@ Index: multipath-tools-130222/libmultipath/print.c #define MAX(x,y) (x > y) ? x : y #define TAIL (line + len - 1 - c) -@@ -754,11 +757,30 @@ snprint_pathgroup (char * line, int len, +@@ -754,12 +757,32 @@ snprint_pathgroup (char * line, int len, extern void print_multipath_topology (struct multipath * mpp, int verbosity) { @@ -56,5 +56,7 @@ Index: multipath-tools-130222/libmultipath/print.c + } + } while (resize); printf("%s", buff); ++ FREE(buff); } + extern int diff --git a/0048-RH-print-defaults.patch b/0048-RH-print-defaults.patch new file mode 100644 index 0000000..be1ce57 --- /dev/null +++ b/0048-RH-print-defaults.patch @@ -0,0 +1,25 @@ +--- + libmultipath/dict.c | 4 ---- + 1 file changed, 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -2468,16 +2468,12 @@ snprint_def_verbosity (char * buff, int + static int + snprint_def_max_polling_interval (char * buff, int len, void * data) + { +- if (conf->max_checkint == MAX_CHECKINT(conf->checkint)) +- return 0; + return snprintf(buff, len, "%i", conf->max_checkint); + } + + static int + snprint_reassign_maps (char * buff, int len, void * data) + { +- if (conf->reassign_maps == DEFAULT_REASSIGN_MAPS) +- return 0; + return snprintf(buff, len, "\"%s\"", + conf->reassign_maps?"yes":"no"); + } diff --git a/0049-RH-remove-ID_FS_TYPE.patch b/0049-RH-remove-ID_FS_TYPE.patch new file mode 100644 index 0000000..732f50f --- /dev/null +++ b/0049-RH-remove-ID_FS_TYPE.patch @@ -0,0 +1,17 @@ +--- + multipath/multipath.rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -11,7 +11,7 @@ ACTION=="add", ENV{DEVTYPE}!="partition" + ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \ + TEST=="/etc/multipath.conf", \ + PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -c $tempnode", \ +- ENV{DM_MULTIPATH_DEVICE_PATH}="1" ++ ENV{DM_MULTIPATH_DEVICE_PATH}="1" ENV{ID_FS_TYPE}="mpath_member" + + ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DEVTYPE}!="partition", \ + RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}" diff --git a/0051-UP-fix-cli-resize.patch b/0051-UP-fix-cli-resize.patch new file mode 100644 index 0000000..f278607 --- /dev/null +++ b/0051-UP-fix-cli-resize.patch @@ -0,0 +1,23 @@ +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index 7b1cb62..4b860bb 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -603,7 +603,18 @@ cli_resize(void *v, char **reply, int *len, void *data) + } + + pgp = VECTOR_SLOT(mpp->pg, 0); ++ ++ if (!pgp){ ++ condlog(0, "%s: couldn't get path group. cannot resize", ++ mapname); ++ return 1; ++ } + pp = VECTOR_SLOT(pgp->paths, 0); ++ ++ if (!pp){ ++ condlog(0, "%s: couldn't get path. cannot resize", mapname); ++ return 1; ++ } + if (!pp->udev || sysfs_get_size(pp, &size)) { + condlog(0, "%s: couldn't get size for sysfs. cannot resize", + mapname); diff --git a/0052-RH-fix-bad-derefs.patch b/0052-RH-fix-bad-derefs.patch new file mode 100644 index 0000000..db5f1db --- /dev/null +++ b/0052-RH-fix-bad-derefs.patch @@ -0,0 +1,54 @@ +--- + multipathd/cli_handlers.c | 3 ++- + multipathd/main.c | 12 ++++++------ + 2 files changed, 8 insertions(+), 7 deletions(-) + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -632,7 +632,8 @@ cli_resize(void *v, char **reply, int *l + return 1; + + dm_lib_release(); +- setup_multipath(vecs, mpp); ++ if (setup_multipath(vecs, mpp) != 0) ++ return 1; + sync_map_state(mpp); + + return 0; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -134,7 +134,6 @@ coalesce_maps(struct vectors *vecs, vect + struct multipath * ompp; + vector ompv = vecs->mpvec; + unsigned int i; +- int j; + + vector_foreach_slot (ompv, ompp, i) { + if (!find_mp_by_wwid(nmpv, ompp->wwid)) { +@@ -148,16 +147,17 @@ coalesce_maps(struct vectors *vecs, vect + /* + * may be just because the device is open + */ ++ if (setup_multipath(vecs, ompp) != 0) { ++ i--; ++ continue; ++ } + if (!vector_alloc_slot(nmpv)) + return 1; + + vector_set_slot(nmpv, ompp); +- setup_multipath(vecs, ompp); + +- if ((j = find_slot(ompv, (void *)ompp)) != -1) +- vector_del_slot(ompv, j); +- +- continue; ++ vector_del_slot(ompv, i); ++ i--; + } + else { + dm_lib_release(); diff --git a/0053-UP-fix-failback.patch b/0053-UP-fix-failback.patch new file mode 100644 index 0000000..936655d --- /dev/null +++ b/0053-UP-fix-failback.patch @@ -0,0 +1,23 @@ +--- + libmultipath/dict.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -1126,11 +1126,11 @@ hw_failback_handler(vector strvec) + + buff = set_value(strvec); + +- if (strlen(buff) == 6 && !strcmp(buff, "\"manual\"")) ++ if (strlen(buff) == 6 && !strcmp(buff, "manual")) + hwe->pgfailback = -FAILBACK_MANUAL; +- else if (strlen(buff) == 9 && !strcmp(buff, "\"immediate\"")) ++ else if (strlen(buff) == 9 && !strcmp(buff, "immediate")) + hwe->pgfailback = -FAILBACK_IMMEDIATE; +- else if (strlen(buff) == 10 && !strcmp(buff, "\"followover\"")) ++ else if (strlen(buff) == 10 && !strcmp(buff, "followover")) + hwe->pgfailback = -FAILBACK_FOLLOWOVER; + else + hwe->pgfailback = atoi(buff); diff --git a/0054-UP-keep-udev-ref.patch b/0054-UP-keep-udev-ref.patch new file mode 100644 index 0000000..e42d716 --- /dev/null +++ b/0054-UP-keep-udev-ref.patch @@ -0,0 +1,308 @@ +--- + libmpathpersist/mpath_persist.c | 7 ++++--- + libmpathpersist/mpath_persist.h | 2 +- + libmpathpersist/mpath_pr_ioctl.c | 5 +++-- + libmultipath/config.c | 9 +++------ + libmultipath/config.h | 2 +- + mpathpersist/Makefile | 2 +- + mpathpersist/main.c | 11 +++++++---- + multipath/Makefile | 2 +- + multipath/main.c | 12 ++++++++---- + multipathd/main.c | 11 ++++++++--- + 10 files changed, 37 insertions(+), 26 deletions(-) + +Index: multipath-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/libmpathpersist/mpath_persist.c +@@ -1,4 +1,3 @@ +-#include "mpath_persist.h" + #include + #include + #include +@@ -8,6 +7,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -20,6 +20,7 @@ + #include + #include + ++#include "mpath_persist.h" + #include "mpathpr.h" + #include "mpath_pr_ioctl.h" + +@@ -32,9 +33,9 @@ + + + int +-mpath_lib_init (void) ++mpath_lib_init (struct udev *udev) + { +- if (load_config(DEFAULT_CONFIGFILE)){ ++ if (load_config(DEFAULT_CONFIGFILE, udev)){ + condlog(0, "Failed to initialize multipath config."); + return 1; + } +Index: multipath-tools-130222/libmpathpersist/mpath_persist.h +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.h ++++ multipath-tools-130222/libmpathpersist/mpath_persist.h +@@ -174,7 +174,7 @@ struct prout_param_descriptor { /* PROU + * + * RETURNS: 0->Success, 1->Failed. + */ +-extern int mpath_lib_init (void ); ++extern int mpath_lib_init (struct udev *udev); + + + /* +Index: multipath-tools-130222/libmpathpersist/mpath_pr_ioctl.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_pr_ioctl.c ++++ multipath-tools-130222/libmpathpersist/mpath_pr_ioctl.c +@@ -10,8 +10,9 @@ + #include + #include + #include +-#include "mpath_pr_ioctl.h" +-#include ++#include ++#include "mpath_pr_ioctl.h" ++#include + + #include + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -467,9 +467,6 @@ free_config (struct config * conf) + if (conf->dev) + FREE(conf->dev); + +- if (conf->udev) +- udev_unref(conf->udev); +- + if (conf->multipath_dir) + FREE(conf->multipath_dir); + +@@ -519,12 +516,12 @@ free_config (struct config * conf) + } + + int +-load_config (char * file) ++load_config (char * file, struct udev *udev) + { + if (!conf) + conf = alloc_config(); + +- if (!conf) ++ if (!conf || !udev) + return 1; + + /* +@@ -533,7 +530,7 @@ load_config (char * file) + if (!conf->verbosity) + conf->verbosity = DEFAULT_VERBOSITY; + +- conf->udev = udev_new(); ++ conf->udev = udev; + dm_drv_version(conf->version, TGT_MPATH); + conf->dev_type = DEV_NONE; + conf->minio = DEFAULT_MINIO; +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -159,7 +159,7 @@ void free_mptable (vector mptable); + + int store_hwe (vector hwtable, struct hwentry *); + +-int load_config (char * file); ++int load_config (char * file, struct udev * udev); + struct config * alloc_config (void); + void free_config (struct config * conf); + +Index: multipath-tools-130222/mpathpersist/main.c +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/main.c ++++ multipath-tools-130222/mpathpersist/main.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include "main.h" + #include +@@ -68,7 +69,8 @@ int main (int argc, char * argv[]) + int noisy = 0; + int num_transport =0; + void *resp = NULL; +- struct transportid * tmp; ++ struct transportid * tmp; ++ struct udev *udev = NULL; + + if (optind == argc) + { +@@ -84,8 +86,8 @@ int main (int argc, char * argv[]) + exit (1); + } + +- +- mpath_lib_init(); ++ udev = udev_new(); ++ mpath_lib_init(udev); + memset(transportids,0,MPATH_MX_TIDS); + + while (1) +@@ -461,12 +463,13 @@ int main (int argc, char * argv[]) + if (res < 0) + { + mpath_lib_exit(); ++ udev_unref(udev); + return MPATH_PR_FILE_ERROR; + } + + out : + mpath_lib_exit(); +- ++ udev_unref(udev); + return (ret >= 0) ? ret : MPATH_PR_OTHER; + } + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -435,6 +436,7 @@ convert_dev(char *dev) + int + main (int argc, char *argv[]) + { ++ struct udev *udev; + int arg; + extern char *optarg; + extern int optind; +@@ -445,7 +447,9 @@ main (int argc, char *argv[]) + exit(1); + } + +- if (load_config(DEFAULT_CONFIGFILE)) ++ udev = udev_new(); ++ ++ if (load_config(DEFAULT_CONFIGFILE, udev)) + exit(1); + + if (dm_prereq()) +@@ -560,11 +564,11 @@ main (int argc, char *argv[]) + + if (init_checkers()) { + condlog(0, "failed to initialize checkers"); +- exit(1); ++ goto out; + } + if (init_prio()) { + condlog(0, "failed to initialize prioritizers"); +- exit(1); ++ goto out; + } + dm_init(); + +@@ -628,7 +632,7 @@ out: + */ + free_config(conf); + conf = NULL; +- ++ udev_unref(udev); + #ifdef _DEBUG_ + dbg_free_final(NULL); + #endif +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -93,6 +93,8 @@ static sem_t exit_sem; + */ + struct vectors * gvecs; + ++struct udev * udev; ++ + static int + need_switch_pathgroup (struct multipath * mpp, int refresh) + { +@@ -1408,7 +1410,7 @@ reconfigure (struct vectors * vecs) + vecs->pathvec = NULL; + conf = NULL; + +- if (!load_config(DEFAULT_CONFIGFILE)) { ++ if (!load_config(DEFAULT_CONFIGFILE, udev)) { + conf->verbosity = old->verbosity; + conf->daemon = 1; + configure(vecs, 1); +@@ -1601,6 +1603,8 @@ child (void * param) + sem_init(&exit_sem, 0, 0); + signal_init(); + ++ udev = udev_new(); ++ + setup_thread_attr(&misc_attr, 64 * 1024, 1); + setup_thread_attr(&waiter_attr, 32 * 1024, 1); + +@@ -1615,7 +1619,7 @@ child (void * param) + condlog(2, "--------start up--------"); + condlog(2, "read " DEFAULT_CONFIGFILE); + +- if (load_config(DEFAULT_CONFIGFILE)) ++ if (load_config(DEFAULT_CONFIGFILE, udev)) + exit(1); + + if (init_checkers()) { +@@ -1765,7 +1769,8 @@ child (void * param) + */ + free_config(conf); + conf = NULL; +- ++ udev_unref(udev); ++ udev = NULL; + #ifdef _DEBUG_ + dbg_free_final(NULL); + #endif +Index: multipath-tools-130222/mpathpersist/Makefile +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/Makefile ++++ multipath-tools-130222/mpathpersist/Makefile +@@ -5,7 +5,7 @@ include ../Makefile.inc + OBJS = main.o + + CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) +-LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath ++LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath -ludev + + EXEC = mpathpersist + +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -7,7 +7,7 @@ include ../Makefile.inc + OBJS = main.o + + CFLAGS += -fPIC -I$(multipathdir) +-LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath ++LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath -ludev + + EXEC = multipath + diff --git a/0055-UP-handle-quiesced-paths.patch b/0055-UP-handle-quiesced-paths.patch new file mode 100644 index 0000000..0556a61 --- /dev/null +++ b/0055-UP-handle-quiesced-paths.patch @@ -0,0 +1,16 @@ +--- + libmultipath/discovery.c | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -799,6 +799,7 @@ path_offline (struct path * pp) + condlog(3, "%s: path state = %s", pp->dev, buff); + + if (!strncmp(buff, "offline", 7) || ++ !strncmp(buff, "quiesce", 7) || + !strncmp(buff, "transport-offline", 17)) { + pp->offline = 1; + return PATH_DOWN; diff --git a/0056-UP-alua-prio-fix.patch b/0056-UP-alua-prio-fix.patch new file mode 100644 index 0000000..0ac41ab --- /dev/null +++ b/0056-UP-alua-prio-fix.patch @@ -0,0 +1,17 @@ +--- + libmultipath/prioritizers/alua.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/prioritizers/alua.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua.c +@@ -108,7 +108,7 @@ int getprio (struct path * pp, char * ar + default: + rc = 0; + } +- if (priopath) ++ if (priopath && aas != AAS_OPTIMIZED) + rc += 80; + } else { + switch(-rc) { diff --git a/0057-UP-fix-tmo.patch b/0057-UP-fix-tmo.patch new file mode 100644 index 0000000..0bfc46b --- /dev/null +++ b/0057-UP-fix-tmo.patch @@ -0,0 +1,329 @@ +--- + libmultipath/discovery.c | 109 +++++++++++++++++++++++++++++++++++++---------- + libmultipath/sysfs.c | 86 +++++++++++++++++++++++++++++++------ + libmultipath/sysfs.h | 2 + 3 files changed, 161 insertions(+), 36 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -162,7 +162,6 @@ declare_sysfs_get_str(cutype); + declare_sysfs_get_str(vendor); + declare_sysfs_get_str(model); + declare_sysfs_get_str(rev); +-declare_sysfs_get_str(state); + declare_sysfs_get_str(dev); + + int +@@ -315,9 +314,14 @@ static void + sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + { + struct udev_device *rport_dev = NULL; +- char value[11]; ++ char value[16]; + char rport_id[32]; ++ int delay_fast_io_fail = 0; ++ int current_dev_loss = 0; ++ int ret; + ++ if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET) ++ return; + sprintf(rport_id, "rport-%d:%d-%d", + pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); + rport_dev = udev_device_new_from_subsystem_sysname(conf->udev, +@@ -330,33 +334,85 @@ sysfs_set_rport_tmo(struct multipath *mp + condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no, + pp->sg_id.channel, pp->sg_id.scsi_id, rport_id); + +- snprintf(value, 11, "%u", mpp->dev_loss); +- if (mpp->dev_loss && +- sysfs_attr_set_value(rport_dev, "dev_loss_tmo", value, 11) <= 0) { +- if ((mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET || +- mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) +- && mpp->dev_loss > 600) { +- condlog(3, "%s: limiting dev_loss_tmo to 600, since " +- "fast_io_fail is not set", mpp->alias); +- snprintf(value, 11, "%u", 600); +- if (sysfs_attr_set_value(rport_dev, "dev_loss_tmo", +- value, 11) <= 0) +- condlog(0, "%s failed to set dev_loss_tmo", +- mpp->alias); ++ memset(value, 0, 16); ++ if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { ++ ret = sysfs_attr_get_value(rport_dev, "dev_loss_tmo", ++ value, 16); ++ if (ret <= 0) { ++ condlog(0, "%s: failed to read dev_loss_tmo value, " ++ "error %d", rport_id, -ret); + goto out; + } ++ if (sscanf(value, "%u\n", ¤t_dev_loss) != 1) { ++ condlog(0, "%s: Cannot parse dev_loss_tmo " ++ "attribute '%s'", rport_id, value); ++ goto out; ++ } ++ if ((mpp->dev_loss && ++ mpp->fast_io_fail >= (int)mpp->dev_loss) || ++ (!mpp->dev_loss && ++ mpp->fast_io_fail >= (int)current_dev_loss)) { ++ condlog(3, "%s: limiting fast_io_fail_tmo to %d, since " ++ "it must be less than dev_loss_tmo", ++ rport_id, mpp->dev_loss - 1); ++ if (mpp->dev_loss) ++ mpp->fast_io_fail = mpp->dev_loss - 1; ++ else ++ mpp->fast_io_fail = current_dev_loss - 1; ++ } ++ if (mpp->fast_io_fail >= (int)current_dev_loss) ++ delay_fast_io_fail = 1; ++ } ++ if (mpp->dev_loss > 600 && ++ (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF || ++ mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)) { ++ condlog(3, "%s: limiting dev_loss_tmo to 600, since " ++ "fast_io_fail is unset or off", rport_id); ++ mpp->dev_loss = 600; + } +- if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET){ ++ if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { + if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) + sprintf(value, "off"); + else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO) + sprintf(value, "0"); ++ else if (delay_fast_io_fail) ++ snprintf(value, 16, "%u", current_dev_loss - 1); + else +- snprintf(value, 11, "%u", mpp->fast_io_fail); +- if (sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo", +- value, 11) <= 0) { +- condlog(0, "%s failed to set fast_io_fail_tmo", +- mpp->alias); ++ snprintf(value, 16, "%u", mpp->fast_io_fail); ++ ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo", ++ value, strlen(value)); ++ if (ret <= 0) { ++ if (ret == -EBUSY) ++ condlog(3, "%s: rport blocked", rport_id); ++ else ++ condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d", ++ rport_id, value, -ret); ++ goto out; ++ } ++ } ++ if (mpp->dev_loss) { ++ snprintf(value, 16, "%u", mpp->dev_loss); ++ ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo", ++ value, strlen(value)); ++ if (ret <= 0) { ++ if (ret == -EBUSY) ++ condlog(3, "%s: rport blocked", rport_id); ++ else ++ condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d", ++ rport_id, value, -ret); ++ goto out; ++ } ++ } ++ if (delay_fast_io_fail) { ++ snprintf(value, 16, "%u", mpp->fast_io_fail); ++ ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo", ++ value, strlen(value)); ++ if (ret <= 0) { ++ if (ret == -EBUSY) ++ condlog(3, "%s: rport blocked", rport_id); ++ else ++ condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d", ++ rport_id, value, -ret); + } + } + out: +@@ -394,7 +450,7 @@ sysfs_set_session_tmo(struct multipath * + } else { + snprintf(value, 11, "%u", mpp->fast_io_fail); + if (sysfs_attr_set_value(session_dev, "recovery_tmo", +- value, 11)) { ++ value, 11) <= 0) { + condlog(3, "%s: Failed to set recovery_tmo, " + " error %d", pp->dev, errno); + } +@@ -752,6 +808,9 @@ cciss_sysfs_pathinfo (struct path * pp) + static int + common_sysfs_pathinfo (struct path * pp) + { ++ if (!pp) ++ return 1; ++ + if (!pp->udev) { + condlog(4, "%s: udev not initialised", pp->dev); + return 1; +@@ -793,7 +852,8 @@ path_offline (struct path * pp) + return PATH_DOWN; + } + +- if (sysfs_get_state(parent, buff, SCSI_STATE_SIZE)) ++ memset(buff, 0x0, SCSI_STATE_SIZE); ++ if (sysfs_attr_get_value(parent, "state", buff, SCSI_STATE_SIZE) <= 0) + return PATH_DOWN; + + condlog(3, "%s: path state = %s", pp->dev, buff); +@@ -983,6 +1043,9 @@ pathinfo (struct path *pp, vector hwtabl + { + int path_state; + ++ if (!pp) ++ return 1; ++ + condlog(3, "%s: mask = 0x%x", pp->dev, mask); + + /* +Index: multipath-tools-130222/libmultipath/sysfs.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/sysfs.c ++++ multipath-tools-130222/libmultipath/sysfs.c +@@ -38,7 +38,12 @@ + #include "debug.h" + #include "devmapper.h" + +-ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, ++/* ++ * When we modify an attribute value we cannot rely on libudev for now, ++ * as libudev lacks the capability to update an attribute value. ++ * So for modified attributes we need to implement our own function. ++ */ ++ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name, + char * value, size_t value_len) + { + char devpath[PATH_SIZE]; +@@ -54,28 +59,83 @@ ssize_t sysfs_attr_set_value(struct udev + condlog(4, "open '%s'", devpath); + if (stat(devpath, &statbuf) != 0) { + condlog(4, "stat '%s' failed: %s", devpath, strerror(errno)); +- return 0; ++ return -errno; + } + + /* skip directories */ +- if (S_ISDIR(statbuf.st_mode)) +- return 0; ++ if (S_ISDIR(statbuf.st_mode)) { ++ condlog(4, "%s is a directory", devpath); ++ return -EISDIR; ++ } + + /* skip non-writeable files */ +- if ((statbuf.st_mode & S_IWUSR) == 0) ++ if ((statbuf.st_mode & S_IRUSR) == 0) { ++ condlog(4, "%s is not readable", devpath); ++ return -EPERM; ++ } ++ ++ /* read attribute value */ ++ fd = open(devpath, O_RDONLY); ++ if (fd < 0) { ++ condlog(4, "attribute '%s' can not be opened: %s", ++ devpath, strerror(errno)); ++ return -errno; ++ } ++ size = read(fd, value, value_len); ++ if (size < 0) { ++ condlog(4, "read from %s failed: %s", devpath, strerror(errno)); ++ size = -errno; ++ } else if (size == value_len) { ++ condlog(4, "overflow while reading from %s", devpath); ++ size = 0; ++ } ++ ++ close(fd); ++ return size; ++} ++ ++ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, ++ char * value, size_t value_len) ++{ ++ char devpath[PATH_SIZE]; ++ struct stat statbuf; ++ int fd; ++ ssize_t size = -1; ++ ++ if (!dev || !attr_name || !value || !value_len) + return 0; + ++ snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev), ++ attr_name); ++ condlog(4, "open '%s'", devpath); ++ if (stat(devpath, &statbuf) != 0) { ++ condlog(4, "stat '%s' failed: %s", devpath, strerror(errno)); ++ return -errno; ++ } ++ ++ /* skip directories */ ++ if (S_ISDIR(statbuf.st_mode)) { ++ condlog(4, "%s is a directory", devpath); ++ return -EISDIR; ++ } ++ ++ /* skip non-writeable files */ ++ if ((statbuf.st_mode & S_IWUSR) == 0) { ++ condlog(4, "%s is not writeable", devpath); ++ return -EPERM; ++ } ++ + /* write attribute value */ + fd = open(devpath, O_WRONLY); + if (fd < 0) { + condlog(4, "attribute '%s' can not be opened: %s", + devpath, strerror(errno)); +- return 0; ++ return -errno; + } + size = write(fd, value, value_len); + if (size < 0) { + condlog(4, "write to %s failed: %s", devpath, strerror(errno)); +- size = 0; ++ size = -errno; + } else if (size < value_len) { + condlog(4, "tried to write %ld to %s. Wrote %ld", + (long)value_len, devpath, (long)size); +@@ -89,14 +149,14 @@ ssize_t sysfs_attr_set_value(struct udev + int + sysfs_get_size (struct path *pp, unsigned long long * size) + { +- const char * attr; ++ char attr[255]; + int r; + +- if (!pp->udev) ++ if (!pp->udev || !size) + return 1; + +- attr = udev_device_get_sysattr_value(pp->udev, "size"); +- if (!attr) { ++ attr[0] = '\0'; ++ if (sysfs_attr_get_value(pp->udev, "size", attr, 255) == 0) { + condlog(3, "%s: No size attribute in sysfs", pp->dev); + return 1; + } +@@ -104,8 +164,8 @@ sysfs_get_size (struct path *pp, unsigne + r = sscanf(attr, "%llu\n", size); + + if (r != 1) { +- condlog(3, "%s: Cannot parse size attribute '%s'", +- pp->dev, attr); ++ condlog(3, "%s: Cannot parse size attribute", pp->dev); ++ *size = 0; + return 1; + } + +Index: multipath-tools-130222/libmultipath/sysfs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/sysfs.h ++++ multipath-tools-130222/libmultipath/sysfs.h +@@ -7,6 +7,8 @@ + + ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, + char * value, size_t value_len); ++ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name, ++ char * value, size_t value_len); + int sysfs_get_size (struct path *pp, unsigned long long * size); + int sysfs_check_holders(char * check_devt, char * new_devt); + #endif diff --git a/0058-UP-fix-failback.patch b/0058-UP-fix-failback.patch new file mode 100644 index 0000000..d1fbaeb --- /dev/null +++ b/0058-UP-fix-failback.patch @@ -0,0 +1,17 @@ +--- + libmultipath/dict.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -2562,7 +2562,7 @@ snprint_def_failback (char * buff, int l + if (!pgfailback) + pgfailback = DEFAULT_FAILBACK; + +- switch(conf->pgfailback) { ++ switch(pgfailback) { + case FAILBACK_UNDEF: + break; + case -FAILBACK_MANUAL: diff --git a/0059-UP-flush-failure-queueing.patch b/0059-UP-flush-failure-queueing.patch new file mode 100644 index 0000000..f72f314 --- /dev/null +++ b/0059-UP-flush-failure-queueing.patch @@ -0,0 +1,71 @@ +--- + libmultipath/devmapper.c | 21 +++++++++++++++++---- + libmultipath/devmapper.h | 2 +- + 2 files changed, 18 insertions(+), 5 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -363,7 +363,7 @@ out: + } + + extern int +-dm_get_map(char * name, unsigned long long * size, char * outparams) ++dm_get_map(const char * name, unsigned long long * size, char * outparams) + { + int r = 1; + struct dm_task *dmt; +@@ -682,7 +682,9 @@ _dm_flush_map (const char * mapname, int + extern int + dm_suspend_and_flush_map (const char * mapname) + { +- int s; ++ int s = 0, queue_if_no_path = 0; ++ unsigned long long mapsize; ++ char params[PARAMS_SIZE] = {0}; + + if (!dm_map_present(mapname)) + return 0; +@@ -690,8 +692,17 @@ dm_suspend_and_flush_map (const char * m + if (dm_type(mapname, TGT_MPATH) <= 0) + return 0; /* nothing to do */ + +- s = dm_queue_if_no_path((char *)mapname, 0); +- if (!s) ++ if (!dm_get_map(mapname, &mapsize, params)) { ++ if (strstr(params, "queue_if_no_path")) ++ queue_if_no_path = 1; ++ } ++ ++ if (queue_if_no_path) ++ s = dm_queue_if_no_path((char *)mapname, 0); ++ /* Leave queue_if_no_path alone if unset failed */ ++ if (s) ++ queue_if_no_path = 0; ++ else + s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0); + + if (!dm_flush_map(mapname)) { +@@ -700,6 +711,8 @@ dm_suspend_and_flush_map (const char * m + } + condlog(2, "failed to remove multipath map %s", mapname); + dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname); ++ if (queue_if_no_path) ++ s = dm_queue_if_no_path((char *)mapname, 1); + return 1; + } + +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -14,7 +14,7 @@ int dm_simplecmd_noflush (int, const cha + int dm_addmap_create (struct multipath *mpp, char *params); + int dm_addmap_reload (struct multipath *mpp, char *params); + int dm_map_present (const char *); +-int dm_get_map(char *, unsigned long long *, char *); ++int dm_get_map(const char *, unsigned long long *, char *); + int dm_get_status(char *, char *); + int dm_type(const char *, char *); + int _dm_flush_map (const char *, int); diff --git a/0060-UP-uevent-loop-udev.patch b/0060-UP-uevent-loop-udev.patch new file mode 100644 index 0000000..88fc005 --- /dev/null +++ b/0060-UP-uevent-loop-udev.patch @@ -0,0 +1,127 @@ +--- + libmultipath/uevent.c | 17 ++++++++++++----- + libmultipath/uevent.h | 4 +++- + multipathd/main.c | 8 +++++--- + 3 files changed, 20 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/libmultipath/uevent.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uevent.c ++++ multipath-tools-130222/libmultipath/uevent.c +@@ -47,7 +47,6 @@ + #include "list.h" + #include "uevent.h" + #include "vector.h" +-#include "config.h" + + typedef int (uev_trigger)(struct uevent *, void * trigger_data); + +@@ -127,11 +126,14 @@ service_uevq(struct list_head *tmpq) + + static void uevq_stop(void *arg) + { ++ struct udev *udev = arg; ++ + condlog(3, "Stopping uev queue"); + pthread_mutex_lock(uevq_lockp); + my_uev_trigger = NULL; + pthread_cond_signal(uev_condp); + pthread_mutex_unlock(uevq_lockp); ++ udev_unref(udev); + } + + void +@@ -399,9 +401,9 @@ exit: + return 1; + } + +-int uevent_listen(void) ++int uevent_listen(struct udev *udev) + { +- int err; ++ int err = 2; + struct udev_monitor *monitor = NULL; + int fd, socket_flags; + int need_failback = 1; +@@ -411,9 +413,14 @@ int uevent_listen(void) + * thereby not getting to empty the socket's receive buffer queue + * often enough. + */ +- pthread_cleanup_push(uevq_stop, NULL); ++ if (!udev) { ++ condlog(1, "no udev context"); ++ return 1; ++ } ++ udev_ref(udev); ++ pthread_cleanup_push(uevq_stop, udev); + +- monitor = udev_monitor_new_from_netlink(conf->udev, "udev"); ++ monitor = udev_monitor_new_from_netlink(udev, "udev"); + if (!monitor) { + condlog(2, "failed to create udev monitor"); + goto out; +Index: multipath-tools-130222/libmultipath/uevent.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uevent.h ++++ multipath-tools-130222/libmultipath/uevent.h +@@ -13,6 +13,8 @@ + #define NETLINK_KOBJECT_UEVENT 15 + #endif + ++struct udev; ++ + struct uevent { + struct list_head node; + struct udev_device *udev; +@@ -27,7 +29,7 @@ struct uevent { + int is_uevent_busy(void); + void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached); + +-int uevent_listen(void); ++int uevent_listen(struct udev *udev); + int uevent_dispatch(int (*store_uev)(struct uevent *, void * trigger_data), + void * trigger_data); + int uevent_get_major(struct uevent *uev); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -840,7 +840,7 @@ out: + static void * + ueventloop (void * ap) + { +- if (uevent_listen()) ++ if (uevent_listen(udev)) + condlog(0, "error starting uevent listener"); + + return NULL; +@@ -1593,7 +1593,7 @@ static int + child (void * param) + { + pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr; +- pthread_attr_t log_attr, misc_attr; ++ pthread_attr_t log_attr, misc_attr, uevent_attr; + struct vectors * vecs; + struct multipath * mpp; + int i; +@@ -1606,6 +1606,7 @@ child (void * param) + udev = udev_new(); + + setup_thread_attr(&misc_attr, 64 * 1024, 1); ++ setup_thread_attr(&uevent_attr, 128 * 1024, 1); + setup_thread_attr(&waiter_attr, 32 * 1024, 1); + + if (logsink) { +@@ -1671,10 +1672,11 @@ child (void * param) + /* + * Start uevent listener early to catch events + */ +- if ((rc = pthread_create(&uevent_thr, &misc_attr, ueventloop, vecs))) { ++ if ((rc = pthread_create(&uevent_thr, &uevent_attr, ueventloop, udev))) { + condlog(0, "failed to create uevent thread: %d", rc); + exit(1); + } ++ pthread_attr_destroy(&uevent_attr); + if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) { + condlog(0, "failed to create cli listener: %d", rc); + exit(1); diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 38ae7f4..259e76c 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,7 +1,7 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath Version: 0.4.9 -Release: 54%{?dist} +Release: 55%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -55,6 +55,19 @@ Patch0044: 0044-RHBZ-976688-fix-wipe-wwids.patch Patch0045: 0045-RHBZ-977297-man-page-fix.patch Patch0046: 0046-RHBZ-883981-move-udev-rules.patch Patch0047: 0047-RHBZ-980777-kpartx-read-only-loop-devs.patch +Patch0048: 0048-RH-print-defaults.patch +Patch0049: 0049-RH-remove-ID_FS_TYPE.patch +#Patch0050: 0050-RH-listing-speedup.patch +Patch0051: 0051-UP-fix-cli-resize.patch +Patch0052: 0052-RH-fix-bad-derefs.patch +Patch0053: 0053-UP-fix-failback.patch +Patch0054: 0054-UP-keep-udev-ref.patch +Patch0055: 0055-UP-handle-quiesced-paths.patch +Patch0056: 0056-UP-alua-prio-fix.patch +Patch0057: 0057-UP-fix-tmo.patch +Patch0058: 0058-UP-fix-failback.patch +Patch0059: 0059-UP-flush-failure-queueing.patch +Patch0060: 0060-UP-uevent-loop-udev.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -154,6 +167,19 @@ kpartx manages partition creation and removal for device-mapper devices. %patch0045 -p1 %patch0046 -p1 %patch0047 -p1 +%patch0048 -p1 +%patch0049 -p1 +# %%patch0050 -p1 +%patch0051 -p1 +%patch0052 -p1 +%patch0053 -p1 +%patch0054 -p1 +%patch0055 -p1 +%patch0056 -p1 +%patch0057 -p1 +%patch0058 -p1 +%patch0059 -p1 +%patch0060 -p1 cp %{SOURCE1} . %build @@ -247,6 +273,40 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/kpartx.8.gz %changelog +* Thu Jul 25 2013 Benjamin Marzinski 0.4.9-55 +- Modify 0015-RH-fix-output-buffer.patch + * Fix memory leak +- Add 0047-RHBZ-kpartx-read-only-loop-devs.patch + * Fix read only loop device handling +- Add 0048-RH-print-defaults.patch +- Add 0049-RH-remove-ID_FS_TYPE.patch + * remove ID_FS_TYPE udev enviroment variable for multipath devices +- Add 0051-UP-fix-cli-resize.patch + * check before dereferencing variables +- Add 0052-RH-fix-bad-derefs.patch + * setup multipath free the multipath device when it fails, so don't keep + using it. +- Add 0053-UP-fix-failback.patch + * setting failback in the devices section was broken +- Add 0054-UP-keep-udev-ref.patch + * multipathd needs to keep the same udev object across reconfigures +- Add 0055-UP-handle-quiesced-paths.patch + * quiesced paths should be treated as down +- Add 0056-UP-alua-prio-fix.patch + * Don't count the preferred bit for paths that are active/optimized +- Add 0057-UP-fix-tmo.patch + * Cleanup how multipath sets dev_loss_tmo and fast_io_fail_tmo. Also + make multipath get changing values directly from sysfs, instead of + from udev, which caches them. +- Add 0058-UP-fix-failback.patch + * make failback print the default value when you show configs. +- Add 0059-UP-flush-failure-queueing.patch + * If you can't flush a multipath device, restore the queue_if_no_paths + value +- Add 0060-UP-uevent-loop-udev.patch + * make ueventloop grab it's own udev reference, since it is cancelled + asychnrously. + * Fri Jul 5 2013 Benjamin Marzinski 0.4.9-54 - Add 0047-RHBZ-980777-kpartx-read-only-loop-devs.patch * make kpartx support read-only files better