r396 - in multipath-tools/trunk/debian: . patches
Guido Guenther
agx at alioth.debian.org
Wed Dec 20 10:52:02 CET 2006
Author: agx
Date: Wed Dec 20 10:52:01 2006
New Revision: 396
Added:
multipath-tools/trunk/debian/patches/
multipath-tools/trunk/debian/patches/exclude-quilt
multipath-tools/trunk/debian/patches/git-40b575955cc189aa993e6a030b66b5fef6bcf288.patch
multipath-tools/trunk/debian/patches/series
Modified:
multipath-tools/trunk/debian/changelog
multipath-tools/trunk/debian/control
multipath-tools/trunk/debian/multipath-tools.init
multipath-tools/trunk/debian/rules
Log:
* Acknowledge NMU - thanks John! (closes: #382244)
* use quilt for the git patch
* remove Bastian and Andres from Uploaders on their request
* cleanup pp_hds_modular so the package is rebuildable several times
Modified: multipath-tools/trunk/debian/changelog
==============================================================================
--- multipath-tools/trunk/debian/changelog (original)
+++ multipath-tools/trunk/debian/changelog Wed Dec 20 10:52:01 2006
@@ -1,8 +1,27 @@
multipath-tools (0.4.7-2) UNRELEASED; urgency=low
+ [ Bastian Blank ]
* Use /lib/udev/scsi_id. (closes: #358985)
- -- Bastian Blank <waldi at debian.org> Wed, 29 Mar 2006 12:09:43 +0200
+ [ Guido Guenther ]
+ * Acknowledge NMU - thanks John! (closes: #382244)
+ * use quilt for the git patch
+ * remove Bastian and Andres from Uploaders on their request
+ * cleanup pp_hds_modular so the package is rebuildable several times
+
+ -- Guido Guenther <agx at sigxcpu.org> Mon, 18 Dec 2006 16:08:47 +0100
+
+multipath-tools (0.4.7-1.1) unstable; urgency=medium
+
+ * Added missing dependency on dmsetup. Closes: #381068.
+ * Fixed PID file handling. Closes: #294066.
+ * Pulled in numerous fixes from upstream git tree to fix
+ various segfaults, spewing garbage onto the console, etc.
+ Tree is now synced to upstream git as of commit
+ 40b575955cc189aa993e6a030b66b5fef6bcf288 on July 19, 2006,
+ which is the current state of the upstream tree. Closes: #382214.
+
+ -- John Goerzen <jgoerzen at complete.org> Wed, 9 Aug 2006 11:52:08 -0500
multipath-tools (0.4.7-1) unstable; urgency=low
Modified: multipath-tools/trunk/debian/control
==============================================================================
--- multipath-tools/trunk/debian/control (original)
+++ multipath-tools/trunk/debian/control Wed Dec 20 10:52:01 2006
@@ -3,12 +3,12 @@
Priority: extra
Maintainer: Debian LVM Team <pkg-lvm-maintainers at lists.alioth.debian.org>
Uploaders: Bastian Blank <waldi at debian.org>, Andres Salomon <dilinger at debian.org>
-Build-Depends: debhelper (>> 4.0.0), po-debconf, libdevmapper-dev (>= 2:1.01.0), libsysfs-dev, libreadline5-dev
+Build-Depends: debhelper (>> 4.0.0), po-debconf, libdevmapper-dev (>= 2:1.01.0), libsysfs-dev, libreadline5-dev, quilt
Standards-Version: 3.6.1
Package: multipath-tools
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, udev (>> 0.086), initscripts (>= 2.85-16)
+Depends: ${shlibs:Depends}, ${misc:Depends}, udev (>> 0.086), initscripts (>= 2.85-16), dmsetup
Description: Command-line utilities for administering multipath disk access
These tools are in charge of maintaining the disk multipath device maps and
react to path and map events.
Modified: multipath-tools/trunk/debian/multipath-tools.init
==============================================================================
--- multipath-tools/trunk/debian/multipath-tools.init (original)
+++ multipath-tools/trunk/debian/multipath-tools.init Wed Dec 20 10:52:01 2006
@@ -2,7 +2,7 @@
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/sbin/multipathd
-NAME=multipath-tools
+NAME=multipathd
DESC="multipath daemon"
test -x $DAEMON || exit 0
@@ -36,7 +36,7 @@
echo "."
;;
*)
- N=/etc/init.d/$NAME
+ N=/etc/init.d/multipath-tools
echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
exit 1
;;
Added: multipath-tools/trunk/debian/patches/exclude-quilt
==============================================================================
--- (empty file)
+++ multipath-tools/trunk/debian/patches/exclude-quilt Wed Dec 20 10:52:01 2006
@@ -0,0 +1,13 @@
+Index: multipath-tools/Makefile
+===================================================================
+--- multipath-tools.orig/Makefile 2006-12-17 20:22:51.000000000 +0100
++++ multipath-tools/Makefile 2006-12-17 20:23:04.000000000 +0100
+@@ -20,7 +20,7 @@
+ export KRNLSRC
+ export KRNLOBJ
+
+-BUILDDIRS = $(shell find . -mindepth 2 -name Makefile -exec dirname {} \; | grep -v ^lib)
++BUILDDIRS = $(shell find . -mindepth 2 -name Makefile -exec dirname {} \; | grep -vE '^lib|/\.pc')
+
+ ifeq ($(MULTIPATH_VERSION),)
+ VERSION = $(shell basename ${PWD} | cut -d'-' -f3)
Added: multipath-tools/trunk/debian/patches/git-40b575955cc189aa993e6a030b66b5fef6bcf288.patch
==============================================================================
--- (empty file)
+++ multipath-tools/trunk/debian/patches/git-40b575955cc189aa993e6a030b66b5fef6bcf288.patch Wed Dec 20 10:52:01 2006
@@ -0,0 +1,3114 @@
+diff -u multipath-tools-0.4.7/multipath.conf.annotated multipath-tools-0.4.7/multipath.conf.annotated
+--- multipath-tools-0.4.7/multipath.conf.annotated
++++ multipath-tools-0.4.7/multipath.conf.annotated
+@@ -237,7 +237,7 @@
+ ##
+ ## name : devices
+ ## scope : multipath & multipathd
+-## desc : list of per storage controler settings
++## desc : list of per storage controller settings
+ ## overrides default settings (device_maps block)
+ ## overriden by per multipath settings (multipaths block)
+ ##
+@@ -245,7 +245,7 @@
+ # #
+ # # name : device
+ # # scope : multipath & multipathd
+-# # desc : settings for this specific storage controler
++# # desc : settings for this specific storage controller
+ # #
+ # device {
+ # #
+@@ -260,7 +260,7 @@
+ # # name : path_grouping_policy
+ # # scope : multipath
+ # # desc : path grouping policy to apply to multipath hosted
+-# # by this storage controler
++# # by this storage controller
+ # # values : failover = 1 path per priority group
+ # # multibus = all valid paths in 1 priority
+ # # group
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/path_priority/pp_alua/mpath_prio_alua.8
++++ multipath-tools-0.4.7/path_priority/pp_alua/mpath_prio_alua.8
+@@ -1,4 +1,4 @@
+-.TH MPATH_PRIO_ALUA 8 "7. June 2005" "multipath-tools" \
++.TH MPATH_PRIO_ALUA 8 "July 2006" "multipath-tools" \
+ "Linux Administrator's Manual"
+ .SH NAME
+ mpath_prio_alua \- Path priority tool based on Asymmetric LUn Access
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/path_priority/pp_alua/rtpg.c
++++ multipath-tools-0.4.7/path_priority/pp_alua/rtpg.c
+@@ -28,7 +28,7 @@
+ #include "rtpg.h"
+
+ #define SENSE_BUFF_LEN 32
+-#define DEF_TIMEOUT 60000
++#define DEF_TIMEOUT 300000
+
+ /*
+ * Macro used to print debug messaged.
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/path_priority/pp_alua/spc3.h
++++ multipath-tools-0.4.7/path_priority/pp_alua/spc3.h
+@@ -148,10 +148,10 @@
+ /* ......x. = command queue support */
+ /* .......x = vs2 */
+ unsigned char vendor_identification[8];
+- unsigned char product_identification[8];
++ unsigned char product_identification[16];
+ unsigned char product_revision[4];
+ unsigned char vendor_specific[20];
+- unsigned char b48; /* xxxx.... = reserved */
++ unsigned char b56; /* xxxx.... = reserved */
+ /* ....xx.. = clocking */
+ /* ......x. = qas */
+ /* .......x = ius */
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/path_priority/pp_balance_units/pp_balance_units.c
++++ multipath-tools-0.4.7/path_priority/pp_balance_units/pp_balance_units.c
+@@ -3,15 +3,15 @@
+ * This code is GPLv2, see license file
+ *
+ * This path prioritizer aims to balance logical units over all
+- * controlers available. The logic is :
++ * controllers available. The logic is :
+ *
+ * - list all paths in all primary path groups
+- * - for each path, get the controler's serial
+- * - compute the number of active paths attached to each controler
+- * - compute the max number of paths attached to the same controler
++ * - for each path, get the controller's serial
++ * - compute the number of active paths attached to each controller
++ * - compute the max number of paths attached to the same controller
+ * - if sums are already balanced or if the path passed as parameter is
+- * attached to controler with less active paths, then return
+- * (max_path_attached_to_one_controler - number_of_paths_on_this_controler)
++ * attached to controller with less active paths, then return
++ * (max_path_attached_to_one_controller - number_of_paths_on_this_controller)
+ * - else, or if anything goes wrong, return 1 as a default prio
+ *
+ */
+@@ -38,7 +38,7 @@
+ #define INQUIRY_CMDLEN 6
+ #define INQUIRY_CMD 0x12
+ #define SENSE_BUFF_LEN 32
+-#define DEF_TIMEOUT 60000
++#define DEF_TIMEOUT 300000
+ #define RECOVERED_ERROR 0x01
+ #define MX_ALLOC_LEN 255
+ #define SCSI_CHECK_CONDITION 0x2
+@@ -61,7 +61,7 @@
+ char serial[SERIAL_SIZE];
+ };
+
+-struct controler {
++struct controller {
+ char serial[SERIAL_SIZE];
+ int path_count;
+ };
+@@ -172,7 +172,7 @@
+ }
+
+ static int
+-get_serial (char * str, char * devt)
++get_serial (char * str, int maxlen, char * devt)
+ {
+ int fd;
+ int len;
+@@ -181,20 +181,22 @@
+ fd = opennode(devt, O_RDONLY);
+
+ if (fd < 0)
+- return 0;
++ return 1;
+
+ if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) {
+ len = buff[3];
++ if (len >= maxlen)
++ return 1;
+ if (len > 0) {
+ memcpy(str, buff + 4, len);
+ buff[len] = '\0';
+ }
+ close(fd);
+- return 1;
++ return 0;
+ }
+
+ closenode(devt, fd);
+- return 0;
++ return 1;
+ }
+
+ static void *
+@@ -358,7 +360,7 @@
+ if (pos == BEFOREPG)
+ pos = INPG;
+
+- get_serial(pp->serial, pp->dev_t);
++ get_serial(pp->serial, SERIAL_SIZE, pp->dev_t);
+ vector_alloc_slot(pathvec);
+ vector_set_slot(pathvec, pp);
+ debug("store %s [%s]",
+@@ -370,40 +372,40 @@
+ }
+
+ static void *
+-find_controler (vector controlers, char * serial)
++find_controller (vector controllers, char * serial)
+ {
+ int i;
+- struct controler * cp;
++ struct controller * cp;
+
+- if (!controlers)
++ if (!controllers)
+ return NULL;
+
+- vector_foreach_slot (controlers, cp, i)
++ vector_foreach_slot (controllers, cp, i)
+ if (!strncmp(cp->serial, serial, SERIAL_SIZE))
+ return cp;
+ return NULL;
+ }
+
+ static void
+-get_controlers (vector controlers, vector pathvec)
++get_controllers (vector controllers, vector pathvec)
+ {
+ int i;
+ struct path * pp;
+- struct controler * cp;
++ struct controller * cp;
+
+- if (!controlers)
++ if (!controllers)
+ return;
+
+ vector_foreach_slot (pathvec, pp, i) {
+ if (!pp || !strlen(pp->serial))
+ continue;
+
+- cp = find_controler(controlers, pp->serial);
++ cp = find_controller(controllers, pp->serial);
+
+ if (!cp) {
+- cp = zalloc(sizeof(struct controler));
+- vector_alloc_slot(controlers);
+- vector_set_slot(controlers, cp);
++ cp = zalloc(sizeof(struct controller));
++ vector_alloc_slot(controllers);
++ vector_set_slot(controllers, cp);
+ strncpy(cp->serial, pp->serial, SERIAL_SIZE);
+ }
+ cp->path_count++;
+@@ -411,17 +413,17 @@
+ }
+
+ static int
+-get_max_path_count (vector controlers)
++get_max_path_count (vector controllers)
+ {
+ int i;
+ int max = 0;
+- struct controler * cp;
++ struct controller * cp;
+
+- if (!controlers)
++ if (!controllers)
+ return 0;
+
+- vector_foreach_slot (controlers, cp, i) {
+- debug("controler %s : %i paths", cp->serial, cp->path_count);
++ vector_foreach_slot (controllers, cp, i) {
++ debug("controller %s : %i paths", cp->serial, cp->path_count);
+ if(cp->path_count > max)
+ max = cp->path_count;
+ }
+@@ -433,9 +435,9 @@
+ main (int argc, char **argv)
+ {
+ vector pathvec = NULL;
+- vector controlers = NULL;
++ vector controllers = NULL;
+ struct path * ref_path = NULL;
+- struct controler * cp = NULL;
++ struct controller * cp = NULL;
+ int max_path_count = 0;
+
+ ref_path = zalloc(sizeof(struct path));
+@@ -449,18 +451,18 @@
+ if (optind<argc)
+ strncpy(ref_path->dev_t, argv[optind], WORD_SIZE);
+
+- get_serial(ref_path->serial, ref_path->dev_t);
++ get_serial(ref_path->serial, SERIAL_SIZE, ref_path->dev_t);
+
+ if (!ref_path->serial || !strlen(ref_path->serial))
+ exit_tool(0);
+
+ pathvec = vector_alloc();
+- controlers = vector_alloc();
++ controllers = vector_alloc();
+
+ get_paths(pathvec);
+- get_controlers(controlers, pathvec);
+- max_path_count = get_max_path_count(controlers);
+- cp = find_controler(controlers, ref_path->serial);
++ get_controllers(controllers, pathvec);
++ max_path_count = get_max_path_count(controllers);
++ cp = find_controller(controllers, ref_path->serial);
+
+ if (!cp) {
+ debug("no other active path on serial %s\n",
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/path_priority/pp_hds_modular/Makefile
++++ multipath-tools-0.4.7/path_priority/pp_hds_modular/Makefile
+@@ -0,0 +1,22 @@
++EXEC = mpath_prio_hds_modular
++BUILD = glibc
++OBJS = pp_hds_modular.o
++
++TOPDIR = ../..
++include $(TOPDIR)/Makefile.inc
++
++all: $(BUILD)
++
++glibc: $(OBJS)
++ $(CC) -o $(EXEC) $(OBJS) $(LDFLAGS)
++
++klibc: $(OBJS)
++ $(CC) -static -o $(EXEC) $(OBJS)
++
++install: $(EXEC)
++ install -s -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC)
++
++uninstall:
++ rm $(DESTDIR)$(bindir)/$(EXEC)
++clean:
++ rm -f *.o $(EXEC)
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/path_priority/pp_hds_modular/pp_hds_modular.c
++++ multipath-tools-0.4.7/path_priority/pp_hds_modular/pp_hds_modular.c
+@@ -0,0 +1,252 @@
++/*
++ * (C) Copyright HDS GmbH 2006. All Rights Reserved.
++ *
++ * pp_hds_modular.c
++ * Version 1.12
++ *
++ * Prioritizer for multipath tools device mapper and HDS Storage
++ *
++ * Hitachis Modular Storage contains two controllers for redundancy. The
++ * Storage internal LUN (LDEV) will normally allocated via two pathes to the
++ * server (one path per controller). For performance reasons should the server
++ * access to a LDEV only via one controller. The other path to the other
++ * controller is stand-by. It is also possible to allocate more as one path
++ * for a LDEV per controller. Here is active/active access allowed. The other
++ * pathes via the other controller are stand-by.
++ *
++ * This prioritizer checks with inquiry commands the represented LDEV and
++ * Controller number and gives back a priority followed by this scheme :
++ *
++ * CONTROLLER ODD and LDEV ODD: PRIORITY 1
++ * CONTROLLER ODD and LDEV EVEN: PRIORITY 0
++ * CONTROLLER EVEN and LDEV ODD: PRIORITY 0
++ * CONTROLLER EVEN and LDEV EVEN: PRIORITY 1
++ *
++ * In the storage you can define for each LDEV a owner controller. If the
++ * server makes IOs via the other controller the storage will switch the
++ * ownership automatically. In this case you can see in the storage that the
++ * current controller is different from the default controller, but this is
++ * absolutely no problem.
++ *
++ * With this prioritizer it is possible to establish a static load balancing.
++ * Half of the LUNs are accessed via one HBA/storage controller and the other
++ * half via the other HBA/storage controller.
++ *
++ * In cluster environmemnts (RAC) it also guarantees that all cluster nodes
++ * have access to the LDEVs via the same controller.
++ *
++ * You can run the prioritizer manually in verbose mode :
++ * # pp_hds_modular -v 8:224
++ * VENDOR: HITACHI
++ * PRODUCT: DF600F-CM
++ * SERIAL: 0x0105
++ * LDEV: 0x00C6
++ * CTRL: 1
++ * PORT: B
++ * CTRL ODD, LDEV EVEN, PRIO 0
++ *
++ * The items VENDOR and PRODUCT helps you to make the correct entries in file
++ * /etc/multipath.conf :
++ * # cat /etc/multipath.conf
++ * ...
++ * devices {
++ * device {
++ * vendor "HITACHI"
++ * product "DF600F"
++ * path_grouping_policy group_by_prio
++ * prio_callout "/sbin/pp_hds_modular %d"
++ * path_checker readsector0
++ * getuid_callout "/sbin/scsi_id -g -u -s /block/%n"
++ * failback immediate
++ * }
++ * device {
++ * vendor "HITACHI"
++ * product "DF600F-CM"
++ * path_grouping_policy group_by_prio
++ * prio_callout "/sbin/pp_hds_modular %d"
++ * path_checker readsector0
++ * getuid_callout "/sbin/scsi_id -g -u -s /block/%n"
++ * failback immediate
++ *
++ *
++ * Author: Matthias Rudolph <matthias.rudolph at hds.com>
++ *
++ * This file is released under the GPL.
++ *
++ */
++
++#include <unistd.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <string.h>
++#include <errno.h>
++#include <sys/ioctl.h>
++#include <stdlib.h>
++#include <libdevmapper.h>
++#include <memory.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <scsi/sg.h> /* take care: fetches glibc's /usr/include/scsi/sg.h */
++
++#define INQ_REPLY_LEN 255
++#define INQ_CMD_CODE 0x12
++#define INQ_CMD_LEN 6
++#define FILE_NAME_SIZE 255
++#define safe_sprintf(var, format, args...) \
++ snprintf(var, sizeof(var), format, ##args) >= sizeof(var)
++#define safe_snprintf(var, size, format, args...) \
++ snprintf(var, size, format, ##args) >= size
++
++int verbose;
++
++int hds_modular_prio(char * major_minor)
++{
++ int sg_fd, k, i;
++ char vendor[32];
++ char product[32];
++ char serial[32];
++ char ldev[32];
++ char ctrl[32];
++ char port[32];
++ char devpath[FILE_NAME_SIZE];
++ unsigned int major;
++ unsigned int minor;
++ unsigned char inqCmdBlk[INQ_CMD_LEN] =
++ {INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0};
++ unsigned char inqBuff[INQ_REPLY_LEN];
++ unsigned char sense_buffer[32];
++ sg_io_hdr_t io_hdr;
++
++ sscanf(major_minor, "%u:%u", &major, &minor);
++ memset(devpath, 0, FILE_NAME_SIZE);
++
++ if (safe_sprintf(devpath, "/tmp/.pp_balance.%u.%u.devnode",
++ major, minor))
++ exit(1);
++
++ unlink (devpath);
++ mknod(devpath, S_IFBLK|S_IRUSR|S_IWUSR, makedev(major, minor));
++
++ if ((sg_fd = open(devpath, O_RDONLY)) < 0) exit(1);
++ if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000))
++ exit(1);
++
++ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
++ io_hdr.interface_id = 'S';
++ io_hdr.cmd_len = sizeof(inqCmdBlk);
++ io_hdr.mx_sb_len = sizeof(sense_buffer);
++ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
++ io_hdr.dxfer_len = INQ_REPLY_LEN;
++ io_hdr.dxferp = inqBuff;
++ io_hdr.cmdp = inqCmdBlk;
++ io_hdr.sbp = sense_buffer;
++ io_hdr.timeout = 2000; /* TimeOut = 2 seconds */
++
++ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) exit(1);
++ if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) exit(1);
++
++ for (i = 0; i < 8 ; i++) vendor[i] = inqBuff[i+8];
++ vendor[8] = 0;
++ for (i = 0; i < 16 ; i++) product[i] = inqBuff[i+16];
++ product[16] = 0;
++ for (i = 0; i < 4 ; i++) serial[i] = inqBuff[i+40];
++ serial[4] = 0;
++ for (i = 0; i < 4 ; i++) ldev[i] = inqBuff[i+44];
++ ldev[4] = 0;
++ ctrl[0] = inqBuff[49];
++ ctrl[1] = 0;
++ port[0] = inqBuff[50];
++ port[1] = 0;
++
++ close(sg_fd);
++
++ if (1 == verbose) {
++ printf("VENDOR: %s\n", vendor);
++ printf("PRODUCT: %s\n", product);
++ printf("SERIAL: 0x%s\n", serial);
++ printf("LDEV: 0x%s\n", ldev);
++ printf("CTRL: %s\n", ctrl);
++ printf("PORT: %s\n", port);
++ }
++ switch( ctrl[0] ) {
++ case '0': case '2': case '4': case '6': case '8':
++ switch( ldev[3] ) {
++ case '0': case '2': case '4': case '6':
++ case '8': case 'A': case 'C': case 'E':
++ if (1 == verbose)
++ printf("CTRL EVEN, LDEV EVEN, "
++ "PRIO 1\n");
++ return 1;
++ break;
++ case '1': case '3': case '5': case '7':
++ case '9': case 'B': case 'D': case 'F':
++ if (1 == verbose)
++ printf("CTRL EVEN, LDEV ODD, "
++ "PRIO 0\n");
++ return 0;
++ break;
++
++ }
++ case '1': case '3': case '5': case '7': case '9':
++ switch( ldev[3] ) {
++ case '0': case '2': case '4': case '6':
++ case '8': case 'A': case 'C': case 'E':
++ if (1 == verbose)
++ printf("CTRL ODD, LDEV EVEN, "
++ "PRIO 0\n");
++ return 0;
++ break;
++ case '1': case '3': case '5': case '7':
++ case '9': case 'B': case 'D': case 'F':
++ if (1 == verbose)
++ printf("CTRL ODD, LDEV ODD, "
++ "PRIO 1\n");
++ return 1;
++ break;
++ }
++ }
++ exit(1);
++}
++
++void print_help(void)
++{
++ printf("Usage: "
++ "pp_hds_modular [-v] <device_major:device_minor>\n");
++ printf("Option: "
++ "-v verbose mode\n");
++ printf("Description: "
++ "Prioritizer for Multipath Tools and HDS Storage\n");
++ printf("Version: "
++ "1.12\n");
++ printf("Author: "
++ "Matthias Rudolph <matthias.rudolph at hds.com>\n");
++ return;
++}
++
++int main(int argc, char * argv[])
++{
++ int prio;
++
++ if (2 == argc) {
++ if (0 == strcmp(argv[1], "-h")) {
++ print_help();
++ exit(0);
++ }
++ else {
++ verbose = 0;
++ prio = hds_modular_prio(argv[1]);
++ printf("%d\n", prio);
++ exit(0);
++ }
++ }
++
++ if ((3 == argc) && (0 == strcmp(argv[1], "-v"))) {
++ verbose = 1;
++ prio = hds_modular_prio(argv[2]);
++ printf("%d\n", prio);
++ exit(0);
++ }
++ print_help();
++ exit(1);
++}
++
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/Makefile
++++ multipath-tools-0.4.7/libmultipath/Makefile
+@@ -6,7 +6,7 @@
+
+ include ../Makefile.inc
+
+-CFLAGS = -I$(checkersdir)
++CFLAGS += -I$(checkersdir)
+
+ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
+ hwtable.o blacklist.o util.o dmparser.o config.o \
+@@ -18,6 +18,7 @@
+ PREVBUILD = $(shell nm debug.o 2> /dev/null|grep log_safe)
+
+ ifeq ($(strip $(DAEMON)),1)
++ OBJS += lock.o waiter.o
+ CFLAGS += -DDAEMON
+ CLEAN = $(shell if [ "x$(PREVBUILD)" = "x" ]; then echo clean; fi)
+ else
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/callout.c
++++ multipath-tools-0.4.7/libmultipath/callout.c
+@@ -78,7 +78,7 @@
+ /* dup write side of pipe to STDOUT */
+ dup(fds[1]);
+
+- retval = execv(argv[0], argv);
++ retval = execvp(argv[0], argv);
+
+ exit(-1);
+ case -1:
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/config.c
++++ multipath-tools-0.4.7/libmultipath/config.c
+@@ -28,14 +28,16 @@
+ regex_t vre, pre;
+
+ vector_foreach_slot (hwtable, hwe, i) {
+- if (regcomp(&vre, hwe->vendor, REG_EXTENDED|REG_NOSUB))
++ if (hwe->vendor &&
++ regcomp(&vre, hwe->vendor, REG_EXTENDED|REG_NOSUB))
+ break;
+- if (regcomp(&pre, hwe->product, REG_EXTENDED|REG_NOSUB)) {
++ if (hwe->product &&
++ regcomp(&pre, hwe->product, REG_EXTENDED|REG_NOSUB)) {
+ regfree(&vre);
+ break;
+ }
+- if (!regexec(&vre, vendor, 0, NULL, 0) &&
+- !regexec(&pre, product, 0, NULL, 0))
++ if ((!hwe->vendor || !regexec(&vre, vendor, 0, NULL, 0)) &&
++ (!hwe->product || !regexec(&pre, product, 0, NULL, 0)))
+ ret = hwe;
+
+ regfree(&pre);
+@@ -305,7 +307,7 @@
+ free_blacklist_device(conf->blist_device);
+ free_mptable(conf->mptable);
+ free_hwtable(conf->hwtable);
+-
++ free_keywords(conf->keywords);
+ FREE(conf);
+ }
+
+@@ -332,6 +334,7 @@
+ * read the config file
+ */
+ if (filepresent(file)) {
++ set_current_keywords(&conf->keywords);
+ if (init_data(file, init_keywords)) {
+ condlog(0, "error parsing config file");
+ goto out;
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/config.h
++++ multipath-tools-0.4.7/libmultipath/config.h
+@@ -48,7 +48,7 @@
+ int with_sysfs;
+ int pgpolicy;
+ struct checker * checker;
+- int dev_type;
++ enum devtypes dev_type;
+ int minio;
+ int checkint;
+ int max_checkint;
+@@ -67,6 +67,7 @@
+ char * hwhandler;
+ char * bindings_file;
+
++ vector keywords;
+ vector mptable;
+ vector hwtable;
+
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/configure.c
++++ multipath-tools-0.4.7/libmultipath/configure.c
+@@ -145,11 +145,6 @@
+ mpp->action = ACT_RENAME;
+ return;
+ }
+- else {
+- condlog(3, "%s: set ACT_CREATE (map does not exist)",
+- mpp->alias);
+- mpp->action = ACT_CREATE;
+- }
+ mpp->action = ACT_CREATE;
+ condlog(3, "%s: set ACT_CREATE (map does not exist)",
+ mpp->alias);
+@@ -286,11 +281,13 @@
+
+ /*
+ * Return value:
+- * -1: Retry
+- * 0: DM_DEVICE_CREATE or DM_DEVICE_RELOAD failed, or dry_run mode.
+- * 1: DM_DEVICE_CREATE or DM_DEVICE_RELOAD succeeded.
+- * 2: Map is already existing.
+ */
++#define DOMAP_RETRY -1
++#define DOMAP_FAIL 0
++#define DOMAP_OK 1
++#define DOMAP_EXIST 2
++#define DOMAP_DRY 3
++
+ extern int
+ domap (struct multipath * mpp)
+ {
+@@ -299,15 +296,15 @@
+ /*
+ * last chance to quit before touching the devmaps
+ */
+- if (conf->dry_run) {
++ if (conf->dry_run && mpp->action != ACT_NOTHING) {
+ print_multipath_topology(mpp, conf->verbosity);
+- return 0;
++ return DOMAP_DRY;
+ }
+
+ switch (mpp->action) {
+ case ACT_REJECT:
+ case ACT_NOTHING:
+- return 2;
++ return DOMAP_EXIST;
+
+ case ACT_SWITCHPG:
+ dm_switchgroup(mpp->alias, mpp->bestpg);
+@@ -317,13 +314,13 @@
+ * retry.
+ */
+ reinstate_paths(mpp);
+- return 2;
++ return DOMAP_EXIST;
+
+ case ACT_CREATE:
+ if (lock_multipath(mpp, 1)) {
+ condlog(3, "%s: failed to create map (in use)",
+ mpp->alias);
+- return -1;
++ return DOMAP_RETRY;
+ }
+ dm_shut_log();
+
+@@ -377,9 +374,9 @@
+ condlog(2, "%s: load table [0 %llu %s %s]", mpp->alias,
+ mpp->size, DEFAULT_TARGET, mpp->params);
+ #endif
++ return DOMAP_OK;
+ }
+-
+- return r;
++ return DOMAP_FAIL;
+ }
+
+ static int
+@@ -486,19 +483,18 @@
+
+ r = domap(mpp);
+
+- if (!r) {
+- condlog(3, "%s: domap (%u) failure "
+- "for create/reload map",
+- mpp->alias, r);
+- remove_map(mpp, vecs, NULL, 0);
+- continue;
+- }
+- else if (r < 0) {
++ if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
+ condlog(3, "%s: domap (%u) failure "
+ "for create/reload map",
+ mpp->alias, r);
+- return r;
++ if (r == DOMAP_FAIL) {
++ remove_map(mpp, vecs, NULL, 0);
++ continue;
++ } else /* if (r == DOMAP_RETRY) */
++ return r;
+ }
++ if (r == DOMAP_DRY)
++ continue;
+
+ if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
+ if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
+@@ -547,11 +543,11 @@
+ }
+
+ extern char *
+-get_refwwid (char * dev, int dev_type, vector pathvec)
++get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
+ {
+ struct path * pp;
+ char buff[FILE_NAME_SIZE];
+- char * refwwid;
++ char * refwwid = NULL;
+
+ if (dev_type == DEV_NONE)
+ return NULL;
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/configure.h
++++ multipath-tools-0.4.7/libmultipath/configure.h
+@@ -25,5 +25,5 @@
+ int domap (struct multipath * mpp);
+ int reinstate_paths (struct multipath *mpp);
+ int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid);
+-char * get_refwwid (char * dev, int dev_type, vector pathvec);
++char * get_refwwid (char * dev, enum devtypes dev_type, vector pathvec);
+
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/debug.c
++++ multipath-tools-0.4.7/libmultipath/debug.c
+@@ -29,17 +29,16 @@
+ struct tm *tb = localtime(&t);
+ char buff[16];
+
+- strftime(buff, 16, "%b %d %H:%M:%S", tb);
++ strftime(buff, sizeof(buff), "%b %d %H:%M:%S", tb);
++ buff[sizeof(buff)-1] = '\0';
+
+ fprintf(stdout, "%s | ", buff);
+ vfprintf(stdout, fmt, ap);
+- fprintf(stdout, "\n");
+ }
+ else
+ log_safe(prio + 3, fmt, ap);
+ #else
+ vfprintf(stdout, fmt, ap);
+- fprintf(stdout, "\n");
+ #endif
+ }
+ va_end(ap);
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/debug.h
++++ multipath-tools-0.4.7/libmultipath/debug.h
+@@ -11,11 +11,11 @@
+ int logsink;
+
+ #define condlog(prio, fmt, args...) \
+- dlog(logsink, prio, fmt, ##args)
++ dlog(logsink, prio, fmt "\n", ##args)
+
+ #else /* DAEMON */
+
+ #define condlog(prio, fmt, args...) \
+- dlog(0, prio, fmt, ##args)
++ dlog(0, prio, fmt "\n", ##args)
+
+ #endif /* DAEMON */
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/devmapper.c
++++ multipath-tools-0.4.7/libmultipath/devmapper.c
+@@ -11,6 +11,7 @@
+ #include <ctype.h>
+ #include <linux/kdev_t.h>
+ #include <unistd.h>
++#include <errno.h>
+
+ #include <checkers.h>
+
+@@ -23,6 +24,10 @@
+ #define MAX_WAIT 5
+ #define LOOPS_PER_SEC 5
+
++#define UUID_PREFIX "mpath-"
++#define UUID_PREFIX_LEN 6
++
++
+ static void
+ dm_dummy_log (int level, const char *file, int line, const char *f, ...)
+ {
+@@ -113,6 +118,7 @@
+ const char *params, unsigned long long size, const char *uuid) {
+ int r = 0;
+ struct dm_task *dmt;
++ char *prefixed_uuid = NULL;
+
+ if (!(dmt = dm_task_create (task)))
+ return 0;
+@@ -123,13 +129,26 @@
+ if (!dm_task_add_target (dmt, 0, size, target, params))
+ goto addout;
+
+- if (uuid && !dm_task_set_uuid(dmt, uuid))
+- goto addout;
++ if (uuid){
++ prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1);
++ if (!prefixed_uuid) {
++ condlog(0, "cannot create prefixed uuid : %s\n",
++ strerror(errno));
++ goto addout;
++ }
++ sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid);
++ if (!dm_task_set_uuid(dmt, prefixed_uuid))
++ goto freeout;
++ }
+
+ dm_task_no_open_count(dmt);
+
+ r = dm_task_run (dmt);
+
++ freeout:
++ if (prefixed_uuid)
++ free(prefixed_uuid);
++
+ addout:
+ dm_task_destroy (dmt);
+ return r;
+@@ -215,8 +234,12 @@
+ goto uuidout;
+
+ uuidtmp = dm_task_get_uuid(dmt);
+- if (uuidtmp)
+- strcpy(uuid, uuidtmp);
++ if (uuidtmp) {
++ if (!strncmp(uuidtmp, UUID_PREFIX, UUID_PREFIX_LEN))
++ strcpy(uuid, uuidtmp + UUID_PREFIX_LEN);
++ else
++ strcpy(uuid, uuidtmp);
++ }
+ else
+ uuid[0] = '\0';
+
+@@ -591,6 +614,7 @@
+ goto out1;
+
+ dm_get_uuid(names->name, mpp->wwid);
++ dm_get_info(names->name, &mpp->dmi);
+ }
+
+ if (!vector_alloc_slot(mp))
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/discovery.c
++++ multipath-tools-0.4.7/libmultipath/discovery.c
+@@ -165,7 +165,7 @@
+ goto out; \
+ \
+ strncpy(buff, attr->value, attr->len - 1); \
+- buff[attr->len - 1] = '\0'; \
++ strchop(buff); \
+ sysfs_close_attribute(attr); \
+ return 0; \
+ out: \
+@@ -237,7 +237,7 @@
+ struct dlist * ls;
+ char attr_path[FILE_NAME_SIZE];
+ char block_path[FILE_NAME_SIZE];
+- struct sysfs_attribute * attr;
++ struct sysfs_attribute * attr = NULL;
+ struct sysfs_class * class;
+ struct sysfs_class_device * dev;
+
+@@ -339,24 +339,26 @@
+ return -1;
+ }
+
+-int
+-get_serial (char * str, int fd)
++static int
++get_serial (char * str, int maxlen, int fd)
+ {
+ int len = 0;
+ char buff[MX_ALLOC_LEN + 1] = {0};
+
+ if (fd < 0)
+- return 0;
++ return 1;
+
+ if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) {
+ len = buff[3];
++ if (len >= maxlen)
++ return 1;
+ if (len > 0) {
+ memcpy(str, buff + 4, len);
+ str[len] = '\0';
+ }
+- return 1;
++ return 0;
+ }
+- return 0;
++ return 1;
+ }
+
+ static int
+@@ -597,7 +599,7 @@
+ scsi_ioctl_pathinfo (struct path * pp, int mask)
+ {
+ if (mask & DI_SERIAL) {
+- get_serial(pp->serial, pp->fd);
++ get_serial(pp->serial, SERIAL_SIZE, pp->fd);
+ condlog(3, "%s: serial = %s", pp->dev, pp->serial);
+ }
+
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/discovery.h
++++ multipath-tools-0.4.7/libmultipath/discovery.h
+@@ -5,7 +5,6 @@
+ #define INQUIRY_CMDLEN 6
+ #define INQUIRY_CMD 0x12
+ #define SENSE_BUFF_LEN 32
+-#define DEF_TIMEOUT 60000
+ #define RECOVERED_ERROR 0x01
+ #define MX_ALLOC_LEN 255
+ #define TUR_CMD_LEN 6
+@@ -14,6 +13,10 @@
+ #define BLKGETSIZE _IO(0x12,96)
+ #endif
+
++#ifndef DEF_TIMEOUT
++#define DEF_TIMEOUT 300000
++#endif
++
+ /*
+ * exerpt from sg_err.h
+ */
+@@ -30,7 +33,6 @@
+ int path_discovery (vector pathvec, struct config * conf, int flag);
+
+ void basename (char *, char *);
+-int get_serial (char * buff, int fd);
+ int do_tur (char *);
+ int devt2devname (char *, char *);
+ int pathinfo (struct path *, vector hwtable, int mask);
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/hwtable.c
++++ multipath-tools-0.4.7/libmultipath/hwtable.c
+@@ -12,13 +12,34 @@
+ * Tuning suggestions on these parameters should go to
+ * dm-devel at redhat.com
+ *
+- * You are welcome to claim maintainership over a controler
++ * You are welcome to claim maintainership over a controller
+ * family. Please mail the currently enlisted maintainer and
+ * the upstream package maintainer.
+ */
+ static struct hwentry default_hw[] = {
+ /*
+- * StorageWorks controler family
++ * Apple controller family
++ *
++ * Maintainer : Shyam Sundar
++ * Mail : g.shyamsundar at yahoo.co.in
++ */
++ {
++ .vendor = "APPLE*",
++ .product = "Xserve RAID ",
++ .getuid = DEFAULT_GETUID,
++ .getprio = NULL,
++ .features = DEFAULT_FEATURES,
++ .hwhandler = DEFAULT_HWHANDLER,
++ .selector = DEFAULT_SELECTOR,
++ .pgpolicy = MULTIBUS,
++ .pgfailback = FAILBACK_UNDEF,
++ .rr_weight = RR_WEIGHT_NONE,
++ .no_path_retry = NO_PATH_RETRY_UNDEF,
++ .minio = DEFAULT_MINIO,
++ .checker_name = DEFAULT_CHECKER,
++ },
++ /*
++ * StorageWorks controller family
+ *
+ * Maintainer : Christophe Varoqui
+ * Mail : christophe.varoqui at free.fr
+@@ -70,22 +91,7 @@
+ },
+ {
+ .vendor = "HP",
+- .product = "HSV2*",
+- .getuid = DEFAULT_GETUID,
+- .getprio = NULL,
+- .features = DEFAULT_FEATURES,
+- .hwhandler = DEFAULT_HWHANDLER,
+- .selector = DEFAULT_SELECTOR,
+- .pgpolicy = MULTIBUS,
+- .pgfailback = FAILBACK_UNDEF,
+- .rr_weight = RR_WEIGHT_NONE,
+- .no_path_retry = NO_PATH_RETRY_UNDEF,
+- .minio = DEFAULT_MINIO,
+- .checker_name = READSECTOR0,
+- },
+- {
+- .vendor = "HP",
+- .product = "DF[456]00",
++ .product = "{HSV2*,A6189A}",
+ .getuid = DEFAULT_GETUID,
+ .getprio = NULL,
+ .features = DEFAULT_FEATURES,
+@@ -99,7 +105,7 @@
+ .checker_name = READSECTOR0,
+ },
+ /*
+- * DDN controler family
++ * DDN controller family
+ *
+ * Maintainer : Christophe Varoqui
+ * Mail : christophe.varoqui at free.fr
+@@ -120,7 +126,7 @@
+ .checker_name = READSECTOR0,
+ },
+ /*
+- * EMC / Clariion controler family
++ * EMC / Clariion controller family
+ *
+ * Maintainer : Edward Goggin, EMC
+ * Mail : egoggin at emc.com
+@@ -145,7 +151,7 @@
+ .product = "*",
+ .bl_product = "LUNZ",
+ .getuid = DEFAULT_GETUID,
+- .getprio = "/sbin/mpath_prio_emc /dev/%n",
++ .getprio = "mpath_prio_emc /dev/%n",
+ .features = "1 queue_if_no_path",
+ .hwhandler = "1 emc",
+ .selector = DEFAULT_SELECTOR,
+@@ -157,7 +163,7 @@
+ .checker_name = EMC_CLARIION,
+ },
+ /*
+- * Fujitsu controler family
++ * Fujitsu controller family
+ *
+ * Maintainer : Christophe Varoqui
+ * Mail : christophe.varoqui at free.fr
+@@ -178,14 +184,14 @@
+ .checker_name = READSECTOR0,
+ },
+ /*
+- * Hitachi controler family
++ * Hitachi controller family
+ *
+- * Maintainer : Christophe Varoqui
+- * Mail : christophe.varoqui at free.fr
++ * Maintainer : Matthias Rudolph
++ * Mail : matthias.rudolph at hds.com
+ */
+ {
+- .vendor = "HITACHI",
+- .product = "{A6189A,OPEN-}",
++ .vendor = "{HITACHI,HP}",
++ .product = "OPEN-*",
+ .getuid = DEFAULT_GETUID,
+ .getprio = NULL,
+ .features = DEFAULT_FEATURES,
+@@ -198,10 +204,25 @@
+ .minio = DEFAULT_MINIO,
+ .checker_name = READSECTOR0,
+ },
++ {
++ .vendor = "HITACHI",
++ .product = "DF*",
++ .getuid = DEFAULT_GETUID,
++ .getprio = "/sbin/mpath_prio_hds_modular %d",
++ .features = DEFAULT_FEATURES,
++ .hwhandler = DEFAULT_HWHANDLER,
++ .selector = DEFAULT_SELECTOR,
++ .pgpolicy = GROUP_BY_PRIO,
++ .pgfailback = -FAILBACK_IMMEDIATE,
++ .rr_weight = RR_WEIGHT_NONE,
++ .no_path_retry = NO_PATH_RETRY_UNDEF,
++ .minio = DEFAULT_MINIO,
++ .checker_name = READSECTOR0,
++ },
+ /*
+- * IBM controler family
++ * IBM controller family
+ *
+- * Maintainer : Hannes Reinecke, Suse
++ * Maintainer : Hannes Reinecke, SuSE
+ * Mail : hare at suse.de
+ */
+ {
+@@ -224,7 +245,7 @@
+ .vendor = "IBM",
+ .product = "1742",
+ .getuid = DEFAULT_GETUID,
+- .getprio = "/sbin/mpath_prio_tpc /dev/%n",
++ .getprio = "mpath_prio_tpc /dev/%n",
+ .features = DEFAULT_FEATURES,
+ .hwhandler = DEFAULT_HWHANDLER,
+ .selector = DEFAULT_SELECTOR,
+@@ -254,7 +275,7 @@
+ {
+ /* IBM ESS F20 aka Shark */
+ .vendor = "IBM",
+- .product = "2105F20",
++ .product = "2105{800,F20}",
+ .getuid = DEFAULT_GETUID,
+ .getprio = NULL,
+ .features = "1 queue_if_no_path",
+@@ -272,7 +293,7 @@
+ .vendor = "IBM",
+ .product = "{1750500,2145}",
+ .getuid = DEFAULT_GETUID,
+- .getprio = "/sbin/mpath_prio_alua /dev/%n",
++ .getprio = "mpath_prio_alua /dev/%n",
+ .features = "1 queue_if_no_path",
+ .hwhandler = DEFAULT_HWHANDLER,
+ .selector = DEFAULT_SELECTOR,
+@@ -303,7 +324,7 @@
+ /* IBM S/390 ECKD DASD */
+ .vendor = "IBM",
+ .product = "S/390 DASD ECKD",
+- .getuid = "/sbin/dasdview -j /dev/%n",
++ .getuid = "/sbin/dasd_id /dev/%n",
+ .getprio = NULL,
+ .features = DEFAULT_FEATURES,
+ .hwhandler = DEFAULT_HWHANDLER,
+@@ -315,29 +336,50 @@
+ .minio = DEFAULT_MINIO,
+ .checker_name = DIRECTIO,
+ },
+- /*
+- * NETAPP controler family
++ /*
++ * NETAPP controller family
+ *
+- * Maintainer : Igor Feoktistov
+- * Mail : igorf at netapp.com
++ * Maintainer : Dave Wysochanski
++ * Mail : davidw at netapp.com
+ */
+ {
+ .vendor = "NETAPP",
+- .product = "LUN",
++ .product = "LUN.*",
+ .getuid = DEFAULT_GETUID,
+- .getprio = "/sbin/mpath_prio_netapp /dev/%n",
++ .getprio = "mpath_prio_netapp /dev/%n",
+ .features = "1 queue_if_no_path",
+ .hwhandler = DEFAULT_HWHANDLER,
+ .selector = DEFAULT_SELECTOR,
+ .pgpolicy = GROUP_BY_PRIO,
+- .pgfailback = FAILBACK_UNDEF,
++ .pgfailback = -FAILBACK_IMMEDIATE,
+ .rr_weight = RR_WEIGHT_NONE,
+ .no_path_retry = NO_PATH_RETRY_UNDEF,
+- .minio = DEFAULT_MINIO,
++ .minio = 128,
++ .checker_name = READSECTOR0,
++ },
++ /*
++ * IBM NSeries (NETAPP) controller family
++ *
++ * Maintainer : Dave Wysochanski
++ * Mail : davidw at netapp.com
++ */
++ {
++ .vendor = "IBM",
++ .product = "Nseries.*",
++ .getuid = DEFAULT_GETUID,
++ .getprio = "mpath_prio_netapp /dev/%n",
++ .features = "1 queue_if_no_path",
++ .hwhandler = DEFAULT_HWHANDLER,
++ .selector = DEFAULT_SELECTOR,
++ .pgpolicy = GROUP_BY_PRIO,
++ .pgfailback = -FAILBACK_IMMEDIATE,
++ .rr_weight = RR_WEIGHT_NONE,
++ .no_path_retry = NO_PATH_RETRY_UNDEF,
++ .minio = 128,
+ .checker_name = READSECTOR0,
+ },
+ /*
+- * Pillar Data controler family
++ * Pillar Data controller family
+ *
+ * Maintainer : Christophe Varoqui
+ * Mail : christophe.varoqui at free.fr
+@@ -346,7 +388,7 @@
+ .vendor = "Pillar",
+ .product = "Axiom 500",
+ .getuid = DEFAULT_GETUID,
+- .getprio = "/sbin/mpath_prio_alua %d",
++ .getprio = "mpath_prio_alua %d",
+ .features = DEFAULT_FEATURES,
+ .hwhandler = DEFAULT_HWHANDLER,
+ .selector = DEFAULT_SELECTOR,
+@@ -382,7 +424,7 @@
+ .vendor = "SGI",
+ .product = "TP9[45]00",
+ .getuid = DEFAULT_GETUID,
+- .getprio = "/sbin/mpath_prio_tpc /dev/%n",
++ .getprio = "mpath_prio_tpc /dev/%n",
+ .features = DEFAULT_FEATURES,
+ .hwhandler = DEFAULT_HWHANDLER,
+ .selector = DEFAULT_SELECTOR,
+@@ -403,7 +445,7 @@
+ .vendor = "STK",
+ .product = "OPENstorage D280",
+ .getuid = DEFAULT_GETUID,
+- .getprio = "/sbin/mpath_prio_tpc /dev/%n",
++ .getprio = "mpath_prio_tpc /dev/%n",
+ .features = DEFAULT_FEATURES,
+ .hwhandler = DEFAULT_HWHANDLER,
+ .selector = DEFAULT_SELECTOR,
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/lock.c
++++ multipath-tools-0.4.7/libmultipath/lock.c
+@@ -0,0 +1,8 @@
++#include <pthread.h>
++#include "lock.h"
++
++void cleanup_lock (void * data)
++{
++ unlock((pthread_mutex_t *)data);
++}
++
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/lock.h
++++ multipath-tools-0.4.7/libmultipath/lock.h
+@@ -0,0 +1,22 @@
++#ifndef _LOCK_H
++#define _LOCK_H
++
++#ifdef LCKDBG
++#define lock(a) \
++ fprintf(stderr, "%s:%s(%i) lock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
++ pthread_mutex_lock(a)
++#define unlock(a) \
++ fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
++ pthread_mutex_unlock(a)
++#define lock_cleanup_pop(a) \
++ fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
++ pthread_cleanup_pop(1);
++#else
++#define lock(a) pthread_mutex_lock(a)
++#define unlock(a) pthread_mutex_unlock(a)
++#define lock_cleanup_pop(a) pthread_cleanup_pop(1);
++#endif
++
++void cleanup_lock (void * data);
++
++#endif /* _LOCK_H */
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/parser.c
++++ multipath-tools-0.4.7/libmultipath/parser.c
+@@ -25,6 +25,13 @@
+ /* local vars */
+ static int sublevel = 0;
+ vector keywords = NULL;
++vector *keywords_addr = NULL;
++
++void set_current_keywords (vector *k)
++{
++ keywords_addr = k;
++ keywords = NULL;
++}
+
+ int
+ keyword_alloc(vector keywords, char *string, int (*handler) (vector),
+@@ -53,7 +60,10 @@
+ int
+ install_keyword_root(char *string, int (*handler) (vector))
+ {
+- return keyword_alloc(keywords, string, handler, NULL);
++ int r = keyword_alloc(keywords, string, handler, NULL);
++ if (!r)
++ *keywords_addr = keywords;
++ return r;
+ }
+
+ void
+@@ -100,6 +110,9 @@
+ struct keyword *keyword;
+ int i;
+
++ if (!keywords)
++ return;
++
+ for (i = 0; i < VECTOR_SIZE(keywords); i++) {
+ keyword = VECTOR_SLOT(keywords, i);
+ if (keyword->sub)
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/parser.h
++++ multipath-tools-0.4.7/libmultipath/parser.h
+@@ -76,6 +76,7 @@
+ extern int process_stream(vector keywords);
+ extern int init_data(char *conf_file, void (*init_keywords) (void));
+ extern struct keyword * find_keyword(vector v, char * name);
++void set_current_keywords (vector *k);
+ int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
+ void *data);
+
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/pgpolicies.h
++++ multipath-tools-0.4.7/libmultipath/pgpolicies.h
+@@ -9,7 +9,7 @@
+
+ #define POLICY_NAME_SIZE 32
+
+-/* Storage controlers capabilities */
++/* Storage controllers capabilities */
+ enum iopolicies {
+ IOPOLICY_UNDEF,
+ FAILOVER,
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/print.c
++++ multipath-tools-0.4.7/libmultipath/print.c
+@@ -13,8 +13,8 @@
+ #include "structs_vec.h"
+ #include "print.h"
+ #include "dmparser.h"
+-#include "configure.h"
+ #include "config.h"
++#include "configure.h"
+ #include "pgpolicies.h"
+ #include "defaults.h"
+ #include "parser.h"
+@@ -52,16 +52,26 @@
+ static int
+ snprint_size (char * buff, size_t len, unsigned long long size)
+ {
+- if (size < (1 << 11))
+- return snprintf(buff, len, "%llu kB", size >> 1);
+- else if (size < (1 << 21))
+- return snprintf(buff, len, "%llu MB", size >> 11);
+- else if (size < (1 << 31))
+- return snprintf(buff, len, "%llu GB", size >> 21);
++ float s = (float)(size >> 1); /* start with KB */
++ char fmt[6] = {};
++ char units[] = {'K','M','G','T','P'};
++ char *u = units;
++
++ while (s >= 1024 && *u != 'P') {
++ s = s / 1024;
++ u++;
++ }
++ if (s < 10)
++ snprintf(fmt, 6, "%%.1f%c", *u);
+ else
+- return snprintf(buff, len, "%llu TB", size >> 31);
++ snprintf(fmt, 6, "%%.0f%c", *u);
++
++ return snprintf(buff, len, fmt, s);
+ }
+
++/*
++ * multipath info printing functions
++ */
+ static int
+ snprint_name (char * buff, size_t len, struct multipath * mpp)
+ {
+@@ -222,6 +232,9 @@
+ }
+ }
+
++/*
++ * path info printing functions
++ */
+ static int
+ snprint_path_uuid (char * buff, size_t len, struct path * pp)
+ {
+@@ -292,8 +305,8 @@
+ static int
+ snprint_vpr (char * buff, size_t len, struct path * pp)
+ {
+- return snprintf(buff, len, "%s/%s/%s",
+- pp->vendor_id, pp->product_id, pp->rev);
++ return snprintf(buff, len, "%s,%s",
++ pp->vendor_id, pp->product_id);
+ }
+
+ static int
+@@ -496,7 +509,7 @@
+ char * f = format; /* format string cursor */
+ int fwd;
+ struct multipath_data * data;
+- char buff[MAX_FIELD_LEN];
++ char buff[MAX_FIELD_LEN] = {};
+
+ do {
+ if (!TAIL)
+@@ -515,6 +528,7 @@
+ data->snprint(buff, MAX_FIELD_LEN, mpp);
+ PRINT(c, TAIL, buff);
+ PAD(data->width);
++ buff[0] = '\0';
+ } while (*f++);
+
+ line[c - line - 1] = '\n';
+@@ -631,7 +645,7 @@
+ extern void
+ print_multipath_topology (struct multipath * mpp, int verbosity)
+ {
+- char buff[MAX_LINE_LEN * MAX_LINES];
++ char buff[MAX_LINE_LEN * MAX_LINES] = {};
+
+ snprint_multipath_topology(&buff[0], MAX_LINE_LEN * MAX_LINES,
+ mpp, verbosity);
+@@ -662,7 +676,10 @@
+ c += sprintf(c, "%%n");
+
+ if (strncmp(mpp->alias, mpp->wwid, WWID_SIZE))
+- c += sprintf(c, " (%%w)");
++ c += sprintf(c, " (%%w) ");
++
++ c += sprintf(c, "%%d ");
++ c += snprint_vpr(c, 24, first_path(mpp));
+
+ fwd += snprint_multipath(buff + fwd, len - fwd, style, mpp);
+ if (fwd > len)
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/propsel.c
++++ multipath-tools-0.4.7/libmultipath/propsel.c
+@@ -15,6 +15,7 @@
+ #include "pgpolicies.h"
+ #include "alias.h"
+ #include "defaults.h"
++#include "devmapper.h"
+
+ pgpolicyfn *pgpolicies[] = {
+ NULL,
+@@ -41,7 +42,7 @@
+ }
+ if (mp->hwe && mp->hwe->rr_weight) {
+ mp->rr_weight = mp->hwe->rr_weight;
+- condlog(3, "%s: rr_weight = %i (controler setting)",
++ condlog(3, "%s: rr_weight = %i (controller setting)",
+ mp->alias, mp->rr_weight);
+ return 0;
+ }
+@@ -68,7 +69,7 @@
+ }
+ if (mp->hwe && mp->hwe->pgfailback != FAILBACK_UNDEF) {
+ mp->pgfailback = mp->hwe->pgfailback;
+- condlog(3, "%s: pgfailback = %i (controler setting)",
++ condlog(3, "%s: pgfailback = %i (controller setting)",
+ mp->alias, mp->pgfailback);
+ return 0;
+ }
+@@ -112,7 +113,7 @@
+ mp->pgpolicyfn = pgpolicies[mp->pgpolicy];
+ get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE,
+ mp->pgpolicy);
+- condlog(3, "%s: pgpolicy = %s (controler setting)",
++ condlog(3, "%s: pgpolicy = %s (controller setting)",
+ mp->alias, pgpolicy_name);
+ return 0;
+ }
+@@ -144,7 +145,7 @@
+ }
+ if (mp->hwe && mp->hwe->selector) {
+ mp->selector = mp->hwe->selector;
+- condlog(3, "%s: selector = %s (controler setting)",
++ condlog(3, "%s: selector = %s (controller setting)",
+ mp->alias, mp->selector);
+ return 0;
+ }
+@@ -164,6 +165,16 @@
+ if (conf->user_friendly_names)
+ mp->alias = get_user_friendly_alias(mp->wwid,
+ conf->bindings_file);
++ if (mp->alias == NULL){
++ char *alias;
++ if ((alias = MALLOC(WWID_SIZE)) != NULL){
++ if (dm_get_name(mp->wwid, DEFAULT_TARGET,
++ alias) == 1)
++ mp->alias = alias;
++ else
++ FREE(alias);
++ }
++ }
+ if (mp->alias == NULL)
+ mp->alias = mp->wwid;
+ }
+@@ -176,7 +187,7 @@
+ {
+ if (mp->hwe && mp->hwe->features) {
+ mp->features = mp->hwe->features;
+- condlog(3, "%s: features = %s (controler setting)",
++ condlog(3, "%s: features = %s (controller setting)",
+ mp->alias, mp->features);
+ return 0;
+ }
+@@ -191,7 +202,7 @@
+ {
+ if (mp->hwe && mp->hwe->hwhandler) {
+ mp->hwhandler = mp->hwe->hwhandler;
+- condlog(3, "%s: hwhandler = %s (controler setting)",
++ condlog(3, "%s: hwhandler = %s (controller setting)",
+ mp->alias, mp->hwhandler);
+ return 0;
+ }
+@@ -208,7 +219,7 @@
+
+ if (pp->hwe && pp->hwe->checker) {
+ checker_get(c, pp->hwe->checker);
+- condlog(3, "%s: path checker = %s (controler setting)",
++ condlog(3, "%s: path checker = %s (controller setting)",
+ pp->dev, checker_name(c));
+ return 0;
+ }
+@@ -229,7 +240,7 @@
+ {
+ if (pp->hwe && pp->hwe->getuid) {
+ pp->getuid = pp->hwe->getuid;
+- condlog(3, "%s: getuid = %s (controler setting)",
++ condlog(3, "%s: getuid = %s (controller setting)",
+ pp->dev, pp->getuid);
+ return 0;
+ }
+@@ -250,7 +261,7 @@
+ {
+ if (pp->hwe && pp->hwe->getprio) {
+ pp->getprio = pp->hwe->getprio;
+- condlog(3, "%s: getprio = %s (controler setting)",
++ condlog(3, "%s: getprio = %s (controller setting)",
+ pp->dev, pp->getprio);
+ return 0;
+ }
+@@ -276,7 +287,7 @@
+ }
+ if (mp->hwe && mp->hwe->no_path_retry != NO_PATH_RETRY_UNDEF) {
+ mp->no_path_retry = mp->hwe->no_path_retry;
+- condlog(3, "%s: no_path_retry = %i (controler setting)",
++ condlog(3, "%s: no_path_retry = %i (controller setting)",
+ mp->alias, mp->no_path_retry);
+ return 0;
+ }
+@@ -303,7 +314,7 @@
+ }
+ if (mp->hwe && mp->hwe->minio) {
+ mp->minio = mp->hwe->minio;
+- condlog(3, "%s: minio = %i (controler setting)",
++ condlog(3, "%s: minio = %i (controller setting)",
+ mp->alias, mp->minio);
+ return 0;
+ }
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/structs.c
++++ multipath-tools-0.4.7/libmultipath/structs.c
+@@ -16,6 +16,7 @@
+ #include "debug.h"
+ #include "structs_vec.h"
+ #include "blacklist.h"
++#include "waiter.h"
+
+ struct path *
+ alloc_path (void)
+@@ -365,3 +366,10 @@
+
+ return count;
+ }
++
++struct path *
++first_path (struct multipath * mpp)
++{
++ struct pathgroup * pgp = VECTOR_SLOT(mpp->pg, 0);
++ return VECTOR_SLOT(pgp->paths, 0);
++}
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/structs.h
++++ multipath-tools-0.4.7/libmultipath/structs.h
+@@ -1,8 +1,8 @@
+ #ifndef _STRUCTS_H
+ #define _STRUCTS_H
+
+-#define WWID_SIZE 64
+-#define SERIAL_SIZE 17
++#define WWID_SIZE 128
++#define SERIAL_SIZE 64
+ #define NODE_NAME_SIZE 19
+ #define PATH_STR_SIZE 16
+ #define PARAMS_SIZE 1024
+@@ -142,7 +142,7 @@
+ struct mpentry * mpe;
+ struct hwentry * hwe;
+
+- /* daemon store a data blob for DM event waiter threads */
++ /* threads */
+ void * waiter;
+
+ /* stats */
+@@ -183,10 +183,11 @@
+
+ struct path * find_path_by_devt (vector pathvec, char * devt);
+ struct path * find_path_by_dev (vector pathvec, char * dev);
++struct path * first_path (struct multipath * mpp);
+
+ int pathcountgr (struct pathgroup *, int);
+ int pathcount (struct multipath *, int);
+
+ char sysfs_path[FILE_NAME_SIZE];
+
+-#endif
++#endif /* _STRUCTS_H */
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/structs_vec.c
++++ multipath-tools-0.4.7/libmultipath/structs_vec.c
+@@ -14,6 +14,7 @@
+ #include "config.h"
+ #include "propsel.h"
+ #include "discovery.h"
++#include "waiter.h"
+
+
+ /*
+@@ -58,8 +59,8 @@
+
+ vector_foreach_slot (pathvec, pp, i) {
+ if (!strncmp(mpp->wwid, pp->wwid, WWID_SIZE)) {
+- condlog(3, "%s ownership set to %s",
+- pp->dev_t, mpp->alias);
++ condlog(3, "%s: ownership set to %s",
++ pp->dev, mpp->alias);
+ pp->mpp = mpp;
+
+ if (!mpp->paths && !(mpp->paths = vector_alloc()))
+@@ -96,7 +97,7 @@
+
+ vector_foreach_slot (pathvec, pp, i) {
+ if (pp->mpp == mpp) {
+- condlog(4, "%s is orphaned", pp->dev_t);
++ condlog(4, "%s: orphaned", pp->dev);
+ orphan_path(pp);
+ }
+ }
+@@ -382,3 +383,90 @@
+ return count;
+ }
+
++int update_multipath (struct vectors *vecs, char *mapname)
++{
++ struct multipath *mpp;
++ struct pathgroup *pgp;
++ struct path *pp;
++ int i, j;
++ int r = 1;
++
++ mpp = find_mp_by_alias(vecs->mpvec, mapname);
++
++ if (!mpp)
++ goto out;
++
++ free_pgvec(mpp->pg, KEEP_PATHS);
++ mpp->pg = NULL;
++
++ if (setup_multipath(vecs, mpp))
++ goto out; /* mpp freed in setup_multipath */
++
++ /*
++ * compare checkers states with DM states
++ */
++ vector_foreach_slot (mpp->pg, pgp, i) {
++ vector_foreach_slot (pgp->paths, pp, j) {
++ if (pp->dmstate != PSTATE_FAILED)
++ continue;
++
++ if (pp->state != PATH_DOWN) {
++ int oldstate = pp->state;
++ condlog(2, "%s: mark as failed", pp->dev_t);
++ mpp->stat_path_failures++;
++ pp->state = PATH_DOWN;
++ if (oldstate == PATH_UP ||
++ oldstate == PATH_GHOST)
++ update_queue_mode_del_path(mpp);
++
++ /*
++ * if opportune,
++ * schedule the next check earlier
++ */
++ if (pp->tick > conf->checkint)
++ pp->tick = conf->checkint;
++ }
++ }
++ }
++ r = 0;
++out:
++ if (r)
++ condlog(0, "failed to update multipath");
++ return r;
++}
++
++/*
++ * mpp->no_path_retry:
++ * -2 (QUEUE) : queue_if_no_path enabled, never turned off
++ * -1 (FAIL) : fail_if_no_path
++ * 0 (UNDEF) : nothing
++ * >0 : queue_if_no_path enabled, turned off after polling n times
++ */
++void update_queue_mode_del_path(struct multipath *mpp)
++{
++ if (--mpp->nr_active == 0 && mpp->no_path_retry > 0) {
++ /*
++ * Enter retry mode.
++ * meaning of +1: retry_tick may be decremented in
++ * checkerloop before starting retry.
++ */
++ mpp->stat_queueing_timeouts++;
++ mpp->retry_tick = mpp->no_path_retry * conf->checkint + 1;
++ condlog(1, "%s: Entering recovery mode: max_retries=%d",
++ mpp->alias, mpp->no_path_retry);
++ }
++ condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
++}
++
++void update_queue_mode_add_path(struct multipath *mpp)
++{
++ if (mpp->nr_active++ == 0 && mpp->no_path_retry > 0) {
++ /* come back to normal mode from retry mode */
++ mpp->retry_tick = 0;
++ dm_queue_if_no_path(mpp->alias, 1);
++ condlog(2, "%s: queue_if_no_path enabled", mpp->alias);
++ condlog(1, "%s: Recovered to normal mode", mpp->alias);
++ }
++ condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
++}
++
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/structs_vec.h
++++ multipath-tools-0.4.7/libmultipath/structs_vec.h
+@@ -9,17 +9,6 @@
+ vector mpvec;
+ };
+
+-#if DAEMON
+-struct event_thread {
+- struct dm_task *dmt;
+- pthread_t thread;
+- int event_nr;
+- char mapname[WWID_SIZE];
+- struct vectors *vecs;
+- struct multipath *mpp;
+-};
+-#endif
+-
+ typedef void (stop_waiter_thread_func) (struct multipath *, struct vectors *);
+ typedef int (start_waiter_thread_func) (struct multipath *, struct vectors *);
+
+@@ -44,5 +33,8 @@
+ start_waiter_thread_func *start_waiter);
+ struct multipath * add_map_with_path (struct vectors * vecs,
+ struct path * pp, int add_vec);
++int update_multipath (struct vectors *vecs, char *mapname);
++void update_queue_mode_del_path(struct multipath *mpp);
++void update_queue_mode_add_path(struct multipath *mpp);
+
+ #endif /* _STRUCTS_VEC_H */
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/util.c
++++ multipath-tools-0.4.7/libmultipath/util.c
+@@ -30,6 +30,15 @@
+ }
+
+ void
++strchop(char *str)
++{
++ int i;
++
++ for (i=strlen(str)-1; i >=0 && isspace(str[i]); --i) ;
++ str[++i] = '\0';
++}
++
++void
+ basename (char * str1, char * str2)
+ {
+ char *p = str1 + (strlen(str1) - 1);
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/util.h
++++ multipath-tools-0.4.7/libmultipath/util.h
+@@ -2,6 +2,7 @@
+ #define _UTIL_H
+
+ int strcmp_chomp(char *, char *);
++void strchop(char *);
+ void basename (char * src, char * dst);
+ int filepresent (char * run);
+ int get_word (char * sentence, char ** word);
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/version.h
++++ multipath-tools-0.4.7/libmultipath/version.h
+@@ -0,0 +1,37 @@
++/*
++ * Soft: multipath device mapper target autoconfig
++ *
++ * Version: $Id: main.h,v 0.0.1 2003/09/18 15:13:38 cvaroqui Exp $
++ *
++ * Author: Christophe Varoqui
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * Copyright (c) 2006 Christophe Varoqui
++ */
++#ifndef _VERSION_H
++#define _VERSION_H
++
++#define VERSION_CODE 0x000407
++#define DATE_CODE 0x030c06
++
++#define PROG "multipath-tools"
++
++#define MULTIPATH_VERSION(version) \
++ (version >> 16) & 0xFF, \
++ (version >> 8) & 0xFF, \
++ version & 0xFF
++
++#define VERSION_STRING PROG" v%d.%d.%d (%.2d/%.2d, 20%.2d)\n", \
++ MULTIPATH_VERSION(VERSION_CODE), \
++ MULTIPATH_VERSION(DATE_CODE)
++
++#endif /* _VERSION_H */
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/waiter.c
++++ multipath-tools-0.4.7/libmultipath/waiter.c
+@@ -0,0 +1,234 @@
++/*
++ * Copyright (c) 2004, 2005 Christophe Varoqui
++ * Copyright (c) 2005 Kiyoshi Ueda, NEC
++ * Copyright (c) 2005 Benjamin Marzinski, Redhat
++ * Copyright (c) 2005 Edward Goggin, EMC
++ */
++#include <unistd.h>
++#include <libdevmapper.h>
++#include <sys/mman.h>
++#include <pthread.h>
++#include <signal.h>
++
++#include "vector.h"
++#include "memory.h"
++#include "checkers.h"
++#include "structs.h"
++#include "structs_vec.h"
++#include "devmapper.h"
++#include "debug.h"
++#include "lock.h"
++#include "waiter.h"
++
++struct event_thread *alloc_waiter (void)
++{
++
++ struct event_thread *wp;
++
++ wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
++
++ return wp;
++}
++
++void free_waiter (void *data)
++{
++ struct event_thread *wp = (struct event_thread *)data;
++
++ /*
++ * indicate in mpp that the wp is already freed storage
++ */
++ lock(wp->vecs->lock);
++
++ if (wp->mpp)
++ /*
++ * be careful, mpp may already be freed -- null if so
++ */
++ wp->mpp->waiter = NULL;
++ else
++ condlog(3, "free_waiter, mpp freed before wp=%p,", wp);
++
++ unlock(wp->vecs->lock);
++
++ if (wp->dmt)
++ dm_task_destroy(wp->dmt);
++
++ FREE(wp);
++}
++
++void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
++{
++ struct event_thread *wp = (struct event_thread *)mpp->waiter;
++
++ if (!wp) {
++ condlog(3, "%s: no waiter thread", mpp->alias);
++ return;
++ }
++ condlog(2, "%s: stop event checker thread", wp->mapname);
++ pthread_kill((pthread_t)wp->thread, SIGUSR1);
++}
++
++static sigset_t unblock_signals(void)
++{
++ sigset_t set, old;
++
++ sigemptyset(&set);
++ sigaddset(&set, SIGHUP);
++ sigaddset(&set, SIGUSR1);
++ pthread_sigmask(SIG_UNBLOCK, &set, &old);
++ return old;
++}
++
++/*
++ * returns the reschedule delay
++ * negative means *stop*
++ */
++int waiteventloop (struct event_thread *waiter)
++{
++ sigset_t set;
++ int event_nr;
++ int r;
++
++ if (!waiter->event_nr)
++ waiter->event_nr = dm_geteventnr(waiter->mapname);
++
++ if (!(waiter->dmt = dm_task_create(DM_DEVICE_WAITEVENT))) {
++ condlog(0, "%s: devmap event #%i dm_task_create error",
++ waiter->mapname, waiter->event_nr);
++ return 1;
++ }
++
++ if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
++ condlog(0, "%s: devmap event #%i dm_task_set_name error",
++ waiter->mapname, waiter->event_nr);
++ dm_task_destroy(waiter->dmt);
++ return 1;
++ }
++
++ if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
++ waiter->event_nr)) {
++ condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
++ waiter->mapname, waiter->event_nr);
++ dm_task_destroy(waiter->dmt);
++ return 1;
++ }
++
++ dm_task_no_open_count(waiter->dmt);
++
++ /* accept wait interruption */
++ set = unblock_signals();
++
++ /* interruption spits messages */
++ dm_shut_log();
++
++ /* wait */
++ r = dm_task_run(waiter->dmt);
++
++ /* wait is over : event or interrupt */
++ pthread_sigmask(SIG_SETMASK, &set, NULL);
++ //dm_restore_log();
++
++ if (!r) /* wait interrupted by signal */
++ return -1;
++
++ dm_task_destroy(waiter->dmt);
++ waiter->dmt = NULL;
++ waiter->event_nr++;
++
++ /*
++ * upon event ...
++ */
++ while (1) {
++ condlog(3, "%s: devmap event #%i",
++ waiter->mapname, waiter->event_nr);
++
++ /*
++ * event might be :
++ *
++ * 1) a table reload, which means our mpp structure is
++ * obsolete : refresh it through update_multipath()
++ * 2) a path failed by DM : mark as such through
++ * update_multipath()
++ * 3) map has gone away : stop the thread.
++ * 4) a path reinstate : nothing to do
++ * 5) a switch group : nothing to do
++ */
++ pthread_cleanup_push(cleanup_lock, waiter->vecs->lock);
++ lock(waiter->vecs->lock);
++ r = update_multipath(waiter->vecs, waiter->mapname);
++ lock_cleanup_pop(waiter->vecs->lock);
++
++ if (r)
++ return -1; /* stop the thread */
++
++ event_nr = dm_geteventnr(waiter->mapname);
++
++ if (waiter->event_nr == event_nr)
++ return 1; /* upon problem reschedule 1s later */
++
++ waiter->event_nr = event_nr;
++ }
++ return -1; /* never reach there */
++}
++
++void *waitevent (void *et)
++{
++ int r;
++ struct event_thread *waiter;
++
++ mlockall(MCL_CURRENT | MCL_FUTURE);
++
++ waiter = (struct event_thread *)et;
++ pthread_cleanup_push(free_waiter, et);
++
++ while (1) {
++ r = waiteventloop(waiter);
++
++ if (r < 0)
++ break;
++
++ sleep(r);
++ }
++
++ pthread_cleanup_pop(1);
++ return NULL;
++}
++
++int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
++{
++ pthread_attr_t attr;
++ struct event_thread *wp;
++
++ if (!mpp)
++ return 0;
++
++ if (pthread_attr_init(&attr))
++ goto out;
++
++ pthread_attr_setstacksize(&attr, 32 * 1024);
++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++
++ wp = alloc_waiter();
++
++ if (!wp)
++ goto out;
++
++ mpp->waiter = (void *)wp;
++ strncpy(wp->mapname, mpp->alias, WWID_SIZE);
++ wp->vecs = vecs;
++ wp->mpp = mpp;
++
++ if (pthread_create(&wp->thread, &attr, waitevent, wp)) {
++ condlog(0, "%s: cannot create event checker", wp->mapname);
++ goto out1;
++ }
++ condlog(2, "%s: event checker started", wp->mapname);
++
++ return 0;
++out1:
++ free_waiter(wp);
++ mpp->waiter = NULL;
++out:
++ condlog(0, "failed to start waiter thread");
++ return 1;
++}
++
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libmultipath/waiter.h
++++ multipath-tools-0.4.7/libmultipath/waiter.h
+@@ -0,0 +1,23 @@
++#ifndef _WAITER_H
++#define _WAITER_H
++
++#if DAEMON
++
++struct event_thread {
++ struct dm_task *dmt;
++ pthread_t thread;
++ int event_nr;
++ char mapname[WWID_SIZE];
++ struct vectors *vecs;
++ struct multipath *mpp;
++};
++
++struct event_thread * alloc_waiter (void);
++void free_waiter (void *data);
++void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs);
++int start_waiter_thread (struct multipath *mpp, struct vectors *vecs);
++int waiteventloop (struct event_thread *waiter);
++void *waitevent (void *et);
++
++#endif /* DAEMON */
++#endif /* _WAITER_H */
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/multipath/main.c
++++ multipath-tools-0.4.7/multipath/main.c
+@@ -46,8 +46,7 @@
+ #include <alias.h>
+ #include <configure.h>
+ #include <pgpolicies.h>
+-
+-#include "main.h"
++#include <version.h>
+
+ static int
+ filter_pathvec (vector pathvec, char * refwwid)
+@@ -305,7 +304,7 @@
+ int arg;
+ extern char *optarg;
+ extern int optind;
+- int i, r;
++ int i, r = 1;
+
+ if (getuid() != 0) {
+ fprintf(stderr, "need to be root\n");
+@@ -322,7 +321,7 @@
+ if (load_config(DEFAULT_CONFIGFILE))
+ exit(1);
+
+- while ((arg = getopt(argc, argv, ":qdl::Ffi:M:v:p:b:")) != EOF ) {
++ while ((arg = getopt(argc, argv, ":dl::FfM:v:p:b:")) != EOF ) {
+ switch(arg) {
+ case 1: printf("optarg : %s\n",optarg);
+ break;
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/multipath/multipath.8
++++ multipath-tools-0.4.7/multipath/multipath.8
+@@ -1,4 +1,4 @@
+-.TH MULTIPATH 8 "February 2004" "" "Linux Administrator's Manual"
++.TH MULTIPATH 8 "July 2006" "" "Linux Administrator's Manual"
+ .SH NAME
+ multipath \- Device mapper target autoconfig
+ .SH SYNOPSIS
+@@ -64,7 +64,7 @@
+ 1 priority group per serial
+ .TP
+ .B group_by_prio
+-1 priority group per priority value. Priorities are determined by callout programs specified as a global, per-controler or per-multipath option in the configuration file
++1 priority group per priority value. Priorities are determined by callout programs specified as a global, per-controller or per-multipath option in the configuration file
+ .TP
+ .B group_by_node_name
+ 1 priority group per target node name. Target node names are fetched in /sys/class/fc_transport/target*/node_name.
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/kpartx/devmapper.c
++++ multipath-tools-0.4.7/kpartx/devmapper.c
+@@ -7,6 +7,10 @@
+ #include <libdevmapper.h>
+ #include <ctype.h>
+ #include <linux/kdev_t.h>
++#include <errno.h>
++
++#define UUID_PREFIX "part%d-"
++#define MAX_PREFIX_LEN 8
+
+ extern int
+ dm_prereq (char * str, int x, int y, int z)
+@@ -68,9 +72,10 @@
+
+ extern int
+ dm_addmap (int task, const char *name, const char *target,
+- const char *params, unsigned long size) {
++ const char *params, unsigned long size, const char *uuid, int part) {
+ int r = 0;
+ struct dm_task *dmt;
++ char *prefixed_uuid;
+
+ if (!(dmt = dm_task_create (task)))
+ return 0;
+@@ -81,10 +86,26 @@
+ if (!dm_task_add_target (dmt, 0, size, target, params))
+ goto addout;
+
++ if (task == DM_DEVICE_CREATE && uuid) {
++ prefixed_uuid = malloc(MAX_PREFIX_LEN + strlen(uuid) + 1);
++ if (!prefixed_uuid) {
++ fprintf(stderr, "cannot create prefixed uuid : %s\n",
++ strerror(errno));
++ goto addout;
++ }
++ sprintf(prefixed_uuid, UUID_PREFIX "%s", part, uuid);
++ if (!dm_task_set_uuid(dmt, prefixed_uuid))
++ goto freeout;
++ }
++
+ dm_task_no_open_count(dmt);
+
+ r = dm_task_run (dmt);
+
++ freeout:
++ if (prefixed_uuid)
++ free(prefixed_uuid);
++
+ addout:
+ dm_task_destroy (dmt);
+ return r;
+@@ -178,3 +199,26 @@
+ return ret;
+ }
+
++char *
++dm_mapuuid(int major, int minor)
++{
++ struct dm_task *dmt;
++ char *tmp, *uuid = NULL;
++
++ if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
++ return NULL;
++
++ dm_task_no_open_count(dmt);
++ dm_task_set_major(dmt, major);
++ dm_task_set_minor(dmt, minor);
++
++ if (!dm_task_run(dmt))
++ goto out;
++
++ tmp = dm_task_get_uuid(dmt);
++ if (tmp[0] != '\0')
++ uuid = strdup(tmp);
++out:
++ dm_task_destroy(dmt);
++ return uuid;
++}
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/kpartx/devmapper.h
++++ multipath-tools-0.4.7/kpartx/devmapper.h
+@@ -1,6 +1,8 @@
+ int dm_prereq (char *, int, int, int);
+ int dm_simplecmd (int, const char *);
+-int dm_addmap (int, const char *, const char *, const char *, unsigned long);
++int dm_addmap (int, const char *, const char *, const char *, unsigned long,
++ char *, int);
+ int dm_map_present (char *);
+ char * dm_mapname(int major, int minor);
+ dev_t dm_get_first_dep(char *devname);
++char * dm_mapuuid(int major, int minor);
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/kpartx/kpartx.8
++++ multipath-tools-0.4.7/kpartx/kpartx.8
+@@ -1,4 +1,4 @@
+-.TH KPARTX 8 "February 2004" "" "Linux Administrator's Manual"
++.TH KPARTX 8 "July 2006" "" "Linux Administrator's Manual"
+ .SH NAME
+ kpartx \- Create device maps from partition tables
+ .SH SYNOPSIS
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/kpartx/kpartx.c
++++ multipath-tools-0.4.7/kpartx/kpartx.c
+@@ -192,6 +192,7 @@
+ char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16];
+ char * loopdev = NULL;
+ char * delim = NULL;
++ char *uuid = NULL;
+ int loopro = 0;
+ int hotplug = 0;
+ struct stat buf;
+@@ -284,11 +285,6 @@
+ }
+
+ if (S_ISREG (buf.st_mode)) {
+- loopdev = malloc(LO_NAME_SIZE * sizeof(char));
+-
+- if (!loopdev)
+- exit(1);
+-
+ /* already looped file ? */
+ loopdev = find_loop_by_file(device);
+
+@@ -313,6 +309,13 @@
+ }
+
+ off = find_devname_offset(device);
++
++ if (!loopdev)
++ uuid = dm_mapuuid((unsigned int)MAJOR(buf.st_rdev),
++ (unsigned int)MINOR(buf.st_rdev));
++ if (!uuid)
++ uuid = device + off;
++
+ fd = open(device, O_RDONLY);
+
+ if (fd == -1) {
+@@ -420,7 +423,7 @@
+ DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
+
+ dm_addmap(op, partname, DM_TARGET, params,
+- slices[j].size);
++ slices[j].size, uuid, j+1);
+
+ if (op == DM_DEVICE_RELOAD)
+ dm_simplecmd(DM_DEVICE_RESUME,
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/multipathd/cli.c
++++ multipath-tools-0.4.7/multipathd/cli.c
+@@ -4,6 +4,7 @@
+ #include <memory.h>
+ #include <vector.h>
+ #include <util.h>
++#include <version.h>
+
+ #include "cli.h"
+
+@@ -305,6 +306,8 @@
+ return NULL;
+
+ p = reply;
++ p += sprintf(p, VERSION_STRING);
++ p += sprintf(p, "CLI commands reference:\n");
+
+ vector_foreach_slot (handlers, h, i) {
+ fp = h->fingerprint;
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/multipathd/cli_handlers.c
++++ multipath-tools-0.4.7/multipathd/cli_handlers.c
+@@ -71,7 +71,7 @@
+
+ c = reply;
+
+- c += snprint_multipath_topology( c, reply + maxlen - c, mpp, 2);
++ c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
+ again = ((c - reply) == (maxlen - 1));
+
+ if (again)
+@@ -92,7 +92,8 @@
+ char * reply;
+ unsigned int maxlen = INITIAL_REPLY_LEN;
+ int again = 1;
+-
++
++ get_path_layout(vecs->pathvec);
+ reply = MALLOC(maxlen);
+
+ while (again) {
+@@ -183,6 +184,7 @@
+ struct vectors * vecs = (struct vectors *)data;
+ char * param = get_keyparam(v, MAP);
+
++ get_path_layout(vecs->pathvec);
+ mpp = find_mp_by_str(vecs->mpvec, param);
+
+ if (!mpp)
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/multipathd/main.c
++++ multipath-tools-0.4.7/multipathd/main.c
+@@ -55,136 +55,29 @@
+ #include "uxclnt.h"
+ #include "cli.h"
+ #include "cli_handlers.h"
++#include "lock.h"
++#include "waiter.h"
+
+ #define FILE_NAME_SIZE 256
+ #define CMDSIZE 160
+
+ #define LOG_MSG(a,b) \
+- if (strlen(b)) condlog(a, "%s: %s", pp->dev_t, b);
+-
+-#ifdef LCKDBG
+-#define lock(a) \
+- fprintf(stderr, "%s:%s(%i) lock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
+- pthread_mutex_lock(a)
+-#define unlock(a) \
+- fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
+- pthread_mutex_unlock(a)
+-#define lock_cleanup_pop(a) \
+- fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
+- pthread_cleanup_pop(1);
+-#else
+-#define lock(a) pthread_mutex_lock(a)
+-#define unlock(a) pthread_mutex_unlock(a)
+-#define lock_cleanup_pop(a) pthread_cleanup_pop(1);
+-#endif
++ if (strlen(b)) condlog(a, "%s: %s", pp->dev, b);
+
+ pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
+ pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+ /*
+- * structs
++ * global copy of vecs for use in sig handlers
+ */
+-struct vectors * gvecs; /* global copy of vecs for use in sig handlers */
+-
+-static struct event_thread *
+-alloc_waiter (void)
+-{
+-
+- struct event_thread * wp;
+-
+- wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
+-
+- return wp;
+-}
+-
+-static void
+-free_waiter (void * data)
+-{
+- struct event_thread * wp = (struct event_thread *)data;
+-
+- /*
+- * indicate in mpp that the wp is already freed storage
+- */
+- lock(wp->vecs->lock);
+-
+- if (wp->mpp)
+- /*
+- * be careful, mpp may already be freed -- null if so
+- */
+- wp->mpp->waiter = NULL;
+- else
+- condlog(3, "free_waiter, mpp freed before wp=%p,", wp);
+-
+- unlock(wp->vecs->lock);
+-
+- if (wp->dmt)
+- dm_task_destroy(wp->dmt);
+-
+- FREE(wp);
+-}
+-
+-static void
+-stop_waiter_thread (struct multipath * mpp, struct vectors * vecs)
+-{
+- struct event_thread * wp = (struct event_thread *)mpp->waiter;
+-
+- if (!wp) {
+- condlog(3, "%s: no waiter thread", mpp->alias);
+- return;
+- }
+- condlog(2, "%s: stop event checker thread", wp->mapname);
+- pthread_kill((pthread_t)wp->thread, SIGUSR1);
+-}
+-
+-static void
+-cleanup_lock (void * data)
+-{
+- unlock((pthread_mutex_t *)data);
+-}
+-
+-/*
+- * mpp->no_path_retry:
+- * -2 (QUEUE) : queue_if_no_path enabled, never turned off
+- * -1 (FAIL) : fail_if_no_path
+- * 0 (UNDEF) : nothing
+- * >0 : queue_if_no_path enabled, turned off after polling n times
+- */
+-static void
+-update_queue_mode_del_path(struct multipath *mpp)
+-{
+- if (--mpp->nr_active == 0 && mpp->no_path_retry > 0) {
+- /*
+- * Enter retry mode.
+- * meaning of +1: retry_tick may be decremented in
+- * checkerloop before starting retry.
+- */
+- mpp->stat_queueing_timeouts++;
+- mpp->retry_tick = mpp->no_path_retry * conf->checkint + 1;
+- condlog(1, "%s: Entering recovery mode: max_retries=%d",
+- mpp->alias, mpp->no_path_retry);
+- }
+- condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
+-}
+-
+-static void
+-update_queue_mode_add_path(struct multipath *mpp)
+-{
+- if (mpp->nr_active++ == 0 && mpp->no_path_retry > 0) {
+- /* come back to normal mode from retry mode */
+- mpp->retry_tick = 0;
+- dm_queue_if_no_path(mpp->alias, 1);
+- condlog(2, "%s: queue_if_no_path enabled", mpp->alias);
+- condlog(1, "%s: Recovered to normal mode", mpp->alias);
+- }
+- condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
+-}
++struct vectors * gvecs;
+
+ static int
+ need_switch_pathgroup (struct multipath * mpp, int refresh)
+ {
+ struct pathgroup * pgp;
+ struct path * pp;
+- int i, j;
++ unsigned int i, j;
+
+ if (!mpp || mpp->pgfailback == -FAILBACK_MANUAL)
+ return 0;
+@@ -219,7 +112,8 @@
+ {
+ struct multipath * ompp;
+ vector ompv = vecs->mpvec;
+- int i, j;
++ unsigned int i;
++ int j;
+
+ vector_foreach_slot (ompv, ompp, i) {
+ if (!find_mp_by_wwid(nmpv, ompp->wwid)) {
+@@ -253,234 +147,12 @@
+ return 0;
+ }
+
+-static int
+-update_multipath (struct vectors *vecs, char *mapname)
+-{
+- struct multipath *mpp;
+- struct pathgroup *pgp;
+- struct path *pp;
+- int i, j;
+- int r = 1;
+-
+- mpp = find_mp_by_alias(vecs->mpvec, mapname);
+-
+- if (!mpp)
+- goto out;
+-
+- free_pgvec(mpp->pg, KEEP_PATHS);
+- mpp->pg = NULL;
+-
+- if (setup_multipath(vecs, mpp))
+- goto out; /* mpp freed in setup_multipath */
+-
+- /*
+- * compare checkers states with DM states
+- */
+- vector_foreach_slot (mpp->pg, pgp, i) {
+- vector_foreach_slot (pgp->paths, pp, j) {
+- if (pp->dmstate != PSTATE_FAILED)
+- continue;
+-
+- if (pp->state != PATH_DOWN) {
+- int oldstate = pp->state;
+- condlog(2, "%s: mark as failed", pp->dev_t);
+- mpp->stat_path_failures++;
+- pp->state = PATH_DOWN;
+- if (oldstate == PATH_UP ||
+- oldstate == PATH_GHOST)
+- update_queue_mode_del_path(mpp);
+-
+- /*
+- * if opportune,
+- * schedule the next check earlier
+- */
+- if (pp->tick > conf->checkint)
+- pp->tick = conf->checkint;
+- }
+- }
+- }
+- r = 0;
+-out:
+- if (r)
+- condlog(0, "failed to update multipath");
+-
+- return r;
+-}
+-
+-static sigset_t unblock_signals(void)
+-{
+- sigset_t set, old;
+-
+- sigemptyset(&set);
+- sigaddset(&set, SIGHUP);
+- sigaddset(&set, SIGUSR1);
+- pthread_sigmask(SIG_UNBLOCK, &set, &old);
+- return old;
+-}
+-
+-/*
+- * returns the reschedule delay
+- * negative means *stop*
+- */
+-static int
+-waiteventloop (struct event_thread * waiter)
+-{
+- sigset_t set;
+- int event_nr;
+- int r;
+-
+- if (!waiter->event_nr)
+- waiter->event_nr = dm_geteventnr(waiter->mapname);
+-
+- if (!(waiter->dmt = dm_task_create(DM_DEVICE_WAITEVENT))) {
+- condlog(0, "%s: devmap event #%i dm_task_create error",
+- waiter->mapname, waiter->event_nr);
+- return 1;
+- }
+-
+- if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
+- condlog(0, "%s: devmap event #%i dm_task_set_name error",
+- waiter->mapname, waiter->event_nr);
+- dm_task_destroy(waiter->dmt);
+- return 1;
+- }
+-
+- if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
+- waiter->event_nr)) {
+- condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
+- waiter->mapname, waiter->event_nr);
+- dm_task_destroy(waiter->dmt);
+- return 1;
+- }
+-
+- dm_task_no_open_count(waiter->dmt);
+-
+- /* accept wait interruption */
+- set = unblock_signals();
+-
+- /* interruption spits messages */
+- dm_shut_log();
+-
+- /* wait */
+- r = dm_task_run(waiter->dmt);
+-
+- /* wait is over : event or interrupt */
+- pthread_sigmask(SIG_SETMASK, &set, NULL);
+- //dm_restore_log();
+-
+- if (!r) /* wait interrupted by signal */
+- return -1;
+-
+- dm_task_destroy(waiter->dmt);
+- waiter->dmt = NULL;
+- waiter->event_nr++;
+-
+- /*
+- * upon event ...
+- */
+- while (1) {
+- condlog(3, "%s: devmap event #%i",
+- waiter->mapname, waiter->event_nr);
+-
+- /*
+- * event might be :
+- *
+- * 1) a table reload, which means our mpp structure is
+- * obsolete : refresh it through update_multipath()
+- * 2) a path failed by DM : mark as such through
+- * update_multipath()
+- * 3) map has gone away : stop the thread.
+- * 4) a path reinstate : nothing to do
+- * 5) a switch group : nothing to do
+- */
+- pthread_cleanup_push(cleanup_lock, waiter->vecs->lock);
+- lock(waiter->vecs->lock);
+- r = update_multipath(waiter->vecs, waiter->mapname);
+- lock_cleanup_pop(waiter->vecs->lock);
+-
+- if (r)
+- return -1; /* stop the thread */
+-
+- event_nr = dm_geteventnr(waiter->mapname);
+-
+- if (waiter->event_nr == event_nr)
+- return 1; /* upon problem reschedule 1s later */
+-
+- waiter->event_nr = event_nr;
+- }
+- return -1; /* never reach there */
+-}
+-
+-static void *
+-waitevent (void * et)
+-{
+- int r;
+- struct event_thread *waiter;
+-
+- mlockall(MCL_CURRENT | MCL_FUTURE);
+-
+- waiter = (struct event_thread *)et;
+- pthread_cleanup_push(free_waiter, et);
+-
+- while (1) {
+- r = waiteventloop(waiter);
+-
+- if (r < 0)
+- break;
+-
+- sleep(r);
+- }
+-
+- pthread_cleanup_pop(1);
+- return NULL;
+-}
+-
+-static int
+-start_waiter_thread (struct multipath * mpp, struct vectors * vecs)
+-{
+- pthread_attr_t attr;
+- struct event_thread * wp;
+-
+- if (!mpp)
+- return 0;
+-
+- if (pthread_attr_init(&attr))
+- goto out;
+-
+- pthread_attr_setstacksize(&attr, 32 * 1024);
+- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+-
+- wp = alloc_waiter();
+-
+- if (!wp)
+- goto out;
+-
+- mpp->waiter = (void *)wp;
+- strncpy(wp->mapname, mpp->alias, WWID_SIZE);
+- wp->vecs = vecs;
+- wp->mpp = mpp;
+-
+- if (pthread_create(&wp->thread, &attr, waitevent, wp)) {
+- condlog(0, "%s: cannot create event checker", wp->mapname);
+- goto out1;
+- }
+- condlog(2, "%s: event checker started", wp->mapname);
+-
+- return 0;
+-out1:
+- free_waiter(wp);
+- mpp->waiter = NULL;
+-out:
+- condlog(0, "failed to start waiter thread");
+- return 1;
+-}
+-
+ static void
+ sync_map_state(struct multipath *mpp)
+ {
+- int i, j;
+ struct pathgroup *pgp;
+ struct path *pp;
++ unsigned int i, j;
+
+ vector_foreach_slot (mpp->pg, pgp, i){
+ vector_foreach_slot (pgp->paths, pp, j){
+@@ -502,7 +174,7 @@
+ static void
+ sync_maps_state(vector mpvec)
+ {
+- int i;
++ unsigned int i;
+ struct multipath *mpp;
+
+ vector_foreach_slot (mpvec, mpp, i)
+@@ -863,7 +535,7 @@
+ }
+ sync_map_state(mpp);
+
+- condlog(3, "%s path removed from devmap %s",
++ condlog(3, "%s: path removed from map %s",
+ devname, mpp->alias);
+ }
+ free_pathvec(rpvec, KEEP_PATHS);
+@@ -898,8 +570,8 @@
+ static int
+ map_discovery (struct vectors * vecs)
+ {
+- int i;
+ struct multipath * mpp;
++ unsigned int i;
+
+ if (dm_get_maps(vecs->mpvec, "multipath"))
+ return 1;
+@@ -1129,7 +801,7 @@
+ mpvec_garbage_collector (struct vectors * vecs)
+ {
+ struct multipath * mpp;
+- int i;
++ unsigned int i;
+
+ vector_foreach_slot (vecs->mpvec, mpp, i) {
+ if (mpp && mpp->alias && !dm_map_present(mpp->alias)) {
+@@ -1144,7 +816,7 @@
+ defered_failback_tick (vector mpvec)
+ {
+ struct multipath * mpp;
+- int i;
++ unsigned int i;
+
+ vector_foreach_slot (mpvec, mpp, i) {
+ /*
+@@ -1163,7 +835,7 @@
+ retry_count_tick(vector mpvec)
+ {
+ struct multipath *mpp;
+- int i;
++ unsigned int i;
+
+ vector_foreach_slot (mpvec, mpp, i) {
+ if (mpp->retry_tick) {
+@@ -1182,8 +854,9 @@
+ {
+ struct vectors *vecs;
+ struct path *pp;
+- int i, count = 0;
++ int count = 0;
+ int newstate;
++ unsigned int i;
+
+ mlockall(MCL_CURRENT | MCL_FUTURE);
+ vecs = (struct vectors *)ap;
+@@ -1351,10 +1024,10 @@
+ vector mpvec;
+ int i;
+
+- if (!(vecs->pathvec = vector_alloc()))
++ if (!vecs->pathvec && !(vecs->pathvec = vector_alloc()))
+ return 1;
+
+- if (!(vecs->mpvec = vector_alloc()))
++ if (!vecs->mpvec && !(vecs->mpvec = vector_alloc()))
+ return 1;
+
+ if (!(mpvec = vector_alloc()))
+@@ -1406,6 +1079,7 @@
+ /*
+ * save new set of maps formed by considering current path state
+ */
++ vector_free(vecs->mpvec);
+ vecs->mpvec = mpvec;
+
+ /*
+@@ -1435,6 +1109,7 @@
+ if (VECTOR_SIZE(vecs->pathvec))
+ free_pathvec(vecs->pathvec, FREE_PATHS);
+
++ vecs->pathvec = NULL;
+ conf = NULL;
+
+ if (load_config(DEFAULT_CONFIGFILE))
+@@ -1467,24 +1142,10 @@
+ if (!vecs->lock)
+ goto out;
+
+- vecs->pathvec = vector_alloc();
+-
+- if (!vecs->pathvec)
+- goto out1;
+-
+- vecs->mpvec = vector_alloc();
+-
+- if (!vecs->mpvec)
+- goto out2;
+-
+ pthread_mutex_init(vecs->lock, NULL);
+
+ return vecs;
+
+-out2:
+- vector_free(vecs->pathvec);
+-out1:
+- FREE(vecs->lock);
+ out:
+ FREE(vecs);
+ condlog(0, "failed to init paths");
+@@ -1543,7 +1204,7 @@
+ signal_set(SIGUSR1, sigusr1);
+ signal_set(SIGINT, sigend);
+ signal_set(SIGTERM, sigend);
+- signal_set(SIGKILL, sigend);
++ signal(SIGPIPE, SIG_IGN);
+ }
+
+ static void
+@@ -1551,7 +1212,7 @@
+ {
+ int res;
+ static struct sched_param sched_param = {
+- sched_priority: 99
++ .sched_priority = 99
+ };
+
+ res = sched_setscheduler (0, SCHED_RR, &sched_param);
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/multipathd/multipathd.8
++++ multipath-tools-0.4.7/multipathd/multipathd.8
+@@ -1,4 +1,4 @@
+-.TH MULTIPATHD 8 "October 2004" "Linux Administrator's Manual"
++.TH MULTIPATHD 8 "July 2006" "Linux Administrator's Manual"
+ .SH NAME
+ multipathd \- multipath daemon
+ .SH SYNOPSYS
+@@ -6,10 +6,10 @@
+
+ This daemon is in charge of checking for failed paths. When this happens,
+ it will reconfigure the multipath map the path belongs to, so that this map
+-regain its maximum performance and redundancy.
++regains its maximum performance and redundancy.
+
+ This daemon executes the external multipath config tool when events occur.
+-In turn, the multipath tool signals the multipathd daemon it is done with
++In turn, the multipath tool signals the multipathd daemon when it is done with
+ devmap reconfiguration, so that it can refresh its failed path list.
+
+ .SH "SEE ALSO"
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/devmap_name/devmap_name.8
++++ multipath-tools-0.4.7/devmap_name/devmap_name.8
+@@ -1,4 +1,4 @@
+-.TH DEVMAP_NAME 8 "February 2004" "" "Linux Administrator's Manual"
++.TH DEVMAP_NAME 8 "July 2006" "" "Linux Administrator's Manual"
+ .SH NAME
+ devmap_name \- Query device-mapper name
+ .SH SYNOPSIS
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libcheckers/checkers.h
++++ multipath-tools-0.4.7/libcheckers/checkers.h
+@@ -20,6 +20,21 @@
+ #define DEFAULT_CHECKER READSECTOR0
+
+ /*
++ * Overloaded storage response time can be very long.
++ * SG_IO timouts after DEF_TIMEOUT milliseconds, and checkers interprets this
++ * as a path failure. multipathd then proactively evicts the path from the DM
++ * multipath table in this case.
++ *
++ * This generaly snow balls and ends up in full eviction and IO errors for end
++ * users. Bad. This may also cause SCSI bus resets, causing disruption for all
++ * local and external storage hardware users.
++ *
++ * Provision a long timeout. Longer than any real-world application would cope
++ * with.
++ */
++#define DEF_TIMEOUT 300000
++
++/*
+ * strings lengths
+ */
+ #define CHECKER_NAME_LEN 16
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libcheckers/emc_clariion.c
++++ multipath-tools-0.4.7/libcheckers/emc_clariion.c
+@@ -57,7 +57,7 @@
+ io_hdr.dxferp = sense_buffer;
+ io_hdr.cmdp = inqCmdBlk;
+ io_hdr.sbp = sb;
+- io_hdr.timeout = 60000;
++ io_hdr.timeout = DEF_TIMEOUT;
+ io_hdr.pack_id = 0;
+ if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
+ MSG(c, "emc_clariion_checker: sending query command failed");
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libcheckers/hp_sw.c
++++ multipath-tools-0.4.7/libcheckers/hp_sw.c
+@@ -19,7 +19,6 @@
+ #define INQUIRY_CMDLEN 6
+ #define INQUIRY_CMD 0x12
+ #define SENSE_BUFF_LEN 32
+-#define DEF_TIMEOUT 60000
+ #define SCSI_CHECK_CONDITION 0x2
+ #define SCSI_COMMAND_TERMINATED 0x22
+ #define SG_ERR_DRIVER_SENSE 0x08
+@@ -111,7 +110,7 @@
+ io_hdr.dxfer_direction = SG_DXFER_NONE;
+ io_hdr.cmdp = turCmdBlk;
+ io_hdr.sbp = sense_buffer;
+- io_hdr.timeout = 20000;
++ io_hdr.timeout = DEF_TIMEOUT;
+ io_hdr.pack_id = 0;
+
+ if (ioctl(fd, SG_IO, &io_hdr) < 0)
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libcheckers/readsector0.c
++++ multipath-tools-0.4.7/libcheckers/readsector0.c
+@@ -16,7 +16,6 @@
+ #include "../libmultipath/sg_include.h"
+
+ #define SENSE_BUFF_LEN 32
+-#define DEF_TIMEOUT 60000
+
+ #define MSG_READSECTOR0_UP "readsector0 checker reports path is up"
+ #define MSG_READSECTOR0_DOWN "readsector0 checker reports path is down"
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/libcheckers/tur.c
++++ multipath-tools-0.4.7/libcheckers/tur.c
+@@ -51,7 +51,7 @@
+ io_hdr.dxfer_direction = SG_DXFER_NONE;
+ io_hdr.cmdp = turCmdBlk;
+ io_hdr.sbp = sense_buffer;
+- io_hdr.timeout = 20000;
++ io_hdr.timeout = DEF_TIMEOUT;
+ io_hdr.pack_id = 0;
+ if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
+ MSG(c, MSG_TUR_DOWN);
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/Makefile
++++ multipath-tools-0.4.7/Makefile
+@@ -22,7 +22,11 @@
+
+ BUILDDIRS = $(shell find . -mindepth 2 -name Makefile -exec dirname {} \; | grep -v ^lib)
+
++ifeq ($(MULTIPATH_VERSION),)
+ VERSION = $(shell basename ${PWD} | cut -d'-' -f3)
++else
++VERSION = $(MULTIPATH_VERSION)
++endif
+
+ all: recurse
+
+only in patch2:
+unchanged:
+--- multipath-tools-0.4.7.orig/multipath-tools.spec.in
++++ multipath-tools-0.4.7/multipath-tools.spec.in
+@@ -50,6 +50,7 @@
+ %{prefix}/sbin/mpath_prio_balance_units
+ %{prefix}/sbin/mpath_prio_netapp
+ %{prefix}/sbin/mpath_prio_tpc
++%{prefix}/sbin/mpath_prio_hds_modular
+ %{prefix}/usr/share/man/man8/devmap_name.8.gz
+ %{prefix}/usr/share/man/man8/multipath.8.gz
+ %{prefix}/usr/share/man/man8/kpartx.8.gz
+
+-- System Information:
+Debian Release: testing/unstable
+ APT prefers unstable
+ APT policy: (500, 'unstable')
+Architecture: i386 (i686)
+Shell: /bin/sh linked to /bin/bash
+Kernel: Linux 2.6.17.2
+Locale: LANG=C, LC_CTYPE=en_US (charmap=ISO-8859-1)
+
+
+
Added: multipath-tools/trunk/debian/patches/series
==============================================================================
--- (empty file)
+++ multipath-tools/trunk/debian/patches/series Wed Dec 20 10:52:01 2006
@@ -0,0 +1,2 @@
+git-40b575955cc189aa993e6a030b66b5fef6bcf288.patch
+exclude-quilt
Modified: multipath-tools/trunk/debian/rules
==============================================================================
--- multipath-tools/trunk/debian/rules (original)
+++ multipath-tools/trunk/debian/rules Wed Dec 20 10:52:01 2006
@@ -1,21 +1,25 @@
#!/usr/bin/make -f
+include /usr/share/quilt/quilt.make
+
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
build: build-stamp
-build-stamp:
+build-stamp: patch
dh_testdir
$(MAKE)
touch $@
-clean:
+clean: unpatch
dh_testdir
rm -f build-stamp
-$(MAKE) clean
+ # work around Makefile not cleaning up everything:
+ rm -rf path_priority/pp_hds_modular/
dh_clean
More information about the pkg-lvm-commits
mailing list