diff --git a/0012-RH-update-on-show-topology.patch b/0012-RH-update-on-show-topology.patch new file mode 100644 index 0000000..24cc6de --- /dev/null +++ b/0012-RH-update-on-show-topology.patch @@ -0,0 +1,141 @@ +--- + libmultipath/structs_vec.c | 18 ++++++++++-------- + libmultipath/structs_vec.h | 6 ++++-- + libmultipath/waiter.c | 2 +- + multipathd/cli_handlers.c | 14 +++++++++++--- + 4 files changed, 26 insertions(+), 14 deletions(-) + +Index: multipath-tools-120123/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-120123.orig/multipathd/cli_handlers.c ++++ multipath-tools-120123/multipathd/cli_handlers.c +@@ -68,13 +68,16 @@ show_paths (char ** r, int * len, struct + } + + int +-show_map_topology (char ** r, int * len, struct multipath * mpp) ++show_map_topology (char ** r, int * len, struct multipath * mpp, ++ struct vectors * vecs) + { + char * c; + char * reply; + unsigned int maxlen = INITIAL_REPLY_LEN; + int again = 1; + ++ if (update_multipath(vecs, mpp->alias, 0)) ++ return 1; + reply = MALLOC(maxlen); + + while (again) { +@@ -112,9 +115,14 @@ show_maps_topology (char ** r, int * len + + c = reply; + +- vector_foreach_slot(vecs->mpvec, mpp, i) ++ vector_foreach_slot(vecs->mpvec, mpp, i) { ++ if (update_multipath(vecs, mpp->alias, 0)) { ++ i--; ++ continue; ++ } + c += snprint_multipath_topology(c, reply + maxlen - c, + mpp, 2); ++ } + + again = ((c - reply) == (maxlen - 1)); + +@@ -232,7 +240,7 @@ cli_list_map_topology (void * v, char ** + + condlog(3, "list multipath %s (operator)", param); + +- return show_map_topology(reply, len, mpp); ++ return show_map_topology(reply, len, mpp, vecs); + } + + int +Index: multipath-tools-120123/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/structs_vec.c ++++ multipath-tools-120123/libmultipath/structs_vec.c +@@ -324,7 +324,7 @@ set_no_path_retry(struct multipath *mpp) + } + + extern int +-setup_multipath (struct vectors * vecs, struct multipath * mpp) ++__setup_multipath (struct vectors * vecs, struct multipath * mpp, int reset) + { + if (dm_get_info(mpp->alias, &mpp->dmi)) { + /* Error accessing table */ +@@ -353,11 +353,13 @@ setup_multipath (struct vectors * vecs, + condlog(3, "%s: no hardware entry found, using defaults", + mpp->alias); + } +- select_rr_weight(mpp); +- select_pgfailback(mpp); +- set_no_path_retry(mpp); +- select_pg_timeout(mpp); +- select_flush_on_last_del(mpp); ++ if (reset) { ++ select_rr_weight(mpp); ++ select_pgfailback(mpp); ++ set_no_path_retry(mpp); ++ select_pg_timeout(mpp); ++ select_flush_on_last_del(mpp); ++ } + + return 0; + out: +@@ -479,7 +481,7 @@ verify_paths(struct multipath * mpp, str + return count; + } + +-int update_multipath (struct vectors *vecs, char *mapname) ++int update_multipath (struct vectors *vecs, char *mapname, int reset) + { + struct multipath *mpp; + struct pathgroup *pgp; +@@ -496,7 +498,7 @@ int update_multipath (struct vectors *ve + free_pgvec(mpp->pg, KEEP_PATHS); + mpp->pg = NULL; + +- if (setup_multipath(vecs, mpp)) ++ if (__setup_multipath(vecs, mpp, reset)) + return 1; /* mpp freed in setup_multipath */ + + adopt_paths(vecs->pathvec, mpp, 0); +Index: multipath-tools-120123/libmultipath/structs_vec.h +=================================================================== +--- multipath-tools-120123.orig/libmultipath/structs_vec.h ++++ multipath-tools-120123/libmultipath/structs_vec.h +@@ -21,7 +21,9 @@ void orphan_path (struct path * pp); + + int verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec); + int update_mpp_paths(struct multipath * mpp, vector pathvec); +-int setup_multipath (struct vectors * vecs, struct multipath * mpp); ++int __setup_multipath (struct vectors * vecs, struct multipath * mpp, ++ int reset); ++#define setup_multipath(vecs, mpp) __setup_multipath(vecs, mpp, 1) + int update_multipath_strings (struct multipath *mpp, vector pathvec); + + void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec); +@@ -32,7 +34,7 @@ void remove_maps_and_stop_waiters (struc + struct multipath * add_map_without_path (struct vectors * vecs, char * alias); + struct multipath * add_map_with_path (struct vectors * vecs, + struct path * pp, int add_vec); +-int update_multipath (struct vectors *vecs, char *mapname); ++int update_multipath (struct vectors *vecs, char *mapname, int reset); + void update_queue_mode_del_path(struct multipath *mpp); + void update_queue_mode_add_path(struct multipath *mpp); + +Index: multipath-tools-120123/libmultipath/waiter.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/waiter.c ++++ multipath-tools-120123/libmultipath/waiter.c +@@ -157,7 +157,7 @@ int waiteventloop (struct event_thread * + */ + pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock); + lock(waiter->vecs->lock); +- r = update_multipath(waiter->vecs, waiter->mapname); ++ r = update_multipath(waiter->vecs, waiter->mapname, 1); + lock_cleanup_pop(waiter->vecs->lock); + + if (r) { diff --git a/0013-RH-manpage-update.patch b/0013-RH-manpage-update.patch new file mode 100644 index 0000000..dbcc408 --- /dev/null +++ b/0013-RH-manpage-update.patch @@ -0,0 +1,169 @@ +--- + multipath/multipath.conf.5 | 79 ++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 64 insertions(+), 15 deletions(-) + +Index: multipath-tools-120123/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-120123.orig/multipath/multipath.conf.5 ++++ multipath-tools-120123/multipath/multipath.conf.5 +@@ -82,6 +82,11 @@ maximal interval between two path checks + directory where udev creates its device nodes; default is + .I /dev + .TP ++.B multipath_dir ++directory where the dynamic shared objects are stored; default is system ++dependent, commonly ++.I /lib/multipath ++.TP + .B verbosity + default verbosity. Higher values increase the verbosity level. Valid + levels are between 0 and 6; default is +@@ -141,7 +146,7 @@ Default value is \fImultibus\fR. + The default program and args to callout to obtain a unique path + identifier. Should be specified with an absolute path. Default value + is +-.I /lib/udev/scsi_id --whitelisted --device=/dev/%n ++.I /lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/%n + .TP + .B prio + The name of the path priority routine. The specified routine +@@ -177,17 +182,22 @@ Generate the path priority for Hitachi H + .B random + Generate a random priority between 1 and 10. + .TP 12 +-.B weightedpath ... +-.I hbtl +-regex can be of SCSI H:B:T:L format Ex: 1:0:.:. , *:0:0:. +-.I devname +-regex can be of device name format Ex: sda , sd.e ++.B weightedpath + Generate the path priority based on the regular expression and the +-priority provided as argument. ++priority provided as argument. requires prio_args keyword. + .TP + Default value is \fBnone\fR. + .RE + .TP ++.B prio_args ++Arguments to pass to to the prio function. Currently only used with ++.I weighted, which needs a value of the form ++.I " ..." ++.I hbtl ++regex can be of SCSI H:B:T:L format Ex: 1:0:.:. , *:0:0:. ++.I devname ++regex can be of device name format Ex: sda , sd.e ++.TP + .B features + Specify any device-mapper features to be used. Syntax is + .I num list +@@ -238,19 +248,33 @@ Default value is \fIdirectio\fR. + .RE + .TP + .B failback +-Tell the daemon to manage path group failback, or not to. 0 or +-.I immediate +-means immediate failback, values >0 means deferred failback (in +-seconds). +-.I manual +-means no failback. Default value is +-.I manual ++Tell multipathd how to manage path group failback. ++.RS ++.TP 12 ++.B immediate ++Immediately failback to the highest priority pathgroup that contains ++active paths. ++.TP ++.B manual ++Do not perform automatic failback. ++.TP ++.B values > 0 ++deferred failback (time to defer in seconds) ++.TP ++Default value is \fImanual\fR. ++.RE + .TP + .B rr_min_io + The number of IO to route to a path before switching to the next in +-the same path group. Default is ++the same path group. This is only for BIO based multipath. Default is + .I 1000 + .TP ++.B rr_min_io_q ++The number of IO requests to route to a path before switching to the ++next in the same path group. This is only for request based multipath. ++Default is ++.I 1 ++.TP + .B rr_weight + If set to \fIpriorities\fR the multipath configurator will assign + path weights as "path prio * rr_min_io". Possible values are +@@ -280,6 +304,13 @@ be overriden by any specific aliases in + Default is + .I no + .TP ++.B flush_on_last_del ++If set to ++.I yes ++, multipathd will disable queueing when the last path to a device has been ++deleted. Default is ++.I no ++.TP + .B max_fds + Specify the maximum number of file descriptors that can be opened by multipath + and multipathd. This is equivalent to ulimit -n. A value of \fImax\fR will set +@@ -413,12 +444,20 @@ section: + .TP + .B prio + .TP ++.B prio_args ++.TP + .B failback + .TP ++.B rr_weight ++.TP ++.B flush_on_last_del ++.TP + .B no_path_retry + .TP + .B rr_min_io + .TP ++.B rr_min_io_q ++.TP + .B features + .RE + .PD +@@ -446,6 +485,10 @@ subsection recognizes the following attr + .B product_blacklist + (Optional) Product strings to blacklist for this vendor + .TP ++.B alias_prefix ++(Optional) The user_friendly_names prefix to use for this ++device type, instead of the default "mpath" ++.TP + .B hardware_handler + (Optional) The hardware handler to use for this device type. + The following hardware handler are implemented: +@@ -483,6 +526,8 @@ section: + .TP + .B prio + .TP ++.B prio_args ++.TP + .B features + .TP + .B failback +@@ -493,9 +538,13 @@ section: + .TP + .B rr_min_io + .TP ++.B rr_min_io_rq ++.TP + .B fast_io_fail_tmo + .TP + .B dev_loss_tmo ++.TP ++.B flush_on_last_del + .RE + .PD + .LP diff --git a/0014-RH-RHEL5-style-partitions.patch b/0014-RH-RHEL5-style-partitions.patch new file mode 100644 index 0000000..47fa725 --- /dev/null +++ b/0014-RH-RHEL5-style-partitions.patch @@ -0,0 +1,327 @@ +--- + kpartx/bsd.c | 35 --------------- + kpartx/dos.c | 7 +-- + kpartx/kpartx.c | 123 +++++++------------------------------------------------- + kpartx/kpartx.h | 1 + kpartx/sun.c | 35 --------------- + 5 files changed, 24 insertions(+), 177 deletions(-) + +Index: multipath-tools-120123/kpartx/bsd.c +=================================================================== +--- multipath-tools-120123.orig/kpartx/bsd.c ++++ multipath-tools-120123/kpartx/bsd.c +@@ -50,10 +50,10 @@ int + read_bsd_pt(int fd, struct slice all, struct slice *sp, int ns) { + struct bsd_disklabel *l; + struct bsd_partition *p; +- unsigned int offset = all.start, end; ++ unsigned int offset = all.start; + int max_partitions; + char *bp; +- int n = 0, i, j; ++ int n = 0; + + bp = getblock(fd, offset+1); /* 1 sector suffices */ + if (bp == NULL) +@@ -79,36 +79,5 @@ read_bsd_pt(int fd, struct slice all, st + break; + } + } +- /* +- * Convention has it that the bsd disklabel will always have +- * the 'c' partition spanning the entire disk. +- * So we have to check for contained slices. +- */ +- for(i = 0; i < n; i++) { +- if (sp[i].size == 0) +- continue; +- +- end = sp[i].start + sp[i].size; +- for(j = 0; j < n; j ++) { +- if ( i == j ) +- continue; +- if (sp[j].size == 0) +- continue; +- +- if (sp[i].start < sp[j].start) { +- if (end > sp[j].start && +- end < sp[j].start + sp[j].size) { +- /* Invalid slice */ +- fprintf(stderr, +- "bsd_disklabel: slice %d overlaps with %d\n", i , j); +- sp[i].size = 0; +- } +- } else { +- if (end <= sp[j].start + sp[j].size) { +- sp[i].container = j + 1; +- } +- } +- } +- } + return n; + } +Index: multipath-tools-120123/kpartx/dos.c +=================================================================== +--- multipath-tools-120123.orig/kpartx/dos.c ++++ multipath-tools-120123/kpartx/dos.c +@@ -16,7 +16,7 @@ is_extended(int type) { + } + + static int +-read_extended_partition(int fd, struct partition *ep, int en, ++read_extended_partition(int fd, struct partition *ep, + struct slice *sp, int ns) + { + struct partition p; +@@ -53,7 +53,6 @@ read_extended_partition(int fd, struct p + if (n < ns) { + sp[n].start = here + le32_to_cpu(p.start_sect); + sp[n].size = le32_to_cpu(p.nr_sects); +- sp[n].container = en + 1; + n++; + } else { + fprintf(stderr, +@@ -98,7 +97,9 @@ read_dos_pt(int fd, struct slice all, st + break; + } + if (is_extended(p.sys_type)) { +- n += read_extended_partition(fd, &p, i, sp+n, ns-n); ++ n += read_extended_partition(fd, &p, sp+n, ns-n); ++ /* hide the extended partition itself */ ++ sp[i].size = 2; + } + } + return n; +Index: multipath-tools-120123/kpartx/kpartx.c +=================================================================== +--- multipath-tools-120123.orig/kpartx/kpartx.c ++++ multipath-tools-120123/kpartx/kpartx.c +@@ -190,7 +190,7 @@ get_hotplug_device(void) + + int + main(int argc, char **argv){ +- int i, j, m, n, op, off, arg, c, d, ro=0; ++ int i, j, m, n, op, off, arg, ro=0; + int fd = -1; + struct slice all; + struct pt *ptp; +@@ -380,49 +380,30 @@ main(int argc, char **argv){ + else + continue; + ++ /* ++ * test for overlap, as in the case of an extended partition ++ * zero their size to avoid mapping ++ */ ++ for (j = 0; j < n; j++) { ++ for (m = j + 1; m < n; m++) { ++ if (slices[m].start > slices[j].start && ++ slices[m].start < slices[j].start + ++ slices[j].size) ++ slices[j].size = 0; ++ } ++ } ++ + switch(what) { + case LIST: +- for (j = 0, c = 0, m = 0; j < n; j++) { ++ for (j = 0; j < n; j++) { + if (slices[j].size == 0) + continue; +- if (slices[j].container > 0) { +- c++; +- continue; +- } +- +- slices[j].minor = m++; + + printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n", + mapname, delim, j+1, + slices[j].size, device, + slices[j].start); + } +- /* Loop to resolve contained slices */ +- d = c; +- while (c) { +- for (j = 0; j < n; j++) { +- uint64_t start; +- int k = slices[j].container - 1; +- +- if (slices[j].size == 0) +- continue; +- if (slices[j].minor > 0) +- continue; +- if (slices[j].container == 0) +- continue; +- slices[j].minor = m++; +- +- start = slices[j].start - slices[k].start; +- printf("%s%s%d : 0 %" PRIu64 " /dev/dm-%d %" PRIu64 "\n", +- mapname, delim, j+1, +- slices[j].size, +- slices[k].minor, start); +- c--; +- } +- /* Terminate loop if nothing more to resolve */ +- if (d == c) +- break; +- } + + break; + +@@ -461,16 +442,10 @@ main(int argc, char **argv){ + case ADD: + case UPDATE: + /* ADD and UPDATE share the same code that adds new partitions. */ +- for (j = 0, c = 0; j < n; j++) { ++ for (j = 0; j < n; j++) { + if (slices[j].size == 0) + continue; + +- /* Skip all contained slices */ +- if (slices[j].container > 0) { +- c++; +- continue; +- } +- + if (safe_sprintf(partname, "%s%s%d", + mapname, delim, j+1)) { + fprintf(stderr, "partname too small\n"); +@@ -511,72 +486,6 @@ main(int argc, char **argv){ + slices[j].minor, slices[j].size, + DM_TARGET, params); + } +- /* Loop to resolve contained slices */ +- d = c; +- while (c) { +- for (j = 0; j < n; j++) { +- uint64_t start; +- int k = slices[j].container - 1; +- +- if (slices[j].size == 0) +- continue; +- +- /* Skip all existing slices */ +- if (slices[j].minor > 0) +- continue; +- +- /* Skip all simple slices */ +- if (slices[j].container == 0) +- continue; +- +- /* Check container slice */ +- if (slices[k].size == 0) +- fprintf(stderr, "Invalid slice %d\n", +- k); +- +- if (safe_sprintf(partname, "%s%s%d", +- mapname, delim, j+1)) { +- fprintf(stderr, "partname too small\n"); +- exit(1); +- } +- strip_slash(partname); +- +- start = slices[j].start - slices[k].start; +- if (safe_sprintf(params, "%d:%d %" PRIu64, +- slices[k].major, +- slices[k].minor, +- start)) { +- fprintf(stderr, "params too small\n"); +- exit(1); +- } +- +- op = (dm_map_present(partname) ? +- DM_DEVICE_RELOAD : DM_DEVICE_CREATE); +- +- dm_addmap(op, partname, DM_TARGET, params, +- slices[j].size, ro, uuid, j+1, +- buf.st_mode & 0777, +- buf.st_uid, buf.st_gid, +- &cookie); +- +- if (op == DM_DEVICE_RELOAD) +- dm_simplecmd(DM_DEVICE_RESUME, +- partname, 1, +- &cookie); +- +- dm_devn(partname, &slices[j].major, +- &slices[j].minor); +- +- if (verbose) +- printf("add map %s : 0 %" PRIu64 " %s %s\n", +- partname, slices[j].size, +- DM_TARGET, params); +- c--; +- } +- /* Terminate loop */ +- if (d == c) +- break; +- } + + if (what == ADD) { + /* Skip code that removes devmappings for deleted partitions */ +Index: multipath-tools-120123/kpartx/kpartx.h +=================================================================== +--- multipath-tools-120123.orig/kpartx/kpartx.h ++++ multipath-tools-120123/kpartx/kpartx.h +@@ -24,7 +24,6 @@ + struct slice { + uint64_t start; + uint64_t size; +- int container; + int major; + int minor; + }; +Index: multipath-tools-120123/kpartx/sun.c +=================================================================== +--- multipath-tools-120123.orig/kpartx/sun.c ++++ multipath-tools-120123/kpartx/sun.c +@@ -62,8 +62,8 @@ int + read_sun_pt(int fd, struct slice all, struct slice *sp, int ns) { + struct sun_disk_label *l; + struct sun_raw_part *s; +- unsigned int offset = all.start, end; +- int i, j, n; ++ unsigned int offset = all.start; ++ int i, n; + char *bp; + + bp = getblock(fd, offset); +@@ -95,37 +95,6 @@ read_sun_pt(int fd, struct slice all, st + break; + } + } +- /* +- * Convention has it that the SUN disklabel will always have +- * the 'c' partition spanning the entire disk. +- * So we have to check for contained slices. +- */ +- for(i = 0; i < SUN_DISK_MAXPARTITIONS; i++) { +- if (sp[i].size == 0) +- continue; +- +- end = sp[i].start + sp[i].size; +- for(j = 0; j < SUN_DISK_MAXPARTITIONS; j ++) { +- if ( i == j ) +- continue; +- if (sp[j].size == 0) +- continue; +- +- if (sp[i].start < sp[j].start) { +- if (end > sp[j].start && +- end < sp[j].start + sp[j].size) { +- /* Invalid slice */ +- fprintf(stderr, +- "sun_disklabel: slice %d overlaps with %d\n", i , j); +- sp[i].size = 0; +- } +- } else { +- if (end <= sp[j].start + sp[j].size) { +- sp[i].container = j + 1; +- } +- } +- } +- } + return n; + } + diff --git a/0015-RH-add-followover.patch b/0015-RH-add-followover.patch new file mode 100644 index 0000000..9f28342 --- /dev/null +++ b/0015-RH-add-followover.patch @@ -0,0 +1,156 @@ +--- + libmultipath/dict.c | 12 ++++++++++++ + libmultipath/print.c | 2 ++ + libmultipath/structs.h | 3 ++- + multipath/multipath.conf.5 | 5 +++++ + multipathd/main.c | 29 ++++++++++++++++++++++++++++- + 5 files changed, 49 insertions(+), 2 deletions(-) + +Index: multipath-tools-120123/libmultipath/dict.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/dict.c ++++ multipath-tools-120123/libmultipath/dict.c +@@ -406,6 +406,8 @@ default_failback_handler(vector strvec) + conf->pgfailback = -FAILBACK_MANUAL; + else if (strlen(buff) == 9 && !strcmp(buff, "immediate")) + conf->pgfailback = -FAILBACK_IMMEDIATE; ++ else if (strlen(buff) == 10 && !strcmp(buff, "followover")) ++ conf->pgfailback = -FAILBACK_FOLLOWOVER; + else + conf->pgfailback = atoi(buff); + +@@ -1031,6 +1033,8 @@ hw_failback_handler(vector strvec) + hwe->pgfailback = -FAILBACK_MANUAL; + else if (strlen(buff) == 9 && !strcmp(buff, "immediate")) + hwe->pgfailback = -FAILBACK_IMMEDIATE; ++ else if (strlen(buff) == 10 && !strcmp(buff, "followover")) ++ hwe->pgfailback = -FAILBACK_FOLLOWOVER; + else + hwe->pgfailback = atoi(buff); + +@@ -1303,6 +1307,8 @@ mp_failback_handler(vector strvec) + mpe->pgfailback = -FAILBACK_MANUAL; + else if (strlen(buff) == 9 && !strcmp(buff, "immediate")) + mpe->pgfailback = -FAILBACK_IMMEDIATE; ++ else if (strlen(buff) == 10 && !strcmp(buff, "followover")) ++ mpe->pgfailback = -FAILBACK_FOLLOWOVER; + else + mpe->pgfailback = atoi(buff); + +@@ -1646,6 +1652,8 @@ snprint_mp_failback (char * buff, int le + return snprintf(buff, len, "manual"); + case -FAILBACK_IMMEDIATE: + return snprintf(buff, len, "immediate"); ++ case -FAILBACK_FOLLOWOVER: ++ return snprintf(buff, len, "followover"); + default: + return snprintf(buff, len, "%i", mpe->pgfailback); + } +@@ -1985,6 +1993,8 @@ snprint_hw_failback (char * buff, int le + return snprintf(buff, len, "manual"); + case -FAILBACK_IMMEDIATE: + return snprintf(buff, len, "immediate"); ++ case -FAILBACK_FOLLOWOVER: ++ return snprintf(buff, len, "followover"); + default: + return snprintf(buff, len, "%i", hwe->pgfailback); + } +@@ -2243,6 +2253,8 @@ snprint_def_failback (char * buff, int l + return snprintf(buff, len, "manual"); + case -FAILBACK_IMMEDIATE: + return snprintf(buff, len, "immediate"); ++ case -FAILBACK_FOLLOWOVER: ++ return snprintf(buff, len, "followover"); + default: + return snprintf(buff, len, "%i", conf->pgfailback); + } +Index: multipath-tools-120123/libmultipath/print.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/print.c ++++ multipath-tools-120123/libmultipath/print.c +@@ -143,6 +143,8 @@ snprint_failback (char * buff, size_t le + { + if (mpp->pgfailback == -FAILBACK_IMMEDIATE) + return snprintf(buff, len, "immediate"); ++ if (mpp->pgfailback == -FAILBACK_FOLLOWOVER) ++ return snprintf(buff, len, "followover"); + + if (!mpp->failback_tick) + return snprintf(buff, len, "-"); +Index: multipath-tools-120123/libmultipath/structs.h +=================================================================== +--- multipath-tools-120123.orig/libmultipath/structs.h ++++ multipath-tools-120123/libmultipath/structs.h +@@ -39,7 +39,8 @@ enum rr_weight_mode { + enum failback_mode { + FAILBACK_UNDEF, + FAILBACK_MANUAL, +- FAILBACK_IMMEDIATE ++ FAILBACK_IMMEDIATE, ++ FAILBACK_FOLLOWOVER + }; + + enum sysfs_buses { +Index: multipath-tools-120123/multipathd/main.c +=================================================================== +--- multipath-tools-120123.orig/multipathd/main.c ++++ multipath-tools-120123/multipathd/main.c +@@ -1011,6 +1011,32 @@ mpvec_garbage_collector (struct vectors + } + } + ++/* This is called after a path has started working again. It the multipath ++ * device for this path uses the followover failback type, and this is the ++ * best pathgroup, and this is the first path in the pathgroup to come back ++ * up, then switch to this pathgroup */ ++static int ++followover_should_failback(struct path * pp) ++{ ++ struct pathgroup * pgp; ++ struct path *pp1; ++ int i; ++ ++ if (pp->mpp->pgfailback != -FAILBACK_FOLLOWOVER || ++ !pp->mpp->pg || !pp->pgindex || ++ pp->pgindex != pp->mpp->bestpg) ++ return 0; ++ ++ pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1); ++ vector_foreach_slot(pgp->paths, pp1, i) { ++ if (pp1 == pp) ++ continue; ++ if (pp1->state != PATH_DOWN && pp1->state != PATH_SHAKY) ++ return 0; ++ } ++ return 1; ++} ++ + static void + defered_failback_tick (vector mpvec) + { +@@ -1238,7 +1264,8 @@ check_path (struct vectors * vecs, struc + (new_path_up || pp->mpp->failback_tick <= 0)) + pp->mpp->failback_tick = + pp->mpp->pgfailback + 1; +- else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE) ++ else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE || ++ followover_should_failback(pp)) + switch_pathgroup(pp->mpp); + } + } +Index: multipath-tools-120123/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-120123.orig/multipath/multipath.conf.5 ++++ multipath-tools-120123/multipath/multipath.conf.5 +@@ -258,6 +258,11 @@ active paths. + .B manual + Do not perform automatic failback. + .TP ++.B followover ++Only perform automatic failback when the first path of a pathgroup ++becomes active. This keeps a node from automatically failing back when ++another node requested the failover. ++.TP + .B values > 0 + deferred failback (time to defer in seconds) + .TP diff --git a/0016-RH-dont-remove-map-on-enomem.patch b/0016-RH-dont-remove-map-on-enomem.patch new file mode 100644 index 0000000..5b54a4a --- /dev/null +++ b/0016-RH-dont-remove-map-on-enomem.patch @@ -0,0 +1,18 @@ +--- + multipathd/main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: multipath-tools-120123/multipathd/main.c +=================================================================== +--- multipath-tools-120123.orig/multipathd/main.c ++++ multipath-tools-120123/multipathd/main.c +@@ -1003,7 +1003,8 @@ mpvec_garbage_collector (struct vectors + return; + + vector_foreach_slot (vecs->mpvec, mpp, i) { +- if (mpp && mpp->alias && !dm_map_present(mpp->alias)) { ++ if (mpp && mpp->alias && !dm_map_present(mpp->alias) && ++ errno != ENOMEM) { + condlog(2, "%s: remove dead map", mpp->alias); + remove_map_and_stop_waiter(mpp, vecs, 1); + i--; diff --git a/0017-RH-fix-shutdown-crash.patch b/0017-RH-fix-shutdown-crash.patch new file mode 100644 index 0000000..0e4f345 --- /dev/null +++ b/0017-RH-fix-shutdown-crash.patch @@ -0,0 +1,69 @@ +--- + libmultipath/log_pthread.c | 1 + + libmultipath/waiter.c | 1 + + multipathd/main.c | 6 +++++- + 3 files changed, 7 insertions(+), 1 deletion(-) + +Index: multipath-tools-120123/multipathd/main.c +=================================================================== +--- multipath-tools-120123.orig/multipathd/main.c ++++ multipath-tools-120123/multipathd/main.c +@@ -735,6 +735,7 @@ uxsock_trigger (char * str, char ** repl + + pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(vecs->lock); ++ pthread_testcancel(); + + r = parse_cmd(str, reply, len, vecs); + +@@ -787,7 +788,9 @@ uev_trigger (struct uevent * uev, void * + if (uev_discard(uev->devpath)) + return 0; + ++ pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(vecs->lock); ++ pthread_testcancel(); + + /* + * device map event +@@ -827,7 +830,7 @@ uev_trigger (struct uevent * uev, void * + } + + out: +- unlock(vecs->lock); ++ lock_cleanup_pop(vecs->lock); + return r; + } + +@@ -1295,6 +1298,7 @@ checkerloop (void *ap) + block_signal(SIGHUP, &old); + pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(vecs->lock); ++ pthread_testcancel(); + condlog(4, "tick"); + + if (vecs->pathvec) { +Index: multipath-tools-120123/libmultipath/waiter.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/waiter.c ++++ multipath-tools-120123/libmultipath/waiter.c +@@ -157,6 +157,7 @@ int waiteventloop (struct event_thread * + */ + pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock); + lock(waiter->vecs->lock); ++ pthread_testcancel(); + r = update_multipath(waiter->vecs, waiter->mapname, 1); + lock_cleanup_pop(waiter->vecs->lock); + +Index: multipath-tools-120123/libmultipath/log_pthread.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/log_pthread.c ++++ multipath-tools-120123/libmultipath/log_pthread.c +@@ -87,6 +87,7 @@ void log_thread_stop (void) + pthread_mutex_lock(logq_lock); + pthread_cancel(log_thr); + pthread_mutex_unlock(logq_lock); ++ pthread_join(log_thr, NULL); + + flush_logqueue(); + diff --git a/0018-RH-warn-on-bad-dev-loss-tmo.patch b/0018-RH-warn-on-bad-dev-loss-tmo.patch new file mode 100644 index 0000000..508a02a --- /dev/null +++ b/0018-RH-warn-on-bad-dev-loss-tmo.patch @@ -0,0 +1,68 @@ +--- + libmultipath/discovery.c | 22 +++++++++++++++------- + libmultipath/structs_vec.c | 5 ----- + 2 files changed, 15 insertions(+), 12 deletions(-) + +Index: multipath-tools-120123/libmultipath/discovery.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/discovery.c ++++ multipath-tools-120123/libmultipath/discovery.c +@@ -299,17 +299,17 @@ sysfs_set_scsi_tmo (struct multipath *mp + no_path_retry_tmo = MAX_DEV_LOSS_TMO; + if (no_path_retry_tmo > dev_loss_tmo) + dev_loss_tmo = no_path_retry_tmo; +- condlog(3, "%s: update dev_loss_tmo to %d\n", ++ condlog(3, "%s: update dev_loss_tmo to %d", + mpp->alias, dev_loss_tmo); + } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE) { + dev_loss_tmo = MAX_DEV_LOSS_TMO; +- condlog(4, "%s: update dev_loss_tmo to %d\n", ++ condlog(3, "%s: update dev_loss_tmo to %d", + mpp->alias, dev_loss_tmo); + } + mpp->dev_loss = dev_loss_tmo; +- if (mpp->fast_io_fail > mpp->dev_loss) { ++ if (mpp->fast_io_fail > (int)mpp->dev_loss) { + mpp->fast_io_fail = mpp->dev_loss; +- condlog(3, "%s: update fast_io_fail to %d\n", ++ condlog(3, "%s: update fast_io_fail to %d", + mpp->alias, mpp->fast_io_fail); + } + if (!mpp->dev_loss && !mpp->fast_io_fail) +@@ -333,9 +333,17 @@ sysfs_set_scsi_tmo (struct multipath *mp + snprintf(value, 11, "%u", mpp->dev_loss); + if (sysfs_attr_set_value(attr_path, "dev_loss_tmo", + value, 11) < 0) { +- condlog(0, "%s failed to set %s/dev_loss_tmo", +- mpp->alias, attr_path); +- return 1; ++ int err = 1; ++ if (mpp->fast_io_fail <= 0 && mpp->dev_loss > 600) { ++ strncpy(value, "600", 4); ++ condlog(3, "%s: limiting dev_loss_tmo to 600, since fast_io_fail is not set", mpp->alias); ++ if (sysfs_attr_set_value(attr_path, "dev_loss_tmo", value, 11) >= 0) ++ err = 0; ++ } ++ if (err) { ++ condlog(0, "%s failed to set %s/dev_loss_tmo", mpp->alias, attr_path); ++ return 1; ++ } + } + } + if (mpp->fast_io_fail){ +Index: multipath-tools-120123/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/structs_vec.c ++++ multipath-tools-120123/libmultipath/structs_vec.c +@@ -441,11 +441,6 @@ verify_paths(struct multipath * mpp, str + if (!mpp) + return 0; + +- select_features(mpp); +- select_no_path_retry(mpp); +- select_dev_loss(mpp); +- sysfs_set_scsi_tmo(mpp); +- + vector_foreach_slot (mpp->paths, pp, i) { + /* + * see if path is in sysfs diff --git a/0019-RH-deprecate-uid-gid-mode.patch b/0019-RH-deprecate-uid-gid-mode.patch new file mode 100644 index 0000000..9270d9d --- /dev/null +++ b/0019-RH-deprecate-uid-gid-mode.patch @@ -0,0 +1,90 @@ +--- + multipath.conf.annotated | 53 ----------------------------------------------- + multipath.conf.synthetic | 3 -- + 2 files changed, 56 deletions(-) + +Index: multipath-tools-120123/multipath.conf.annotated +=================================================================== +--- multipath-tools-120123.orig/multipath.conf.annotated ++++ multipath-tools-120123/multipath.conf.annotated +@@ -186,32 +186,6 @@ + # user_friendly_names no + # + # # +-# # name : mode +-# # scope : multipath & multipathd +-# # desc : The mode to use for the multipath device nodes, in octal. +-# # values : 0000 - 0777 +-# # default : determined by the process +-# mode 0644 +-# +-# # +-# # name : uid +-# # scope : multipath & multipathd +-# # desc : The user id to use for the multipath device nodes. You +-# # may use either the numeric or symbolic uid +-# # values : +-# # default : determined by the process +-# uid 0 +-# +-# # +-# # name : gid +-# # scope : multipath & multipathd +-# # desc : The group id to user for the multipath device nodes. You +-# # may use either the numeric or symbolic gid +-# # values : +-# # default : determined by the process +-# gid disk +-# +-# # + # # name : checker_timeout + # # scope : multipath & multipathd + # # desc : The timeout to use for path checkers that issue scsi +@@ -388,33 +362,6 @@ + # # + # flush_on_last_del yes + # +-# # +-# # name : mode +-# # scope : multipath & multipathd +-# # desc : The mode to use for the multipath device nodes, in +-# # octal. +-# # values : 0000 - 0777 +-# # default : determined by the process +-# mode 0644 +-# +-# # +-# # name : uid +-# # scope : multipath & multipathd +-# # desc : The user id to use for the multipath device nodes. +-# # You may use either the numeric or symbolic uid +-# # values : +-# # default : determined by the process +-# uid 0 +-# +-# # +-# # name : gid +-# # scope : multipath & multipathd +-# # desc : The group id to user for the multipath device nodes. +-# # You may use either the numeric or symbolic gid +-# # values : +-# # default : determined by the process +-# gid 0 +-# + # } + # multipath { + # wwid 1DEC_____321816758474 +Index: multipath-tools-120123/multipath.conf.synthetic +=================================================================== +--- multipath-tools-120123.orig/multipath.conf.synthetic ++++ multipath-tools-120123/multipath.conf.synthetic +@@ -18,9 +18,6 @@ + # no_path_retry fail + # queue_without_daemon no + # user_friendly_names no +-# mode 644 +-# uid 0 +-# gid disk + #} + #blacklist { + # wwid 26353900f02796769 diff --git a/0020-RH-dont-remove-map-twice.patch b/0020-RH-dont-remove-map-twice.patch new file mode 100644 index 0000000..559ec1e --- /dev/null +++ b/0020-RH-dont-remove-map-twice.patch @@ -0,0 +1,17 @@ +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-120123/multipathd/main.c +=================================================================== +--- multipath-tools-120123.orig/multipathd/main.c ++++ multipath-tools-120123/multipathd/main.c +@@ -524,7 +524,7 @@ rescan: + * update our state from kernel regardless of create or reload + */ + if (setup_multipath(vecs, mpp)) +- goto fail_map; ++ goto fail; /* if setup_multipath fails, it removes the map */ + + sync_map_state(mpp); + diff --git a/0021-RH-validate-guid-partitions.patch b/0021-RH-validate-guid-partitions.patch new file mode 100644 index 0000000..19040d3 --- /dev/null +++ b/0021-RH-validate-guid-partitions.patch @@ -0,0 +1,24 @@ +--- + kpartx/gpt.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +Index: multipath-tools-120123/kpartx/gpt.c +=================================================================== +--- multipath-tools-120123.orig/kpartx/gpt.c ++++ multipath-tools-120123/kpartx/gpt.c +@@ -367,6 +367,15 @@ is_gpt_valid(int fd, uint64_t lba, + } + + ++ /* Check that sizeof_partition_entry has the correct value */ ++ if (__le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { ++ // printf("GUID partition entry size check failed.\n"); ++ free(*gpt); ++ *gpt = NULL; ++ return 0; ++ } ++ ++ + if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) { + free(*gpt); + *gpt = NULL; diff --git a/0022-RH-adjust-messages.patch b/0022-RH-adjust-messages.patch new file mode 100644 index 0000000..d7b021a --- /dev/null +++ b/0022-RH-adjust-messages.patch @@ -0,0 +1,32 @@ +--- + libmultipath/configure.c | 3 +++ + libmultipath/discovery.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +Index: multipath-tools-120123/libmultipath/configure.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/configure.c ++++ multipath-tools-120123/libmultipath/configure.c +@@ -590,6 +590,9 @@ coalesce_paths (struct vectors * vecs, v + "for create/reload map", + mpp->alias, r); + if (r == DOMAP_FAIL) { ++ condlog(2, "%s: %s map", ++ mpp->alias, (mpp->action == ACT_CREATE)? ++ "ignoring" : "removing"); + remove_map(mpp, vecs, 0); + continue; + } else /* if (r == DOMAP_RETRY) */ +Index: multipath-tools-120123/libmultipath/discovery.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/discovery.c ++++ multipath-tools-120123/libmultipath/discovery.c +@@ -318,7 +318,7 @@ sysfs_set_scsi_tmo (struct multipath *mp + vector_foreach_slot(mpp->paths, pp, i) { + rport_id = find_rport_id(pp); + if (rport_id < 0) { +- condlog(0, "failed to find rport_id for target%d:%d:%d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id); ++ condlog(3, "failed to find rport_id for target%d:%d:%d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id); + return 1; + } + diff --git a/0023-RH-manpage-update.patch b/0023-RH-manpage-update.patch new file mode 100644 index 0000000..475ad41 --- /dev/null +++ b/0023-RH-manpage-update.patch @@ -0,0 +1,19 @@ +--- + multipath/multipath.conf.5 | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +Index: multipath-tools-120123/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-120123.orig/multipath/multipath.conf.5 ++++ multipath-tools-120123/multipath/multipath.conf.5 +@@ -338,7 +338,9 @@ 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. ++been detected on a FC remote port before removing it from the system. This ++can be set to "infinity" which sets it to the max value of 2147483647 ++seconds, or 68 years. + .TP + .B queue_without_daemon + If set to diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index cffd86a..59570ef 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: 21%{?dist} +Release: 22%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -19,6 +19,18 @@ Patch0008: 0008-RH-add-mpathconf.patch Patch0009: 0009-RH-add-find-multipaths.patch Patch0010: 0010-RH-check-if-multipath-owns-path.patch Patch0011: 0011-RH-add-hp_tur-checker.patch +Patch0012: 0012-RH-update-on-show-topology.patch +Patch0013: 0013-RH-manpage-update.patch +Patch0014: 0014-RH-RHEL5-style-partitions.patch +Patch0015: 0015-RH-add-followover.patch +Patch0016: 0016-RH-dont-remove-map-on-enomem.patch +Patch0017: 0017-RH-fix-shutdown-crash.patch +Patch0018: 0018-RH-warn-on-bad-dev-loss-tmo.patch +Patch0019: 0019-RH-deprecate-uid-gid-mode.patch +Patch0020: 0020-RH-dont-remove-map-twice.patch +Patch0021: 0021-RH-validate-guid-partitions.patch +Patch0022: 0022-RH-adjust-messages.patch +Patch0023: 0023-RH-manpage-update.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -82,6 +94,18 @@ kpartx manages partition creation and removal for device-mapper devices. %patch0009 -p1 %patch0010 -p1 %patch0011 -p1 +%patch0012 -p1 +%patch0013 -p1 +%patch0014 -p1 +%patch0015 -p1 +%patch0016 -p1 +%patch0017 -p1 +%patch0018 -p1 +%patch0019 -p1 +%patch0020 -p1 +%patch0021 -p1 +%patch0022 -p1 +%patch0023 -p1 cp %{SOURCE1} . %build @@ -172,6 +196,20 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/kpartx.8.gz %changelog +* Fri Feb 10 2012 Benjamin Marzinski 0.4.9-22 +- Add 0012-RH-update-on-show-topology.patch +- Add 0013-RH-manpage-update.patch +- Add 0014-RH-RHEL5-style-partitions.patch +- Add 0015-RH-add-followover.patch +- Add 0016-RH-dont-remove-map-on-enomem.patch +- Add 0017-RH-fix-shutdown-crash.patch +- Add 0018-RH-warn-on-bad-dev-loss-tmo.patch +- Add 0019-RH-deprecate-uid-gid-mode.patch +- Add 0020-RH-dont-remove-map-twice.patch +- Add 0021-RH-validate-guid-partitions.patch +- Add 0022-RH-adjust-messages.patch +- Add 0023-RH-manpage-update.patch + * Tue Jan 24 2012 Benjamin Marzinski 0.4.9-21 - Updated to latest upstream 0.4.9 code : multipath-tools-120123.tgz (git commit id: 63704387009443bdb37d9deaaafa9ab121d45bfb)