--- multipath-tools-0.4.7.orig/path_priority/pp_random/Makefile +++ multipath-tools-0.4.7/path_priority/pp_random/Makefile @@ -14,7 +14,8 @@ $(CC) -static -o $(EXEC) $(OBJS) install: $(EXEC) - install -s -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) + install -d $(DESTDIR)$(bindir) + install -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) uninstall: rm $(DESTDIR)$(bindir)/$(EXEC) --- multipath-tools-0.4.7.orig/path_priority/pp_alua/Makefile +++ multipath-tools-0.4.7/path_priority/pp_alua/Makefile @@ -36,7 +36,7 @@ $(CC) -static -o $(EXEC) $(OBJS) install: $(BUILD) $(EXEC).8.gz - $(INSTALL) -s -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) + $(INSTALL) -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) $(INSTALL) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)/$(EXEC).8.gz uninstall: --- 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. --- 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 --- 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 */ --- 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 (optinddev_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", --- 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 + * + * This file is released under the GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* 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] \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 \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); +} + --- 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) --- 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: --- 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); --- 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, --- 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; --- 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); +} --- 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; --- 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 */ --- multipath-tools-0.4.7.orig/libmultipath/defaults.h +++ multipath-tools-0.4.7/libmultipath/defaults.h @@ -1,4 +1,4 @@ -#define DEFAULT_GETUID "/sbin/scsi_id -g -u -s /block/%n" +#define DEFAULT_GETUID "/lib/udev/scsi_id -g -u -s /block/%n" #define DEFAULT_UDEVDIR "/dev" #define DEFAULT_SELECTOR "round-robin 0" #define DEFAULT_FEATURES "0" --- 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); --- 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; --- 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); --- 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); +} + --- 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); --- 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); --- 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 */ --- 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 --- 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 */ --- 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); } --- 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); --- multipath-tools-0.4.7.orig/libmultipath/devmapper.c +++ multipath-tools-0.4.7/libmultipath/devmapper.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -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)) --- 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; } --- 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@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@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@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@free.fr @@ -120,7 +126,7 @@ .checker_name = READSECTOR0, }, /* - * EMC / Clariion controler family + * EMC / Clariion controller family * * Maintainer : Edward Goggin, EMC * Mail : egoggin@emc.com @@ -128,7 +134,7 @@ { .vendor = "EMC", .product = "SYMMETRIX", - .getuid = "/sbin/scsi_id -g -u -ppre-spc3-83 -s /block/%n", + .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 -s /block/%n", .getprio = NULL, .features = DEFAULT_FEATURES, .hwhandler = DEFAULT_HWHANDLER, @@ -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@free.fr @@ -178,14 +184,14 @@ .checker_name = READSECTOR0, }, /* - * Hitachi controler family + * Hitachi controller family * - * Maintainer : Christophe Varoqui - * Mail : christophe.varoqui@free.fr + * Maintainer : Matthias Rudolph + * Mail : matthias.rudolph@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@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@netapp.com + * Maintainer : Dave Wysochanski + * Mail : davidw@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@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@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, --- 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) --- 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) --- multipath-tools-0.4.7.orig/libmultipath/lock.c +++ multipath-tools-0.4.7/libmultipath/lock.c @@ -0,0 +1,8 @@ +#include +#include "lock.h" + +void cleanup_lock (void * data) +{ + unlock((pthread_mutex_t *)data); +} + --- 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 */ --- 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 */ --- 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 +#include +#include +#include +#include + +#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; +} + --- 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 */ --- multipath-tools-0.4.7.orig/multipath/multipath.rules +++ multipath-tools-0.4.7/multipath/multipath.rules @@ -2,17 +2,27 @@ # multipath and multipath partitions nodes are created in /dev/mapper/ # this file should be installed in /etc/udev/rules.d # -# !! udev must not discard DM events !! -# !! check the other installed rules !! -# -# lookup the devmap name -#ACTION=="add", SUBSYSTEM=="block", KERNEL=="dm-*", \ -# PROGRAM="/sbin/devmap_name %M %m" -ACTION=="add", SUBSYSTEM=="block", KERNEL=="dm-*", \ - PROGRAM="/sbin/dmsetup -j %M -m %m --noopencount --noheadings -c -o name info" +## take care to inizialize HSG80 disks when configured in multibus failover +# old kernels reports 2097152 (10GB) size on the passive path +ACTION=="add", SUBSYSTEM=="block", \ + ATTRS{model}=="HSG80", ATTRS{size}=="2097152", \ + RUN+="/sbin/hsg80_start %k", \ + GOTO="nomultipath" + +# new kernels report 0 size on the passive path +ACTION=="add", SUBSYSTEM=="block", \ + ATTRS{model}=="HSG80", ATTRS{size}=="0", \ + RUN+="/sbin/hsg80_start %k", \ + GOTO="nomultipath" + +# call multipath -v 0 to add devices as they appear +ACTION=="add|change", SUBSYSTEM=="block", \ + RUN+="/sbin/multipath -v 0 /dev/%k" + +LABEL="nomultipath" # take care of devmap partitioning -ACTION=="add", SUBSYSTEM=="block", KERNEL=="dm-*", \ +ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="dm-*", \ + PROGRAM="/sbin/dmsetup -j %M -m %m --noopencount --noheadings -c -o name info", \ RUN+="/sbin/kpartx -a /dev/mapper/%c" - --- multipath-tools-0.4.7.orig/multipath/main.c +++ multipath-tools-0.4.7/multipath/main.c @@ -46,8 +46,7 @@ #include #include #include - -#include "main.h" +#include 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; --- multipath-tools-0.4.7.orig/multipath/02_multipath +++ multipath-tools-0.4.7/multipath/02_multipath @@ -12,10 +12,10 @@ # feed the dependencies too # scsi_id is dynamicaly linked, so store the libs too # -cp /sbin/scsi_id $INITRDDIR/sbin +cp /lib/udev/scsi_id $INITRDDIR/sbin cp /bin/mountpoint $INITRDDIR/bin -PROGS="/sbin/scsi_id /bin/mountpoint" +PROGS="/lib/udev/scsi_id /bin/mountpoint" LIBS=`ldd $PROGS | grep -v linux-gate.so | sort -u | \ awk '{print $3}'` for i in $LIBS --- multipath-tools-0.4.7.orig/multipath/Makefile +++ multipath-tools-0.4.7/multipath/Makefile @@ -39,9 +39,9 @@ install: install -d $(DESTDIR)$(bindir) - install -s -m 755 $(EXEC) $(DESTDIR)$(bindir)/ - install -d $(DESTDIR)/etc/udev/rules.d - install -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/ + install -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + install -d $(DESTDIR)/etc/udev + install -m 644 multipath.rules $(DESTDIR)/etc/udev/ install -d $(DESTDIR)$(mandir) install -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) --- 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. --- multipath-tools-0.4.7.orig/multipath/multipath.sh +++ multipath-tools-0.4.7/multipath/multipath.sh @@ -0,0 +1,14 @@ +#!/bin/sh -e + +if [ ! "${ACTION}" = add ] ; then + exit +fi + +if [ "${1:0:3}" = "dm-" ] ; then + dev=$( #include #include - -#if defined(__hppa__) || defined(__powerpc64__) || defined (__alpha__) \ - || defined (__x86_64__) -typedef unsigned long __kernel_old_dev_t; -#elif defined(__powerpc__) || defined(__ia64__) -typedef unsigned int __kernel_old_dev_t; -#else -typedef unsigned short __kernel_old_dev_t; -#endif - -#define dev_t __kernel_old_dev_t +#include #include #include "lopart.h" #include "xstrncpy.h" -#if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \ - && !defined (__s390x__) -#define int2ptr(x) ((void *) ((int) x)) -#else -#define int2ptr(x) ((void *) ((long) x)) -#endif +#define int2ptr(x) ((void *) ((uintptr_t) x)) static char * xstrdup (const char *s) --- 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, --- multipath-tools-0.4.7.orig/kpartx/devmapper.c +++ multipath-tools-0.4.7/kpartx/devmapper.c @@ -7,6 +7,10 @@ #include #include #include +#include + +#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; +} --- 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); --- 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 --- multipath-tools-0.4.7.orig/multipath.conf.synthetic +++ multipath-tools-0.4.7/multipath.conf.synthetic @@ -7,7 +7,7 @@ # polling_interval 10 # selector "round-robin 0" # path_grouping_policy multibus -# getuid_callout "/sbin/scsi_id -g -u -s /block/%n" +# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" # prio_callout /bin/true # path_checker readsector0 # rr_min_io 100 @@ -48,7 +48,7 @@ # vendor "COMPAQ " # product "HSV110 (C)COMPAQ" # path_grouping_policy multibus -# getuid_callout "/sbin/scsi_id -g -u -s /block/%n" +# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" # path_checker readsector0 # path_selector "round-robin 0" # hardware_handler "0" --- multipath-tools-0.4.7.orig/multipath.conf.annotated +++ multipath-tools-0.4.7/multipath.conf.annotated @@ -11,7 +11,7 @@ # # # # name : udev_dir # # desc : directory where udev creates its device nodes -# # default : /udev +# # default : /dev # # # udev_dir /dev # @@ -47,9 +47,9 @@ # # scope : multipath # # desc : the default program and args to callout to obtain a unique # # path identifier. Absolute path required -# # default : /sbin/scsi_id -g -u -s +# # default : /lib/udev/scsi_id -g -u -s # # -# getuid_callout "/sbin/scsi_id -g -u -s /block/%n" +# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" # # # # # name : prio_callout @@ -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 @@ -275,9 +275,9 @@ # # scope : multipath # # desc : the program and args to callout to obtain a unique # # path identifier. Absolute path required -# # default : /sbin/scsi_id -g -u -s +# # default : /lib/udev/scsi_id -g -u -s # # -# getuid_callout "/sbin/scsi_id -g -u -s /block/%n" +# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" # # # # # name : prio_callout --- 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" --- multipath-tools-0.4.7.orig/multipathd/cli.c +++ multipath-tools-0.4.7/multipathd/cli.c @@ -4,6 +4,7 @@ #include #include #include +#include #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; --- 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); --- 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) --- multipath-tools-0.4.7.orig/multipathd/uxlsnr.c +++ multipath-tools-0.4.7/multipathd/uxlsnr.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -93,11 +94,16 @@ int ux_sock; size_t len; int rlen; + mode_t mask; char *inbuf; char *reply; + mask=umask(0177); + ux_sock = ux_socket_listen(DEFAULT_SOCKET); + umask(mask); + if (ux_sock == -1) { condlog(0, "ux_socket_listen error"); exit(1); --- 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 --- 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) --- 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"); --- 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); --- 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" --- 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 --- 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 --- multipath-tools-0.4.7.orig/debian/changelog +++ multipath-tools-0.4.7/debian/changelog @@ -0,0 +1,222 @@ +multipath-tools (0.4.7-1.1ubuntu3) feisty; urgency=low + + * Remove multipath-tools-boot init script. + + * Wild changes and updates to udev rules: + - All the hsg80 MULTIBUS FAILOVER are now handled here. + - Fix rule to call kpartx also on "change" udev events. + - Invoke multipath -v 0 device to make sure we hot plug + all devices into multipath. + + * Add /sbin/hsg80_start that wraps all the work to make an hsg80 in + MULTIBUS FAILOVER working properly. + This is automatically called by udev. + + (Closes LP: #98518) + + -- Fabio M. Di Nitto Wed, 04 Apr 2007 08:17:48 +0200 + +multipath-tools (0.4.7-1.1ubuntu2) feisty; urgency=low + + * Remove devmap_name from this package, and Depend on dmsetup instead. + Fixes file overwrite conflict with dmsetup. (LP 84894.) + + -- Ian Jackson Tue, 13 Feb 2007 16:16:46 +0000 + +multipath-tools (0.4.7-1.1ubuntu1) feisty; urgency=low + + * Merge from debian unstable, remaining changes: + - remove stop links from rc0 and rc6 + - suggest sg3-utils, conflict sg-utils + - fix path to scsi_id + - ubuntu udev rules + - set umask + + -- Scott James Remnant Tue, 28 Nov 2006 15:24:16 +0000 + +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 Wed, 9 Aug 2006 11:52:08 -0500 + +multipath-tools (0.4.7-1ubuntu8) edgy; urgency=low + + * Remove stop script symlinks from rc0 and rc6. + + -- Scott James Remnant Fri, 15 Sep 2006 17:30:19 +0100 + +multipath-tools (0.4.7-1ubuntu7) dapper; urgency=low + + * Fix typo in init script that was executing hsg80_init unconditionally. + + * Suggests: sg3-utils and Conflicts: sg-utils (obsoleted). + + -- Fabio M. Di Nitto Mon, 22 May 2006 09:56:07 +0200 + +multipath-tools (0.4.7-1ubuntu6) dapper; urgency=low + + * no changes upload to rebuild with new libdevmapper. + + -- Fabio M. Di Nitto Wed, 10 May 2006 09:31:20 +0200 + +multipath-tools (0.4.7-1ubuntu5) dapper; urgency=low + + The "give Scott a crying biscuit" release. + + * Apply patch from Dennis Kaarsemaker. + (Closes Ubuntu: #41318) + + -- Fabio M. Di Nitto Wed, 26 Apr 2006 10:20:07 +0200 + +multipath-tools (0.4.7-1ubuntu4) dapper; urgency=low + + * Remove 2 extra lines from multipath.rules that were really not supposed + to be there. + + -- Fabio M. Di Nitto Thu, 06 Apr 2006 17:43:10 +0200 + +multipath-tools (0.4.7-1ubuntu3) dapper; urgency=low + + * Add hsg80_init function to multipath-tools-boot init script. + The script takes care to perform a proper initialization of the disks + when the hsg80 is configured in multibus failover mode. + + NOTE: multipathd is not able to understand properly what happens in this + multi-bugs situation and it will require manual kill and restart once + the disks have been readded to the system, otherwise failover is not + guaranteed and syslog will be flooded. + + -- Fabio M. Di Nitto Thu, 06 Apr 2006 09:33:51 +0200 + +multipath-tools (0.4.7-1ubuntu2) dapper; urgency=low + + * Fix socket permissions. + + -- Fabio M. Di Nitto Tue, 04 Apr 2006 18:20:20 +0200 + +multipath-tools (0.4.7-1ubuntu1) dapper; urgency=low + + * Fix path to scsi_id. + + * Make install: target depends on build in debian/rules. + + * Change NAME to multipathd in init scripts so that we can actually stop + multipathd. + + * Swap multipath-tools-boot and multipath-tools init scripts order in + postinst and make multipath-tools-boot start. + + * UVF exception granted by Colin Watson. + + -- Fabio M. Di Nitto Tue, 04 Apr 2006 06:31:09 +0200 + +multipath-tools (0.4.7-1) unstable; urgency=low + + * New upstream version. + - Build against libsysfs2. (closes: #355775) + * Acknowledge NMU. (closes: #337081) + + -- Bastian Blank Fri, 17 Mar 2006 17:23:03 +0100 + +multipath-tools (0.4.6-1) unstable; urgency=low + + * New upstream version. + + -- Bastian Blank Thu, 09 Feb 2006 22:12:52 +0100 + +multipath-tools (0.4.5-3) unstable; urgency=low + + * Fix kpartx compiling errors and dos support. + + -- Bastian Blank Fri, 30 Sep 2005 13:01:55 +0200 + +multipath-tools (0.4.5-2) unstable; urgency=low + + * Move boot init script before udev and load dm-multipath module. + + -- Bastian Blank Wed, 28 Sep 2005 19:35:49 +0200 + +multipath-tools (0.4.5-1) unstable; urgency=low + + * New upstream version. + * Move device check logic to udev rules. + * Don't longer create devices in /dev by default. + + -- Bastian Blank Mon, 19 Sep 2005 16:32:00 +0200 + +multipath-tools (0.4.2.4-2) unstable; urgency=medium + + * New maintainer. + * Rebuild against new libdevmapper. + + -- Bastian Blank Fri, 04 Mar 2005 15:16:30 +0100 + +multipath-tools (0.4.2.4-1) unstable; urgency=low + + * New upstream. + NOTE: This is actually upstream's 0.4.2 but 0.4.2.3 came first for some + reason. + * Use start-stop-daemon to control the multipathd daemon and do it's own + PID file handling (which is now commented out of the daemon itself) + + -- Patrick Caulfield Fri, 28 Jan 2005 15:15:01 +0000 + +multipath-tools (0.4.2.3-1) unstable; urgency=low + + * New upstream + * Remove initrd files as they break things. + Closes: #288150 + * Fix some duplicate patching. + + -- Patrick Caulfield Mon, 17 Jan 2005 11:19:20 +0000 + +multipath-tools (0.4.1-1) unstable; urgency=low + + * New upstream + Closes: #295926, #286789 + * Include initrd scripts contributed by Guido Guenther + Closes: #286791 + + -- Patrick Caulfield Thu, 13 Jan 2005 09:25:42 +0000 + +multipath-tools (0.4.0-1) unstable; urgency=low + + * New upstream + + -- Patrick Caulfield Fri, 24 Dec 2004 11:54:44 +0000 + +multipath-tools (0.3.9-1) unstable; urgency=low + + * New upstream + + -- Patrick Caulfield Tue, 7 Dec 2004 13:15:15 +0000 + +multipath-tools (0.3.8-1) unstable; urgency=low + + * New upstream + * Fix error in preinst, when upgrading. + * Don't clean klibc directory. + Closes: #283043 + + -- Patrick Caulfield Mon, 29 Nov 2004 08:56:50 +0000 + +multipath-tools (0.3.7-1) unstable; urgency=low + + * New upstream + + -- Patrick Caulfield Sat, 13 Nov 2004 11:14:35 +0000 + +multipath-tools (0.3.6-1) unstable; urgency=low + + * Initial upload. Based loosely on upstream's work + Closes: #277898 + + -- Patrick Caulfield Wed, 3 Nov 2004 10:16:34 +0000 + --- multipath-tools-0.4.7.orig/debian/hsg80_start +++ multipath-tools-0.4.7/debian/hsg80_start @@ -0,0 +1,37 @@ +#!/bin/sh + +device="$1" + +# checking proper invocation and if we have the tools to work. +# sfdisk is part of util-linux (Essential: yes) +if [ -z "$device" ] || ! which sg_start > /dev/null; then + exit 0 +fi + +# wait maximum 1 minute for a device to appear in /dev +slumber=600 +while [ ${slumber} -gt 0 -a ! -b /dev/$device ]; do + sleep 0.1 + slumber=$(( ${slumber} - 1 )) +done + +# if the device finally exists start it. +if [ -b /dev/$device ]; then + if ! sg_turs /dev/$device > /dev/null 2>&1; then + # start the device and wait for it + sg_start --imm=0 --start /dev/$device + sleep 2 + fi + # rescan the device + echo 1 > /sys/block/$device/device/rescan + # rescan partition table + if which sfdisk > /dev/null; then + sfdisk -R /dev/$device + fi + # this is harsh but multipathd needs a hard restart + kill -9 $(pidof /sbin/multipathd) || true + multipath -v 0 /dev/$device + invoke-rc.d multipath-tools start > /dev/null 2>&1 || true +fi + +exit 0 --- multipath-tools-0.4.7.orig/debian/NEWS +++ multipath-tools-0.4.7/debian/NEWS @@ -0,0 +1,11 @@ +multipath-tools (0.4.5-1) unstable; urgency=low + + * This version removes creation of devices via udev in /dev. All + device-mapper devices are created by libdevmapper in /dev/mapper. + + To readd the creation of devices in /dev, add the following line to + the udev rules (e.g. /etc/udev/rules.d/multipath.rules): + KERNEL=="dm-[0-9]*", PROGRAM="/sbin/devmap_name %M %m", NAME="%k", SYMLINK="%c", OPTIONS+="last_rule" + + -- Bastian Blank Mon, 19 Sep 2005 15:03:31 +0200 + --- multipath-tools-0.4.7.orig/debian/copyright +++ multipath-tools-0.4.7/debian/copyright @@ -0,0 +1,12 @@ +This is the Debian GNU/Linux prepackaged version of multipath-tools. + +Copyright (C) 2003,2004 Christophe Varoqui + +multipath-tools is licensed under the GNU GPL version 2. +libsysfs is licensed under the GNU LGPL version 2.1 or later. +libdevmapper is licensed under the GNU LGPL version 2. + +On Debian systems, the complete text of the GNU General Public License +and of the GNU Lesser Public License can be found in +/usr/share/common-licenses/GPL and /usr/share/common-licenses/LGPL . + --- multipath-tools-0.4.7.orig/debian/rules +++ multipath-tools-0.4.7/debian/rules @@ -0,0 +1,59 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +build: build-stamp +build-stamp: + dh_testdir + + $(MAKE) + + touch $@ + +clean: + dh_testdir + rm -f build-stamp + + -$(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp + mkdir debian/tmp/etc/udev/rules.d + mv debian/tmp/etc/udev/multipath.rules debian/tmp/etc/udev/rules.d/85-multipath.rules + cp debian/hsg80_start debian/tmp/sbin/hsg80_start + chmod 755 debian/tmp/sbin/hsg80_start + dh_install --sourcedir=$(CURDIR)/debian/tmp -X devmap_name + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples + dh_installinit -pmultipath-tools -- multiuser + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: binary binary-arch binary-indep unpack configure build clean --- multipath-tools-0.4.7.orig/debian/compat +++ multipath-tools-0.4.7/debian/compat @@ -0,0 +1 @@ +4 --- multipath-tools-0.4.7.orig/debian/control +++ multipath-tools-0.4.7/debian/control @@ -0,0 +1,16 @@ +Source: multipath-tools +Section: admin +Priority: extra +Maintainer: Debian LVM Team +Uploaders: Bastian Blank , Andres Salomon +Build-Depends: debhelper (>> 4.0.0), po-debconf, libdevmapper-dev (>= 2:1.01.0), libsysfs-dev, libreadline5-dev +Standards-Version: 3.6.1 + +Package: multipath-tools +Architecture: any +Suggests: sg3-utils +Conflicts: sg-utils +Depends: ${shlibs:Depends}, ${misc:Depends}, udev (>> 0.070), initscripts (>= 2.85-16), dmsetup, sysv-rc (>= 2.86.ds1-14.1ubuntu2) +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. --- multipath-tools-0.4.7.orig/debian/multipath-tools.examples +++ multipath-tools-0.4.7/debian/multipath-tools.examples @@ -0,0 +1,2 @@ +multipath.conf.annotated +multipath.conf.synthetic --- multipath-tools-0.4.7.orig/debian/multipath-tools.docs +++ multipath-tools-0.4.7/debian/multipath-tools.docs @@ -0,0 +1,2 @@ +FAQ +README --- multipath-tools-0.4.7.orig/debian/multipath-tools.preinst +++ multipath-tools-0.4.7/debian/multipath-tools.preinst @@ -0,0 +1,35 @@ +#! /bin/sh +# preinst script for multipath-tools + +set -e + +case "$1" in + install) + ;; + + upgrade) + if dpkg --compare-versions "$2" lt "0.4.5-1"; then + [ -e /etc/rcS.d/S04multipath-tools ] && rm /etc/rcS.d/S04multipath-tools + fi + if dpkg --compare-versions "$2" lt "0.4.5-2"; then + [ -e /etc/rcS.d/S05multipath-tools-boot ] && rm /etc/rcS.d/S05multipath-tools-boot + fi + if dpkg --compare-versions "$2" lt "0.4.7-1.1ubuntu3"; then + [ -e /etc/rcS.d/S03multipath-tools-boot ] && rm /etc/rcS.d/S03multipath-tools-boot + fi + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 + + --- multipath-tools-0.4.7.orig/debian/multipath-tools.install +++ multipath-tools-0.4.7/debian/multipath-tools.install @@ -0,0 +1,2 @@ +etc +sbin --- multipath-tools-0.4.7.orig/debian/multipath-tools.init +++ multipath-tools-0.4.7/debian/multipath-tools.init @@ -0,0 +1,45 @@ +#! /bin/sh + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/sbin/multipathd +NAME=multipathd +DESC="multipath daemon" + +test -x $DAEMON || exit 0 + +if [ -f /etc/default/multipath-tools ] ; then + . /etc/default/multipath-tools +fi + +set -e + +case "$1" in + start) + echo -n "Starting $DESC" + start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS + echo "." + ;; + stop) + echo -n "Stopping $DESC" + start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON + echo "." + ;; + reload|force-reload) + echo "Reloading $DESC." + start-stop-daemon --stop --signal 1 --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON + ;; + restart|force-reload) + echo -n "Restarting $DESC" + start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON + sleep 1 + start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS + echo "." + ;; + *) + N=/etc/init.d/multipath-tools + echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 --- multipath-tools-0.4.7.orig/debian/multipath-tools.manpages +++ multipath-tools-0.4.7/debian/multipath-tools.manpages @@ -0,0 +1,3 @@ +kpartx/kpartx.8 +multipathd/multipathd.8 +multipath/multipath.8 --- multipath-tools-0.4.7.orig/debian/multipath-tools.postinst +++ multipath-tools-0.4.7/debian/multipath-tools.postinst @@ -0,0 +1,30 @@ +#! /bin/sh +# postinst script for multipath-tools + +set -e + +case "$1" in + configure) + # Remove leftover symlink installed by previous versions + [ -L /etc/udev/rules.d/multipath.rules ] && rm -f /etc/udev/rules.d/multipath.rules + + # Remove shutdown and reboot links; this init script does not need them. + if dpkg --compare-versions "$2" lt "0.4.7-1ubuntu8"; then + rm -f /etc/rc0.d/K20multipath-tools /etc/rc6.d/K20multipath-tools + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 + +