diff --git a/multipath-tools-0.4.8-opensuse-11.2.diff.bz2 b/multipath-tools-0.4.8-opensuse-11.2.diff.bz2 new file mode 100644 index 0000000..e55f7ec --- /dev/null +++ b/multipath-tools-0.4.8-opensuse-11.2.diff.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:507361270bd9d1c703a265834334ba5d39f3d2d4677dd531ab23611c845fb381 +size 131381 diff --git a/multipath-tools-adapt-to-new-sysfs-layout b/multipath-tools-adapt-to-new-sysfs-layout deleted file mode 100644 index a46cd30..0000000 --- a/multipath-tools-adapt-to-new-sysfs-layout +++ /dev/null @@ -1,45 +0,0 @@ -From b33a53646ba745dca3ef93ca29c45cbef2dfa171 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 18 Nov 2008 08:29:17 +0100 -Subject: [PATCH] Adapt to new sysfs layout in uev_discard() - -Later kernel moved the block sysfs entry below the device path, -so we have to check for the 'block' directory somewhere in the -devpath, not at the beginning. - -Signed-off-by: Hannes Reinecke ---- - multipathd/main.c | 13 +++++++++---- - 1 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index a4b0311..6908902 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -603,14 +603,19 @@ uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data) - static int - uev_discard(char * devpath) - { -- char a[10], b[10]; -+ char a[10], b[10], *c; - - /* - * keep only block devices, discard partitions - */ -- if (sscanf(devpath, "/block/%10s", a) != 1 || -- sscanf(devpath, "/block/%10[^/]/%10s", a, b) == 2) { -- condlog(4, "discard event on %s", devpath); -+ c = strstr(devpath,"/block"); -+ if (!c) { -+ condlog(3, "discard non-block event on %s", devpath); -+ return 1; -+ } -+ if (sscanf(c, "/block/%10s", a) != 1 || -+ sscanf(c, "/block/%10[^/]/%10s", a, b) == 2) { -+ condlog(3, "discard event on %s", c); - return 1; - } - return 0; --- -1.5.3.2 - diff --git a/multipath-tools-add-IBM-storage-to-hwtable b/multipath-tools-add-IBM-storage-to-hwtable deleted file mode 100644 index b610896..0000000 --- a/multipath-tools-add-IBM-storage-to-hwtable +++ /dev/null @@ -1,81 +0,0 @@ -From b0ce6c618b0953b708f4810e763ce307f1bad590 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Mon, 20 Oct 2008 08:49:04 +0200 -Subject: [PATCH] Add support for couple of IBM storage devices - -Few of the IBM rdac storage devices are not available in the multipath -tools. This patch adds support for those. - -Signed-Off-by: Chandra Seetharaman -Signed-off-by: Hannes Reinecke ---- - libmultipath/hwtable.c | 38 +++++++++++++++++++++++++++++++++++--- - 1 files changed, 35 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index cd9a9d2..f87907d 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -358,9 +358,9 @@ static struct hwentry default_hw[] = { - .prio_name = PRIO_RDAC, - }, - { -- /* IBM DS3400 */ -+ /* IBM DS4100 */ - .vendor = "IBM", -- .product = "1726-4xx", -+ .product = "1724", - .getuid = DEFAULT_GETUID, - .features = "1 queue_if_no_path", - .hwhandler = "1 rdac", -@@ -374,7 +374,23 @@ static struct hwentry default_hw[] = { - .prio_name = PRIO_RDAC, - }, - { -- /* IBM DS4400 / FAStT700 */ -+ /* IBM DS3200 / DS3300 / DS3400 */ -+ .vendor = "IBM", -+ .product = "1726", -+ .getuid = DEFAULT_GETUID, -+ .features = "1 queue_if_no_path", -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = 300, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, -+ }, -+ { -+ /* IBM DS4400 / DS4500 / FAStT700 */ - .vendor = "IBM", - .product = "1742", - .getuid = DEFAULT_GETUID, -@@ -422,6 +438,22 @@ static struct hwentry default_hw[] = { - .prio_name = PRIO_RDAC, - }, - { -+ /* IBM DS5000 */ -+ .vendor = "IBM", -+ .product = "1818", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, -+ }, -+ { - /* IBM Netfinity Fibre Channel RAID Controller Unit */ - .vendor = "IBM", - .product = "3526", --- -1.5.2.4 - diff --git a/multipath-tools-add-compellent-hwtable-entry b/multipath-tools-add-compellent-hwtable-entry deleted file mode 100644 index 5503a72..0000000 --- a/multipath-tools-add-compellent-hwtable-entry +++ /dev/null @@ -1,44 +0,0 @@ -From af9e485cddb49d75d89f438c1f0f5ac27802e1e5 Mon Sep 17 00:00:00 2001 -From: Jim Lester -Date: Sun, 21 Sep 2008 12:36:33 +0200 -Subject: [PATCH] [lib] new hardware from compellent in defaults table - ---- - libmultipath/hwtable.c | 21 +++++++++++++++++++++ - 1 files changed, 21 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index ada5c55..3e33352 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -18,6 +18,27 @@ - */ - static struct hwentry default_hw[] = { - /* -+ * Compellent Technologies, Inc. -+ * -+ * Maintainer : Jim Lester, Compellent -+ * Mail : jim.lester@compellent.com -+ */ -+ { -+ .vendor = "COMPELNT", -+ .product = "Compellent Vol", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = DEFAULT_HWHANDLER, -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = MULTIBUS, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, -+ .minio = DEFAULT_MINIO, -+ .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, -+ }, -+ /* - * Apple controller family - * - * Maintainer : Shyam Sundar --- -1.5.2.4 - diff --git a/multipath-tools-add-missing-unlock-on-exit b/multipath-tools-add-missing-unlock-on-exit deleted file mode 100644 index 5dfd4ed..0000000 --- a/multipath-tools-add-missing-unlock-on-exit +++ /dev/null @@ -1,27 +0,0 @@ -From 1feee37da59d67c4a38e01348e7138d4570c1fd4 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 18 Dec 2008 16:20:09 +0100 -Subject: [PATCH] Add missing unlock() on exit path - -We forgot to unlock the paths on exit. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/configure.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 68178c3..d1e26a1 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -337,6 +337,7 @@ domap (struct multipath * mpp, char * params) - - if (dm_map_present(mpp->alias)) { - condlog(3, "%s: map already present", mpp->alias); -+ lock_multipath(mpp, 0); - break; - } - --- -1.6.0.2 - diff --git a/multipath-tools-add-new-MSA-to-hwtable b/multipath-tools-add-new-MSA-to-hwtable deleted file mode 100644 index b8575e6..0000000 --- a/multipath-tools-add-new-MSA-to-hwtable +++ /dev/null @@ -1,35 +0,0 @@ -commit 4faa9b359e4b35882459c45176760ca2b0c8caaa -Author: Hannes Reinecke -Date: Thu Jan 15 12:03:34 2009 +0100 - - Add new HP arrays to internal hardware table - - This patch is to include entries for 2 new HP arrays in the hwtable. - - References: bnc#442133 - - Signed-off-by: Vijayakumar Balasubramanian - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index d742d6d..97c979e 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -145,7 +145,7 @@ static struct hwentry default_hw[] = { - { - /* EVA 3000/5000 with new firmware, EVA 4000/6000/8000 */ - .vendor = "(COMPAQ|HP)", -- .product = "HSV1[01]1|HSV2[01]0|HSV300", -+ .product = "HSV1[01]1|HSV2[01]0|HSV300|HSV4[05]0", - .getuid = DEFAULT_GETUID, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, -@@ -177,7 +177,7 @@ static struct hwentry default_hw[] = { - { - /* HP MSA2000 product family with new firmware */ - .vendor = "HP", -- .product = "MSA2012sa|MSA23(12|24)(fc|i|sa)", -+ .product = "MSA2012sa|MSA23(12|24)(fc|i|sa)|MSA2000s VOLUME", - .getuid = DEFAULT_GETUID, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, diff --git a/multipath-tools-add-show-status-cmd b/multipath-tools-add-show-status-cmd deleted file mode 100644 index 92d9e79..0000000 --- a/multipath-tools-add-show-status-cmd +++ /dev/null @@ -1,244 +0,0 @@ -From 88eb616ae1a673127ef4fd995d703a8b46a63822 Mon Sep 17 00:00:00 2001 -From: Christophe Varoqui -Date: Thu, 11 Sep 2008 00:17:37 +0200 -Subject: [PATCH] [multipathd] add "show status" cli command - -For now just print the number of paths in each path checker state, -if not zero. For example : - -path checker states: -up 2 -down 1 -ghost 1 ---- - libmultipath/checkers.c | 15 +++++++++++++++ - libmultipath/checkers.h | 18 +++++++++++------- - libmultipath/print.c | 24 ++++++++++++++++++++++++ - libmultipath/print.h | 1 + - libmultipath/structs.c | 2 +- - multipathd/cli.c | 1 + - multipathd/cli_handlers.c | 30 ++++++++++++++++++++++++++++++ - multipathd/cli_handlers.h | 1 + - multipathd/main.c | 4 +++- - 9 files changed, 87 insertions(+), 9 deletions(-) - -diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c -index 5889ad7..5132081 100644 ---- a/libmultipath/checkers.c -+++ b/libmultipath/checkers.c -@@ -8,8 +8,23 @@ - #include "vector.h" - #include "config.h" - -+char *checker_state_names[] = { -+ "wild", -+ "unchecked", -+ "down", -+ "up", -+ "shaky", -+ "ghost", -+ "pending" -+}; -+ - static LIST_HEAD(checkers); - -+char * checker_state_name (int i) -+{ -+ return checker_state_names[i]; -+} -+ - int init_checkers (void) - { - INIT_LIST_HEAD(&checkers); -diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h -index a65aaf9..e735250 100644 ---- a/libmultipath/checkers.h -+++ b/libmultipath/checkers.h -@@ -47,13 +47,16 @@ - * - Use: All async checkers - * - Description: Indicates a check IO is in flight. - */ --#define PATH_WILD -1 --#define PATH_UNCHECKED 0 --#define PATH_DOWN 1 --#define PATH_UP 2 --#define PATH_SHAKY 3 --#define PATH_GHOST 4 --#define PATH_PENDING 5 -+enum path_check_state { -+ PATH_WILD, -+ PATH_UNCHECKED, -+ PATH_DOWN, -+ PATH_UP, -+ PATH_SHAKY, -+ PATH_GHOST, -+ PATH_PENDING, -+ PATH_MAX_STATE -+}; - - #define DIRECTIO "directio" - #define TUR "tur" -@@ -106,6 +109,7 @@ struct checker { - - #define MSG(c, fmt, args...) snprintf((c)->message, CHECKER_MSG_LEN, fmt, ##args); - -+char * checker_state_name (int); - int init_checkers (void); - struct checker * add_checker (char *); - struct checker * checker_lookup (char *); -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 08ebd51..459b973 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -1133,6 +1133,30 @@ snprint_blacklist_except (char * buff, int len) - } - - extern int -+snprint_status (char * buff, int len, struct vectors *vecs) -+{ -+ int fwd = 0; -+ int i; -+ unsigned int count[PATH_MAX_STATE] = {0}; -+ struct path * pp; -+ -+ vector_foreach_slot (vecs->pathvec, pp, i) { -+ count[pp->state]++; -+ } -+ fwd += snprintf(buff + fwd, len - fwd, "path checker states:\n"); -+ for (i=0; i len) -+ return len; -+ return fwd; -+} -+ -+extern int - snprint_devices (char * buff, int len, struct vectors *vecs) - { - DIR *blkdir; -diff --git a/libmultipath/print.h b/libmultipath/print.h -index 5c7023c..1718c94 100644 ---- a/libmultipath/print.h -+++ b/libmultipath/print.h -@@ -44,6 +44,7 @@ int snprint_defaults (char *, int); - int snprint_blacklist (char *, int); - int snprint_blacklist_except (char *, int); - int snprint_blacklist_report (char *, int); -+int snprint_status (char *, int, struct vectors *); - int snprint_devices (char *, int, struct vectors *); - int snprint_hwtable (char *, int, vector); - int snprint_mptable (char *, int, vector); -diff --git a/libmultipath/structs.c b/libmultipath/structs.c -index 50f66f4..bb0d9f7 100644 ---- a/libmultipath/structs.c -+++ b/libmultipath/structs.c -@@ -349,7 +349,7 @@ pathcountgr (struct pathgroup * pgp, int state) - int i; - - vector_foreach_slot (pgp->paths, pp, i) -- if ((pp->state == state) || (state < 0)) -+ if ((pp->state == state) || (state == PATH_WILD)) - count++; - - return count; -diff --git a/multipathd/cli.c b/multipathd/cli.c -index 7eaac73..051624a 100644 ---- a/multipathd/cli.c -+++ b/multipathd/cli.c -@@ -406,6 +406,7 @@ cli_init (void) { - - add_handler(LIST+PATHS, NULL); - add_handler(LIST+PATHS+FMT, NULL); -+ add_handler(LIST+STATUS, NULL); - add_handler(LIST+MAPS, NULL); - add_handler(LIST+MAPS+STATUS, NULL); - add_handler(LIST+MAPS+STATS, NULL); -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index c84805a..415f865 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -224,6 +224,26 @@ cli_list_maps_topology (void * v, char ** reply, int * len, void * data) - } - - int -+show_status (char ** r, int *len, struct vectors * vecs) -+{ -+ char * c; -+ char * reply; -+ -+ unsigned int maxlen = INITIAL_REPLY_LEN; -+ reply = MALLOC(maxlen); -+ -+ if (!reply) -+ return 1; -+ -+ c = reply; -+ c += snprint_status(c, reply + maxlen - c, vecs); -+ -+ *r = reply; -+ *len = (int)(c - reply + 1); -+ return 0; -+} -+ -+int - show_maps (char ** r, int *len, struct vectors * vecs, char * style) - { - int i; -@@ -270,6 +290,16 @@ cli_list_maps (void * v, char ** reply, int * len, void * data) - } - - int -+cli_list_status (void * v, char ** reply, int * len, void * data) -+{ -+ struct vectors * vecs = (struct vectors *)data; -+ -+ condlog(3, "list status (operator)"); -+ -+ return show_status(reply, len, vecs); -+} -+ -+int - cli_list_maps_status (void * v, char ** reply, int * len, void * data) - { - struct vectors * vecs = (struct vectors *)data; -diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h -index a688481..cfc4b12 100644 ---- a/multipathd/cli_handlers.h -+++ b/multipathd/cli_handlers.h -@@ -1,5 +1,6 @@ - int cli_list_paths (void * v, char ** reply, int * len, void * data); - int cli_list_paths_fmt (void * v, char ** reply, int * len, void * data); -+int cli_list_status (void * v, char ** reply, int * len, void * data); - int cli_list_maps (void * v, char ** reply, int * len, void * data); - int cli_list_maps_status (void * v, char ** reply, int * len, void * data); - int cli_list_maps_stats (void * v, char ** reply, int * len, void * data); -diff --git a/multipathd/main.c b/multipathd/main.c -index 8d74cb9..e57a3e4 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -159,7 +159,8 @@ sync_map_state(struct multipath *mpp) - - vector_foreach_slot (mpp->pg, pgp, i){ - vector_foreach_slot (pgp->paths, pp, j){ -- if (pp->state <= PATH_UNCHECKED) -+ if (pp->state == PATH_UNCHECKED || -+ pp->state == PATH_WILD) - continue; - if ((pp->dmstate == PSTATE_FAILED || - pp->dmstate == PSTATE_UNDEF) && -@@ -693,6 +694,7 @@ uxlsnrloop (void * ap) - set_handler_callback(LIST+PATHS, cli_list_paths); - set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt); - set_handler_callback(LIST+MAPS, cli_list_maps); -+ set_handler_callback(LIST+STATUS, cli_list_status); - set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status); - set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats); - set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology); --- -1.5.2.4 - diff --git a/multipath-tools-add-show-wildcards-cmd b/multipath-tools-add-show-wildcards-cmd deleted file mode 100644 index 8511355..0000000 --- a/multipath-tools-add-show-wildcards-cmd +++ /dev/null @@ -1,204 +0,0 @@ -From 27ec49eca021f1cc85e66d55509f1e051a820bd4 Mon Sep 17 00:00:00 2001 -From: Christophe Varoqui -Date: Mon, 29 Sep 2008 01:37:02 +0200 -Subject: [PATCH] [multipathd] add "show wildcards" cli command - -The fact I had to look at the code to find the wildcards to use -in "show paths format ...", "show multipath format ..." and -"show pathgroup format ..." was a clear sign that more help was -necessary. - -The "show wildcards" command outputs : - -multipath format wildcards: -%n name -%w uuid -%d sysfs -%F failback -%Q queueing -%N paths -%r write_prot -%t dm-st -%S size -%f features -%h hwhandler -%A action -%0 path_faults -%1 switch_grp -%2 map_loads -%3 total_q_time -%4 q_timeouts -%s vend/prod/rev - -path format wildcards: -%w uuid -%i hcil -%d dev -%D dev_t -%t dm_st -%T chk_st -%s vend/prod/rev -%C next_check -%p pri -%S size - -pathgroup format wildcards: -%s selector -%p pri -%t dm_st - -And for example, "show paths format foo:%d:%S:%i", outs - -foo:dev:size:hcil -foo:sda:149G:2:0:0:0 ---- - libmultipath/print.c | 21 +++++++++++++++++++++ - libmultipath/print.h | 1 + - multipathd/cli.c | 2 ++ - multipathd/cli.h | 2 ++ - multipathd/cli_handlers.c | 17 +++++++++++++++++ - multipathd/cli_handlers.h | 1 + - multipathd/main.c | 1 + - 7 files changed, 45 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 7411ccc..09b3579 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -436,8 +436,29 @@ struct pathgroup_data pgd[] = { - {'s', "selector", 0, snprint_pg_selector}, - {'p', "pri", 0, snprint_pg_pri}, - {'t', "dm_st", 0, snprint_pg_state}, -+ {0, NULL, 0 , NULL} - }; - -+int -+snprint_wildcards (char * buff, int len) -+{ -+ int i, fwd = 0; -+ -+ fwd += snprintf(buff + fwd, len - fwd, "multipath format wildcards:\n"); -+ for (i = 0; mpd[i].header; i++) -+ fwd += snprintf(buff + fwd, len - fwd, "%%%c %s\n", -+ mpd[i].wildcard, mpd[i].header); -+ fwd += snprintf(buff + fwd, len - fwd, "\npath format wildcards:\n"); -+ for (i = 0; pd[i].header; i++) -+ fwd += snprintf(buff + fwd, len - fwd, "%%%c %s\n", -+ pd[i].wildcard, pd[i].header); -+ fwd += snprintf(buff + fwd, len - fwd, "\npathgroup format wildcards:\n"); -+ for (i = 0; pgd[i].header; i++) -+ fwd += snprintf(buff + fwd, len - fwd, "%%%c %s\n", -+ pgd[i].wildcard, pgd[i].header); -+ return fwd; -+} -+ - void - get_path_layout (vector pathvec, int header) - { -diff --git a/libmultipath/print.h b/libmultipath/print.h -index 1718c94..a8be408 100644 ---- a/libmultipath/print.h -+++ b/libmultipath/print.h -@@ -44,6 +44,7 @@ int snprint_defaults (char *, int); - int snprint_blacklist (char *, int); - int snprint_blacklist_except (char *, int); - int snprint_blacklist_report (char *, int); -+int snprint_wildcards (char *, int); - int snprint_status (char *, int, struct vectors *); - int snprint_devices (char *, int, struct vectors *); - int snprint_hwtable (char *, int, vector); -diff --git a/multipathd/cli.c b/multipathd/cli.c -index 051624a..34ae07c 100644 ---- a/multipathd/cli.c -+++ b/multipathd/cli.c -@@ -170,6 +170,7 @@ load_keys (void) - r += add_key(keys, "blacklist", BLACKLIST, 0); - r += add_key(keys, "devices", DEVICES, 0); - r += add_key(keys, "format", FMT, 1); -+ r += add_key(keys, "wildcards", WILDCARDS, 0); - - if (r) { - free_keys(keys); -@@ -416,6 +417,7 @@ cli_init (void) { - add_handler(LIST+CONFIG, NULL); - add_handler(LIST+BLACKLIST, NULL); - add_handler(LIST+DEVICES, NULL); -+ add_handler(LIST+WILDCARDS, NULL); - add_handler(ADD+PATH, NULL); - add_handler(DEL+PATH, NULL); - add_handler(ADD+MAP, NULL); -diff --git a/multipathd/cli.h b/multipathd/cli.h -index 8c83eab..9932d96 100644 ---- a/multipathd/cli.h -+++ b/multipathd/cli.h -@@ -20,6 +20,7 @@ enum { - __BLACKLIST, - __DEVICES, - __FMT, -+ __WILDCARDS, - }; - - #define LIST (1 << __LIST) -@@ -43,6 +44,7 @@ enum { - #define BLACKLIST (1 << __BLACKLIST) - #define DEVICES (1 << __DEVICES) - #define FMT (1 << __FMT) -+#define WILDCARDS (1 << __WILDCARDS) - - #define INITIAL_REPLY_LEN 1000 - -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index 415f865..36a4968 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -224,6 +224,23 @@ cli_list_maps_topology (void * v, char ** reply, int * len, void * data) - } - - int -+cli_list_wildcards (void * v, char ** reply, int * len, void * data) -+{ -+ char * c; -+ -+ *reply = MALLOC(INITIAL_REPLY_LEN); -+ -+ if (!reply) -+ return 1; -+ -+ c = *reply; -+ c += snprint_wildcards(c, INITIAL_REPLY_LEN); -+ -+ *len = INITIAL_REPLY_LEN; -+ return 0; -+} -+ -+int - show_status (char ** r, int *len, struct vectors * vecs) - { - char * c; -diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h -index cfc4b12..703a925 100644 ---- a/multipathd/cli_handlers.h -+++ b/multipathd/cli_handlers.h -@@ -9,6 +9,7 @@ int cli_list_maps_topology (void * v, char ** reply, int * len, void * data); - int cli_list_config (void * v, char ** reply, int * len, void * data); - int cli_list_blacklist (void * v, char ** reply, int * len, void * data); - int cli_list_devices (void * v, char ** reply, int * len, void * data); -+int cli_list_wildcards (void * v, char ** reply, int * len, void * data); - int cli_add_path (void * v, char ** reply, int * len, void * data); - int cli_del_path (void * v, char ** reply, int * len, void * data); - int cli_add_map (void * v, char ** reply, int * len, void * data); -diff --git a/multipathd/main.c b/multipathd/main.c -index e57a3e4..84fb5c4 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -703,6 +703,7 @@ uxlsnrloop (void * ap) - set_handler_callback(LIST+CONFIG, cli_list_config); - set_handler_callback(LIST+BLACKLIST, cli_list_blacklist); - set_handler_callback(LIST+DEVICES, cli_list_devices); -+ set_handler_callback(LIST+WILDCARDS, cli_list_wildcards); - set_handler_callback(ADD+PATH, cli_add_path); - set_handler_callback(DEL+PATH, cli_del_path); - set_handler_callback(ADD+MAP, cli_add_map); --- -1.5.2.4 - diff --git a/multipath-tools-allow-zero-paths b/multipath-tools-allow-zero-paths deleted file mode 100644 index 2b874c8..0000000 --- a/multipath-tools-allow-zero-paths +++ /dev/null @@ -1,38 +0,0 @@ -From 6ebe82d29b759049d1df1cb689f9c35bdaf58808 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 20 Nov 2008 13:33:10 +0100 -Subject: [PATCH] Allow zero paths for device-mapper strings - -There is no reason why we shouldn't allow zero paths in the device -mapper output. - -References: 435688 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/dmparser.c | 7 ++++--- - 1 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c -index 9441b11..0cef666 100644 ---- a/libmultipath/dmparser.c -+++ b/libmultipath/dmparser.c -@@ -187,11 +187,12 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp) - num_pg = atoi(word); - FREE(word); - -- if (num_pg > 0 && !mpp->pg) -+ if (num_pg > 0 && !mpp->pg) { - mpp->pg = vector_alloc(); - -- if (!mpp->pg) -- return 1; -+ if (!mpp->pg) -+ return 1; -+ } - - /* - * first pg to try --- -1.5.3.2 - diff --git a/multipath-tools-always-allocate-alias b/multipath-tools-always-allocate-alias deleted file mode 100644 index eea132a..0000000 --- a/multipath-tools-always-allocate-alias +++ /dev/null @@ -1,94 +0,0 @@ -From 1532369e0269ddc8bbb295f3cc26f102b247bca0 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 20 Nov 2008 08:50:10 +0100 -Subject: [PATCH] Always allocate space for alias - -We should always allocate memory for the alias, this makes freeing -up the string less error-prone. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/devmapper.c | 8 ++++---- - libmultipath/propsel.c | 6 +++--- - libmultipath/structs.c | 4 +--- - 3 files changed, 8 insertions(+), 10 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 92afae7..bc4f9db 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -765,7 +765,7 @@ dm_get_name(char *uuid, char *name) - { - vector vec; - struct multipath *mpp; -- int i; -+ int i, retval = 0; - - vec = vector_alloc(); - -@@ -779,14 +779,14 @@ dm_get_name(char *uuid, char *name) - - vector_foreach_slot(vec, mpp, i) { - if (!strcmp(uuid, mpp->wwid)) { -- vector_free(vec); - strcpy(name, mpp->alias); -- return 1; -+ retval = 1; - } -+ free_multipath(mpp, KEEP_PATHS); - } - - vector_free(vec); -- return 0; -+ return retval; - } - - int -diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c -index 43611ff..5a16182 100644 ---- a/libmultipath/propsel.c -+++ b/libmultipath/propsel.c -@@ -159,7 +159,7 @@ extern int - select_alias (struct multipath * mp) - { - if (mp->mpe && mp->mpe->alias) -- mp->alias = mp->mpe->alias; -+ mp->alias = strdup(mp->mpe->alias); - else { - mp->alias = NULL; - if (conf->user_friendly_names) -@@ -175,7 +175,7 @@ select_alias (struct multipath * mp) - } - } - if (mp->alias == NULL) -- mp->alias = mp->wwid; -+ mp->alias = strdup(mp->wwid); - } - - return 0; -@@ -365,6 +365,6 @@ select_pg_timeout(struct multipath *mp) - return 0; - } - mp->pg_timeout = PGTIMEOUT_UNDEF; -- condlog(3, "pg_timeout = NONE (internal default)"); -+ condlog(3, "%s: pg_timeout = NONE (internal default)", mp->alias); - return 0; - } -diff --git a/libmultipath/structs.c b/libmultipath/structs.c -index bb0d9f7..d2bfc2d 100644 ---- a/libmultipath/structs.c -+++ b/libmultipath/structs.c -@@ -161,9 +161,7 @@ free_multipath (struct multipath * mpp, int free_paths) - - free_multipath_attributes(mpp); - -- if (mpp->alias && -- (!mpp->mpe || (mpp->mpe && mpp->alias != mpp->mpe->alias)) && -- (mpp->wwid && mpp->alias != mpp->wwid)) { -+ if (mpp->alias) { - FREE(mpp->alias); - mpp->alias = NULL; - } --- -1.5.3.2 - diff --git a/multipath-tools-basename-return-value b/multipath-tools-basename-return-value deleted file mode 100644 index 5d17673..0000000 --- a/multipath-tools-basename-return-value +++ /dev/null @@ -1,114 +0,0 @@ -From 53c7a13bf5383814a7118607d3b1da41de51c4b1 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 20 Nov 2008 08:40:59 +0100 -Subject: [PATCH] Return number of characters written in basename() - -basename() can fail, so we should return the number of -characters written to get some error indicator. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/configure.c | 12 +++++++++--- - libmultipath/discovery.h | 1 - - libmultipath/util.c | 13 +++++++++++-- - libmultipath/util.h | 2 +- - 4 files changed, 21 insertions(+), 7 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 8444ef2..494ea70 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -34,13 +34,14 @@ - #include "dict.h" - #include "alias.h" - #include "prio.h" -+#include "util.h" - - extern int - setup_map (struct multipath * mpp) - { - struct pathgroup * pgp; - int i; -- -+ - /* - * don't bother if devmap size is unknown - */ -@@ -579,9 +580,14 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec) - return NULL; - - if (dev_type == DEV_DEVNODE) { -- basename(dev, buff); -+ if (basename(dev, buff) == 0) { -+ condlog(1, "basename failed for '%s' (%s)", -+ dev, buff); -+ return NULL; -+ } -+ - pp = find_path_by_dev(pathvec, buff); -- -+ - if (!pp) { - pp = alloc_path(); - -diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h -index c7cf7e8..05b1cfe 100644 ---- a/libmultipath/discovery.h -+++ b/libmultipath/discovery.h -@@ -27,7 +27,6 @@ - int sysfs_get_dev (struct sysfs_device * dev, char * buff, size_t len); - int path_discovery (vector pathvec, struct config * conf, int flag); - --void basename (char *, char *); - int do_tur (char *); - int devt2devname (char *, char *); - int pathinfo (struct path *, vector hwtable, int mask); -diff --git a/libmultipath/util.c b/libmultipath/util.c -index c7fe6b4..3afe7ea 100644 ---- a/libmultipath/util.c -+++ b/libmultipath/util.c -@@ -38,10 +38,18 @@ strchop(char *str) - str[++i] = '\0'; - } - --void -+int - basename (char * str1, char * str2) - { -- char *p = str1 + (strlen(str1) - 1); -+ char *p; -+ -+ if (!str1 || !strlen(str1)) -+ return 0; -+ -+ if (!str2) -+ return 0; -+ -+ p = str1 + (strlen(str1) - 1); - - while (*--p != '/' && p != str1) - continue; -@@ -50,6 +58,7 @@ basename (char * str1, char * str2) - p++; - - strcpy(str2, p); -+ return strlen(p); - } - - int -diff --git a/libmultipath/util.h b/libmultipath/util.h -index d0df8aa..14af696 100644 ---- a/libmultipath/util.h -+++ b/libmultipath/util.h -@@ -3,7 +3,7 @@ - - int strcmp_chomp(char *, char *); - void strchop(char *); --void basename (char * src, char * dst); -+int basename (char * src, char * dst); - int filepresent (char * run); - int get_word (char * sentence, char ** word); - size_t strlcpy(char *dst, const char *src, size_t size); --- -1.5.3.2 - diff --git a/multipath-tools-check-for-empty-mpvecs b/multipath-tools-check-for-empty-mpvecs deleted file mode 100644 index e059652..0000000 --- a/multipath-tools-check-for-empty-mpvecs +++ /dev/null @@ -1,27 +0,0 @@ -commit 1b043535b5584cf8298bf535e5794289f1b98f43 -Author: Hannes Reinecke -Date: Tue Nov 4 09:40:26 2008 +0100 - - Check for empty mpvecs in mpvec_garbage_collector() - - During shutdown the mpvec pointer can indeed be empty, so we should - check it first before trying to access it. - - References: 437245 - - Signed-off-by: Hannes Reinecke - -diff --git a/multipathd/main.c b/multipathd/main.c -index 78e6ed3..a4b0311 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -798,6 +798,9 @@ mpvec_garbage_collector (struct vectors * vecs) - struct multipath * mpp; - unsigned int i; - -+ if (!vecs->mpvec) -+ return; -+ - vector_foreach_slot (vecs->mpvec, mpp, i) { - if (mpp && mpp->alias && !dm_map_present(mpp->alias)) { - condlog(2, "%s: remove dead map", mpp->alias); diff --git a/multipath-tools-check-get_inq-return-values b/multipath-tools-check-get_inq-return-values deleted file mode 100644 index 438bbee..0000000 --- a/multipath-tools-check-get_inq-return-values +++ /dev/null @@ -1,152 +0,0 @@ -commit 08a140c02f9010f356e5b18dc7b7652cc15fc79d -Author: Hannes Reinecke -Date: Fri Sep 26 15:31:07 2008 +0200 - - multipath: Check return value for get_inq() - - Check the return value of get_inq() to correctly handle devices - with unconnected LUNs. - - References: 419123 - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index dd45e03..e1a67ac 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -275,7 +275,7 @@ devt2devname (char *devname, char *devt) - - int - do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, -- void *resp, int mx_resp_len, int noisy) -+ void *resp, int mx_resp_len) - { - unsigned char inqCmdBlk[INQUIRY_CMDLEN] = - { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -@@ -334,7 +334,7 @@ get_serial (char * str, int maxlen, int fd) - if (fd < 0) - return 1; - -- if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { -+ if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN)) { - len = buff[3]; - if (len >= maxlen) - return 1; -@@ -348,26 +348,69 @@ get_serial (char * str, int maxlen, int fd) - } - - static int --get_inq (char * vendor, char * product, char * rev, int fd) -+get_inq (char * dev, char * vendor, char * product, char * rev, int fd) - { -- char buff[MX_ALLOC_LEN + 1] = {0}; -+ unsigned char buff[MX_ALLOC_LEN + 1] = {0}; -+ int len; - - if (fd < 0) - return 1; - -- if (0 == do_inq(fd, 0, 0, 0, buff, MX_ALLOC_LEN, 0)) { -- memcpy(vendor, buff + 8, 8); -- vendor[8] = '\0'; -- strchop(vendor); -- memcpy(product, buff + 16, 16); -- product[16] = '\0'; -- strchop(product); -- memcpy(rev, buff + 32, 4); -- rev[4] = '\0'; -- strchop(rev); -- return 0; -+ if (0 != do_inq(fd, 0, 0, 0, buff, MX_ALLOC_LEN)) -+ return 1; -+ -+ /* Check peripheral qualifier */ -+ if ((buff[0] >> 5) != 0) { -+ int pqual = (buff[0] >> 5); -+ switch (pqual) { -+ case 1: -+ condlog(3, "%s: INQUIRY failed, LU not connected", dev); -+ break; -+ case 3: -+ condlog(3, "%s: INQUIRY failed, LU not supported", dev); -+ break; -+ default: -+ condlog(3, "%s: INQUIRY failed, Invalid PQ %x", -+ dev, pqual); -+ break; -+ } -+ -+ return 1; - } -- return 1; -+ -+ len = buff[4] + 4; -+ -+ if (len < 8) { -+ condlog(3, "%s: INQUIRY response too short (len %d)", -+ dev, len); -+ return 1; -+ } -+ -+ len -= 8; -+ memset(vendor, 0x0, 8); -+ memcpy(vendor, buff + 8, len > 8 ? 8 : len); -+ vendor[8] = '\0'; -+ strchop(vendor); -+ if (len <= 8) -+ return 0; -+ -+ len -= 8; -+ -+ memset(product, 0x0, 16); -+ memcpy(product, buff + 16, len > 16 ? 16 : len); -+ product[16] = '\0'; -+ strchop(product); -+ if (len <= 16) -+ return 0; -+ -+ len -= 16; -+ -+ memset(rev, 0x0, 4); -+ memcpy(rev, buff + 32, 4); -+ rev[4] = '\0'; -+ strchop(rev); -+ -+ return 0; - } - - static int -@@ -549,13 +592,16 @@ sysfs_pathinfo(struct path * pp) - if (!strncmp(parent->kernel, "block",5)) - parent = sysfs_device_get_parent(parent); - -+ if (!strncmp(pp->dev,"cciss",5)) -+ strcpy(parent->subsystem,"cciss"); -+ - condlog(3, "%s: subsystem = %s", pp->dev, parent->subsystem); - - if (!strncmp(parent->subsystem, "scsi",4)) - pp->bus = SYSFS_BUS_SCSI; - if (!strncmp(parent->subsystem, "ccw",3)) - pp->bus = SYSFS_BUS_CCW; -- if (!strncmp(pp->dev,"cciss",5)) -+ if (!strncmp(parent->subsystem,"cciss",5)) - pp->bus = SYSFS_BUS_CCISS; - - if (pp->bus == SYSFS_BUS_UNDEF) -@@ -587,8 +633,14 @@ scsi_ioctl_pathinfo (struct path * pp, int mask) - static int - cciss_ioctl_pathinfo (struct path * pp, int mask) - { -+ int ret; -+ - if (mask & DI_SYSFS) { -- get_inq(pp->vendor_id, pp->product_id, pp->rev, pp->fd); -+ ret = get_inq(pp->dev, pp->vendor_id, pp->product_id, -+ pp->rev, pp->fd); -+ if (ret) -+ return ret; -+ - condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id); - condlog(3, "%s: product = %s", pp->dev, pp->product_id); - condlog(3, "%s: revision = %s", pp->dev, pp->rev); diff --git a/multipath-tools-check-vector-defines b/multipath-tools-check-vector-defines deleted file mode 100644 index fc767f9..0000000 --- a/multipath-tools-check-vector-defines +++ /dev/null @@ -1,30 +0,0 @@ -commit 03b42661495abdb9fa594ff82105f705d2c4148f -Author: Hannes Reinecke -Date: Mon Jan 26 13:01:33 2009 +0100 - - Error checking for VECTOR_XXX defines - - Christophe doesn't believe in error checking. I, however, have - been tripping over them all the time. - - References: bnc#469269 - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/vector.h b/libmultipath/vector.h -index aa9e134..59cfd27 100644 ---- a/libmultipath/vector.h -+++ b/libmultipath/vector.h -@@ -31,9 +31,9 @@ struct _vector { - typedef struct _vector *vector; - - #define VECTOR_DEFAULT_SIZE 1 --#define VECTOR_SLOT(V,E) ((V)->slot[(E)]) --#define VECTOR_SIZE(V) ((V)->allocated) --#define VECTOR_LAST_SLOT(V) ((V)->slot[((V)->allocated - 1)]) -+#define VECTOR_SLOT(V,E) (((V) && (E) < (V)->allocated) ? (V)->slot[(E)] : NULL) -+#define VECTOR_SIZE(V) ((V) ? (V)->allocated : 0) -+#define VECTOR_LAST_SLOT(V) (((V) && (V)->allocated) ? (V)->slot[((V)->allocated - 1)] : NULL) - - #define vector_foreach_slot(v,p,i) \ - for (i = 0; (v) && i < (v)->allocated && ((p) = (v)->slot[i]); i++) diff --git a/multipath-tools-crash-in-update-multipath b/multipath-tools-crash-in-update-multipath deleted file mode 100644 index 237094a..0000000 --- a/multipath-tools-crash-in-update-multipath +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index eb7ac03..3903b28 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -114,6 +114,9 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) - struct pathgroup * cpgp; - int r = 0; - -+ if (!mpp) -+ return 0; -+ - vector_foreach_slot (mpp->pg, pgp, i) { - compute_pgid(pgp); - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index e3cace9..3770566 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -163,6 +163,9 @@ _remove_maps (struct vectors * vecs, int stop_waiter) - int i; - struct multipath * mpp; - -+ if (!vecs) -+ return; -+ - vector_foreach_slot (vecs->mpvec, mpp, i) { - _remove_map(mpp, vecs, stop_waiter, 1); - i--; -@@ -451,6 +454,9 @@ verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec) - int count = 0; - int i, j; - -+ if (!mpp) -+ return 0; -+ - vector_foreach_slot (mpp->paths, pp, i) { - /* - * see if path is in sysfs -diff --git a/libmultipath/vector.h b/libmultipath/vector.h -index 993ba79..aa9e134 100644 ---- a/libmultipath/vector.h -+++ b/libmultipath/vector.h -@@ -36,9 +36,9 @@ typedef struct _vector *vector; - #define VECTOR_LAST_SLOT(V) ((V)->slot[((V)->allocated - 1)]) - - #define vector_foreach_slot(v,p,i) \ -- for (i = 0; i < (v)->allocated && ((p) = (v)->slot[i]); i++) -+ for (i = 0; (v) && i < (v)->allocated && ((p) = (v)->slot[i]); i++) - #define vector_foreach_slot_after(v,p,i) \ -- for (; i < (v)->allocated && ((p) = (v)->slot[i]); i++) -+ for (; (v) && i < (v)->allocated && ((p) = (v)->slot[i]); i++) - - /* Prototypes */ - extern vector vector_alloc(void); diff --git a/multipath-tools-display-checker-name-on-failure b/multipath-tools-display-checker-name-on-failure deleted file mode 100644 index 4761776..0000000 --- a/multipath-tools-display-checker-name-on-failure +++ /dev/null @@ -1,69 +0,0 @@ -From 2abb4feab7683ba7946a3cf387568de3f7312df3 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 13 Jan 2009 15:28:23 +0100 -Subject: [PATCH] Checker name is not displayed on failure - -If add_checker() isn't able to locate the checker -it won't display the name in free_checker(). - -Signed-off-by: Hannes Reinecke ---- - libmultipath/checkers.c | 5 +++-- - libmultipath/prio.c | 5 +++-- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c -index 4378621..e1789e5 100644 ---- a/libmultipath/checkers.c -+++ b/libmultipath/checkers.c -@@ -87,10 +87,12 @@ struct checker * add_checker (char * name) - c = alloc_checker(); - if (!c) - return NULL; -+ snprintf(c->name, CHECKER_NAME_LEN, "%s", name); - snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so", - conf->multipath_dir, name); - if (stat(libname,&stbuf) < 0) { -- condlog(0,"Invalid checker '%s'", name); -+ condlog(0,"Checker '%s' not found in %s", -+ name, conf->multipath_dir); - goto out; - } - condlog(3, "loading %s checker", libname); -@@ -122,7 +124,6 @@ struct checker * add_checker (char * name) - if (!c->free) - goto out; - -- snprintf(c->name, CHECKER_NAME_LEN, "%s", name); - c->fd = 0; - c->sync = 1; - list_add(&c->node, &checkers); -diff --git a/libmultipath/prio.c b/libmultipath/prio.c -index 30e03c2..7508a8a 100644 ---- a/libmultipath/prio.c -+++ b/libmultipath/prio.c -@@ -71,10 +71,12 @@ struct prio * add_prio (char * name) - p = alloc_prio(); - if (!p) - return NULL; -+ snprintf(p->name, PRIO_NAME_LEN, "%s", name); - snprintf(libname, LIB_PRIO_NAMELEN, "%s/libprio%s.so", - conf->multipath_dir, name); - if (stat(libname,&stbuf) < 0) { -- condlog(0,"Invalid prioritizer '%s'", name); -+ condlog(0,"Prioritizer '%s' not found in %s", -+ name, conf->multipath_dir); - goto out; - } - condlog(3, "loading %s prioritizer", libname); -@@ -91,7 +93,6 @@ struct prio * add_prio (char * name) - condlog(0, "A dynamic linking error occurred: (%s)", errstr); - if (!p->getprio) - goto out; -- snprintf(p->name, PRIO_NAME_LEN, "%s", name); - list_add(&p->node, &prioritizers); - return p; - out: --- -1.5.3.2 - diff --git a/multipath-tools-dmraid-uuid-in-uppercase b/multipath-tools-dmraid-uuid-in-uppercase deleted file mode 100644 index c00d0d2..0000000 --- a/multipath-tools-dmraid-uuid-in-uppercase +++ /dev/null @@ -1,34 +0,0 @@ -commit 1942363f6acc7d9e507d4bc82063287da19cd05a -Author: Hannes Reinecke -Date: Tue Nov 4 10:08:01 2008 +0100 - - dmraid uuid starts with 'DMRAID' - - The dmraid uuid starts with 'DMRAID', not 'dmraid'. - - References: 439439 - - Signed-off-by: Hannes Reinecke - -diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules -index 2746eff..3e09dcf 100644 ---- a/kpartx/kpartx.rules -+++ b/kpartx/kpartx.rules -@@ -18,7 +18,7 @@ ENV{DM_UUID}=="mpath-*", \ - SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}" - - # Create persistent links for dmraid tables --ENV{DM_UUID}=="dmraid-*", \ -+ENV{DM_UUID}=="DMRAID-*", \ - SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}" - - # Create persistent links for linear tables -@@ -32,7 +32,7 @@ ENV{DM_PART}=="?*", \ - # Create dm tables for partitions - ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="mpath-*", \ - RUN+="/sbin/kpartx -a -p _part /dev/$kernel" --ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="dmraid-*", \ -+ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="DMRAID-*", \ - RUN+="/sbin/kpartx -a -p _part /dev/$kernel" - ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="linear-*", \ - RUN+="/sbin/kpartx -a -p _part /dev/$kernel" diff --git a/multipath-tools-do-not-reinitialize-prio-and-checker-list b/multipath-tools-do-not-reinitialize-prio-and-checker-list deleted file mode 100644 index 0652c90..0000000 --- a/multipath-tools-do-not-reinitialize-prio-and-checker-list +++ /dev/null @@ -1,46 +0,0 @@ -From f333a7d0516c053f2acc67c9ecec702e24ffdf44 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 8 Jan 2009 11:44:13 +0100 -Subject: [PATCH] Do not reinitialize prio and checker list after config init - -init_prio() and init_checker() are called after the config file -is read as we have to know the path to the shared libraries. -But we should not overwrite any checker or prio information read -from the config file. - -References: 464373 - -Signed-off-by: Konrad Rzeszutek -Signed-off-by: Hannes Reinecke ---- - libmultipath/checkers.c | 1 - - libmultipath/prio.c | 1 - - 2 files changed, 0 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c -index 45ef531..4378621 100644 ---- a/libmultipath/checkers.c -+++ b/libmultipath/checkers.c -@@ -28,7 +28,6 @@ char * checker_state_name (int i) - - int init_checkers (void) - { -- INIT_LIST_HEAD(&checkers); - if (!add_checker(DEFAULT_CHECKER)) - return 1; - return 0; -diff --git a/libmultipath/prio.c b/libmultipath/prio.c -index 5e01f54..30e03c2 100644 ---- a/libmultipath/prio.c -+++ b/libmultipath/prio.c -@@ -12,7 +12,6 @@ static LIST_HEAD(prioritizers); - - int init_prio (void) - { -- INIT_LIST_HEAD(&prioritizers); - if (!add_prio(DEFAULT_PRIO)) - return 1; - return 0; --- -1.6.0.2 - diff --git a/multipath-tools-dont-access-blocked-devices-in-checkerloop b/multipath-tools-dont-access-blocked-devices-in-checkerloop deleted file mode 100644 index 9fb795c..0000000 --- a/multipath-tools-dont-access-blocked-devices-in-checkerloop +++ /dev/null @@ -1,146 +0,0 @@ -commit 33a9016139228c492f5e95278c8ee77418c53efa -Author: Hannes Reinecke -Date: Mon Jan 26 13:50:28 2009 +0100 - - Check for blocked devices in checkerloop() - - The checkerloop should also check for blocked devices; reducing - multipathd stall even further. - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 2e63cdf..b56899a 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -688,7 +688,7 @@ static int sysfs_get_sdev_state(struct path *pp) - if (!sysfs_get_state(parent, dev_state, 32)) { - if (!strncmp(dev_state, "blocked", 7)) { - condlog(3, "%s: device blocked", pp->dev); -- return PATH_UNCHECKED; -+ return PATH_PENDING; - } else if (!strncmp(dev_state, "running", 7)) { - return PATH_UP; - } -@@ -792,40 +792,40 @@ cciss_ioctl_pathinfo (struct path * pp, int mask) - return 0; - } - --static int -+int - get_state (struct path * pp) - { - struct checker * c = &pp->checker; -+ int state = PATH_UNCHECKED; - - condlog(3, "%s: get_state", pp->dev); - - if (pp->bus == SYSFS_BUS_SCSI && pp->sysdev) { - /* Check the sdev state before accessing it */ -- pp->state = sysfs_get_sdev_state(pp); -- if (pp->state == PATH_UNCHECKED || pp->state == PATH_DOWN) { -+ state = sysfs_get_sdev_state(pp); -+ if (state == PATH_PENDING || state == PATH_DOWN) { - /* Further checking pointless */ -- pp->priority = 0; -- return 0; -+ return state; - } - } - if (!checker_selected(c)) { - select_checker(pp); - if (!checker_selected(c)) { - condlog(3, "%s: No checker selected", pp->dev); -- return 1; -+ return PATH_UNCHECKED; - } - checker_set_fd(c, pp->fd); - if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) { - condlog(3, "%s: checker init failed", pp->dev); -- return 1; -+ return PATH_UNCHECKED; - } - } -- pp->state = checker_check(c); -- condlog(3, "%s: state = %i", pp->dev, pp->state); -- if (pp->state == PATH_DOWN && strlen(checker_message(c))) -+ state = checker_check(c); -+ condlog(3, "%s: state = %i", pp->dev, state); -+ if (state == PATH_DOWN && strlen(checker_message(c))) - condlog(3, "%s: checker msg is \"%s\"", - pp->dev, checker_message(c)); -- return 0; -+ return state; - } - - static int -@@ -839,7 +839,7 @@ get_prio (struct path * pp) - if (pp->bus == SYSFS_BUS_SCSI) { - /* Check the sdev state before accessing it */ - path_state = sysfs_get_sdev_state(pp); -- if (path_state == PATH_DOWN || path_state == PATH_UNCHECKED) { -+ if (path_state == PATH_DOWN || path_state == PATH_PENDING) { - pp->priority = PRIO_UNDEF; - return 0; - } -@@ -914,8 +914,11 @@ pathinfo (struct path *pp, vector hwtable, int mask) - cciss_ioctl_pathinfo(pp, mask)) - goto blank; - -- if (mask & DI_CHECKER && get_state(pp)) -- goto blank; -+ if (mask & DI_CHECKER) { -+ pp->state = get_state(pp); -+ if (pp->state == PATH_UNCHECKED || pp->state == PATH_WILD) -+ goto blank; -+ } - - /* - * Retrieve path priority, even for PATH_DOWN paths if it has never -diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h -index 3749674..a460491 100644 ---- a/libmultipath/discovery.h -+++ b/libmultipath/discovery.h -@@ -33,6 +33,7 @@ int pathinfo (struct path *, vector hwtable, int mask); - struct path * store_pathinfo (vector pathvec, vector hwtable, - char * devname, int flag); - int sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo); -+int get_state(struct path *pp); - - /* - * discovery bitmask -diff --git a/multipathd/main.c b/multipathd/main.c -index 7bc0211..5456a6c 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -116,6 +116,9 @@ coalesce_maps(struct vectors *vecs, vector nmpv) - unsigned int i; - int j; - -+ if (!vecs) -+ return 0; -+ - vector_foreach_slot (ompv, ompp, i) { - if (!find_mp_by_wwid(nmpv, ompp->wwid)) { - /* -@@ -942,16 +945,16 @@ check_path (struct vectors * vecs, struct path * pp) - */ - checker_set_async(&pp->checker); - -- newstate = checker_check(&pp->checker); -+ newstate = get_state(pp); - -- if (newstate < 0) { -+ if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) { - condlog(2, "%s: unusable path", pp->dev); - pathinfo(pp, conf->hwtable, 0); - return; - } - /* -- * Async IO in flight. Keep the previous path state -- * and reschedule as soon as possible -+ * Async IO in flight or path blocked. Keep the previous -+ * path state and reschedule as soon as possible - */ - if (newstate == PATH_PENDING) { - pp->tick = 1; diff --git a/multipath-tools-dont-check-valid-context-in-get_state b/multipath-tools-dont-check-valid-context-in-get_state deleted file mode 100644 index 67a7e64..0000000 --- a/multipath-tools-dont-check-valid-context-in-get_state +++ /dev/null @@ -1,42 +0,0 @@ -From 0d18112f4f937626b3c335bf52a6231f5118dd9e Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 30 Oct 2008 13:46:15 +0100 -Subject: [PATCH] Do not check for valid mp context in get_state() - -When called from 'multipath -ll' get_state() does not -have a valid context. But the checkers should run nevertheless -as we need the state here but are not interested in any long-term -issues. - -References: 433659 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/discovery.c | 5 ++--- - 1 files changed, 2 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index a5ae8aa..9929e19 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -659,15 +659,14 @@ get_state (struct path * pp) - { - struct checker * c = &pp->checker; - -- if (!pp->mpp) -- return 0; -+ condlog(3, "%s: get_state", pp->dev); - - if (!checker_selected(c)) { - select_checker(pp); - if (!checker_selected(c)) - return 1; - checker_set_fd(c, pp->fd); -- if (checker_init(c, &pp->mpp->mpcontext)) -+ if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) - return 1; - } - pp->state = checker_check(c); --- -1.5.4.5 - diff --git a/multipath-tools-dont-run-checkers-for-blocked-devices b/multipath-tools-dont-run-checkers-for-blocked-devices deleted file mode 100644 index 1e93dbc..0000000 --- a/multipath-tools-dont-run-checkers-for-blocked-devices +++ /dev/null @@ -1,82 +0,0 @@ -From 23348c651f2c4bc7d41a6aa32957615403cf1533 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 13 Jan 2009 15:32:52 +0100 -Subject: [PATCH] Don't run checkers or prio for blocked devices - -When a device is in 'blocked' state any I/O to it will be -blocked. Hence multipathd will stall when running the -path checker until the device is unblocked, leaving the -entire mulitpath daemon hanging. -So we have to check for the state and _not_ run any -checker or prioritizer if the device is blocked. - -References: bnc#464155 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/discovery.c | 35 +++++++++++++++++++++++++++++++++++ - 1 files changed, 35 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index a18a46a..afd247d 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -144,6 +144,7 @@ declare_sysfs_get_str(cutype); - declare_sysfs_get_str(vendor); - declare_sysfs_get_str(model); - declare_sysfs_get_str(rev); -+declare_sysfs_get_str(state); - - int - sysfs_get_dev (struct sysfs_device * dev, char * buff, size_t len) -@@ -688,6 +689,23 @@ get_state (struct path * pp) - - condlog(3, "%s: get_state", pp->dev); - -+ if (pp->bus == SYSFS_BUS_SCSI && pp->sysdev) { -+ struct sysfs_device *parent; -+ char dev_state[32]; -+ -+ /* check device state */ -+ parent = sysfs_device_get_parent(pp->sysdev); -+ if (parent && !strncmp(parent->kernel, "block", 5)) -+ parent = sysfs_device_get_parent(parent); -+ if (parent && !sysfs_get_state(parent, dev_state, 32)) { -+ if (!strncmp(dev_state, "blocked", 7)) { -+ condlog(3, "%s: device blocked", pp->dev); -+ pp->state = PATH_DOWN; -+ pp->priority = 0; -+ return 0; -+ } -+ } -+ } - if (!checker_selected(c)) { - select_checker(pp); - if (!checker_selected(c)) { -@@ -714,6 +732,23 @@ get_prio (struct path * pp) - if (!pp) - return 0; - -+ if (pp->bus == SYSFS_BUS_SCSI && pp->sysdev) { -+ struct sysfs_device *parent; -+ char dev_state[32]; -+ -+ /* check device state */ -+ parent = sysfs_device_get_parent(pp->sysdev); -+ if (parent && !strncmp(parent->kernel, "block", 5)) -+ parent = sysfs_device_get_parent(parent); -+ if (parent && !sysfs_get_state(parent, dev_state, 32)) { -+ if (!strncmp(dev_state, "blocked", 7)) { -+ condlog(3, "%s: device blocked", pp->dev); -+ pp->priority = PRIO_UNDEF; -+ return 0; -+ } -+ } -+ } -+ - if (!pp->prio) { - select_prio(pp); - if (!pp->prio) { --- -1.5.3.2 - diff --git a/multipath-tools-enhance-error-for-checkers b/multipath-tools-enhance-error-for-checkers deleted file mode 100644 index e444ed6..0000000 --- a/multipath-tools-enhance-error-for-checkers +++ /dev/null @@ -1,136 +0,0 @@ -From 5974ba6dd190ed7b5633467962c2cd1dd2beb85d Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Fri, 12 Dec 2008 13:49:30 +0100 -Subject: [PATCH] Enhanced error for invalid checker or prioritizer - -An invalid checker or prioritizer shouldn't be greeted -with the incomprehensible 'A dynamic linking error ...' -message. Rather display something sensible here. -Oh, and fix up list initialization alloc_X(). - -References: 456214 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/checkers.c | 23 +++++++++++++++++------ - libmultipath/prio.c | 22 +++++++++++++++++----- - 2 files changed, 34 insertions(+), 11 deletions(-) - -diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c -index 2640281..231b408 100644 ---- a/libmultipath/checkers.c -+++ b/libmultipath/checkers.c -@@ -2,6 +2,7 @@ - #include - #include - #include -+#include - - #include "debug.h" - #include "checkers.h" -@@ -35,7 +36,12 @@ int init_checkers (void) - - struct checker * alloc_checker (void) - { -- return zalloc(sizeof(struct checker)); -+ struct checker *c; -+ -+ c = zalloc(sizeof(struct checker)); -+ if (c) -+ INIT_LIST_HEAD(&c->node); -+ return c; - } - - void free_checker (struct checker * c) -@@ -75,6 +81,7 @@ struct checker * checker_lookup (char * name) - struct checker * add_checker (char * name) - { - char libname[LIB_CHECKER_NAMELEN]; -+ struct stat stbuf; - struct checker * c; - char *errstr; - -@@ -83,14 +90,18 @@ struct checker * add_checker (char * name) - return NULL; - snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so", - conf->multipath_dir, name); -+ if (stat(libname,&stbuf) < 0) { -+ condlog(0,"Invalid checker '%s'", name); -+ goto out; -+ } - condlog(3, "loading %s checker", libname); - c->handle = dlopen(libname, RTLD_NOW); -- errstr = dlerror(); -- if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -- if (!c->handle) -+ if (!c->handle) { -+ if ((errstr = dlerror()) != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", -+ errstr); - goto out; -- -+ } - c->check = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_check"); - errstr = dlerror(); - if (errstr != NULL) -diff --git a/libmultipath/prio.c b/libmultipath/prio.c -index 352e9ca..1b9f51b 100644 ---- a/libmultipath/prio.c -+++ b/libmultipath/prio.c -@@ -2,6 +2,7 @@ - #include - #include - #include -+#include - - #include "debug.h" - #include "prio.h" -@@ -19,7 +20,12 @@ int init_prio (void) - - struct prio * alloc_prio (void) - { -- return zalloc(sizeof(struct prio)); -+ struct prio *p; -+ -+ p = zalloc(sizeof(struct prio)); -+ if (p) -+ INIT_LIST_HEAD(&p->node); -+ return p; - } - - void free_prio (struct prio * p) -@@ -59,6 +65,7 @@ struct prio * prio_lookup (char * name) - struct prio * add_prio (char * name) - { - char libname[LIB_PRIO_NAMELEN]; -+ struct stat stbuf; - struct prio * p; - char *errstr; - -@@ -67,13 +74,18 @@ struct prio * add_prio (char * name) - return NULL; - snprintf(libname, LIB_PRIO_NAMELEN, "%s/libprio%s.so", - conf->multipath_dir, name); -+ if (stat(libname,&stbuf) < 0) { -+ condlog(0,"Invalid prioritizer '%s'", name); -+ goto out; -+ } - condlog(3, "loading %s prioritizer", libname); - p->handle = dlopen(libname, RTLD_NOW); -- errstr = dlerror(); -- if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -- if (!p->handle) -+ if (!p->handle) { -+ if ((errstr = dlerror()) != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", -+ errstr); - goto out; -+ } - p->getprio = (int (*)(struct path *)) dlsym(p->handle, "getprio"); - errstr = dlerror(); - if (errstr != NULL) --- -1.6.0.2 - diff --git a/multipath-tools-fix-directio-error-messages b/multipath-tools-fix-directio-error-messages deleted file mode 100644 index effdd84..0000000 --- a/multipath-tools-fix-directio-error-messages +++ /dev/null @@ -1,40 +0,0 @@ -commit 91b2c44cb23076ec0cb647dc42b438f1583677c7 -Author: Hannes Reinecke -Date: Wed Jan 21 13:26:51 2009 +0100 - - Update misleading debug messages for directio checker - - io_getevents returns the number of events received, so '1' - is actual a success. And calling 'strerror(errno)' unconditionally - here will lead to false errors as the errno value won't be - updated then. - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c -index c701609..ecf0dd2 100644 ---- a/libmultipath/checkers/directio.c -+++ b/libmultipath/checkers/directio.c -@@ -149,14 +149,19 @@ check_state(int fd, struct directio_context *ct, int sync) - ct->running++; - - r = io_getevents(ct->ioctx, 1L, 1L, &event, &timeout); -- LOG(3, "async io getevents returns %li (errno=%s)", r, strerror(errno)); - -- if (r < 1L) { -+ if (r < 0 ) { -+ LOG(3, "async io getevents returned %li (errno=%s)", r, -+ strerror(errno)); -+ rc = PATH_UNCHECKED; -+ } else if (r < 1L) { - if (ct->running > ASYNC_TIMEOUT_SEC || sync) { - LOG(3, "abort check on timeout"); - rc = PATH_DOWN; -- } else -+ } else { -+ LOG(3, "async io pending"); - rc = PATH_PENDING; -+ } - } else { - LOG(3, "io finished %lu/%lu", event.res, event.res2); - ct->running = 0; diff --git a/multipath-tools-fix-sysfs_attr_get_value b/multipath-tools-fix-sysfs_attr_get_value deleted file mode 100644 index 80fe6fc..0000000 --- a/multipath-tools-fix-sysfs_attr_get_value +++ /dev/null @@ -1,60 +0,0 @@ -From 67c3b7d8d0ec6f438d11c02c0ad78041ef67d924 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Wed, 7 Jan 2009 10:52:25 +0100 -Subject: [PATCH] Fix sysfs_attr_get_value() - -sysfs_attr_get_value() should return NULL if the attribute was not -found or found to be empty. And we should increase the attribute -value size to avoid overflows. -And overflows should be truncated, not ignored. - -References: bnc#456747 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/structs.h | 2 +- - libmultipath/sysfs.c | 8 +++++--- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/libmultipath/structs.h b/libmultipath/structs.h -index 75bd379..8596e8d 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -10,7 +10,7 @@ - #define CALLOUT_MAX_SIZE 128 - #define BLK_DEV_SIZE 33 - #define PATH_SIZE 512 --#define NAME_SIZE 128 -+#define NAME_SIZE 512 - - - #define SCSI_VENDOR_SIZE 9 -diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c -index c0d4d5f..e00a101 100644 ---- a/libmultipath/sysfs.c -+++ b/libmultipath/sysfs.c -@@ -445,8 +445,10 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) - close(fd); - if (size < 0) - goto out; -- if (size == sizeof(value)) -- goto out; -+ if (size == sizeof(value)) { -+ dbg("overflow in attribute '%s', truncating", path_full); -+ size--; -+ } - - /* got a valid value, store and return it */ - value[size] = '\0'; -@@ -456,7 +458,7 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) - attr->value = attr->value_local; - - out: -- return attr->value; -+ return attr && attr->value && strlen(attr->value) ? attr->value : NULL; - } - - int sysfs_lookup_devpath_by_subsys_id(char *devpath_full, size_t len, --- -1.6.0.2 - diff --git a/multipath-tools-fix-weightedpath-merge-error b/multipath-tools-fix-weightedpath-merge-error deleted file mode 100644 index 3d76a82..0000000 --- a/multipath-tools-fix-weightedpath-merge-error +++ /dev/null @@ -1,47 +0,0 @@ -From 297a4a148a8469e272c6ed0cfb394a38a324fb0b Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Fri, 12 Dec 2008 14:41:51 +0100 -Subject: [PATCH] Fix merge error from prio_weightedpath - -Merge error. - -References: 441007 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/dict.c | 19 +++++++++++-------- - 1 files changed, 11 insertions(+), 8 deletions(-) - -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index 9ba3961..09ecf51 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -640,14 +640,17 @@ hw_prio_handler(vector strvec) - return 1; - temp = buff; - -- while ((result = strsep(&temp, split_char))) { -- if (prio_lookup(result)) { -- conf->prio_name = STRDUP(result); -- if (temp) -- conf->prio_arg = STRDUP(temp); -- else -- conf->prio_arg = NULL; -- break; -+ while (temp) { -+ result = strsep(&temp, split_char); -+ if (strcmp(result, "")) { -+ if (prio_lookup(result)) { -+ hwe->prio_name = STRDUP(result); -+ if (temp) -+ hwe->prio_arg = STRDUP(temp); -+ else -+ hwe->prio_arg = NULL; -+ break; -+ } - } - } - --- -1.6.0.2 - diff --git a/multipath-tools-fixes-for-show-paths-format b/multipath-tools-fixes-for-show-paths-format deleted file mode 100644 index 9735dce..0000000 --- a/multipath-tools-fixes-for-show-paths-format +++ /dev/null @@ -1,123 +0,0 @@ -From 244454da2d4f3cb5d197a6b0e6fc2b4c8d72d08c Mon Sep 17 00:00:00 2001 -From: Christophe Varoqui -Date: Mon, 29 Sep 2008 00:44:46 +0200 -Subject: [PATCH] [libmultipath] fixes for "show paths format" - -o undue 1-char rollback when encountering unknown wildcard -o fix segfault when format starts with an unknown wildard -o continue parsing the format after an unknown wildcard ---- - libmultipath/print.c | 33 +++++++++++++-------------------- - 1 files changed, 13 insertions(+), 20 deletions(-) - -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 459b973..7411ccc 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -28,6 +28,9 @@ - #define NOPAD s = c - #define PAD(x) while ((int)(c - s) < (x) && (c < (line + len - 1))) \ - *c++ = ' '; s = c -+#define ENDLINE \ -+ if (c > line) \ -+ line[c - line - 1] = '\n' - #define PRINT(var, size, format, args...) \ - fwd = snprintf(var, size, format, ##args); \ - c += (fwd >= size) ? size : fwd; -@@ -532,15 +535,13 @@ snprint_multipath_header (char * line, int len, char * format) - f++; - - if (!(data = mpd_lookup(*f))) -- break; /* unknown wildcard */ -+ continue; /* unknown wildcard */ - - PRINT(c, TAIL, data->header); - PAD(data->width); - } while (*f++); - -- line[c - line - 1] = '\n'; -- line[c - line] = '\0'; -- -+ ENDLINE; - return (c - line); - } - -@@ -567,7 +568,7 @@ snprint_multipath (char * line, int len, char * format, - f++; - - if (!(data = mpd_lookup(*f))) -- break; -+ continue; - - data->snprint(buff, MAX_FIELD_LEN, mpp); - PRINT(c, TAIL, buff); -@@ -575,9 +576,7 @@ snprint_multipath (char * line, int len, char * format, - buff[0] = '\0'; - } while (*f++); - -- line[c - line - 1] = '\n'; -- line[c - line] = '\0'; -- -+ ENDLINE; - return (c - line); - } - -@@ -602,15 +601,13 @@ snprint_path_header (char * line, int len, char * format) - f++; - - if (!(data = pd_lookup(*f))) -- break; /* unknown wildcard */ -+ continue; /* unknown wildcard */ - - PRINT(c, TAIL, data->header); - PAD(data->width); - } while (*f++); - -- line[c - line - 1] = '\n'; -- line[c - line] = '\0'; -- -+ ENDLINE; - return (c - line); - } - -@@ -637,16 +634,14 @@ snprint_path (char * line, int len, char * format, - f++; - - if (!(data = pd_lookup(*f))) -- break; -+ continue; - - data->snprint(buff, MAX_FIELD_LEN, pp); - PRINT(c, TAIL, buff); - PAD(data->width); - } while (*f++); - -- line[c - line - 1] = '\n'; -- line[c - line] = '\0'; -- -+ ENDLINE; - return (c - line); - } - -@@ -673,16 +668,14 @@ snprint_pathgroup (char * line, int len, char * format, - f++; - - if (!(data = pgd_lookup(*f))) -- break; -+ continue; - - data->snprint(buff, MAX_FIELD_LEN, pgp); - PRINT(c, TAIL, buff); - PAD(data->width); - } while (*f++); - -- line[c - line - 1] = '\n'; -- line[c - line] = '\0'; -- -+ ENDLINE; - return (c - line); - } - --- -1.5.2.4 - diff --git a/multipath-tools-fixup-scsi_id-for-cciss b/multipath-tools-fixup-scsi_id-for-cciss deleted file mode 100644 index d71a0a8..0000000 --- a/multipath-tools-fixup-scsi_id-for-cciss +++ /dev/null @@ -1,29 +0,0 @@ -From 62ff5068186fd0baf3d93ea85b00aaffe3bf4810 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Wed, 29 Oct 2008 17:00:16 +0100 -Subject: [PATCH] Incorrect scsi_id commandline for cciss - -The scsi_id program was called with incorrect commandline -for cciss devices. Fix. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/hwtable.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index f87907d..fda131c 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -193,7 +193,7 @@ static struct hwentry default_hw[] = { - /* HP Smart Array */ - .vendor = "HP", - .product = "LOGICAL VOLUME.*", -- .getuid = "/lib/udev/scsi_id -n -g -u -d /dev/%n", -+ .getuid = "/lib/udev/scsi_id -g -u -d /dev/%n", - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, --- -1.5.4.5 - diff --git a/multipath-tools-fopen-returns-NULL b/multipath-tools-fopen-returns-NULL deleted file mode 100644 index d9f6499..0000000 --- a/multipath-tools-fopen-returns-NULL +++ /dev/null @@ -1,28 +0,0 @@ -From 3cf5b5aaa64e673364e8758640e5d5434425235b Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 9 Oct 2008 12:53:38 +0200 -Subject: [PATCH] fopen returns NULL on failure, not -1 - -References: 432598 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/discovery.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index e1a67ac..a5ae8aa 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -237,7 +237,7 @@ devt2devname (char *devname, char *devt) - return 1; - } - -- if ((fd = fopen("/proc/partitions", "r")) < 0) { -+ if (!(fd = fopen("/proc/partitions", "r"))) { - condlog(0, "Cannot open /proc/partitions"); - return 1; - } --- -1.5.2.4 - diff --git a/multipath-tools-git-update b/multipath-tools-git-update deleted file mode 100644 index 3fb5337..0000000 --- a/multipath-tools-git-update +++ /dev/null @@ -1,14275 +0,0 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..5ef5aec ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,9 @@ -+*.o -+.dotest -+*~ -+*.so -+*.a -+*.gz -+kpartx -+multipath -+multipathd -diff --git a/Makefile b/Makefile -index ee554e7..54be0a5 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,8 +1,7 @@ - # Makefile - # - # Copyright (C) 2003 Christophe Varoqui, -- --BUILD = glibc -+# - - # - # Try to supply the linux kernel headers. -@@ -20,7 +19,13 @@ endif - export KRNLSRC - export KRNLOBJ - --BUILDDIRS = $(shell find . -mindepth 2 -name Makefile -exec dirname {} \; | grep -vE '^lib|/\.') -+BUILDDIRS = \ -+ libmultipath \ -+ libmultipath/prioritizers \ -+ libmultipath/checkers \ -+ multipath \ -+ multipathd \ -+ kpartx - - ifeq ($(MULTIPATH_VERSION),) - VERSION = $(shell basename ${PWD} | cut -d'-' -f3) -diff --git a/Makefile.inc b/Makefile.inc -index 7e2d4e6..3e5bca0 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -13,31 +13,22 @@ ifeq ($(TOPDIR),) - TOPDIR = .. - endif - --ifeq ($(strip $(BUILD)),klibc) -- CC = klcc -- klibcdir = /usr/lib/klibc -- libdm = $(klibcdir)/lib/libdevmapper.a --endif -- - prefix = - exec_prefix = $(prefix) - bindir = $(exec_prefix)/sbin - libudevdir = ${prefix}/lib/udev --checkersdir = $(TOPDIR)/libcheckers - multipathdir = $(TOPDIR)/libmultipath - mandir = $(prefix)/usr/share/man/man8 - man5dir = $(prefix)/usr/share/man/man5 - rcdir = $(prefix)/etc/init.d -+libdir = $(prefix)/lib/multipath - - GZIP = /bin/gzip -9 -c -- --CHECKERSLIB = $(checkersdir)/libcheckers --MULTIPATHLIB = $(multipathdir)/libmultipath -- --INSTALL_PROGRAM = install -s -+INSTALL_PROGRAM = install - - OPTFLAGS = -pipe -g -Wall -Wunused -Wstrict-prototypes --CFLAGS = $(OPTFLAGS) -+CFLAGS = $(OPTFLAGS) -fPIC -+SHARED_FLAGS = -shared - - %.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< -diff --git a/devmap_name/Makefile b/devmap_name/Makefile -deleted file mode 100644 -index d8d8b09..0000000 ---- a/devmap_name/Makefile -+++ /dev/null -@@ -1,42 +0,0 @@ --# Makefile --# --# Copyright (C) 2003 Christophe Varoqui, --BUILD = glibc -- --include ../Makefile.inc -- --OBJS = devmap_name.o -- --ifeq ($(strip $(BUILD)),klibc) -- OBJS += $(libdm) --else -- LDFLAGS = -ldevmapper --endif -- --EXEC = devmap_name -- --all: $(BUILD) -- --prepare: -- rm -f core *.o *.gz -- --glibc: prepare $(OBJS) -- $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) -- $(GZIP) $(EXEC).8 > $(EXEC).8.gz -- --klibc: prepare $(OBJS) -- $(CC) -static -o $(EXEC) $(OBJS) -- $(GZIP) $(EXEC).8 > $(EXEC).8.gz -- --install: $(EXEC) $(EXEC).8 -- install -d $(DESTDIR)$(bindir) -- install -m 755 $(EXEC) $(DESTDIR)$(bindir)/ -- install -d $(DESTDIR)$(mandir) -- install -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) -- rm $(DESTDIR)$(mandir)/$(EXEC).8.gz -- --clean: -- rm -f core *.o $(EXEC) *.gz -diff --git a/devmap_name/devmap_name.8 b/devmap_name/devmap_name.8 -deleted file mode 100644 -index 86d0931..0000000 ---- a/devmap_name/devmap_name.8 -+++ /dev/null -@@ -1,30 +0,0 @@ --.TH DEVMAP_NAME 8 "July 2006" "" "Linux Administrator's Manual" --.SH NAME --devmap_name \- Query device-mapper name --.SH SYNOPSIS --.BI devmap_name " major minor" --.SH DESCRIPTION --.B devmap_name --queries the device-mapper for the name for the device --specified by --.I major --and --.I minor --number. --.br --.B devmap_name --can be called from --.B udev --by the following rule in --.IR /etc/udev/udev.rules : --.sp --.nf --KERNEL="dm-[0-9]*", PROGRAM="/sbin/devmap_name %M %m", \\ -- NAME="%k", SYMLINK="%c" --.fi --.SH "SEE ALSO" --.BR udev (8), --.BR dmsetup (8) --.SH AUTHORS --.B devmap_name --was developed by Christophe Varoqui, and others. -diff --git a/devmap_name/devmap_name.c b/devmap_name/devmap_name.c -deleted file mode 100644 -index 525c348..0000000 ---- a/devmap_name/devmap_name.c -+++ /dev/null -@@ -1,88 +0,0 @@ --/* -- * Copyright (c) 2004, 2005 Christophe Varoqui -- */ --#include --#include --#include --#include --#include --#include --#include -- --static void usage(char * progname) { -- fprintf(stderr, "usage : %s [-t target type] dev_t\n", progname); -- fprintf(stderr, "where dev_t is either 'major minor' or 'major:minor'\n"); -- exit(1); --} -- --int dm_target_type(int major, int minor, char *type) --{ -- struct dm_task *dmt; -- void *next = NULL; -- uint64_t start, length; -- char *target_type = NULL; -- char *params; -- int r = 1; -- -- if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) -- return 1; -- -- if (!dm_task_set_major(dmt, major) || -- !dm_task_set_minor(dmt, minor)) -- goto bad; -- -- dm_task_no_open_count(dmt); -- -- if (!dm_task_run(dmt)) -- goto bad; -- -- if (!type) -- goto good; -- -- do { -- next = dm_get_next_target(dmt, next, &start, &length, -- &target_type, ¶ms); -- if (target_type && strcmp(target_type, type)) -- goto bad; -- } while (next); -- --good: -- printf("%s\n", dm_task_get_name(dmt)); -- r = 0; --bad: -- dm_task_destroy(dmt); -- return r; --} -- --int main(int argc, char **argv) --{ -- int c; -- int major, minor; -- char *target_type = NULL; -- -- while ((c = getopt(argc, argv, "t:")) != -1) { -- switch (c) { -- case 't': -- target_type = optarg; -- break; -- default: -- usage(argv[0]); -- return 1; -- break; -- } -- } -- -- /* sanity check */ -- if (optind == argc - 2) { -- major = atoi(argv[argc - 2]); -- minor = atoi(argv[argc - 1]); -- } else if (optind != argc - 1 || -- 2 != sscanf(argv[argc - 1], "%i:%i", &major, &minor)) -- usage(argv[0]); -- -- if (dm_target_type(major, minor, target_type)) -- return 1; -- -- return 0; --} -- -diff --git a/kpartx/Makefile b/kpartx/Makefile -index b4cca6c..21e4ad4 100644 ---- a/kpartx/Makefile -+++ b/kpartx/Makefile -@@ -2,49 +2,30 @@ - # - # Copyright (C) 2003 Christophe Varoqui, - # --BUILD=glibc -- - include ../Makefile.inc - - CFLAGS += -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 - --ifeq ($(strip $(BUILD)),klibc) -- OBJS = bsd.o dos.o kpartx.o solaris.o unixware.o gpt.o crc32.o \ -- lopart.o xstrncpy.o devmapper.o dasd.o mac.o sun.o \ -- $(MULTIPATHLIB)-$(BUILD).a $(libdm) --else -- LDFLAGS = -ldevmapper -- OBJS = bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \ -- gpt.o mac.o crc32.o lopart.o xstrncpy.o devmapper.o --endif -- -+LDFLAGS = -ldevmapper -+OBJS = bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \ -+ gpt.o mac.o crc32.o lopart.o xstrncpy.o devmapper.o - EXEC = kpartx - --all: $(BUILD) -- --prepare: -- rm -f core *.o *.gz -+all: $(EXEC) - --glibc: prepare $(OBJS) -+$(EXEC): $(OBJS) - $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) - $(GZIP) $(EXEC).8 > $(EXEC).8.gz - --klibc: prepare $(OBJS) -- $(CC) -static -o $(EXEC) $(CRT0) $(OBJS) $(KLIBC) $(LIBGCC) -- $(GZIP) $(EXEC).8 > $(EXEC).8.gz -- --$(MULTIPATHLIB)-$(BUILD).a: -- make -C $(multipathdir) BUILD=$(BUILD) -- - install: $(EXEC) $(EXEC).8 -- install -d $(DESTDIR)$(bindir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) -- install -d $(DESTDIR)$(libudevdir) -- install -m 755 kpartx_id $(DESTDIR)$(libudevdir) -- install -d $(DESTDIR)/etc/udev/rules.d -- install -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/ -- install -d $(DESTDIR)$(mandir) -- install -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir) -+ $(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d -+ $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/ -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) - - uninstall: - rm -f $(DESTDIR)$(bindir)/$(EXEC) -diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c -index 6e3e198..893d6dd 100644 ---- a/kpartx/devmapper.c -+++ b/kpartx/devmapper.c -@@ -4,10 +4,12 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include "devmapper.h" - - #define UUID_PREFIX "part%d-" - #define MAX_PREFIX_LEN 8 -@@ -72,10 +74,10 @@ dm_simplecmd (int task, const char *name) { - - extern int - dm_addmap (int task, const char *name, const char *target, -- const char *params, unsigned long size, const char *uuid, int part) { -+ const char *params, uint64_t size, const char *uuid, int part) { - int r = 0; - struct dm_task *dmt; -- char *prefixed_uuid; -+ char *prefixed_uuid = NULL; - - if (!(dmt = dm_task_create (task))) - return 0; -diff --git a/kpartx/devmapper.h b/kpartx/devmapper.h -index ccdbead..2bd27d2 100644 ---- a/kpartx/devmapper.h -+++ b/kpartx/devmapper.h -@@ -1,7 +1,7 @@ - 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, -- char *, int); -+int dm_addmap (int, const char *, const char *, const char *, uint64_t, -+ const char *, int); - int dm_map_present (char *); - char * dm_mapname(int major, int minor); - dev_t dm_get_first_dep(char *devname); -diff --git a/kpartx/gpt.c b/kpartx/gpt.c -index dc846ca..047a829 100644 ---- a/kpartx/gpt.c -+++ b/kpartx/gpt.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - #include "crc32.h" - - #if BYTE_ORDER == LITTLE_ENDIAN -@@ -50,10 +51,18 @@ - # define __cpu_to_le32(x) bswap_32(x) - #endif - -+#ifndef BLKGETLASTSECT - #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */ -+#endif -+#ifndef BLKGETSIZE - #define BLKGETSIZE _IO(0x12,96) /* return device size */ -+#endif -+#ifndef BLKSSZGET - #define BLKSSZGET _IO(0x12,104) /* get block device sector size */ -+#endif -+#ifndef BLKGETSIZE64 - #define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */ -+#endif - - struct blkdev_ioctl_param { - unsigned int block; -@@ -143,20 +152,14 @@ get_sector_size(int filedes) - static uint64_t - _get_num_sectors(int filedes) - { -- unsigned long sectors=0; - int rc; --#if 0 -- uint64_t bytes=0; -+ uint64_t bytes=0; - -- rc = ioctl(filedes, BLKGETSIZE64, &bytes); -+ rc = ioctl(filedes, BLKGETSIZE64, &bytes); - if (!rc) - return bytes / get_sector_size(filedes); --#endif -- rc = ioctl(filedes, BLKGETSIZE, §ors); -- if (rc) -- return 0; -- -- return sectors; -+ -+ return 0; - } - - /************************************************************ -@@ -193,7 +196,7 @@ last_lba(int filedes) - sectors = 1; - } - -- return sectors - 1; -+ return sectors ? sectors - 1 : 0; - } - - -@@ -220,17 +223,22 @@ read_lba(int fd, uint64_t lba, void *buffer, size_t bytes) - { - int sector_size = get_sector_size(fd); - off_t offset = lba * sector_size; -+ uint64_t lastlba; - ssize_t bytesread; - - lseek(fd, offset, SEEK_SET); - bytesread = read(fd, buffer, bytes); - -+ lastlba = last_lba(fd); -+ if (!lastlba) -+ return bytesread; -+ - /* Kludge. This is necessary to read/write the last - block of an odd-sized disk, until Linux 2.5.x kernel fixes. - This is only used by gpt.c, and only to read - one sector, so we don't have to be fancy. - */ -- if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) { -+ if (!bytesread && !(lastlba & 1) && lba == lastlba) { - bytesread = read_lastoddsector(fd, lba, buffer, bytes); - } - return bytesread; -@@ -505,7 +513,8 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes) - if (!gpt || !ptes) - return 0; - -- lastlba = last_lba(fd); -+ if (!(lastlba = last_lba(fd))) -+ return 0; - good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA, - &pgpt, &pptes); - if (good_pgpt) { -diff --git a/kpartx/kpartx.8 b/kpartx/kpartx.8 -index 87b07ce..c61f312 100644 ---- a/kpartx/kpartx.8 -+++ b/kpartx/kpartx.8 -@@ -26,6 +26,9 @@ List partition mappings that would be added -a - .B \-p - set device name-partition number delimiter - .TP -+.B \-g -+force GUID partition table (GPT) -+.TP - .B \-v - Operate verbosely - .SH "SEE ALSO" -diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c -index dbe2ee2..8658731 100644 ---- a/kpartx/kpartx.c -+++ b/kpartx/kpartx.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -82,7 +83,7 @@ initpts(void) - addpts("sun", read_sun_pt); - } - --static char short_opts[] = "ladgvnp:t:"; -+static char short_opts[] = "ladgvp:t:"; - - /* Used in gpt.c */ - int force_gpt=0; -@@ -94,6 +95,7 @@ usage(void) { - printf("\t-d del partition devmappings\n"); - printf("\t-l list partitions devmappings that would be added by -a\n"); - printf("\t-p set device name-partition number delimiter\n"); -+ printf("\t-g force GUID partition table (GPT)\n"); - printf("\t-v verbose\n"); - return 1; - } -@@ -187,8 +189,7 @@ main(int argc, char **argv){ - struct slice all; - struct pt *ptp; - enum action what = LIST; -- char *p, *type, *diskdevice, *device, *progname; -- int lower, upper; -+ char *type, *diskdevice, *device, *progname; - int verbose = 0; - char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16]; - char * loopdev = NULL; -@@ -202,7 +203,6 @@ main(int argc, char **argv){ - initpts(); - init_crc32(); - -- lower = upper = 0; - type = device = diskdevice = NULL; - memset(&all, 0, sizeof(all)); - memset(&partname, 0, sizeof(partname)); -@@ -239,14 +239,6 @@ main(int argc, char **argv){ - case 'v': - verbose = 1; - break; -- case 'n': -- p = optarg; -- lower = atoi(p); -- if ((p[1] == '-') && p[2]) -- upper = atoi(p+2); -- else -- upper = lower; -- break; - case 'p': - delim = optarg; - break; -@@ -331,10 +323,9 @@ main(int argc, char **argv){ - perror(device); - exit(1); - } -- if (!lower) -- lower = 1; - - /* add/remove partitions to the kernel devmapper tables */ -+ int r = 0; - for (i = 0; i < ptct; i++) { - ptp = &pts[i]; - -@@ -366,16 +357,16 @@ main(int argc, char **argv){ - - slices[j].minor = m++; - -- printf("%s%s%d : 0 %lu %s %lu\n", -+ printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n", - mapname, delim, j+1, -- (unsigned long) slices[j].size, device, -- (unsigned long) slices[j].start); -+ slices[j].size, device, -+ slices[j].start); - } - /* Loop to resolve contained slices */ - d = c; - while (c) { - for (j = 0; j < n; j++) { -- unsigned long start; -+ uint64_t start; - int k = slices[j].container - 1; - - if (slices[j].size == 0) -@@ -387,9 +378,9 @@ main(int argc, char **argv){ - slices[j].minor = m++; - - start = slices[j].start - slices[k].start; -- printf("%s%s%d : 0 %lu /dev/dm-%d %lu\n", -+ printf("%s%s%d : 0 %" PRIu64 " /dev/dm-%d %" PRIu64 "\n", - mapname, delim, j+1, -- (unsigned long) slices[j].size, -+ slices[j].size, - slices[k].minor, start); - c--; - } -@@ -401,7 +392,7 @@ main(int argc, char **argv){ - break; - - case DELETE: -- for (j = 0; j < n; j++) { -+ for (j = n-1; j >= 0; j--) { - if (safe_sprintf(partname, "%s%s%d", - mapname, delim, j+1)) { - fprintf(stderr, "partname too small\n"); -@@ -412,9 +403,10 @@ main(int argc, char **argv){ - if (!slices[j].size || !dm_map_present(partname)) - continue; - -- if (!dm_simplecmd(DM_DEVICE_REMOVE, partname)) -+ if (!dm_simplecmd(DM_DEVICE_REMOVE, partname)) { -+ r++; - continue; -- -+ } - if (verbose) - printf("del devmap : %s\n", partname); - } -@@ -448,8 +440,8 @@ main(int argc, char **argv){ - } - strip_slash(partname); - -- if (safe_sprintf(params, "%s %lu", device, -- (unsigned long)slices[j].start)) { -+ if (safe_sprintf(params, "%s %" PRIu64 , -+ device, slices[j].start)) { - fprintf(stderr, "params too small\n"); - exit(1); - } -@@ -457,18 +449,23 @@ main(int argc, char **argv){ - op = (dm_map_present(partname) ? - DM_DEVICE_RELOAD : DM_DEVICE_CREATE); - -- dm_addmap(op, partname, DM_TARGET, params, -- slices[j].size, uuid, j+1); -- -- if (op == DM_DEVICE_RELOAD) -- dm_simplecmd(DM_DEVICE_RESUME, -- partname); -- -+ if (!dm_addmap(op, partname, DM_TARGET, params, -+ slices[j].size, uuid, j+1)) { -+ fprintf(stderr, "create/reload failed on %s\n", -+ partname); -+ r++; -+ } -+ if (op == DM_DEVICE_RELOAD && -+ !dm_simplecmd(DM_DEVICE_RESUME, partname)) { -+ fprintf(stderr, "resume failed on %s\n", -+ partname); -+ r++; -+ } - dm_devn(partname, &slices[j].major, - &slices[j].minor); - - if (verbose) -- printf("add map %s (%d:%d): 0 %lu %s %s\n", -+ printf("add map %s (%d:%d): 0 %" PRIu64 " %s %s\n", - partname, slices[j].major, - slices[j].minor, slices[j].size, - DM_TARGET, params); -@@ -502,10 +499,10 @@ main(int argc, char **argv){ - } - strip_slash(partname); - -- if (safe_sprintf(params, "%d:%d %lu", -+ if (safe_sprintf(params, "%d:%d %" PRIu64, - slices[k].major, - slices[k].minor, -- (unsigned long)slices[j].start)) { -+ slices[j].start)) { - fprintf(stderr, "params too small\n"); - exit(1); - } -@@ -524,7 +521,7 @@ main(int argc, char **argv){ - &slices[j].minor); - - if (verbose) -- printf("add map %s : 0 %lu %s %s\n", -+ printf("add map %s : 0 %" PRIu64 " %s %s\n", - partname, slices[j].size, - DM_TARGET, params); - c--; -@@ -545,7 +542,7 @@ main(int argc, char **argv){ - dm_lib_release(); - dm_lib_exit(); - -- return 0; -+ return r; - } - - void * -diff --git a/kpartx/kpartx.h b/kpartx/kpartx.h -index 9b3aeca..43ae3f8 100644 ---- a/kpartx/kpartx.h -+++ b/kpartx/kpartx.h -@@ -1,6 +1,8 @@ - #ifndef _KPARTX_H - #define _KPARTX_H - -+#include -+ - /* - * For each partition type there is a routine that takes - * a block device and a range, and returns the list of -@@ -20,8 +22,8 @@ - * units: 512 byte sectors - */ - struct slice { -- unsigned long start; -- unsigned long size; -+ uint64_t start; -+ uint64_t size; - int container; - int major; - int minor; -diff --git a/libcheckers/Makefile b/libcheckers/Makefile -deleted file mode 100644 -index 6340a68..0000000 ---- a/libcheckers/Makefile -+++ /dev/null -@@ -1,27 +0,0 @@ --# Makefile --# --# Copyright (C) 2003 Christophe Varoqui, --# --BUILD = glibc -- --include ../Makefile.inc -- --OBJS = libsg.o checkers.o readsector0.o tur.o directio.o emc_clariion.o hp_sw.o rdac.o -- --all: $(BUILD) -- --prepare: -- @file *-$(BUILD).a >/dev/null 2>&1 || rm -f core *.o *.gz -- --klibc: prepare $(OBJS) -- ar rs libcheckers-klibc.a *.o -- --glibc: prepare $(OBJS) -- ar rs libcheckers-glibc.a *.o -- --install: -- --uninstall: -- --clean: -- rm -f core *.a *.o *.gz -diff --git a/libcheckers/checkers.c b/libcheckers/checkers.c -deleted file mode 100644 -index d7728a5..0000000 ---- a/libcheckers/checkers.c -+++ /dev/null -@@ -1,159 +0,0 @@ --#include --#include -- --#include "checkers.h" -- --#include "directio.h" --#include "tur.h" --#include "hp_sw.h" --#include "emc_clariion.h" --#include "rdac.h" --#include "readsector0.h" -- --static struct checker checkers[] = { -- { -- .fd = 0, -- .sync = 1, -- .name = DIRECTIO, -- .message = "", -- .context = NULL, -- .check = directio, -- .init = directio_init, -- .free = directio_free -- }, -- { -- .fd = 0, -- .sync = 1, -- .name = TUR, -- .message = "", -- .context = NULL, -- .check = tur, -- .init = tur_init, -- .free = tur_free -- }, -- { -- .fd = 0, -- .sync = 1, -- .name = HP_SW, -- .message = "", -- .context = NULL, -- .check = hp_sw, -- .init = hp_sw_init, -- .free = hp_sw_free -- }, -- { -- .fd = 0, -- .sync = 1, -- .name = EMC_CLARIION, -- .message = "", -- .context = NULL, -- .check = emc_clariion, -- .init = emc_clariion_init, -- .free = emc_clariion_free -- }, -- { -- .fd = 0, -- .sync = 1, -- .name = RDAC, -- .message = "", -- .context = NULL, -- .check = rdac, -- .init = rdac_init, -- .free = rdac_free -- }, -- { -- .fd = 0, -- .sync = 1, -- .name = READSECTOR0, -- .message = "", -- .context = NULL, -- .check = readsector0, -- .init = readsector0_init, -- .free = readsector0_free -- }, -- {0, 1, "", "", NULL, NULL, NULL, NULL}, --}; -- --void checker_set_fd (struct checker * c, int fd) --{ -- c->fd = fd; --} -- --void checker_set_sync (struct checker * c) --{ -- c->sync = 1; --} -- --void checker_set_async (struct checker * c) --{ -- c->sync = 0; --} -- --struct checker * checker_lookup (char * name) --{ -- struct checker * c = &checkers[0]; -- -- while (c->check) { -- if (!strncmp(name, c->name, CHECKER_NAME_LEN)) -- return c; -- c++; -- } -- return NULL; --} -- --int checker_init (struct checker * c, void ** mpctxt_addr) --{ -- c->mpcontext = mpctxt_addr; -- return c->init(c); --} -- --void checker_put (struct checker * c) --{ -- if (c->free) -- c->free(c); -- memset(c, 0x0, sizeof(struct checker)); --} -- --int checker_check (struct checker * c) --{ -- int r; -- -- if (c->fd <= 0) { -- MSG(c, "no usable fd"); -- return PATH_WILD; -- } -- r = c->check(c); -- -- return r; --} -- --int checker_selected (struct checker * c) --{ -- return (c->check) ? 1 : 0; --} -- --char * checker_name (struct checker * c) --{ -- return c->name; --} -- --char * checker_message (struct checker * c) --{ -- return c->message; --} -- --struct checker * checker_default (void) --{ -- return checker_lookup(DEFAULT_CHECKER); --} -- --void checker_get (struct checker * dst, struct checker * src) --{ -- dst->fd = src->fd; -- dst->sync = src->sync; -- strncpy(dst->name, src->name, CHECKER_NAME_LEN); -- strncpy(dst->message, src->message, CHECKER_MSG_LEN); -- dst->check = src->check; -- dst->init = src->init; -- dst->free = src->free; --} -diff --git a/libcheckers/checkers.h b/libcheckers/checkers.h -deleted file mode 100644 -index 9b270eb..0000000 ---- a/libcheckers/checkers.h -+++ /dev/null -@@ -1,116 +0,0 @@ --#ifndef _CHECKERS_H --#define _CHECKERS_H -- --/* -- * -- * Userspace (multipath/multipathd) path states -- * -- * PATH_WILD: -- * - Use: None of the checkers (returned if we don't have an fd) -- * - Description: Corner case where "fd <= 0" for path fd (see checker_check()) -- * -- * PATH_UNCHECKED: -- * - Use: Only in directio checker -- * - Description: set when fcntl(F_GETFL) fails to return flags or O_DIRECT -- * not include in flags, or O_DIRECT read fails -- * - Notes: -- * - multipathd: uses it to skip over paths in sync_map_state() -- * - multipath: used in update_paths(); if state==PATH_UNCHECKED, call -- * pathinfo() -- * -- * PATH_DOWN: -- * - Use: All checkers (directio, emc_clariion, hp_sw, readsector0, tur) -- * - Description: Either a) SG_IO ioctl failed, or b) check condition on some -- * SG_IO ioctls that succeed (tur, readsector0 checkers); path is down and -- * you shouldn't try to send commands to it -- * -- * PATH_UP: -- * - Use: All checkers (directio, emc_clariion, hp_sw, readsector0, tur) -- * - Description: Path is up and I/O can be sent to it -- * -- * PATH_SHAKY: -- * - Use: Only emc_clariion -- * - Description: Indicates path not available for "normal" operations -- * -- * PATH_GHOST: -- * - Use: Only hp_sw -- * - Description: Indicates a "passive/standby" path on active/passive HP -- * arrays. These paths will return valid answers to certain SCSI commands -- * (tur, read_capacity, inquiry, start_stop), but will fail I/O commands. -- * The path needs an initialization command to be sent to it in order for -- * I/Os to succeed. -- * -- * PATH_PENDING: -- * - Use: All async checkers -- * - Description: Indicates a check IO is in flight. -- */ --#define PATH_WILD -1 --#define PATH_UNCHECKED 0 --#define PATH_DOWN 1 --#define PATH_UP 2 --#define PATH_SHAKY 3 --#define PATH_GHOST 4 --#define PATH_PENDING 5 -- --#define DIRECTIO "directio" --#define TUR "tur" --#define HP_SW "hp_sw" --#define RDAC "rdac" --#define EMC_CLARIION "emc_clariion" --#define READSECTOR0 "readsector0" -- --#define DEFAULT_CHECKER DIRECTIO -- --/* -- * 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 --#define ASYNC_TIMEOUT_SEC 30 -- --/* -- * strings lengths -- */ --#define CHECKER_NAME_LEN 16 --#define CHECKER_MSG_LEN 256 --#define CHECKER_DEV_LEN 256 -- --struct checker { -- int fd; -- int sync; -- char name[CHECKER_NAME_LEN]; -- char message[CHECKER_MSG_LEN]; /* comm with callers */ -- void * context; /* store for persistent data */ -- void ** mpcontext; /* store for persistent data -- shared multipath-wide */ -- int (*check)(struct checker *); -- int (*init)(struct checker *); /* to allocate the context */ -- void (*free)(struct checker *); /* to free the context */ --}; -- --#define MSG(c, fmt, args...) snprintf((c)->message, CHECKER_MSG_LEN, fmt, ##args); -- --int checker_init (struct checker *, void **); --void checker_put (struct checker *); --void checker_reset (struct checker * c); --void checker_set_sync (struct checker * c); --void checker_set_async (struct checker * c); --void checker_set_fd (struct checker *, int); --struct checker * checker_lookup (char *); --int checker_check (struct checker *); --int checker_selected (struct checker *); --char * checker_name (struct checker *); --char * checker_message (struct checker *); --struct checker * checker_default (void); --void checker_get (struct checker *, struct checker *); -- --#endif /* _CHECKERS_H */ -diff --git a/libcheckers/directio.c b/libcheckers/directio.c -deleted file mode 100644 -index ee09af7..0000000 ---- a/libcheckers/directio.c -+++ /dev/null -@@ -1,197 +0,0 @@ --/* -- * Copyright (c) 2005 Hannes Reinecke, Suse -- */ --#define _GNU_SOURCE --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "checkers.h" --#include "../libmultipath/debug.h" -- --#define MSG_DIRECTIO_UNKNOWN "directio checker is not available" --#define MSG_DIRECTIO_UP "directio checker reports path is up" --#define MSG_DIRECTIO_DOWN "directio checker reports path is down" --#define MSG_DIRECTIO_PENDING "directio checker is waiting on aio" -- --#define LOG(prio, fmt, args...) condlog(prio, "directio: " fmt, ##args) -- --struct directio_context { -- int running; -- int reset_flags; -- int blksize; -- unsigned char * buf; -- unsigned char * ptr; -- io_context_t ioctx; -- struct iocb io; --}; -- -- --int directio_init (struct checker * c) --{ -- unsigned long pgsize = getpagesize(); -- struct directio_context * ct; -- long flags; -- -- ct = malloc(sizeof(struct directio_context)); -- if (!ct) -- return 1; -- memset(ct, 0, sizeof(struct directio_context)); -- -- if (io_setup(1, &ct->ioctx) != 0) { -- condlog(1, "io_setup failed"); -- free(ct); -- return 1; -- } -- -- if (ioctl(c->fd, BLKBSZGET, &ct->blksize) < 0) { -- MSG(c, "cannot get blocksize, set default"); -- ct->blksize = 512; -- } -- if (ct->blksize > 4096) { -- /* -- * Sanity check for DASD; BSZGET is broken -- */ -- ct->blksize = 4096; -- } -- if (!ct->blksize) -- goto out; -- ct->buf = (unsigned char *)malloc(ct->blksize + pgsize); -- if (!ct->buf) -- goto out; -- -- flags = fcntl(c->fd, F_GETFL); -- if (flags < 0) -- goto out; -- if (!(flags & O_DIRECT)) { -- flags |= O_DIRECT; -- if (fcntl(c->fd, F_SETFL, flags) < 0) -- goto out; -- ct->reset_flags = 1; -- } -- -- ct->ptr = (unsigned char *) (((unsigned long)ct->buf + pgsize - 1) & -- (~(pgsize - 1))); -- -- /* Sucessfully initialized, return the context. */ -- c->context = (void *) ct; -- return 0; -- --out: -- if (ct->buf) -- free(ct->buf); -- io_destroy(ct->ioctx); -- free(ct); -- return 1; --} -- --void directio_free (struct checker * c) --{ -- struct directio_context * ct = (struct directio_context *)c->context; -- long flags; -- -- if (!ct) -- return; -- -- if (ct->reset_flags) { -- if ((flags = fcntl(c->fd, F_GETFL)) >= 0) { -- flags &= ~O_DIRECT; -- /* No point in checking for errors */ -- fcntl(c->fd, F_SETFL, flags); -- } -- } -- -- if (ct->buf) -- free(ct->buf); -- io_destroy(ct->ioctx); -- free(ct); --} -- --static int --check_state(int fd, struct directio_context *ct, int sync) --{ -- struct timespec timeout = { .tv_nsec = 5 }; -- struct io_event event; -- struct stat sb; -- int rc = PATH_UNCHECKED; -- long r; -- -- if (fstat(fd, &sb) == 0) { -- LOG(4, "called for %x", (unsigned) sb.st_rdev); -- } -- if (sync) { -- LOG(4, "called in synchronous mode"); -- timeout.tv_sec = ASYNC_TIMEOUT_SEC; -- timeout.tv_nsec = 0; -- } -- -- if (!ct->running) { -- struct iocb *ios[1] = { &ct->io }; -- -- LOG(3, "starting new request"); -- memset(&ct->io, 0, sizeof(struct iocb)); -- io_prep_pread(&ct->io, fd, ct->ptr, ct->blksize, 0); -- if (io_submit(ct->ioctx, 1, ios) != 1) { -- LOG(3, "io_submit error %i", errno); -- return PATH_UNCHECKED; -- } -- } -- ct->running++; -- -- r = io_getevents(ct->ioctx, 1L, 1L, &event, &timeout); -- LOG(3, "async io getevents returns %li (errno=%s)", r, strerror(errno)); -- -- if (r < 1L) { -- if (ct->running > ASYNC_TIMEOUT_SEC || sync) { -- LOG(3, "abort check on timeout"); -- rc = PATH_DOWN; -- } else -- rc = PATH_PENDING; -- } else { -- LOG(3, "io finished %lu/%lu", event.res, event.res2); -- ct->running = 0; -- rc = (event.res == ct->blksize) ? PATH_UP : PATH_DOWN; -- } -- -- return rc; --} -- --int directio (struct checker * c) --{ -- int ret; -- struct directio_context * ct = (struct directio_context *)c->context; -- -- if (!ct) -- return PATH_UNCHECKED; -- -- ret = check_state(c->fd, ct, c->sync); -- -- switch (ret) -- { -- case PATH_UNCHECKED: -- MSG(c, MSG_DIRECTIO_UNKNOWN); -- break; -- case PATH_DOWN: -- MSG(c, MSG_DIRECTIO_DOWN); -- break; -- case PATH_UP: -- MSG(c, MSG_DIRECTIO_UP); -- break; -- case PATH_PENDING: -- MSG(c, MSG_DIRECTIO_PENDING); -- break; -- default: -- break; -- } -- return ret; --} -diff --git a/libcheckers/directio.h b/libcheckers/directio.h -deleted file mode 100644 -index 1865b1f..0000000 ---- a/libcheckers/directio.h -+++ /dev/null -@@ -1,8 +0,0 @@ --#ifndef _DIRECTIO_H --#define _DIRECTIO_H -- --int directio (struct checker *); --int directio_init (struct checker *); --void directio_free (struct checker *); -- --#endif /* _DIRECTIO_H */ -diff --git a/libcheckers/emc_clariion.c b/libcheckers/emc_clariion.c -deleted file mode 100644 -index 6c7167e..0000000 ---- a/libcheckers/emc_clariion.c -+++ /dev/null -@@ -1,230 +0,0 @@ --/* -- * Copyright (c) 2004, 2005 Lars Marowsky-Bree -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "../libmultipath/sg_include.h" --#include "libsg.h" --#include "checkers.h" -- --#define INQUIRY_CMD 0x12 --#define INQUIRY_CMDLEN 6 --#define HEAVY_CHECK_COUNT 10 -- --/* -- * Mechanism to track CLARiiON inactive snapshot LUs. -- * This is done so that we can fail passive paths -- * to an inactive snapshot LU even though since a -- * simple read test would return 02/04/03 instead -- * of 05/25/01 sensekey/ASC/ASCQ data. -- */ --#define IS_INACTIVE_SNAP(c) (c->mpcontext ? \ -- ((struct emc_clariion_checker_LU_context *) \ -- (*c->mpcontext))->inactive_snap \ -- : 0) -- --#define SET_INACTIVE_SNAP(c) if (c->mpcontext) \ -- ((struct emc_clariion_checker_LU_context *)\ -- (*c->mpcontext))->inactive_snap = 1 -- --#define CLR_INACTIVE_SNAP(c) if (c->mpcontext) \ -- ((struct emc_clariion_checker_LU_context *)\ -- (*c->mpcontext))->inactive_snap = 0 -- --struct emc_clariion_checker_path_context { -- char wwn[16]; -- unsigned wwn_set; --}; -- --struct emc_clariion_checker_LU_context { -- int inactive_snap; --}; -- --extern void --hexadecimal_to_ascii(char * wwn, char *wwnstr) --{ -- int i,j, nbl; -- -- for (i=0,j=0;i<16;i++) { -- wwnstr[j++] = ((nbl = ((wwn[i]&0xf0) >> 4)) <= 9) ? -- '0' + nbl : 'a' + (nbl - 10); -- wwnstr[j++] = ((nbl = (wwn[i]&0x0f)) <= 9) ? -- '0' + nbl : 'a' + (nbl - 10); -- } -- wwnstr[32]=0; --} -- --int emc_clariion_init (struct checker * c) --{ -- /* -- * Allocate and initialize the path specific context. -- */ -- c->context = malloc(sizeof(struct emc_clariion_checker_path_context)); -- if (!c->context) -- return 1; -- ((struct emc_clariion_checker_path_context *)c->context)->wwn_set = 0; -- -- /* -- * Allocate and initialize the multi-path global context. -- */ -- if (c->mpcontext) { -- void * mpctxt = malloc(sizeof(int)); -- *c->mpcontext = mpctxt; -- CLR_INACTIVE_SNAP(c); -- } -- -- return 0; --} -- --void emc_clariion_free (struct checker * c) --{ -- free(c->context); --} -- --int emc_clariion(struct checker * c) --{ -- unsigned char sense_buffer[128] = { 0, }; -- unsigned char sb[SENSE_BUFF_LEN] = { 0, }, *sbb; -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0, -- sizeof(sense_buffer), 0}; -- struct sg_io_hdr io_hdr; -- struct emc_clariion_checker_path_context * ct = -- (struct emc_clariion_checker_path_context *)c->context; -- char wwnstr[33]; -- int ret; -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = sizeof (sense_buffer); -- io_hdr.dxferp = sense_buffer; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sb; -- 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"); -- return PATH_DOWN; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- MSG(c, "emc_clariion_checker: query command indicates error"); -- return PATH_DOWN; -- } -- if (/* Verify the code page - right page & revision */ -- sense_buffer[1] != 0xc0 || sense_buffer[9] != 0x00) { -- MSG(c, "emc_clariion_checker: Path unit report page in " -- "unknown format"); -- return PATH_DOWN; -- } -- -- if ( /* Effective initiator type */ -- sense_buffer[27] != 0x03 -- /* -- * Failover mode should be set to 1 (PNR failover mode) -- * or 4 (ALUA failover mode). -- */ -- || (((sense_buffer[28] & 0x07) != 0x04) && -- ((sense_buffer[28] & 0x07) != 0x06)) -- /* Arraycommpath should be set to 1 */ -- || (sense_buffer[30] & 0x04) != 0x04) { -- MSG(c, "emc_clariion_checker: Path not correctly configured " -- "for failover"); -- return PATH_DOWN; -- } -- -- if ( /* LUN operations should indicate normal operations */ -- sense_buffer[48] != 0x00) { -- MSG(c, "emc_clariion_checker: Path not available for normal " -- "operations"); -- return PATH_SHAKY; -- } -- -- if ( /* LUN should at least be bound somewhere and not be LUNZ */ -- sense_buffer[4] == 0x00) { -- MSG(c, "emc_clariion_checker: Logical Unit is unbound " -- "or LUNZ"); -- return PATH_DOWN; -- } -- -- /* -- * store the LUN WWN there and compare that it indeed did not -- * change in between, to protect against the path suddenly -- * pointing somewhere else. -- */ -- if (ct->wwn_set) { -- if (memcmp(ct->wwn, &sense_buffer[10], 16) != 0) { -- MSG(c, "emc_clariion_checker: Logical Unit WWN " -- "has changed!"); -- return PATH_DOWN; -- } -- } else { -- memcpy(ct->wwn, &sense_buffer[10], 16); -- ct->wwn_set = 1; -- } -- -- /* -- * Issue read on active path to determine if inactive snapshot. -- */ -- if (sense_buffer[4] == 2) {/* if active path */ -- unsigned char buf[4096]; -- -- ret = sg_read(c->fd, &buf[0], sbb = &sb[0]); -- if (ret == PATH_DOWN) { -- hexadecimal_to_ascii(ct->wwn, wwnstr); -- -- /* -- * Check for inactive snapshot LU this way. Must -- * fail these. -- */ -- if (((sbb[2]&0xf) == 5) && (sbb[12] == 0x25) && -- (sbb[13]==1)) { -- /* -- * Do this so that we can fail even the -- * passive paths which will return -- * 02/04/03 not 05/25/01 on read. -- */ -- SET_INACTIVE_SNAP(c); -- MSG(c, "emc_clariion_checker: Active " -- "path to inactive snapshot WWN %s.", -- wwnstr); -- } else -- MSG(c, "emc_clariion_checker: Read " -- "error for WWN %s. Sense data are " -- "0x%x/0x%x/0x%x.", wwnstr, -- sbb[2]&0xf, sbb[12], sbb[13]); -- } else { -- MSG(c, "emc_clariion_checker: Active path is " -- "healthy."); -- /* -- * Remove the path from the set of paths to inactive -- * snapshot LUs if it was in this list since the -- * snapshot is no longer inactive. -- */ -- CLR_INACTIVE_SNAP(c); -- } -- } else { -- if (IS_INACTIVE_SNAP(c)) { -- hexadecimal_to_ascii(ct->wwn, wwnstr); -- MSG(c, "emc_clariion_checker: Passive " -- "path to inactive snapshot WWN %s.", -- wwnstr); -- ret = PATH_DOWN; -- } else { -- MSG(c, -- "emc_clariion_checker: Passive path is healthy."); -- ret = PATH_UP; /* not ghost */ -- } -- } -- -- return ret; --} -diff --git a/libcheckers/emc_clariion.h b/libcheckers/emc_clariion.h -deleted file mode 100644 -index a1018a6..0000000 ---- a/libcheckers/emc_clariion.h -+++ /dev/null -@@ -1,8 +0,0 @@ --#ifndef _EMC_CLARIION_H --#define _EMC_CLARIION_H -- --int emc_clariion (struct checker *); --int emc_clariion_init (struct checker *); --void emc_clariion_free (struct checker *); -- --#endif /* _EMC_CLARIION_H */ -diff --git a/libcheckers/hp_sw.c b/libcheckers/hp_sw.c -deleted file mode 100644 -index b9731ff..0000000 ---- a/libcheckers/hp_sw.c -+++ /dev/null -@@ -1,141 +0,0 @@ --/* -- * Copyright (c) 2005 Christophe Varoqui -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "checkers.h" -- --#include "../libmultipath/sg_include.h" -- --#define TUR_CMD_LEN 6 --#define INQUIRY_CMDLEN 6 --#define INQUIRY_CMD 0x12 --#define SENSE_BUFF_LEN 32 --#define SCSI_CHECK_CONDITION 0x2 --#define SCSI_COMMAND_TERMINATED 0x22 --#define SG_ERR_DRIVER_SENSE 0x08 --#define RECOVERED_ERROR 0x01 --#define MX_ALLOC_LEN 255 --#define HEAVY_CHECK_COUNT 10 -- --#define MSG_HP_SW_UP "hp_sw checker reports path is up" --#define MSG_HP_SW_DOWN "hp_sw checker reports path is down" --#define MSG_HP_SW_GHOST "hp_sw checker reports path is ghost" -- --struct sw_checker_context { -- void * dummy; --}; -- --int hp_sw_init (struct checker * c) --{ -- return 0; --} -- --void hp_sw_free (struct checker * c) --{ -- return; --} -- --static int --do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, -- void *resp, int mx_resp_len, int noisy) --{ -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = -- { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -- unsigned char sense_b[SENSE_BUFF_LEN]; -- struct sg_io_hdr io_hdr; -- -- if (cmddt) -- inqCmdBlk[1] |= 2; -- if (evpd) -- inqCmdBlk[1] |= 1; -- inqCmdBlk[2] = (unsigned char) pg_op; -- inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); -- inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_b); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = mx_resp_len; -- io_hdr.dxferp = resp; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sense_b; -- io_hdr.timeout = DEF_TIMEOUT; -- -- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -- return 1; -- -- /* treat SG_ERR here to get rid of sg_err.[ch] */ -- io_hdr.status &= 0x7e; -- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -- (0 == io_hdr.driver_status)) -- return 0; -- if ((SCSI_CHECK_CONDITION == io_hdr.status) || -- (SCSI_COMMAND_TERMINATED == io_hdr.status) || -- (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -- if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -- int sense_key; -- unsigned char * sense_buffer = io_hdr.sbp; -- if (sense_buffer[0] & 0x2) -- sense_key = sense_buffer[1] & 0xf; -- else -- sense_key = sense_buffer[2] & 0xf; -- if(RECOVERED_ERROR == sense_key) -- return 0; -- } -- } -- return 1; --} -- --static int --do_tur (int fd) --{ -- unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -- struct sg_io_hdr io_hdr; -- unsigned char sense_buffer[32]; -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (turCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_buffer); -- io_hdr.dxfer_direction = SG_DXFER_NONE; -- io_hdr.cmdp = turCmdBlk; -- io_hdr.sbp = sense_buffer; -- io_hdr.timeout = DEF_TIMEOUT; -- io_hdr.pack_id = 0; -- -- if (ioctl(fd, SG_IO, &io_hdr) < 0) -- return 1; -- -- if (io_hdr.info & SG_INFO_OK_MASK) -- return 1; -- -- return 0; --} -- --extern int --hp_sw (struct checker * c) --{ -- char buff[MX_ALLOC_LEN]; -- -- if (0 != do_inq(c->fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { -- MSG(c, MSG_HP_SW_DOWN); -- return PATH_DOWN; -- } -- -- if (do_tur(c->fd)) { -- MSG(c, MSG_HP_SW_GHOST); -- return PATH_GHOST; -- } -- MSG(c, MSG_HP_SW_UP); -- return PATH_UP; --} -diff --git a/libcheckers/hp_sw.h b/libcheckers/hp_sw.h -deleted file mode 100644 -index 3be0d8e..0000000 ---- a/libcheckers/hp_sw.h -+++ /dev/null -@@ -1,8 +0,0 @@ --#ifndef _HP_SW_H --#define _HP_SW_H -- --int hp_sw (struct checker *); --int hp_sw_init (struct checker *); --void hp_sw_free (struct checker *); -- --#endif /* _HP_SW_H */ -diff --git a/libcheckers/libsg.c b/libcheckers/libsg.c -deleted file mode 100644 -index 9171b10..0000000 ---- a/libcheckers/libsg.c -+++ /dev/null -@@ -1,84 +0,0 @@ --/* -- * Copyright (c) 2004, 2005 Christophe Varoqui -- */ --#include --#include --#include --#include -- --#include "checkers.h" --#include "libsg.h" --#include "../libmultipath/sg_include.h" -- --int --sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff) --{ -- /* defaults */ -- int blocks = 1; -- long long start_block = 0; -- int bs = 512; -- int cdbsz = 10; -- int * diop = NULL; -- -- unsigned char rdCmd[cdbsz]; -- unsigned char *sbb = senseBuff; -- struct sg_io_hdr io_hdr; -- int res; -- int rd_opcode[] = {0x8, 0x28, 0xa8, 0x88}; -- int sz_ind; -- struct stat filestatus; -- int retry_count = 3; -- -- if (fstat(sg_fd, &filestatus) != 0) -- return PATH_DOWN; -- bs = (filestatus.st_blksize > 4096)? 4096: filestatus.st_blksize; -- memset(rdCmd, 0, cdbsz); -- sz_ind = 1; -- rdCmd[0] = rd_opcode[sz_ind]; -- rdCmd[2] = (unsigned char)((start_block >> 24) & 0xff); -- rdCmd[3] = (unsigned char)((start_block >> 16) & 0xff); -- rdCmd[4] = (unsigned char)((start_block >> 8) & 0xff); -- rdCmd[5] = (unsigned char)(start_block & 0xff); -- rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff); -- rdCmd[8] = (unsigned char)(blocks & 0xff); -- -- memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = cdbsz; -- io_hdr.cmdp = rdCmd; -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = bs * blocks; -- io_hdr.dxferp = buff; -- io_hdr.mx_sb_len = SENSE_BUFF_LEN; -- io_hdr.sbp = senseBuff; -- io_hdr.timeout = DEF_TIMEOUT; -- io_hdr.pack_id = (int)start_block; -- if (diop && *diop) -- io_hdr.flags |= SG_FLAG_DIRECT_IO; -- --retry: -- memset(senseBuff, 0, SENSE_BUFF_LEN); -- while (((res = ioctl(sg_fd, SG_IO, &io_hdr)) < 0) && (EINTR == errno)); -- -- if (res < 0) { -- if (ENOMEM == errno) { -- return PATH_UP; -- } -- return PATH_DOWN; -- } -- -- if ((0 == io_hdr.status) && -- (0 == io_hdr.host_status) && -- (0 == io_hdr.driver_status)) { -- return PATH_UP; -- } else { -- /* -- * Retry if UNIT_ATTENTION check condition. -- */ -- if ((sbb[2]&0xf) == 6) { -- if (--retry_count) -- goto retry; -- } -- return PATH_DOWN; -- } --} -diff --git a/libcheckers/libsg.h b/libcheckers/libsg.h -deleted file mode 100644 -index 97c4491..0000000 ---- a/libcheckers/libsg.h -+++ /dev/null -@@ -1,8 +0,0 @@ --#ifndef _LIBSG_H --#define _LIBSG_H -- --#define SENSE_BUFF_LEN 32 -- --int sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff); -- --#endif /* _LIBSG_H */ -diff --git a/libcheckers/rdac.c b/libcheckers/rdac.c -deleted file mode 100644 -index f430488..0000000 ---- a/libcheckers/rdac.c -+++ /dev/null -@@ -1,109 +0,0 @@ --/* -- * Copyright (c) 2005 Christophe Varoqui -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "checkers.h" -- --#include "../libmultipath/sg_include.h" -- --#define INQUIRY_CMDLEN 6 --#define INQUIRY_CMD 0x12 --#define SENSE_BUFF_LEN 32 --#define RDAC_DEF_TIMEOUT 60000 --#define SCSI_CHECK_CONDITION 0x2 --#define SCSI_COMMAND_TERMINATED 0x22 --#define SG_ERR_DRIVER_SENSE 0x08 --#define RECOVERED_ERROR 0x01 -- --#define MSG_RDAC_UP "rdac checker reports path is up" --#define MSG_RDAC_DOWN "rdac checker reports path is down" --#define MSG_RDAC_GHOST "rdac checker reports path is ghost" -- --struct rdac_checker_context { -- void * dummy; --}; -- --int rdac_init (struct checker * c) --{ -- return 0; --} -- --void rdac_free (struct checker * c) --{ -- return; --} -- --static int --do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len) --{ -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = { INQUIRY_CMD, 1, 0, 0, 0, 0 }; -- unsigned char sense_b[SENSE_BUFF_LEN]; -- struct sg_io_hdr io_hdr; -- -- inqCmdBlk[2] = (unsigned char) pg_op; -- inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_b); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = mx_resp_len; -- io_hdr.dxferp = resp; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sense_b; -- io_hdr.timeout = RDAC_DEF_TIMEOUT; -- -- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -- return 1; -- -- /* treat SG_ERR here to get rid of sg_err.[ch] */ -- io_hdr.status &= 0x7e; -- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -- (0 == io_hdr.driver_status)) -- return 0; -- if ((SCSI_CHECK_CONDITION == io_hdr.status) || -- (SCSI_COMMAND_TERMINATED == io_hdr.status) || -- (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -- if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -- int sense_key; -- unsigned char * sense_buffer = io_hdr.sbp; -- if (sense_buffer[0] & 0x2) -- sense_key = sense_buffer[1] & 0xf; -- else -- sense_key = sense_buffer[2] & 0xf; -- if (RECOVERED_ERROR == sense_key) -- return 0; -- } -- } -- return 1; --} -- --struct volume_access_inq --{ -- char dontcare0[8]; -- char avtcvp; -- char dontcare1[39]; --}; -- --extern int --rdac(struct checker * c) --{ -- struct volume_access_inq inq; -- -- if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq))) { -- MSG(c, MSG_RDAC_DOWN); -- return PATH_DOWN; -- } -- -- return ((inq.avtcvp & 0x1) ? PATH_UP : PATH_GHOST); --} -diff --git a/libcheckers/rdac.h b/libcheckers/rdac.h -deleted file mode 100644 -index d7bf812..0000000 ---- a/libcheckers/rdac.h -+++ /dev/null -@@ -1,8 +0,0 @@ --#ifndef _RDAC_H --#define _RDAC_H -- --int rdac(struct checker *); --int rdac_init(struct checker *); --void rdac_free(struct checker *); -- --#endif /* _RDAC_H */ -diff --git a/libcheckers/readsector0.c b/libcheckers/readsector0.c -deleted file mode 100644 -index bef0eb6..0000000 ---- a/libcheckers/readsector0.c -+++ /dev/null -@@ -1,47 +0,0 @@ --/* -- * Copyright (c) 2004, 2005 Christophe Varoqui -- */ --#include -- --#include "checkers.h" --#include "libsg.h" -- --#define MSG_READSECTOR0_UP "readsector0 checker reports path is up" --#define MSG_READSECTOR0_DOWN "readsector0 checker reports path is down" -- --struct readsector0_checker_context { -- void * dummy; --}; -- --int readsector0_init (struct checker * c) --{ -- return 0; --} -- --void readsector0_free (struct checker * c) --{ -- return; --} -- --extern int --readsector0 (struct checker * c) --{ -- unsigned char buf[4096]; -- unsigned char sbuf[SENSE_BUFF_LEN]; -- int ret; -- -- ret = sg_read(c->fd, &buf[0], &sbuf[0]); -- -- switch (ret) -- { -- case PATH_DOWN: -- MSG(c, MSG_READSECTOR0_DOWN); -- break; -- case PATH_UP: -- MSG(c, MSG_READSECTOR0_UP); -- break; -- default: -- break; -- } -- return ret; --} -diff --git a/libcheckers/readsector0.h b/libcheckers/readsector0.h -deleted file mode 100644 -index 0f5d654..0000000 ---- a/libcheckers/readsector0.h -+++ /dev/null -@@ -1,8 +0,0 @@ --#ifndef _READSECTOR0_H --#define _READSECTOR0_H -- --int readsector0 (struct checker *); --int readsector0_init (struct checker *); --void readsector0_free (struct checker *); -- --#endif /* _READSECTOR0_H */ -diff --git a/libcheckers/tur.c b/libcheckers/tur.c -deleted file mode 100644 -index e79bc0a..0000000 ---- a/libcheckers/tur.c -+++ /dev/null -@@ -1,66 +0,0 @@ --/* -- * Some code borrowed from sg-utils. -- * -- * Copyright (c) 2004 Christophe Varoqui -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "checkers.h" -- --#include "../libmultipath/sg_include.h" -- --#define TUR_CMD_LEN 6 --#define HEAVY_CHECK_COUNT 10 -- --#define MSG_TUR_UP "tur checker reports path is up" --#define MSG_TUR_DOWN "tur checker reports path is down" -- --struct tur_checker_context { -- void * dummy; --}; -- --int tur_init (struct checker * c) --{ -- return 0; --} -- --void tur_free (struct checker * c) --{ -- return; --} -- --extern int --tur (struct checker * c) --{ -- struct sg_io_hdr io_hdr; -- unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -- unsigned char sense_buffer[32]; -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (turCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_buffer); -- io_hdr.dxfer_direction = SG_DXFER_NONE; -- io_hdr.cmdp = turCmdBlk; -- io_hdr.sbp = sense_buffer; -- io_hdr.timeout = DEF_TIMEOUT; -- io_hdr.pack_id = 0; -- if (ioctl(c->fd, SG_IO, &io_hdr) < 0) { -- MSG(c, MSG_TUR_DOWN); -- return PATH_DOWN; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- MSG(c, MSG_TUR_DOWN); -- return PATH_DOWN; -- } -- MSG(c, MSG_TUR_UP); -- return PATH_UP; --} -diff --git a/libcheckers/tur.h b/libcheckers/tur.h -deleted file mode 100644 -index a2e8c88..0000000 ---- a/libcheckers/tur.h -+++ /dev/null -@@ -1,8 +0,0 @@ --#ifndef _TUR_H --#define _TUR_H -- --int tur (struct checker *); --int tur_init (struct checker *); --void tur_free (struct checker *); -- --#endif /* _TUR_H */ -diff --git a/libmultipath/Makefile b/libmultipath/Makefile -index 511f5ad..21fcd74 100644 ---- a/libmultipath/Makefile -+++ b/libmultipath/Makefile -@@ -2,50 +2,35 @@ - # - # Copyright (C) 2003 Christophe Varoqui, - # --BUILD = glibc -- - include ../Makefile.inc - --CFLAGS += -I$(checkersdir) -+LIBS = libmultipath.so - - OBJS = memory.o parser.o vector.o devmapper.o callout.o \ - hwtable.o blacklist.o util.o dmparser.o config.o \ - structs.o discovery.o propsel.o dict.o \ - pgpolicies.o debug.o regex.o defaults.o uevent.o \ - switchgroup.o uxsock.o print.o alias.o log_pthread.o \ -- log.o configure.o structs_vec.o sysfs.o -- --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 -- CLEAN = $(shell if [ ! "x$(PREVBUILD)" = "x" ]; then echo clean; fi) --endif -+ log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \ -+ lock.o waiter.o - --LIBDM_API_FLUSH = $(shell objdump -T /lib/libdevmapper.so.* | grep -c dm_task_no_flush) -+LIBDM_API_FLUSH = $(shell if test -d /lib64 ; then objdump -T /lib64/libdevmapper.so* ; else objdump -T /lib/libdevmapper.so.* ; fi | grep -c dm_task_no_flush) - - ifeq ($(strip $(LIBDM_API_FLUSH)),1) - CFLAGS += -DLIBDM_API_FLUSH - endif - --all: $(BUILD) -- --prepare: $(CLEAN) -- @file *-$(BUILD).a >/dev/null 2>&1 || rm -f core *.o *.gz -- @rm -f *-$(BUILD).a -- --klibc: $(OBJS) -- ar rs libmultipath-klibc.a *.o -+all: $(LIBS) - --glibc: $(OBJS) -- ar rs libmultipath-glibc.a *.o -+$(LIBS): $(OBJS) -+ $(CC) $(SHARED_FLAGS) $(CFLAGS) -o $@ $(OBJS) - - install: -+ $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(libdir) -+ $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir)/$(LIBS) - - uninstall: -+ rm -f $(DESTDIR)$(libdir)/$(LIBS) - - clean: -- rm -f core *.a *.o *.gz -+ rm -f core *.a *.o *.gz *.so -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index ca434fe..517b055 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -179,6 +179,46 @@ fail: - return -1; - } - -+static int -+format_devname(char *name, int id, int len) -+{ -+ int pos; -+ -+ memset(name,0, len); -+ strcpy(name,"mpath"); -+ for (pos = len - 1; pos >= 5; pos--) { -+ name[pos] = 'a' + id % 26; -+ if (id < 26) -+ break; -+ id /= 26; -+ id--; -+ } -+ memmove(name + 5, name + pos, len - pos); -+ name[5 + len - pos] = '\0'; -+ return (5 + len - pos); -+} -+ -+static int -+scan_devname(char *alias) -+{ -+ char *c; -+ int i, n = 0; -+ -+ if (strncmp(alias, "mpath", 5)) -+ return -1; -+ -+ c = alias + 5; -+ while (*c != '\0' && *c != ' ' && *c != '\t') { -+ i = *c - 'a'; -+ n = ( n * 26 ) + i; -+ c++; -+ if (*c < 'a' || *c > 'z') -+ break; -+ n++; -+ } -+ -+ return n; -+} - - static int - lookup_binding(FILE *f, char *map_wwid, char **map_alias) -@@ -200,7 +240,8 @@ lookup_binding(FILE *f, char *map_wwid, char **map_alias) - alias = strtok(buf, " \t"); - if (!alias) /* blank line */ - continue; -- if (sscanf(alias, "mpath%d", &curr_id) == 1 && curr_id >= id) -+ curr_id = scan_devname(alias); -+ if (curr_id >= id) - id = curr_id + 1; - wwid = strtok(NULL, " \t"); - if (!wwid){ -@@ -221,7 +262,7 @@ lookup_binding(FILE *f, char *map_wwid, char **map_alias) - } - condlog(3, "No matching wwid [%s] in bindings file.", map_wwid); - return id; --} -+} - - static int - rlookup_binding(FILE *f, char **map_wwid, char *map_alias) -@@ -243,7 +284,8 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias) - alias = strtok(buf, " \t"); - if (!alias) /* blank line */ - continue; -- if (sscanf(alias, "mpath%d", &curr_id) == 1 && curr_id >= id) -+ curr_id = scan_devname(alias); -+ if (curr_id >= id) - id = curr_id + 1; - wwid = strtok(NULL, " \t"); - if (!wwid){ -@@ -264,7 +306,7 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias) - } - condlog(3, "No matching alias [%s] in bindings file.", map_alias); - return id; --} -+} - - static char * - allocate_binding(int fd, char *wwid, int id) -@@ -272,13 +314,16 @@ allocate_binding(int fd, char *wwid, int id) - char buf[LINE_MAX]; - off_t offset; - char *alias, *c; -- -+ int i; -+ - if (id < 0) { - condlog(0, "Bindings file full. Cannot allocate new binding"); - return NULL; - } -- -- snprintf(buf, LINE_MAX, "mpath%d %s\n", id, wwid); -+ -+ i = format_devname(buf, id, LINE_MAX); -+ c = buf + i; -+ snprintf(c,LINE_MAX - i, " %s\n", wwid); - buf[LINE_MAX - 1] = '\0'; - - offset = lseek(fd, 0, SEEK_END); -@@ -304,7 +349,7 @@ allocate_binding(int fd, char *wwid, int id) - condlog(3, "Created new binding [%s] for WWID [%s]", alias, - wwid); - return alias; --} -+} - - char * - get_user_friendly_alias(char *wwid, char *file) -diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c -index 0c277cb..d85b385 100644 ---- a/libmultipath/blacklist.c -+++ b/libmultipath/blacklist.c -@@ -2,8 +2,8 @@ - * Copyright (c) 2004, 2005 Christophe Varoqui - */ - #include --#include - -+#include "checkers.h" - #include "memory.h" - #include "vector.h" - #include "util.h" -@@ -297,16 +297,14 @@ _filter_path (struct config * conf, struct path * pp) - int r; - - r = _filter_devnode(conf->blist_devnode, conf->elist_devnode,pp->dev); -- if (r) -- return r; -- r = _filter_wwid(conf->blist_wwid, conf->elist_devnode, pp->wwid); -- if (r) -+ if (r > 0) - return r; - r = _filter_device(conf->blist_device, conf->elist_device, - pp->vendor_id, pp->product_id); -- if (r) -+ if (r > 0) - return r; -- return 0; -+ r = _filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid); -+ return r; - } - - int -diff --git a/libmultipath/callout.c b/libmultipath/callout.c -index 46b89e6..4dd33c5 100644 ---- a/libmultipath/callout.c -+++ b/libmultipath/callout.c -@@ -10,11 +10,11 @@ - #include - #include - #include -+#include - #include - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "structs.h" - #include "debug.h" -@@ -33,7 +33,7 @@ int execute_program(char *path, char *value, int len) - int retval; - int count; - int status; -- int fds[2]; -+ int fds[2], null_fd; - pid_t pid; - char *pos; - char arg[PROGRAM_SIZE]; -@@ -76,7 +76,16 @@ int execute_program(char *path, char *value, int len) - close(STDOUT_FILENO); - - /* dup write side of pipe to STDOUT */ -- dup(fds[1]); -+ if (dup(fds[1]) < 0) -+ return -1; -+ -+ /* Ignore writes to stderr */ -+ null_fd = open("/dev/null", O_WRONLY); -+ if (null_fd > 0) { -+ close(STDERR_FILENO); -+ dup(null_fd); -+ close(null_fd); -+ } - - retval = execv(argv[0], argv); - -diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c -new file mode 100644 -index 0000000..5889ad7 ---- /dev/null -+++ b/libmultipath/checkers.c -@@ -0,0 +1,187 @@ -+#include -+#include -+#include -+#include -+ -+#include "debug.h" -+#include "checkers.h" -+#include "vector.h" -+#include "config.h" -+ -+static LIST_HEAD(checkers); -+ -+int init_checkers (void) -+{ -+ INIT_LIST_HEAD(&checkers); -+ if (!add_checker(DEFAULT_CHECKER)) -+ return 1; -+ return 0; -+} -+ -+struct checker * alloc_checker (void) -+{ -+ return zalloc(sizeof(struct checker)); -+} -+ -+void free_checker (struct checker * c) -+{ -+ free(c); -+} -+ -+void cleanup_checkers (void) -+{ -+ struct checker * checker_loop; -+ struct checker * checker_temp; -+ -+ list_for_each_entry_safe(checker_loop, checker_temp, &checkers, node) { -+ list_del(&checker_loop->node); -+ free(checker_loop); -+ } -+} -+ -+struct checker * checker_lookup (char * name) -+{ -+ struct checker * c; -+ -+ list_for_each_entry(c, &checkers, node) { -+ if (!strncmp(name, c->name, CHECKER_NAME_LEN)) -+ return c; -+ } -+ return add_checker(name); -+} -+ -+struct checker * add_checker (char * name) -+{ -+ char libname[LIB_CHECKER_NAMELEN]; -+ void * handle; -+ struct checker * c; -+ char *errstr; -+ -+ c = alloc_checker(); -+ if (!c) -+ return NULL; -+ snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so", -+ conf->multipath_dir, name); -+ condlog(3, "loading %s checker", libname); -+ handle = dlopen(libname, RTLD_NOW); -+ errstr = dlerror(); -+ if (errstr != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!handle) -+ goto out; -+ -+ c->check = (int (*)(struct checker *)) dlsym(handle, "libcheck_check"); -+ errstr = dlerror(); -+ if (errstr != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!c->check) -+ goto out; -+ -+ c->init = (int (*)(struct checker *)) dlsym(handle, "libcheck_init"); -+ errstr = dlerror(); -+ if (errstr != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!c->init) -+ goto out; -+ -+ c->free = (void (*)(struct checker *)) dlsym(handle, "libcheck_free"); -+ errstr = dlerror(); -+ if (errstr != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!c->free) -+ goto out; -+ -+ snprintf(c->name, CHECKER_NAME_LEN, "%s", name); -+ c->fd = 0; -+ c->sync = 1; -+ list_add(&c->node, &checkers); -+ return c; -+out: -+ free_checker(c); -+ return NULL; -+} -+ -+void checker_set_fd (struct checker * c, int fd) -+{ -+ c->fd = fd; -+} -+ -+void checker_set_sync (struct checker * c) -+{ -+ c->sync = 1; -+} -+ -+void checker_set_async (struct checker * c) -+{ -+ c->sync = 0; -+} -+ -+void checker_enable (struct checker * c) -+{ -+ c->disable = 0; -+} -+ -+void checker_disable (struct checker * c) -+{ -+ c->disable = 1; -+} -+ -+int checker_init (struct checker * c, void ** mpctxt_addr) -+{ -+ c->mpcontext = mpctxt_addr; -+ return c->init(c); -+} -+ -+void checker_put (struct checker * c) -+{ -+ if (c->free) -+ c->free(c); -+ memset(c, 0x0, sizeof(struct checker)); -+} -+ -+int checker_check (struct checker * c) -+{ -+ int r; -+ -+ if (c->disable) -+ return PATH_UNCHECKED; -+ if (c->fd <= 0) { -+ MSG(c, "no usable fd"); -+ return PATH_WILD; -+ } -+ r = c->check(c); -+ -+ return r; -+} -+ -+int checker_selected (struct checker * c) -+{ -+ return (c->check) ? 1 : 0; -+} -+ -+char * checker_name (struct checker * c) -+{ -+ return c->name; -+} -+ -+char * checker_message (struct checker * c) -+{ -+ return c->message; -+} -+ -+void checker_get (struct checker * dst, char * name) -+{ -+ struct checker * src = checker_lookup(name); -+ -+ if (!src) { -+ dst->check = NULL; -+ return; -+ } -+ dst->fd = src->fd; -+ dst->sync = src->sync; -+ strncpy(dst->name, src->name, CHECKER_NAME_LEN); -+ strncpy(dst->message, src->message, CHECKER_MSG_LEN); -+ dst->check = src->check; -+ dst->init = src->init; -+ dst->free = src->free; -+} -diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h -new file mode 100644 -index 0000000..a65aaf9 ---- /dev/null -+++ b/libmultipath/checkers.h -@@ -0,0 +1,126 @@ -+#ifndef _CHECKERS_H -+#define _CHECKERS_H -+ -+#include "list.h" -+#include "memory.h" -+ -+/* -+ * -+ * Userspace (multipath/multipathd) path states -+ * -+ * PATH_WILD: -+ * - Use: None of the checkers (returned if we don't have an fd) -+ * - Description: Corner case where "fd <= 0" for path fd (see checker_check()) -+ * -+ * PATH_UNCHECKED: -+ * - Use: Only in directio checker -+ * - Description: set when fcntl(F_GETFL) fails to return flags or O_DIRECT -+ * not include in flags, or O_DIRECT read fails -+ * - Notes: -+ * - multipathd: uses it to skip over paths in sync_map_state() -+ * - multipath: used in update_paths(); if state==PATH_UNCHECKED, call -+ * pathinfo() -+ * -+ * PATH_DOWN: -+ * - Use: All checkers (directio, emc_clariion, hp_sw, readsector0, tur) -+ * - Description: Either a) SG_IO ioctl failed, or b) check condition on some -+ * SG_IO ioctls that succeed (tur, readsector0 checkers); path is down and -+ * you shouldn't try to send commands to it -+ * -+ * PATH_UP: -+ * - Use: All checkers (directio, emc_clariion, hp_sw, readsector0, tur) -+ * - Description: Path is up and I/O can be sent to it -+ * -+ * PATH_SHAKY: -+ * - Use: Only emc_clariion -+ * - Description: Indicates path not available for "normal" operations -+ * -+ * PATH_GHOST: -+ * - Use: Only hp_sw -+ * - Description: Indicates a "passive/standby" path on active/passive HP -+ * arrays. These paths will return valid answers to certain SCSI commands -+ * (tur, read_capacity, inquiry, start_stop), but will fail I/O commands. -+ * The path needs an initialization command to be sent to it in order for -+ * I/Os to succeed. -+ * -+ * PATH_PENDING: -+ * - Use: All async checkers -+ * - Description: Indicates a check IO is in flight. -+ */ -+#define PATH_WILD -1 -+#define PATH_UNCHECKED 0 -+#define PATH_DOWN 1 -+#define PATH_UP 2 -+#define PATH_SHAKY 3 -+#define PATH_GHOST 4 -+#define PATH_PENDING 5 -+ -+#define DIRECTIO "directio" -+#define TUR "tur" -+#define HP_SW "hp_sw" -+#define RDAC "rdac" -+#define EMC_CLARIION "emc_clariion" -+#define READSECTOR0 "readsector0" -+#define CCISS_TUR "cciss_tur" -+ -+#define DEFAULT_CHECKER DIRECTIO -+ -+/* -+ * 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 -+#define ASYNC_TIMEOUT_SEC 30 -+ -+/* -+ * strings lengths -+ */ -+#define CHECKER_NAME_LEN 16 -+#define CHECKER_MSG_LEN 256 -+#define CHECKER_DEV_LEN 256 -+#define LIB_CHECKER_NAMELEN 256 -+ -+struct checker { -+ struct list_head node; -+ int fd; -+ int sync; -+ int disable; -+ char name[CHECKER_NAME_LEN]; -+ char message[CHECKER_MSG_LEN]; /* comm with callers */ -+ void * context; /* store for persistent data */ -+ void ** mpcontext; /* store for persistent data -+ shared multipath-wide */ -+ int (*check)(struct checker *); -+ int (*init)(struct checker *); /* to allocate the context */ -+ void (*free)(struct checker *); /* to free the context */ -+}; -+ -+#define MSG(c, fmt, args...) snprintf((c)->message, CHECKER_MSG_LEN, fmt, ##args); -+ -+int init_checkers (void); -+struct checker * add_checker (char *); -+struct checker * checker_lookup (char *); -+int checker_init (struct checker *, void **); -+void checker_put (struct checker *); -+void checker_reset (struct checker *); -+void checker_set_sync (struct checker *); -+void checker_set_async (struct checker *); -+void checker_set_fd (struct checker *, int); -+void checker_enable (struct checker *); -+void checker_disable (struct checker *); -+int checker_check (struct checker *); -+int checker_selected (struct checker *); -+char * checker_name (struct checker *); -+char * checker_message (struct checker *); -+void checker_get (struct checker *, char *); -+ -+#endif /* _CHECKERS_H */ -diff --git a/libmultipath/checkers/Makefile b/libmultipath/checkers/Makefile -new file mode 100644 -index 0000000..a20dfac ---- /dev/null -+++ b/libmultipath/checkers/Makefile -@@ -0,0 +1,30 @@ -+# Makefile -+# -+# Copyright (C) 2003 Christophe Varoqui, -+# -+include ../../Makefile.inc -+ -+LIBS= \ -+ libcheckcciss_tur.so \ -+ libcheckreadsector0.so \ -+ libchecktur.so \ -+ libcheckdirectio.so \ -+ libcheckemc_clariion.so \ -+ libcheckhp_sw.so \ -+ libcheckrdac.so -+ -+CFLAGS += -I.. -+ -+all: $(LIBS) -+ -+libcheck%.so: libsg.o %.o -+ $(CC) $(SHARED_FLAGS) -o $@ $^ -+ -+install: -+ $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir) -+ -+uninstall: -+ rm -f $(DESTDIR)$(libdir)/$(LIBS) -+ -+clean: -+ rm -f core *.a *.o *.gz *.so -diff --git a/libmultipath/checkers/cciss.h b/libmultipath/checkers/cciss.h -new file mode 100644 -index 0000000..ebdff06 ---- /dev/null -+++ b/libmultipath/checkers/cciss.h -@@ -0,0 +1,142 @@ -+#ifndef CCISS_H -+#define CCISS_H -+ -+#include -+#include -+ -+#define CCISS_IOC_MAGIC 'B' -+ -+/* -+ * transfer direction -+ */ -+#define XFER_NONE 0x00 -+#define XFER_WRITE 0x01 -+#define XFER_READ 0x02 -+#define XFER_RSVD 0x03 -+ -+/* -+ * task attribute -+ */ -+#define ATTR_UNTAGGED 0x00 -+#define ATTR_SIMPLE 0x04 -+#define ATTR_HEADOFQUEUE 0x05 -+#define ATTR_ORDERED 0x06 -+#define ATTR_ACA 0x07 -+ -+/* -+ * cdb type -+ */ -+#define TYPE_CMD 0x00 -+#define TYPE_MSG 0x01 -+ -+#define SENSEINFOBYTES 32 -+ -+/* -+ * Type defs used in the following structs -+ */ -+#define BYTE __u8 -+#define WORD __u16 -+#define HWORD __u16 -+#define DWORD __u32 -+ -+#pragma pack(1) -+ -+//Command List Structure -+typedef union _SCSI3Addr_struct { -+ struct { -+ BYTE Dev; -+ BYTE Bus:6; -+ BYTE Mode:2; // b00 -+ } PeripDev; -+ struct { -+ BYTE DevLSB; -+ BYTE DevMSB:6; -+ BYTE Mode:2; // b01 -+ } LogDev; -+ struct { -+ BYTE Dev:5; -+ BYTE Bus:3; -+ BYTE Targ:6; -+ BYTE Mode:2; // b10 -+ } LogUnit; -+} SCSI3Addr_struct; -+ -+typedef struct _PhysDevAddr_struct { -+ DWORD TargetId:24; -+ DWORD Bus:6; -+ DWORD Mode:2; -+ SCSI3Addr_struct Target[2]; //2 level target device addr -+} PhysDevAddr_struct; -+ -+typedef struct _LogDevAddr_struct { -+ DWORD VolId:30; -+ DWORD Mode:2; -+ BYTE reserved[4]; -+} LogDevAddr_struct; -+ -+typedef union _LUNAddr_struct { -+ BYTE LunAddrBytes[8]; -+ SCSI3Addr_struct SCSI3Lun[4]; -+ PhysDevAddr_struct PhysDev; -+ LogDevAddr_struct LogDev; -+} LUNAddr_struct; -+ -+typedef struct _RequestBlock_struct { -+ BYTE CDBLen; -+ struct { -+ BYTE Type:3; -+ BYTE Attribute:3; -+ BYTE Direction:2; -+ } Type; -+ HWORD Timeout; -+ BYTE CDB[16]; -+} RequestBlock_struct; -+ -+typedef union _MoreErrInfo_struct{ -+ struct { -+ BYTE Reserved[3]; -+ BYTE Type; -+ DWORD ErrorInfo; -+ }Common_Info; -+ struct{ -+ BYTE Reserved[2]; -+ BYTE offense_size;//size of offending entry -+ BYTE offense_num; //byte # of offense 0-base -+ DWORD offense_value; -+ }Invalid_Cmd; -+}MoreErrInfo_struct; -+ -+typedef struct _ErrorInfo_struct { -+ BYTE ScsiStatus; -+ BYTE SenseLen; -+ HWORD CommandStatus; -+ DWORD ResidualCnt; -+ MoreErrInfo_struct MoreErrInfo; -+ BYTE SenseInfo[SENSEINFOBYTES]; -+} ErrorInfo_struct; -+ -+#pragma pack() -+ -+typedef struct _IOCTL_Command_struct { -+ LUNAddr_struct LUN_info; -+ RequestBlock_struct Request; -+ ErrorInfo_struct error_info; -+ WORD buf_size; /* size in bytes of the buf */ -+ BYTE *buf; -+} IOCTL_Command_struct; -+ -+typedef struct _LogvolInfo_struct{ -+ __u32 LunID; -+ int num_opens; /* number of opens on the logical volume */ -+ int num_parts; /* number of partitions configured on logvol */ -+} LogvolInfo_struct; -+ -+#define CCISS_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 11, IOCTL_Command_struct) -+#define CCISS_GETLUNINFO _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_struct) -+ -+int cciss_init( struct checker *); -+void cciss_free (struct checker * c); -+int cciss_tur( struct checker *); -+ -+#endif -+ -diff --git a/libmultipath/checkers/cciss_tur.c b/libmultipath/checkers/cciss_tur.c -new file mode 100644 -index 0000000..4c26901 ---- /dev/null -+++ b/libmultipath/checkers/cciss_tur.c -@@ -0,0 +1,137 @@ -+/* -+ ***************************************************************************** -+ * * -+ * (C) Copyright 2007 Hewlett-Packard Development Company, L.P * -+ * * -+ * 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. * -+ * * -+ * 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. * -+ * * -+ * You should have received a copy of the GNU General Public License along * -+ * with this program; if not, write to the Free Software Foundation, Inc., * -+ * 675 Mass Ave, Cambridge, MA 02139, USA. * -+ * * -+ * The copy of the GNU General Public License is available at * -+ * /opt/hp/HPDMmultipath-tool directoy * -+ * * -+ ***************************************************************************** -+*/ -+ -+/* -+ * This program originally derived from and inspired by -+ * Christophe Varoqui's tur.c, part of libchecker. -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "checkers.h" -+ -+#include "cciss.h" -+ -+#define TUR_CMD_LEN 6 -+#define HEAVY_CHECK_COUNT 10 -+ -+#define MSG_CCISS_TUR_UP "cciss_tur checker reports path is up" -+#define MSG_CCISS_TUR_DOWN "cciss_tur checker reports path is down" -+ -+struct cciss_tur_checker_context { -+ void * dummy; -+}; -+ -+int libcheck_init (struct checker * c) -+{ -+ return 0; -+} -+ -+void libcheck_free (struct checker * c) -+{ -+ return; -+} -+ -+extern int -+libcheck_check (struct checker * c) -+{ -+ int rc; -+ int ret; -+ unsigned int lun = 0; -+ struct cciss_tur_checker_context * ctxt = NULL; -+ LogvolInfo_struct lvi; // logical "volume" info -+ IOCTL_Command_struct cic; // cciss ioctl command -+ -+ if ((c->fd) <= 0) { -+ MSG(c,"no usable fd"); -+ ret = -1; -+ goto out; -+ } -+ -+ rc = ioctl(c->fd, CCISS_GETLUNINFO, &lvi); -+ if ( rc != 0) { -+ perror("Error: "); -+ fprintf(stderr, "cciss TUR failed in CCISS_GETLUNINFO: %s\n", -+ strerror(errno)); -+ MSG(c,MSG_CCISS_TUR_DOWN); -+ ret = PATH_DOWN; -+ goto out; -+ } else { -+ lun = lvi.LunID; -+ } -+ -+ memset(&cic, 0, sizeof(cic)); -+ cic.LUN_info.LogDev.VolId = lun & 0x3FFFFFFF; -+ cic.LUN_info.LogDev.Mode = 0x01; /* logical volume addressing */ -+ cic.Request.CDBLen = 6; /* need to try just 2 bytes here */ -+ cic.Request.Type.Type = TYPE_CMD; // It is a command. -+ cic.Request.Type.Attribute = ATTR_SIMPLE; -+ cic.Request.Type.Direction = XFER_NONE; -+ cic.Request.Timeout = 0; -+ -+ cic.Request.CDB[0] = 0; -+ cic.Request.CDB[1] = 0; -+ cic.Request.CDB[2] = 0; -+ cic.Request.CDB[3] = 0; -+ cic.Request.CDB[4] = 0; -+ cic.Request.CDB[5] = 0; -+ -+ rc = ioctl(c->fd, CCISS_PASSTHRU, &cic); -+ if (rc < 0) { -+ fprintf(stderr, "cciss TUR failed: %s\n", -+ strerror(errno)); -+ MSG(c,MSG_CCISS_TUR_DOWN); -+ ret = PATH_DOWN; -+ goto out; -+ } -+ -+ if ((cic.error_info.CommandStatus | cic.error_info.ScsiStatus )) { -+ MSG(c,MSG_CCISS_TUR_DOWN); -+ ret = PATH_DOWN; -+ goto out; -+ } -+ -+ MSG(c,MSG_CCISS_TUR_UP); -+ -+ ret = PATH_UP; -+out: -+ /* -+ * caller told us he doesn't want to keep the context : -+ * free it -+ */ -+ if (!c->context) -+ free(ctxt); -+ -+ return(ret); -+} -diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c -new file mode 100644 -index 0000000..5c92dac ---- /dev/null -+++ b/libmultipath/checkers/directio.c -@@ -0,0 +1,197 @@ -+/* -+ * Copyright (c) 2005 Hannes Reinecke, Suse -+ */ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "checkers.h" -+#include "../libmultipath/debug.h" -+ -+#define MSG_DIRECTIO_UNKNOWN "directio checker is not available" -+#define MSG_DIRECTIO_UP "directio checker reports path is up" -+#define MSG_DIRECTIO_DOWN "directio checker reports path is down" -+#define MSG_DIRECTIO_PENDING "directio checker is waiting on aio" -+ -+#define LOG(prio, fmt, args...) condlog(prio, "directio: " fmt, ##args) -+ -+struct directio_context { -+ int running; -+ int reset_flags; -+ int blksize; -+ unsigned char * buf; -+ unsigned char * ptr; -+ io_context_t ioctx; -+ struct iocb io; -+}; -+ -+ -+int libcheck_init (struct checker * c) -+{ -+ unsigned long pgsize = getpagesize(); -+ struct directio_context * ct; -+ long flags; -+ -+ ct = malloc(sizeof(struct directio_context)); -+ if (!ct) -+ return 1; -+ memset(ct, 0, sizeof(struct directio_context)); -+ -+ if (io_setup(1, &ct->ioctx) != 0) { -+ condlog(1, "io_setup failed"); -+ free(ct); -+ return 1; -+ } -+ -+ if (ioctl(c->fd, BLKBSZGET, &ct->blksize) < 0) { -+ MSG(c, "cannot get blocksize, set default"); -+ ct->blksize = 512; -+ } -+ if (ct->blksize > 4096) { -+ /* -+ * Sanity check for DASD; BSZGET is broken -+ */ -+ ct->blksize = 4096; -+ } -+ if (!ct->blksize) -+ goto out; -+ ct->buf = (unsigned char *)malloc(ct->blksize + pgsize); -+ if (!ct->buf) -+ goto out; -+ -+ flags = fcntl(c->fd, F_GETFL); -+ if (flags < 0) -+ goto out; -+ if (!(flags & O_DIRECT)) { -+ flags |= O_DIRECT; -+ if (fcntl(c->fd, F_SETFL, flags) < 0) -+ goto out; -+ ct->reset_flags = 1; -+ } -+ -+ ct->ptr = (unsigned char *) (((unsigned long)ct->buf + pgsize - 1) & -+ (~(pgsize - 1))); -+ -+ /* Sucessfully initialized, return the context. */ -+ c->context = (void *) ct; -+ return 0; -+ -+out: -+ if (ct->buf) -+ free(ct->buf); -+ io_destroy(ct->ioctx); -+ free(ct); -+ return 1; -+} -+ -+void libcheck_free (struct checker * c) -+{ -+ struct directio_context * ct = (struct directio_context *)c->context; -+ long flags; -+ -+ if (!ct) -+ return; -+ -+ if (ct->reset_flags) { -+ if ((flags = fcntl(c->fd, F_GETFL)) >= 0) { -+ flags &= ~O_DIRECT; -+ /* No point in checking for errors */ -+ fcntl(c->fd, F_SETFL, flags); -+ } -+ } -+ -+ if (ct->buf) -+ free(ct->buf); -+ io_destroy(ct->ioctx); -+ free(ct); -+} -+ -+static int -+check_state(int fd, struct directio_context *ct, int sync) -+{ -+ struct timespec timeout = { .tv_nsec = 5 }; -+ struct io_event event; -+ struct stat sb; -+ int rc = PATH_UNCHECKED; -+ long r; -+ -+ if (fstat(fd, &sb) == 0) { -+ LOG(4, "called for %x", (unsigned) sb.st_rdev); -+ } -+ if (sync) { -+ LOG(4, "called in synchronous mode"); -+ timeout.tv_sec = ASYNC_TIMEOUT_SEC; -+ timeout.tv_nsec = 0; -+ } -+ -+ if (!ct->running) { -+ struct iocb *ios[1] = { &ct->io }; -+ -+ LOG(3, "starting new request"); -+ memset(&ct->io, 0, sizeof(struct iocb)); -+ io_prep_pread(&ct->io, fd, ct->ptr, ct->blksize, 0); -+ if (io_submit(ct->ioctx, 1, ios) != 1) { -+ LOG(3, "io_submit error %i", errno); -+ return PATH_UNCHECKED; -+ } -+ } -+ ct->running++; -+ -+ r = io_getevents(ct->ioctx, 1L, 1L, &event, &timeout); -+ LOG(3, "async io getevents returns %li (errno=%s)", r, strerror(errno)); -+ -+ if (r < 1L) { -+ if (ct->running > ASYNC_TIMEOUT_SEC || sync) { -+ LOG(3, "abort check on timeout"); -+ rc = PATH_DOWN; -+ } else -+ rc = PATH_PENDING; -+ } else { -+ LOG(3, "io finished %lu/%lu", event.res, event.res2); -+ ct->running = 0; -+ rc = (event.res == ct->blksize) ? PATH_UP : PATH_DOWN; -+ } -+ -+ return rc; -+} -+ -+int libcheck_check (struct checker * c) -+{ -+ int ret; -+ struct directio_context * ct = (struct directio_context *)c->context; -+ -+ if (!ct) -+ return PATH_UNCHECKED; -+ -+ ret = check_state(c->fd, ct, c->sync); -+ -+ switch (ret) -+ { -+ case PATH_UNCHECKED: -+ MSG(c, MSG_DIRECTIO_UNKNOWN); -+ break; -+ case PATH_DOWN: -+ MSG(c, MSG_DIRECTIO_DOWN); -+ break; -+ case PATH_UP: -+ MSG(c, MSG_DIRECTIO_UP); -+ break; -+ case PATH_PENDING: -+ MSG(c, MSG_DIRECTIO_PENDING); -+ break; -+ default: -+ break; -+ } -+ return ret; -+} -diff --git a/libmultipath/checkers/directio.h b/libmultipath/checkers/directio.h -new file mode 100644 -index 0000000..1865b1f ---- /dev/null -+++ b/libmultipath/checkers/directio.h -@@ -0,0 +1,8 @@ -+#ifndef _DIRECTIO_H -+#define _DIRECTIO_H -+ -+int directio (struct checker *); -+int directio_init (struct checker *); -+void directio_free (struct checker *); -+ -+#endif /* _DIRECTIO_H */ -diff --git a/libmultipath/checkers/emc_clariion.c b/libmultipath/checkers/emc_clariion.c -new file mode 100644 -index 0000000..9eac31d ---- /dev/null -+++ b/libmultipath/checkers/emc_clariion.c -@@ -0,0 +1,230 @@ -+/* -+ * Copyright (c) 2004, 2005 Lars Marowsky-Bree -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../libmultipath/sg_include.h" -+#include "libsg.h" -+#include "checkers.h" -+ -+#define INQUIRY_CMD 0x12 -+#define INQUIRY_CMDLEN 6 -+#define HEAVY_CHECK_COUNT 10 -+ -+/* -+ * Mechanism to track CLARiiON inactive snapshot LUs. -+ * This is done so that we can fail passive paths -+ * to an inactive snapshot LU even though since a -+ * simple read test would return 02/04/03 instead -+ * of 05/25/01 sensekey/ASC/ASCQ data. -+ */ -+#define IS_INACTIVE_SNAP(c) (c->mpcontext ? \ -+ ((struct emc_clariion_checker_LU_context *) \ -+ (*c->mpcontext))->inactive_snap \ -+ : 0) -+ -+#define SET_INACTIVE_SNAP(c) if (c->mpcontext) \ -+ ((struct emc_clariion_checker_LU_context *)\ -+ (*c->mpcontext))->inactive_snap = 1 -+ -+#define CLR_INACTIVE_SNAP(c) if (c->mpcontext) \ -+ ((struct emc_clariion_checker_LU_context *)\ -+ (*c->mpcontext))->inactive_snap = 0 -+ -+struct emc_clariion_checker_path_context { -+ char wwn[16]; -+ unsigned wwn_set; -+}; -+ -+struct emc_clariion_checker_LU_context { -+ int inactive_snap; -+}; -+ -+extern void -+hexadecimal_to_ascii(char * wwn, char *wwnstr) -+{ -+ int i,j, nbl; -+ -+ for (i=0,j=0;i<16;i++) { -+ wwnstr[j++] = ((nbl = ((wwn[i]&0xf0) >> 4)) <= 9) ? -+ '0' + nbl : 'a' + (nbl - 10); -+ wwnstr[j++] = ((nbl = (wwn[i]&0x0f)) <= 9) ? -+ '0' + nbl : 'a' + (nbl - 10); -+ } -+ wwnstr[32]=0; -+} -+ -+int libcheck_init (struct checker * c) -+{ -+ /* -+ * Allocate and initialize the path specific context. -+ */ -+ c->context = malloc(sizeof(struct emc_clariion_checker_path_context)); -+ if (!c->context) -+ return 1; -+ ((struct emc_clariion_checker_path_context *)c->context)->wwn_set = 0; -+ -+ /* -+ * Allocate and initialize the multi-path global context. -+ */ -+ if (c->mpcontext) { -+ void * mpctxt = malloc(sizeof(int)); -+ *c->mpcontext = mpctxt; -+ CLR_INACTIVE_SNAP(c); -+ } -+ -+ return 0; -+} -+ -+void libcheck_free (struct checker * c) -+{ -+ free(c->context); -+} -+ -+int libcheck_check (struct checker * c) -+{ -+ unsigned char sense_buffer[128] = { 0, }; -+ unsigned char sb[SENSE_BUFF_LEN] = { 0, }, *sbb; -+ unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0, -+ sizeof(sense_buffer), 0}; -+ struct sg_io_hdr io_hdr; -+ struct emc_clariion_checker_path_context * ct = -+ (struct emc_clariion_checker_path_context *)c->context; -+ char wwnstr[33]; -+ int ret; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (inqCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = sizeof (sense_buffer); -+ io_hdr.dxferp = sense_buffer; -+ io_hdr.cmdp = inqCmdBlk; -+ io_hdr.sbp = sb; -+ 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"); -+ return PATH_DOWN; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ MSG(c, "emc_clariion_checker: query command indicates error"); -+ return PATH_DOWN; -+ } -+ if (/* Verify the code page - right page & revision */ -+ sense_buffer[1] != 0xc0 || sense_buffer[9] != 0x00) { -+ MSG(c, "emc_clariion_checker: Path unit report page in " -+ "unknown format"); -+ return PATH_DOWN; -+ } -+ -+ if ( /* Effective initiator type */ -+ sense_buffer[27] != 0x03 -+ /* -+ * Failover mode should be set to 1 (PNR failover mode) -+ * or 4 (ALUA failover mode). -+ */ -+ || (((sense_buffer[28] & 0x07) != 0x04) && -+ ((sense_buffer[28] & 0x07) != 0x06)) -+ /* Arraycommpath should be set to 1 */ -+ || (sense_buffer[30] & 0x04) != 0x04) { -+ MSG(c, "emc_clariion_checker: Path not correctly configured " -+ "for failover"); -+ return PATH_DOWN; -+ } -+ -+ if ( /* LUN operations should indicate normal operations */ -+ sense_buffer[48] != 0x00) { -+ MSG(c, "emc_clariion_checker: Path not available for normal " -+ "operations"); -+ return PATH_SHAKY; -+ } -+ -+ if ( /* LUN should at least be bound somewhere and not be LUNZ */ -+ sense_buffer[4] == 0x00) { -+ MSG(c, "emc_clariion_checker: Logical Unit is unbound " -+ "or LUNZ"); -+ return PATH_DOWN; -+ } -+ -+ /* -+ * store the LUN WWN there and compare that it indeed did not -+ * change in between, to protect against the path suddenly -+ * pointing somewhere else. -+ */ -+ if (ct->wwn_set) { -+ if (memcmp(ct->wwn, &sense_buffer[10], 16) != 0) { -+ MSG(c, "emc_clariion_checker: Logical Unit WWN " -+ "has changed!"); -+ return PATH_DOWN; -+ } -+ } else { -+ memcpy(ct->wwn, &sense_buffer[10], 16); -+ ct->wwn_set = 1; -+ } -+ -+ /* -+ * Issue read on active path to determine if inactive snapshot. -+ */ -+ if (sense_buffer[4] == 2) {/* if active path */ -+ unsigned char buf[4096]; -+ -+ ret = sg_read(c->fd, &buf[0], sbb = &sb[0]); -+ if (ret == PATH_DOWN) { -+ hexadecimal_to_ascii(ct->wwn, wwnstr); -+ -+ /* -+ * Check for inactive snapshot LU this way. Must -+ * fail these. -+ */ -+ if (((sbb[2]&0xf) == 5) && (sbb[12] == 0x25) && -+ (sbb[13]==1)) { -+ /* -+ * Do this so that we can fail even the -+ * passive paths which will return -+ * 02/04/03 not 05/25/01 on read. -+ */ -+ SET_INACTIVE_SNAP(c); -+ MSG(c, "emc_clariion_checker: Active " -+ "path to inactive snapshot WWN %s.", -+ wwnstr); -+ } else -+ MSG(c, "emc_clariion_checker: Read " -+ "error for WWN %s. Sense data are " -+ "0x%x/0x%x/0x%x.", wwnstr, -+ sbb[2]&0xf, sbb[12], sbb[13]); -+ } else { -+ MSG(c, "emc_clariion_checker: Active path is " -+ "healthy."); -+ /* -+ * Remove the path from the set of paths to inactive -+ * snapshot LUs if it was in this list since the -+ * snapshot is no longer inactive. -+ */ -+ CLR_INACTIVE_SNAP(c); -+ } -+ } else { -+ if (IS_INACTIVE_SNAP(c)) { -+ hexadecimal_to_ascii(ct->wwn, wwnstr); -+ MSG(c, "emc_clariion_checker: Passive " -+ "path to inactive snapshot WWN %s.", -+ wwnstr); -+ ret = PATH_DOWN; -+ } else { -+ MSG(c, -+ "emc_clariion_checker: Passive path is healthy."); -+ ret = PATH_UP; /* not ghost */ -+ } -+ } -+ -+ return ret; -+} -diff --git a/libmultipath/checkers/emc_clariion.h b/libmultipath/checkers/emc_clariion.h -new file mode 100644 -index 0000000..a1018a6 ---- /dev/null -+++ b/libmultipath/checkers/emc_clariion.h -@@ -0,0 +1,8 @@ -+#ifndef _EMC_CLARIION_H -+#define _EMC_CLARIION_H -+ -+int emc_clariion (struct checker *); -+int emc_clariion_init (struct checker *); -+void emc_clariion_free (struct checker *); -+ -+#endif /* _EMC_CLARIION_H */ -diff --git a/libmultipath/checkers/hp_sw.c b/libmultipath/checkers/hp_sw.c -new file mode 100644 -index 0000000..7509307 ---- /dev/null -+++ b/libmultipath/checkers/hp_sw.c -@@ -0,0 +1,141 @@ -+/* -+ * Copyright (c) 2005 Christophe Varoqui -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "checkers.h" -+ -+#include "../libmultipath/sg_include.h" -+ -+#define TUR_CMD_LEN 6 -+#define INQUIRY_CMDLEN 6 -+#define INQUIRY_CMD 0x12 -+#define SENSE_BUFF_LEN 32 -+#define SCSI_CHECK_CONDITION 0x2 -+#define SCSI_COMMAND_TERMINATED 0x22 -+#define SG_ERR_DRIVER_SENSE 0x08 -+#define RECOVERED_ERROR 0x01 -+#define MX_ALLOC_LEN 255 -+#define HEAVY_CHECK_COUNT 10 -+ -+#define MSG_HP_SW_UP "hp_sw checker reports path is up" -+#define MSG_HP_SW_DOWN "hp_sw checker reports path is down" -+#define MSG_HP_SW_GHOST "hp_sw checker reports path is ghost" -+ -+struct sw_checker_context { -+ void * dummy; -+}; -+ -+int libcheck_init (struct checker * c) -+{ -+ return 0; -+} -+ -+void libcheck_free (struct checker * c) -+{ -+ return; -+} -+ -+static int -+do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, -+ void *resp, int mx_resp_len, int noisy) -+{ -+ unsigned char inqCmdBlk[INQUIRY_CMDLEN] = -+ { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -+ unsigned char sense_b[SENSE_BUFF_LEN]; -+ struct sg_io_hdr io_hdr; -+ -+ if (cmddt) -+ inqCmdBlk[1] |= 2; -+ if (evpd) -+ inqCmdBlk[1] |= 1; -+ inqCmdBlk[2] = (unsigned char) pg_op; -+ inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); -+ inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (inqCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sense_b); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = mx_resp_len; -+ io_hdr.dxferp = resp; -+ io_hdr.cmdp = inqCmdBlk; -+ io_hdr.sbp = sense_b; -+ io_hdr.timeout = DEF_TIMEOUT; -+ -+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -+ return 1; -+ -+ /* treat SG_ERR here to get rid of sg_err.[ch] */ -+ io_hdr.status &= 0x7e; -+ if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -+ (0 == io_hdr.driver_status)) -+ return 0; -+ if ((SCSI_CHECK_CONDITION == io_hdr.status) || -+ (SCSI_COMMAND_TERMINATED == io_hdr.status) || -+ (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -+ if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -+ int sense_key; -+ unsigned char * sense_buffer = io_hdr.sbp; -+ if (sense_buffer[0] & 0x2) -+ sense_key = sense_buffer[1] & 0xf; -+ else -+ sense_key = sense_buffer[2] & 0xf; -+ if(RECOVERED_ERROR == sense_key) -+ return 0; -+ } -+ } -+ return 1; -+} -+ -+static int -+do_tur (int fd) -+{ -+ unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -+ struct sg_io_hdr io_hdr; -+ unsigned char sense_buffer[32]; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (turCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sense_buffer); -+ io_hdr.dxfer_direction = SG_DXFER_NONE; -+ io_hdr.cmdp = turCmdBlk; -+ io_hdr.sbp = sense_buffer; -+ io_hdr.timeout = DEF_TIMEOUT; -+ io_hdr.pack_id = 0; -+ -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) -+ return 1; -+ -+ if (io_hdr.info & SG_INFO_OK_MASK) -+ return 1; -+ -+ return 0; -+} -+ -+extern int -+libcheck_check (struct checker * c) -+{ -+ char buff[MX_ALLOC_LEN]; -+ -+ if (0 != do_inq(c->fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { -+ MSG(c, MSG_HP_SW_DOWN); -+ return PATH_DOWN; -+ } -+ -+ if (do_tur(c->fd)) { -+ MSG(c, MSG_HP_SW_GHOST); -+ return PATH_GHOST; -+ } -+ MSG(c, MSG_HP_SW_UP); -+ return PATH_UP; -+} -diff --git a/libmultipath/checkers/hp_sw.h b/libmultipath/checkers/hp_sw.h -new file mode 100644 -index 0000000..3be0d8e ---- /dev/null -+++ b/libmultipath/checkers/hp_sw.h -@@ -0,0 +1,8 @@ -+#ifndef _HP_SW_H -+#define _HP_SW_H -+ -+int hp_sw (struct checker *); -+int hp_sw_init (struct checker *); -+void hp_sw_free (struct checker *); -+ -+#endif /* _HP_SW_H */ -diff --git a/libmultipath/checkers/libsg.c b/libmultipath/checkers/libsg.c -new file mode 100644 -index 0000000..4cb7ecc ---- /dev/null -+++ b/libmultipath/checkers/libsg.c -@@ -0,0 +1,95 @@ -+/* -+ * Copyright (c) 2004, 2005 Christophe Varoqui -+ */ -+#include -+#include -+#include -+#include -+ -+#include "checkers.h" -+#include "libsg.h" -+#include "../libmultipath/sg_include.h" -+ -+int -+sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff) -+{ -+ /* defaults */ -+ int blocks = 1; -+ long long start_block = 0; -+ int bs = 512; -+ int cdbsz = 10; -+ int * diop = NULL; -+ -+ unsigned char rdCmd[cdbsz]; -+ unsigned char *sbb = senseBuff; -+ struct sg_io_hdr io_hdr; -+ int res; -+ int rd_opcode[] = {0x8, 0x28, 0xa8, 0x88}; -+ int sz_ind; -+ struct stat filestatus; -+ int retry_count = 3; -+ -+ if (fstat(sg_fd, &filestatus) != 0) -+ return PATH_DOWN; -+ bs = (filestatus.st_blksize > 4096)? 4096: filestatus.st_blksize; -+ memset(rdCmd, 0, cdbsz); -+ sz_ind = 1; -+ rdCmd[0] = rd_opcode[sz_ind]; -+ rdCmd[2] = (unsigned char)((start_block >> 24) & 0xff); -+ rdCmd[3] = (unsigned char)((start_block >> 16) & 0xff); -+ rdCmd[4] = (unsigned char)((start_block >> 8) & 0xff); -+ rdCmd[5] = (unsigned char)(start_block & 0xff); -+ rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff); -+ rdCmd[8] = (unsigned char)(blocks & 0xff); -+ -+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = cdbsz; -+ io_hdr.cmdp = rdCmd; -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = bs * blocks; -+ io_hdr.dxferp = buff; -+ io_hdr.mx_sb_len = SENSE_BUFF_LEN; -+ io_hdr.sbp = senseBuff; -+ io_hdr.timeout = DEF_TIMEOUT; -+ io_hdr.pack_id = (int)start_block; -+ if (diop && *diop) -+ io_hdr.flags |= SG_FLAG_DIRECT_IO; -+ -+retry: -+ memset(senseBuff, 0, SENSE_BUFF_LEN); -+ while (((res = ioctl(sg_fd, SG_IO, &io_hdr)) < 0) && (EINTR == errno)); -+ -+ if (res < 0) { -+ if (ENOMEM == errno) { -+ return PATH_UP; -+ } -+ return PATH_DOWN; -+ } -+ -+ if ((0 == io_hdr.status) && -+ (0 == io_hdr.host_status) && -+ (0 == io_hdr.driver_status)) { -+ return PATH_UP; -+ } else { -+ int key = 0; -+ -+ if (io_hdr.sb_len_wr > 3) { -+ if (sbb[0] == 0x72 || sbb[0] == 0x73) -+ key = sbb[1] & 0x0f; -+ else if (io_hdr.sb_len_wr > 13 && -+ ((sbb[0] & 0x7f) == 0x70 || -+ (sbb[0] & 0x7f) == 0x71)) -+ key = sbb[2] & 0x0f; -+ } -+ -+ /* -+ * Retry if UNIT_ATTENTION check condition. -+ */ -+ if (key == 0x6) { -+ if (--retry_count) -+ goto retry; -+ } -+ return PATH_DOWN; -+ } -+} -diff --git a/libmultipath/checkers/libsg.h b/libmultipath/checkers/libsg.h -new file mode 100644 -index 0000000..97c4491 ---- /dev/null -+++ b/libmultipath/checkers/libsg.h -@@ -0,0 +1,8 @@ -+#ifndef _LIBSG_H -+#define _LIBSG_H -+ -+#define SENSE_BUFF_LEN 32 -+ -+int sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff); -+ -+#endif /* _LIBSG_H */ -diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c -new file mode 100644 -index 0000000..0086125 ---- /dev/null -+++ b/libmultipath/checkers/rdac.c -@@ -0,0 +1,109 @@ -+/* -+ * Copyright (c) 2005 Christophe Varoqui -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "checkers.h" -+ -+#include "../libmultipath/sg_include.h" -+ -+#define INQUIRY_CMDLEN 6 -+#define INQUIRY_CMD 0x12 -+#define SENSE_BUFF_LEN 32 -+#define RDAC_DEF_TIMEOUT 60000 -+#define SCSI_CHECK_CONDITION 0x2 -+#define SCSI_COMMAND_TERMINATED 0x22 -+#define SG_ERR_DRIVER_SENSE 0x08 -+#define RECOVERED_ERROR 0x01 -+ -+#define MSG_RDAC_UP "rdac checker reports path is up" -+#define MSG_RDAC_DOWN "rdac checker reports path is down" -+#define MSG_RDAC_GHOST "rdac checker reports path is ghost" -+ -+struct rdac_checker_context { -+ void * dummy; -+}; -+ -+int libcheck_init (struct checker * c) -+{ -+ return 0; -+} -+ -+void libcheck_free (struct checker * c) -+{ -+ return; -+} -+ -+static int -+do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len) -+{ -+ unsigned char inqCmdBlk[INQUIRY_CMDLEN] = { INQUIRY_CMD, 1, 0, 0, 0, 0 }; -+ unsigned char sense_b[SENSE_BUFF_LEN]; -+ struct sg_io_hdr io_hdr; -+ -+ inqCmdBlk[2] = (unsigned char) pg_op; -+ inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (inqCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sense_b); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = mx_resp_len; -+ io_hdr.dxferp = resp; -+ io_hdr.cmdp = inqCmdBlk; -+ io_hdr.sbp = sense_b; -+ io_hdr.timeout = RDAC_DEF_TIMEOUT; -+ -+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -+ return 1; -+ -+ /* treat SG_ERR here to get rid of sg_err.[ch] */ -+ io_hdr.status &= 0x7e; -+ if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -+ (0 == io_hdr.driver_status)) -+ return 0; -+ if ((SCSI_CHECK_CONDITION == io_hdr.status) || -+ (SCSI_COMMAND_TERMINATED == io_hdr.status) || -+ (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -+ if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -+ int sense_key; -+ unsigned char * sense_buffer = io_hdr.sbp; -+ if (sense_buffer[0] & 0x2) -+ sense_key = sense_buffer[1] & 0xf; -+ else -+ sense_key = sense_buffer[2] & 0xf; -+ if (RECOVERED_ERROR == sense_key) -+ return 0; -+ } -+ } -+ return 1; -+} -+ -+struct volume_access_inq -+{ -+ char dontcare0[8]; -+ char avtcvp; -+ char dontcare1[39]; -+}; -+ -+extern int -+libcheck_check (struct checker * c) -+{ -+ struct volume_access_inq inq; -+ -+ if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq))) { -+ MSG(c, MSG_RDAC_DOWN); -+ return PATH_DOWN; -+ } -+ -+ return ((inq.avtcvp & 0x1) ? PATH_UP : PATH_GHOST); -+} -diff --git a/libmultipath/checkers/rdac.h b/libmultipath/checkers/rdac.h -new file mode 100644 -index 0000000..d7bf812 ---- /dev/null -+++ b/libmultipath/checkers/rdac.h -@@ -0,0 +1,8 @@ -+#ifndef _RDAC_H -+#define _RDAC_H -+ -+int rdac(struct checker *); -+int rdac_init(struct checker *); -+void rdac_free(struct checker *); -+ -+#endif /* _RDAC_H */ -diff --git a/libmultipath/checkers/readsector0.c b/libmultipath/checkers/readsector0.c -new file mode 100644 -index 0000000..24182e6 ---- /dev/null -+++ b/libmultipath/checkers/readsector0.c -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (c) 2004, 2005 Christophe Varoqui -+ */ -+#include -+ -+#include "checkers.h" -+#include "libsg.h" -+ -+#define MSG_READSECTOR0_UP "readsector0 checker reports path is up" -+#define MSG_READSECTOR0_DOWN "readsector0 checker reports path is down" -+ -+struct readsector0_checker_context { -+ void * dummy; -+}; -+ -+int libcheck_init (struct checker * c) -+{ -+ return 0; -+} -+ -+void libcheck_free (struct checker * c) -+{ -+ return; -+} -+ -+int libcheck_check (struct checker * c) -+{ -+ unsigned char buf[4096]; -+ unsigned char sbuf[SENSE_BUFF_LEN]; -+ int ret; -+ -+ ret = sg_read(c->fd, &buf[0], &sbuf[0]); -+ -+ switch (ret) -+ { -+ case PATH_DOWN: -+ MSG(c, MSG_READSECTOR0_DOWN); -+ break; -+ case PATH_UP: -+ MSG(c, MSG_READSECTOR0_UP); -+ break; -+ default: -+ break; -+ } -+ return ret; -+} -diff --git a/libmultipath/checkers/readsector0.h b/libmultipath/checkers/readsector0.h -new file mode 100644 -index 0000000..0f5d654 ---- /dev/null -+++ b/libmultipath/checkers/readsector0.h -@@ -0,0 +1,8 @@ -+#ifndef _READSECTOR0_H -+#define _READSECTOR0_H -+ -+int readsector0 (struct checker *); -+int readsector0_init (struct checker *); -+void readsector0_free (struct checker *); -+ -+#endif /* _READSECTOR0_H */ -diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c -new file mode 100644 -index 0000000..43b846d ---- /dev/null -+++ b/libmultipath/checkers/tur.c -@@ -0,0 +1,88 @@ -+/* -+ * Some code borrowed from sg-utils. -+ * -+ * Copyright (c) 2004 Christophe Varoqui -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "checkers.h" -+ -+#include "../libmultipath/sg_include.h" -+ -+#define TUR_CMD_LEN 6 -+#define HEAVY_CHECK_COUNT 10 -+ -+#define MSG_TUR_UP "tur checker reports path is up" -+#define MSG_TUR_DOWN "tur checker reports path is down" -+ -+struct tur_checker_context { -+ void * dummy; -+}; -+ -+int libcheck_init (struct checker * c) -+{ -+ return 0; -+} -+ -+void libcheck_free (struct checker * c) -+{ -+ return; -+} -+ -+extern int -+libcheck_check (struct checker * c) -+{ -+ struct sg_io_hdr io_hdr; -+ unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -+ unsigned char sense_buffer[32]; -+ int retry_tur = 5; -+ -+ retry: -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (turCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sense_buffer); -+ io_hdr.dxfer_direction = SG_DXFER_NONE; -+ io_hdr.cmdp = turCmdBlk; -+ io_hdr.sbp = sense_buffer; -+ io_hdr.timeout = DEF_TIMEOUT; -+ io_hdr.pack_id = 0; -+ if (ioctl(c->fd, SG_IO, &io_hdr) < 0) { -+ MSG(c, MSG_TUR_DOWN); -+ return PATH_DOWN; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ int key = 0, asc, ascq; -+ -+ if (io_hdr.sb_len_wr > 3) { -+ if (io_hdr.sbp[0] == 0x72 || io_hdr.sbp[0] == 0x73) { -+ key = io_hdr.sbp[1] & 0x0f; -+ asc = io_hdr.sbp[2]; -+ ascq = io_hdr.sbp[3]; -+ } else if (io_hdr.sb_len_wr > 13 && -+ ((io_hdr.sbp[0] & 0x7f) == 0x70 || -+ (io_hdr.sbp[0] & 0x7f) == 0x71)) { -+ key = io_hdr.sbp[2] & 0x0f; -+ asc = io_hdr.sbp[12]; -+ ascq = io_hdr.sbp[13]; -+ } -+ } -+ if (key == 0x6) { -+ /* Unit Attention, retry */ -+ if (--retry_tur) -+ goto retry; -+ } -+ MSG(c, MSG_TUR_DOWN); -+ return PATH_DOWN; -+ } -+ MSG(c, MSG_TUR_UP); -+ return PATH_UP; -+} -diff --git a/libmultipath/checkers/tur.h b/libmultipath/checkers/tur.h -new file mode 100644 -index 0000000..a2e8c88 ---- /dev/null -+++ b/libmultipath/checkers/tur.h -@@ -0,0 +1,8 @@ -+#ifndef _TUR_H -+#define _TUR_H -+ -+int tur (struct checker *); -+int tur_init (struct checker *); -+void tur_free (struct checker *); -+ -+#endif /* _TUR_H */ -diff --git a/libmultipath/config.c b/libmultipath/config.c -index a39af8a..a109cd9 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -6,8 +6,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "memory.h" - #include "util.h" - #include "debug.h" -@@ -19,24 +18,33 @@ - #include "config.h" - #include "blacklist.h" - #include "defaults.h" -+#include "prio.h" - --static struct hwentry * --find_hwe_strmatch (vector hwtable, char * vendor, char * product, char * revision) -+static int -+hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2) - { -- int i; -- struct hwentry *hwe, *ret = NULL; -+ if (hwe1->vendor && hwe2->vendor && strcmp(hwe1->vendor, hwe2->vendor)) -+ return 1; - -- vector_foreach_slot (hwtable, hwe, i) { -- if (hwe->vendor && vendor && strcmp(hwe->vendor, vendor)) -- continue; -+ if (hwe1->product && hwe2->product && strcmp(hwe1->product, hwe2->product)) -+ return 1; - -- if (hwe->product && product && strcmp(hwe->product, product)) -- continue; -+ if (hwe1->revision && hwe2->revision && strcmp(hwe1->revision, hwe2->revision)) -+ return 1; - -- if (hwe->revision && revision && strcmp(hwe->revision, revision)) -- continue; -+ return 0; -+} - -- ret = hwe; -+static struct hwentry * -+find_hwe_strmatch (vector hwtable, struct hwentry *hwe) -+{ -+ int i; -+ struct hwentry *tmp, *ret = NULL; -+ -+ vector_foreach_slot (hwtable, tmp, i) { -+ if (hwe_strmatch(tmp, hwe)) -+ continue; -+ ret = tmp; - break; - } - return ret; -@@ -135,9 +143,6 @@ free_hwe (struct hwentry * hwe) - if (hwe->getuid) - FREE(hwe->getuid); - -- if (hwe->getprio) -- FREE(hwe->getprio); -- - if (hwe->features) - FREE(hwe->features); - -@@ -242,12 +247,47 @@ set_param_str(char * str) - return dst; - } - -+#define merge_str(s) \ -+ if (hwe2->s) { \ -+ if (hwe1->s) \ -+ free(hwe1->s); \ -+ if (!(hwe1->s = set_param_str(hwe2->s))) \ -+ return 1; \ -+ } -+ -+#define merge_num(s) \ -+ if (hwe2->s) \ -+ hwe1->s = hwe2->s -+ -+ -+static int -+merge_hwe (struct hwentry * hwe1, struct hwentry * hwe2) -+{ -+ merge_str(vendor); -+ merge_str(product); -+ merge_str(revision); -+ merge_str(getuid); -+ merge_str(features); -+ merge_str(hwhandler); -+ merge_str(selector); -+ merge_str(checker_name); -+ merge_str(prio_name); -+ merge_str(bl_product); -+ merge_num(pgpolicy); -+ merge_num(pgfailback); -+ merge_num(rr_weight); -+ merge_num(no_path_retry); -+ merge_num(minio); -+ -+ return 0; -+} -+ - int - store_hwe (vector hwtable, struct hwentry * dhwe) - { - struct hwentry * hwe; - -- if (find_hwe_strmatch(hwtable, dhwe->vendor, dhwe->product, dhwe->revision)) -+ if (find_hwe_strmatch(hwtable, dhwe)) - return 0; - - if (!(hwe = alloc_hwe())) -@@ -265,9 +305,6 @@ store_hwe (vector hwtable, struct hwentry * dhwe) - if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid))) - goto out; - -- if (dhwe->getprio && !(hwe->getprio = set_param_str(dhwe->getprio))) -- goto out; -- - if (dhwe->features && !(hwe->features = set_param_str(dhwe->features))) - goto out; - -@@ -276,13 +313,18 @@ store_hwe (vector hwtable, struct hwentry * dhwe) - - if (dhwe->selector && !(hwe->selector = set_param_str(dhwe->selector))) - goto out; -+ -+ if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name))) -+ goto out; -+ -+ if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name))) -+ goto out; - - hwe->pgpolicy = dhwe->pgpolicy; - hwe->pgfailback = dhwe->pgfailback; - hwe->rr_weight = dhwe->rr_weight; - hwe->no_path_retry = dhwe->no_path_retry; - hwe->minio = dhwe->minio; -- hwe->checker = dhwe->checker; - - if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product))) - goto out; -@@ -297,6 +339,27 @@ out: - return 1; - } - -+static int -+factorize_hwtable (vector hw) -+{ -+ struct hwentry *hwe1, *hwe2; -+ int i, j; -+ -+ vector_foreach_slot(hw, hwe1, i) { -+ j = i+1; -+ vector_foreach_slot_after(hw, hwe2, j) { -+ if (hwe_strmatch(hwe1, hwe2)) -+ continue; -+ /* dup */ -+ merge_hwe(hwe1, hwe2); -+ free_hwe(hwe2); -+ vector_del_slot(hw, j); -+ j--; -+ } -+ } -+ return 0; -+} -+ - struct config * - alloc_config (void) - { -@@ -315,15 +378,15 @@ free_config (struct config * conf) - if (conf->udev_dir) - FREE(conf->udev_dir); - -+ if (conf->multipath_dir) -+ FREE(conf->multipath_dir); -+ - if (conf->selector) - FREE(conf->selector); - - if (conf->getuid) - FREE(conf->getuid); - -- if (conf->getprio) -- FREE(conf->getprio); -- - if (conf->features) - FREE(conf->features); - -@@ -361,7 +424,21 @@ load_config (char * file) - - conf->dev_type = DEV_NONE; - conf->minio = 1000; -+ conf->max_fds = 0; - conf->bindings_file = DEFAULT_BINDINGS_FILE; -+ conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR); -+ -+ /* -+ * preload default hwtable -+ */ -+ if (conf->hwtable == NULL) { -+ conf->hwtable = vector_alloc(); -+ -+ if (!conf->hwtable) -+ goto out; -+ } -+ if (setup_default_hwtable(conf->hwtable)) -+ goto out; - - /* - * read the config file -@@ -373,35 +450,31 @@ load_config (char * file) - goto out; - } - } -- -+ - /* -- * fill the voids left in the config file -+ * remove duplica in hwtable. config file takes precedence -+ * over build-in hwtable - */ -- if (conf->hwtable == NULL) { -- conf->hwtable = vector_alloc(); -- -- if (!conf->hwtable) -- goto out; -- -- } -- if (setup_default_hwtable(conf->hwtable)) -- goto out; -+ factorize_hwtable(conf->hwtable); - -+ /* -+ * fill the voids left in the config file -+ */ - if (conf->blist_devnode == NULL) { - conf->blist_devnode = vector_alloc(); -- -+ - if (!conf->blist_devnode) - goto out; - } - if (conf->blist_wwid == NULL) { - conf->blist_wwid = vector_alloc(); -- -+ - if (!conf->blist_wwid) - goto out; - } - if (conf->blist_device == NULL) { - conf->blist_device = vector_alloc(); -- -+ - if (!conf->blist_device) - goto out; - } -@@ -409,21 +482,21 @@ load_config (char * file) - goto out; - - if (conf->elist_devnode == NULL) { -- conf->elist_devnode = vector_alloc(); -+ conf->elist_devnode = vector_alloc(); - -- if (!conf->elist_devnode) -+ if (!conf->elist_devnode) - goto out; - } - if (conf->elist_wwid == NULL) { - conf->elist_wwid = vector_alloc(); - -- if (!conf->elist_wwid) -+ if (!conf->elist_wwid) - goto out; - } - - if (conf->elist_device == NULL) { - conf->elist_device = vector_alloc(); -- -+ - if (!conf->elist_device) - goto out; - } -@@ -449,13 +522,16 @@ load_config (char * file) - if (conf->hwhandler == NULL) - conf->hwhandler = set_default(DEFAULT_HWHANDLER); - -- if (!conf->selector || !conf->udev_dir || -+ if (!conf->selector || !conf->udev_dir || !conf->multipath_dir || - !conf->getuid || !conf->features || - !conf->hwhandler) - goto out; - -- if (!conf->checker) -- conf->checker = checker_lookup(DEFAULT_CHECKER); -+ if (!conf->prio_name) -+ conf->prio_name = set_default(DEFAULT_PRIO); -+ -+ if (!conf->checker_name) -+ conf->checker_name = set_default(DEFAULT_CHECKER); - - return 0; - out: -diff --git a/libmultipath/config.h b/libmultipath/config.h -index a25b3ad..fb917f4 100644 ---- a/libmultipath/config.h -+++ b/libmultipath/config.h -@@ -16,11 +16,11 @@ struct hwentry { - char * product; - char * revision; - char * getuid; -- char * getprio; - char * features; - char * hwhandler; - char * selector; - char * checker_name; -+ char * prio_name; - - int pgpolicy; - int pgfailback; -@@ -28,7 +28,6 @@ struct hwentry { - int no_path_retry; - int minio; - int pg_timeout; -- struct checker * checker; - char * bl_product; - }; - -@@ -53,7 +52,6 @@ struct config { - int pgpolicy_flag; - int with_sysfs; - int pgpolicy; -- struct checker * checker; - enum devtypes dev_type; - int minio; - int checkint; -@@ -64,16 +62,20 @@ struct config { - int no_path_retry; - int user_friendly_names; - int pg_timeout; -+ int max_fds; -+ int force_reload; - - char * dev; - char * sysfs_dir; - char * udev_dir; -+ char * multipath_dir; - char * selector; - char * getuid; -- char * getprio; - char * features; - char * hwhandler; - char * bindings_file; -+ char * prio_name; -+ char * checker_name; - - vector keywords; - vector mptable; -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 3cd6041..285a8a2 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -14,8 +14,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "memory.h" - #include "devmapper.h" -@@ -34,6 +33,7 @@ - #include "pgpolicies.h" - #include "dict.h" - #include "alias.h" -+#include "prio.h" - - extern int - setup_map (struct multipath * mpp) -@@ -130,7 +130,7 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) - } - - static void --select_action (struct multipath * mpp, vector curmp) -+select_action (struct multipath * mpp, vector curmp, int force_reload) - { - struct multipath * cmpp; - -@@ -154,7 +154,7 @@ select_action (struct multipath * mpp, vector curmp) - - if (!find_mp_by_wwid(curmp, mpp->wwid)) { - condlog(2, "%s: remove (wwid changed)", cmpp->alias); -- dm_flush_map(mpp->alias, DEFAULT_TARGET); -+ dm_flush_map(mpp->alias); - strncat(cmpp->wwid, mpp->wwid, WWID_SIZE); - drop_multipath(curmp, cmpp->wwid, KEEP_PATHS); - mpp->action = ACT_CREATE; -@@ -169,6 +169,12 @@ select_action (struct multipath * mpp, vector curmp) - mpp->alias); - return; - } -+ if (force_reload) { -+ mpp->action = ACT_RELOAD; -+ condlog(3, "%s: set ACT_RELOAD (forced by user)", -+ mpp->alias); -+ return; -+ } - if (cmpp->size != mpp->size) { - mpp->action = ACT_RELOAD; - condlog(3, "%s: set ACT_RELOAD (size change)", -@@ -183,14 +189,14 @@ select_action (struct multipath * mpp, vector curmp) - mpp->alias); - return; - } -- if (strncmp(cmpp->hwhandler, mpp->hwhandler, -+ if (!cmpp->selector || strncmp(cmpp->hwhandler, mpp->hwhandler, - strlen(mpp->hwhandler))) { - mpp->action = ACT_RELOAD; - condlog(3, "%s: set ACT_RELOAD (hwhandler change)", - mpp->alias); - return; - } -- if (strncmp(cmpp->selector, mpp->selector, -+ if (!cmpp->selector || strncmp(cmpp->selector, mpp->selector, - strlen(mpp->selector))) { - mpp->action = ACT_RELOAD; - condlog(3, "%s: set ACT_RELOAD (selector change)", -@@ -203,7 +209,7 @@ select_action (struct multipath * mpp, vector curmp) - mpp->alias, cmpp->minio, mpp->minio); - return; - } -- if (VECTOR_SIZE(cmpp->pg) != VECTOR_SIZE(mpp->pg)) { -+ if (!cmpp->pg || VECTOR_SIZE(cmpp->pg) != VECTOR_SIZE(mpp->pg)) { - mpp->action = ACT_RELOAD; - condlog(3, "%s: set ACT_RELOAD (path group number change)", - mpp->alias); -@@ -330,28 +336,19 @@ domap (struct multipath * mpp) - break; - } - -- r = dm_addmap(DM_DEVICE_CREATE, mpp->alias, DEFAULT_TARGET, -- mpp->params, mpp->size, mpp->wwid); -+ r = dm_addmap_create(mpp->alias, mpp->params, mpp->size, -+ mpp->wwid); - -- /* -- * DM_DEVICE_CREATE is actually DM_DEV_CREATE plus -- * DM_TABLE_LOAD. Failing the second part leaves an -- * empty map. Clean it up. -- */ -- if (!r && dm_map_present(mpp->alias)) { -- condlog(3, "%s: failed to load map " -- "(a path might be in use)", -- mpp->alias); -- dm_flush_map(mpp->alias, DEFAULT_TARGET); -- } -+ if (!r) -+ r = dm_addmap_create_ro(mpp->alias, mpp->params, -+ mpp->size, mpp->wwid); - - lock_multipath(mpp, 0); - break; - - case ACT_RELOAD: -- r = (dm_addmap(DM_DEVICE_RELOAD, mpp->alias, DEFAULT_TARGET, -- mpp->params, mpp->size, NULL) && -- dm_simplecmd(DM_DEVICE_RESUME, mpp->alias)); -+ r = (dm_addmap_reload(mpp->alias, mpp->params, mpp->size, NULL) -+ && dm_simplecmd(DM_DEVICE_RESUME, mpp->alias)); - break; - - case ACT_RENAME: -@@ -364,18 +361,24 @@ domap (struct multipath * mpp) - - if (r) { - /* -- * DM_DEVICE_CREATE, DM_DEIVCE_RENAME, or DM_DEVICE_RELOAD -+ * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD - * succeeded - */ --#ifndef DAEMON -- dm_switchgroup(mpp->alias, mpp->bestpg); -- if (mpp->action != ACT_NOTHING) -- print_multipath_topology(mpp, conf->verbosity); --#else -- mpp->stat_map_loads++; -- condlog(2, "%s: load table [0 %llu %s %s]", mpp->alias, -- mpp->size, DEFAULT_TARGET, mpp->params); --#endif -+ if (!mpp->waiter) { -+ /* multipath client mode */ -+ dm_switchgroup(mpp->alias, mpp->bestpg); -+ if (mpp->action != ACT_NOTHING) -+ print_multipath_topology(mpp, conf->verbosity); -+ } else { -+ /* multipath daemon mode */ -+ mpp->stat_map_loads++; -+ condlog(2, "%s: load table [0 %llu %s %s]", mpp->alias, -+ mpp->size, TGT_MPATH, mpp->params); -+ /* -+ * Required action is over, reset for the stateful daemon -+ */ -+ mpp->action = ACT_NOTHING; -+ } - return DOMAP_OK; - } - return DOMAP_FAIL; -@@ -404,7 +407,7 @@ deadmap (struct multipath * mpp) - } - - extern int --coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) -+coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_reload) - { - int r = 1; - int k, i; -@@ -417,6 +420,11 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) - - memset(empty_buff, 0, WWID_SIZE); - -+ if (force_reload) { -+ vector_foreach_slot (pathvec, pp1, k) { -+ pp1->mpp = NULL; -+ } -+ } - vector_foreach_slot (pathvec, pp1, k) { - /* skip this path for some reason */ - -@@ -440,7 +448,8 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) - /* - * at this point, we know we really got a new mp - */ -- if ((mpp = add_map_with_path(vecs, pp1, 0)) == NULL) -+ mpp = add_map_with_path(vecs, pp1, 0); -+ if (!mpp) - return 1; - - if (pp1->priority == PRIO_UNDEF) -@@ -448,7 +457,7 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) - - if (!mpp->paths) { - condlog(0, "%s: skip coalesce (no paths)", mpp->alias); -- remove_map(mpp, vecs, NULL, 0); -+ remove_map(mpp, vecs, 0); - continue; - } - -@@ -476,12 +485,12 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) - verify_paths(mpp, vecs, NULL); - - if (setup_map(mpp)) { -- remove_map(mpp, vecs, NULL, 0); -+ remove_map(mpp, vecs, 0); - continue; - } - - if (mpp->action == ACT_UNDEF) -- select_action(mpp, curmp); -+ select_action(mpp, curmp, force_reload); - - r = domap(mpp); - -@@ -490,7 +499,7 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) - "for create/reload map", - mpp->alias, r); - if (r == DOMAP_FAIL) { -- remove_map(mpp, vecs, NULL, 0); -+ remove_map(mpp, vecs, 0); - continue; - } else /* if (r == DOMAP_RETRY) */ - return r; -@@ -518,7 +527,7 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) - vector_set_slot(newmp, mpp); - } - else -- remove_map(mpp, vecs, NULL, 0); -+ remove_map(mpp, vecs, 0); - } - } - /* -@@ -538,9 +547,9 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid) - if ((j = find_slot(newmp, (void *)mpp)) != -1) - vector_del_slot(newmp, j); - -- remove_map(mpp, vecs, NULL, 0); -+ remove_map(mpp, vecs, 0); - -- if (dm_flush_map(mpp->alias, DEFAULT_TARGET)) -+ if (dm_flush_map(mpp->alias)) - condlog(2, "%s: remove failed (dead)", - mpp->alias); - else -diff --git a/libmultipath/configure.h b/libmultipath/configure.h -index 1cbbe82..75d5057 100644 ---- a/libmultipath/configure.h -+++ b/libmultipath/configure.h -@@ -24,6 +24,6 @@ enum actions { - int setup_map (struct multipath * mpp); - int domap (struct multipath * mpp); - int reinstate_paths (struct multipath *mpp); --int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid); -+int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload); - char * get_refwwid (char * dev, enum devtypes dev_type, vector pathvec); - -diff --git a/libmultipath/debug.c b/libmultipath/debug.c -index 05dfb06..d30517d 100644 ---- a/libmultipath/debug.c -+++ b/libmultipath/debug.c -@@ -5,11 +5,9 @@ - #include - #include - --#if DAEMON - #include "log_pthread.h" - #include - #include --#endif - - #include "vector.h" - #include "config.h" -@@ -23,12 +21,11 @@ void dlog (int sink, int prio, const char * fmt, ...) - thres = (conf) ? conf->verbosity : 0; - - if (prio <= thres) { --#if DAEMON - if (!sink) { - time_t t = time(NULL); - struct tm *tb = localtime(&t); - char buff[16]; -- -+ - strftime(buff, sizeof(buff), "%b %d %H:%M:%S", tb); - buff[sizeof(buff)-1] = '\0'; - -@@ -37,9 +34,6 @@ void dlog (int sink, int prio, const char * fmt, ...) - } - else - log_safe(prio + 3, fmt, ap); --#else -- vfprintf(stdout, fmt, ap); --#endif - } - va_end(ap); - } -diff --git a/libmultipath/debug.h b/libmultipath/debug.h -index 082fff1..c6120c1 100644 ---- a/libmultipath/debug.h -+++ b/libmultipath/debug.h -@@ -1,21 +1,13 @@ - void dlog (int sink, int prio, const char * fmt, ...) - __attribute__((format(printf, 3, 4))); - --#if DAEMON - - #include - #include - - #include "log_pthread.h" - --int logsink; -+extern int logsink; - - #define condlog(prio, fmt, args...) \ - dlog(logsink, prio, fmt "\n", ##args) -- --#else /* DAEMON */ -- --#define condlog(prio, fmt, args...) \ -- dlog(0, prio, fmt "\n", ##args) -- --#endif /* DAEMON */ -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index df7d971..826f360 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -1,10 +1,10 @@ - #define DEFAULT_GETUID "/lib/udev/scsi_id -g -u -s /block/%n" - #define DEFAULT_UDEVDIR "/dev" -+#define DEFAULT_MULTIPATHDIR "/lib/multipath" - #define DEFAULT_SELECTOR "round-robin 0" - #define DEFAULT_FEATURES "0" - #define DEFAULT_HWHANDLER "0" - #define DEFAULT_MINIO 1000 --#define DEFAULT_GETPRIO NULL - #define DEFAULT_PGPOLICY FAILOVER - #define DEFAULT_FAILBACK -FAILBACK_MANUAL - #define DEFAULT_RR_WEIGHT RR_WEIGHT_NONE -@@ -15,7 +15,6 @@ - #define DEFAULT_CHECKINT 5 - #define MAX_CHECKINT(a) (a << 2) - --#define DEFAULT_TARGET "multipath" - #define DEFAULT_PIDFILE "/var/run/multipathd.pid" - #define DEFAULT_SOCKET "/var/run/multipathd.sock" - #define DEFAULT_CONFIGFILE "/etc/multipath.conf" -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index d6991ba..d329781 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -14,8 +14,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "structs.h" - #include "debug.h" -@@ -23,11 +22,9 @@ - #include "devmapper.h" - #include "config.h" - --#if DAEMON - #include "log_pthread.h" - #include - #include --#endif - - #define MAX_WAIT 5 - #define LOOPS_PER_SEC 5 -@@ -48,8 +45,7 @@ dm_write_log (int level, const char *file, int line, const char *f, ...) - if (thres <= 3 || level > thres) - return; - -- va_start(ap, f); --#if DAEMON -+ va_start(ap, f); - if (!logsink) { - time_t t = time(NULL); - struct tm *tb = localtime(&t); -@@ -66,12 +62,7 @@ dm_write_log (int level, const char *file, int line, const char *f, ...) - condlog(level, "libdevmapper: %s(%i): ", file, line); - log_safe(level + 3, f, ap); - } --#else -- fprintf(stdout, "libdevmapper: %s(%i): ", file, line); -- vfprintf(stdout, f, ap); -- fprintf(stdout, "\n"); --#endif -- va_end(ap); -+ va_end(ap); - - return; - } -@@ -151,11 +142,11 @@ out: - } - - extern int --dm_prereq (char * str) -+dm_prereq (void) - { - if (dm_libprereq()) - return 1; -- return dm_drvprereq(str); -+ return dm_drvprereq(TGT_MPATH); - } - - extern int -@@ -184,7 +175,8 @@ dm_simplecmd (int task, const char *name) { - - extern int - dm_addmap (int task, const char *name, const char *target, -- const char *params, unsigned long long size, const char *uuid) { -+ const char *params, unsigned long long size, const char *uuid, -+ int ro) { - int r = 0; - struct dm_task *dmt; - char *prefixed_uuid = NULL; -@@ -198,6 +190,9 @@ dm_addmap (int task, const char *name, const char *target, - if (!dm_task_add_target (dmt, 0, size, target, params)) - goto addout; - -+ if (ro) -+ dm_task_set_ro(dmt); -+ - if (uuid){ - prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1); - if (!prefixed_uuid) { -@@ -220,11 +215,59 @@ dm_addmap (int task, const char *name, const char *target, - - addout: - dm_task_destroy (dmt); -+ -+ return r; -+} -+ -+static int -+_dm_addmap_create (const char *name, const char *params, -+ unsigned long long size, const char *uuid, int ro) { -+ int r; -+ r = dm_addmap(DM_DEVICE_CREATE, name, TGT_MPATH, params, size, uuid, -+ ro); -+ /* -+ * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD. -+ * Failing the second part leaves an empty map. Clean it up. -+ */ -+ if (!r && dm_map_present(name)) { -+ condlog(3, "%s: failed to load map (a path might be in use)", -+ name); -+ dm_flush_map(name); -+ } - return r; - } - -+#define ADDMAP_RW 0 -+#define ADDMAP_RO 1 -+ -+extern int -+dm_addmap_create (const char *name, const char *params, -+ unsigned long long size, const char *uuid) { -+ return _dm_addmap_create(name, params, size, uuid, ADDMAP_RW); -+} -+ -+extern int -+dm_addmap_create_ro (const char *name, const char *params, -+ unsigned long long size, const char *uuid) { -+ return _dm_addmap_create(name, params, size, uuid, ADDMAP_RO); -+} -+ -+extern int -+dm_addmap_reload (const char *name, const char *params, -+ unsigned long long size, const char *uuid) { -+ return dm_addmap(DM_DEVICE_RELOAD, name, TGT_MPATH, params, size, uuid, -+ ADDMAP_RW); -+} -+ -+extern int -+dm_addmap_reload_ro (const char *name, const char *params, -+ unsigned long long size, const char *uuid) { -+ return dm_addmap(DM_DEVICE_RELOAD, name, TGT_MPATH, params, size, uuid, -+ ADDMAP_RO); -+} -+ - extern int --dm_map_present (char * str) -+dm_map_present (const char * str) - { - int r = 0; - struct dm_task *dmt; -@@ -361,7 +404,7 @@ out: - * -1 : empty map - */ - extern int --dm_type(char * name, char * type) -+dm_type(const char * name, char * type) - { - int r = 0; - struct dm_task *dmt; -@@ -396,7 +439,7 @@ out: - } - - static int --dm_dev_t (char * mapname, char * dev_t, int len) -+dm_dev_t (const char * mapname, char * dev_t, int len) - { - int r = 1; - struct dm_task *dmt; -@@ -425,7 +468,7 @@ out: - } - - int --dm_get_opencount (char * mapname) -+dm_get_opencount (const char * mapname) - { - int r = -1; - struct dm_task *dmt; -@@ -475,14 +518,14 @@ out: - } - - extern int --dm_flush_map (char * mapname, char * type) -+dm_flush_map (const char * mapname) - { - int r; - - if (!dm_map_present(mapname)) - return 0; - -- if (dm_type(mapname, type) <= 0) -+ if (dm_type(mapname, TGT_MPATH) <= 0) - return 1; - - if (dm_remove_partmaps(mapname)) -@@ -503,7 +546,7 @@ dm_flush_map (char * mapname, char * type) - } - - extern int --dm_flush_maps (char * type) -+dm_flush_maps (void) - { - int r = 0; - struct dm_task *dmt; -@@ -525,7 +568,7 @@ dm_flush_maps (char * type) - goto out; - - do { -- r += dm_flush_map(names->name, type); -+ r += dm_flush_map(names->name); - next = names->next; - names = (void *) names + next; - } while (next); -@@ -642,7 +685,7 @@ dm_disablegroup(char * mapname, int index) - } - - int --dm_get_maps (vector mp, char * type) -+dm_get_maps (vector mp) - { - struct multipath * mpp; - int r = 1; -@@ -651,7 +694,7 @@ dm_get_maps (vector mp, char * type) - struct dm_names *names; - unsigned next = 0; - -- if (!type || !mp) -+ if (!mp) - return 1; - - if (!(dmt = dm_task_create(DM_DEVICE_LIST))) -@@ -671,7 +714,7 @@ dm_get_maps (vector mp, char * type) - } - - do { -- info = dm_type(names->name, type); -+ info = dm_type(names->name, TGT_MPATH); - - if (info <= 0) - goto next; -@@ -717,7 +760,7 @@ out: - } - - extern int --dm_get_name(char *uuid, char *type, char *name) -+dm_get_name(char *uuid, char *name) - { - vector vec; - struct multipath *mpp; -@@ -728,7 +771,7 @@ dm_get_name(char *uuid, char *type, char *name) - if (!vec) - return 0; - -- if (dm_get_maps(vec, type)) { -+ if (dm_get_maps(vec)) { - vector_free(vec); - return 0; - } -@@ -827,7 +870,7 @@ bad: - } - - int --dm_remove_partmaps (char * mapname) -+dm_remove_partmaps (const char * mapname) - { - struct dm_task *dmt; - struct dm_names *names; -@@ -861,7 +904,7 @@ dm_remove_partmaps (char * mapname) - /* - * if devmap target is "linear" - */ -- (dm_type(names->name, "linear") > 0) && -+ (dm_type(names->name, TGT_PART) > 0) && - - /* - * and the multipath mapname and the part mapname start -@@ -984,7 +1027,7 @@ dm_rename_partmaps (char * old, char * new) - /* - * if devmap target is "linear" - */ -- (dm_type(names->name, "linear") > 0) && -+ (dm_type(names->name, TGT_PART) > 0) && - - /* - * and the multipath mapname and the part mapname start -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index 8438034..a340c00 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -1,14 +1,23 @@ -+#define TGT_MPATH "multipath" -+#define TGT_PART "linear" -+ - void dm_init(void); --int dm_prereq (char *); -+int dm_prereq (void); - int dm_simplecmd (int, const char *); --int dm_addmap (int, const char *, const char *, const char *, -- unsigned long long, const char *uuid); --int dm_map_present (char *); -+int dm_addmap_create (const char *, const char *, -+ unsigned long long size, const char *uuid); -+int dm_addmap_create_ro (const char *, const char *, -+ unsigned long long size, const char *uuid); -+int dm_addmap_reload (const char *, const char *, -+ unsigned long long size, const char *uuid); -+int dm_addmap_reload_ro (const char *, const char *, -+ unsigned long long size, const char *uuid); -+int dm_map_present (const char *); - int dm_get_map(char *, unsigned long long *, char *); - int dm_get_status(char *, char *); --int dm_type(char *, char *); --int dm_flush_map (char *, char *); --int dm_flush_maps (char *); -+int dm_type(const char *, char *); -+int dm_flush_map (const char *); -+int dm_flush_maps (void); - int dm_fail_path(char * mapname, char * path); - int dm_reinstate_path(char * mapname, char * path); - int dm_queue_if_no_path(char *mapname, int enable); -@@ -16,12 +25,12 @@ int dm_set_pg_timeout(char *mapname, int timeout_val); - int dm_switchgroup(char * mapname, int index); - int dm_enablegroup(char * mapname, int index); - int dm_disablegroup(char * mapname, int index); --int dm_get_maps (vector mp, char * type); -+int dm_get_maps (vector mp); - int dm_geteventnr (char *name); - int dm_get_minor (char *name); - char * dm_mapname(int major, int minor); --int dm_remove_partmaps (char * mapname); -+int dm_remove_partmaps (const char * mapname); - int dm_get_uuid(char *name, char *uuid); - int dm_get_info (char * mapname, struct dm_info ** dmi); - int dm_rename (char * old, char * new); --int dm_get_name(char * uuid, char * type, char * name); -+int dm_get_name(char * uuid, char * name); -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index 4572a7d..f5bca30 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -4,8 +4,7 @@ - * Copyright (c) 2005 Benjamin Marzinski, Redhat - * Copyright (c) 2005 Kiyoshi Ueda, NEC - */ --#include -- -+#include "checkers.h" - #include "vector.h" - #include "hwtable.h" - #include "structs.h" -@@ -16,6 +15,7 @@ - #include "pgpolicies.h" - #include "blacklist.h" - #include "defaults.h" -+#include "prio.h" - - /* - * default block handlers -@@ -44,6 +44,17 @@ udev_dir_handler(vector strvec) - } - - static int -+multipath_dir_handler(vector strvec) -+{ -+ conf->multipath_dir = set_value(strvec); -+ -+ if (!conf->multipath_dir) -+ return 1; -+ -+ return 0; -+} -+ -+static int - def_selector_handler(vector strvec) - { - conf->selector = set_value(strvec); -@@ -82,19 +93,13 @@ def_getuid_callout_handler(vector strvec) - } - - static int --def_prio_callout_handler(vector strvec) -+def_prio_handler(vector strvec) - { -- conf->getprio = set_value(strvec); -+ conf->prio_name = set_value(strvec); - -- if (!conf->getprio) -+ if (!conf->prio_name) - return 1; -- -- if (strlen(conf->getprio) == 4 && -- !strcmp(conf->getprio, "none")) { -- FREE(conf->getprio); -- conf->getprio = NULL; -- } -- -+ - return 0; - } - -@@ -112,21 +117,32 @@ def_features_handler(vector strvec) - static int - def_path_checker_handler(vector strvec) - { -+ conf->checker_name = set_value(strvec); -+ -+ if (!conf->checker_name) -+ return 1; -+ -+ return 0; -+} -+ -+static int -+def_minio_handler(vector strvec) -+{ - char * buff; - - buff = set_value(strvec); - - if (!buff) - return 1; -- -- conf->checker = checker_lookup(buff); -+ -+ conf->minio = atoi(buff); - FREE(buff); - - return 0; - } - - static int --def_minio_handler(vector strvec) -+max_fds_handler(vector strvec) - { - char * buff; - -@@ -135,7 +151,11 @@ def_minio_handler(vector strvec) - if (!buff) - return 1; - -- conf->minio = atoi(buff); -+ if (strlen(buff) == 9 && -+ !strcmp(buff, "unlimited")) -+ conf->max_fds = MAX_FDS_UNLIMITED; -+ else -+ conf->max_fds = atoi(buff); - FREE(buff); - - return 0; -@@ -398,7 +418,8 @@ ble_except_product_handler(vector strvec) - static int - devices_handler(vector strvec) - { -- conf->hwtable = vector_alloc(); -+ if (!conf->hwtable) -+ conf->hwtable = vector_alloc(); - - if (!conf->hwtable) - return 1; -@@ -521,20 +542,16 @@ hw_selector_handler(vector strvec) - static int - hw_path_checker_handler(vector strvec) - { -- char * buff; - struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); - - if (!hwe) - return 1; - -- buff = set_value(strvec); -+ hwe->checker_name = set_value(strvec); - -- if (!buff) -+ if (!hwe->checker_name) - return 1; - -- hwe->checker = checker_lookup(buff); -- FREE(buff); -- - return 0; - } - -@@ -571,23 +588,18 @@ hw_handler_handler(vector strvec) - } - - static int --prio_callout_handler(vector strvec) -+hw_prio_handler(vector strvec) - { - struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); -- -+ - if (!hwe) - return 1; - -- hwe->getprio = set_value(strvec); -+ hwe->prio_name = set_value(strvec); - -- if (!hwe->getprio) -+ if (!hwe->prio_name) - return 1; - -- if (strlen(hwe->getprio) == 4 && !strcmp(hwe->getprio, "none")) { -- FREE(hwe->getprio); -- hwe->getprio = NULL; -- } -- - return 0; - } - -@@ -1075,7 +1087,7 @@ snprint_hw_vendor (char * buff, int len, void * data) - if (!hwe->vendor) - return 0; - -- return snprintf(buff, len, "%s", hwe->vendor); -+ return snprintf(buff, len, "\"%s\"", hwe->vendor); - } - - static int -@@ -1086,7 +1098,7 @@ snprint_hw_product (char * buff, int len, void * data) - if (!hwe->product) - return 0; - -- return snprintf(buff, len, "%s", hwe->product); -+ return snprintf(buff, len, "\"%s\"", hwe->product); - } - - static int -@@ -1097,7 +1109,7 @@ snprint_hw_bl_product (char * buff, int len, void * data) - if (!hwe->bl_product) - return 0; - -- return snprintf(buff, len, "%s", hwe->bl_product); -+ return snprintf(buff, len, "\"%s\"", hwe->bl_product); - } - - static int -@@ -1111,27 +1123,20 @@ snprint_hw_getuid_callout (char * buff, int len, void * data) - !strcmp(hwe->getuid, conf->getuid)) - return 0; - -- return snprintf(buff, len, "%s", hwe->getuid); -+ return snprintf(buff, len, "\"%s\"", hwe->getuid); - } - - static int --snprint_hw_prio_callout (char * buff, int len, void * data) -+snprint_hw_prio (char * buff, int len, void * data) - { - struct hwentry * hwe = (struct hwentry *)data; - -- if (!conf->getprio && !hwe->getprio) -+ if (!hwe->prio_name) - return 0; -- if (!conf->getprio && hwe->getprio) -- return snprintf(buff, len, "%s", hwe->getprio); -- if (conf->getprio && !hwe->getprio) -- return snprintf(buff, len, "none"); -- -- /* conf->getprio && hwe->getprio */ -- if (strlen(hwe->getprio) == strlen(conf->getprio) && -- !strcmp(hwe->getprio, conf->getprio)) -+ if (!strcmp(hwe->prio_name, conf->prio_name)) - return 0; -- -- return snprintf(buff, len, "%s", hwe->getprio); -+ -+ return snprintf(buff, len, "%s", hwe->prio_name); - } - - static int -@@ -1145,7 +1150,7 @@ snprint_hw_features (char * buff, int len, void * data) - !strcmp(hwe->features, conf->features)) - return 0; - -- return snprintf(buff, len, "%s", hwe->features); -+ return snprintf(buff, len, "\"%s\"", hwe->features); - } - - static int -@@ -1159,7 +1164,7 @@ snprint_hw_hardware_handler (char * buff, int len, void * data) - !strcmp(hwe->hwhandler, conf->hwhandler)) - return 0; - -- return snprintf(buff, len, "%s", hwe->hwhandler); -+ return snprintf(buff, len, "\"%s\"", hwe->hwhandler); - } - - static int -@@ -1294,14 +1299,12 @@ snprint_hw_path_checker (char * buff, int len, void * data) - { - struct hwentry * hwe = (struct hwentry *)data; - -- if (!hwe->checker) -+ if (!hwe->checker_name) - return 0; -- if (!checker_selected(hwe->checker)) -- return 0; -- if (hwe->checker == conf->checker) -+ if (!strcmp(hwe->checker_name, conf->checker_name)) - return 0; - -- return snprintf(buff, len, "%s", checker_name(hwe->checker)); -+ return snprintf(buff, len, "%s", hwe->checker_name); - } - - static int -@@ -1321,7 +1324,19 @@ snprint_def_udev_dir (char * buff, int len, void * data) - !strcmp(conf->udev_dir, DEFAULT_UDEVDIR)) - return 0; - -- return snprintf(buff, len, "%s", conf->udev_dir); -+ return snprintf(buff, len, "\"%s\"", conf->udev_dir); -+} -+ -+static int -+snprint_def_multipath_dir (char * buff, int len, void * data) -+{ -+ if (!conf->udev_dir) -+ return 0; -+ if (strlen(DEFAULT_MULTIPATHDIR) == strlen(conf->multipath_dir) && -+ !strcmp(conf->multipath_dir, DEFAULT_MULTIPATHDIR)) -+ return 0; -+ -+ return snprintf(buff, len, "\"%s\"", conf->multipath_dir); - } - - static int -@@ -1360,16 +1375,20 @@ snprint_def_getuid_callout (char * buff, int len, void * data) - !strcmp(conf->getuid, DEFAULT_GETUID)) - return 0; - -- return snprintf(buff, len, "%s", conf->getuid); -+ return snprintf(buff, len, "\"%s\"", conf->getuid); - } - - static int --snprint_def_getprio_callout (char * buff, int len, void * data) -+snprint_def_prio (char * buff, int len, void * data) - { -- if (!conf->getprio) -+ if (!conf->prio_name) - return 0; - -- return snprintf(buff, len, "%s", conf->getprio); -+ if (strlen(conf->prio_name) == strlen(DEFAULT_PRIO) && -+ !strcmp(conf->prio_name, DEFAULT_PRIO)) -+ return 0; -+ -+ return snprintf(buff, len, "%s", conf->prio_name); - } - - static int -@@ -1381,18 +1400,19 @@ snprint_def_features (char * buff, int len, void * data) - !strcmp(conf->features, DEFAULT_FEATURES)) - return 0; - -- return snprintf(buff, len, "%s", conf->features); -+ return snprintf(buff, len, "\"%s\"", conf->features); - } - - static int - snprint_def_path_checker (char * buff, int len, void * data) - { -- if (!conf->checker) -+ if (!conf->checker_name) - return 0; -- if (conf->checker == checker_default()) -+ if (strlen(conf->checker_name) == strlen(DEFAULT_CHECKER) && -+ !strcmp(conf->checker_name, DEFAULT_CHECKER)) - return 0; - -- return snprintf(buff, len, "%s", checker_name(conf->checker)); -+ return snprintf(buff, len, "%s", conf->checker_name); - } - - static int -@@ -1428,6 +1448,17 @@ snprint_def_rr_min_io (char * buff, int len, void * data) - } - - static int -+snprint_max_fds (char * buff, int len, void * data) -+{ -+ if (!conf->max_fds) -+ return 0; -+ -+ if (conf->max_fds < 0) -+ return snprintf(buff, len, "unlimited"); -+ return snprintf(buff, len, "%d", conf->max_fds); -+} -+ -+static int - snprint_def_rr_weight (char * buff, int len, void * data) - { - if (!conf->rr_weight) -@@ -1493,7 +1524,7 @@ snprint_ble_simple (char * buff, int len, void * data) - { - struct blentry * ble = (struct blentry *)data; - -- return snprintf(buff, len, "%s", ble->str); -+ return snprintf(buff, len, "\"%s\"", ble->str); - } - - static int -@@ -1501,7 +1532,7 @@ snprint_bled_vendor (char * buff, int len, void * data) - { - struct blentry_device * bled = (struct blentry_device *)data; - -- return snprintf(buff, len, "%s", bled->vendor); -+ return snprintf(buff, len, "\"%s\"", bled->vendor); - } - - static int -@@ -1509,7 +1540,7 @@ snprint_bled_product (char * buff, int len, void * data) - { - struct blentry_device * bled = (struct blentry_device *)data; - -- return snprintf(buff, len, "%s", bled->product); -+ return snprintf(buff, len, "\"%s\"", bled->product); - } - - #define __deprecated -@@ -1520,14 +1551,17 @@ init_keywords(void) - install_keyword_root("defaults", NULL); - install_keyword("polling_interval", &polling_interval_handler, &snprint_def_polling_interval); - install_keyword("udev_dir", &udev_dir_handler, &snprint_def_udev_dir); -+ install_keyword("multipath_dir", &multipath_dir_handler, &snprint_def_multipath_dir); - install_keyword("selector", &def_selector_handler, &snprint_def_selector); - install_keyword("path_grouping_policy", &def_pgpolicy_handler, &snprint_def_path_grouping_policy); - install_keyword("getuid_callout", &def_getuid_callout_handler, &snprint_def_getuid_callout); -- install_keyword("prio_callout", &def_prio_callout_handler, &snprint_def_getprio_callout); -+ install_keyword("prio", &def_prio_handler, &snprint_def_prio); - install_keyword("features", &def_features_handler, &snprint_def_features); - install_keyword("path_checker", &def_path_checker_handler, &snprint_def_path_checker); -+ install_keyword("checker", &def_path_checker_handler, &snprint_def_path_checker); - install_keyword("failback", &default_failback_handler, &snprint_def_failback); - install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io); -+ install_keyword("max_fds", &max_fds_handler, &snprint_max_fds); - install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight); - install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry); - install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout); -@@ -1535,7 +1569,6 @@ init_keywords(void) - __deprecated install_keyword("default_selector", &def_selector_handler, NULL); - __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); - __deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL); -- __deprecated install_keyword("default_prio_callout", &def_prio_callout_handler, NULL); - __deprecated install_keyword("default_features", &def_features_handler, NULL); - __deprecated install_keyword("default_path_checker", &def_path_checker_handler, NULL); - -@@ -1577,9 +1610,10 @@ init_keywords(void) - install_keyword("getuid_callout", &hw_getuid_callout_handler, &snprint_hw_getuid_callout); - install_keyword("path_selector", &hw_selector_handler, &snprint_hw_selector); - install_keyword("path_checker", &hw_path_checker_handler, &snprint_hw_path_checker); -+ install_keyword("checker", &hw_path_checker_handler, &snprint_hw_path_checker); - install_keyword("features", &hw_features_handler, &snprint_hw_features); - install_keyword("hardware_handler", &hw_handler_handler, &snprint_hw_hardware_handler); -- install_keyword("prio_callout", &prio_callout_handler, &snprint_hw_prio_callout); -+ install_keyword("prio", &hw_prio_handler, &snprint_hw_prio); - install_keyword("failback", &hw_failback_handler, &snprint_hw_failback); - install_keyword("rr_weight", &hw_weight_handler, &snprint_hw_rr_weight); - install_keyword("no_path_retry", &hw_no_path_retry_handler, &snprint_hw_no_path_retry); -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index c842eb0..7baa9e7 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -11,8 +11,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "memory.h" - #include "util.h" -@@ -25,6 +24,7 @@ - #include "sg_include.h" - #include "sysfs.h" - #include "discovery.h" -+#include "prio.h" - - struct path * - store_pathinfo (vector pathvec, vector hwtable, char * devname, int flag) -@@ -133,9 +133,9 @@ sysfs_get_##fname (struct sysfs_device * dev, char * buff, size_t len) \ - attr = sysfs_attr_get_value(dev->devpath, #fname); \ - if (!attr) \ - return 1; \ --\ - if (strlcpy(buff, attr, len) != strlen(attr)) \ - return 2; \ -+ strchop(buff); \ - return 0; \ - } - -@@ -361,10 +361,13 @@ get_inq (char * vendor, char * product, char * rev, int fd) - if (0 == do_inq(fd, 0, 0, 0, buff, MX_ALLOC_LEN, 0)) { - memcpy(vendor, buff + 8, 8); - vendor[8] = '\0'; -+ strchop(vendor); - memcpy(product, buff + 16, 16); - product[16] = '\0'; -+ strchop(product); - memcpy(rev, buff + 32, 4); - rev[4] = '\0'; -+ strchop(rev); - return 0; - } - return 1; -@@ -546,6 +549,9 @@ sysfs_pathinfo(struct path * pp) - if (!parent) - parent = pp->sysdev; - -+ if (!strncmp(parent->kernel, "block",5)) -+ parent = sysfs_device_get_parent(parent); -+ - condlog(3, "%s: subsystem = %s", pp->dev, parent->subsystem); - - if (!strncmp(parent->subsystem, "scsi",4)) -@@ -617,8 +623,8 @@ get_state (struct path * pp) - } - pp->state = checker_check(c); - condlog(3, "%s: state = %i", pp->dev, pp->state); -- if (pp->state == PATH_DOWN) -- condlog(2, "%s: checker msg is \"%s\"", -+ if (pp->state == PATH_DOWN && strlen(checker_message(c))) -+ condlog(3, "%s: checker msg is \"%s\"", - pp->dev, checker_message(c)); - return 0; - } -@@ -626,27 +632,22 @@ get_state (struct path * pp) - static int - get_prio (struct path * pp) - { -- char buff[CALLOUT_MAX_SIZE]; -- char prio[16]; -+ if (!pp) -+ return 0; - -- if (!pp->getprio_selected) { -- select_getprio(pp); -- pp->getprio_selected = 1; -+ if (!pp->prio) { -+ select_prio(pp); -+ if (!pp->prio) -+ return 1; - } -- if (!pp->getprio) { -- pp->priority = PRIO_DEFAULT; -- } else if (apply_format(pp->getprio, &buff[0], pp)) { -- condlog(0, "error formatting prio callout command"); -- pp->priority = PRIO_UNDEF; -- return 1; -- } else if (execute_program(buff, prio, 16)) { -- condlog(0, "error calling out %s", buff); -+ pp->priority = prio_getprio(pp->prio, pp); -+ if (pp->priority < 0) { -+ condlog(3, "%s: %s prio error", pp->dev, prio_name(pp->prio)); - pp->priority = PRIO_UNDEF; - return 1; -- } else -- pp->priority = atoi(prio); -- -- condlog(3, "%s: prio = %u", pp->dev, pp->priority); -+ } -+ condlog(3, "%s: %s prio = %u", -+ pp->dev, prio_name(pp->prio), pp->priority); - return 0; - } - -@@ -662,7 +663,7 @@ get_uid (struct path * pp) - condlog(0, "error formatting uid callout command"); - memset(pp->wwid, 0, WWID_SIZE); - } else if (execute_program(buff, pp->wwid, WWID_SIZE)) { -- condlog(0, "error calling out %s", buff); -+ condlog(3, "error calling out %s", buff); - memset(pp->wwid, 0, WWID_SIZE); - return 1; - } -@@ -723,5 +724,6 @@ blank: - */ - memset(pp->wwid, 0, WWID_SIZE); - pp->state = PATH_DOWN; -+ - return 0; - } -diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c -index 631933d..bc3f231 100644 ---- a/libmultipath/dmparser.c -+++ b/libmultipath/dmparser.c -@@ -7,8 +7,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "memory.h" - #include "structs.h" -@@ -146,6 +145,8 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp) - FREE(word); - return 1; - } -+ setup_feature(mpp, word); -+ - FREE(word); - } - -@@ -183,11 +184,12 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp) - num_pg = atoi(word); - FREE(word); - -- if (num_pg > 0 && !mpp->pg) -+ if (num_pg > 0 && !mpp->pg) { - mpp->pg = vector_alloc(); -- -- if (!mpp->pg) -- return 1; -+ if (!mpp->pg) -+ return 1; -+ } -+ - /* - * first pg to try - */ -@@ -278,10 +280,9 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp) - - strncpy(pp->dev_t, word, BLK_DEV_SIZE); - --#ifndef DAEMON -- if (store_path(pathvec, pp)) -+ /* Only call this in multipath client mode */ -+ if (!mpp->waiter && store_path(pathvec, pp)) - goto out; --#endif - } - FREE(word); - -@@ -329,6 +330,7 @@ out1: - FREE(word); - out: - free_pgvec(mpp->pg, KEEP_PATHS); -+ mpp->pg = NULL; - return 1; - } - -@@ -398,6 +400,9 @@ disassemble_status (char * params, struct multipath * mpp) - num_pg = atoi(word); - FREE(word); - -+ if (num_pg == 0) -+ return 0; -+ - /* - * next pg to try - */ -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index ef761d7..0a94f10 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -1,12 +1,12 @@ - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "defaults.h" - #include "structs.h" - #include "config.h" - #include "pgpolicies.h" -+#include "prio.h" - - /* - * Tuning suggestions on these parameters should go to -@@ -27,7 +27,6 @@ static struct hwentry default_hw[] = { - .vendor = "APPLE*", - .product = "Xserve RAID ", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -37,6 +36,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = DEFAULT_CHECKER, -+ .prio_name = DEFAULT_PRIO, - }, - /* - * StorageWorks controller family -@@ -48,7 +48,6 @@ static struct hwentry default_hw[] = { - .vendor = "3PARdata", - .product = "VV", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -58,14 +57,14 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = DEFAULT_CHECKER, -+ .prio_name = DEFAULT_PRIO, - }, - { - .vendor = "DEC", - .product = "HSG80", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_hp_sw /dev/%n", - .features = "1 queue_if_no_path", -- .hwhandler = "1 hp_sw", -+ .hwhandler = "1 hp-sw", - .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = FAILBACK_UNDEF, -@@ -73,101 +72,117 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = HP_SW, -+ .prio_name = PRIO_HP_SW, - }, - { - .vendor = "HP", - .product = "A6189A", - .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, -+ .no_path_retry = 12, - .minio = DEFAULT_MINIO, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, - }, - { - /* MSA 1000/MSA1500 EVA 3000/5000 with old firmware */ - .vendor = "(COMPAQ|HP)", - .product = "(MSA|HSV)1.0.*", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_hp_sw /dev/%n", - .features = "1 queue_if_no_path", -- .hwhandler = "1 hp_sw", -+ .hwhandler = "1 hp-sw", - .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = FAILBACK_UNDEF, - .rr_weight = RR_WEIGHT_NONE, -- .no_path_retry = NO_PATH_RETRY_UNDEF, -+ .no_path_retry = 12, - .minio = DEFAULT_MINIO, - .checker_name = HP_SW, -+ .prio_name = PRIO_HP_SW, - }, - { - /* MSA 1000/1500 with new firmware */ - .vendor = "HP", - .product = "MSA VOLUME", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_alua /dev/%n", - .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, -+ .no_path_retry = 12, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = PRIO_ALUA, - }, - { -- /* EVA 3000/5000 with new firmware */ -+ .vendor = "HP", -+ .product = "MSA2000s*", -+ .getuid = "/sbin/cciss_id %n", -+ .features = DEFAULT_FEATURES, -+ .hwhandler = DEFAULT_HWHANDLER, -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = 12, -+ .minio = DEFAULT_MINIO, -+ .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, -+ }, -+ { -+ /* EVA 3000/5000 with new firmware, EVA 4000/6000/8000 */ - .vendor = "(COMPAQ|HP)", -- .product = "(MSA|HSV)1.1.*", -+ .product = "HSV1[01]1|HSV2[01]0|HSV300", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_alua /dev/%n", - .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, -+ .no_path_retry = 12, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = PRIO_ALUA, - }, - { -- /* EVA 4000/6000/8000 */ -+ /* HP MSA2000 product family */ - .vendor = "HP", -- .product = "HSV2.*", -+ .product = "MSA2[02]12*", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_alua /dev/%n", - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -- .pgpolicy = GROUP_BY_PRIO, -+ .pgpolicy = MULTIBUS, - .pgfailback = -FAILBACK_IMMEDIATE, - .rr_weight = RR_WEIGHT_NONE, -- .no_path_retry = NO_PATH_RETRY_UNDEF, -+ .no_path_retry = 12, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, - }, - { - /* HP Smart Array */ - .vendor = "HP", - .product = "LOGICAL VOLUME.*", - .getuid = "/lib/udev/scsi_id -n -g -u -s /block/%n", -- .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, -+ .no_path_retry = 12, - .minio = DEFAULT_MINIO, -- .checker_name = TUR, -+ .checker_name = CCISS_TUR, -+ .prio_name = DEFAULT_PRIO, - }, - /* - * DDN controller family -@@ -179,7 +194,6 @@ static struct hwentry default_hw[] = { - .vendor = "DDN", - .product = "SAN DataDirector", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -189,6 +203,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, - }, - /* - * EMC / Clariion controller family -@@ -200,7 +215,6 @@ static struct hwentry default_hw[] = { - .vendor = "EMC", - .product = "SYMMETRIX", - .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 -s /block/%n", -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -209,14 +223,14 @@ static struct hwentry default_hw[] = { - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, - }, - { - .vendor = "DGC", - .product = ".*", - .bl_product = "LUNZ", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_emc /dev/%n", - .features = "1 queue_if_no_path", - .hwhandler = "1 emc", - .selector = DEFAULT_SELECTOR, -@@ -226,6 +240,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = (300 / DEFAULT_CHECKINT), - .minio = DEFAULT_MINIO, - .checker_name = EMC_CLARIION, -+ .prio_name = PRIO_EMC, - }, - /* - * Fujitsu controller family -@@ -237,7 +252,6 @@ static struct hwentry default_hw[] = { - .vendor = "FSC", - .product = "CentricStor", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -246,7 +260,8 @@ static struct hwentry default_hw[] = { - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, - }, - /* - * Hitachi controller family -@@ -258,7 +273,6 @@ static struct hwentry default_hw[] = { - .vendor = "(HITACHI|HP)", - .product = "OPEN-.*", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -268,12 +282,12 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, - }, - { - .vendor = "HITACHI", - .product = "DF.*", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_hds_modular /dev/%n", - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -283,6 +297,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = PRIO_HDS, - }, - /* - * IBM controller family -@@ -294,7 +309,6 @@ static struct hwentry default_hw[] = { - .vendor = "IBM", - .product = "ProFibre 4000R", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -303,46 +317,94 @@ static struct hwentry default_hw[] = { - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, - }, - { -- /* IBM DS4100 / FAStT100 */ -+ /* IBM FAStT 1722-600 */ -+ .vendor = "IBM", -+ .product = "1722-600", -+ .getuid = DEFAULT_GETUID, -+ .features = "1 queue_if_no_path", -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = 300, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, -+ }, -+ { -+ /* IBM DS4400 / FAStT700 */ - .vendor = "IBM", - .product = "1742", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_rdac /dev/%n", - .features = DEFAULT_FEATURES, -- .hwhandler = DEFAULT_HWHANDLER, -+ .hwhandler = "1 rdac", - .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = -FAILBACK_IMMEDIATE, - .rr_weight = RR_WEIGHT_NONE, -- .no_path_retry = NO_PATH_RETRY_UNDEF, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, - .minio = DEFAULT_MINIO, -- .checker_name = TUR, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, -+ }, -+ { -+ /* IBM DS4700 */ -+ .vendor = "IBM", -+ .product = "1814", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, -+ }, -+ { -+ /* IBM DS4800 */ -+ .vendor = "IBM", -+ .product = "1815", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, - }, - { - /* IBM Netfinity Fibre Channel RAID Controller Unit */ - .vendor = "IBM", - .product = "3526", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_rdac /dev/%n", - .features = DEFAULT_FEATURES, -- .hwhandler = DEFAULT_HWHANDLER, -+ .hwhandler = "1 rdac", - .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = -FAILBACK_IMMEDIATE, - .rr_weight = RR_WEIGHT_NONE, -- .no_path_retry = NO_PATH_RETRY_UNDEF, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, - .minio = DEFAULT_MINIO, -- .checker_name = TUR, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, - }, - { - /* IBM DS4200 / FAStT200 */ - .vendor = "IBM", - .product = "3542", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -352,13 +414,13 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, - }, - { - /* IBM ESS F20 aka Shark */ - .vendor = "IBM", - .product = "2105(800|F20)", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -368,13 +430,13 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, - }, - { - /* IBM DS6000 */ - .vendor = "IBM", - .product = "1750500", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_alua /dev/%n", - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -384,13 +446,13 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = PRIO_ALUA, - }, - { - /* IBM DS8000 */ - .vendor = "IBM", - .product = "2107900", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -400,13 +462,13 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, - }, - { - /* IBM SAN Volume Controller */ - .vendor = "IBM", - .product = "2145", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_alua /dev/%n", - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -416,6 +478,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = PRIO_ALUA, - }, - { - /* IBM S/390 ECKD DASD */ -@@ -423,7 +486,6 @@ static struct hwentry default_hw[] = { - .product = "S/390 DASD ECKD", - .bl_product = "S/390.*", - .getuid = "/sbin/dasdinfo -u -b %n", -- .getprio = NULL, - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -433,8 +495,26 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, - }, -- /* -+ { -+ /* IBM S/390 FBA DASD */ -+ .vendor = "IBM", -+ .product = "S/390 DASD FBA", -+ .bl_product = "S/390.*", -+ .getuid = "/sbin/dasdinfo -u -b %n", -+ .features = "1 queue_if_no_path", -+ .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 = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, -+ }, -+ /* - * NETAPP controller family - * - * Maintainer : Dave Wysochanski -@@ -444,7 +524,6 @@ static struct hwentry default_hw[] = { - .vendor = "NETAPP", - .product = "LUN.*", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_netapp /dev/%n", - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -453,9 +532,10 @@ static struct hwentry default_hw[] = { - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = 128, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = PRIO_NETAPP, - }, -- /* -+ /* - * IBM NSeries (NETAPP) controller family - * - * Maintainer : Dave Wysochanski -@@ -465,7 +545,6 @@ static struct hwentry default_hw[] = { - .vendor = "IBM", - .product = "Nseries.*", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_netapp /dev/%n", - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -474,7 +553,8 @@ static struct hwentry default_hw[] = { - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = 128, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = PRIO_NETAPP, - }, - /* - * Pillar Data controller family -@@ -486,7 +566,6 @@ static struct hwentry default_hw[] = { - .vendor = "Pillar", - .product = "Axiom.*", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_alua %n", - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -496,6 +575,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = PRIO_ALUA, - }, - /* - * SGI arrays -@@ -507,7 +587,6 @@ static struct hwentry default_hw[] = { - .vendor = "SGI", - .product = "TP9[13]00", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -516,15 +595,15 @@ static struct hwentry default_hw[] = { - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, - }, - { - .vendor = "SGI", - .product = "TP9[45]00", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_rdac /dev/%n", - .features = DEFAULT_FEATURES, -- .hwhandler = DEFAULT_HWHANDLER, -+ .hwhandler = "1 rdac", - .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = -FAILBACK_IMMEDIATE, -@@ -532,14 +611,14 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_QUEUE, - .minio = DEFAULT_MINIO, - .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, - }, - { - .vendor = "SGI", - .product = "IS.*", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_rdac /dev/%n", - .features = DEFAULT_FEATURES, -- .hwhandler = DEFAULT_HWHANDLER, -+ .hwhandler = "1 rdac", - .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = -FAILBACK_IMMEDIATE, -@@ -547,6 +626,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_QUEUE, - .minio = DEFAULT_MINIO, - .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, - }, - /* - * STK arrays -@@ -558,9 +638,8 @@ static struct hwentry default_hw[] = { - .vendor = "STK", - .product = "OPENstorage D280", - .getuid = DEFAULT_GETUID, -- .getprio = "/sbin/mpath_prio_rdac /dev/%n", - .features = DEFAULT_FEATURES, -- .hwhandler = DEFAULT_HWHANDLER, -+ .hwhandler = "1 rdac", - .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = -FAILBACK_IMMEDIATE, -@@ -568,6 +647,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, - .checker_name = TUR, -+ .prio_name = PRIO_RDAC, - }, - /* - * SUN arrays -@@ -579,7 +659,6 @@ static struct hwentry default_hw[] = { - .vendor = "SUN", - .product = "(StorEdge 3510|T4)", - .getuid = DEFAULT_GETUID, -- .getprio = NULL, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -588,7 +667,60 @@ static struct hwentry default_hw[] = { - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = DEFAULT_MINIO, -- .checker_name = READSECTOR0, -+ .checker_name = DIRECTIO, -+ .prio_name = DEFAULT_PRIO, -+ }, -+ /* -+ * Pivot3 RAIGE -+ * -+ * Maintainer : Bart Brooks, Pivot3 -+ * Mail : bartb@pivot3.com -+ */ -+ { -+ .vendor = "PIVOT3", -+ .product = "RAIGE VOLUME", -+ .getuid = "/sbin/scsi_id -p 0x80 -g -u -s /block/%n", -+ .features = "1 queue_if_no_path", -+ .hwhandler = DEFAULT_HWHANDLER, -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = MULTIBUS, -+ .pgfailback = FAILBACK_UNDEF, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_UNDEF, -+ .minio = 100, -+ .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, -+ }, -+ { -+ .vendor = "SUN", -+ .product = "CSM200_R", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, -+ }, -+ /* SUN/LSI 2540 */ -+ { -+ .vendor = "SUN", -+ .product = "LCSM100_F", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_QUEUE, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, - }, - /* - * EOL -@@ -597,7 +729,6 @@ static struct hwentry default_hw[] = { - .vendor = NULL, - .product = NULL, - .getuid = NULL, -- .getprio = NULL, - .features = NULL, - .hwhandler = NULL, - .selector = NULL, -@@ -607,6 +738,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = 0, - .minio = 0, - .checker_name = NULL, -+ .prio_name = NULL, - }, - }; - -@@ -617,7 +749,6 @@ setup_default_hwtable (vector hw) - struct hwentry * hwe = default_hw; - - while (hwe->vendor) { -- hwe->checker = checker_lookup(hwe->checker_name); - r += store_hwe(hw, hwe); - hwe++; - } -diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c -index 5a82b6a..8909440 100644 ---- a/libmultipath/log_pthread.c -+++ b/libmultipath/log_pthread.c -@@ -15,9 +15,7 @@ - void log_safe (int prio, const char * fmt, va_list ap) - { - pthread_mutex_lock(logq_lock); -- //va_start(ap, fmt); - log_enqueue(prio, fmt, ap); -- va_end(ap); - pthread_mutex_unlock(logq_lock); - - pthread_mutex_lock(logev_lock); -@@ -33,7 +31,8 @@ static void flush_logqueue (void) - pthread_mutex_lock(logq_lock); - empty = log_dequeue(la->buff); - pthread_mutex_unlock(logq_lock); -- log_syslog(la->buff); -+ if (!empty) -+ log_syslog(la->buff); - } while (empty == 0); - } - -diff --git a/libmultipath/parser.c b/libmultipath/parser.c -index f9c555e..ad2bb4f 100644 ---- a/libmultipath/parser.c -+++ b/libmultipath/parser.c -@@ -203,7 +203,7 @@ alloc_strvec(char *string) - cp = string; - - /* Skip white spaces */ -- while (isspace((int) *cp) && *cp != '\0') -+ while ((isspace((int) *cp) || !isascii((int) *cp)) && *cp != '\0') - cp++; - - /* Return if there is only white spaces */ -@@ -241,8 +241,10 @@ alloc_strvec(char *string) - in_string = 1; - - } else { -- while ((in_string || !isspace((int) *cp)) && *cp -- != '\0' && *cp != '"') -+ while ((in_string || -+ (!isspace((int) *cp) && isascii((int) *cp) && -+ *cp != '!' && *cp != '#')) && -+ *cp != '\0' && *cp != '"') - cp++; - strlen = cp - start; - token = MALLOC(strlen + 1); -@@ -255,7 +257,8 @@ alloc_strvec(char *string) - } - vector_set_slot(strvec, token); - -- while (isspace((int) *cp) && *cp != '\0') -+ while ((isspace((int) *cp) || !isascii((int) *cp)) -+ && *cp != '\0') - cp++; - if (*cp == '\0' || *cp == '!' || *cp == '#') - return strvec; -diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c -index 0ac7448..2a9671a 100644 ---- a/libmultipath/pgpolicies.c -+++ b/libmultipath/pgpolicies.c -@@ -5,8 +5,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "util.h" - #include "memory.h" - #include "vector.h" -@@ -127,6 +126,7 @@ out1: - FREE(bitmap); - out: - free_pgvec(mp->pg, KEEP_PATHS); -+ mp->pg = NULL; - return 1; - } - -@@ -198,6 +198,7 @@ out1: - FREE(bitmap); - out: - free_pgvec(mp->pg, KEEP_PATHS); -+ mp->pg = NULL; - return 1; - } - -@@ -232,6 +233,7 @@ one_path_per_group (struct multipath * mp) - return 0; - out: - free_pgvec(mp->pg, KEEP_PATHS); -+ mp->pg = NULL; - return 1; - } - -@@ -264,6 +266,7 @@ one_group (struct multipath * mp) /* aka multibus */ - return 0; - out: - free_pgvec(mp->pg, KEEP_PATHS); -+ mp->pg = NULL; - return 1; - } - -@@ -338,6 +341,7 @@ group_by_prio (struct multipath * mp) - return 0; - out: - free_pgvec(mp->pg, KEEP_PATHS); -+ mp->pg = NULL; - return 1; - - } -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 01a157a..3be1c9d 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -8,8 +8,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "structs.h" - #include "structs_vec.h" -@@ -21,6 +20,8 @@ - #include "defaults.h" - #include "parser.h" - #include "blacklist.h" -+#include "switchgroup.h" -+#include "devmapper.h" - - #define MAX(x,y) (x > y) ? x : y - #define TAIL (line + len - 1 - c) -@@ -89,8 +90,19 @@ snprint_sysfs (char * buff, size_t len, struct multipath * mpp) - { - if (mpp->dmi) - return snprintf(buff, len, "dm-%i", mpp->dmi->minor); -+ else -+ return snprintf(buff, len, "n/a"); -+} - -- return 0; -+static int -+snprint_ro (char * buff, size_t len, struct multipath * mpp) -+{ -+ if (!mpp->dmi) -+ return snprintf(buff, len, "n/a"); -+ if (mpp->dmi->read_only) -+ return snprintf(buff, len, "ro"); -+ else -+ return snprintf(buff, len, "rw"); - } - - static int -@@ -221,6 +233,16 @@ snprint_multipath_uuid (char * buff, size_t len, struct multipath * mpp) - } - - static int -+snprint_multipath_vpr (char * buff, size_t len, struct multipath * mpp) -+{ -+ struct path * pp = first_path(mpp); -+ if (!pp) -+ return 0; -+ return snprintf(buff, len, "%s,%s", -+ pp->vendor_id, pp->product_id); -+} -+ -+static int - snprint_action (char * buff, size_t len, struct multipath * mpp) - { - switch (mpp->action) { -@@ -340,6 +362,13 @@ snprint_pg_selector (char * buff, size_t len, struct pathgroup * pgp) - static int - snprint_pg_pri (char * buff, size_t len, struct pathgroup * pgp) - { -+ /* -+ * path group priority is not updated for every path prio change, -+ * but only on switch group code path. -+ * -+ * Printing is another reason to update. -+ */ -+ path_group_prio_update(pgp); - return snprint_int(buff, len, pgp->priority); - } - -@@ -371,6 +400,7 @@ struct multipath_data mpd[] = { - {'F', "failback", 0, snprint_failback}, - {'Q', "queueing", 0, snprint_queueing}, - {'N', "paths", 0, snprint_nb_paths}, -+ {'r', "write_prot", 0, snprint_ro}, - {'t', "dm-st", 0, snprint_dm_map_state}, - {'S', "size", 0, snprint_multipath_size}, - {'f', "features", 0, snprint_features}, -@@ -381,6 +411,7 @@ struct multipath_data mpd[] = { - {'2', "map_loads", 0, snprint_map_loads}, - {'3', "total_q_time", 0, snprint_total_q_time}, - {'4', "q_timeouts", 0, snprint_q_timeouts}, -+ {'s', "vend/prod/rev", 0, snprint_multipath_vpr}, - {0, NULL, 0 , NULL} - }; - -@@ -405,14 +436,17 @@ struct pathgroup_data pgd[] = { - }; - - void --get_path_layout (vector pathvec) -+get_path_layout (vector pathvec, int header) - { - int i, j; - char buff[MAX_FIELD_LEN]; - struct path * pp; - - for (j = 0; pd[j].header; j++) { -- pd[j].width = strlen(pd[j].header); -+ if (header) -+ pd[j].width = strlen(pd[j].header); -+ else -+ pd[j].width = 0; - - vector_foreach_slot (pathvec, pp, i) { - pd[j].snprint(buff, MAX_FIELD_LEN, pp); -@@ -422,14 +456,17 @@ get_path_layout (vector pathvec) - } - - void --get_multipath_layout (vector mpvec) -+get_multipath_layout (vector mpvec, int header) - { - int i, j; - char buff[MAX_FIELD_LEN]; - struct multipath * mpp; - - for (j = 0; mpd[j].header; j++) { -- mpd[j].width = strlen(mpd[j].header); -+ if (header) -+ mpd[j].width = strlen(mpd[j].header); -+ else -+ mpd[j].width = 0; - - vector_foreach_slot (mpvec, mpp, i) { - mpd[j].snprint(buff, MAX_FIELD_LEN, mpp); -@@ -683,16 +720,15 @@ snprint_multipath_topology (char * buff, int len, struct multipath * mpp, - 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)); -+ c += sprintf(c, " %%d %%s"); - - fwd += snprint_multipath(buff + fwd, len - fwd, style, mpp); - if (fwd > len) - return len; - fwd += snprint_multipath(buff + fwd, len - fwd, -- "[size=%S][features=%f][hwhandler=%h]", mpp); -+ "[size=%S][features=%f][hwhandler=%h][%r]", mpp); - if (fwd > len) - return len; - -@@ -1118,15 +1154,16 @@ snprint_devices (char * buff, int len, struct vectors *vecs) - return len; - fwd += snprintf(buff + fwd, len - fwd, "available block devices:\n"); - -- strcpy(devpath,"/sys/block"); -- devptr = devpath + 10; -+ strcpy(devpath,"/sys/block/"); - while ((blkdev = readdir(blkdir)) != NULL) { - if ((strcmp(blkdev->d_name,".") == 0) || - (strcmp(blkdev->d_name,"..") == 0)) - continue; - -- strcat(devptr,blkdev->d_name); -- if (stat(devptr, &statbuf) < 0) -+ devptr = devpath + 11; -+ *devptr = '\0'; -+ strncat(devptr, blkdev->d_name, PATH_MAX-12); -+ if (stat(devpath, &statbuf) < 0) - continue; - - if (S_ISDIR(statbuf.st_mode) == 0) -@@ -1135,18 +1172,20 @@ snprint_devices (char * buff, int len, struct vectors *vecs) - if ((len - fwd - threshold) <= 0) - return len; - -- fwd += snprintf(buff + fwd, len - fwd, " %s", devpath); -- pp = find_path_by_dev(vecs->pathvec, devpath); -+ fwd += snprintf(buff + fwd, len - fwd, " %s", devptr); -+ pp = find_path_by_dev(vecs->pathvec, devptr); - if (!pp) { - r = filter_devnode(conf->blist_devnode, -- conf->elist_devnode, devpath); -+ conf->elist_devnode, devptr); - if (r > 0) - fwd += snprintf(buff + fwd, len - fwd, -- " (blacklisted)"); -+ " devnode blacklisted, unmonitored"); - else if (r < 0) - fwd += snprintf(buff + fwd, len - fwd, -- " (whitelisted)"); -- } -+ " devnode whitelisted, unmonitored"); -+ } else -+ fwd += snprintf(buff + fwd, len - fwd, -+ " devnode whitelisted, monitored"); - fwd += snprintf(buff + fwd, len - fwd, "\n"); - } - closedir(blkdir); -@@ -1197,13 +1236,19 @@ print_map (struct multipath * mpp) - { - if (mpp->size && mpp->params) - printf("0 %llu %s %s\n", -- mpp->size, DEFAULT_TARGET, mpp->params); -+ mpp->size, TGT_MPATH, mpp->params); - return; - } - - extern void - print_all_paths (vector pathvec, int banner) - { -+ print_all_paths_custo(pathvec, banner, PRINT_PATH_LONG); -+} -+ -+extern void -+print_all_paths_custo (vector pathvec, int banner, char *fmt) -+{ - int i; - struct path * pp; - char line[MAX_LINE_LEN]; -@@ -1217,11 +1262,11 @@ print_all_paths (vector pathvec, int banner) - if (banner) - fprintf(stdout, "===== paths list =====\n"); - -- get_path_layout(pathvec); -- snprint_path_header(line, MAX_LINE_LEN, PRINT_PATH_LONG); -+ get_path_layout(pathvec, 1); -+ snprint_path_header(line, MAX_LINE_LEN, fmt); - fprintf(stdout, "%s", line); - - vector_foreach_slot (pathvec, pp, i) -- print_path(pp, PRINT_PATH_LONG); -+ print_path(pp, fmt); - } - -diff --git a/libmultipath/print.h b/libmultipath/print.h -index 73c2f63..5c7023c 100644 ---- a/libmultipath/print.h -+++ b/libmultipath/print.h -@@ -1,7 +1,7 @@ - #define PRINT_PATH_LONG "%w %i %d %D %p %t%T %s" - #define PRINT_PATH_INDENT " \\_ %i %d %D %t%T" - #define PRINT_PATH_CHECKER "%i %d %D %p %t%T %C" --#define PRINT_MAP_STATUS "%n %F %Q %N %t" -+#define PRINT_MAP_STATUS "%n %F %Q %N %t %r" - #define PRINT_MAP_STATS "%n %0 %1 %2 %3 %4" - #define PRINT_MAP_NAMES "%n %d %w" - #define PRINT_PG_INDENT "\\_ %s [prio=%p]%t" -@@ -32,8 +32,8 @@ struct pathgroup_data { - int (*snprint)(char * buff, size_t len, struct pathgroup * pgp); - }; - --void get_path_layout (vector pathvec); --void get_multipath_layout (vector mpvec); -+void get_path_layout (vector pathvec, int header); -+void get_multipath_layout (vector mpvec, int header); - int snprint_path_header (char *, int, char *); - int snprint_multipath_header (char *, int, char *); - int snprint_path (char *, int, char *, struct path *); -@@ -54,5 +54,6 @@ void print_multipath (struct multipath * mpp, char * style); - void print_pathgroup (struct pathgroup * pgp, char * style); - void print_map (struct multipath * mpp); - void print_all_paths (vector pathvec, int banner); -+void print_all_paths_custo (vector pathvec, int banner, char *fmt); - void print_hwtable (vector hwtable); - -diff --git a/libmultipath/prio.c b/libmultipath/prio.c -new file mode 100644 -index 0000000..c9d2873 ---- /dev/null -+++ b/libmultipath/prio.c -@@ -0,0 +1,93 @@ -+#include -+#include -+#include -+#include -+ -+#include "debug.h" -+#include "prio.h" -+#include "config.h" -+ -+static LIST_HEAD(prioritizers); -+ -+int init_prio (void) -+{ -+ INIT_LIST_HEAD(&prioritizers); -+ if (!add_prio(DEFAULT_PRIO)) -+ return 1; -+ return 0; -+} -+ -+struct prio * alloc_prio (void) -+{ -+ return zalloc(sizeof(struct prio)); -+} -+ -+void free_prio (struct prio * p) -+{ -+ free(p); -+} -+ -+void cleanup_prio(void) -+{ -+ struct prio * prio_loop; -+ struct prio * prio_temp; -+ -+ list_for_each_entry_safe(prio_loop, prio_temp, &prioritizers, node) { -+ list_del(&prio_loop->node); -+ free(prio_loop); -+ } -+} -+ -+struct prio * prio_lookup (char * name) -+{ -+ struct prio * p; -+ -+ list_for_each_entry(p, &prioritizers, node) { -+ if (!strncmp(name, p->name, PRIO_NAME_LEN)) -+ return p; -+ } -+ return add_prio(name); -+} -+ -+struct prio * add_prio (char * name) -+{ -+ char libname[LIB_PRIO_NAMELEN]; -+ void * handle; -+ struct prio * p; -+ char *errstr; -+ -+ p = alloc_prio(); -+ if (!p) -+ return NULL; -+ snprintf(libname, LIB_PRIO_NAMELEN, "%s/libprio%s.so", -+ conf->multipath_dir, name); -+ condlog(3, "loading %s prioritizer", libname); -+ handle = dlopen(libname, RTLD_NOW); -+ errstr = dlerror(); -+ if (errstr != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!handle) -+ goto out; -+ p->getprio = (int (*)(struct path *)) dlsym(handle, "getprio"); -+ errstr = dlerror(); -+ if (errstr != NULL) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!p->getprio) -+ goto out; -+ snprintf(p->name, PRIO_NAME_LEN, "%s", name); -+ list_add(&p->node, &prioritizers); -+ return p; -+out: -+ free_prio(p); -+ return NULL; -+} -+ -+int prio_getprio (struct prio * p, struct path * pp) -+{ -+ return p->getprio(pp); -+} -+ -+char * prio_name (struct prio * p) -+{ -+ return p->name; -+} -diff --git a/libmultipath/prio.h b/libmultipath/prio.h -new file mode 100644 -index 0000000..491e6fc ---- /dev/null -+++ b/libmultipath/prio.h -@@ -0,0 +1,50 @@ -+#ifndef _PRIO_H -+#define _PRIO_H -+ -+/* -+ * knowing about path struct gives flexibility to prioritizers -+ */ -+#include "checkers.h" -+#include "vector.h" -+#include "structs.h" -+#include "list.h" -+#include "memory.h" -+ -+#define DEFAULT_PRIO "const" -+ -+/* -+ * Known prioritizers for use in hwtable.c -+ */ -+#define PRIO_ALUA "alua" -+#define PRIO_CONST "const" -+#define PRIO_EMC "emc" -+#define PRIO_HDS "hds" -+#define PRIO_HP_SW "hp_sw" -+#define PRIO_NETAPP "netapp" -+#define PRIO_RANDOM "random" -+#define PRIO_RDAC "rdac" -+ -+/* -+ * Value used to mark the fact prio was not defined -+ */ -+#define PRIO_UNDEF -1 -+ -+/* -+ * strings lengths -+ */ -+#define LIB_PRIO_NAMELEN 255 -+#define PRIO_NAME_LEN 16 -+ -+struct prio { -+ struct list_head node; -+ char name[PRIO_NAME_LEN]; -+ int (*getprio)(struct path *); -+}; -+ -+int init_prio (void); -+struct prio * add_prio (char *); -+struct prio * prio_lookup (char *); -+int prio_getprio (struct prio *, struct path *); -+char * prio_name (struct prio *); -+ -+#endif /* _PRIO_H */ -diff --git a/libmultipath/prioritizers/Makefile b/libmultipath/prioritizers/Makefile -new file mode 100644 -index 0000000..1f70ef1 ---- /dev/null -+++ b/libmultipath/prioritizers/Makefile -@@ -0,0 +1,34 @@ -+# Makefile -+# -+# Copyright (C) 2007 Christophe Varoqui, -+# -+include ../../Makefile.inc -+ -+LIBS = \ -+ libpriorandom.so \ -+ libprioconst.so \ -+ libpriohp_sw.so \ -+ libprioemc.so \ -+ libpriordac.so \ -+ libprioalua.so \ -+ libprionetapp.so \ -+ libpriohds.so -+ -+CFLAGS += -I.. -+ -+all: $(LIBS) -+ -+libprioalua.so: alua.o alua_rtpg.o -+ $(CC) $(SHARED_FLAGS) -o $@ $^ -+ -+libprio%.so: %.o -+ $(CC) $(SHARED_FLAGS) -o $@ $^ -+ -+install: $(LIBS) -+ $(INSTALL_PROGRAM) -m 755 libprio*.so $(DESTDIR)$(libdir) -+ -+uninstall: -+ rm -f $(DESTDIR)$(libdir)/libprio*.so -+ -+clean: -+ rm -f core *.a *.o *.gz *.so -diff --git a/libmultipath/prioritizers/alua.c b/libmultipath/prioritizers/alua.c -new file mode 100644 -index 0000000..1b52b8e ---- /dev/null -+++ b/libmultipath/prioritizers/alua.c -@@ -0,0 +1,95 @@ -+/* -+ * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -+ * -+ * main.c -+ * -+ * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -+ * It determines the ALUA state of a device and prints a priority value to -+ * stdout. -+ * -+ * Author(s): Jan Kunigk -+ * S. Bader -+ * -+ * This file is released under the GPL. -+ */ -+#include -+ -+#include -+#include -+ -+#include "alua.h" -+ -+#define ALUA_PRIO_NOT_SUPPORTED 1 -+#define ALUA_PRIO_RTPG_FAILED 2 -+#define ALUA_PRIO_GETAAS_FAILED 3 -+#define ALUA_PRIO_TPGS_FAILED 4 -+ -+int -+get_alua_info(int fd) -+{ -+ char * aas_string[] = { -+ [AAS_OPTIMIZED] = "active/optimized", -+ [AAS_NON_OPTIMIZED] = "active/non-optimized", -+ [AAS_STANDBY] = "standby", -+ [AAS_UNAVAILABLE] = "unavailable", -+ [AAS_TRANSITIONING] = "transitioning between states", -+ }; -+ int rc; -+ int tpg; -+ -+ rc = get_target_port_group_support(fd); -+ if (rc < 0) -+ return -ALUA_PRIO_TPGS_FAILED; -+ -+ if (rc == TPGS_NONE) -+ return -ALUA_PRIO_NOT_SUPPORTED; -+ -+ tpg = get_target_port_group(fd); -+ if (tpg < 0) -+ return -ALUA_PRIO_RTPG_FAILED; -+ -+ condlog(3, "reported target port group is %i", tpg); -+ rc = get_asymmetric_access_state(fd, tpg); -+ if (rc < 0) -+ return -ALUA_PRIO_GETAAS_FAILED; -+ -+ condlog(3, "aas = [%s]", -+ (aas_string[rc]) ? aas_string[rc] : "invalid/reserved"); -+ return rc; -+} -+ -+int getprio (struct path * pp) -+{ -+ int rc = get_alua_info(pp->fd); -+ if (rc >= 0) { -+ switch(rc) { -+ case AAS_OPTIMIZED: -+ rc = 50; -+ break; -+ case AAS_NON_OPTIMIZED: -+ rc = 10; -+ break; -+ case AAS_STANDBY: -+ rc = 1; -+ break; -+ default: -+ rc = 0; -+ } -+ } else { -+ switch(-rc) { -+ case ALUA_PRIO_NOT_SUPPORTED: -+ condlog(0, "%s: alua not supported", pp->dev); -+ break; -+ case ALUA_PRIO_RTPG_FAILED: -+ condlog(0, "%s: couldn't get target port group", pp->dev); -+ break; -+ case ALUA_PRIO_GETAAS_FAILED: -+ condlog(0, "%s: couln't get asymmetric access state", pp->dev); -+ break; -+ case ALUA_PRIO_TPGS_FAILED: -+ condlog(3, "%s: couln't get supported alua states", pp->dev); -+ break; -+ } -+ } -+ return rc; -+} -diff --git a/libmultipath/prioritizers/alua.h b/libmultipath/prioritizers/alua.h -new file mode 100644 -index 0000000..78a3d15 ---- /dev/null -+++ b/libmultipath/prioritizers/alua.h -@@ -0,0 +1,9 @@ -+#ifndef _ALUA_H -+#define _ALUA_H -+ -+#include "alua_rtpg.h" -+ -+#define PRIO_ALUA "alua" -+int prio_alua(struct path * pp); -+ -+#endif -diff --git a/libmultipath/prioritizers/alua_rtpg.c b/libmultipath/prioritizers/alua_rtpg.c -new file mode 100644 -index 0000000..c5528c5 ---- /dev/null -+++ b/libmultipath/prioritizers/alua_rtpg.c -@@ -0,0 +1,301 @@ -+/* -+ * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -+ * -+ * rtpg.c -+ * -+ * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -+ * It determines the ALUA state of a device and prints a priority value to -+ * stdout. -+ * -+ * Author(s): Jan Kunigk -+ * S. Bader -+ * -+ * This file is released under the GPL. -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#define __user -+#include -+ -+#include "alua_rtpg.h" -+ -+#define SENSE_BUFF_LEN 32 -+#define DEF_TIMEOUT 300000 -+ -+/* -+ * Macro used to print debug messaged. -+ */ -+#if DEBUG > 0 -+#define PRINT_DEBUG(f, a...) \ -+ fprintf(stderr, "DEBUG: " f, ##a) -+#else -+#define PRINT_DEBUG(f, a...) -+#endif -+ -+/* -+ * Optionally print the commands sent and the data received a hex dump. -+ */ -+#if DEBUG > 0 -+#if DEBUG_DUMPHEX > 0 -+#define PRINT_HEX(p, l) print_hex(p, l) -+void -+print_hex(unsigned char *p, unsigned long len) -+{ -+ int i; -+ -+ for(i = 0; i < len; i++) { -+ if (i % 16 == 0) -+ printf("%04x: ", i); -+ printf("%02x%s", p[i], (((i + 1) % 16) == 0) ? "\n" : " "); -+ } -+ printf("\n"); -+} -+#else -+#define PRINT_HEX(p, l) -+#endif -+#else -+#define PRINT_HEX(p, l) -+#endif -+ -+/* -+ * Returns 0 if the SCSI command either was successful or if the an error was -+ * recovered, otherwise 1. (definitions taken from sg_err.h) -+ */ -+#define SCSI_CHECK_CONDITION 0x2 -+#define SCSI_COMMAND_TERMINATED 0x22 -+#define SG_ERR_DRIVER_SENSE 0x08 -+#define RECOVERED_ERROR 0x01 -+ -+static int -+scsi_error(struct sg_io_hdr *hdr) -+{ -+ /* Treat SG_ERR here to get rid of sg_err.[ch] */ -+ hdr->status &= 0x7e; -+ -+ if ( -+ (hdr->status == 0) && -+ (hdr->host_status == 0) && -+ (hdr->driver_status == 0) -+ ) { -+ return 0; -+ } -+ -+ if ( -+ (hdr->status == SCSI_CHECK_CONDITION) || -+ (hdr->status == SCSI_COMMAND_TERMINATED) || -+ ((hdr->driver_status & 0xf) == SG_ERR_DRIVER_SENSE) -+ ) { -+ if (hdr->sbp && (hdr->sb_len_wr > 2)) { -+ int sense_key; -+ unsigned char * sense_buffer = hdr->sbp; -+ -+ if (sense_buffer[0] & 0x2) -+ sense_key = sense_buffer[1] & 0xf; -+ else -+ sense_key = sense_buffer[2] & 0xf; -+ -+ if (sense_key == RECOVERED_ERROR) -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ -+/* -+ * Helper function to setup and run a SCSI inquiry command. -+ */ -+int -+do_inquiry(int fd, int evpd, unsigned int codepage, void *resp, int resplen) -+{ -+ struct inquiry_command cmd; -+ struct sg_io_hdr hdr; -+ unsigned char sense[SENSE_BUFF_LEN]; -+ -+ memset(&cmd, 0, sizeof(cmd)); -+ cmd.op = OPERATION_CODE_INQUIRY; -+ if (evpd) { -+ inquiry_command_set_evpd(&cmd); -+ cmd.page = codepage; -+ } -+ set_uint16(cmd.length, resplen); -+ PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); -+ -+ memset(&hdr, 0, sizeof(hdr)); -+ hdr.interface_id = 'S'; -+ hdr.cmdp = (unsigned char *) &cmd; -+ hdr.cmd_len = sizeof(cmd); -+ hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ hdr.dxferp = resp; -+ hdr.dxfer_len = resplen; -+ hdr.sbp = sense; -+ hdr.mx_sb_len = sizeof(sense); -+ hdr.timeout = DEF_TIMEOUT; -+ -+ if (ioctl(fd, SG_IO, &hdr) < 0) { -+ PRINT_DEBUG("do_inquiry: IOCTL failed!\n"); -+ return -RTPG_INQUIRY_FAILED; -+ } -+ -+ if (scsi_error(&hdr)) { -+ PRINT_DEBUG("do_inquiry: SCSI error!\n"); -+ return -RTPG_INQUIRY_FAILED; -+ } -+ PRINT_HEX((unsigned char *) resp, resplen); -+ -+ return 0; -+} -+ -+/* -+ * This function returns the support for target port groups by evaluating the -+ * data returned by the standard inquiry command. -+ */ -+int -+get_target_port_group_support(int fd) -+{ -+ struct inquiry_data inq; -+ int rc; -+ -+ rc = do_inquiry(fd, 0, 0x00, &inq, sizeof(inq)); -+ if (!rc) { -+ rc = inquiry_data_get_tpgs(&inq); -+ } -+ -+ return rc; -+} -+ -+int -+get_target_port_group(int fd) -+{ -+ unsigned char buf[128]; -+ struct vpd83_data * vpd83; -+ struct vpd83_dscr * dscr; -+ int rc; -+ -+ rc = do_inquiry(fd, 1, 0x83, buf, sizeof(buf)); -+ if (!rc) { -+ vpd83 = (struct vpd83_data *) buf; -+ -+ rc = -RTPG_NO_TPG_IDENTIFIER; -+ FOR_EACH_VPD83_DSCR(vpd83, dscr) { -+ if ((((char *) dscr) - ((char *) vpd83)) > sizeof(buf)) -+ break; -+ -+ if (vpd83_dscr_istype(dscr, IDTYPE_TARGET_PORT_GROUP)) { -+ struct vpd83_tpg_dscr * p; -+ -+ if (rc != -RTPG_NO_TPG_IDENTIFIER) { -+ PRINT_DEBUG("get_target_port_group: " -+ "more than one TPG identifier " -+ "found!\n"); -+ continue; -+ } -+ -+ p = (struct vpd83_tpg_dscr *) dscr->data; -+ rc = get_uint16(p->tpg); -+ } -+ } -+ if (rc == -RTPG_NO_TPG_IDENTIFIER) { -+ PRINT_DEBUG("get_target_port_group: " -+ "no TPG identifier found!\n"); -+ } -+ } -+ -+ return rc; -+} -+ -+int -+do_rtpg(int fd, void* resp, long resplen) -+{ -+ struct rtpg_command cmd; -+ struct sg_io_hdr hdr; -+ unsigned char sense[SENSE_BUFF_LEN]; -+ -+ memset(&cmd, 0, sizeof(cmd)); -+ cmd.op = OPERATION_CODE_RTPG; -+ rtpg_command_set_service_action(&cmd); -+ set_uint32(cmd.length, resplen); -+ PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); -+ -+ memset(&hdr, 0, sizeof(hdr)); -+ hdr.interface_id = 'S'; -+ hdr.cmdp = (unsigned char *) &cmd; -+ hdr.cmd_len = sizeof(cmd); -+ hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ hdr.dxferp = resp; -+ hdr.dxfer_len = resplen; -+ hdr.mx_sb_len = sizeof(sense); -+ hdr.sbp = sense; -+ hdr.timeout = DEF_TIMEOUT; -+ -+ if (ioctl(fd, SG_IO, &hdr) < 0) -+ return -RTPG_RTPG_FAILED; -+ -+ if (scsi_error(&hdr)) { -+ PRINT_DEBUG("do_rtpg: SCSI error!\n"); -+ return -RTPG_RTPG_FAILED; -+ } -+ PRINT_HEX(resp, resplen); -+ -+ return 0; -+} -+ -+int -+get_asymmetric_access_state(int fd, unsigned int tpg) -+{ -+ unsigned char *buf; -+ struct rtpg_data * tpgd; -+ struct rtpg_tpg_dscr * dscr; -+ int rc; -+ int buflen; -+ uint32_t scsi_buflen; -+ -+ buflen = 128; /* Initial value from old code */ -+ buf = (unsigned char *)malloc(buflen); -+ if (!buf) { -+ PRINT_DEBUG ("malloc failed: could not allocate" -+ "%u bytes\n", buflen); -+ return -RTPG_RTPG_FAILED; -+ } -+ rc = do_rtpg(fd, buf, buflen); -+ if (rc < 0) -+ return rc; -+ scsi_buflen = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -+ if (buflen < (scsi_buflen + 4)) { -+ free(buf); -+ buf = (unsigned char *)malloc(scsi_buflen); -+ if (!buf) { -+ PRINT_DEBUG ("malloc failed: could not allocate" -+ "%u bytes\n", scsi_buflen); -+ return -RTPG_RTPG_FAILED; -+ } -+ buflen = scsi_buflen; -+ rc = do_rtpg(fd, buf, buflen); -+ if (rc < 0) -+ goto out; -+ } -+ -+ -+ tpgd = (struct rtpg_data *) buf; -+ rc = -RTPG_TPG_NOT_FOUND; -+ RTPG_FOR_EACH_PORT_GROUP(tpgd, dscr) { -+ if (get_uint16(dscr->tpg) == tpg) { -+ if (rc != -RTPG_TPG_NOT_FOUND) { -+ PRINT_DEBUG("get_asymmetric_access_state: " -+ "more than one entry with same port " -+ "group.\n"); -+ } else { -+ PRINT_DEBUG("pref=%i\n", dscr->pref); -+ rc = rtpg_tpg_dscr_get_aas(dscr); -+ } -+ } -+ } -+out: -+ free(buf); -+ return rc; -+} -+ -diff --git a/libmultipath/prioritizers/alua_rtpg.h b/libmultipath/prioritizers/alua_rtpg.h -new file mode 100644 -index 0000000..c43e0a9 ---- /dev/null -+++ b/libmultipath/prioritizers/alua_rtpg.h -@@ -0,0 +1,30 @@ -+/* -+ * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -+ * -+ * rtpg.h -+ * -+ * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -+ * It determines the ALUA state of a device and prints a priority value to -+ * stdout. -+ * -+ * Author(s): Jan Kunigk -+ * S. Bader -+ * -+ * This file is released under the GPL. -+ */ -+#ifndef __RTPG_H__ -+#define __RTPG_H__ -+#include "alua_spc3.h" -+ -+#define RTPG_SUCCESS 0 -+#define RTPG_INQUIRY_FAILED 1 -+#define RTPG_NO_TPG_IDENTIFIER 2 -+#define RTPG_RTPG_FAILED 3 -+#define RTPG_TPG_NOT_FOUND 4 -+ -+int get_target_port_group_support(int fd); -+int get_target_port_group(int fd); -+int get_asymmetric_access_state(int fd, unsigned int tpg); -+ -+#endif /* __RTPG_H__ */ -+ -diff --git a/libmultipath/prioritizers/alua_spc3.h b/libmultipath/prioritizers/alua_spc3.h -new file mode 100644 -index 0000000..bddbbdd ---- /dev/null -+++ b/libmultipath/prioritizers/alua_spc3.h -@@ -0,0 +1,322 @@ -+/* -+ * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -+ * -+ * spc3.h -+ * -+ * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -+ * It determines the ALUA state of a device and prints a priority value to -+ * stdout. -+ * -+ * Author(s): Jan Kunigk -+ * S. Bader -+ * -+ * This file is released under the GPL. -+ */ -+#ifndef __SPC3_H__ -+#define __SPC3_H__ -+/*============================================================================= -+ * Some helper functions for getting and setting 16 and 32 bit values. -+ *============================================================================= -+ */ -+static inline unsigned short -+get_uint16(unsigned char *p) -+{ -+ return (p[0] << 8) + p[1]; -+} -+ -+static inline void -+set_uint16(unsigned char *p, unsigned short v) -+{ -+ p[0] = (v >> 8) & 0xff; -+ p[1] = v & 0xff; -+} -+ -+static inline unsigned int -+get_uint32(unsigned char *p) -+{ -+ return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; -+} -+ -+static inline void -+set_uint32(unsigned char *p, unsigned int v) -+{ -+ p[0] = (v >> 24) & 0xff; -+ p[1] = (v >> 16) & 0xff; -+ p[2] = (v >> 8) & 0xff; -+ p[3] = v & 0xff; -+} -+ -+/*============================================================================= -+ * Definitions to support the standard inquiry command as defined in SPC-3. -+ * If the evpd (enable vital product data) bit is set the data that will be -+ * returned is selected by the page field. This field must be 0 if the evpd -+ * bit is not set. -+ *============================================================================= -+ */ -+#define OPERATION_CODE_INQUIRY 0x12 -+ -+struct inquiry_command { -+ unsigned char op; -+ unsigned char b1; /* xxxxxx.. = reserved */ -+ /* ......x. = obsolete */ -+ /* .......x = evpd */ -+ unsigned char page; -+ unsigned char length[2]; -+ unsigned char control; -+} __attribute__((packed)); -+ -+static inline void -+inquiry_command_set_evpd(struct inquiry_command *ic) -+{ -+ ic->b1 |= 1; -+} -+ -+/*----------------------------------------------------------------------------- -+ * Data returned by the standard inquiry command. -+ *----------------------------------------------------------------------------- -+ * -+ * Peripheral qualifier codes. -+ */ -+#define PQ_CONNECTED 0x0 -+#define PQ_DISCONNECTED 0x1 -+#define PQ_UNSUPPORTED 0x3 -+ -+/* Defined peripheral device types. */ -+#define PDT_DIRECT_ACCESS 0x00 -+#define PDT_SEQUENTIAL_ACCESS 0x01 -+#define PDT_PRINTER 0x02 -+#define PDT_PROCESSOR 0x03 -+#define PDT_WRITE_ONCE 0x04 -+#define PDT_CD_DVD 0x05 -+#define PDT_SCANNER 0x06 -+#define PDT_OPTICAL_MEMORY 0x07 -+#define PDT_MEDIUM_CHANGER 0x08 -+#define PDT_COMMUNICATIONS 0x09 -+#define PDT_STORAGE_ARRAY_CONTROLLER 0x0c -+#define PDT_ENCLOSURE_SERVICES 0x0d -+#define PDT_SIMPLIFIED_DIRECT_ACCESS 0x0e -+#define PDT_OPTICAL_CARD_READER_WRITER 0x0f -+#define PDT_BRIDGE_CONTROLLER 0x10 -+#define PDT_OBJECT_BASED 0x11 -+#define PDT_AUTOMATION_INTERFACE 0x12 -+#define PDT_LUN 0x1e -+#define PDT_UNKNOWN 0x1f -+ -+/* Defined version codes. */ -+#define VERSION_NONE 0x00 -+#define VERSION_SPC 0x03 -+#define VERSION_SPC2 0x04 -+#define VERSION_SPC3 0x05 -+ -+/* Defined TPGS field values. */ -+#define TPGS_NONE 0x0 -+#define TPGS_IMPLICIT 0x1 -+#define TPGS_EXPLICIT 0x2 -+#define TPGS_BOTH 0x3 -+ -+struct inquiry_data { -+ unsigned char b0; /* xxx..... = peripheral_qualifier */ -+ /* ...xxxxx = peripheral_device_type */ -+ unsigned char b1; /* x....... = removable medium */ -+ /* .xxxxxxx = reserverd */ -+ unsigned char version; -+ unsigned char b3; /* xx...... = obsolete */ -+ /* ..x..... = normal aca supported */ -+ /* ...x.... = hirarchichal lun supp. */ -+ /* ....xxxx = response format */ -+ /* 2 is spc-3 format */ -+ unsigned char length; -+ unsigned char b5; /* x....... = storage controller */ -+ /* component supported */ -+ /* .x...... = access controls coord. */ -+ /* ..xx.... = target port group supp.*/ -+ /* ....x... = third party copy supp. */ -+ /* .....xx. = reserved */ -+ /* .......x = protection info supp. */ -+ unsigned char b6; /* x....... = bque */ -+ /* .x...... = enclosure services sup.*/ -+ /* ..x..... = vs1 */ -+ /* ...x.... = multiport support */ -+ /* ....x... = medium changer */ -+ /* .....xx. = obsolete */ -+ /* .......x = add16 */ -+ unsigned char b7; /* xx...... = obsolete */ -+ /* ..x..... = wbus16 */ -+ /* ...x.... = sync */ -+ /* ....x... = linked commands supp. */ -+ /* .....x.. = obsolete */ -+ /* ......x. = command queue support */ -+ /* .......x = vs2 */ -+ unsigned char vendor_identification[8]; -+ unsigned char product_identification[16]; -+ unsigned char product_revision[4]; -+ unsigned char vendor_specific[20]; -+ unsigned char b56; /* xxxx.... = reserved */ -+ /* ....xx.. = clocking */ -+ /* ......x. = qas */ -+ /* .......x = ius */ -+ unsigned char reserved4; -+ unsigned char version_descriptor[8][2]; -+ unsigned char reserved5[22]; -+ unsigned char vendor_parameters[0]; -+} __attribute__((packed)); -+ -+static inline int -+inquiry_data_get_tpgs(struct inquiry_data *id) -+{ -+ return (id->b5 >> 4) & 3; -+} -+ -+/*----------------------------------------------------------------------------- -+ * Inquiry data returned when requesting vital product data page 0x83. -+ *----------------------------------------------------------------------------- -+ */ -+#define CODESET_BINARY 0x1 -+#define CODESET_ACSII 0x2 -+#define CODESET_UTF8 0x3 -+ -+#define ASSOCIATION_UNIT 0x0 -+#define ASSOCIATION_PORT 0x1 -+#define ASSOCIATION_DEVICE 0x2 -+ -+#define IDTYPE_VENDOR_SPECIFIC 0x0 -+#define IDTYPE_T10_VENDOR_ID 0x1 -+#define IDTYPE_EUI64 0x2 -+#define IDTYPE_NAA 0x3 -+#define IDTYPE_RELATIVE_TPG_ID 0x4 -+#define IDTYPE_TARGET_PORT_GROUP 0x5 -+#define IDTYPE_LUN_GROUP 0x6 -+#define IDTYPE_MD5_LUN_ID 0x7 -+#define IDTYPE_SCSI_NAME_STRING 0x8 -+ -+struct vpd83_tpg_dscr { -+ unsigned char reserved1[2]; -+ unsigned char tpg[2]; -+} __attribute__((packed)); -+ -+struct vpd83_dscr { -+ unsigned char b0; /* xxxx.... = protocol id */ -+ /* ....xxxx = codeset */ -+ unsigned char b1; /* x....... = protocol id valid */ -+ /* .x...... = reserved */ -+ /* ..xx.... = association */ -+ /* ....xxxx = id type */ -+ unsigned char reserved2; -+ unsigned char length; /* size-4 */ -+ unsigned char data[0]; -+} __attribute__((packed)); -+ -+static inline int -+vpd83_dscr_istype(struct vpd83_dscr *d, unsigned char type) -+{ -+ return ((d->b1 & 7) == type); -+} -+ -+struct vpd83_data { -+ unsigned char b0; /* xxx..... = peripheral_qualifier */ -+ /* ...xxxxx = peripheral_device_type */ -+ unsigned char page_code; /* 0x83 */ -+ unsigned char length[2]; /* size-4 */ -+ struct vpd83_dscr data[0]; -+} __attribute__((packed)); -+ -+/*----------------------------------------------------------------------------- -+ * This macro should be used to walk through all identification descriptors -+ * defined in the code page 0x83. -+ * The argument p is a pointer to the code page 0x83 data and d is used to -+ * point to the current descriptor. -+ *----------------------------------------------------------------------------- -+ */ -+#define FOR_EACH_VPD83_DSCR(p, d) \ -+ for( \ -+ d = p->data; \ -+ (((char *) d) - ((char *) p)) < \ -+ get_uint16(p->length); \ -+ d = (struct vpd83_dscr *) \ -+ ((char *) d + d->length + 4) \ -+ ) -+ -+/*============================================================================= -+ * The following stuctures and macros are used to call the report target port -+ * groups command defined in SPC-3. -+ * This command is used to get information about the target port groups (which -+ * states are supported, which ports belong to this group, and so on) and the -+ * current state of each target port group. -+ *============================================================================= -+ */ -+#define OPERATION_CODE_RTPG 0xa3 -+#define SERVICE_ACTION_RTPG 0x0a -+ -+struct rtpg_command { -+ unsigned char op; /* 0xa3 */ -+ unsigned char b1; /* xxx..... = reserved */ -+ /* ...xxxxx = service action (0x0a) */ -+ unsigned char reserved2[4]; -+ unsigned char length[4]; -+ unsigned char reserved3; -+ unsigned char control; -+} __attribute__((packed)); -+ -+static inline void -+rtpg_command_set_service_action(struct rtpg_command *cmd) -+{ -+ cmd->b1 = (cmd->b1 & 0xe0) | SERVICE_ACTION_RTPG; -+} -+ -+struct rtpg_tp_dscr { -+ unsigned char obsolete1[2]; -+ /* The Relative Target Port Identifier of a target port. */ -+ unsigned char rtpi[2]; -+} __attribute__((packed)); -+ -+#define AAS_OPTIMIZED 0x0 -+#define AAS_NON_OPTIMIZED 0x1 -+#define AAS_STANDBY 0x2 -+#define AAS_UNAVAILABLE 0x3 -+#define AAS_TRANSITIONING 0xf -+ -+#define TPG_STATUS_NONE 0x0 -+#define TPG_STATUS_SET 0x1 -+#define TPG_STATUS_IMPLICIT_CHANGE 0x2 -+ -+struct rtpg_tpg_dscr { -+ unsigned char b0; /* x....... = pref(ered) port */ -+ /* .xxx.... = reserved */ -+ /* ....xxxx = asymetric access state */ -+ unsigned char b1; /* xxxx.... = reserved */ -+ /* ....x... = unavailable support */ -+ /* .....x.. = standby support */ -+ /* ......x. = non-optimized support */ -+ /* .......x = optimized support */ -+ unsigned char tpg[2]; -+ unsigned char reserved3; -+ unsigned char status; -+ unsigned char vendor_unique; -+ unsigned char port_count; -+ struct rtpg_tp_dscr data[0]; -+} __attribute__((packed)); -+ -+static inline int -+rtpg_tpg_dscr_get_aas(struct rtpg_tpg_dscr *d) -+{ -+ return (d->b0 & 0x0f); -+} -+ -+struct rtpg_data { -+ unsigned char length[4]; /* size-4 */ -+ struct rtpg_tpg_dscr data[0]; -+} __attribute__((packed)); -+ -+#define RTPG_FOR_EACH_PORT_GROUP(p, g) \ -+ for( \ -+ g = &(p->data[0]); \ -+ (((char *) g) - ((char *) p)) < get_uint32(p->length); \ -+ g = (struct rtpg_tpg_dscr *) ( \ -+ ((char *) g) + \ -+ sizeof(struct rtpg_tpg_dscr) + \ -+ g->port_count * sizeof(struct rtpg_tp_dscr) \ -+ ) \ -+ ) -+ -+#endif /* __SPC3_H__ */ -+ -diff --git a/libmultipath/prioritizers/const.c b/libmultipath/prioritizers/const.c -new file mode 100644 -index 0000000..529cf82 ---- /dev/null -+++ b/libmultipath/prioritizers/const.c -@@ -0,0 +1,8 @@ -+#include -+ -+#include -+ -+int getprio (struct path * pp) -+{ -+ return 1; -+} -diff --git a/libmultipath/prioritizers/const.h b/libmultipath/prioritizers/const.h -new file mode 100644 -index 0000000..220db54 ---- /dev/null -+++ b/libmultipath/prioritizers/const.h -@@ -0,0 +1,7 @@ -+#ifndef _CONST_H -+#define _CONST_H -+ -+#define PRIO_CONST "const" -+int prio_const(struct path * pp); -+ -+#endif -diff --git a/libmultipath/prioritizers/emc.c b/libmultipath/prioritizers/emc.c -new file mode 100644 -index 0000000..61d7a77 ---- /dev/null -+++ b/libmultipath/prioritizers/emc.c -@@ -0,0 +1,79 @@ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define INQUIRY_CMD 0x12 -+#define INQUIRY_CMDLEN 6 -+ -+#define pp_emc_log(prio, msg) condlog(prio, "%s: emc prio: " msg, dev) -+ -+int emc_clariion_prio(const char *dev, int fd) -+{ -+ unsigned char sense_buffer[256]; -+ unsigned char sb[128]; -+ unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0, -+ sizeof(sb), 0}; -+ struct sg_io_hdr io_hdr; -+ int ret = 0; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (inqCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = sizeof (sense_buffer); -+ io_hdr.dxferp = sense_buffer; -+ io_hdr.cmdp = inqCmdBlk; -+ io_hdr.sbp = sb; -+ io_hdr.timeout = 60000; -+ io_hdr.pack_id = 0; -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) { -+ pp_emc_log(0, "sending query command failed"); -+ goto out; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ pp_emc_log(0, "query command indicates error"); -+ goto out; -+ } -+ -+ if (/* Verify the code page - right page & revision */ -+ sense_buffer[1] != 0xc0 || sense_buffer[9] != 0x00) { -+ pp_emc_log(0, "path unit report page in unknown format"); -+ goto out; -+ } -+ -+ if ( /* Effective initiator type */ -+ sense_buffer[27] != 0x03 -+ /* -+ * Failover mode should be set to 1 (PNR failover mode) -+ * or 4 (ALUA failover mode). -+ */ -+ || (((sense_buffer[28] & 0x07) != 0x04) && -+ ((sense_buffer[28] & 0x07) != 0x06)) -+ /* Arraycommpath should be set to 1 */ -+ || (sense_buffer[30] & 0x04) != 0x04) { -+ pp_emc_log(0, "path not correctly configured for failover"); -+ } -+ -+ if ( /* LUN operations should indicate normal operations */ -+ sense_buffer[48] != 0x00) { -+ pp_emc_log(0, "path not available for normal operations"); -+ } -+ -+ /* Is the default owner equal to this path? */ -+ /* Note this will switch to the default priority group, even if -+ * it is not the currently active one. */ -+ ret = (sense_buffer[5] == sense_buffer[8]) ? 1 : 0; -+ -+out: -+ return(ret); -+} -+ -+int getprio (struct path * pp) -+{ -+ return emc_clariion_prio(pp->dev, pp->fd); -+} -diff --git a/libmultipath/prioritizers/emc.h b/libmultipath/prioritizers/emc.h -new file mode 100644 -index 0000000..0ab0bc5 ---- /dev/null -+++ b/libmultipath/prioritizers/emc.h -@@ -0,0 +1,7 @@ -+#ifndef _EMC_H -+#define _EMC_H -+ -+#define PRIO_EMC "emc" -+int prio_emc(struct path * pp); -+ -+#endif -diff --git a/libmultipath/prioritizers/hds.c b/libmultipath/prioritizers/hds.c -new file mode 100644 -index 0000000..6ebe4d8 ---- /dev/null -+++ b/libmultipath/prioritizers/hds.c -@@ -0,0 +1,170 @@ -+/* -+ * (C) Copyright HDS GmbH 2006. All Rights Reserved. -+ * -+ * pp_hds_modular.c -+ * Version 2.00 -+ * -+ * Prioritizer for Device Mapper Multipath 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 command 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 -+ * -+ * To compile this source please execute # cc pp_hds_modular.c -o /sbin/mpath_prio_hds_modular -+ * -+ * Changes 2006-07-16: -+ * - Changed to forward declaration of functions -+ * - The switch-statement was changed to a logical expression -+ * - unlinking of the devpath now also occurs at the end of -+ * hds_modular_prio to avoid old /tmp/.pp_balance.%u.%u.devnode -+ * entries in /tmp-Directory -+ * - The for-statements for passing variables where changed to -+ * snprintf-commands in verbose mode -+ * Changes 2006-08-10: -+ * - Back to the old switch statements because the regular expression does -+ * not work under RHEL4 U3 i386 -+ * Changes 2007-06-27: -+ * - switched from major:minor argument to device node argument -+ * -+ * This file is released under the GPL. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define INQ_REPLY_LEN 255 -+#define INQ_CMD_CODE 0x12 -+#define INQ_CMD_LEN 6 -+ -+#define pp_hds_log(prio, fmt, args...) \ -+ condlog(prio, "%s: hds prio: " fmt, dev, ##args) -+ -+int hds_modular_prio (const char *dev, int fd) -+{ -+ int k; -+ char vendor[8]; -+ char product[32]; -+ char serial[32]; -+ char ldev[32]; -+ char ctrl[32]; -+ char port[32]; -+ unsigned char inqCmdBlk[INQ_CMD_LEN] = { INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0 }; -+ unsigned char inqBuff[INQ_REPLY_LEN]; -+ unsigned char *inqBuffp = inqBuff; -+ unsigned char sense_buffer[32]; -+ sg_io_hdr_t io_hdr; -+ -+ if ((ioctl (fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) { -+ pp_hds_log(0, "can't use SG ioctl interface"); -+ return -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 (fd, SG_IO, &io_hdr) < 0) { -+ pp_hds_log(0, "SG_IO error"); -+ return -1; -+ } -+ if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { -+ pp_hds_log(0, "SCSI error"); -+ return -1; -+ } -+ -+ snprintf (vendor, 9, "%.8s", inqBuffp + 8); -+ snprintf (product, 17, "%.16s", inqBuffp + 16); -+ snprintf (serial, 5, "%.4s", inqBuffp + 40); -+ snprintf (ldev, 5, "%.4s", inqBuffp + 44); -+ snprintf (ctrl, 2, "%.1s", inqBuffp + 49); -+ snprintf (port, 2, "%.1s", inqBuffp + 50); -+ -+ pp_hds_log(4, "VENDOR: %s", vendor); -+ pp_hds_log(4, "PRODUCT: %s", product); -+ pp_hds_log(4, "SERIAL: 0x%s", serial); -+ pp_hds_log(4, "LDEV: 0x%s", ldev); -+ pp_hds_log(4, "CTRL: %s", ctrl); -+ pp_hds_log(4, "PORT: %s", 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': -+ pp_hds_log(4, "CTRL EVEN, LDEV EVEN, PRIO 1"); -+ return 1; -+ break; -+ case '1': case '3': case '5': case '7': case '9': case 'B': case 'D': case 'F': -+ pp_hds_log(4, "CTRL EVEN, LDEV ODD, PRIO 0"); -+ 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': -+ pp_hds_log(4, "CTRL ODD, LDEV EVEN, PRIO 0"); -+ return 0; -+ break; -+ case '1': case '3': case '5': case '7': case '9': case 'B': case 'D': case 'F': -+ pp_hds_log(4, "CTRL ODD, LDEV ODD, PRIO 1"); -+ return 1; -+ break; -+ } -+ } -+ return -1; -+} -+ -+int getprio (struct path * pp) -+{ -+ return hds_modular_prio(pp->dev, pp->fd); -+} -diff --git a/libmultipath/prioritizers/hds.h b/libmultipath/prioritizers/hds.h -new file mode 100644 -index 0000000..084d77c ---- /dev/null -+++ b/libmultipath/prioritizers/hds.h -@@ -0,0 +1,7 @@ -+#ifndef _HDS_H -+#define _HDS_H -+ -+#define PRIO_HDS "hds" -+int prio_hds(struct path * pp); -+ -+#endif -diff --git a/libmultipath/prioritizers/hp_sw.c b/libmultipath/prioritizers/hp_sw.c -new file mode 100644 -index 0000000..ae0975f ---- /dev/null -+++ b/libmultipath/prioritizers/hp_sw.c -@@ -0,0 +1,100 @@ -+/* -+ * Path priority checker for HP active/standby controller -+ * -+ * Check the path state and sort them into groups. -+ * There is actually a preferred path in the controller; -+ * we should ask HP on how to retrieve that information. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define TUR_CMD_LEN 6 -+#define SCSI_CHECK_CONDITION 0x2 -+#define SCSI_COMMAND_TERMINATED 0x22 -+#define SG_ERR_DRIVER_SENSE 0x08 -+#define RECOVERED_ERROR 0x01 -+#define NOT_READY 0x02 -+#define UNIT_ATTENTION 0x06 -+ -+#define HP_PATH_ACTIVE 0x04 -+#define HP_PATH_STANDBY 0x02 -+#define HP_PATH_FAILED 0x00 -+ -+#define pp_hp_sw_log(prio, fmt, args...) \ -+ condlog(prio, "%s: hp_sw prio: " fmt, dev, ##args) -+ -+int hp_sw_prio(const char *dev, int fd) -+{ -+ unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -+ unsigned char sb[128]; -+ struct sg_io_hdr io_hdr; -+ int ret = HP_PATH_FAILED; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (turCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_NONE; -+ io_hdr.cmdp = turCmdBlk; -+ io_hdr.sbp = sb; -+ io_hdr.timeout = 60000; -+ io_hdr.pack_id = 0; -+ retry: -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) { -+ pp_hp_sw_log(0, "sending tur command failed"); -+ goto out; -+ } -+ io_hdr.status &= 0x7e; -+ if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -+ (0 == io_hdr.driver_status)) { -+ /* Command completed normally, path is active */ -+ ret = HP_PATH_ACTIVE; -+ } -+ -+ if ((SCSI_CHECK_CONDITION == io_hdr.status) || -+ (SCSI_COMMAND_TERMINATED == io_hdr.status) || -+ (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -+ if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -+ int sense_key, asc, asq; -+ unsigned char * sense_buffer = io_hdr.sbp; -+ if (sense_buffer[0] & 0x2) { -+ sense_key = sense_buffer[1] & 0xf; -+ asc = sense_buffer[2]; -+ asq = sense_buffer[3]; -+ } else { -+ sense_key = sense_buffer[2] & 0xf; -+ asc = sense_buffer[12]; -+ asq = sense_buffer[13]; -+ } -+ if(RECOVERED_ERROR == sense_key) -+ ret = HP_PATH_ACTIVE; -+ if(NOT_READY == sense_key) { -+ if (asc == 0x04 && asq == 0x02) { -+ /* This is a standby path */ -+ ret = HP_PATH_STANDBY; -+ } -+ } -+ if(UNIT_ATTENTION == sense_key) { -+ if (asc == 0x29) { -+ /* Retry for device reset */ -+ goto retry; -+ } -+ } -+ } -+ } -+out: -+ return(ret); -+} -+ -+int getprio (struct path * pp) -+{ -+ return hp_sw_prio(pp->dev, pp->fd); -+} -diff --git a/libmultipath/prioritizers/hp_sw.h b/libmultipath/prioritizers/hp_sw.h -new file mode 100644 -index 0000000..2fea486 ---- /dev/null -+++ b/libmultipath/prioritizers/hp_sw.h -@@ -0,0 +1,7 @@ -+#ifndef _HP_SW_H -+#define _HP_SW_H -+ -+#define PRIO_HP_SW "hp_sw" -+int prio_hp_sw(struct path * pp); -+ -+#endif -diff --git a/libmultipath/prioritizers/netapp.c b/libmultipath/prioritizers/netapp.c -new file mode 100644 -index 0000000..812ecf6 ---- /dev/null -+++ b/libmultipath/prioritizers/netapp.c -@@ -0,0 +1,243 @@ -+/* -+ * Copyright 2005 Network Appliance, Inc., All Rights Reserved -+ * Author: David Wysochanski available at davidw@netapp.com -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * 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 v2 for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define INQUIRY_CMD 0x12 -+#define INQUIRY_CMDLEN 6 -+#define DEFAULT_PRIOVAL 10 -+#define RESULTS_MAX 256 -+#define SG_TIMEOUT 30000 -+ -+#define pp_netapp_log(prio, fmt, args...) \ -+ condlog(prio, "%s: netapp prio: " fmt, dev, ##args) -+ -+static void dump_cdb(unsigned char *cdb, int size) -+{ -+ int i; -+ char buf[10*5+1]; -+ char * p = &buf[0]; -+ -+ condlog(0, "- SCSI CDB: "); -+ for (i=0; imasked_status, -+ io_hdr->host_status, io_hdr->driver_status); -+ if (io_hdr->sb_len_wr > 0) { -+ condlog(0, "- SCSI sense data: "); -+ for (i=0; isb_len_wr; i++) { -+ p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ", -+ io_hdr->sbp[i]); -+ } -+ condlog(0, "%s", buf); -+ } -+} -+ -+/* -+ * Returns: -+ * -1: error, errno set -+ * 0: success -+ */ -+static int send_gva(const char *dev, int fd, unsigned char pg, -+ unsigned char *results, int *results_size) -+{ -+ unsigned char sb[128]; -+ unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa, -+ pg, sizeof(sb), 0, 0}; -+ struct sg_io_hdr io_hdr; -+ int ret = -1; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (cdb); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = *results_size; -+ io_hdr.dxferp = results; -+ io_hdr.cmdp = cdb; -+ io_hdr.sbp = sb; -+ io_hdr.timeout = SG_TIMEOUT; -+ io_hdr.pack_id = 0; -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) { -+ pp_netapp_log(0, "SG_IO ioctl failed, errno=%d", errno); -+ dump_cdb(cdb, sizeof(cdb)); -+ goto out; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ pp_netapp_log(0, "SCSI error"); -+ dump_cdb(cdb, sizeof(cdb)); -+ process_sg_error(&io_hdr); -+ goto out; -+ } -+ -+ if (results[4] != 0x0a || results[5] != 0x98 || -+ results[6] != 0x0a ||results[7] != 0x01) { -+ dump_cdb(cdb, sizeof(cdb)); -+ pp_netapp_log(0, "GVA return wrong format "); -+ pp_netapp_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x", -+ results[4], results[5], results[6], results[7]); -+ goto out; -+ } -+ ret = 0; -+ out: -+ return(ret); -+} -+ -+/* -+ * Retuns: -+ * -1: Unable to obtain proxy info -+ * 0: Device _not_ proxy path -+ * 1: Device _is_ proxy path -+ */ -+static int get_proxy(const char *dev, int fd) -+{ -+ unsigned char results[256]; -+ unsigned char sb[128]; -+ unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0, -+ sizeof(sb), 0}; -+ struct sg_io_hdr io_hdr; -+ int ret = -1; -+ -+ memset(&results, 0, sizeof (results)); -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (cdb); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = sizeof (results); -+ io_hdr.dxferp = results; -+ io_hdr.cmdp = cdb; -+ io_hdr.sbp = sb; -+ io_hdr.timeout = SG_TIMEOUT; -+ io_hdr.pack_id = 0; -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) { -+ pp_netapp_log(0, "ioctl sending inquiry command failed, " -+ "errno=%d", errno); -+ dump_cdb(cdb, sizeof(cdb)); -+ goto out; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ pp_netapp_log(0, "SCSI error"); -+ dump_cdb(cdb, sizeof(cdb)); -+ process_sg_error(&io_hdr); -+ goto out; -+ } -+ -+ if (results[1] != 0xc1 || results[8] != 0x0a || -+ results[9] != 0x98 || results[10] != 0x0a || -+ results[11] != 0x0 || results[12] != 0xc1 || -+ results[13] != 0x0) { -+ pp_netapp_log(0,"proxy info page in unknown format - "); -+ pp_netapp_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x " -+ "0x%02x 0x%02x", -+ results[8], results[9], results[10], -+ results[11], results[12], results[13]); -+ dump_cdb(cdb, sizeof(cdb)); -+ goto out; -+ } -+ ret = (results[19] & 0x02) >> 1; -+ -+ out: -+ return(ret); -+} -+ -+/* -+ * Returns priority of device based on device info. -+ * -+ * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol -+ * 3: iSCSI HBA -+ * 2: iSCSI software -+ * 1: FCP proxy -+ */ -+static int netapp_prio(const char *dev, int fd) -+{ -+ unsigned char results[RESULTS_MAX]; -+ int results_size=RESULTS_MAX; -+ int rc; -+ int is_proxy; -+ int is_iscsi_software; -+ int is_iscsi_hardware; -+ int tot_len; -+ -+ is_iscsi_software = is_iscsi_hardware = is_proxy = 0; -+ -+ memset(&results, 0, sizeof (results)); -+ rc = send_gva(dev, fd, 0x41, results, &results_size); -+ if (rc == 0) { -+ tot_len = results[0] << 24 | results[1] << 16 | -+ results[2] << 8 | results[3]; -+ if (tot_len <= 8) { -+ goto try_fcp_proxy; -+ } -+ if (results[8] != 0x41) { -+ pp_netapp_log(0, "GVA page 0x41 error - " -+ "results[8] = 0x%x", results[8]); -+ goto try_fcp_proxy; -+ } -+ if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) || -+ (strncmp((char *)&results[12], "iswt", 4) == 0)) { -+ is_iscsi_software = 1; -+ goto prio_select; -+ } -+ else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) { -+ is_iscsi_hardware = 1; -+ goto prio_select; -+ } -+ } -+ -+ try_fcp_proxy: -+ rc = get_proxy(dev, fd); -+ if (rc >= 0) { -+ is_proxy = rc; -+ } -+ -+ prio_select: -+ if (is_iscsi_hardware) { -+ return 3; -+ } else if (is_iscsi_software) { -+ return 2; -+ } else { -+ if (is_proxy) { -+ return 1; -+ } else { -+ /* Either non-proxy, or couldn't get proxy info */ -+ return 4; -+ } -+ } -+} -+ -+int getprio (struct path * pp) -+{ -+ return netapp_prio(pp->dev, pp->fd); -+} -diff --git a/libmultipath/prioritizers/netapp.h b/libmultipath/prioritizers/netapp.h -new file mode 100644 -index 0000000..ec38821 ---- /dev/null -+++ b/libmultipath/prioritizers/netapp.h -@@ -0,0 +1,7 @@ -+#ifndef _NETAPP_H -+#define _NETAPP_H -+ -+#define PRIO_NETAPP "netapp" -+int prio_netapp(struct path * pp); -+ -+#endif -diff --git a/libmultipath/prioritizers/random.c b/libmultipath/prioritizers/random.c -new file mode 100644 -index 0000000..e3852a7 ---- /dev/null -+++ b/libmultipath/prioritizers/random.c -@@ -0,0 +1,15 @@ -+#include -+#include -+#include -+#include -+ -+#include -+ -+int getprio (struct path * pp) -+{ -+ struct timeval tv; -+ -+ gettimeofday(&tv, NULL); -+ srand((unsigned int)tv.tv_usec); -+ return 1+(int) (10.0*rand()/(RAND_MAX+1.0)); -+} -diff --git a/libmultipath/prioritizers/random.h b/libmultipath/prioritizers/random.h -new file mode 100644 -index 0000000..b9dae69 ---- /dev/null -+++ b/libmultipath/prioritizers/random.h -@@ -0,0 +1,7 @@ -+#ifndef _RANDOM_H -+#define _RANDOM_H -+ -+#define PRIO_RANDOM "random" -+int prio_random(struct path * pp); -+ -+#endif -diff --git a/libmultipath/prioritizers/rdac.c b/libmultipath/prioritizers/rdac.c -new file mode 100644 -index 0000000..4dd8f44 ---- /dev/null -+++ b/libmultipath/prioritizers/rdac.c -@@ -0,0 +1,90 @@ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define INQUIRY_CMD 0x12 -+#define INQUIRY_CMDLEN 6 -+ -+#define pp_rdac_log(prio, msg) condlog(prio, "%s: rdac prio: " msg, dev) -+ -+int rdac_prio(const char *dev, int fd) -+{ -+ unsigned char sense_buffer[256]; -+ unsigned char sb[128]; -+ unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC9, 0, -+ sizeof(sb), 0}; -+ struct sg_io_hdr io_hdr; -+ int ret = 0; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (inqCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = sizeof (sense_buffer); -+ io_hdr.dxferp = sense_buffer; -+ io_hdr.cmdp = inqCmdBlk; -+ io_hdr.sbp = sb; -+ io_hdr.timeout = 60000; -+ io_hdr.pack_id = 0; -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) { -+ pp_rdac_log(0, "sending inquiry command failed"); -+ goto out; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ pp_rdac_log(0, "inquiry command indicates error"); -+ goto out; -+ } -+ -+ if (/* Verify the code page - right page & page identifier */ -+ sense_buffer[1] != 0xc9 || -+ sense_buffer[3] != 0x2c || -+ sense_buffer[4] != 'v' || -+ sense_buffer[5] != 'a' || -+ sense_buffer[6] != 'c' ) { -+ pp_rdac_log(0, "volume access control page in unknown format"); -+ goto out; -+ } -+ -+ if ( /* Current Volume Path Bit */ -+ ( sense_buffer[8] & 0x01) == 0x01 ) { -+ /* -+ * This volume was owned by the controller receiving -+ * the inquiry command. -+ */ -+ ret |= 0x01; -+ } -+ -+ /* Volume Preferred Path Priority */ -+ switch ( sense_buffer[9] & 0x0F ) { -+ case 0x01: -+ /* -+ * Access to this volume is most preferred through -+ * this path and other paths with this value. -+ */ -+ ret |= 0x02; -+ break; -+ case 0x02: -+ /* -+ * Access to this volume through this path is to be used -+ * as a secondary path. Typically this path would be used -+ * for fail-over situations. -+ */ -+ /* Fallthrough */ -+ default: -+ /* Reserved values */ -+ break; -+ } -+ -+out: -+ return(ret); -+} -+ -+int getprio (struct path * pp) -+{ -+ return rdac_prio(pp->dev, pp->fd); -+} -diff --git a/libmultipath/prioritizers/rdac.h b/libmultipath/prioritizers/rdac.h -new file mode 100644 -index 0000000..a5b7f8e ---- /dev/null -+++ b/libmultipath/prioritizers/rdac.h -@@ -0,0 +1,7 @@ -+#ifndef _RDAC_H -+#define _RDAC_H -+ -+#define PRIO_RDAC "rdac" -+int prio_rdac(struct path * pp); -+ -+#endif -diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c -index 45a3728..43611ff 100644 ---- a/libmultipath/propsel.c -+++ b/libmultipath/propsel.c -@@ -5,8 +5,7 @@ - */ - #include - --#include -- -+#include "checkers.h" - #include "memory.h" - #include "vector.h" - #include "structs.h" -@@ -16,6 +15,7 @@ - #include "alias.h" - #include "defaults.h" - #include "devmapper.h" -+#include "prio.h" - - pgpolicyfn *pgpolicies[] = { - NULL, -@@ -168,8 +168,7 @@ select_alias (struct multipath * mp) - if (mp->alias == NULL){ - char *alias; - if ((alias = MALLOC(WWID_SIZE)) != NULL){ -- if (dm_get_name(mp->wwid, DEFAULT_TARGET, -- alias) == 1) -+ if (dm_get_name(mp->wwid, alias) == 1) - mp->alias = alias; - else - FREE(alias); -@@ -217,19 +216,19 @@ select_checker(struct path *pp) - { - struct checker * c = &pp->checker; - -- if (pp->hwe && pp->hwe->checker) { -- checker_get(c, pp->hwe->checker); -+ if (pp->hwe && pp->hwe->checker_name) { -+ checker_get(c, pp->hwe->checker_name); - condlog(3, "%s: path checker = %s (controller setting)", - pp->dev, checker_name(c)); - return 0; - } -- if (conf->checker) { -- checker_get(c, conf->checker); -+ if (conf->checker_name) { -+ checker_get(c, conf->checker_name); - condlog(3, "%s: path checker = %s (config file default)", - pp->dev, checker_name(c)); - return 0; - } -- checker_get(c, checker_default()); -+ checker_get(c, DEFAULT_CHECKER); - condlog(3, "%s: path checker = %s (internal default)", - pp->dev, checker_name(c)); - return 0; -@@ -257,22 +256,23 @@ select_getuid (struct path * pp) - } - - extern int --select_getprio (struct path * pp) -+select_prio (struct path * pp) - { -- if (pp->hwe && pp->hwe->getprio) { -- pp->getprio = pp->hwe->getprio; -- condlog(3, "%s: getprio = %s (controller setting)", -- pp->dev, pp->getprio); -+ if (pp->hwe && pp->hwe->prio_name) { -+ pp->prio = prio_lookup(pp->hwe->prio_name); -+ condlog(3, "%s: prio = %s (controller setting)", -+ pp->dev, pp->hwe->prio_name); - return 0; - } -- if (conf->getprio) { -- pp->getprio = conf->getprio; -- condlog(3, "%s: getprio = %s (config file default)", -- pp->dev, pp->getprio); -+ if (conf->prio_name) { -+ pp->prio = prio_lookup(conf->prio_name); -+ condlog(3, "%s: prio = %s (config file default)", -+ pp->dev, conf->prio_name); - return 0; - } -- pp->getprio = DEFAULT_GETPRIO; -- condlog(3, "%s: getprio = NULL (internal default)", pp->dev); -+ pp->prio = prio_lookup(DEFAULT_PRIO); -+ condlog(3, "%s: prio = %s (internal default)", -+ pp->dev, DEFAULT_PRIO); - return 0; - } - -diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h -index afd1f88..62802f8 100644 ---- a/libmultipath/propsel.h -+++ b/libmultipath/propsel.h -@@ -7,7 +7,7 @@ int select_features (struct multipath * mp); - int select_hwhandler (struct multipath * mp); - int select_checker(struct path *pp); - int select_getuid (struct path * pp); --int select_getprio (struct path * pp); -+int select_prio (struct path * pp); - int select_no_path_retry(struct multipath *mp); - int select_pg_timeout(struct multipath *mp); - int select_minio(struct multipath *mp); -diff --git a/libmultipath/structs.c b/libmultipath/structs.c -index d36eaef..852e6b3 100644 ---- a/libmultipath/structs.c -+++ b/libmultipath/structs.c -@@ -6,8 +6,7 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "memory.h" - #include "vector.h" - #include "util.h" -@@ -17,6 +16,7 @@ - #include "structs_vec.h" - #include "blacklist.h" - #include "waiter.h" -+#include "prio.h" - - struct path * - alloc_path (void) -@@ -170,14 +170,12 @@ free_multipath (struct multipath * mpp, int free_paths) - - if (mpp->dmi) - FREE(mpp->dmi); -- --#if DAEMON -+ - /* - * better own vecs->lock here - */ - if (mpp->waiter) - ((struct event_thread *)mpp->waiter)->mpp = NULL; --#endif - - free_pathvec(mpp->paths, free_paths); - free_pgvec(mpp->pg, free_paths); -@@ -364,15 +362,27 @@ pathcount (struct multipath * mpp, int state) - int count = 0; - int i; - -- vector_foreach_slot (mpp->pg, pgp, i) -- count += pathcountgr(pgp, state); -- -+ if (mpp->pg) { -+ vector_foreach_slot (mpp->pg, pgp, i) -+ count += pathcountgr(pgp, state); -+ } - return count; - } - - struct path * - first_path (struct multipath * mpp) - { -- struct pathgroup * pgp = VECTOR_SLOT(mpp->pg, 0); -- return VECTOR_SLOT(pgp->paths, 0); -+ struct pathgroup * pgp; -+ if (!mpp->pg) -+ return NULL; -+ pgp = VECTOR_SLOT(mpp->pg, 0); -+ -+ return pgp?VECTOR_SLOT(pgp->paths, 0):NULL; -+} -+ -+extern void -+setup_feature(struct multipath * mpp, char *feature) -+{ -+ if (!strncmp(feature, "queue_if_no_path", 16)) -+ mpp->no_path_retry = NO_PATH_RETRY_QUEUE; - } -diff --git a/libmultipath/structs.h b/libmultipath/structs.h -index f821f87..85d5109 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -21,8 +21,7 @@ - #define NO_PATH_RETRY_FAIL -1 - #define NO_PATH_RETRY_QUEUE -2 - --#define PRIO_UNDEF -1 --#define PRIO_DEFAULT 1 -+#define MAX_FDS_UNLIMITED -1 - - enum free_path_switch { - KEEP_PATHS, -@@ -121,8 +120,7 @@ struct path { - int priority; - int pgindex; - char * getuid; -- char * getprio; -- int getprio_selected; -+ struct prio * prio; - struct checker checker; - struct multipath * mpp; - int fd; -@@ -213,6 +211,7 @@ struct path * first_path (struct multipath * mpp); - - int pathcountgr (struct pathgroup *, int); - int pathcount (struct multipath *, int); -+void setup_feature(struct multipath *, char *); - - extern char sysfs_path[PATH_SIZE]; - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 1cc6028..34b7669 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -2,20 +2,20 @@ - #include - #include - --#include -- -+#include "checkers.h" - #include "vector.h" - #include "defaults.h" - #include "debug.h" - #include "structs.h" - #include "structs_vec.h" -+#include "waiter.h" - #include "devmapper.h" - #include "dmparser.h" - #include "config.h" - #include "propsel.h" - #include "sysfs.h" - #include "discovery.h" --#include "waiter.h" -+#include "prio.h" - - /* - * creates or updates mpp->paths reading mpp->pg -@@ -62,7 +62,7 @@ adopt_paths (vector pathvec, struct multipath * mpp) - condlog(3, "%s: ownership set to %s", - pp->dev, mpp->alias); - pp->mpp = mpp; -- -+ - if (!mpp->paths && !(mpp->paths = vector_alloc())) - return 1; - -@@ -81,8 +81,7 @@ orphan_path (struct path * pp) - pp->mpp = NULL; - pp->dmstate = PSTATE_UNDEF; - pp->getuid = NULL; -- pp->getprio = NULL; -- pp->getprio_selected = 0; -+ pp->prio = NULL; - checker_put(&pp->checker); - if (pp->fd >= 0) - close(pp->fd); -@@ -112,9 +111,13 @@ set_multipath_wwid (struct multipath * mpp) - dm_get_uuid(mpp->alias, mpp->wwid); - } - --extern void --remove_map (struct multipath * mpp, struct vectors * vecs, -- stop_waiter_thread_func *stop_waiter, int purge_vec) -+#define KEEP_WAITER 0 -+#define STOP_WAITER 1 -+#define PURGE_VEC 1 -+ -+static void -+_remove_map (struct multipath * mpp, struct vectors * vecs, -+ int stop_waiter, int purge_vec) - { - int i; - -@@ -124,7 +127,7 @@ remove_map (struct multipath * mpp, struct vectors * vecs, - * stop the DM event waiter thread - */ - if (stop_waiter) -- stop_waiter(mpp, vecs); -+ stop_waiter_thread(mpp, vecs); - - /* - * clear references to this map -@@ -142,14 +145,26 @@ remove_map (struct multipath * mpp, struct vectors * vecs, - } - - extern void --remove_maps (struct vectors * vecs, -- stop_waiter_thread_func *stop_waiter) -+remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec) -+{ -+ _remove_map(mpp, vecs, KEEP_WAITER, purge_vec); -+} -+ -+extern void -+remove_map_and_stop_waiter (struct multipath * mpp, struct vectors * vecs, -+ int purge_vec) -+{ -+ _remove_map(mpp, vecs, STOP_WAITER, purge_vec); -+} -+ -+static void -+_remove_maps (struct vectors * vecs, int stop_waiter) - { - int i; - struct multipath * mpp; - - vector_foreach_slot (vecs->mpvec, mpp, i) { -- remove_map(mpp, vecs, stop_waiter, 1); -+ _remove_map(mpp, vecs, stop_waiter, 1); - i--; - } - -@@ -157,16 +172,31 @@ remove_maps (struct vectors * vecs, - vecs->mpvec = NULL; - } - -+extern void -+remove_maps (struct vectors * vecs) -+{ -+ _remove_maps(vecs, KEEP_WAITER); -+} -+ -+extern void -+remove_maps_and_stop_waiters (struct vectors * vecs) -+{ -+ _remove_maps(vecs, STOP_WAITER); -+} -+ - static struct hwentry * - extract_hwe_from_path(struct multipath * mpp) - { -- struct path * pp; -- struct pathgroup * pgp; -+ struct path * pp = NULL; -+ struct pathgroup * pgp = NULL; - -- pgp = VECTOR_SLOT(mpp->pg, 0); -- pp = VECTOR_SLOT(pgp->paths, 0); -+ if (mpp && mpp->pg) -+ pgp = VECTOR_SLOT(mpp->pg, 0); - -- return pp->hwe; -+ if (pgp && pgp->paths) -+ pp = VECTOR_SLOT(pgp->paths, 0); -+ -+ return pp?pp->hwe:NULL; - } - - static int -@@ -220,7 +250,8 @@ set_no_path_retry(struct multipath *mpp) - { - mpp->retry_tick = 0; - mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST); -- select_no_path_retry(mpp); -+ if (mpp->nr_active > 0) -+ select_no_path_retry(mpp); - - switch (mpp->no_path_retry) { - case NO_PATH_RETRY_UNDEF: -@@ -267,18 +298,17 @@ retry: - char new_alias[WWID_SIZE]; - - /* -- * detect an external rename of the multipath device -+ * detect an external rename of the multipath device - */ -- if (dm_get_name(mpp->wwid, DEFAULT_TARGET, new_alias)) { -+ if (dm_get_name(mpp->wwid, new_alias)) { - condlog(3, "%s multipath mapped device name has " - "changed from %s to %s", mpp->wwid, - mpp->alias, new_alias); - strcpy(mpp->alias, new_alias); --#if DAEMON -- if (mpp->waiter) -+ -+ if (mpp->waiter) - strncpy(((struct event_thread *)mpp->waiter)->mapname, - new_alias, WWID_SIZE); --#endif - goto retry; - } - condlog(0, "%s: failed to setup multipath", mpp->alias); -@@ -294,14 +324,13 @@ retry: - - return 0; - out: -- remove_map(mpp, vecs, NULL, 1); -+ remove_map(mpp, vecs, PURGE_VEC); - return 1; - } - - extern struct multipath * - add_map_without_path (struct vectors * vecs, -- int minor, char * alias, -- start_waiter_thread_func *start_waiter) -+ int minor, char * alias) - { - struct multipath * mpp = alloc_multipath(); - -@@ -315,18 +344,18 @@ add_map_without_path (struct vectors * vecs, - - if (adopt_paths(vecs->pathvec, mpp)) - goto out; -- -+ - if (!vector_alloc_slot(vecs->mpvec)) - goto out; - - vector_set_slot(vecs->mpvec, mpp); - -- if (start_waiter(mpp, vecs)) -+ if (start_waiter_thread(mpp, vecs)) - goto out; - - return mpp; - out: -- remove_map(mpp, vecs, NULL, 1); -+ remove_map(mpp, vecs, PURGE_VEC); - return NULL; - } - -@@ -359,7 +388,7 @@ add_map_with_path (struct vectors * vecs, - return mpp; - - out: -- remove_map(mpp, vecs, NULL, add_vec); -+ remove_map(mpp, vecs, PURGE_VEC); - return NULL; - } - -diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h -index 81d9eaa..19a2387 100644 ---- a/libmultipath/structs_vec.h -+++ b/libmultipath/structs_vec.h -@@ -2,16 +2,11 @@ - #define _STRUCTS_VEC_H - - struct vectors { --#if DAEMON - pthread_mutex_t *lock; --#endif - vector pathvec; - vector mpvec; - }; - --typedef void (stop_waiter_thread_func) (struct multipath *, struct vectors *); --typedef int (start_waiter_thread_func) (struct multipath *, struct vectors *); -- - void set_no_path_retry(struct multipath *mpp); - - int adopt_paths (vector pathvec, struct multipath * mpp); -@@ -23,14 +18,13 @@ int update_mpp_paths(struct multipath * mpp, vector pathvec); - int setup_multipath (struct vectors * vecs, struct multipath * mpp); - int update_multipath_strings (struct multipath *mpp, vector pathvec); - --void remove_map (struct multipath * mpp, struct vectors * vecs, -- stop_waiter_thread_func *stop_waiter, int purge_vec); --void remove_maps (struct vectors * vecs, -- stop_waiter_thread_func *stop_waiter); -+void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec); -+void remove_map_and_stop_waiter (struct multipath * mpp, struct vectors * vecs, int purge_vec); -+void remove_maps (struct vectors * vecs); -+void remove_maps_and_stop_waiters (struct vectors * vecs); - - struct multipath * add_map_without_path (struct vectors * vecs, -- int minor, char * alias, -- start_waiter_thread_func *start_waiter); -+ int minor, char * alias); - struct multipath * add_map_with_path (struct vectors * vecs, - struct path * pp, int add_vec); - int update_multipath (struct vectors *vecs, char *mapname); -diff --git a/libmultipath/switchgroup.c b/libmultipath/switchgroup.c -index 757543f..58b08f6 100644 ---- a/libmultipath/switchgroup.c -+++ b/libmultipath/switchgroup.c -@@ -2,21 +2,36 @@ - * Copyright (c) 2005 Christophe Varoqui - * Copyright (c) 2005 Edward Goggin, EMC - */ --#include -- -+#include "checkers.h" - #include "vector.h" - #include "structs.h" - #include "switchgroup.h" - -+extern void -+path_group_prio_update (struct pathgroup * pgp) -+{ -+ int i; -+ int priority = 0; -+ struct path * pp; -+ -+ if (!pgp->paths) { -+ pgp->priority = 0; -+ return; -+ } -+ vector_foreach_slot (pgp->paths, pp, i) { -+ if (pp->state != PATH_DOWN) -+ priority += pp->priority; -+ } -+ pgp->priority = priority; -+} -+ - extern int - select_path_group (struct multipath * mpp) - { -- int i, j; -+ int i; - int highest = 0; - int bestpg = 1; - struct pathgroup * pgp; -- struct path * pp; -- int priority; - - if (!mpp->pg) - return 1; -@@ -25,14 +40,7 @@ select_path_group (struct multipath * mpp) - if (!pgp->paths) - continue; - -- priority = 0; -- -- vector_foreach_slot (pgp->paths, pp, j) { -- if (pp->state != PATH_DOWN) -- priority += pp->priority; -- } -- pgp->priority = priority; -- -+ path_group_prio_update(pgp); - if (pgp->priority > highest) { - highest = pgp->priority; - bestpg = i + 1; -diff --git a/libmultipath/switchgroup.h b/libmultipath/switchgroup.h -index edf6f24..9365e2e 100644 ---- a/libmultipath/switchgroup.h -+++ b/libmultipath/switchgroup.h -@@ -1 +1,2 @@ -+void path_group_prio_update (struct pathgroup * pgp); - int select_path_group (struct multipath * mpp); -diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c -index b9621ac..9f11b95 100644 ---- a/libmultipath/sysfs.c -+++ b/libmultipath/sysfs.c -@@ -4,12 +4,12 @@ - * 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 version 2 of the License. -- * -+ * - * 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. -- * -+ * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -@@ -58,7 +58,7 @@ int sysfs_init(char *path, size_t len) - strlcpy(sysfs_path, path, len); - remove_trailing_chars(sysfs_path, '/'); - } else -- strlcpy(sysfs_path, "/sys", len); -+ strlcpy(sysfs_path, "/sys", sizeof(sysfs_path)); - dbg("sysfs_path='%s'", sysfs_path); - - INIT_LIST_HEAD(&attr_list); -@@ -80,6 +80,7 @@ void sysfs_cleanup(void) - } - - list_for_each_entry_safe(sysdev_loop, sysdev_temp, &sysfs_dev_list, node) { -+ list_del(&sysdev_loop->node); - free(sysdev_loop); - } - } -@@ -162,9 +163,23 @@ struct sysfs_device *sysfs_device_get(const char *devpath) - int len; - char *pos; - -+ /* we handle only these devpathes */ -+ if (devpath != NULL && -+ strncmp(devpath, "/devices/", 9) != 0 && -+ strncmp(devpath, "/subsystem/", 11) != 0 && -+ strncmp(devpath, "/module/", 8) != 0 && -+ strncmp(devpath, "/bus/", 5) != 0 && -+ strncmp(devpath, "/class/", 7) != 0 && -+ strncmp(devpath, "/block/", 7) != 0) { -+ dbg("invalid devpath '%s'", devpath); -+ return NULL; -+ } -+ - dbg("open '%s'", devpath); - strlcpy(devpath_real, devpath, sizeof(devpath_real)); - remove_trailing_chars(devpath_real, '/'); -+ if (devpath[0] == '\0' ) -+ return NULL; - - /* if we got a link, resolve it to the real device */ - strlcpy(path, sysfs_path, sizeof(path)); -@@ -174,24 +189,26 @@ struct sysfs_device *sysfs_device_get(const char *devpath) - dbg("stat '%s' failed: %s", path, strerror(errno)); - list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) { - if (strcmp(sysdev_loop->dev.devpath, devpath_real) == 0) { -- dbg("found vanished dev in cache '%s'", sysdev_loop->dev.devpath); -+ dbg("found vanished dev in cache '%s'", -+ sysdev_loop->dev.devpath); - return &sysdev_loop->dev; - } - } - return NULL; - } -+ - if (S_ISLNK(statbuf.st_mode)) { - if (sysfs_resolve_link(devpath_real, sizeof(devpath_real)) != 0) - return NULL; -- - } - - list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) { - if (strcmp(sysdev_loop->dev.devpath, devpath_real) == 0) { - dbg("found dev in cache '%s'", sysdev_loop->dev.devpath); -- dev = &sysdev_loop->dev; -+ dev = &sysdev_loop->dev; - } - } -+ - if(!dev) { - /* it is a new device */ - dbg("new device '%s'", devpath_real); -@@ -217,33 +234,25 @@ struct sysfs_device *sysfs_device_get(const char *devpath) - pos = strrchr(link_target, '/'); - if (pos != NULL) - strlcpy(dev->subsystem, &pos[1], sizeof(dev->subsystem)); -- } else if (strncmp(dev->devpath, "/class/", 7) == 0) { -- /* get subsystem from class dir */ -- strlcpy(dev->subsystem, &dev->devpath[7], sizeof(dev->subsystem)); -- pos = strchr(dev->subsystem, '/'); -- if (pos != NULL) -- pos[0] = '\0'; -- else -- dev->subsystem[0] = '\0'; -- } else if (strncmp(dev->devpath, "/block/", 7) == 0) { -- strlcpy(dev->subsystem, "block", sizeof(dev->subsystem)); -- } else if (strncmp(dev->devpath, "/devices/", 9) == 0) { -- /* get subsystem from "bus" link */ -- strlcpy(link_path, sysfs_path, sizeof(link_path)); -- strlcat(link_path, dev->devpath, sizeof(link_path)); -- strlcat(link_path, "/bus", sizeof(link_path)); -- len = readlink(link_path, link_target, sizeof(link_target)); -- if (len > 0) { -- link_target[len] = '\0'; -- dbg("bus link '%s' points to '%s'", link_path, link_target); -- pos = strrchr(link_target, '/'); -- if (pos != NULL) -- strlcpy(dev->subsystem, &pos[1], sizeof(dev->subsystem)); -- } - } else if (strstr(dev->devpath, "/drivers/") != NULL) { - strlcpy(dev->subsystem, "drivers", sizeof(dev->subsystem)); - } else if (strncmp(dev->devpath, "/module/", 8) == 0) { - strlcpy(dev->subsystem, "module", sizeof(dev->subsystem)); -+ } else if (strncmp(dev->devpath, "/subsystem/", 11) == 0) { -+ pos = strrchr(dev->devpath, '/'); -+ if (pos == &dev->devpath[10]) -+ strlcpy(dev->subsystem, "subsystem", -+ sizeof(dev->subsystem)); -+ } else if (strncmp(dev->devpath, "/class/", 7) == 0) { -+ pos = strrchr(dev->devpath, '/'); -+ if (pos == &dev->devpath[6]) -+ strlcpy(dev->subsystem, "subsystem", -+ sizeof(dev->subsystem)); -+ } else if (strncmp(dev->devpath, "/bus/", 5) == 0) { -+ pos = strrchr(dev->devpath, '/'); -+ if (pos == &dev->devpath[4]) -+ strlcpy(dev->subsystem, "subsystem", -+ sizeof(dev->subsystem)); - } - - /* get driver name */ -@@ -258,6 +267,7 @@ struct sysfs_device *sysfs_device_get(const char *devpath) - if (pos != NULL) - strlcpy(dev->driver, &pos[1], sizeof(dev->driver)); - } -+ - return dev; - } - -@@ -272,13 +282,6 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev) - if (dev->parent != NULL) - return dev->parent; - -- /* requesting a parent is only valid for devices */ -- if ((strncmp(dev->devpath, "/devices/", 9) != 0) && -- (strncmp(dev->devpath, "/subsystem/", 11) != 0) && -- (strncmp(dev->devpath, "/class/", 7) != 0) && -- (strncmp(dev->devpath, "/block/", 7) != 0)) -- return NULL; -- - strlcpy(parent_devpath, dev->devpath, sizeof(parent_devpath)); - dbg("'%s'", parent_devpath); - -@@ -288,20 +291,6 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev) - return NULL; - pos[0] = '\0'; - -- /* are we at the top level of /devices */ -- if (strcmp(parent_devpath, "/devices") == 0) { -- dbg("/devices top level"); -- return NULL; -- } -- -- /* at the subsystems top level we want to follow the old-style "device" link */ -- if (strncmp(parent_devpath, "/subsystem", 10) == 0) { -- pos = strrchr(parent_devpath, '/'); -- if (pos == &parent_devpath[10] || pos == parent_devpath || strcmp(pos, "/devices") == 0) { -- dbg("/subsystem top level, look for device link"); -- goto device_link; -- } -- } - if (strncmp(parent_devpath, "/class", 6) == 0) { - pos = strrchr(parent_devpath, '/'); - if (pos == &parent_devpath[6] || pos == parent_devpath) { -@@ -314,6 +303,11 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev) - goto device_link; - } - -+ /* are we at the top level? */ -+ pos = strrchr(parent_devpath, '/'); -+ if (pos == NULL || pos == parent_devpath) -+ return NULL; -+ - /* get parent and remember it */ - dev->parent = sysfs_device_get(parent_devpath); - return dev->parent; -@@ -375,6 +369,8 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) - - dbg("open '%s'/'%s'", devpath, attr_name); - sysfs_len = strlcpy(path_full, sysfs_path, sizeof(path_full)); -+ if(sysfs_len >= sizeof(path_full)) -+ sysfs_len = sizeof(path_full) - 1; - path = &path_full[sysfs_len]; - strlcat(path_full, devpath, sizeof(path_full)); - strlcat(path_full, "/", sizeof(path_full)); -@@ -419,8 +415,10 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) - link_target[len] = '\0'; - pos = strrchr(link_target, '/'); - if (pos != NULL) { -- dbg("cache '%s' with link value '%s'", path_full, value); -- strlcpy(attr->value_local, &pos[1], sizeof(attr->value_local)); -+ dbg("cache '%s' with link value '%s'", -+ path_full, value); -+ strlcpy(attr->value_local, &pos[1], -+ sizeof(attr->value_local)); - attr->value = attr->value_local; - } - } -@@ -438,7 +436,8 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) - /* read attribute value */ - fd = open(path_full, O_RDONLY); - if (fd < 0) { -- dbg("attribute '%s' does not exist", path_full); -+ dbg("attribute '%s' can not be opened: %s", -+ path_full, strerror(errno)); - goto out; - } - size = read(fd, value, sizeof(value)); -@@ -458,3 +457,95 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) - out: - return attr->value; - } -+ -+int sysfs_lookup_devpath_by_subsys_id(char *devpath_full, size_t len, -+ const char *subsystem, const char *id) -+{ -+ size_t sysfs_len; -+ char path_full[PATH_SIZE]; -+ char *path; -+ struct stat statbuf; -+ -+ sysfs_len = strlcpy(path_full, sysfs_path, sizeof(path_full)); -+ path = &path_full[sysfs_len]; -+ -+ if (strcmp(subsystem, "subsystem") == 0) { -+ strlcpy(path, "/subsystem/", sizeof(path_full) - sysfs_len); -+ strlcat(path, id, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ -+ strlcpy(path, "/bus/", sizeof(path_full) - sysfs_len); -+ strlcat(path, id, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ goto out; -+ -+ strlcpy(path, "/class/", sizeof(path_full) - sysfs_len); -+ strlcat(path, id, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ } -+ -+ if (strcmp(subsystem, "module") == 0) { -+ strlcpy(path, "/module/", sizeof(path_full) - sysfs_len); -+ strlcat(path, id, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ goto out; -+ } -+ -+ if (strcmp(subsystem, "drivers") == 0) { -+ char subsys[NAME_SIZE]; -+ char *driver; -+ -+ strlcpy(subsys, id, sizeof(subsys)); -+ driver = strchr(subsys, ':'); -+ if (driver != NULL) { -+ driver[0] = '\0'; -+ driver = &driver[1]; -+ strlcpy(path, "/subsystem/", sizeof(path_full) - sysfs_len); -+ strlcat(path, subsys, sizeof(path_full) - sysfs_len); -+ strlcat(path, "/drivers/", sizeof(path_full) - sysfs_len); -+ strlcat(path, driver, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ -+ strlcpy(path, "/bus/", sizeof(path_full) - sysfs_len); -+ strlcat(path, subsys, sizeof(path_full) - sysfs_len); -+ strlcat(path, "/drivers/", sizeof(path_full) - sysfs_len); -+ strlcat(path, driver, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ } -+ goto out; -+ } -+ -+ strlcpy(path, "/subsystem/", sizeof(path_full) - sysfs_len); -+ strlcat(path, subsystem, sizeof(path_full) - sysfs_len); -+ strlcat(path, "/devices/", sizeof(path_full) - sysfs_len); -+ strlcat(path, id, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ -+ strlcpy(path, "/bus/", sizeof(path_full) - sysfs_len); -+ strlcat(path, subsystem, sizeof(path_full) - sysfs_len); -+ strlcat(path, "/devices/", sizeof(path_full) - sysfs_len); -+ strlcat(path, id, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+ -+ strlcpy(path, "/class/", sizeof(path_full) - sysfs_len); -+ strlcat(path, subsystem, sizeof(path_full) - sysfs_len); -+ strlcat(path, "/", sizeof(path_full) - sysfs_len); -+ strlcat(path, id, sizeof(path_full) - sysfs_len); -+ if (stat(path_full, &statbuf) == 0) -+ goto found; -+out: -+ return 0; -+found: -+ if (S_ISLNK(statbuf.st_mode)) -+ sysfs_resolve_link(path, sizeof(path_full) - sysfs_len); -+ strlcpy(devpath_full, path, len); -+ return 1; -+} -diff --git a/libmultipath/uxsock.c b/libmultipath/uxsock.c -index abb9f85..a070943 100644 ---- a/libmultipath/uxsock.c -+++ b/libmultipath/uxsock.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - - #include "memory.h" -@@ -127,9 +128,23 @@ size_t read_all(int fd, void *buf, size_t len) - */ - int send_packet(int fd, const char *buf, size_t len) - { -- if (write_all(fd, &len, sizeof(len)) != sizeof(len)) return -1; -- if (write_all(fd, buf, len) != len) return -1; -- return 0; -+ int ret = 0; -+ sigset_t set, old; -+ -+ /* Block SIGPIPE */ -+ sigemptyset(&set); -+ sigaddset(&set, SIGPIPE); -+ pthread_sigmask(SIG_BLOCK, &set, &old); -+ -+ if (write_all(fd, &len, sizeof(len)) != sizeof(len)) -+ ret = -1; -+ if (!ret && write_all(fd, buf, len) != len) -+ ret = -1; -+ -+ /* And unblock it again */ -+ pthread_sigmask(SIG_SETMASK, &old, NULL); -+ -+ return ret; - } - - /* -diff --git a/libmultipath/waiter.h b/libmultipath/waiter.h -index 0223924..468ce5f 100644 ---- a/libmultipath/waiter.h -+++ b/libmultipath/waiter.h -@@ -1,8 +1,6 @@ - #ifndef _WAITER_H - #define _WAITER_H - --#if DAEMON -- - struct event_thread { - struct dm_task *dmt; - pthread_t thread; -@@ -19,5 +17,4 @@ 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 */ -diff --git a/multipath-tools.spec.in b/multipath-tools.spec.in -index 3caede6..b224779 100644 ---- a/multipath-tools.spec.in -+++ b/multipath-tools.spec.in -@@ -22,7 +22,6 @@ are : - * multipath : scan the system for multipathed devices, assembles them - and update the device-mapper's maps - * multipathd : wait for maps events, then execs multipath --* devmap-name : provides a meaningful device name to udev for devmaps - * kpartx : maps linear devmaps upon device partitions, which makes - multipath maps partionable - -@@ -41,20 +40,10 @@ rm -rf $RPM_BUILD_ROOT - - %files - %defattr(-,root,root,-) --%{prefix}/sbin/devmap_name - %{prefix}/sbin/multipath - %{prefix}/sbin/kpartx --%{prefix}/sbin/mpath_prio_alua --%{prefix}/sbin/mpath_prio_emc --%{prefix}/sbin/mpath_prio_random --%{prefix}/sbin/mpath_prio_balance_units --%{prefix}/sbin/mpath_prio_netapp --%{prefix}/sbin/mpath_prio_rdac --%{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 --%{prefix}/usr/share/man/man8/mpath_prio_alua.8.gz - %{prefix}/usr/share/man/man8/multipathd.8.gz - %{prefix}/sbin/multipathd - %{prefix}/etc/udev/rules.d/multipath.rules -diff --git a/multipath.conf.annotated b/multipath.conf.annotated -index e6cfe9a..49c9c5c 100644 ---- a/multipath.conf.annotated -+++ b/multipath.conf.annotated -@@ -38,7 +38,7 @@ - # # scope : multipath - # # desc : the default path grouping policy to apply to unspecified - # # multipaths --# # default : multibus -+# # default : failover - # # - # path_grouping_policy multibus - # -@@ -52,14 +52,14 @@ - # getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" - # - # # --# # name : prio_callout -+# # name : prio - # # scope : multipath --# # desc : the default program and args to callout to obtain a path -+# # desc : the default function to call to obtain a path - # # priority value. The ALUA bits in SPC-3 provide an --# # exploitable prio value for example. "none" is a valid value -+# # exploitable prio value for example. - # # default : (null) - # # --# #prio_callout "/bin/true" -+# #prio "alua" - # - # # - # # name : path_checker -@@ -80,6 +80,16 @@ - # rr_min_io 100 - # - # # -+# # name : max_fds -+# # scope : multipathd -+# # desc : Sets the maximum number of open file descriptors for the -+# # multipathd process. -+# # values : unlimited|n > 0 -+# # default : None -+# # -+# max_fds 8192 -+# -+# # - # # name : rr_weight - # # scope : multipath - # # desc : if set to priorities the multipath configurator will assign -@@ -96,9 +106,9 @@ - # # 0 means immediate failback, values >0 means deffered failback - # # expressed in seconds. - # # values : manual|immediate|n > 0 --# # default : immediate -+# # default : manual - # # --# failback manual -+# failback immediate - # - # # - # # name : no_path_retry -@@ -219,9 +229,9 @@ - # # 0 means immediate failback, values >0 means deffered failback - # # expressed in seconds. - # # values : manual|immediate|n > 0 --# # default : immediate -+# # default : manual - # # --# failback manual -+# failback immediate - # - # # - # # name : no_path_retry -@@ -296,15 +306,14 @@ - # getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" - # - # # --# # name : prio_callout -+# # name : prio - # # scope : multipath --# # desc : the program and args to callout to obtain a path -+# # desc : the function to call to obtain a path - # # weight. Weights are summed for each path group to - # # determine the next PG to use case of failure. --# # "none" is a valid value. - # # default : no callout, all paths equals - # # --# prio_callout "/sbin/mpath_prio_balance_units %d" -+# prio "hp_sw" - # - # # - # # name : path_checker -@@ -331,7 +340,7 @@ - # # 0 means immediate failback, values >0 means deffered failback - # # expressed in seconds. - # # values : manual|immediate|n > 0 --# # default : immediate -+# # default : manual - # # - # failback 30 - # -diff --git a/multipath.conf.synthetic b/multipath.conf.synthetic -index 633d625..33f820b 100644 ---- a/multipath.conf.synthetic -+++ b/multipath.conf.synthetic -@@ -8,9 +8,10 @@ - # selector "round-robin 0" - # path_grouping_policy multibus - # getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" --# prio_callout /bin/true -+# prio const - # path_checker directio - # rr_min_io 100 -+# max_fds 8192 - # rr_weight priorities - # failback immediate - # no_path_retry fail -diff --git a/multipath/02_multipath b/multipath/02_multipath -index 067c582..467a7cb 100755 ---- a/multipath/02_multipath -+++ b/multipath/02_multipath -@@ -5,7 +5,6 @@ - # this tool is statically linked against klibc : no additional libs - # - cp /sbin/multipath $INITRDDIR/sbin --cp /sbin/devmap_name $INITRDDIR/sbin - cp /sbin/kpartx $INITRDDIR/sbin - - # -diff --git a/multipath/Makefile b/multipath/Makefile -index 4923b2f..2d74ffe 100644 ---- a/multipath/Makefile -+++ b/multipath/Makefile -@@ -1,52 +1,33 @@ - # Makefile - # - # Copyright (C) 2003 Christophe Varoqui, --BUILD = glibc -- -+# - include ../Makefile.inc - --OBJS = main.o $(MULTIPATHLIB)-$(BUILD).a $(CHECKERSLIB)-$(BUILD).a -+OBJS = main.o - --CFLAGS += -I$(multipathdir) -I$(checkersdir) --LDFLAGS += -laio -- --ifeq ($(strip $(BUILD)),klibc) -- OBJS += $(libdm) --else -- LDFLAGS += -ldevmapper --endif -+CFLAGS += -I$(multipathdir) -Wl,-rpath,$(libdir) -+LDFLAGS += -lpthread -ldevmapper -laio -ldl \ -+ -lmultipath -L$(multipathdir) - - EXEC = multipath - --all: $(BUILD) -+all: $(EXEC) - --prepare: -- make -C $(multipathdir) prepare -- rm -f core *.o *.gz -+$(EXEC): $(OBJS) -+ $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) - $(GZIP) $(EXEC).8 > $(EXEC).8.gz - $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz - --glibc: prepare $(OBJS) -- $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) -- --klibc: prepare $(OBJS) -- $(CC) -static -o $(EXEC) $(CRT0) $(OBJS) $(KLIBC) $(LIBGCC) -- --$(CHECKERSLIB)-$(BUILD).a: -- make -C $(checkersdir) BUILD=$(BUILD) $(BUILD) -- --$(MULTIPATHLIB)-$(BUILD).a: -- make -C $(multipathdir) BUILD=$(BUILD) $(BUILD) -- - install: -- install -d $(DESTDIR)$(bindir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ -- install -d $(DESTDIR)/etc/udev/rules.d -- install -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/ -- install -d $(DESTDIR)$(mandir) -- install -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -- install -d $(DESTDIR)$(man5dir) -- install -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d -+ $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/ -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) - - uninstall: - rm $(DESTDIR)/etc/udev/rules.d/multipath.rules -diff --git a/multipath/main.c b/multipath/main.c -index 815c307..4c65808 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -27,6 +27,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -48,6 +49,8 @@ - #include - #include - -+int logsink; -+ - static int - filter_pathvec (vector pathvec, char * refwwid) - { -@@ -72,34 +75,39 @@ static void - usage (char * progname) - { - fprintf (stderr, VERSION_STRING); -- fprintf (stderr, "Usage: %s\t[-v level] [-d] [-h|-l|-ll|-f|-F]\n", -- progname); -+ fprintf (stderr, "Usage:\n"); -+ fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname); -+ fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); -+ fprintf (stderr, " %s -F [-v lvl]\n", progname); -+ fprintf (stderr, " %s -h\n", progname); - fprintf (stderr, -- "\t\t\t[-p failover|multibus|group_by_serial|group_by_prio]\n" \ -- "\t\t\t[device]\n" \ -- "\n" \ -- "\t-v level\tverbosity level\n" \ -- "\t 0\t\t\tno output\n" \ -- "\t 1\t\t\tprint created devmap names only\n" \ -- "\t 2\t\t\tdefault verbosity\n" \ -- "\t 3\t\t\tprint debug information\n" \ -- "\t-h\t\tprint this usage text\n" \ -- "\t-b file\t\tbindings file location\n" \ -- "\t-d\t\tdry run, do not create or update devmaps\n" \ -- "\t-l\t\tshow multipath topology (sysfs and DM info)\n" \ -- "\t-ll\t\tshow multipath topology (maximum info)\n" \ -- "\t-f\t\tflush a multipath device map\n" \ -- "\t-F\t\tflush all multipath device maps\n" \ -- "\t-p policy\tforce all maps to specified policy :\n" \ -- "\t failover\t\t1 path per priority group\n" \ -- "\t multibus\t\tall paths in 1 priority group\n" \ -- "\t group_by_serial\t1 priority group per serial\n" \ -- "\t group_by_prio\t1 priority group per priority lvl\n" \ -- "\t group_by_node_name\t1 priority group per target node\n" \ -- "\n" \ -- "\tdevice\t\tlimit scope to the device's multipath\n" \ -- "\t\t\t(udev-style $DEVNAME reference, eg /dev/sdb\n" \ -- "\t\t\tor major:minor or a device map name)\n" \ -+ "\n" -+ "Where:\n" -+ " -h print this usage text\n" \ -+ " -l show multipath topology (sysfs and DM info)\n" \ -+ " -ll show multipath topology (maximum info)\n" \ -+ " -f flush a multipath device map\n" \ -+ " -F flush all multipath device maps\n" \ -+ " -d dry run, do not create or update devmaps\n" \ -+ " -r force devmap reload\n" \ -+ " -p policy failover|multibus|group_by_serial|group_by_prio\n" \ -+ " -b fil bindings file location\n" \ -+ " -p pol force all maps to specified path grouping policy :\n" \ -+ " . failover one path per priority group\n" \ -+ " . multibus all paths in one priority group\n" \ -+ " . group_by_serial one priority group per serial\n" \ -+ " . group_by_prio one priority group per priority lvl\n" \ -+ " . group_by_node_name one priority group per target node\n" \ -+ " -v lvl verbosity level\n" \ -+ " . 0 no output\n" \ -+ " . 1 print created devmap names only\n" \ -+ " . 2 default verbosity\n" \ -+ " . 3 print debug information\n" \ -+ " dev action limited to:\n" \ -+ " . multipath named 'dev' (ex: mpath0) or\n" \ -+ " . multipath whose wwid is 'dev' (ex: 60051..)\n" \ -+ " . multipath including the path named 'dev' (ex: /dev/sda)\n" \ -+ " . multipath including the path with maj:min 'dev' (ex: 8:0)\n" \ - ); - - exit(1); -@@ -149,7 +157,7 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid) - int i; - struct multipath * mpp; - -- if (dm_get_maps(curmp, DEFAULT_TARGET)) -+ if (dm_get_maps(curmp)) - return 1; - - vector_foreach_slot (curmp, mpp, i) { -@@ -280,7 +288,7 @@ configure (void) - if (conf->verbosity > 2) - print_all_paths(pathvec, 1); - -- get_path_layout(pathvec); -+ get_path_layout(pathvec, 1); - - if (get_dm_mpvec(curmp, pathvec, refwwid)) - goto out; -@@ -295,7 +303,7 @@ configure (void) - /* - * core logic entry point - */ -- r = coalesce_paths(&vecs, NULL, NULL); -+ r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload); - - out: - if (refwwid) -@@ -320,17 +328,25 @@ main (int argc, char *argv[]) - exit(1); - } - -- if (dm_prereq(DEFAULT_TARGET)) -+ if (dm_prereq()) - exit(1); - - if (load_config(DEFAULT_CONFIGFILE)) - exit(1); - -+ if (init_checkers()) { -+ condlog(0, "failed to initialize checkers"); -+ exit(1); -+ } -+ if (init_prio()) { -+ condlog(0, "failed to initialize prioritizers"); -+ exit(1); -+ } - if (sysfs_init(conf->sysfs_dir, FILE_NAME_SIZE)) { - condlog(0, "multipath tools need sysfs mounted"); - exit(1); - } -- while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:")) != EOF ) { -+ while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:r")) != EOF ) { - switch(arg) { - case 1: printf("optarg : %s\n",optarg); - break; -@@ -373,6 +389,9 @@ main (int argc, char *argv[]) - usage(argv[0]); - } - break; -+ case 'r': -+ conf->force_reload = 1; -+ break; - case 'h': - usage(argv[0]); - case ':': -@@ -405,14 +424,14 @@ main (int argc, char *argv[]) - - if (conf->remove == FLUSH_ONE) { - if (conf->dev_type == DEV_DEVMAP) -- dm_flush_map(conf->dev, DEFAULT_TARGET); -+ dm_flush_map(conf->dev); - else - condlog(0, "must provide a map name to remove"); - - goto out; - } - else if (conf->remove == FLUSH_ALL) { -- dm_flush_maps(DEFAULT_TARGET); -+ dm_flush_maps(); - goto out; - } - while ((r = configure()) < 0) -@@ -420,9 +439,17 @@ main (int argc, char *argv[]) - - out: - sysfs_cleanup(); -- free_config(conf); - dm_lib_release(); - dm_lib_exit(); -+ -+ /* -+ * Freeing config must be done after dm_lib_exit(), because -+ * the logging function (dm_write_log()), which is called there, -+ * references the config. -+ */ -+ free_config(conf); -+ conf = NULL; -+ - #ifdef _DEBUG_ - dbg_free_final(NULL); - #endif -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index c8ab6b0..c66d7fc 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -374,6 +374,15 @@ section: - .RE - .PD - .LP -+.SH "KNOWN ISSUES" -+The usage of -+.B queue_if_no_path -+option can lead to -+.B D state -+processes being hung and not killable in situations where all the paths to the LUN go offline. -+It is advisable to use the -+.B no_path_retry -+option instead. - .SH "SEE ALSO" - .BR udev (8), - .BR dmsetup (8) -diff --git a/multipathd/Makefile b/multipathd/Makefile -index b430b94..b1af76c 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -1,4 +1,3 @@ --BUILD = glibc - EXEC = multipathd - - include ../Makefile.inc -@@ -6,8 +5,9 @@ include ../Makefile.inc - # - # basic flags setting - # --CFLAGS += -DDAEMON -I$(multipathdir) -I$(checkersdir) --LDFLAGS = -lpthread -ldevmapper -lreadline -lncurses -laio -+CFLAGS += -I$(multipathdir) -Wl,-rpath,$(libdir) -+LDFLAGS += -lpthread -ldevmapper -lreadline -lncurses -laio -ldl \ -+ -lmultipath -L$(multipathdir) - - # - # debuging stuff -@@ -19,36 +19,24 @@ LDFLAGS = -lpthread -ldevmapper -lreadline -lncurses -laio - # - # object files - # --OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o \ -- $(MULTIPATHLIB)-glibc.a $(CHECKERSLIB)-glibc.a \ -+OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o - - - # - # directives - # --all : $(BUILD) -+all : $(EXEC) - --glibc: $(EXEC) -- --klibc: -- $(MAKE) BUILD=glibc glibc -- --$(EXEC): clean $(OBJS) -- $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) -+$(EXEC): $(OBJS) -+ $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXEC) $(OBJS) - $(GZIP) $(EXEC).8 > $(EXEC).8.gz - --$(CHECKERSLIB)-glibc.a: -- $(MAKE) -C $(checkersdir) BUILD=glibc glibc -- --$(MULTIPATHLIB)-glibc.a: -- $(MAKE) -C $(multipathdir) DAEMON=1 BUILD=glibc glibc -- - install: -- install -d $(DESTDIR)$(bindir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) -- install -d $(DESTDIR)$(rcdir) -- install -d $(DESTDIR)$(mandir) -- install -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) - - uninstall: - rm -f $(DESTDIR)$(bindir)/$(EXEC) -@@ -56,6 +44,5 @@ uninstall: - rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz - - clean: -- $(MAKE) -C $(multipathdir) prepare DAEMON=1 - rm -f core *.o $(EXEC) *.gz - -diff --git a/multipathd/cli.c b/multipathd/cli.c -index d786eef..7eaac73 100644 ---- a/multipathd/cli.c -+++ b/multipathd/cli.c -@@ -3,6 +3,7 @@ - */ - #include - #include -+#include - #include - #include - #include -@@ -168,6 +169,7 @@ load_keys (void) - r += add_key(keys, "config", CONFIG, 0); - r += add_key(keys, "blacklist", BLACKLIST, 0); - r += add_key(keys, "devices", DEVICES, 0); -+ r += add_key(keys, "format", FMT, 1); - - if (r) { - free_keys(keys); -@@ -210,13 +212,17 @@ find_key (const char * str) - static int - get_cmdvec (char * cmd, vector *v) - { -- int fwd = 1; -+ int i; - int r = 0; -- char * p = cmd; -+ int get_param = 0; - char * buff; - struct key * kw = NULL; - struct key * cmdkw = NULL; -- vector cmdvec; -+ vector cmdvec, strvec; -+ -+ strvec = alloc_strvec(cmd); -+ if (!strvec) -+ return 0; - - cmdvec = vector_alloc(); - *v = cmdvec; -@@ -224,21 +230,20 @@ get_cmdvec (char * cmd, vector *v) - if (!cmdvec) - return E_NOMEM; - -- while (fwd) { -- fwd = get_word(p, &buff); -- -- if (!buff) -- break; -- -- p += fwd; -+ vector_foreach_slot(strvec, buff, i) { -+ if (*buff == '"') -+ continue; -+ if (get_param) { -+ get_param = 0; -+ cmdkw->param = strdup(buff); -+ continue; -+ } - kw = find_key(buff); -- FREE(buff); -- -- if (!kw) -- return E_SYNTAX; -- -+ if (!kw) { -+ r = E_SYNTAX; -+ goto out; -+ } - cmdkw = alloc_key(); -- - if (!cmdkw) { - r = E_NOMEM; - goto out; -@@ -251,23 +256,17 @@ get_cmdvec (char * cmd, vector *v) - vector_set_slot(cmdvec, cmdkw); - cmdkw->code = kw->code; - cmdkw->has_param = kw->has_param; -- -- if (kw->has_param) { -- if (*p == '\0') -- goto out; -- -- fwd = get_word(p, &buff); -- -- if (!buff) -- return E_NOPARM; -- -- p += fwd; -- cmdkw->param = buff; -- } -+ if (kw->has_param) -+ get_param = 1; -+ } -+ if (get_param) { -+ r = E_NOPARM; -+ goto out; - } - return 0; - - out: -+ free_strvec(strvec); - free_keys(cmdvec); - *v = NULL; - return r; -@@ -406,6 +405,7 @@ cli_init (void) { - return 1; - - add_handler(LIST+PATHS, NULL); -+ add_handler(LIST+PATHS+FMT, NULL); - add_handler(LIST+MAPS, NULL); - add_handler(LIST+MAPS+STATUS, NULL); - add_handler(LIST+MAPS+STATS, NULL); -diff --git a/multipathd/cli.h b/multipathd/cli.h -index a2397df..8c83eab 100644 ---- a/multipathd/cli.h -+++ b/multipathd/cli.h -@@ -19,6 +19,7 @@ enum { - __CONFIG, - __BLACKLIST, - __DEVICES, -+ __FMT, - }; - - #define LIST (1 << __LIST) -@@ -41,6 +42,7 @@ enum { - #define CONFIG (1 << __CONFIG) - #define BLACKLIST (1 << __BLACKLIST) - #define DEVICES (1 << __DEVICES) -+#define FMT (1 << __FMT) - - #define INITIAL_REPLY_LEN 1000 - -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index 7bae02a..c84805a 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -28,7 +28,7 @@ show_paths (char ** r, int * len, struct vectors * vecs, char * style) - unsigned int maxlen = INITIAL_REPLY_LEN; - int again = 1; - -- get_path_layout(vecs->pathvec); -+ get_path_layout(vecs->pathvec, 1); - reply = MALLOC(maxlen); - - while (again) { -@@ -94,7 +94,7 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs) - unsigned int maxlen = INITIAL_REPLY_LEN; - int again = 1; - -- get_path_layout(vecs->pathvec); -+ get_path_layout(vecs->pathvec, 0); - reply = MALLOC(maxlen); - - while (again) { -@@ -185,13 +185,24 @@ cli_list_paths (void * v, char ** reply, int * len, void * data) - } - - int -+cli_list_paths_fmt (void * v, char ** reply, int * len, void * data) -+{ -+ struct vectors * vecs = (struct vectors *)data; -+ char * fmt = get_keyparam(v, FMT); -+ -+ condlog(3, "list paths (operator)"); -+ -+ return show_paths(reply, len, vecs, fmt); -+} -+ -+int - cli_list_map_topology (void * v, char ** reply, int * len, void * data) - { - struct multipath * mpp; - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, MAP); - -- get_path_layout(vecs->pathvec); -+ get_path_layout(vecs->pathvec, 0); - mpp = find_mp_by_str(vecs->mpvec, param); - - if (!mpp) -@@ -222,7 +233,7 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style) - unsigned int maxlen = INITIAL_REPLY_LEN; - int again = 1; - -- get_multipath_layout(vecs->mpvec); -+ get_multipath_layout(vecs->mpvec, 1); - reply = MALLOC(maxlen); - - while (again) { -@@ -431,6 +442,7 @@ cli_reinstate(void * v, char ** reply, int * len, void * data) - condlog(2, "%s: reinstate path %s (operator)", - pp->mpp->alias, pp->dev_t); - -+ checker_enable(&pp->checker); - return dm_reinstate_path(pp->mpp->alias, pp->dev_t); - } - -@@ -440,6 +452,7 @@ cli_fail(void * v, char ** reply, int * len, void * data) - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, PATH); - struct path * pp; -+ int r; - - pp = find_path_by_dev(vecs->pathvec, param); - -@@ -452,7 +465,13 @@ cli_fail(void * v, char ** reply, int * len, void * data) - condlog(2, "%s: fail path %s (operator)", - pp->mpp->alias, pp->dev_t); - -- return dm_fail_path(pp->mpp->alias, pp->dev_t); -+ r = dm_fail_path(pp->mpp->alias, pp->dev_t); -+ /* -+ * Suspend path checking to avoid auto-reinstating the path -+ */ -+ if (!r) -+ checker_disable(&pp->checker); -+ return r; - } - - int -diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h -index 863694b..a688481 100644 ---- a/multipathd/cli_handlers.h -+++ b/multipathd/cli_handlers.h -@@ -1,4 +1,5 @@ - int cli_list_paths (void * v, char ** reply, int * len, void * data); -+int cli_list_paths_fmt (void * v, char ** reply, int * len, void * data); - int cli_list_maps (void * v, char ** reply, int * len, void * data); - int cli_list_maps_status (void * v, char ** reply, int * len, void * data); - int cli_list_maps_stats (void * v, char ** reply, int * len, void * data); -diff --git a/multipathd/main.c b/multipathd/main.c -index da5fd8f..8d74cb9 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -12,6 +12,8 @@ - #include - #include - #include -+#include -+#include - - /* - * libcheckers -@@ -43,6 +45,7 @@ - #include - #include - #include -+#include - - #include "main.h" - #include "pidfile.h" -@@ -62,6 +65,8 @@ - pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER; - pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER; - -+int logsink; -+ - /* - * global copy of vecs for use in sig handlers - */ -@@ -116,7 +121,7 @@ coalesce_maps(struct vectors *vecs, vector nmpv) - * remove all current maps not allowed by the - * current configuration - */ -- if (dm_flush_map(ompp->alias, DEFAULT_TARGET)) { -+ if (dm_flush_map(ompp->alias)) { - condlog(0, "%s: unable to flush devmap", - ompp->alias); - /* -@@ -135,7 +140,7 @@ coalesce_maps(struct vectors *vecs, vector nmpv) - } - else { - dm_lib_release(); -- condlog(3, "%s devmap removed", ompp->alias); -+ condlog(2, "%s devmap removed", ompp->alias); - } - } - } -@@ -149,6 +154,9 @@ sync_map_state(struct multipath *mpp) - struct path *pp; - unsigned int i, j; - -+ if (!mpp->pg) -+ return; -+ - vector_foreach_slot (mpp->pg, pgp, i){ - vector_foreach_slot (pgp->paths, pp, j){ - if (pp->state <= PATH_UNCHECKED) -@@ -183,7 +191,7 @@ flush_map(struct multipath * mpp, struct vectors * vecs) - * clear references to this map before flushing so we can ignore - * the spurious uevent we may generate with the dm_flush_map call below - */ -- if (dm_flush_map(mpp->alias, DEFAULT_TARGET)) { -+ if (dm_flush_map(mpp->alias)) { - /* - * May not really be an error -- if the map was already flushed - * from the device mapper by dmsetup(8) for instance. -@@ -193,11 +201,11 @@ flush_map(struct multipath * mpp, struct vectors * vecs) - } - else { - dm_lib_release(); -- condlog(3, "%s: devmap removed", mpp->alias); -+ condlog(2, "%s: devmap removed", mpp->alias); - } - - orphan_paths(vecs->pathvec, mpp); -- remove_map(mpp, vecs, stop_waiter_thread, 1); -+ remove_map_and_stop_waiter(mpp, vecs, 1); - - return 0; - } -@@ -232,7 +240,7 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) - - map_present = dm_map_present(alias); - -- if (map_present && dm_type(alias, DEFAULT_TARGET) <= 0) { -+ if (map_present && dm_type(alias, TGT_MPATH) <= 0) { - condlog(4, "%s: not a multipath map", alias); - return 0; - } -@@ -253,21 +261,20 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) - /* - * now we can register the map - */ -- if (map_present && (mpp = add_map_without_path(vecs, minor, alias, -- start_waiter_thread))) { -+ if (map_present && (mpp = add_map_without_path(vecs, minor, alias))) { - sync_map_state(mpp); -- condlog(3, "%s: devmap %s added", alias, dev->kernel); -+ condlog(2, "%s: devmap %s added", alias, dev->kernel); - return 0; - } - refwwid = get_refwwid(dev->kernel, DEV_DEVMAP, vecs->pathvec); - - if (refwwid) { -- r = coalesce_paths(vecs, NULL, refwwid); -+ r = coalesce_paths(vecs, NULL, refwwid, 0); - dm_lib_release(); - } - - if (!r) -- condlog(3, "%s: devmap %s added", alias, dev->kernel); -+ condlog(2, "%s: devmap %s added", alias, dev->kernel); - else - condlog(0, "%s: uev_add_map %s failed", alias, dev->kernel); - -@@ -290,7 +297,7 @@ ev_remove_map (char * devname, struct vectors * vecs) - mpp = find_mp_by_str(vecs->mpvec, devname); - - if (!mpp) { -- condlog(3, "%s: devmap not registered, can't remove", -+ condlog(2, "%s: devmap not registered, can't remove", - devname); - return 0; - } -@@ -368,7 +375,7 @@ ev_add_path (char * devname, struct vectors * vecs) - condlog(0, "%s: failed to get path uid", devname); - return 1; /* leave path added to pathvec */ - } -- if (filter_path(conf, pp)){ -+ if (filter_path(conf, pp) > 0){ - int i = find_slot(vecs->pathvec, (void *)pp); - if (i != -1) - vector_del_slot(vecs->pathvec, i); -@@ -431,11 +438,11 @@ rescan: - start_waiter_thread(mpp, vecs)) - goto out; - -- condlog(3, "%s path added to devmap %s", devname, mpp->alias); -+ condlog(2, "%s path added to devmap %s", devname, mpp->alias); - return 0; - - out: -- remove_map(mpp, vecs, NULL, 1); -+ remove_map(mpp, vecs, 1); - return 1; - } - -@@ -457,8 +464,7 @@ ev_remove_path (char * devname, struct vectors * vecs) - { - struct multipath * mpp; - struct path * pp; -- int i; -- int rm_path = 1; -+ int i, retval = 0; - - pp = find_path_by_dev(vecs->pathvec, devname); - -@@ -468,100 +474,81 @@ ev_remove_path (char * devname, struct vectors * vecs) - } - - /* -- * avoid referring to the map of an orphanned path -+ * avoid referring to the map of an orphaned path - */ - if ((mpp = pp->mpp)) { -+ /* -+ * transform the mp->pg vector of vectors of paths -+ * into a mp->params string to feed the device-mapper -+ */ -+ if (update_mpp_paths(mpp, vecs->pathvec)) { -+ condlog(0, "%s: failed to update paths", -+ mpp->alias); -+ goto out; -+ } -+ if ((i = find_slot(mpp->paths, (void *)pp)) != -1) -+ vector_del_slot(mpp->paths, i); - - /* - * remove the map IFF removing the last path - */ -- if (pathcount(mpp, PATH_WILD) > 1) { -- vector rpvec = vector_alloc(); -+ if (VECTOR_SIZE(mpp->paths) == 0) { -+ char alias[WWID_SIZE]; - - /* -- * transform the mp->pg vector of vectors of paths -- * into a mp->params string to feed the device-mapper -+ * flush_map will fail if the device is open - */ -- update_mpp_paths(mpp, vecs->pathvec); -- if ((i = find_slot(mpp->paths, (void *)pp)) != -1) -- vector_del_slot(mpp->paths, i); -- -- if (VECTOR_SIZE(mpp->paths) == 0) { -- char alias[WWID_SIZE]; -- -- /* -- * flush_map will fail if the device is open -- */ -- strncpy(alias, mpp->alias, WWID_SIZE); -- if (flush_map(mpp, vecs)) -- rm_path = 0; -- else -- condlog(3, "%s: removed map after removing" -- " multiple paths", alias); -- } -- else { -- if (setup_map(mpp)) { -- condlog(0, "%s: failed to setup map for" -- " removal of path %s", mpp->alias, devname); -- free_pathvec(rpvec, KEEP_PATHS); -- goto out; -- } -- /* -- * reload the map -- */ -- mpp->action = ACT_RELOAD; -- if (domap(mpp) <= 0) { -- condlog(0, "%s: failed in domap for " -- "removal of path %s", -- mpp->alias, devname); -- /* -- * Delete path from pathvec so that -- * update_mpp_paths wont find it later -- * when/if another path is removed. -- */ -- if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1) -- vector_del_slot(vecs->pathvec, i); -- free_path(pp); -- return 1; -- } -- /* -- * update our state from kernel -- */ -- if (setup_multipath(vecs, mpp)) { -- free_pathvec(rpvec, KEEP_PATHS); -- goto out; -- } -- sync_map_state(mpp); -- -- condlog(3, "%s: path removed from map %s", -- devname, mpp->alias); -+ strncpy(alias, mpp->alias, WWID_SIZE); -+ if (!flush_map(mpp, vecs)) { -+ condlog(2, "%s: removed map after" -+ " removing all paths", -+ alias); -+ free_path(pp); -+ return 0; - } -- free_pathvec(rpvec, KEEP_PATHS); -+ /* -+ * Not an error, continue -+ */ - } -- else { -- char alias[WWID_SIZE]; - -+ if (setup_map(mpp)) { -+ condlog(0, "%s: failed to setup map for" -+ " removal of path %s", mpp->alias, -+ devname); -+ goto out; -+ } -+ /* -+ * reload the map -+ */ -+ mpp->action = ACT_RELOAD; -+ if (domap(mpp) <= 0) { -+ condlog(0, "%s: failed in domap for " -+ "removal of path %s", -+ mpp->alias, devname); -+ retval = 1; -+ } else { - /* -- * flush_map will fail if the device is open -+ * update our state from kernel - */ -- strncpy(alias, mpp->alias, WWID_SIZE); -- if (flush_map(mpp, vecs)) -- rm_path = 0; -- else -- condlog(3, "%s: removed map", alias); -+ if (setup_multipath(vecs, mpp)) { -+ goto out; -+ } -+ sync_map_state(mpp); -+ -+ condlog(2, "%s: path removed from map %s", -+ devname, mpp->alias); - } - } - -- if (rm_path) { -- if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1) -- vector_del_slot(vecs->pathvec, i); -- free_path(pp); -- } -+ if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1) -+ vector_del_slot(vecs->pathvec, i); - -- return 0; -+ free_path(pp); -+ -+ return retval; - - out: -- remove_map(mpp, vecs, stop_waiter_thread, 1); -+ remove_map_and_stop_waiter(mpp, vecs, 1); - return 1; - } - -@@ -571,7 +558,7 @@ map_discovery (struct vectors * vecs) - struct multipath * mpp; - unsigned int i; - -- if (dm_get_maps(vecs->mpvec, "multipath")) -+ if (dm_get_maps(vecs->mpvec)) - return 1; - - vector_foreach_slot (vecs->mpvec, mpp, i) -@@ -704,6 +691,7 @@ uxlsnrloop (void * ap) - return NULL; - - set_handler_callback(LIST+PATHS, cli_list_paths); -+ set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt); - set_handler_callback(LIST+MAPS, cli_list_maps); - set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status); - set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats); -@@ -809,7 +797,7 @@ mpvec_garbage_collector (struct vectors * vecs) - vector_foreach_slot (vecs->mpvec, mpp, i) { - if (mpp && mpp->alias && !dm_map_present(mpp->alias)) { - condlog(2, "%s: remove dead map", mpp->alias); -- remove_map(mpp, vecs, stop_waiter_thread, 1); -+ remove_map_and_stop_waiter(mpp, vecs, 1); - i--; - } - } -@@ -852,171 +840,182 @@ retry_count_tick(vector mpvec) - } - } - --static void * --checkerloop (void *ap) -+void -+check_path (struct vectors * vecs, struct path * pp) - { -- struct vectors *vecs; -- struct path *pp; -- int count = 0; - int newstate; -- unsigned int i; - -- mlockall(MCL_CURRENT | MCL_FUTURE); -- vecs = (struct vectors *)ap; -- condlog(2, "path checkers start up"); -+ if (!pp->mpp) -+ return; -+ -+ if (pp->tick && --pp->tick) -+ return; /* don't check this path yet */ - - /* -- * init the path check interval -+ * provision a next check soonest, -+ * in case we exit abnormaly from here - */ -- vector_foreach_slot (vecs->pathvec, pp, i) { -- pp->checkint = conf->checkint; -+ pp->tick = conf->checkint; -+ -+ if (!checker_selected(&pp->checker)) { -+ pathinfo(pp, conf->hwtable, DI_SYSFS); -+ select_checker(pp); - } -+ if (!checker_selected(&pp->checker)) { -+ condlog(0, "%s: checker is not set", pp->dev); -+ return; -+ } -+ /* -+ * Set checker in async mode. -+ * Honored only by checker implementing the said mode. -+ */ -+ checker_set_async(&pp->checker); - -- while (1) { -- pthread_cleanup_push(cleanup_lock, vecs->lock); -- lock(vecs->lock); -- condlog(4, "tick"); -+ newstate = checker_check(&pp->checker); - -- vector_foreach_slot (vecs->pathvec, pp, i) { -- if (!pp->mpp) -- continue; -+ if (newstate < 0) { -+ condlog(2, "%s: unusable path", pp->dev); -+ pathinfo(pp, conf->hwtable, 0); -+ return; -+ } -+ /* -+ * Async IO in flight. Keep the previous path state -+ * and reschedule as soon as possible -+ */ -+ if (newstate == PATH_PENDING) { -+ pp->tick = 1; -+ return; -+ } -+ if (newstate != pp->state) { -+ int oldstate = pp->state; -+ pp->state = newstate; -+ LOG_MSG(1, checker_message(&pp->checker)); - -- if (pp->tick && --pp->tick) -- continue; /* don't check this path yet */ -+ /* -+ * upon state change, reset the checkint -+ * to the shortest delay -+ */ -+ pp->checkint = conf->checkint; - -+ if (newstate == PATH_DOWN || newstate == PATH_SHAKY || -+ update_multipath_strings(pp->mpp, vecs->pathvec)) { - /* -- * provision a next check soonest, -- * in case we exit abnormaly from here -+ * proactively fail path in the DM - */ -- pp->tick = conf->checkint; -+ if (oldstate == PATH_UP || -+ oldstate == PATH_GHOST) -+ fail_path(pp, 1); -+ else -+ fail_path(pp, 0); - -- if (!checker_selected(&pp->checker)) { -- pathinfo(pp, conf->hwtable, DI_SYSFS); -- select_checker(pp); -- } -- if (!checker_selected(&pp->checker)) { -- condlog(0, "%s: checker is not set", pp->dev); -- continue; -- } - /* -- * Set checker in async mode. -- * Honored only by checker implementing the said mode. -+ * cancel scheduled failback - */ -- checker_set_async(&pp->checker); -+ pp->mpp->failback_tick = 0; -+ -+ pp->mpp->stat_path_failures++; -+ return; -+ } - -- newstate = checker_check(&pp->checker); -+ /* -+ * reinstate this path -+ */ -+ if (oldstate != PATH_UP && -+ oldstate != PATH_GHOST) -+ reinstate_path(pp, 1); -+ else -+ reinstate_path(pp, 0); - -- if (newstate < 0) { -- condlog(2, "%s: unusable path", pp->dev); -- pathinfo(pp, conf->hwtable, 0); -- continue; -- } -- /* -- * Async IO in flight. Keep the previous path state -- * and reschedule as soon as possible -- */ -- if (newstate == PATH_PENDING) { -- pp->tick = 1; -- continue; -- } -- if (newstate != pp->state) { -- int oldstate = pp->state; -- pp->state = newstate; -- LOG_MSG(1, checker_message(&pp->checker)); -+ /* -+ * schedule [defered] failback -+ */ -+ if (pp->mpp->pgfailback > 0) -+ pp->mpp->failback_tick = -+ pp->mpp->pgfailback + 1; -+ else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE && -+ need_switch_pathgroup(pp->mpp, 1)) -+ switch_pathgroup(pp->mpp); - -- /* -- * upon state change, reset the checkint -- * to the shortest delay -- */ -- pp->checkint = conf->checkint; -- -- if (newstate == PATH_DOWN || -- newstate == PATH_SHAKY || -- update_multipath_strings(pp->mpp, -- vecs->pathvec)) { -- /* -- * proactively fail path in the DM -- */ -- if (oldstate == PATH_UP || -- oldstate == PATH_GHOST) -- fail_path(pp, 1); -- else -- fail_path(pp, 0); -- -- /* -- * cancel scheduled failback -- */ -- pp->mpp->failback_tick = 0; -- -- pp->mpp->stat_path_failures++; -- continue; -- } -+ /* -+ * if at least one path is up in a group, and -+ * the group is disabled, re-enable it -+ */ -+ if (newstate == PATH_UP) -+ enable_group(pp); -+ } -+ else if (newstate == PATH_UP || newstate == PATH_GHOST) { -+ LOG_MSG(4, checker_message(&pp->checker)); -+ /* -+ * double the next check delay. -+ * max at conf->max_checkint -+ */ -+ if (pp->checkint < (conf->max_checkint / 2)) -+ pp->checkint = 2 * pp->checkint; -+ else -+ pp->checkint = conf->max_checkint; - -- /* -- * reinstate this path -- */ -- if (oldstate != PATH_UP && -- oldstate != PATH_GHOST) -- reinstate_path(pp, 1); -- else -- reinstate_path(pp, 0); -+ pp->tick = pp->checkint; -+ condlog(4, "%s: delay next check %is", -+ pp->dev_t, pp->tick); -+ } -+ else if (newstate == PATH_DOWN) -+ LOG_MSG(2, checker_message(&pp->checker)); - -- /* -- * schedule [defered] failback -- */ -- if (pp->mpp->pgfailback > 0) -- pp->mpp->failback_tick = -- pp->mpp->pgfailback + 1; -- else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE && -- need_switch_pathgroup(pp->mpp, 1)) -- switch_pathgroup(pp->mpp); -+ pp->state = newstate; - -- /* -- * if at least one path is up in a group, and -- * the group is disabled, re-enable it -- */ -- if (newstate == PATH_UP) -- enable_group(pp); -- } -- else if (newstate == PATH_UP || newstate == PATH_GHOST) { -- LOG_MSG(4, checker_message(&pp->checker)); -- /* -- * double the next check delay. -- * max at conf->max_checkint -- */ -- if (pp->checkint < (conf->max_checkint / 2)) -- pp->checkint = 2 * pp->checkint; -- else -- pp->checkint = conf->max_checkint; -- -- pp->tick = pp->checkint; -- condlog(4, "%s: delay next check %is", -- pp->dev_t, pp->tick); -- } -- else if (newstate == PATH_DOWN) -- LOG_MSG(2, checker_message(&pp->checker)); -+ /* -+ * path prio refreshing -+ */ -+ condlog(4, "path prio refresh"); -+ pathinfo(pp, conf->hwtable, DI_PRIO); - -- pp->state = newstate; -+ /* -+ * pathgroup failback policy -+ */ -+ if (need_switch_pathgroup(pp->mpp, 0)) { -+ if (pp->mpp->pgfailback > 0 && -+ pp->mpp->failback_tick <= 0) -+ pp->mpp->failback_tick = -+ pp->mpp->pgfailback + 1; -+ else if (pp->mpp->pgfailback == -+ -FAILBACK_IMMEDIATE) -+ switch_pathgroup(pp->mpp); -+ } -+} - -- /* -- * path prio refreshing -- */ -- condlog(4, "path prio refresh"); -- pathinfo(pp, conf->hwtable, DI_PRIO); -- -- if (need_switch_pathgroup(pp->mpp, 0)) { -- if (pp->mpp->pgfailback > 0 && -- pp->mpp->failback_tick <= 0) -- pp->mpp->failback_tick = -- pp->mpp->pgfailback + 1; -- else if (pp->mpp->pgfailback == -- -FAILBACK_IMMEDIATE) -- switch_pathgroup(pp->mpp); -+static void * -+checkerloop (void *ap) -+{ -+ struct vectors *vecs; -+ struct path *pp; -+ int count = 0; -+ unsigned int i; -+ -+ mlockall(MCL_CURRENT | MCL_FUTURE); -+ vecs = (struct vectors *)ap; -+ condlog(2, "path checkers start up"); -+ -+ /* -+ * init the path check interval -+ */ -+ vector_foreach_slot (vecs->pathvec, pp, i) { -+ pp->checkint = conf->checkint; -+ } -+ -+ while (1) { -+ pthread_cleanup_push(cleanup_lock, vecs->lock); -+ lock(vecs->lock); -+ condlog(4, "tick"); -+ -+ if (vecs->pathvec) { -+ vector_foreach_slot (vecs->pathvec, pp, i) { -+ check_path(vecs, pp); - } - } -- defered_failback_tick(vecs->mpvec); -- retry_count_tick(vecs->mpvec); -- -+ if (vecs->mpvec) { -+ defered_failback_tick(vecs->mpvec); -+ retry_count_tick(vecs->mpvec); -+ } - if (count) - count--; - else { -@@ -1054,7 +1053,7 @@ configure (struct vectors * vecs, int start_waiters) - path_discovery(vecs->pathvec, conf, DI_ALL); - - vector_foreach_slot (vecs->pathvec, pp, i){ -- if (filter_path(conf, pp)){ -+ if (filter_path(conf, pp) > 0){ - vector_del_slot(vecs->pathvec, i); - free_path(pp); - i--; -@@ -1068,7 +1067,7 @@ configure (struct vectors * vecs, int start_waiters) - /* - * create new set of maps & push changed ones into dm - */ -- if (coalesce_paths(vecs, mpvec, NULL)) -+ if (coalesce_paths(vecs, mpvec, NULL, 0)) - return 1; - - /* -@@ -1085,7 +1084,7 @@ configure (struct vectors * vecs, int start_waiters) - /* - * purge dm of old maps - */ -- remove_maps(vecs, NULL); -+ remove_maps(vecs); - - /* - * save new set of maps formed by considering current path state -@@ -1115,7 +1114,7 @@ reconfigure (struct vectors * vecs) - * free old map and path vectors ... they use old conf state - */ - if (VECTOR_SIZE(vecs->mpvec)) -- remove_maps(vecs, stop_waiter_thread); -+ remove_maps_and_stop_waiters(vecs); - - if (VECTOR_SIZE(vecs->pathvec)) - free_pathvec(vecs->pathvec, FREE_PATHS); -@@ -1265,6 +1264,15 @@ child (void * param) - if (load_config(DEFAULT_CONFIGFILE)) - exit(1); - -+ if (init_checkers()) { -+ condlog(0, "failed to initialize checkers"); -+ exit(1); -+ } -+ if (init_prio()) { -+ condlog(0, "failed to initialize prioritizers"); -+ exit(1); -+ } -+ - setlogmask(LOG_UPTO(conf->verbosity + 3)); - - /* -@@ -1275,6 +1283,21 @@ child (void * param) - conf->max_checkint = MAX_CHECKINT(conf->checkint); - } - -+ if (conf->max_fds) { -+ struct rlimit fd_limit; -+ if (conf->max_fds > 0) { -+ fd_limit.rlim_cur = conf->max_fds; -+ fd_limit.rlim_max = conf->max_fds; -+ } -+ else { -+ fd_limit.rlim_cur = RLIM_INFINITY; -+ fd_limit.rlim_max = RLIM_INFINITY; -+ } -+ if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) -+ condlog(0, "can't set open fds limit to %d : %s\n", -+ conf->max_fds, strerror(errno)); -+ } -+ - if (pidfile_create(DEFAULT_PIDFILE, getpid())) { - if (logsink) - log_thread_stop(); -@@ -1319,7 +1342,7 @@ child (void * param) - * exit path - */ - lock(vecs->lock); -- remove_maps(vecs, stop_waiter_thread); -+ remove_maps_and_stop_waiters(vecs); - free_pathvec(vecs->pathvec, FREE_PATHS); - - pthread_cancel(check_thr); -@@ -1340,8 +1363,6 @@ child (void * param) - vecs->lock = NULL; - FREE(vecs); - vecs = NULL; -- free_config(conf); -- conf = NULL; - - condlog(2, "--------shut down-------"); - -@@ -1351,6 +1372,14 @@ child (void * param) - dm_lib_release(); - dm_lib_exit(); - -+ /* -+ * Freeing config must be done after condlog() and dm_lib_exit(), -+ * because logging functions like dlog() and dm_write_log() -+ * reference the config. -+ */ -+ free_config(conf); -+ conf = NULL; -+ - #ifdef _DEBUG_ - dbg_free_final(NULL); - #endif -diff --git a/path_priority/pp_alua/LICENSE b/path_priority/pp_alua/LICENSE -deleted file mode 100644 -index 9e31bbf..0000000 ---- a/path_priority/pp_alua/LICENSE -+++ /dev/null -@@ -1,483 +0,0 @@ -- -- GNU LIBRARY GENERAL PUBLIC LICENSE -- Version 2, June 1991 -- -- Copyright (C) 1991 Free Software Foundation, Inc. -- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -- Everyone is permitted to copy and distribute verbatim copies -- of this license document, but changing it is not allowed. -- --[This is the first released version of the library GPL. It is -- numbered 2 because it goes with version 2 of the ordinary GPL.] -- -- Preamble -- -- The licenses for most software are designed to take away your --freedom to share and change it. By contrast, the GNU General Public --Licenses are intended to guarantee your freedom to share and change --free software--to make sure the software is free for all its users. -- -- This license, the Library General Public License, applies to some --specially designated Free Software Foundation software, and to any --other libraries whose authors decide to use it. You can use it for --your libraries, too. -- -- When we speak of free software, we are referring to freedom, not --price. Our General Public Licenses are designed to make sure that you --have the freedom to distribute copies of free software (and charge for --this service if you wish), that you receive source code or can get it --if you want it, that you can change the software or use pieces of it --in new free programs; and that you know you can do these things. -- -- To protect your rights, we need to make restrictions that forbid --anyone to deny you these rights or to ask you to surrender the rights. --These restrictions translate to certain responsibilities for you if --you distribute copies of the library, or if you modify it. -- -- For example, if you distribute copies of the library, whether gratis --or for a fee, you must give the recipients all the rights that we gave --you. You must make sure that they, too, receive or can get the source --code. If you link a program with the library, you must provide --complete object files to the recipients so that they can relink them --with the library, after making changes to the library and recompiling --it. And you must show them these terms so they know their rights. -- -- Our method of protecting your rights has two steps: (1) copyright --the library, and (2) offer you this license which gives you legal --permission to copy, distribute and/or modify the library. -- -- Also, for each distributor's protection, we want to make certain --that everyone understands that there is no warranty for this free --library. If the library is modified by someone else and passed on, we --want its recipients to know that what they have is not the original --version, so that any problems introduced by others will not reflect on --the original authors' reputations. -- -- Finally, any free program is threatened constantly by software --patents. We wish to avoid the danger that companies distributing free --software will individually obtain patent licenses, thus in effect --transforming the program into proprietary software. To prevent this, --we have made it clear that any patent must be licensed for everyone's --free use or not licensed at all. -- -- Most GNU software, including some libraries, is covered by the ordinary --GNU General Public License, which was designed for utility programs. This --license, the GNU Library General Public License, applies to certain --designated libraries. This license is quite different from the ordinary --one; be sure to read it in full, and don't assume that anything in it is --the same as in the ordinary license. -- -- The reason we have a separate public license for some libraries is that --they blur the distinction we usually make between modifying or adding to a --program and simply using it. Linking a program with a library, without --changing the library, is in some sense simply using the library, and is --analogous to running a utility program or application program. However, in --a textual and legal sense, the linked executable is a combined work, a --derivative of the original library, and the ordinary General Public License --treats it as such. -- -- Because of this blurred distinction, using the ordinary General --Public License for libraries did not effectively promote software --sharing, because most developers did not use the libraries. We --concluded that weaker conditions might promote sharing better. -- -- However, unrestricted linking of non-free programs would deprive the --users of those programs of all benefit from the free status of the --libraries themselves. This Library General Public License is intended to --permit developers of non-free programs to use free libraries, while --preserving your freedom as a user of such programs to change the free --libraries that are incorporated in them. (We have not seen how to achieve --this as regards changes in header files, but we have achieved it as regards --changes in the actual functions of the Library.) The hope is that this --will lead to faster development of free libraries. -- -- The precise terms and conditions for copying, distribution and --modification follow. Pay close attention to the difference between a --"work based on the library" and a "work that uses the library". The --former contains code derived from the library, while the latter only --works together with the library. -- -- Note that it is possible for a library to be covered by the ordinary --General Public License rather than by this special one. -- -- GNU LIBRARY GENERAL PUBLIC LICENSE -- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -- -- 0. This License Agreement applies to any software library which --contains a notice placed by the copyright holder or other authorized --party saying it may be distributed under the terms of this Library --General Public License (also called "this License"). Each licensee is --addressed as "you". -- -- A "library" means a collection of software functions and/or data --prepared so as to be conveniently linked with application programs --(which use some of those functions and data) to form executables. -- -- The "Library", below, refers to any such software library or work --which has been distributed under these terms. A "work based on the --Library" means either the Library or any derivative work under --copyright law: that is to say, a work containing the Library or a --portion of it, either verbatim or with modifications and/or translated --straightforwardly into another language. (Hereinafter, translation is --included without limitation in the term "modification".) -- -- "Source code" for a work means the preferred form of the work for --making modifications to it. For a library, complete source code means --all the source code for all modules it contains, plus any associated --interface definition files, plus the scripts used to control compilation --and installation of the library. -- -- Activities other than copying, distribution and modification are not --covered by this License; they are outside its scope. The act of --running a program using the Library is not restricted, and output from --such a program is covered only if its contents constitute a work based --on the Library (independent of the use of the Library in a tool for --writing it). Whether that is true depends on what the Library does --and what the program that uses the Library does. -- -- 1. You may copy and distribute verbatim copies of the Library's --complete source code as you receive it, in any medium, provided that --you conspicuously and appropriately publish on each copy an --appropriate copyright notice and disclaimer of warranty; keep intact --all the notices that refer to this License and to the absence of any --warranty; and distribute a copy of this License along with the --Library. -- -- You may charge a fee for the physical act of transferring a copy, --and you may at your option offer warranty protection in exchange for a --fee. -- -- 2. You may modify your copy or copies of the Library or any portion --of it, thus forming a work based on the Library, and copy and --distribute such modifications or work under the terms of Section 1 --above, provided that you also meet all of these conditions: -- -- a) The modified work must itself be a software library. -- -- b) You must cause the files modified to carry prominent notices -- stating that you changed the files and the date of any change. -- -- c) You must cause the whole of the work to be licensed at no -- charge to all third parties under the terms of this License. -- -- d) If a facility in the modified Library refers to a function or a -- table of data to be supplied by an application program that uses -- the facility, other than as an argument passed when the facility -- is invoked, then you must make a good faith effort to ensure that, -- in the event an application does not supply such function or -- table, the facility still operates, and performs whatever part of -- its purpose remains meaningful. -- -- (For example, a function in a library to compute square roots has -- a purpose that is entirely well-defined independent of the -- application. Therefore, Subsection 2d requires that any -- application-supplied function or table used by this function must -- be optional: if the application does not supply it, the square -- root function must still compute square roots.) -- --These requirements apply to the modified work as a whole. If --identifiable sections of that work are not derived from the Library, --and can be reasonably considered independent and separate works in --themselves, then this License, and its terms, do not apply to those --sections when you distribute them as separate works. But when you --distribute the same sections as part of a whole which is a work based --on the Library, the distribution of the whole must be on the terms of --this License, whose permissions for other licensees extend to the --entire whole, and thus to each and every part regardless of who wrote --it. -- --Thus, it is not the intent of this section to claim rights or contest --your rights to work written entirely by you; rather, the intent is to --exercise the right to control the distribution of derivative or --collective works based on the Library. -- --In addition, mere aggregation of another work not based on the Library --with the Library (or with a work based on the Library) on a volume of --a storage or distribution medium does not bring the other work under --the scope of this License. -- -- 3. You may opt to apply the terms of the ordinary GNU General Public --License instead of this License to a given copy of the Library. To do --this, you must alter all the notices that refer to this License, so --that they refer to the ordinary GNU General Public License, version 2, --instead of to this License. (If a newer version than version 2 of the --ordinary GNU General Public License has appeared, then you can specify --that version instead if you wish.) Do not make any other change in --these notices. -- -- Once this change is made in a given copy, it is irreversible for --that copy, so the ordinary GNU General Public License applies to all --subsequent copies and derivative works made from that copy. -- -- This option is useful when you wish to copy part of the code of --the Library into a program that is not a library. -- -- 4. You may copy and distribute the Library (or a portion or --derivative of it, under Section 2) in object code or executable form --under the terms of Sections 1 and 2 above provided that you accompany --it with the complete corresponding machine-readable source code, which --must be distributed under the terms of Sections 1 and 2 above on a --medium customarily used for software interchange. -- -- If distribution of object code is made by offering access to copy --from a designated place, then offering equivalent access to copy the --source code from the same place satisfies the requirement to --distribute the source code, even though third parties are not --compelled to copy the source along with the object code. -- -- 5. A program that contains no derivative of any portion of the --Library, but is designed to work with the Library by being compiled or --linked with it, is called a "work that uses the Library". Such a --work, in isolation, is not a derivative work of the Library, and --therefore falls outside the scope of this License. -- -- However, linking a "work that uses the Library" with the Library --creates an executable that is a derivative of the Library (because it --contains portions of the Library), rather than a "work that uses the --library". The executable is therefore covered by this License. --Section 6 states terms for distribution of such executables. -- -- When a "work that uses the Library" uses material from a header file --that is part of the Library, the object code for the work may be a --derivative work of the Library even though the source code is not. --Whether this is true is especially significant if the work can be --linked without the Library, or if the work is itself a library. The --threshold for this to be true is not precisely defined by law. -- -- If such an object file uses only numerical parameters, data --structure layouts and accessors, and small macros and small inline --functions (ten lines or less in length), then the use of the object --file is unrestricted, regardless of whether it is legally a derivative --work. (Executables containing this object code plus portions of the --Library will still fall under Section 6.) -- -- Otherwise, if the work is a derivative of the Library, you may --distribute the object code for the work under the terms of Section 6. --Any executables containing that work also fall under Section 6, --whether or not they are linked directly with the Library itself. -- -- 6. As an exception to the Sections above, you may also compile or --link a "work that uses the Library" with the Library to produce a --work containing portions of the Library, and distribute that work --under terms of your choice, provided that the terms permit --modification of the work for the customer's own use and reverse --engineering for debugging such modifications. -- -- You must give prominent notice with each copy of the work that the --Library is used in it and that the Library and its use are covered by --this License. You must supply a copy of this License. If the work --during execution displays copyright notices, you must include the --copyright notice for the Library among them, as well as a reference --directing the user to the copy of this License. Also, you must do one --of these things: -- -- a) Accompany the work with the complete corresponding -- machine-readable source code for the Library including whatever -- changes were used in the work (which must be distributed under -- Sections 1 and 2 above); and, if the work is an executable linked -- with the Library, with the complete machine-readable "work that -- uses the Library", as object code and/or source code, so that the -- user can modify the Library and then relink to produce a modified -- executable containing the modified Library. (It is understood -- that the user who changes the contents of definitions files in the -- Library will not necessarily be able to recompile the application -- to use the modified definitions.) -- -- b) Accompany the work with a written offer, valid for at -- least three years, to give the same user the materials -- specified in Subsection 6a, above, for a charge no more -- than the cost of performing this distribution. -- -- c) If distribution of the work is made by offering access to copy -- from a designated place, offer equivalent access to copy the above -- specified materials from the same place. -- -- d) Verify that the user has already received a copy of these -- materials or that you have already sent this user a copy. -- -- For an executable, the required form of the "work that uses the --Library" must include any data and utility programs needed for --reproducing the executable from it. However, as a special exception, --the source code distributed need not include anything that is normally --distributed (in either source or binary form) with the major --components (compiler, kernel, and so on) of the operating system on --which the executable runs, unless that component itself accompanies --the executable. -- -- It may happen that this requirement contradicts the license --restrictions of other proprietary libraries that do not normally --accompany the operating system. Such a contradiction means you cannot --use both them and the Library together in an executable that you --distribute. -- -- 7. You may place library facilities that are a work based on the --Library side-by-side in a single library together with other library --facilities not covered by this License, and distribute such a combined --library, provided that the separate distribution of the work based on --the Library and of the other library facilities is otherwise --permitted, and provided that you do these two things: -- -- a) Accompany the combined library with a copy of the same work -- based on the Library, uncombined with any other library -- facilities. This must be distributed under the terms of the -- Sections above. -- -- b) Give prominent notice with the combined library of the fact -- that part of it is a work based on the Library, and explaining -- where to find the accompanying uncombined form of the same work. -- -- 8. You may not copy, modify, sublicense, link with, or distribute --the Library except as expressly provided under this License. Any --attempt otherwise to copy, modify, sublicense, link with, or --distribute the Library is void, and will automatically terminate your --rights under this License. However, parties who have received copies, --or rights, from you under this License will not have their licenses --terminated so long as such parties remain in full compliance. -- -- 9. You are not required to accept this License, since you have not --signed it. However, nothing else grants you permission to modify or --distribute the Library or its derivative works. These actions are --prohibited by law if you do not accept this License. Therefore, by --modifying or distributing the Library (or any work based on the --Library), you indicate your acceptance of this License to do so, and --all its terms and conditions for copying, distributing or modifying --the Library or works based on it. -- -- 10. Each time you redistribute the Library (or any work based on the --Library), the recipient automatically receives a license from the --original licensor to copy, distribute, link with or modify the Library --subject to these terms and conditions. You may not impose any further --restrictions on the recipients' exercise of the rights granted herein. --You are not responsible for enforcing compliance by third parties to --this License. -- -- 11. If, as a consequence of a court judgment or allegation of patent --infringement or for any other reason (not limited to patent issues), --conditions are imposed on you (whether by court order, agreement or --otherwise) that contradict the conditions of this License, they do not --excuse you from the conditions of this License. If you cannot --distribute so as to satisfy simultaneously your obligations under this --License and any other pertinent obligations, then as a consequence you --may not distribute the Library at all. For example, if a patent --license would not permit royalty-free redistribution of the Library by --all those who receive copies directly or indirectly through you, then --the only way you could satisfy both it and this License would be to --refrain entirely from distribution of the Library. -- --If any portion of this section is held invalid or unenforceable under any --particular circumstance, the balance of the section is intended to apply, --and the section as a whole is intended to apply in other circumstances. -- --It is not the purpose of this section to induce you to infringe any --patents or other property right claims or to contest validity of any --such claims; this section has the sole purpose of protecting the --integrity of the free software distribution system which is --implemented by public license practices. Many people have made --generous contributions to the wide range of software distributed --through that system in reliance on consistent application of that --system; it is up to the author/donor to decide if he or she is willing --to distribute software through any other system and a licensee cannot --impose that choice. -- --This section is intended to make thoroughly clear what is believed to --be a consequence of the rest of this License. -- -- 12. If the distribution and/or use of the Library is restricted in --certain countries either by patents or by copyrighted interfaces, the --original copyright holder who places the Library under this License may add --an explicit geographical distribution limitation excluding those countries, --so that distribution is permitted only in or among countries not thus --excluded. In such case, this License incorporates the limitation as if --written in the body of this License. -- -- 13. The Free Software Foundation may publish revised and/or new --versions of the Library General Public License from time to time. --Such new versions will be similar in spirit to the present version, --but may differ in detail to address new problems or concerns. -- --Each version is given a distinguishing version number. If the Library --specifies a version number of this License which applies to it and --"any later version", you have the option of following the terms and --conditions either of that version or of any later version published by --the Free Software Foundation. If the Library does not specify a --license version number, you may choose any version ever published by --the Free Software Foundation. -- -- 14. If you wish to incorporate parts of the Library into other free --programs whose distribution conditions are incompatible with these, --write to the author to ask for permission. For software which is --copyrighted by the Free Software Foundation, write to the Free --Software Foundation; we sometimes make exceptions for this. Our --decision will be guided by the two goals of preserving the free status --of all derivatives of our free software and of promoting the sharing --and reuse of software generally. -- -- NO WARRANTY -- -- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO --WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. --EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR --OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY --KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE --IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR --PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE --LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME --THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. -- -- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN --WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY --AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU --FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR --CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE --LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING --RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A --FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF --SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH --DAMAGES. -- -- END OF TERMS AND CONDITIONS -- -- Appendix: How to Apply These Terms to Your New Libraries -- -- If you develop a new library, and you want it to be of the greatest --possible use to the public, we recommend making it free software that --everyone can redistribute and change. You can do so by permitting --redistribution under these terms (or, alternatively, under the terms of the --ordinary General Public License). -- -- To apply these terms, attach the following notices to the library. It is --safest to attach them to the start of each source file to most effectively --convey the exclusion of warranty; and each file should have at least the --"copyright" line and a pointer to where the full notice is found. -- -- -- Copyright (C) -- -- This library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Library General Public -- License as published by the Free Software Foundation; either -- version 2 of the License, or (at your option) any later version. -- -- This library 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 -- Library General Public License for more details. -- -- You should have received a copy of the GNU Library General Public -- License along with this library; if not, write to the Free -- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -- MA 02111-1307, USA -- --Also add information on how to contact you by electronic and paper mail. -- --You should also get your employer (if you work as a programmer) or your --school, if any, to sign a "copyright disclaimer" for the library, if --necessary. Here is a sample; alter the names: -- -- Yoyodyne, Inc., hereby disclaims all copyright interest in the -- library `Frob' (a library for tweaking knobs) written by James Random Hacker. -- -- , 1 April 1990 -- Ty Coon, President of Vice -- --That's all there is to it! -diff --git a/path_priority/pp_alua/Makefile b/path_priority/pp_alua/Makefile -deleted file mode 100644 -index 6f356a1..0000000 ---- a/path_priority/pp_alua/Makefile -+++ /dev/null -@@ -1,54 +0,0 @@ --#============================================================================== --# (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. --# --# Makefile --# --# Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. --# It determines the ALUA state of a device and prints a priority value to --# stdout. --# --# Author(s): Jan Kunigk --# S. Bader --# --# This file is released under the GPL. --#============================================================================== --EXEC = mpath_prio_alua --BUILD = glibc --DEBUG = 0 --DEBUG_DUMPHEX = 0 --OBJS = main.o rtpg.o --INSTALL = install -D -- --TOPDIR = ../.. -- --ifneq ($(shell ls $(TOPDIR)/Makefile.inc 2>/dev/null),) --include $(TOPDIR)/Makefile.inc --endif -- --CFLAGS += -DDEBUG=$(DEBUG) -- --all: $(BUILD) -- --glibc: $(OBJS) -- $(CC) -o $(EXEC) $(OBJS) $(LDFLAGS) -- --klibc: $(OBJS) -- $(CC) -static -o $(EXEC) $(OBJS) -- --install: $(EXEC) $(EXEC).8.gz -- $(INSTALL) -s -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) -- $(INSTALL) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)/$(EXEC).8.gz -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) -- rm $(DESTDIR)$(mandir)/$(EXEC).8.gz -- --clean: -- rm -f *.o *.gz $(EXEC) -- --$(EXEC).8.gz: $(EXEC).8 -- $(GZIP) $< >$@ -- --main.o: main.c rtpg.h spc3.h -- --rtpg.o: rtpg.c rtpg.h spc3.h -diff --git a/path_priority/pp_alua/main.c b/path_priority/pp_alua/main.c -deleted file mode 100644 -index ba8da99..0000000 ---- a/path_priority/pp_alua/main.c -+++ /dev/null -@@ -1,279 +0,0 @@ --/* -- * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -- * -- * main.c -- * -- * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -- * It determines the ALUA state of a device and prints a priority value to -- * stdout. -- * -- * Author(s): Jan Kunigk -- * S. Bader -- * -- * This file is released under the GPL. -- */ --#include --#include -- --#include --#include --#include --#include --#include --#include --#include -- --#include "rtpg.h" -- --#define ALUA_PRIO_SUCCESS 0 --#define ALUA_PRIO_INVALID_COMMANDLINE 1 --#define ALUA_PRIO_OPEN_FAILED 2 --#define ALUA_PRIO_NOT_SUPPORTED 3 --#define ALUA_PRIO_RTPG_FAILED 4 --#define ALUA_PRIO_GETAAS_FAILED 5 -- --#define ALUA_PRIO_MAJOR 0 --#define ALUA_PRIO_MINOR 6 -- --#define PRINT_ERROR(f, a...) \ -- if (verbose) \ -- fprintf(stderr, "ERROR: " f, ##a) --#define PRINT_VERBOSE(f, a...) \ -- if (verbose) \ -- printf(f, ##a) -- --char * devicename = NULL; --int verbose = 0; -- --char *basename(char *p) --{ -- char *r; -- -- for(r = p; *r != '\0'; r++); -- for(; r > p && *(r - 1) != '/'; r--); -- -- return r; --} -- --void --print_help(char *command) --{ -- printf("Usage: %s [ [...]]\n\n", -- basename(command)); -- printf("Options are:\n"); -- -- printf("\t-d \n"); -- printf("\t\tSets the directory prefix for relative path names and"); -- printf(" created\n\t\tpath names. (default = \"/dev\")\n"); -- -- printf("\t-h\n"); -- printf("\t\tPrint this help.\n"); -- -- printf("\t-v\n"); -- printf("\t\tTurn on verbose output.\n"); -- -- printf("\t-V\n"); -- printf("\t\tPrints the version number and exits.\n"); -- -- printf("\nDevice may be an absolute or relative path to a device "); -- printf("node or a major and\nminor number seperated by a colon (:)."); -- printf(" In this case a temporary device node\nwill be created in "); -- printf("the device directory.\n"); --} -- --void --print_version(char *command) --{ -- printf("(C) Copyright IBM Corp. 2004, 2005 All Rights Reserved.\n"); -- printf("This is %s version %u.%u\n", -- basename(command), -- ALUA_PRIO_MAJOR, -- ALUA_PRIO_MINOR -- ); --} -- --int --open_block_device(char *name) --{ -- int fd; -- struct stat st; -- -- if (stat(name, &st) != 0) { -- PRINT_ERROR("Cannot get file status from %s (errno = %i)!\n", -- name, errno); -- return -ALUA_PRIO_OPEN_FAILED; -- } -- if (!S_ISBLK(st.st_mode)) { -- PRINT_ERROR("%s is not a block device!\n", name); -- return -ALUA_PRIO_OPEN_FAILED; -- } -- fd = open(name, O_RDONLY); -- if (fd < 0) { -- PRINT_ERROR("Couldn't open %s (errno = %i)!\n", name, errno); -- return -ALUA_PRIO_OPEN_FAILED; -- } -- return fd; --} -- --int --close_block_device(int fd) --{ -- return close(fd); --} -- --int --get_alua_info(int fd) --{ -- char * aas_string[] = { -- [AAS_OPTIMIZED] = "active/optimized", -- [AAS_NON_OPTIMIZED] = "active/non-optimized", -- [AAS_STANDBY] = "standby", -- [AAS_UNAVAILABLE] = "unavailable", -- [AAS_TRANSITIONING] = "transitioning between states", -- }; -- int rc; -- int tpg; -- -- rc = get_target_port_group_support(fd); -- if (rc < 0) -- return rc; -- -- if (verbose) { -- printf("Target port groups are "); -- switch(rc) { -- case TPGS_NONE: -- printf("not"); -- break; -- case TPGS_IMPLICIT: -- printf("implicitly"); -- break; -- case TPGS_EXPLICIT: -- printf("explicitly"); -- break; -- case TPGS_BOTH: -- printf("implicitly and explicitly"); -- break; -- } -- printf(" supported.\n"); -- } -- -- if (rc == TPGS_NONE) -- return -ALUA_PRIO_NOT_SUPPORTED; -- -- tpg = get_target_port_group(fd); -- if (tpg < 0) { -- PRINT_ERROR("Couldn't get target port group!\n"); -- return -ALUA_PRIO_RTPG_FAILED; -- } -- PRINT_VERBOSE("Reported target port group is %i", tpg); -- -- rc = get_asymmetric_access_state(fd, tpg); -- if (rc < 0) { -- PRINT_VERBOSE(" [get AAS failed]\n"); -- PRINT_ERROR("Couln't get asymmetric access state!\n"); -- return -ALUA_PRIO_GETAAS_FAILED; -- } -- PRINT_VERBOSE(" [%s]\n", -- (aas_string[rc]) ? aas_string[rc] : "invalid/reserved" -- ); -- -- return rc; --} -- --int --main (int argc, char **argv) --{ -- char devicepath[PATH_MAX]; -- char * devicedir; -- char * s_opts = "d:hvV"; -- char * pos; -- int fd; -- int rc; -- int c; -- -- devicedir = "/dev"; -- while ((c = getopt(argc, argv, s_opts)) >= 0) { -- switch(c) { -- case 'd': -- devicedir = optarg; -- break; -- case 'h': -- print_help(argv[0]); -- return ALUA_PRIO_SUCCESS; -- case 'V': -- print_version(argv[0]); -- return ALUA_PRIO_SUCCESS; -- case 'v': -- verbose = 1; -- break; -- case '?': -- case ':': -- default: -- return ALUA_PRIO_INVALID_COMMANDLINE; -- } -- } -- -- if (optind == argc) { -- print_help(argv[0]); -- printf("\n"); -- PRINT_ERROR("No device specified!\n"); -- return ALUA_PRIO_INVALID_COMMANDLINE; -- } -- -- rc = ALUA_PRIO_SUCCESS; -- for(c = optind; c < argc && !rc; c++) { -- if (argv[c][0] == '/') { -- pos = NULL; -- sprintf(devicepath, "%s", argv[c]); -- } else if ((pos = index(argv[c], ':')) == NULL) { -- sprintf(devicepath, "%s/%s", devicedir, argv[c]); -- } else { -- int major; -- int minor; -- -- major = atoi(argv[c]); -- minor = atoi(++pos); -- sprintf(devicepath, "%s/tmpdev-%u:%u-%u", -- devicedir, major, minor, getpid() -- ); -- mknod( -- devicepath, -- S_IFBLK|S_IRUSR|S_IWUSR, -- makedev(major, minor) -- ); -- -- } -- -- fd = open_block_device(devicepath); -- if (fd < 0) { -- if (pos != NULL) -- unlink(devicepath); -- return -fd; -- } -- rc = get_alua_info(fd); -- if (rc >= 0) { -- switch(rc) { -- case AAS_OPTIMIZED: -- rc = 50; -- break; -- case AAS_NON_OPTIMIZED: -- rc = 10; -- break; -- case AAS_STANDBY: -- rc = 1; -- break; -- default: -- rc = 0; -- } -- printf("%u\n", rc); -- rc = ALUA_PRIO_SUCCESS; -- } -- close_block_device(fd); -- -- /* The path was created before. */ -- if (pos != NULL) -- unlink(devicepath); -- } -- -- return -rc; --} -diff --git a/path_priority/pp_alua/mpath_prio_alua.8 b/path_priority/pp_alua/mpath_prio_alua.8 -deleted file mode 100644 -index 58568a5..0000000 ---- a/path_priority/pp_alua/mpath_prio_alua.8 -+++ /dev/null -@@ -1,162 +0,0 @@ --.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 --.SH SYNOPSIS --.B mpath_prio_alua --.RB [\| \-d\ \c --.IR directory \|] --.RB [\| \-h \|] --.RB [\| \-v \|] --.RB [\| \-V \|] --.IR device " \|[ " device " \|[ " ... " \|]\|]" --.SH DESCRIPTION --.B mpath_prio_alua --is used as a priority callout for the multipath command. It returns a number --that is used by multipath to group devices with the same priority together. --.SH OPTIONS --.TP --.BI \-d " directory" --target directory for devices given as relative device names or devices given --as --.IR major : minor \c -- number. --Default is "/dev". --.TP --.B \-h --displays the command line help. --.TP --.B \-v --turns on verbose output. This shows all results in human readable format. --This includes information about the port group the device is in and its --current state. --.TP --.B \-V --shows the version number and exits. --.TP --.BI device --specifies the device to query (the device must be a SCSI device that supports --the \*[lq]Report Target Port Groups\*[rq] command). --One of the following three formats may be used: --.RS --.IP \(bu 2 --The full path name that starts with '/' (e.g. /dev/sda). --.IP \(bu --The device name only. This will prefix the directory name given by the --\-d option (e.g. sda). --.IP \(bu --The major and minor number of the device separated by ':'. This will --create a temporary device node in the device directory (e.g. 8:0). The --temporary name will be --.RB \*[lq] tmpdev-:- \*[rq]. --.SH "RETURN VALUE" --The mpath_prio_alua command returns the following values: --.IP \fB0 --on success. In this case the priority for the device is printed to --stdout. The priority value is: --.RS --.IP \fB50\fP --for devices that are in the active, optimized group --.IP \fB10 --for devices that are in an active but non-optimized group --.IP \fB1 --for devices that are in the standby group --.IP \fB0 --for all other groups --.RE --.IP "" --The reason for the widely spaced priority values is the way multipath handles --them. It will multiply the number of paths in a group with the priority value --and select the group with the highest result. Thus, if there are six paths in --the active, non-optimized group and only one in the active, optimized one, --the non-optimized group would be used. --.IP \fB1 --Indicates an error parsing the command line. --.IP \fB2 --The given devices could not be opened for reading. --.IP \fB3 --The device does not support target port groups. --.IP \fB4 --The inquiry command did not return a target port group for the given device. --.IP \fB5 --The report target port group command failed or did not return a target --port group that was obtained from the inquiry command. --.SH "EXAMPLES" --This example queries a device directly and returns the priority string: --.P --.RS --.B #> mpath_prio_alua /dev/sda --.br --50 --.RE --.P --Now the major and minor number is used to specify the device and verbose --output is selected: --.P --.RS --.B #> mpath_prio_alua -v 8:0 --.br --Target port groups are implicitly supported. --.br --Reported target port group is 0 [active/optimized] --.br --50 --.RE --.P --The following example shows the entries in the devices section of the --.RI "multipath-tool configuration file (" /etc/multipath.conf ) --to support an IBM DS6000 storage system: --.P --.RS --.PD 0 --device { --.RS --.TP 22 --.B vendor --"IBM " --.TP --.B product --"1750500 " --.TP --.B path_grouping_policy --group_by_prio --.TP --.B prio_callout --"/sbin/mpath_prio_alua -d/tmp %d" --.TP --.B features --"1 queue_if_no_path" --.TP --.B path_checker --tur --.RE --} --.PD --.RE --.TP --.B Notes: --.IP \(bu 2 --Depending on your default configuration not all keywords are required --.RB "(e.g. if your " path_checker " is set to tur you don't have to" --.RB "use the " path_checker " statement in the device section)." --.IP \(bu --.RB "The entries for " vendor " and " product " must be strings that are 8" --.RB "characters long (for " vendor ") and 16 characters long (for " product ")." --The strings have to be padded with blanks if necessary. --.IP \(bu --If you are working with hotpluggable devices whose device nodes are created --by udev you should use the %d flag in the --.BR prio_callout " statement." --This is because a short time elapses between the devices being available --and udev creating the device nodes. --.IP \(bu --If under certain circumstances your storage subsystem temporarily reports --.RB "failures on all paths, you should use the " features " statement showed" --in the example. --This will configure the multipath volume to requeue I/O until a path becomes --available again, instead of reporting failures in that case. --.SH "SEE ALSO" --.BR multipath (8), --.SH AUTHORS --.B mpath_prio_alua --was developed by Jan Kunigk and adapted by Stefan Bader -diff --git a/path_priority/pp_alua/rtpg.c b/path_priority/pp_alua/rtpg.c -deleted file mode 100644 -index 701f9d5..0000000 ---- a/path_priority/pp_alua/rtpg.c -+++ /dev/null -@@ -1,306 +0,0 @@ --/* -- * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -- * -- * rtpg.c -- * -- * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -- * It determines the ALUA state of a device and prints a priority value to -- * stdout. -- * -- * Author(s): Jan Kunigk -- * S. Bader -- * -- * This file is released under the GPL. -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define __user --#include -- --#include "rtpg.h" -- --#define SENSE_BUFF_LEN 32 --#define DEF_TIMEOUT 300000 -- --/* -- * Macro used to print debug messaged. -- */ --#if DEBUG > 0 --#define PRINT_DEBUG(f, a...) \ -- fprintf(stderr, "DEBUG: " f, ##a) --#else --#define PRINT_DEBUG(f, a...) --#endif -- --/* -- * Optionally print the commands sent and the data received a hex dump. -- */ --#if DEBUG > 0 --#if DEBUG_DUMPHEX > 0 --#define PRINT_HEX(p, l) print_hex(p, l) --void --print_hex(unsigned char *p, unsigned long len) --{ -- int i; -- -- for(i = 0; i < len; i++) { -- if (i % 16 == 0) -- printf("%04x: ", i); -- printf("%02x%s", p[i], (((i + 1) % 16) == 0) ? "\n" : " "); -- } -- printf("\n"); --} --#else --#define PRINT_HEX(p, l) --#endif --#else --#define PRINT_HEX(p, l) --#endif -- --/* -- * Returns 0 if the SCSI command either was successful or if the an error was -- * recovered, otherwise 1. (definitions taken from sg_err.h) -- */ --#define SCSI_CHECK_CONDITION 0x2 --#define SCSI_COMMAND_TERMINATED 0x22 --#define SG_ERR_DRIVER_SENSE 0x08 --#define RECOVERED_ERROR 0x01 -- --static int --scsi_error(struct sg_io_hdr *hdr) --{ -- /* Treat SG_ERR here to get rid of sg_err.[ch] */ -- hdr->status &= 0x7e; -- -- if ( -- (hdr->status == 0) && -- (hdr->host_status == 0) && -- (hdr->driver_status == 0) -- ) { -- return 0; -- } -- -- if ( -- (hdr->status == SCSI_CHECK_CONDITION) || -- (hdr->status == SCSI_COMMAND_TERMINATED) || -- ((hdr->driver_status & 0xf) == SG_ERR_DRIVER_SENSE) -- ) { -- if (hdr->sbp && (hdr->sb_len_wr > 2)) { -- int sense_key; -- unsigned char * sense_buffer = hdr->sbp; -- -- if (sense_buffer[0] & 0x2) -- sense_key = sense_buffer[1] & 0xf; -- else -- sense_key = sense_buffer[2] & 0xf; -- -- if (sense_key == RECOVERED_ERROR) -- return 0; -- } -- } -- -- return 1; --} -- --/* -- * Helper function to setup and run a SCSI inquiry command. -- */ --int --do_inquiry(int fd, int evpd, unsigned int codepage, void *resp, int resplen) --{ -- struct inquiry_command cmd; -- struct sg_io_hdr hdr; -- unsigned char sense[SENSE_BUFF_LEN]; -- -- memset(&cmd, 0, sizeof(cmd)); -- cmd.op = OPERATION_CODE_INQUIRY; -- if (evpd) { -- inquiry_command_set_evpd(&cmd); -- cmd.page = codepage; -- } -- set_uint16(cmd.length, resplen); -- PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); -- -- memset(&hdr, 0, sizeof(hdr)); -- hdr.interface_id = 'S'; -- hdr.cmdp = (unsigned char *) &cmd; -- hdr.cmd_len = sizeof(cmd); -- hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- hdr.dxferp = resp; -- hdr.dxfer_len = resplen; -- hdr.sbp = sense; -- hdr.mx_sb_len = sizeof(sense); -- hdr.timeout = DEF_TIMEOUT; -- -- if (ioctl(fd, SG_IO, &hdr) < 0) { -- PRINT_DEBUG("do_inquiry: IOCTL failed!\n"); -- return -RTPG_INQUIRY_FAILED; -- } -- -- if (scsi_error(&hdr)) { -- PRINT_DEBUG("do_inquiry: SCSI error!\n"); -- return -RTPG_INQUIRY_FAILED; -- } -- PRINT_HEX((unsigned char *) resp, resplen); -- -- return 0; --} -- --/* -- * This function returns the support for target port groups by evaluating the -- * data returned by the standard inquiry command. -- */ --int --get_target_port_group_support(int fd) --{ -- struct inquiry_data inq; -- int rc; -- -- rc = do_inquiry(fd, 0, 0x00, &inq, sizeof(inq)); -- if (!rc) { -- rc = inquiry_data_get_tpgs(&inq); -- } -- -- return rc; --} -- --int --get_target_port_group(int fd) --{ -- unsigned char buf[128]; -- struct vpd83_data * vpd83; -- struct vpd83_dscr * dscr; -- int rc; -- -- rc = do_inquiry(fd, 1, 0x83, buf, sizeof(buf)); -- if (!rc) { -- vpd83 = (struct vpd83_data *) buf; -- -- rc = -RTPG_NO_TPG_IDENTIFIER; -- FOR_EACH_VPD83_DSCR(vpd83, dscr) { -- if ((((char *) dscr) - ((char *) vpd83)) > sizeof(buf)) -- break; -- -- if (vpd83_dscr_istype(dscr, IDTYPE_TARGET_PORT_GROUP)) { -- struct vpd83_tpg_dscr * p; -- -- if (rc != -RTPG_NO_TPG_IDENTIFIER) { -- PRINT_DEBUG("get_target_port_group: " -- "more than one TPG identifier " -- "found!\n"); -- continue; -- } -- -- p = (struct vpd83_tpg_dscr *) dscr->data; -- rc = get_uint16(p->tpg); -- } -- } -- if (rc == -RTPG_NO_TPG_IDENTIFIER) { -- PRINT_DEBUG("get_target_port_group: " -- "no TPG identifier found!\n"); -- } -- } -- -- return rc; --} -- --int --do_rtpg(int fd, void* resp, long resplen) --{ -- struct rtpg_command cmd; -- struct sg_io_hdr hdr; -- unsigned char sense[SENSE_BUFF_LEN]; -- -- memset(&cmd, 0, sizeof(cmd)); -- cmd.op = OPERATION_CODE_RTPG; -- rtpg_command_set_service_action(&cmd); -- set_uint32(cmd.length, resplen); -- PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); -- -- memset(&hdr, 0, sizeof(hdr)); -- hdr.interface_id = 'S'; -- hdr.cmdp = (unsigned char *) &cmd; -- hdr.cmd_len = sizeof(cmd); -- hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- hdr.dxferp = resp; -- hdr.dxfer_len = resplen; -- hdr.mx_sb_len = sizeof(sense); -- hdr.sbp = sense; -- hdr.timeout = DEF_TIMEOUT; -- -- if (ioctl(fd, SG_IO, &hdr) < 0) -- return -RTPG_RTPG_FAILED; -- -- if (scsi_error(&hdr)) { -- PRINT_DEBUG("do_rtpg: SCSI error!\n"); -- return -RTPG_RTPG_FAILED; -- } -- PRINT_HEX(resp, resplen); -- -- return 0; --} -- --int --get_asymmetric_access_state(int fd, unsigned int tpg) --{ -- unsigned char *buf; -- struct rtpg_data * tpgd; -- struct rtpg_tpg_dscr * dscr; -- int rc; -- int buflen; -- uint32_t scsi_buflen; -- -- buflen = 128; /* Initial value from old code */ -- buf = (unsigned char *)malloc(buflen); -- if (!buf) { -- PRINT_DEBUG ("malloc failed: could not allocate" -- "%u bytes\n", buflen); -- return -RTPG_RTPG_FAILED; -- } -- rc = do_rtpg(fd, buf, buflen); -- if (rc < 0) -- return rc; -- scsi_buflen = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -- if (buflen < (scsi_buflen + 4)) { -- free(buf); -- buf = (unsigned char *)malloc(scsi_buflen); -- if (!buf) { -- PRINT_DEBUG ("malloc failed: could not allocate" -- "%u bytes\n", scsi_buflen); -- return -RTPG_RTPG_FAILED; -- } -- buflen = scsi_buflen; -- rc = do_rtpg(fd, buf, buflen); -- if (rc < 0) -- goto out; -- } -- -- -- tpgd = (struct rtpg_data *) buf; -- rc = -RTPG_TPG_NOT_FOUND; -- RTPG_FOR_EACH_PORT_GROUP(tpgd, dscr) { -- if (get_uint16(dscr->tpg) == tpg) { -- if (rc != -RTPG_TPG_NOT_FOUND) { -- PRINT_DEBUG("get_asymmetric_access_state: " -- "more than one entry with same port " -- "group.\n"); -- } else { -- PRINT_DEBUG("pref=%i\n", dscr->pref); -- rc = rtpg_tpg_dscr_get_aas(dscr); -- } -- } -- } --out: -- free(buf); -- return rc; --} -- -diff --git a/path_priority/pp_alua/rtpg.h b/path_priority/pp_alua/rtpg.h -deleted file mode 100644 -index 3c5dcf1..0000000 ---- a/path_priority/pp_alua/rtpg.h -+++ /dev/null -@@ -1,30 +0,0 @@ --/* -- * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -- * -- * rtpg.h -- * -- * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -- * It determines the ALUA state of a device and prints a priority value to -- * stdout. -- * -- * Author(s): Jan Kunigk -- * S. Bader -- * -- * This file is released under the GPL. -- */ --#ifndef __RTPG_H__ --#define __RTPG_H__ --#include "spc3.h" -- --#define RTPG_SUCCESS 0 --#define RTPG_INQUIRY_FAILED 1 --#define RTPG_NO_TPG_IDENTIFIER 2 --#define RTPG_RTPG_FAILED 3 --#define RTPG_TPG_NOT_FOUND 4 -- --int get_target_port_group_support(int fd); --int get_target_port_group(int fd); --int get_asymmetric_access_state(int fd, unsigned int tpg); -- --#endif /* __RTPG_H__ */ -- -diff --git a/path_priority/pp_alua/spc3.h b/path_priority/pp_alua/spc3.h -deleted file mode 100644 -index bddbbdd..0000000 ---- a/path_priority/pp_alua/spc3.h -+++ /dev/null -@@ -1,322 +0,0 @@ --/* -- * (C) Copyright IBM Corp. 2004, 2005 All Rights Reserved. -- * -- * spc3.h -- * -- * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access. -- * It determines the ALUA state of a device and prints a priority value to -- * stdout. -- * -- * Author(s): Jan Kunigk -- * S. Bader -- * -- * This file is released under the GPL. -- */ --#ifndef __SPC3_H__ --#define __SPC3_H__ --/*============================================================================= -- * Some helper functions for getting and setting 16 and 32 bit values. -- *============================================================================= -- */ --static inline unsigned short --get_uint16(unsigned char *p) --{ -- return (p[0] << 8) + p[1]; --} -- --static inline void --set_uint16(unsigned char *p, unsigned short v) --{ -- p[0] = (v >> 8) & 0xff; -- p[1] = v & 0xff; --} -- --static inline unsigned int --get_uint32(unsigned char *p) --{ -- return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; --} -- --static inline void --set_uint32(unsigned char *p, unsigned int v) --{ -- p[0] = (v >> 24) & 0xff; -- p[1] = (v >> 16) & 0xff; -- p[2] = (v >> 8) & 0xff; -- p[3] = v & 0xff; --} -- --/*============================================================================= -- * Definitions to support the standard inquiry command as defined in SPC-3. -- * If the evpd (enable vital product data) bit is set the data that will be -- * returned is selected by the page field. This field must be 0 if the evpd -- * bit is not set. -- *============================================================================= -- */ --#define OPERATION_CODE_INQUIRY 0x12 -- --struct inquiry_command { -- unsigned char op; -- unsigned char b1; /* xxxxxx.. = reserved */ -- /* ......x. = obsolete */ -- /* .......x = evpd */ -- unsigned char page; -- unsigned char length[2]; -- unsigned char control; --} __attribute__((packed)); -- --static inline void --inquiry_command_set_evpd(struct inquiry_command *ic) --{ -- ic->b1 |= 1; --} -- --/*----------------------------------------------------------------------------- -- * Data returned by the standard inquiry command. -- *----------------------------------------------------------------------------- -- * -- * Peripheral qualifier codes. -- */ --#define PQ_CONNECTED 0x0 --#define PQ_DISCONNECTED 0x1 --#define PQ_UNSUPPORTED 0x3 -- --/* Defined peripheral device types. */ --#define PDT_DIRECT_ACCESS 0x00 --#define PDT_SEQUENTIAL_ACCESS 0x01 --#define PDT_PRINTER 0x02 --#define PDT_PROCESSOR 0x03 --#define PDT_WRITE_ONCE 0x04 --#define PDT_CD_DVD 0x05 --#define PDT_SCANNER 0x06 --#define PDT_OPTICAL_MEMORY 0x07 --#define PDT_MEDIUM_CHANGER 0x08 --#define PDT_COMMUNICATIONS 0x09 --#define PDT_STORAGE_ARRAY_CONTROLLER 0x0c --#define PDT_ENCLOSURE_SERVICES 0x0d --#define PDT_SIMPLIFIED_DIRECT_ACCESS 0x0e --#define PDT_OPTICAL_CARD_READER_WRITER 0x0f --#define PDT_BRIDGE_CONTROLLER 0x10 --#define PDT_OBJECT_BASED 0x11 --#define PDT_AUTOMATION_INTERFACE 0x12 --#define PDT_LUN 0x1e --#define PDT_UNKNOWN 0x1f -- --/* Defined version codes. */ --#define VERSION_NONE 0x00 --#define VERSION_SPC 0x03 --#define VERSION_SPC2 0x04 --#define VERSION_SPC3 0x05 -- --/* Defined TPGS field values. */ --#define TPGS_NONE 0x0 --#define TPGS_IMPLICIT 0x1 --#define TPGS_EXPLICIT 0x2 --#define TPGS_BOTH 0x3 -- --struct inquiry_data { -- unsigned char b0; /* xxx..... = peripheral_qualifier */ -- /* ...xxxxx = peripheral_device_type */ -- unsigned char b1; /* x....... = removable medium */ -- /* .xxxxxxx = reserverd */ -- unsigned char version; -- unsigned char b3; /* xx...... = obsolete */ -- /* ..x..... = normal aca supported */ -- /* ...x.... = hirarchichal lun supp. */ -- /* ....xxxx = response format */ -- /* 2 is spc-3 format */ -- unsigned char length; -- unsigned char b5; /* x....... = storage controller */ -- /* component supported */ -- /* .x...... = access controls coord. */ -- /* ..xx.... = target port group supp.*/ -- /* ....x... = third party copy supp. */ -- /* .....xx. = reserved */ -- /* .......x = protection info supp. */ -- unsigned char b6; /* x....... = bque */ -- /* .x...... = enclosure services sup.*/ -- /* ..x..... = vs1 */ -- /* ...x.... = multiport support */ -- /* ....x... = medium changer */ -- /* .....xx. = obsolete */ -- /* .......x = add16 */ -- unsigned char b7; /* xx...... = obsolete */ -- /* ..x..... = wbus16 */ -- /* ...x.... = sync */ -- /* ....x... = linked commands supp. */ -- /* .....x.. = obsolete */ -- /* ......x. = command queue support */ -- /* .......x = vs2 */ -- unsigned char vendor_identification[8]; -- unsigned char product_identification[16]; -- unsigned char product_revision[4]; -- unsigned char vendor_specific[20]; -- unsigned char b56; /* xxxx.... = reserved */ -- /* ....xx.. = clocking */ -- /* ......x. = qas */ -- /* .......x = ius */ -- unsigned char reserved4; -- unsigned char version_descriptor[8][2]; -- unsigned char reserved5[22]; -- unsigned char vendor_parameters[0]; --} __attribute__((packed)); -- --static inline int --inquiry_data_get_tpgs(struct inquiry_data *id) --{ -- return (id->b5 >> 4) & 3; --} -- --/*----------------------------------------------------------------------------- -- * Inquiry data returned when requesting vital product data page 0x83. -- *----------------------------------------------------------------------------- -- */ --#define CODESET_BINARY 0x1 --#define CODESET_ACSII 0x2 --#define CODESET_UTF8 0x3 -- --#define ASSOCIATION_UNIT 0x0 --#define ASSOCIATION_PORT 0x1 --#define ASSOCIATION_DEVICE 0x2 -- --#define IDTYPE_VENDOR_SPECIFIC 0x0 --#define IDTYPE_T10_VENDOR_ID 0x1 --#define IDTYPE_EUI64 0x2 --#define IDTYPE_NAA 0x3 --#define IDTYPE_RELATIVE_TPG_ID 0x4 --#define IDTYPE_TARGET_PORT_GROUP 0x5 --#define IDTYPE_LUN_GROUP 0x6 --#define IDTYPE_MD5_LUN_ID 0x7 --#define IDTYPE_SCSI_NAME_STRING 0x8 -- --struct vpd83_tpg_dscr { -- unsigned char reserved1[2]; -- unsigned char tpg[2]; --} __attribute__((packed)); -- --struct vpd83_dscr { -- unsigned char b0; /* xxxx.... = protocol id */ -- /* ....xxxx = codeset */ -- unsigned char b1; /* x....... = protocol id valid */ -- /* .x...... = reserved */ -- /* ..xx.... = association */ -- /* ....xxxx = id type */ -- unsigned char reserved2; -- unsigned char length; /* size-4 */ -- unsigned char data[0]; --} __attribute__((packed)); -- --static inline int --vpd83_dscr_istype(struct vpd83_dscr *d, unsigned char type) --{ -- return ((d->b1 & 7) == type); --} -- --struct vpd83_data { -- unsigned char b0; /* xxx..... = peripheral_qualifier */ -- /* ...xxxxx = peripheral_device_type */ -- unsigned char page_code; /* 0x83 */ -- unsigned char length[2]; /* size-4 */ -- struct vpd83_dscr data[0]; --} __attribute__((packed)); -- --/*----------------------------------------------------------------------------- -- * This macro should be used to walk through all identification descriptors -- * defined in the code page 0x83. -- * The argument p is a pointer to the code page 0x83 data and d is used to -- * point to the current descriptor. -- *----------------------------------------------------------------------------- -- */ --#define FOR_EACH_VPD83_DSCR(p, d) \ -- for( \ -- d = p->data; \ -- (((char *) d) - ((char *) p)) < \ -- get_uint16(p->length); \ -- d = (struct vpd83_dscr *) \ -- ((char *) d + d->length + 4) \ -- ) -- --/*============================================================================= -- * The following stuctures and macros are used to call the report target port -- * groups command defined in SPC-3. -- * This command is used to get information about the target port groups (which -- * states are supported, which ports belong to this group, and so on) and the -- * current state of each target port group. -- *============================================================================= -- */ --#define OPERATION_CODE_RTPG 0xa3 --#define SERVICE_ACTION_RTPG 0x0a -- --struct rtpg_command { -- unsigned char op; /* 0xa3 */ -- unsigned char b1; /* xxx..... = reserved */ -- /* ...xxxxx = service action (0x0a) */ -- unsigned char reserved2[4]; -- unsigned char length[4]; -- unsigned char reserved3; -- unsigned char control; --} __attribute__((packed)); -- --static inline void --rtpg_command_set_service_action(struct rtpg_command *cmd) --{ -- cmd->b1 = (cmd->b1 & 0xe0) | SERVICE_ACTION_RTPG; --} -- --struct rtpg_tp_dscr { -- unsigned char obsolete1[2]; -- /* The Relative Target Port Identifier of a target port. */ -- unsigned char rtpi[2]; --} __attribute__((packed)); -- --#define AAS_OPTIMIZED 0x0 --#define AAS_NON_OPTIMIZED 0x1 --#define AAS_STANDBY 0x2 --#define AAS_UNAVAILABLE 0x3 --#define AAS_TRANSITIONING 0xf -- --#define TPG_STATUS_NONE 0x0 --#define TPG_STATUS_SET 0x1 --#define TPG_STATUS_IMPLICIT_CHANGE 0x2 -- --struct rtpg_tpg_dscr { -- unsigned char b0; /* x....... = pref(ered) port */ -- /* .xxx.... = reserved */ -- /* ....xxxx = asymetric access state */ -- unsigned char b1; /* xxxx.... = reserved */ -- /* ....x... = unavailable support */ -- /* .....x.. = standby support */ -- /* ......x. = non-optimized support */ -- /* .......x = optimized support */ -- unsigned char tpg[2]; -- unsigned char reserved3; -- unsigned char status; -- unsigned char vendor_unique; -- unsigned char port_count; -- struct rtpg_tp_dscr data[0]; --} __attribute__((packed)); -- --static inline int --rtpg_tpg_dscr_get_aas(struct rtpg_tpg_dscr *d) --{ -- return (d->b0 & 0x0f); --} -- --struct rtpg_data { -- unsigned char length[4]; /* size-4 */ -- struct rtpg_tpg_dscr data[0]; --} __attribute__((packed)); -- --#define RTPG_FOR_EACH_PORT_GROUP(p, g) \ -- for( \ -- g = &(p->data[0]); \ -- (((char *) g) - ((char *) p)) < get_uint32(p->length); \ -- g = (struct rtpg_tpg_dscr *) ( \ -- ((char *) g) + \ -- sizeof(struct rtpg_tpg_dscr) + \ -- g->port_count * sizeof(struct rtpg_tp_dscr) \ -- ) \ -- ) -- --#endif /* __SPC3_H__ */ -- -diff --git a/path_priority/pp_balance_units/Makefile b/path_priority/pp_balance_units/Makefile -deleted file mode 100644 -index cb1e6c6..0000000 ---- a/path_priority/pp_balance_units/Makefile -+++ /dev/null -@@ -1,44 +0,0 @@ --# Makefile --# --# Copyright (C) 2003 Christophe Varoqui, --# --BUILD = glibc --DEBUG = 0 -- --TOPDIR = ../.. --include $(TOPDIR)/Makefile.inc -- --ifeq ($(strip $(BUILD)),klibc) -- CFLAGS += -I/usr/include -DDEBUG=$(DEBUG) -- OBJS = pp_balance_units.o $(MULTIPATHLIB)-$(BUILD).a --else -- CFLAGS += -I$(multipathdir) -DDEBUG=$(DEBUG) -- LDFLAGS = -ldevmapper -- OBJS = pp_balance_units.o $(MULTIPATHLIB)-$(BUILD).a --endif -- --EXEC = mpath_prio_balance_units -- --all: $(BUILD) -- --prepare: -- rm -f core *.o *.gz -- --glibc: prepare $(OBJS) -- $(CC) -o $(EXEC) $(OBJS) $(LDFLAGS) -- --klibc: prepare $(OBJS) -- $(CC) -static -o $(EXEC) $(CRT0) $(OBJS) $(KLIBC) $(LIBGCC) -- --$(MULTIPATHLIB)-$(BUILD).a: -- make -C $(multipathdir) BUILD=$(BUILD) $(BUILD) -- --install: -- install -d $(DESTDIR)$(bindir) -- $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) -- --clean: -- rm -f core *.o $(EXEC) *.gz -diff --git a/path_priority/pp_balance_units/pp_balance_units.c b/path_priority/pp_balance_units/pp_balance_units.c -deleted file mode 100644 -index ea70f13..0000000 ---- a/path_priority/pp_balance_units/pp_balance_units.c -+++ /dev/null -@@ -1,476 +0,0 @@ --/* -- * Christophe Varoqui (2004) -- * This code is GPLv2, see license file -- * -- * This path prioritizer aims to balance logical units over all -- * controllers available. The logic is : -- * -- * - list all paths in all primary path groups -- * - 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 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 -- * -- */ --#define __user -- --#include --#include --#include --#include --#include -- --#include --#include --#include --#include --#include --#include --#include -- --#define SERIAL_SIZE 255 --#define WORD_SIZE 255 --#define PARAMS_SIZE 255 --#define FILE_NAME_SIZE 255 --#define INQUIRY_CMDLEN 6 --#define INQUIRY_CMD 0x12 --#define SENSE_BUFF_LEN 32 --#define DEF_TIMEOUT 300000 --#define RECOVERED_ERROR 0x01 --#define MX_ALLOC_LEN 255 --#define SCSI_CHECK_CONDITION 0x2 --#define SCSI_COMMAND_TERMINATED 0x22 --#define SG_ERR_DRIVER_SENSE 0x08 -- --#if DEBUG --#define debug(format, arg...) fprintf(stderr, format "\n", ##arg) --#else --#define debug(format, arg...) do {} while(0) --#endif -- --#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 -- --struct path { -- char dev_t[WORD_SIZE]; -- char serial[SERIAL_SIZE]; --}; -- --struct controller { -- char serial[SERIAL_SIZE]; -- int path_count; --}; -- --static int --exit_tool (int ret) --{ -- printf("1\n"); -- exit(ret); --} -- --static int --opennode (char * devt, int mode) --{ -- char devpath[FILE_NAME_SIZE]; -- unsigned int major; -- unsigned int minor; -- int fd; -- -- sscanf(devt, "%u:%u", &major, &minor); -- memset(devpath, 0, FILE_NAME_SIZE); -- -- if (safe_sprintf(devpath, "/tmp/.pp_balance.%u.%u.devnode", -- major, minor)) { -- fprintf(stderr, "devpath too small\n"); -- return -1; -- } -- unlink (devpath); -- mknod(devpath, S_IFBLK|S_IRUSR|S_IWUSR, makedev(major, minor)); -- fd = open(devpath, mode); -- -- if (fd < 0) -- unlink(devpath); -- -- return fd; -- --} -- --static void --closenode (char * devt, int fd) --{ -- char devpath[FILE_NAME_SIZE]; -- unsigned int major; -- unsigned int minor; -- -- if (fd >= 0) -- close(fd); -- -- sscanf(devt, "%u:%u", &major, &minor); -- if (safe_sprintf(devpath, "/tmp/.pp_balance.%u.%u.devnode", -- major, minor)) { -- fprintf(stderr, "devpath too small\n"); -- return; -- } -- unlink(devpath); --} -- --static int --do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, -- void *resp, int mx_resp_len, int noisy) --{ -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = -- { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -- unsigned char sense_b[SENSE_BUFF_LEN]; -- struct sg_io_hdr io_hdr; -- -- if (cmddt) -- inqCmdBlk[1] |= 2; -- if (evpd) -- inqCmdBlk[1] |= 1; -- inqCmdBlk[2] = (unsigned char) pg_op; -- inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); -- inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_b); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = mx_resp_len; -- io_hdr.dxferp = resp; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sense_b; -- io_hdr.timeout = DEF_TIMEOUT; -- -- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -- return -1; -- -- /* treat SG_ERR here to get rid of sg_err.[ch] */ -- io_hdr.status &= 0x7e; -- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -- (0 == io_hdr.driver_status)) -- return 0; -- if ((SCSI_CHECK_CONDITION == io_hdr.status) || -- (SCSI_COMMAND_TERMINATED == io_hdr.status) || -- (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -- if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -- int sense_key; -- unsigned char * sense_buffer = io_hdr.sbp; -- if (sense_buffer[0] & 0x2) -- sense_key = sense_buffer[1] & 0xf; -- else -- sense_key = sense_buffer[2] & 0xf; -- if(RECOVERED_ERROR == sense_key) -- return 0; -- } -- } -- return -1; --} -- --static int --get_serial (char * str, int maxlen, char * devt) --{ -- int fd; -- int len; -- char buff[MX_ALLOC_LEN + 1]; -- -- fd = opennode(devt, O_RDONLY); -- -- if (fd < 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 0; -- } -- -- closenode(devt, fd); -- return 1; --} -- --static void * --get_params (void) --{ -- struct dm_task *dmt, *dmt1; -- struct dm_names *names = NULL; -- unsigned next = 0; -- void *nexttgt; -- uint64_t start, length; -- char *target_type = NULL; -- char *params; -- char *pp; -- vector paramsvec = NULL; -- -- if (!(dmt = dm_task_create(DM_DEVICE_LIST))) -- return NULL; -- -- if (!dm_task_run(dmt)) -- goto out; -- -- if (!(names = dm_task_get_names(dmt))) -- goto out; -- -- if (!names->dev) { -- debug("no devmap found"); -- goto out; -- } -- do { -- /* -- * keep only multipath maps -- */ -- names = (void *) names + next; -- nexttgt = NULL; -- debug("devmap %s :", names->name); -- -- if (!(dmt1 = dm_task_create(DM_DEVICE_TABLE))) -- goto out; -- -- if (!dm_task_set_name(dmt1, names->name)) -- goto out1; -- -- if (!dm_task_run(dmt1)) -- goto out1; -- -- do { -- nexttgt = dm_get_next_target(dmt1, nexttgt, -- &start, -- &length, -- &target_type, -- ¶ms); -- debug("\\_ %lu %lu %s", (unsigned long) start, -- (unsigned long) length, -- target_type); -- -- if (!target_type) { -- debug("unknown target type"); -- goto out1; -- } -- -- if (!strncmp(target_type, "multipath", 9)) { -- if (!paramsvec) -- paramsvec = vector_alloc(); -- -- pp = malloc(PARAMS_SIZE); -- strncpy(pp, params, PARAMS_SIZE); -- vector_alloc_slot(paramsvec); -- vector_set_slot(paramsvec, pp); -- } else -- debug("skip non multipath target"); -- } while (nexttgt); --out1: -- dm_task_destroy(dmt1); -- next = names->next; -- } while (next); --out: -- dm_task_destroy(dmt); -- return paramsvec; --} -- --static int --get_word (char *sentence, char *word) --{ -- char *p; -- int skip = 0; -- -- while (*sentence == ' ') { -- sentence++; -- skip++; -- } -- p = sentence; -- -- while (*p != ' ' && *p != '\0') -- p++; -- -- skip += (p - sentence); -- -- if (p - sentence > WORD_SIZE) { -- fprintf(stderr, "word too small\n"); -- exit_tool(1); -- } -- strncpy(word, sentence, WORD_SIZE); -- word += p - sentence; -- *word = '\0'; -- -- if (*p == '\0') -- return 0; -- -- return skip; --} -- --static int --is_path (char * word) --{ -- char *p; -- -- if (!word) -- return 0; -- -- p = word; -- -- while (*p != '\0') { -- if (*p == ':') -- return 1; -- p++; -- } -- return 0; --} -- --static int --get_paths (vector pathvec) --{ -- vector paramsvec = NULL; -- char * str; -- struct path * pp; -- int i; -- enum where {BEFOREPG, INPG, AFTERPG}; -- int pos = BEFOREPG; -- -- if (!pathvec) -- return 1; -- -- if (!(paramsvec = get_params())) -- exit_tool(0); -- -- vector_foreach_slot (paramsvec, str, i) { -- debug("params %s", str); -- while (pos != AFTERPG) { -- pp = zalloc(sizeof(struct path)); -- str += get_word(str, pp->dev_t); -- -- if (!is_path(pp->dev_t)) { -- debug("skip \"%s\"", pp->dev_t); -- free(pp); -- -- if (pos == INPG) -- pos = AFTERPG; -- -- continue; -- } -- if (pos == BEFOREPG) -- pos = INPG; -- -- get_serial(pp->serial, SERIAL_SIZE, pp->dev_t); -- vector_alloc_slot(pathvec); -- vector_set_slot(pathvec, pp); -- debug("store %s [%s]", -- pp->dev_t, pp->serial); -- } -- pos = BEFOREPG; -- } -- return 0; --} -- --static void * --find_controller (vector controllers, char * serial) --{ -- int i; -- struct controller * cp; -- -- if (!controllers) -- return NULL; -- -- vector_foreach_slot (controllers, cp, i) -- if (!strncmp(cp->serial, serial, SERIAL_SIZE)) -- return cp; -- return NULL; --} -- --static void --get_controllers (vector controllers, vector pathvec) --{ -- int i; -- struct path * pp; -- struct controller * cp; -- -- if (!controllers) -- return; -- -- vector_foreach_slot (pathvec, pp, i) { -- if (!pp || !strlen(pp->serial)) -- continue; -- -- cp = find_controller(controllers, pp->serial); -- -- if (!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++; -- } --} -- --static int --get_max_path_count (vector controllers) --{ -- int i; -- int max = 0; -- struct controller * cp; -- -- if (!controllers) -- return 0; -- -- 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; -- } -- debug("max_path_count = %i", max); -- return max; --} -- --int --main (int argc, char **argv) --{ -- vector pathvec = NULL; -- vector controllers = NULL; -- struct path * ref_path = NULL; -- struct controller * cp = NULL; -- int max_path_count = 0; -- -- ref_path = zalloc(sizeof(struct path)); -- -- if (!ref_path) -- exit_tool(1); -- -- if (argc != 2) -- exit_tool(1); -- -- if (optinddev_t, argv[optind], WORD_SIZE); -- -- 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(); -- controllers = vector_alloc(); -- -- get_paths(pathvec); -- 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", -- ref_path->serial); -- exit_tool(0); -- } -- -- printf("%i\n", max_path_count - cp->path_count + 1); -- -- return(0); --} -diff --git a/path_priority/pp_emc/Makefile b/path_priority/pp_emc/Makefile -deleted file mode 100644 -index 93e6075..0000000 ---- a/path_priority/pp_emc/Makefile -+++ /dev/null -@@ -1,25 +0,0 @@ --EXEC = mpath_prio_emc --BUILD = glibc --OBJS = pp_emc.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_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) --clean: -- rm -f *.o $(EXEC) -- --%.o: %.c -- $(CC) $(CFLAGS) -c -o $@ $< -diff --git a/path_priority/pp_emc/pp_emc.c b/path_priority/pp_emc/pp_emc.c -deleted file mode 100644 -index 4031720..0000000 ---- a/path_priority/pp_emc/pp_emc.c -+++ /dev/null -@@ -1,101 +0,0 @@ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "../../libmultipath/sg_include.h" -- --#define INQUIRY_CMD 0x12 --#define INQUIRY_CMDLEN 6 -- --int emc_clariion_prio(const char *dev) --{ -- unsigned char sense_buffer[256]; -- unsigned char sb[128]; -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0, -- sizeof(sb), 0}; -- struct sg_io_hdr io_hdr; -- int ret = 0; -- int fd; -- -- fd = open(dev, O_RDWR|O_NONBLOCK); -- -- if (fd <= 0) { -- fprintf(stderr, "Opening the device failed.\n"); -- goto out; -- } -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = sizeof (sense_buffer); -- io_hdr.dxferp = sense_buffer; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sb; -- io_hdr.timeout = 60000; -- io_hdr.pack_id = 0; -- if (ioctl(fd, SG_IO, &io_hdr) < 0) { -- fprintf(stderr, "sending query command failed\n"); -- goto out; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- fprintf(stderr, "query command indicates error"); -- goto out; -- } -- -- close(fd); -- -- if (/* Verify the code page - right page & revision */ -- sense_buffer[1] != 0xc0 || sense_buffer[9] != 0x00) { -- fprintf(stderr, "Path unit report page in unknown format"); -- goto out; -- } -- -- if ( /* Effective initiator type */ -- sense_buffer[27] != 0x03 -- /* -- * Failover mode should be set to 1 (PNR failover mode) -- * or 4 (ALUA failover mode). -- */ -- || (((sense_buffer[28] & 0x07) != 0x04) && -- ((sense_buffer[28] & 0x07) != 0x06)) -- /* Arraycommpath should be set to 1 */ -- || (sense_buffer[30] & 0x04) != 0x04) { -- fprintf(stderr, "Path not correctly configured for failover"); -- } -- -- if ( /* LUN operations should indicate normal operations */ -- sense_buffer[48] != 0x00) { -- fprintf(stderr, "Path not available for normal operations"); -- } -- -- /* Is the default owner equal to this path? */ -- /* Note this will switch to the default priority group, even if -- * it is not the currently active one. */ -- ret = (sense_buffer[5] == sense_buffer[8]) ? 1 : 0; -- --out: -- return(ret); --} -- --int --main (int argc, char **argv) --{ -- int prio; -- if (argc != 2) { -- fprintf(stderr, "Arguments wrong!\n"); -- prio = 0; -- } else -- prio = emc_clariion_prio(argv[1]); -- -- printf("%d\n", prio); -- exit(0); --} -- -diff --git a/path_priority/pp_hds_modular/Makefile b/path_priority/pp_hds_modular/Makefile -deleted file mode 100644 -index ca00ca7..0000000 ---- a/path_priority/pp_hds_modular/Makefile -+++ /dev/null -@@ -1,22 +0,0 @@ --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_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) --clean: -- rm -f *.o $(EXEC) -diff --git a/path_priority/pp_hds_modular/pp_hds_modular.c b/path_priority/pp_hds_modular/pp_hds_modular.c -deleted file mode 100644 -index 7411508..0000000 ---- a/path_priority/pp_hds_modular/pp_hds_modular.c -+++ /dev/null -@@ -1,211 +0,0 @@ --/* -- * (C) Copyright HDS GmbH 2006. All Rights Reserved. -- * -- * pp_hds_modular.c -- * Version 2.00 -- * -- * Prioritizer for Device Mapper Multipath 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 command 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 -- * -- * To compile this source please execute # cc pp_hds_modular.c -o /sbin/mpath_prio_hds_modular -- * -- * Changes 2006-07-16: -- * - Changed to forward declaration of functions -- * - The switch-statement was changed to a logical expression -- * - unlinking of the devpath now also occurs at the end of -- * hds_modular_prio to avoid old /tmp/.pp_balance.%u.%u.devnode -- * entries in /tmp-Directory -- * - The for-statements for passing variables where changed to -- * snprintf-commands in verbose mode -- * Changes 2006-08-10: -- * - Back to the old switch statements because the regular expression does -- * not work under RHEL4 U3 i386 -- * Changes 2007-06-27: -- * - switched from major:minor argument to device node argument -- * -- * This file is released under the GPL. -- * -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define INQ_REPLY_LEN 255 --#define INQ_CMD_CODE 0x12 --#define INQ_CMD_LEN 6 --#define FILE_NAME_SIZE 255 -- --int verbose=0; -- --void print_help (void); --int hds_modular_prio (const char *); -- --int main (int argc, char **argv) --{ -- int prio; -- if (argc == 2) -- { -- if (strcmp (argv[1], "-h") == 0) -- { -- print_help (); -- exit (0); -- } -- else -- { -- verbose = 0; -- prio = hds_modular_prio (argv[1]); -- printf ("%d\n", prio); -- exit (0); -- } -- } -- if ((argc == 3) && (strcmp (argv[1], "-v")) == 0) -- { -- verbose = 1; -- prio = hds_modular_prio (argv[2]); -- printf ("%d\n", prio); -- exit (0); -- } -- print_help (); -- exit (1); --} -- --int hds_modular_prio (const char *dev) --{ -- int sg_fd, k; -- char vendor[8]; -- char product[32]; -- char serial[32]; -- char ldev[32]; -- char ctrl[32]; -- char port[32]; -- unsigned char inqCmdBlk[INQ_CMD_LEN] = { INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0 }; -- unsigned char inqBuff[INQ_REPLY_LEN]; -- unsigned char *inqBuffp = inqBuff; -- unsigned char sense_buffer[32]; -- sg_io_hdr_t io_hdr; -- -- if ((sg_fd = open (dev, 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); -- -- snprintf (vendor, 9, "%.8s\n", inqBuffp + 8); -- snprintf (product, 17, "%.16s", inqBuffp + 16); -- snprintf (serial, 5, "%.4s", inqBuffp + 40); -- snprintf (ldev, 5, "%.4s", inqBuffp + 44); -- snprintf (ctrl, 2, "%.1s", inqBuffp + 49); -- snprintf (port, 2, "%.1s", inqBuffp + 50); -- -- close (sg_fd); -- -- if (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; -- } -- } -- return 0; --} -- --void print_help (void) --{ -- printf ("\n"); -- printf ("Usage: pp_hds_modular [-v] \n"); -- printf ("Option: -v verbose mode\n"); -- printf ("Description: Prioritizer for Device Mapper Multipath and HDS Storage\n"); -- printf ("Version: 2.00\n"); -- printf ("Author: Matthias Rudolph \n"); -- printf ("Remarks: Prioritizer CTRL#1 corresponds to hardware CTRL#0\n"); -- printf (" Prioritizer CTRL#2 corresponds to hardware CTRL#1\n"); -- printf ("\n"); -- return; --} -- -diff --git a/path_priority/pp_hp_sw/Makefile b/path_priority/pp_hp_sw/Makefile -deleted file mode 100644 -index e7debf5..0000000 ---- a/path_priority/pp_hp_sw/Makefile -+++ /dev/null -@@ -1,25 +0,0 @@ --EXEC = mpath_prio_hp_sw --BUILD = glibc --OBJS = pp_hp_sw.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 -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) --clean: -- rm -f *.o $(EXEC) -- --%.o: %.c -- $(CC) $(CFLAGS) -c -o $@ $< -diff --git a/path_priority/pp_hp_sw/pp_hp_sw.c b/path_priority/pp_hp_sw/pp_hp_sw.c -deleted file mode 100644 -index e4a18b1..0000000 ---- a/path_priority/pp_hp_sw/pp_hp_sw.c -+++ /dev/null -@@ -1,119 +0,0 @@ --/* -- * Path priority checker for HP active/standby controller -- * -- * Check the path state and sort them into groups. -- * There is actually a preferred path in the controller; -- * we should ask HP on how to retrieve that information. -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define TUR_CMD_LEN 6 --#define SCSI_CHECK_CONDITION 0x2 --#define SCSI_COMMAND_TERMINATED 0x22 --#define SG_ERR_DRIVER_SENSE 0x08 --#define RECOVERED_ERROR 0x01 --#define NOT_READY 0x02 --#define UNIT_ATTENTION 0x06 -- --#define HP_PATH_ACTIVE 0x04 --#define HP_PATH_STANDBY 0x02 --#define HP_PATH_FAILED 0x00 -- --#include "../../libmultipath/sg_include.h" -- --int hp_sw_prio(const char *dev) --{ -- unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -- unsigned char sb[128]; -- struct sg_io_hdr io_hdr; -- int ret = HP_PATH_FAILED; -- int fd; -- -- fd = open(dev, O_RDWR|O_NONBLOCK); -- -- if (fd <= 0) { -- fprintf(stderr, "Opening the device failed.\n"); -- goto out; -- } -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (turCmdBlk); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_NONE; -- io_hdr.cmdp = turCmdBlk; -- io_hdr.sbp = sb; -- io_hdr.timeout = 60000; -- io_hdr.pack_id = 0; -- retry: -- if (ioctl(fd, SG_IO, &io_hdr) < 0) { -- fprintf(stderr, "sending tur command failed\n"); -- goto out; -- } -- io_hdr.status &= 0x7e; -- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -- (0 == io_hdr.driver_status)) { -- /* Command completed normally, path is active */ -- ret = HP_PATH_ACTIVE; -- } -- -- if ((SCSI_CHECK_CONDITION == io_hdr.status) || -- (SCSI_COMMAND_TERMINATED == io_hdr.status) || -- (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -- if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -- int sense_key, asc, asq; -- unsigned char * sense_buffer = io_hdr.sbp; -- if (sense_buffer[0] & 0x2) { -- sense_key = sense_buffer[1] & 0xf; -- asc = sense_buffer[2]; -- asq = sense_buffer[3]; -- } else { -- sense_key = sense_buffer[2] & 0xf; -- asc = sense_buffer[12]; -- asq = sense_buffer[13]; -- } -- if(RECOVERED_ERROR == sense_key) -- ret = HP_PATH_ACTIVE; -- if(NOT_READY == sense_key) { -- if (asc == 0x04 && asq == 0x02) { -- /* This is a standby path */ -- ret = HP_PATH_STANDBY; -- } -- } -- if(UNIT_ATTENTION == sense_key) { -- if (asc == 0x29) { -- /* Retry for device reset */ -- goto retry; -- } -- } -- } -- } -- -- close(fd); -- --out: -- return(ret); --} -- --int --main (int argc, char **argv) --{ -- int prio; -- if (argc != 2) { -- fprintf(stderr, "Arguments wrong!\n"); -- prio = 0; -- } else -- prio = hp_sw_prio(argv[1]); -- -- printf("%d\n", prio); -- exit(0); --} -- -diff --git a/path_priority/pp_netapp/Makefile b/path_priority/pp_netapp/Makefile -deleted file mode 100644 -index b29d002..0000000 ---- a/path_priority/pp_netapp/Makefile -+++ /dev/null -@@ -1,22 +0,0 @@ --EXEC = mpath_prio_netapp --BUILD = glibc --OBJS = pp_netapp.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_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) --clean: -- rm -f *.o $(EXEC) -diff --git a/path_priority/pp_netapp/pp_netapp.c b/path_priority/pp_netapp/pp_netapp.c -deleted file mode 100644 -index 8562a95..0000000 ---- a/path_priority/pp_netapp/pp_netapp.c -+++ /dev/null -@@ -1,268 +0,0 @@ --/* -- * Copyright 2005 Network Appliance, Inc., All Rights Reserved -- * Author: David Wysochanski available at davidw@netapp.com -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * 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 v2 for more details. -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "../../libmultipath/sg_include.h" -- --#define INQUIRY_CMD 0x12 --#define INQUIRY_CMDLEN 6 --#define DEFAULT_PRIO 10 --#define RESULTS_MAX 256 --#define SG_TIMEOUT 30000 -- -- --static void dump_cdb(unsigned char *cdb, int size) --{ -- int i; -- -- fprintf(stderr, "- SCSI CDB: "); -- for (i=0; imasked_status, -- io_hdr->host_status, io_hdr->driver_status); -- if (io_hdr->sb_len_wr > 0) { -- fprintf(stderr, "- SCSI sense data: "); -- for (i=0; isb_len_wr; i++) { -- fprintf(stderr, "0x%02x ", io_hdr->sbp[i]); -- } -- fprintf(stderr, "\n"); -- } --} -- --/* -- * Returns: -- * -1: error, errno set -- * 0: success -- */ --static int send_gva(const char *dev, unsigned char pg, -- unsigned char *results, int *results_size) --{ -- unsigned char sb[128]; -- unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa, -- pg, sizeof(sb), 0, 0}; -- struct sg_io_hdr io_hdr; -- int ret = -1; -- int fd; -- -- fd = open(dev, O_RDWR|O_NONBLOCK); -- -- if (fd <= 0) { -- fprintf(stderr, "Opening %s failed, errno=%d.\n", dev, errno); -- goto out_no_close; -- } -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (cdb); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = *results_size; -- io_hdr.dxferp = results; -- io_hdr.cmdp = cdb; -- io_hdr.sbp = sb; -- io_hdr.timeout = SG_TIMEOUT; -- io_hdr.pack_id = 0; -- if (ioctl(fd, SG_IO, &io_hdr) < 0) { -- fprintf(stderr, "SG_IO ioctl failed, errno=%d\n", errno); -- dump_cdb(cdb, sizeof(cdb)); -- goto out; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- fprintf(stderr, "SCSI error\n"); -- dump_cdb(cdb, sizeof(cdb)); -- process_sg_error(&io_hdr); -- goto out; -- } -- -- if (results[4] != 0x0a || results[5] != 0x98 || -- results[6] != 0x0a ||results[7] != 0x01) { -- dump_cdb(cdb, sizeof(cdb)); -- fprintf(stderr, "GVA return wrong format "); -- fprintf(stderr, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x\n", -- results[4], results[5], results[6], results[7]); -- goto out; -- } -- ret = 0; -- out: -- close(fd); -- out_no_close: -- return(ret); --} -- --/* -- * Retuns: -- * -1: Unable to obtain proxy info -- * 0: Device _not_ proxy path -- * 1: Device _is_ proxy path -- */ --static int get_proxy(const char *dev) --{ -- unsigned char results[256]; -- unsigned char sb[128]; -- unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0, -- sizeof(sb), 0}; -- struct sg_io_hdr io_hdr; -- int ret = -1; -- int fd; -- -- fd = open(dev, O_RDWR|O_NONBLOCK); -- -- if (fd <= 0) { -- fprintf(stderr, "Opening %s failed, errno=%d.\n", dev, errno); -- goto out_no_close; -- } -- -- memset(&results, 0, sizeof (results)); -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (cdb); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = sizeof (results); -- io_hdr.dxferp = results; -- io_hdr.cmdp = cdb; -- io_hdr.sbp = sb; -- io_hdr.timeout = SG_TIMEOUT; -- io_hdr.pack_id = 0; -- if (ioctl(fd, SG_IO, &io_hdr) < 0) { -- fprintf(stderr, "ioctl sending inquiry command failed, " -- "errno=%d\n", errno); -- dump_cdb(cdb, sizeof(cdb)); -- goto out; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- fprintf(stderr, "SCSI error\n"); -- dump_cdb(cdb, sizeof(cdb)); -- process_sg_error(&io_hdr); -- goto out; -- } -- -- if (results[1] != 0xc1 || results[8] != 0x0a || -- results[9] != 0x98 || results[10] != 0x0a || -- results[11] != 0x0 || results[12] != 0xc1 || -- results[13] != 0x0) { -- fprintf(stderr,"Proxy info page in unknown format - "); -- fprintf(stderr,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x " -- "0x%02x 0x%02x\n", -- results[8], results[9], results[10], -- results[11], results[12], results[13]); -- dump_cdb(cdb, sizeof(cdb)); -- goto out; -- } -- ret = (results[19] & 0x02) >> 1; -- -- out: -- close(fd); -- out_no_close: -- return(ret); --} -- --/* -- * Returns priority of device based on device info. -- * -- * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol -- * 3: iSCSI HBA -- * 2: iSCSI software -- * 1: FCP proxy -- */ --static int netapp_prio(const char *dev) --{ -- unsigned char results[RESULTS_MAX]; -- int results_size=RESULTS_MAX; -- int rc; -- int is_proxy; -- int is_iscsi_software; -- int is_iscsi_hardware; -- int tot_len; -- -- is_iscsi_software = is_iscsi_hardware = is_proxy = 0; -- -- memset(&results, 0, sizeof (results)); -- rc = send_gva(dev, 0x41, results, &results_size); -- if (rc == 0) { -- tot_len = results[0] << 24 | results[1] << 16 | -- results[2] << 8 | results[3]; -- if (tot_len <= 8) { -- goto try_fcp_proxy; -- } -- if (results[8] != 0x41) { -- fprintf(stderr, "GVA page 0x41 error - " -- "results[8] = 0x%x\n", results[8]); -- goto try_fcp_proxy; -- } -- if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) || -- (strncmp((char *)&results[12], "iswt", 4) == 0)) { -- is_iscsi_software = 1; -- goto prio_select; -- } -- else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) { -- is_iscsi_hardware = 1; -- goto prio_select; -- } -- } -- -- try_fcp_proxy: -- rc = get_proxy(dev); -- if (rc >= 0) { -- is_proxy = rc; -- } -- -- prio_select: -- if (is_iscsi_hardware) { -- return 3; -- } else if (is_iscsi_software) { -- return 2; -- } else { -- if (is_proxy) { -- return 1; -- } else { -- /* Either non-proxy, or couldn't get proxy info */ -- return 4; -- } -- } --} -- --int --main (int argc, char **argv) --{ -- int prio; -- if (argc != 2) { -- fprintf(stderr, "Arguments wrong!\n"); -- prio = 0; -- } else -- prio = netapp_prio(argv[1]); -- -- printf("%d\n", prio); -- exit(0); --} -- -diff --git a/path_priority/pp_random/Makefile b/path_priority/pp_random/Makefile -deleted file mode 100644 -index 85d7c2f..0000000 ---- a/path_priority/pp_random/Makefile -+++ /dev/null -@@ -1,22 +0,0 @@ --EXEC = mpath_prio_random --BUILD = glibc --OBJS = pp_random.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_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) --clean: -- rm -f *.o $(EXEC) -diff --git a/path_priority/pp_random/pp_random.c b/path_priority/pp_random/pp_random.c -deleted file mode 100644 -index 05c4b8d..0000000 ---- a/path_priority/pp_random/pp_random.c -+++ /dev/null -@@ -1,14 +0,0 @@ --#include --#include --#include --#include -- --int main(void) --{ -- struct timeval tv; -- -- gettimeofday(&tv, NULL); -- srand((unsigned int)tv.tv_usec); -- printf("%i\n", 1+(int) (10.0*rand()/(RAND_MAX+1.0))); -- return 0; --} -diff --git a/path_priority/pp_rdac/Makefile b/path_priority/pp_rdac/Makefile -deleted file mode 100644 -index 64ed4c3..0000000 ---- a/path_priority/pp_rdac/Makefile -+++ /dev/null -@@ -1,22 +0,0 @@ --EXEC = mpath_prio_rdac --BUILD = glibc --OBJS = pp_rdac.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_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) -- --uninstall: -- rm $(DESTDIR)$(bindir)/$(EXEC) --clean: -- rm -f *.o $(EXEC) -diff --git a/path_priority/pp_rdac/pp_rdac.c b/path_priority/pp_rdac/pp_rdac.c -deleted file mode 100644 -index 49a13cf..0000000 ---- a/path_priority/pp_rdac/pp_rdac.c -+++ /dev/null -@@ -1,112 +0,0 @@ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "../../libmultipath/sg_include.h" -- --#define INQUIRY_CMD 0x12 --#define INQUIRY_CMDLEN 6 -- --int rdac_prio(const char *dev) --{ -- unsigned char sense_buffer[256]; -- unsigned char sb[128]; -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC9, 0, -- sizeof(sb), 0}; -- struct sg_io_hdr io_hdr; -- int ret = 0; -- int fd; -- -- fd = open(dev, O_RDWR|O_NONBLOCK); -- -- if (fd <= 0) { -- fprintf(stderr, "opening of the device failed.\n"); -- goto out; -- } -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = sizeof (sense_buffer); -- io_hdr.dxferp = sense_buffer; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sb; -- io_hdr.timeout = 60000; -- io_hdr.pack_id = 0; -- if (ioctl(fd, SG_IO, &io_hdr) < 0) { -- fprintf(stderr, "sending inquiry command failed\n"); -- goto out; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- fprintf(stderr, "inquiry command indicates error"); -- goto out; -- } -- -- close(fd); -- -- if (/* Verify the code page - right page & page identifier */ -- sense_buffer[1] != 0xc9 || -- sense_buffer[3] != 0x2c || -- sense_buffer[4] != 'v' || -- sense_buffer[5] != 'a' || -- sense_buffer[6] != 'c' ) { -- fprintf(stderr, "Volume access control page in unknown format"); -- goto out; -- } -- -- if ( /* Current Volume Path Bit */ -- ( sense_buffer[8] & 0x01) == 0x01 ) { -- /* -- * This volume was owned by the controller receiving -- * the inquiry command. -- */ -- ret |= 0x01; -- } -- -- /* Volume Preferred Path Priority */ -- switch ( sense_buffer[9] & 0x0F ) { -- case 0x01: -- /* -- * Access to this volume is most preferred through -- * this path and other paths with this value. -- */ -- ret |= 0x02; -- break; -- case 0x02: -- /* -- * Access to this volume through this path is to be used -- * as a secondary path. Typically this path would be used -- * for fail-over situations. -- */ -- /* Fallthrough */ -- default: -- /* Reserved values */ -- break; -- } -- --out: -- return(ret); --} -- --int --main (int argc, char **argv) --{ -- int prio; -- if (argc != 2) { -- fprintf(stderr, "Wrong number of arguments.\n"); -- fprintf(stderr, "Usage: %s device\n", argv[0]); -- prio = 0; -- } else -- prio = rdac_prio(argv[1]); -- -- printf("%d\n", prio); -- exit(0); --} diff --git a/multipath-tools-handle-arguments-from-init-file b/multipath-tools-handle-arguments-from-init-file deleted file mode 100644 index a715a34..0000000 --- a/multipath-tools-handle-arguments-from-init-file +++ /dev/null @@ -1,67 +0,0 @@ -commit 4322929c30a2f2bb57ebb1d427eb7536adb05dc1 -Author: Hannes Reinecke -Date: Thu Nov 6 09:16:00 2008 +0100 - - Handle arguments to multipathd from the init file - - Introduces a $ARGS variable through which we could - pass arguments to multipathd. - - There's also a change in the stop section of the initscript. If multipathd - is manually executed with an option like "-v9", the output of $DAEMON does not - match $PROCNAME. This leads to multipathd never being killed when stop is called - - Signed-off-by: Ritesh Raj Sarraf - Signed-off-by: Hannes Reinecke - -diff --git a/multipathd/multipathd.init.suse b/multipathd/multipathd.init.suse -index 664a4c5..d9bcc51 100755 ---- a/multipathd/multipathd.init.suse -+++ b/multipathd/multipathd.init.suse -@@ -22,6 +22,7 @@ - PATH=/bin:/usr/bin:/sbin:/usr/sbin - DAEMON=/sbin/multipathd - PIDFILE=/var/run/multipathd.pid -+ARGS="" - - # Set the maximum number of open files - MAX_OPEN_FDS=4096 -@@ -46,11 +47,11 @@ case "$1" in - - if [ -f $PIDFILE ]; then - PID="$(cat $PIDFILE)" -- PROCNAME="$(ps -o cmd --no-headers $PID)" -+ PROCNAME="$(ps -p $PID -o comm=)" - fi - -- if [ "$PROCNAME" != "$DAEMON" ]; then -- $DAEMON -+ if [ "$PROCNAME" != `basename $DAEMON` ]; then -+ $DAEMON $ARGS - fi - - # Remember status and be verbose -@@ -64,10 +65,10 @@ case "$1" in - # So implement a cruder version: - if [ -f $PIDFILE ]; then - PID="$(cat $PIDFILE)" -- PROCNAME="$(ps -o cmd --no-headers $PID)" -+ PROCNAME="$(ps -p $PID -o comm=)" - fi - -- if [ "$PROCNAME" == "$DAEMON" ]; then -+ if [ "$PROCNAME" == `basename $DAEMON` ]; then - kill -TERM $PID - fi - -@@ -109,8 +110,8 @@ case "$1" in - - if [ -f $PIDFILE ]; then - PID="$(cat $PIDFILE)" -- PROCNAME="$(ps -o cmd --no-headers $PID)" -- if [ "$PROCNAME" == "$DAEMON" ]; then -+ PROCNAME="$(ps -p $PID -o comm=)" -+ if [ "$PROCNAME" == `basename $DAEMON` ]; then - (exit 0) - else - (exit 1) diff --git a/multipath-tools-implement-dev_loss_tmo b/multipath-tools-implement-dev_loss_tmo deleted file mode 100644 index b1813ca..0000000 --- a/multipath-tools-implement-dev_loss_tmo +++ /dev/null @@ -1,423 +0,0 @@ -From 4c6e3b7eff9825353610bfc3130276e6f5233247 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 13 Jan 2009 16:01:30 +0100 -Subject: [PATCH] Implement dev_loss_tmo and fast_io_fail_tmo - -When using multipath the 'dev_loss_tmo' and 'fast_io_fail_tmo' -settings should be as small as possible to avoid any stalls -in multipathd. So we should be able to configure both -from within mulitpath. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/config.c | 2 + - libmultipath/config.h | 4 + - libmultipath/dict.c | 144 ++++++++++++++++++++++++++++++++++++++++++++ - libmultipath/discovery.c | 104 +++++++++++++++++++++++++++++++ - libmultipath/discovery.h | 1 + - libmultipath/structs_vec.c | 6 ++ - multipath/multipath.conf.5 | 12 ++++ - 7 files changed, 273 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 83da6e7..ea7ad99 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -463,6 +463,8 @@ load_config (char * file) - conf->dev_type = DEV_NONE; - conf->minio = 1000; - conf->max_fds = 0; -+ conf->dev_loss_tmo = 0; -+ conf->fast_io_fail_tmo = 0; - conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR); - - /* -diff --git a/libmultipath/config.h b/libmultipath/config.h -index fc0e22d..7d23927 100644 ---- a/libmultipath/config.h -+++ b/libmultipath/config.h -@@ -29,6 +29,8 @@ struct hwentry { - int no_path_retry; - int minio; - int pg_timeout; -+ int dev_loss_tmo; -+ int fast_io_fail_tmo; - char * bl_product; - }; - -@@ -67,6 +69,8 @@ struct config { - int pg_timeout; - int max_fds; - int force_reload; -+ int dev_loss_tmo; -+ int fast_io_fail_tmo; - - char * dev; - char * sysfs_dir; -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index 09ecf51..ed77000 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -189,6 +189,46 @@ max_fds_handler(vector strvec) - } - - static int -+def_dev_loss_tmo_handler(vector strvec) -+{ -+ char * buff; -+ -+ buff = set_value(strvec); -+ -+ if (!buff) -+ return 1; -+ -+ if (strlen(buff) == 9 && -+ !strcmp(buff, "off")) -+ conf->dev_loss_tmo = -1; -+ else -+ conf->dev_loss_tmo = atoi(buff); -+ FREE(buff); -+ -+ return 0; -+} -+ -+static int -+def_fast_io_fail_tmo_handler(vector strvec) -+{ -+ char * buff; -+ -+ buff = set_value(strvec); -+ -+ if (!buff) -+ return 1; -+ -+ if (strlen(buff) == 9 && -+ !strcmp(buff, "off")) -+ conf->fast_io_fail_tmo = -1; -+ else -+ conf->fast_io_fail_tmo = atoi(buff); -+ FREE(buff); -+ -+ return 0; -+} -+ -+static int - def_weight_handler(vector strvec) - { - char * buff; -@@ -779,6 +819,54 @@ hw_pg_timeout_handler(vector strvec) - return 0; - } - -+static int -+hw_dev_loss_tmo_handler(vector strvec) -+{ -+ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); -+ char * buff; -+ -+ if (!hwe) -+ return 1; -+ -+ buff = set_value(strvec); -+ -+ if (!buff) -+ return 1; -+ -+ if (strlen(buff) == 9 && -+ !strcmp(buff, "off")) -+ hwe->dev_loss_tmo = -1; -+ else -+ hwe->dev_loss_tmo = atoi(buff); -+ FREE(buff); -+ -+ return 0; -+} -+ -+static int -+hw_fast_io_fail_tmo_handler(vector strvec) -+{ -+ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); -+ char * buff; -+ -+ if (!hwe) -+ return 1; -+ -+ buff = set_value(strvec); -+ -+ if (!buff) -+ return 1; -+ -+ if (strlen(buff) == 9 && -+ !strcmp(buff, "off")) -+ hwe->fast_io_fail_tmo = -1; -+ else -+ hwe->fast_io_fail_tmo = atoi(buff); -+ FREE(buff); -+ -+ return 0; -+} -+ - /* - * multipaths block handlers - */ -@@ -1406,6 +1494,36 @@ snprint_hw_path_checker (char * buff, int len, void * data) - } - - static int -+snprint_hw_dev_loss_tmo (char * buff, int len, void * data) -+{ -+ struct hwentry * hwe = (struct hwentry *)data; -+ -+ if (!hwe->dev_loss_tmo) -+ return 0; -+ if (hwe->dev_loss_tmo == conf->dev_loss_tmo) -+ return 0; -+ -+ if (hwe->dev_loss_tmo < 0) -+ return snprintf(buff, len, "off"); -+ return snprintf(buff, len, "%u", hwe->dev_loss_tmo); -+} -+ -+static int -+snprint_hw_fast_io_fail_tmo (char * buff, int len, void * data) -+{ -+ struct hwentry * hwe = (struct hwentry *)data; -+ -+ if (!hwe->fast_io_fail_tmo) -+ return 0; -+ if (hwe->fast_io_fail_tmo == conf->fast_io_fail_tmo) -+ return 0; -+ -+ if (hwe->fast_io_fail_tmo < 0) -+ return snprintf(buff, len, "off"); -+ return snprintf(buff, len, "%u", hwe->fast_io_fail_tmo); -+} -+ -+static int - snprint_def_polling_interval (char * buff, int len, void * data) - { - if (conf->checkint == DEFAULT_CHECKINT) -@@ -1565,6 +1683,28 @@ snprint_max_fds (char * buff, int len, void * data) - } - - static int -+snprint_def_dev_loss_tmo (char * buff, int len, void * data) -+{ -+ if (!conf->dev_loss_tmo) -+ return 0; -+ -+ if (conf->dev_loss_tmo < 0) -+ return snprintf(buff, len, "off"); -+ return snprintf(buff, len, "%d", conf->dev_loss_tmo); -+} -+ -+static int -+snprint_def_fast_io_fail_tmo (char * buff, int len, void * data) -+{ -+ if (!conf->fast_io_fail_tmo) -+ return 0; -+ -+ if (conf->fast_io_fail_tmo < 0) -+ return snprintf(buff, len, "off"); -+ return snprintf(buff, len, "%d", conf->fast_io_fail_tmo); -+} -+ -+static int - snprint_def_rr_weight (char * buff, int len, void * data) - { - if (!conf->rr_weight) -@@ -1681,6 +1821,8 @@ init_keywords(void) - install_keyword("failback", &default_failback_handler, &snprint_def_failback); - install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io); - install_keyword("max_fds", &max_fds_handler, &snprint_max_fds); -+ install_keyword("dev_loss_tmo", &def_dev_loss_tmo_handler, &snprint_def_dev_loss_tmo); -+ install_keyword("fast_io_fail_tmo", &def_fast_io_fail_tmo_handler, &snprint_def_fast_io_fail_tmo); - install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight); - install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry); - install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout); -@@ -1739,6 +1881,8 @@ init_keywords(void) - install_keyword("no_path_retry", &hw_no_path_retry_handler, &snprint_hw_no_path_retry); - install_keyword("rr_min_io", &hw_minio_handler, &snprint_hw_rr_min_io); - install_keyword("pg_timeout", &hw_pg_timeout_handler, &snprint_hw_pg_timeout); -+ install_keyword("dev_loss_tmo", &hw_dev_loss_tmo_handler, &snprint_hw_dev_loss_tmo); -+ install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_tmo_handler, &snprint_hw_fast_io_fail_tmo); - install_sublevel_end(); - - install_keyword_root("multipaths", &multipaths_handler); -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index afd247d..6e4ce1e 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -209,6 +209,110 @@ sysfs_get_fc_nodename (struct sysfs_device * dev, char * node, - return 1; - } - -+int -+sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo) -+{ -+ char attr_path[SYSFS_PATH_SIZE]; -+ char host_path[SYSFS_PATH_SIZE]; -+ char attr_value[NAME_SIZE]; -+ DIR *host_dir, *rport_dir; -+ struct dirent *host_ent, *rport_ent; -+ int host, channel, lun, port, num; -+ int rport_channel = -1; -+ int rport_id = -1; -+ -+ if (dev_loss_tmo == 0 || fast_io_fail_tmo == 0) { -+ condlog(4, "%s: no FC settings", pp->dev); -+ return 0; -+ } -+ -+ if (safe_sprintf(host_path, "/sys/class/fc_host/host%i/device", -+ pp->sg_id.host_no)) { -+ condlog(0, "host_path too small"); -+ return 1; -+ } -+ if (!(host_dir = opendir(host_path))) { -+ condlog(3, "host %d not a FC HBA", pp->sg_id.host_no); -+ return 0; -+ } -+ -+ while (rport_channel < 0 && rport_id < 0 && -+ (host_ent = readdir(host_dir))) { -+ if (sscanf(host_ent->d_name, "rport-%d:%d-%d", -+ &host, &port, &num) != 3) -+ continue; -+ -+ if (host != pp->sg_id.host_no) -+ continue; -+ -+ if (safe_sprintf(attr_path, "%s/%s", -+ host_path, host_ent->d_name)) { -+ condlog(0, "target_path too small"); -+ continue; -+ } -+ -+ if (!(rport_dir = opendir(attr_path))) { -+ condlog(1, "cannot open rport path '%s'", attr_path); -+ continue; -+ } -+ -+ while ((rport_ent = readdir(rport_dir))) { -+ if (sscanf(rport_ent->d_name, "target%d:%d:%d", -+ &host, &channel, &lun) != 3) -+ continue; -+ -+ if (host != pp->sg_id.host_no && -+ channel != pp->sg_id.channel && -+ lun != pp->sg_id.scsi_id) -+ continue; -+ -+ rport_channel = port; -+ rport_id = num; -+ break; -+ } -+ } -+ -+ if (rport_channel < 0 && rport_id < 0) { -+ condlog(1, "No rport found"); -+ return 0; -+ } -+ -+ if (safe_sprintf(attr_path, -+ "/class/fc_remote_ports/rport-%d:%d-%d", -+ pp->sg_id.host_no, rport_channel, rport_id)) { -+ condlog(0, "attr_path too small"); -+ return 0; -+ } -+ -+ if (dev_loss_tmo < 0) -+ sprintf(attr_value, "%d", 0); -+ else -+ sprintf(attr_value, "%d", dev_loss_tmo); -+ num = sysfs_attr_set_value(attr_path, "dev_loss_tmo", -+ attr_value, strlen(attr_value)); -+ if (num > 0) -+ condlog(4, "%s: set dev_loss_tmo to %d", pp->dev, -+ dev_loss_tmo); -+ else -+ condlog(4, "%s: failed to set dev_loss_tmo (%d)", -+ pp->dev, errno); -+ -+ if (fast_io_fail_tmo < 0) -+ sprintf(attr_value, "%d", 0); -+ else -+ sprintf(attr_value, "%d", fast_io_fail_tmo); -+ num = sysfs_attr_set_value(attr_path, "fast_io_fail_tmo", -+ attr_value, strlen(attr_value)); -+ if (num > 0) -+ condlog(4, "%s: set fast_io_fail_tmo to %d", pp->dev, -+ fast_io_fail_tmo); -+ else -+ condlog(4, "%s: failed to set fast_io_fail_tmo (%d)", -+ pp->dev, errno); -+ -+ return num == strlen(attr_value) ? 0 : 1; -+} -+ - static int - opennode (char * dev, int mode) - { -diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h -index 05b1cfe..3749674 100644 ---- a/libmultipath/discovery.h -+++ b/libmultipath/discovery.h -@@ -32,6 +32,7 @@ int devt2devname (char *, char *); - int pathinfo (struct path *, vector hwtable, int mask); - struct path * store_pathinfo (vector pathvec, vector hwtable, - char * devname, int flag); -+int sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo); - - /* - * discovery bitmask -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index a1d9632..1632c9d 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -479,6 +479,12 @@ verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec) - free_path(pp); - } - } else { -+ if (pp->hwe) -+ sysfs_set_fc_values(pp, pp->hwe->dev_loss_tmo, -+ pp->hwe->fast_io_fail_tmo); -+ else -+ sysfs_set_fc_values(pp, conf->dev_loss_tmo, -+ conf->fast_io_fail_tmo); - condlog(4, "%s: verified path %s dev_t %s", - mpp->alias, pp->dev, pp->dev_t); - } -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index 8ac1f1c..926ff69 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -263,6 +263,14 @@ Default is - .B bindings_file - The full pathname of the binding file to be used when the user_friendly_names option is set. Defaults to - .I /var/lib/multipath/bindings -+.TP -+.B dev_loss_tmo -+The default dev_loss_tmo setting for an FC remote port in seconds. If an rport has vanished from the fabric all devices on that port will be removed from sysfs after this timeout. -+.TP -+.B fast_io_fail_tmo -+The default fast_io_fail_tmo setting for an FC remote port in seconds. If an rport has vanished from the fabric all I/O to the devices on that port will be terminated after this timeout. Should be smaller than -+.B dev_loss_tmo -+setting. - . - .SH "blacklist section" - The -@@ -413,6 +421,10 @@ section: - .B no_path_retry - .TP - .B rr_min_io -+.TP -+.B dev_loss_tmo -+.TP -+.B fast_io_fail_tmo - .RE - .PD - .LP --- -1.5.3.2 - diff --git a/multipath-tools-implement-map-resize b/multipath-tools-implement-map-resize deleted file mode 100644 index e795b2a..0000000 --- a/multipath-tools-implement-map-resize +++ /dev/null @@ -1,541 +0,0 @@ -commit 4b080ac4b0124a911e3785ce3ac77001390d1a23 -Author: Hannes Reinecke -Date: Fri Sep 26 16:07:13 2008 +0200 - - multipath: Implement 'resize map' cli command - - To properly support device resize we'll have to notify - multipath about the size changes, too. - - References: FATE#302007 - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 43324c6..8444ef2 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -348,7 +348,16 @@ domap (struct multipath * mpp) - - case ACT_RELOAD: - r = (dm_addmap_reload(mpp->alias, mpp->params, mpp->size, NULL) -- && dm_simplecmd(DM_DEVICE_RESUME, mpp->alias)); -+ && dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, 1)); -+ break; -+ -+ case ACT_RESIZE: -+ r = dm_addmap_reload(mpp->alias, mpp->params, mpp->size, NULL); -+ if (!r) -+ r = dm_addmap_reload_ro(mpp->alias, mpp->params, -+ mpp->size, NULL); -+ if (r) -+ r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, 0); - break; - - case ACT_RENAME: -diff --git a/libmultipath/configure.h b/libmultipath/configure.h -index 75d5057..25891ba 100644 ---- a/libmultipath/configure.h -+++ b/libmultipath/configure.h -@@ -7,6 +7,7 @@ - #define ACT_SWITCHPG_STR "switchpg" - #define ACT_RENAME_STR "rename" - #define ACT_CREATE_STR "create" -+#define ACT_RESIZE_STR "resize" - - enum actions { - ACT_UNDEF, -@@ -15,7 +16,8 @@ enum actions { - ACT_RELOAD, - ACT_SWITCHPG, - ACT_RENAME, -- ACT_CREATE -+ ACT_CREATE, -+ ACT_RESIZE, - }; - - #define FLUSH_ONE 1 -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 70e10c2..92afae7 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -150,7 +150,7 @@ dm_prereq (void) - } - - extern int --dm_simplecmd (int task, const char *name) { -+dm_simplecmd (int task, const char *name, int no_flush) { - int r = 0; - struct dm_task *dmt; - -@@ -163,7 +163,8 @@ dm_simplecmd (int task, const char *name) { - dm_task_no_open_count(dmt); - dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ - #ifdef LIBDM_API_FLUSH -- dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ -+ if (no_flush) -+ dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ - #endif - - r = dm_task_run (dmt); -@@ -536,7 +537,7 @@ dm_flush_map (const char * mapname) - return 1; - } - -- r = dm_simplecmd(DM_DEVICE_REMOVE, mapname); -+ r = dm_simplecmd(DM_DEVICE_REMOVE, mapname, 0); - - if (r) { - condlog(4, "multipath map %s removed", mapname); -@@ -933,7 +934,7 @@ dm_remove_partmaps (const char * mapname) - */ - condlog(4, "partition map %s removed", - names->name); -- dm_simplecmd(DM_DEVICE_REMOVE, names->name); -+ dm_simplecmd(DM_DEVICE_REMOVE, names->name, 0); - } - - next = names->next; -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index a340c00..b262efa 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -3,7 +3,7 @@ - - void dm_init(void); - int dm_prereq (void); --int dm_simplecmd (int, const char *); -+int dm_simplecmd (int, const char *, int); - int dm_addmap_create (const char *, const char *, - unsigned long long size, const char *uuid); - int dm_addmap_create_ro (const char *, const char *, -diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h -index e7fa3e7..2cd762f 100644 ---- a/libmultipath/sysfs.h -+++ b/libmultipath/sysfs.h -@@ -21,5 +21,6 @@ struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device - void sysfs_device_put(struct sysfs_device *dev); - char *sysfs_attr_get_value(const char *devpath, const char *attr_name); - int sysfs_resolve_link(char *path, size_t size); -+int sysfs_get_size (struct sysfs_device * dev, unsigned long long * size); - - #endif -diff --git a/multipathd/cli.c b/multipathd/cli.c -index 7eaac73..f5b9797 100644 ---- a/multipathd/cli.c -+++ b/multipathd/cli.c -@@ -155,6 +155,7 @@ load_keys (void) - r += add_key(keys, "resume", RESUME, 0); - r += add_key(keys, "reinstate", REINSTATE, 0); - r += add_key(keys, "fail", FAIL, 0); -+ r += add_key(keys, "resize", RESIZE, 0); - r += add_key(keys, "paths", PATHS, 0); - r += add_key(keys, "maps", MAPS, 0); - r += add_key(keys, "multipaths", MAPS, 0); -diff --git a/multipathd/cli.h b/multipathd/cli.h -index 8c83eab..d4a038c 100644 ---- a/multipathd/cli.h -+++ b/multipathd/cli.h -@@ -7,6 +7,7 @@ enum { - __RESUME, - __REINSTATE, - __FAIL, -+ __RESIZE, - __PATHS, - __MAPS, - __PATH, -@@ -30,6 +31,7 @@ enum { - #define RESUME (1 << __RESUME) - #define REINSTATE (1 << __REINSTATE) - #define FAIL (1 << __FAIL) -+#define RESIZE (1 << __RESIZE) - #define PATHS (1 << __PATHS) - #define MAPS (1 << __MAPS) - #define PATH (1 << __PATH) -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index c84805a..38130f5 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include "main.h" - #include "cli.h" -@@ -362,12 +363,139 @@ cli_del_map (void * v, char ** reply, int * len, void * data) - } - - int -+reload_paths(struct multipath *mpp, struct vectors * vecs) -+{ -+ struct pathgroup *pgp; -+ struct path *pp; -+ int i, j, err = 1; -+ char *dev; -+ vector path_names; -+ -+ path_names = vector_alloc(); -+ if (!path_names){ -+ condlog(0, "%s: unable to allcoate space for pathnames vector", -+ mpp->alias); -+ return 1; -+ } -+ vector_foreach_slot(mpp->pg, pgp, i) { -+ vector_foreach_slot(pgp->paths, pp, j) { -+ -+ dev = strdup(pp->dev); -+ if (!dev) { -+ condlog(0, "%s: unable to allocate path name", -+ mpp->alias); -+ goto out; -+ } -+ if (!vector_alloc_slot(path_names)){ -+ condlog(0, "%s: unable to allocate path name slot", -+ mpp->alias); -+ free(dev); -+ goto out; -+ } -+ vector_set_slot(path_names, dev); -+ } -+ } -+ vector_foreach_slot(path_names, dev, i) { -+ err = ev_remove_path(dev, vecs); -+ if (err) { -+ condlog(0, "%s: couldn't remove path '%s' : %s", -+ mpp->alias, dev, strerror(errno)); -+ goto out; -+ } -+ err = ev_add_path(dev, vecs); -+ if (err) -+ condlog(0, "%s: couldn't add path '%s' : %s", -+ mpp->alias, dev, strerror(errno)); -+ } -+out: -+ vector_foreach_slot(path_names, dev, i) -+ free(dev); -+ vector_free(path_names); -+ return err; -+} -+ -+int resize_map(struct multipath *mpp, unsigned long long size, -+ struct vectors * vecs) -+{ -+ mpp->size = size; -+ update_mpp_paths(mpp, vecs->pathvec); -+ setup_map(mpp); -+ mpp->action = ACT_RESIZE; -+ if (domap(mpp) <= 0) { -+ condlog(0, "%s: failed to resize map : %s", mpp->alias, -+ strerror(errno)); -+ return 1; -+ } -+ return 0; -+} -+ -+int -+cli_resize(void *v, char **reply, int *len, void *data) -+{ -+ struct vectors * vecs = (struct vectors *)data; -+ char * mapname = get_keyparam(v, MAP); -+ struct multipath *mpp; -+ int minor; -+ unsigned long long size; -+ struct pathgroup *pgp; -+ struct path *pp; -+ -+ condlog(2, "%s: resize map (operator)", mapname); -+ if (sscanf(mapname, "dm-%d", &minor) == 1) -+ mpp = find_mp_by_minor(vecs->mpvec, minor); -+ else -+ mpp = find_mp_by_alias(vecs->mpvec, mapname); -+ -+ if (!mpp) { -+ condlog(0, "%s: invalid map name. cannot resize", mapname); -+ return 1; -+ } -+ -+ pgp = VECTOR_SLOT(mpp->pg, 0); -+ pp = VECTOR_SLOT(pgp->paths, 0); -+ if (sysfs_get_size(pp->sysdev, &size)) { -+ condlog(0, "%s: couldn't get size for sysfs. cannot resize", -+ mapname); -+ return 1; -+ } -+ if (size == mpp->size) { -+ condlog(0, "%s: map is still the same size (%llu)", mapname, -+ mpp->size); -+ return 0; -+ } -+ condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size, -+ size); -+ if (size > mpp->size) { -+ if (reload_paths(mpp, vecs) != 0) { -+ condlog(0, "%s: failed to reload paths", mapname); -+ return 1; -+ } -+ if (resize_map(mpp, size, vecs) != 0) -+ return 1; -+ } -+ else { -+ if (resize_map(mpp, size, vecs) != 0) -+ return 1; -+ if (reload_paths(mpp, vecs) != 0) { -+ condlog(0, "%s: failed to reload paths", mapname); -+ return 1; -+ } -+ } -+ dm_lib_release(); -+ setup_multipath(vecs, mpp); -+ sync_map_state(mpp); -+ -+ return 0; -+} -+ -+int - cli_switch_group(void * v, char ** reply, int * len, void * data) - { - char * mapname = get_keyparam(v, MAP); - int groupnum = atoi(get_keyparam(v, GROUP)); -- -- condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum); -+ -+ condlog(2, "%s: switch to path group #%i (operator)", -+ mapname, groupnum); - - return dm_switchgroup(mapname, groupnum); - } -@@ -376,7 +504,7 @@ int - cli_reconfigure(void * v, char ** reply, int * len, void * data) - { - struct vectors * vecs = (struct vectors *)data; -- -+ - condlog(2, "reconfigure (operator)"); - - return reconfigure(vecs); -@@ -387,18 +515,17 @@ cli_suspend(void * v, char ** reply, int * len, void * data) - { - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, MAP); -- int r = dm_simplecmd(DM_DEVICE_SUSPEND, param); -+ int r = dm_simplecmd(DM_DEVICE_SUSPEND, param, 1); -+ struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); - - condlog(2, "%s: suspend (operator)", param); - - if (!r) /* error */ - return 1; -- -- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); - - if (!mpp) - return 1; -- -+ - dm_get_info(param, &mpp->dmi); - return 0; - } -@@ -408,18 +535,17 @@ cli_resume(void * v, char ** reply, int * len, void * data) - { - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, MAP); -- int r = dm_simplecmd(DM_DEVICE_RESUME, param); -+ int r = dm_simplecmd(DM_DEVICE_RESUME, param, 1); -+ struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); - - condlog(2, "%s: resume (operator)", param); - - if (!r) /* error */ - return 1; -- -- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); - - if (!mpp) - return 1; -- -+ - dm_get_info(param, &mpp->dmi); - return 0; - } -@@ -430,7 +556,7 @@ cli_reinstate(void * v, char ** reply, int * len, void * data) - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, PATH); - struct path * pp; -- -+ - pp = find_path_by_dev(vecs->pathvec, param); - - if (!pp) -@@ -453,7 +579,7 @@ cli_fail(void * v, char ** reply, int * len, void * data) - char * param = get_keyparam(v, PATH); - struct path * pp; - int r; -- -+ - pp = find_path_by_dev(vecs->pathvec, param); - - if (!pp) -@@ -477,67 +603,67 @@ cli_fail(void * v, char ** reply, int * len, void * data) - int - show_blacklist (char ** r, int * len) - { -- char *c = NULL; -- char *reply = NULL; -- unsigned int maxlen = INITIAL_REPLY_LEN; -- int again = 1; -+ char *c = NULL; -+ char *reply = NULL; -+ unsigned int maxlen = INITIAL_REPLY_LEN; -+ int again = 1; - -- while (again) { -+ while (again) { - reply = MALLOC(maxlen); - if (!reply) - return 1; - -- c = reply; -- c += snprint_blacklist_report(c, maxlen); -- again = ((c - reply) == maxlen); -- if (again) { -+ c = reply; -+ c += snprint_blacklist_report(c, maxlen); -+ again = ((c - reply) == maxlen); -+ if (again) { - maxlen *= 2; - FREE(reply); -- continue; -- } -- } -+ continue; -+ } -+ } - -- *r = reply; -- *len = (int)(c - reply + 1); -+ *r = reply; -+ *len = (int)(c - reply + 1); - -- return 0; -+ return 0; - } - - int - cli_list_blacklist (void * v, char ** reply, int * len, void * data) - { -- condlog(3, "list blacklist (operator)"); -+ condlog(3, "list blacklist (operator)"); - -- return show_blacklist(reply, len); -+ return show_blacklist(reply, len); - } - - int - show_devices (char ** r, int * len, struct vectors *vecs) - { -- char *c = NULL; -- char *reply = NULL; -- unsigned int maxlen = INITIAL_REPLY_LEN; -- int again = 1; -- -- while (again) { -- reply = MALLOC(maxlen); -- if (!reply) -- return 1; -- -- c = reply; -- c += snprint_devices(c, maxlen, vecs); -- again = ((c - reply) == maxlen); -- if (again) { -- maxlen *= 2; -- FREE(reply); -- continue; -- } -- } -- -- *r = reply; -- *len = (int)(c - reply + 1); -- -- return 0; -+ char *c = NULL; -+ char *reply = NULL; -+ unsigned int maxlen = INITIAL_REPLY_LEN; -+ int again = 1; -+ -+ while (again) { -+ reply = MALLOC(maxlen); -+ if (!reply) -+ return 1; -+ -+ c = reply; -+ c += snprint_devices(c, maxlen, vecs); -+ again = ((c - reply) == maxlen); -+ if (again) { -+ maxlen *= 2; -+ FREE(reply); -+ continue; -+ } -+ } -+ -+ *r = reply; -+ *len = (int)(c - reply + 1); -+ -+ return 0; - } - - int -@@ -545,7 +671,7 @@ cli_list_devices (void * v, char ** reply, int * len, void * data) - { - struct vectors * vecs = (struct vectors *)data; - -- condlog(3, "list devices (operator)"); -+ condlog(3, "list devices (operator)"); - -- return show_devices(reply, len, vecs); -+ return show_devices(reply, len, vecs); - } -diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h -index a688481..72ed54a 100644 ---- a/multipathd/cli_handlers.h -+++ b/multipathd/cli_handlers.h -@@ -14,6 +14,7 @@ int cli_add_map (void * v, char ** reply, int * len, void * data); - int cli_del_map (void * v, char ** reply, int * len, void * data); - int cli_switch_group(void * v, char ** reply, int * len, void * data); - int cli_reconfigure(void * v, char ** reply, int * len, void * data); -+int cli_resize(void * v, char ** reply, int * len, void * data); - int cli_suspend(void * v, char ** reply, int * len, void * data); - int cli_resume(void * v, char ** reply, int * len, void * data); - int cli_reinstate(void * v, char ** reply, int * len, void * data); -diff --git a/multipathd/main.c b/multipathd/main.c -index 4fbac3b..b1e440a 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -147,7 +147,7 @@ coalesce_maps(struct vectors *vecs, vector nmpv) - return 0; - } - --static void -+void - sync_map_state(struct multipath *mpp) - { - struct pathgroup *pgp; -@@ -709,6 +709,7 @@ uxlsnrloop (void * ap) - set_handler_callback(RECONFIGURE, cli_reconfigure); - set_handler_callback(SUSPEND+MAP, cli_suspend); - set_handler_callback(RESUME+MAP, cli_resume); -+ set_handler_callback(RESIZE+MAP, cli_resize); - set_handler_callback(REINSTATE+PATH, cli_reinstate); - set_handler_callback(FAIL+PATH, cli_fail); - -diff --git a/multipathd/main.h b/multipathd/main.h -index 1a6dc55..d73cd70 100644 ---- a/multipathd/main.h -+++ b/multipathd/main.h -@@ -9,5 +9,6 @@ int ev_add_path (char *, struct vectors *); - int ev_remove_path (char *, struct vectors *); - int ev_add_map (struct sysfs_device *, struct vectors *); - int ev_remove_map (char *, struct vectors *); -+void sync_map_state (struct multipath *); - - #endif /* MAIN_H */ diff --git a/multipath-tools-implement-sysfs-attr-set-value b/multipath-tools-implement-sysfs-attr-set-value deleted file mode 100644 index aeb6556..0000000 --- a/multipath-tools-implement-sysfs-attr-set-value +++ /dev/null @@ -1,143 +0,0 @@ -From e3354354518377b34fa3b501c11a62b61a54b0d4 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 13 Jan 2009 15:34:55 +0100 -Subject: [PATCH] Implement sysfs_attr_set_value() - -Complement to sysfs_attr_get_value(). We might want to modify some -sysfs values from multipathing. - -References: bnc#464155 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/sysfs.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ - libmultipath/sysfs.h | 2 + - 2 files changed, 102 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c -index e00a101..4a472ae 100644 ---- a/libmultipath/sysfs.c -+++ b/libmultipath/sysfs.c -@@ -461,6 +461,106 @@ out: - return attr && attr->value && strlen(attr->value) ? attr->value : NULL; - } - -+int sysfs_attr_set_value(const char *devpath, const char *attr_name, -+ char *value, int value_len) -+{ -+ char path_full[PATH_SIZE]; -+ const char *path; -+ struct sysfs_attr *attr_loop; -+ struct sysfs_attr *attr = NULL; -+ struct stat statbuf; -+ int fd; -+ ssize_t size = 0; -+ size_t sysfs_len; -+ -+ dbg("open '%s'/'%s'", devpath, attr_name); -+ sysfs_len = strlcpy(path_full, sysfs_path, sizeof(path_full)); -+ if(sysfs_len >= sizeof(path_full)) -+ sysfs_len = sizeof(path_full) - 1; -+ path = &path_full[sysfs_len]; -+ strlcat(path_full, devpath, sizeof(path_full)); -+ strlcat(path_full, "/", sizeof(path_full)); -+ strlcat(path_full, attr_name, sizeof(path_full)); -+ -+ /* look for attribute in cache */ -+ list_for_each_entry(attr_loop, &attr_list, node) { -+ if (strcmp(attr_loop->path, path) == 0) { -+ dbg("found in cache '%s'", attr_loop->path); -+ attr = attr_loop; -+ } -+ } -+ if (!attr) { -+ /* store attribute in cache */ -+ dbg("new uncached attribute '%s'", path_full); -+ attr = malloc(sizeof(struct sysfs_attr)); -+ if (attr == NULL) -+ return -1; -+ memset(attr, 0x00, sizeof(struct sysfs_attr)); -+ strlcpy(attr->path, path, sizeof(attr->path)); -+ dbg("add to cache '%s'", path_full); -+ list_add(&attr->node, &attr_list); -+ } else { -+ /* clear old value */ -+ if(attr->value) -+ memset(attr->value, 0x00, sizeof(attr->value)); -+ } -+ -+ if (lstat(path_full, &statbuf) != 0) { -+ dbg("stat '%s' failed: %s", path_full, strerror(errno)); -+ goto out; -+ } -+ -+ if (S_ISLNK(statbuf.st_mode)) { -+ /* links return the last element of the target path */ -+ char link_target[PATH_SIZE]; -+ int len; -+ const char *pos; -+ -+ len = readlink(path_full, link_target, sizeof(link_target)); -+ if (len > 0) { -+ link_target[len] = '\0'; -+ pos = strrchr(link_target, '/'); -+ if (pos != NULL) { -+ dbg("cache '%s' with link value '%s'", -+ path_full, value); -+ strlcpy(attr->value_local, &pos[1], -+ sizeof(attr->value_local)); -+ attr->value = attr->value_local; -+ } -+ } -+ goto out; -+ } -+ -+ /* skip directories */ -+ if (S_ISDIR(statbuf.st_mode)) -+ goto out; -+ -+ /* skip non-readable files */ -+ if ((statbuf.st_mode & S_IRUSR) == 0) -+ goto out; -+ -+ /* write attribute value */ -+ fd = open(path_full, O_WRONLY); -+ if (fd < 0) { -+ dbg("attribute '%s' can not be opened: %s", -+ path_full, strerror(errno)); -+ goto out; -+ } -+ size = write(fd, value, value_len); -+ close(fd); -+ if (size < 0) -+ goto out; -+ -+ /* successfully wrote new value, store it */ -+ remove_trailing_chars(value, '\n'); -+ dbg("cache '%s' with attribute value '%s'", path_full, value); -+ strlcpy(attr->value_local, value, sizeof(attr->value_local)); -+ attr->value = attr->value_local; -+ -+out: -+ return size; -+} -+ - int sysfs_lookup_devpath_by_subsys_id(char *devpath_full, size_t len, - const char *subsystem, const char *id) - { -diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h -index 620962c..ac76acf 100644 ---- a/libmultipath/sysfs.h -+++ b/libmultipath/sysfs.h -@@ -20,6 +20,8 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev); - struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device *dev, const char *subsystem); - void sysfs_device_put(struct sysfs_device *dev); - char *sysfs_attr_get_value(const char *devpath, const char *attr_name); -+int sysfs_attr_set_value(const char *devpath, const char *attr_name, -+ char *value, int value_len); - int sysfs_resolve_link(char *path, size_t size); - int sysfs_get_size (struct sysfs_device * dev, unsigned long long * size); - --- -1.5.3.2 - diff --git a/multipath-tools-include-device-handler-modules b/multipath-tools-include-device-handler-modules deleted file mode 100644 index f30c72e..0000000 --- a/multipath-tools-include-device-handler-modules +++ /dev/null @@ -1,26 +0,0 @@ -Subject: Add device-handler modules to mkinitrd script -From: Hannes Reinecke -Date: Mon Oct 27 14:39:59 2008 +0100: -Git: 9ac06d484adb369c1848f5793cf36ab681899ef7 - -The mkinitrd boot script still tries to include the obsolete -device-mapper hardware handler modules. Update it to include -the SCSI device-handler modules. - -References: 431877 - -Signed-off-by: Hannes Reinecke - -diff --git a/multipath/boot-multipath.sh b/multipath/boot-multipath.sh -index a946785..ae11a26 100755 ---- a/multipath/boot-multipath.sh -+++ b/multipath/boot-multipath.sh -@@ -4,7 +4,7 @@ - #%provides: dmroot - #%programs: /sbin/multipath /lib/multipath/* - #%if: "$root_mpath" --#%modules: dm-multipath dm-round-robin dm-emc dm-hp_sw dm-rdac -+#%modules: dm-multipath dm-round-robin scsi-dh-emc scsi-dh-hp_sw scsi-dh-rdac scsi-dh-alua - # - ##### Multipath - ## diff --git a/multipath-tools-increase-bindings-file-lock-timeout b/multipath-tools-increase-bindings-file-lock-timeout deleted file mode 100644 index 0e94d04..0000000 --- a/multipath-tools-increase-bindings-file-lock-timeout +++ /dev/null @@ -1,27 +0,0 @@ -From 669b5c11d8c82252f9697e35d183a0c840386261 Mon Sep 17 00:00:00 2001 -From: Dave Wysochanski -Date: Sun, 28 Sep 2008 22:32:29 +0200 -Subject: [PATCH] [lib] Increase bindings file lock timeout to avoid failure of user_friendly_names - -On setups with a large number of paths / multipath maps, contention for -the advisory lock on the bindings file may take longer than 3 seconds, -and some multipath processes may create maps based on WWID despite having -user_friendly_names set. Increasing the timeout is a simple fix that -gets us a bit further. ---- - libmultipath/alias.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/libmultipath/alias.h b/libmultipath/alias.h -index 3d64b9b..fe1191b 100644 ---- a/libmultipath/alias.h -+++ b/libmultipath/alias.h -@@ -1,4 +1,4 @@ --#define BINDINGS_FILE_TIMEOUT 3 -+#define BINDINGS_FILE_TIMEOUT 30 - #define BINDINGS_FILE_HEADER \ - "# Multipath bindings, Version : 1.0\n" \ - "# NOTE: this file is automatically maintained by the multipath program.\n" \ --- -1.5.2.4 - diff --git a/multipath-tools-increase-loop-buffer-size b/multipath-tools-increase-loop-buffer-size deleted file mode 100644 index 820d2ef..0000000 --- a/multipath-tools-increase-loop-buffer-size +++ /dev/null @@ -1,31 +0,0 @@ -From 18903014d3e6402909e709fedaf669d2a55c1490 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 21 Oct 2008 10:22:16 +0200 -Subject: [PATCH] Increase buffer size in find_loop_by_file() - -find_loop_by_file() uses an internal buffer of 20 chars, which is compared -to a buffer of the size of 64 chars. Not good. - -References: 436428 - -Signed-off-by: Hannes Reinecke ---- - kpartx/lopart.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/kpartx/lopart.c b/kpartx/lopart.c -index b18d6fa..be483da 100644 ---- a/kpartx/lopart.c -+++ b/kpartx/lopart.c -@@ -105,7 +105,7 @@ is_loop_device (const char *device) - extern char * - find_loop_by_file (const char * filename) - { -- char dev[20]; -+ char dev[64]; - char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" }; - int i, j, fd; - struct stat statbuf; --- -1.5.2.4 - diff --git a/multipath-tools-kpartx-doesnt-remove-loop-device b/multipath-tools-kpartx-doesnt-remove-loop-device deleted file mode 100644 index dda1566..0000000 --- a/multipath-tools-kpartx-doesnt-remove-loop-device +++ /dev/null @@ -1,56 +0,0 @@ -From 67f0f96ae532f8fda862576fba6f718809ade128 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 14 Oct 2008 08:38:29 +0200 -Subject: [PATCH] kpartx -l does not remove it's loop device - -When doing a kpartx -l it does not remove it's loop device when done. - -The appended patch to multipath-tools could fix this. - -References: 417266 - -Signed-off-by: Philipp Zimmer -Signed-off-by: Hannes Reinecke ---- - kpartx/kpartx.c | 11 +++++++++++ - 1 files changed, 11 insertions(+), 0 deletions(-) - -diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c -index d1ba87c..43dcd13 100644 ---- a/kpartx/kpartx.c -+++ b/kpartx/kpartx.c -@@ -198,6 +198,7 @@ main(int argc, char **argv){ - char *mapname = NULL; - int loopro = 0; - int hotplug = 0; -+ int loopcreated = 0; - struct stat buf; - - initpts(); -@@ -292,6 +293,7 @@ main(int argc, char **argv){ - fprintf(stderr, "can't set up loop\n"); - exit (1); - } -+ loopcreated = 1; - } - device = loopdev; - } -@@ -394,6 +396,15 @@ main(int argc, char **argv){ - break; - } - -+ if (loopcreated && S_ISREG (buf.st_mode)) { -+ if (del_loop(device)) { -+ if (verbose) -+ printf("can't del loop : %s\n", -+ device); -+ exit(1); -+ } -+ printf("loop deleted : %s\n", device); -+ } - break; - - case DELETE: --- -1.5.2.4 - diff --git a/multipath-tools-link-directio-against-libaio b/multipath-tools-link-directio-against-libaio deleted file mode 100644 index 2049d7c..0000000 --- a/multipath-tools-link-directio-against-libaio +++ /dev/null @@ -1,74 +0,0 @@ -From 2fb0035d2322771bd9753e26a2a1c5babbfc2abc Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 30 Oct 2008 16:49:50 +0100 -Subject: [PATCH] Link directio checker against libaio - -The directio checker has to link against libaio explicitely, -otherwise any versioning information is lost. - -References: 433659 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/checkers/Makefile | 3 +++ - libmultipath/checkers/directio.c | 2 +- - multipath/Makefile | 2 +- - multipathd/Makefile | 2 +- - 4 files changed, 6 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/checkers/Makefile b/libmultipath/checkers/Makefile -index a20dfac..99b3dc2 100644 ---- a/libmultipath/checkers/Makefile -+++ b/libmultipath/checkers/Makefile -@@ -17,6 +17,9 @@ CFLAGS += -I.. - - all: $(LIBS) - -+libcheckdirectio.so: directio.o -+ $(CC) $(SHARED_FLAGS) -o $@ $^ -laio -+ - libcheck%.so: libsg.o %.o - $(CC) $(SHARED_FLAGS) -o $@ $^ - -diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c -index 5c92dac..c701609 100644 ---- a/libmultipath/checkers/directio.c -+++ b/libmultipath/checkers/directio.c -@@ -13,7 +13,7 @@ - #include - #include - #include --#include -+#include - #include - - #include "checkers.h" -diff --git a/multipath/Makefile b/multipath/Makefile -index 75d4ddf..a02107b 100644 ---- a/multipath/Makefile -+++ b/multipath/Makefile -@@ -7,7 +7,7 @@ include ../Makefile.inc - OBJS = main.o - - CFLAGS += -I$(multipathdir) -Wl,-rpath,$(libdir) --LDFLAGS += -lpthread -ldevmapper -laio -ldl \ -+LDFLAGS += -lpthread -ldevmapper -ldl \ - -lmultipath -L$(multipathdir) - - EXEC = multipath -diff --git a/multipathd/Makefile b/multipathd/Makefile -index b019959..565210f 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -6,7 +6,7 @@ include ../Makefile.inc - # basic flags setting - # - CFLAGS += -I$(multipathdir) -Wl,-rpath,$(libdir) --LDFLAGS += -lpthread -ldevmapper -lreadline -lncurses -laio -ldl \ -+LDFLAGS += -lpthread -ldevmapper -lreadline -lncurses -ldl \ - -lmultipath -L$(multipathdir) - - # --- -1.5.4.5 - diff --git a/multipath-tools-make-params-local b/multipath-tools-make-params-local deleted file mode 100644 index 69c3a6b..0000000 --- a/multipath-tools-make-params-local +++ /dev/null @@ -1,526 +0,0 @@ -From 28b790ea42f100c74f682f1abea6c33e7d0e3553 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 20 Nov 2008 12:36:24 +0100 -Subject: [PATCH] Make 'params' and 'status' local variables - -The 'params' and 'status' fields in the multipath structure are -just scratch variables where the output from device-mapper is stored -into. And as we call device-mapper quite frequently it really looks -not thread-safe as the multipath structure can be accessed from -all threads. So better make them local variables to eliminate this -problem. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/configure.c | 30 ++++++++++++++++-------------- - libmultipath/configure.h | 4 ++-- - libmultipath/devmapper.c | 12 +++++++----- - libmultipath/dmparser.c | 19 +++++++++++-------- - libmultipath/dmparser.h | 2 +- - libmultipath/print.c | 6 +++--- - libmultipath/print.h | 2 +- - libmultipath/structs.h | 2 -- - libmultipath/structs_vec.c | 20 ++++++++++++++++---- - libmultipath/waiter.c | 1 + - multipath/main.c | 13 +++++++++---- - multipathd/cli_handlers.c | 6 ++++-- - multipathd/main.c | 15 +++++++++++---- - 13 files changed, 82 insertions(+), 50 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 494ea70..eb7ac03 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -37,7 +37,7 @@ - #include "util.h" - - extern int --setup_map (struct multipath * mpp) -+setup_map (struct multipath * mpp, char * params, int params_size) - { - struct pathgroup * pgp; - int i; -@@ -89,7 +89,7 @@ setup_map (struct multipath * mpp) - * transform the mp->pg vector of vectors of paths - * into a mp->params strings to feed the device-mapper - */ -- if (assemble_map(mpp)) { -+ if (assemble_map(mpp, params, params_size)) { - condlog(0, "%s: problem assembing map", mpp->alias); - return 1; - } -@@ -298,7 +298,7 @@ lock_multipath (struct multipath * mpp, int lock) - #define DOMAP_DRY 3 - - extern int --domap (struct multipath * mpp) -+domap (struct multipath * mpp, char * params) - { - int r = 0; - -@@ -337,25 +337,25 @@ domap (struct multipath * mpp) - break; - } - -- r = dm_addmap_create(mpp->alias, mpp->params, mpp->size, -+ r = dm_addmap_create(mpp->alias, params, mpp->size, - mpp->wwid); - - if (!r) -- r = dm_addmap_create_ro(mpp->alias, mpp->params, -+ r = dm_addmap_create_ro(mpp->alias, params, - mpp->size, mpp->wwid); - - lock_multipath(mpp, 0); - break; - - case ACT_RELOAD: -- r = (dm_addmap_reload(mpp->alias, mpp->params, mpp->size, NULL) -+ r = (dm_addmap_reload(mpp->alias, params, mpp->size, NULL) - && dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, 1)); - break; - - case ACT_RESIZE: -- r = dm_addmap_reload(mpp->alias, mpp->params, mpp->size, NULL); -+ r = dm_addmap_reload(mpp->alias, params, mpp->size, NULL); - if (!r) -- r = dm_addmap_reload_ro(mpp->alias, mpp->params, -+ r = dm_addmap_reload_ro(mpp->alias, params, - mpp->size, NULL); - if (r) - r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, 0); -@@ -383,7 +383,7 @@ domap (struct multipath * mpp) - /* multipath daemon mode */ - mpp->stat_map_loads++; - condlog(2, "%s: load table [0 %llu %s %s]", mpp->alias, -- mpp->size, TGT_MPATH, mpp->params); -+ mpp->size, TGT_MPATH, params); - /* - * Required action is over, reset for the stateful daemon - */ -@@ -422,6 +422,7 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r - int r = 1; - int k, i; - char empty_buff[WWID_SIZE]; -+ char params[PARAMS_SIZE]; - struct multipath * mpp; - struct path * pp1; - struct path * pp2; -@@ -493,8 +494,9 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r - mpp->action = ACT_REJECT; - } - verify_paths(mpp, vecs, NULL); -- -- if (setup_map(mpp)) { -+ -+ params[0] = '\0'; -+ if (setup_map(mpp, params, PARAMS_SIZE)) { - remove_map(mpp, vecs, 0); - continue; - } -@@ -502,7 +504,7 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r - if (mpp->action == ACT_UNDEF) - select_action(mpp, curmp, force_reload); - -- r = domap(mpp); -+ r = domap(mpp, params); - - if (r == DOMAP_FAIL || r == DOMAP_RETRY) { - condlog(3, "%s: domap (%u) failure " -@@ -610,7 +612,7 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec) - - if (dev_type == DEV_DEVT) { - pp = find_path_by_devt(pathvec, dev); -- -+ - if (!pp) { - if (devt2devname(buff, dev)) - return NULL; -@@ -624,7 +626,7 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec) - - if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID)) - return NULL; -- -+ - if (store_path(pathvec, pp)) { - free_path(pp); - return NULL; -diff --git a/libmultipath/configure.h b/libmultipath/configure.h -index 25891ba..ec2800d 100644 ---- a/libmultipath/configure.h -+++ b/libmultipath/configure.h -@@ -23,8 +23,8 @@ enum actions { - #define FLUSH_ONE 1 - #define FLUSH_ALL 2 - --int setup_map (struct multipath * mpp); --int domap (struct multipath * mpp); -+int setup_map (struct multipath * mpp, char * params, int params_size); -+int domap (struct multipath * mpp, char * params); - int reinstate_paths (struct multipath *mpp); - int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload); - char * get_refwwid (char * dev, enum devtypes dev_type, vector pathvec); -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index cde98eb..a7ab41f 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -206,6 +206,8 @@ dm_addmap (int task, const char *name, const char *target, - goto freeout; - } - -+ condlog(4, "%s: addmap [0 %llu %s %s]\n", name, size, target, params); -+ - dm_task_no_open_count(dmt); - - r = dm_task_run (dmt); -@@ -323,7 +325,10 @@ dm_get_map(char * name, unsigned long long * size, char * outparams) - if (size) - *size = length; - -- if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE) -+ if (outparams) { -+ if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE) -+ r = 0; -+ } else - r = 0; - out: - dm_task_destroy(dmt); -@@ -756,10 +761,7 @@ dm_get_maps (vector mp) - goto out1; - - if (info > 0) { -- if (dm_get_map(names->name, &mpp->size, mpp->params)) -- goto out1; -- -- if (dm_get_status(names->name, mpp->status)) -+ if (dm_get_map(names->name, &mpp->size, NULL)) - goto out1; - - dm_get_uuid(names->name, mpp->wwid); -diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c -index d1face5..9441b11 100644 ---- a/libmultipath/dmparser.c -+++ b/libmultipath/dmparser.c -@@ -47,7 +47,7 @@ merge_words (char ** dst, char * word, int space) - * Transforms the path group vector into a proper device map string - */ - int --assemble_map (struct multipath * mp) -+assemble_map (struct multipath * mp, char * params, int len) - { - int i, j; - int shift, freechar; -@@ -57,15 +57,15 @@ assemble_map (struct multipath * mp) - struct path * pp; - - minio = mp->minio; -- p = mp->params; -- freechar = sizeof(mp->params); -+ p = params; -+ freechar = len; - - shift = snprintf(p, freechar, "%s %s %i %i", - mp->features, mp->hwhandler, - VECTOR_SIZE(mp->pg), mp->bestpg); - - if (shift >= freechar) { -- fprintf(stderr, "mp->params too small\n"); -+ condlog(0, "%s: params too small\n", mp->alias); - return 1; - } - p += shift; -@@ -76,7 +76,7 @@ assemble_map (struct multipath * mp) - shift = snprintf(p, freechar, " %s %i 1", mp->selector, - VECTOR_SIZE(pgp->paths)); - if (shift >= freechar) { -- fprintf(stderr, "mp->params too small\n"); -+ condlog(0, "%s: params too small\n", mp->alias); - return 1; - } - p += shift; -@@ -88,11 +88,14 @@ assemble_map (struct multipath * mp) - if (mp->rr_weight == RR_WEIGHT_PRIO - && pp->priority > 0) - tmp_minio = minio * pp->priority; -- -+ if (!strlen(pp->dev_t) ) { -+ condlog(0, "dev_t not set for '%s'\n", pp->dev); -+ return 1; -+ } - shift = snprintf(p, freechar, " %s %d", - pp->dev_t, tmp_minio); - if (shift >= freechar) { -- fprintf(stderr, "mp->params too small\n"); -+ condlog(0, "%s: params too small\n", mp->alias); - return 1; - } - p += shift; -@@ -100,7 +103,7 @@ assemble_map (struct multipath * mp) - } - } - if (freechar < 1) { -- fprintf(stderr, "mp->params too small\n"); -+ condlog(0, "%s: params too small\n", mp->alias); - return 1; - } - snprintf(p, 1, "\n"); -diff --git a/libmultipath/dmparser.h b/libmultipath/dmparser.h -index bf4b2c3..1b45df0 100644 ---- a/libmultipath/dmparser.h -+++ b/libmultipath/dmparser.h -@@ -1,3 +1,3 @@ --int assemble_map (struct multipath *); -+int assemble_map (struct multipath *, char *, int); - int disassemble_map (vector, char *, struct multipath *); - int disassemble_status (char *, struct multipath *); -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 7467411..9dea392 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -1276,11 +1276,11 @@ print_pathgroup (struct pathgroup * pgp, char * style) - } - - extern void --print_map (struct multipath * mpp) -+print_map (struct multipath * mpp, char * params) - { -- if (mpp->size && mpp->params) -+ if (mpp->size && params) - printf("0 %llu %s %s\n", -- mpp->size, TGT_MPATH, mpp->params); -+ mpp->size, TGT_MPATH, params); - return; - } - -diff --git a/libmultipath/print.h b/libmultipath/print.h -index a8be408..5fe826b 100644 ---- a/libmultipath/print.h -+++ b/libmultipath/print.h -@@ -54,7 +54,7 @@ void print_multipath_topology (struct multipath * mpp, int verbosity); - void print_path (struct path * pp, char * style); - void print_multipath (struct multipath * mpp, char * style); - void print_pathgroup (struct pathgroup * pgp, char * style); --void print_map (struct multipath * mpp); -+void print_map (struct multipath * mpp, char * params); - void print_all_paths (vector pathvec, int banner); - void print_all_paths_custo (vector pathvec, int banner, char *fmt); - void print_hwtable (vector hwtable); -diff --git a/libmultipath/structs.h b/libmultipath/structs.h -index 85d5109..658d6b2 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -151,8 +151,6 @@ struct multipath { - unsigned long long size; - vector paths; - vector pg; -- char params[PARAMS_SIZE]; -- char status[PARAMS_SIZE]; - struct dm_info * dmi; - - /* configlet pointers */ -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 17cafd1..e3cace9 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -237,14 +237,20 @@ extract_hwe_from_path(struct multipath * mpp) - static int - update_multipath_table (struct multipath *mpp, vector pathvec) - { -+ char params[PARAMS_SIZE] = {0}; -+ - if (!mpp) - return 1; - -- if (dm_get_map(mpp->alias, &mpp->size, mpp->params)) -+ if (dm_get_map(mpp->alias, &mpp->size, params)) { -+ condlog(3, "%s: cannot get map", mpp->alias); - return 1; -+ } - -- if (disassemble_map(pathvec, mpp->params, mpp)) -+ if (disassemble_map(pathvec, params, mpp)) { -+ condlog(3, "%s: cannot disassemble map", mpp->alias); - return 1; -+ } - - return 0; - } -@@ -252,14 +258,20 @@ update_multipath_table (struct multipath *mpp, vector pathvec) - static int - update_multipath_status (struct multipath *mpp) - { -+ char status[PARAMS_SIZE] = {0}; -+ - if (!mpp) - return 1; - -- if(dm_get_status(mpp->alias, mpp->status)) -+ if (dm_get_status(mpp->alias, status)) { -+ condlog(3, "%s: cannot get status", mpp->alias); - return 1; -+ } - -- if (disassemble_status(mpp->status, mpp)) -+ if (disassemble_status(status, mpp)) { -+ condlog(3, "%s: cannot disassemble status", mpp->alias); - return 1; -+ } - - return 0; - } -diff --git a/libmultipath/waiter.c b/libmultipath/waiter.c -index 54cd19f..530180f 100644 ---- a/libmultipath/waiter.c -+++ b/libmultipath/waiter.c -@@ -26,6 +26,7 @@ struct event_thread *alloc_waiter (void) - struct event_thread *wp; - - wp = (struct event_thread *)MALLOC(sizeof(struct event_thread)); -+ memset(wp, 0, sizeof(struct event_thread)); - - return wp; - } -diff --git a/multipath/main.c b/multipath/main.c -index 60244a5..ffa6eb5 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -158,6 +158,7 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid) - { - int i; - struct multipath * mpp; -+ char params[PARAMS_SIZE], status[PARAMS_SIZE]; - - if (dm_get_maps(curmp)) - return 1; -@@ -175,10 +176,12 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid) - continue; - } - -- condlog(3, "params = %s", mpp->params); -- condlog(3, "status = %s", mpp->status); -+ dm_get_map(mpp->alias, &mpp->size, params); -+ condlog(3, "params = %s", params); -+ dm_get_status(mpp->alias, status); -+ condlog(3, "status = %s", status); - -- disassemble_map(pathvec, mpp->params, mpp); -+ disassemble_map(pathvec, params, mpp); - - /* - * disassemble_map() can add new paths to pathvec. -@@ -191,7 +194,7 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid) - if (conf->list > 1) - mpp->bestpg = select_path_group(mpp); - -- disassemble_status(mpp->status, mpp); -+ disassemble_status(status, mpp); - - if (conf->list) - print_multipath_topology(mpp, conf->verbosity); -@@ -495,6 +498,8 @@ out: - sysfs_cleanup(); - dm_lib_release(); - dm_lib_exit(); -+ cleanup_prio(); -+ cleanup_checkers(); - - /* - * Freeing config must be done after dm_lib_exit(), because -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index f9b0da4..4f639b6 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -463,11 +463,13 @@ out: - int resize_map(struct multipath *mpp, unsigned long long size, - struct vectors * vecs) - { -+ char params[PARAMS_SIZE] = {0}; -+ - mpp->size = size; - update_mpp_paths(mpp, vecs->pathvec); -- setup_map(mpp); -+ setup_map(mpp, params, PARAMS_SIZE); - mpp->action = ACT_RESIZE; -- if (domap(mpp) <= 0) { -+ if (domap(mpp, params) <= 0) { - condlog(0, "%s: failed to resize map : %s", mpp->alias, - strerror(errno)); - return 1; -diff --git a/multipathd/main.c b/multipathd/main.c -index bb396ec..444494e 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -158,6 +158,8 @@ sync_map_state(struct multipath *mpp) - if (!mpp->pg) - return; - -+ condlog(5, "%s: sync map state", mpp->alias); -+ - vector_foreach_slot (mpp->pg, pgp, i){ - vector_foreach_slot (pgp->paths, pp, j){ - if (pp->state == PATH_UNCHECKED || -@@ -355,6 +357,7 @@ ev_add_path (char * devname, struct vectors * vecs) - struct multipath * mpp; - struct path * pp; - char empty_buff[WWID_SIZE] = {0}; -+ char params[PARAMS_SIZE] = {0}; - - pp = find_path_by_dev(vecs->pathvec, devname); - -@@ -409,7 +412,7 @@ rescan: - /* - * push the map to the device-mapper - */ -- if (setup_map(mpp)) { -+ if (setup_map(mpp, params, PARAMS_SIZE)) { - condlog(0, "%s: failed to setup map for addition of new " - "path %s", mpp->alias, devname); - goto out; -@@ -417,7 +420,7 @@ rescan: - /* - * reload the map for the multipath mapped device - */ -- if (domap(mpp) <= 0) { -+ if (domap(mpp, params) <= 0) { - condlog(0, "%s: failed in domap for addition of new " - "path %s", mpp->alias, devname); - /* -@@ -480,6 +483,7 @@ ev_remove_path (char * devname, struct vectors * vecs) - struct multipath * mpp; - struct path * pp; - int i, retval = 0; -+ char params[PARAMS_SIZE] = {0}; - - pp = find_path_by_dev(vecs->pathvec, devname); - -@@ -526,7 +530,7 @@ ev_remove_path (char * devname, struct vectors * vecs) - */ - } - -- if (setup_map(mpp)) { -+ if (setup_map(mpp, params, PARAMS_SIZE)) { - condlog(0, "%s: failed to setup map for" - " removal of path %s", mpp->alias, - devname); -@@ -536,7 +540,7 @@ ev_remove_path (char * devname, struct vectors * vecs) - * reload the map - */ - mpp->action = ACT_RELOAD; -- if (domap(mpp) <= 0) { -+ if (domap(mpp, params) <= 0) { - condlog(0, "%s: failed in domap for " - "removal of path %s", - mpp->alias, devname); -@@ -1395,6 +1399,9 @@ child (void * param) - cleanup_checkers(); - cleanup_prio(); - -+ cleanup_checkers(); -+ cleanup_prio(); -+ - condlog(2, "--------shut down-------"); - - if (logsink) --- -1.5.3.2 - diff --git a/multipath-tools-missing-fixes-for-ontap b/multipath-tools-missing-fixes-for-ontap deleted file mode 100644 index 31b06f4..0000000 --- a/multipath-tools-missing-fixes-for-ontap +++ /dev/null @@ -1,51 +0,0 @@ -From 375c38b4f4aa88fddd6106e4f2722e120fc1dac4 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Wed, 15 Oct 2008 13:44:00 +0200 -Subject: [PATCH] Missing fixes for libprio ontap.c - -The ontap.c libprio source file available on SLES10 SP2 has a few -deviations from the corresponding pp_ontap.c source file in the -path_priority directory. - -References: 426975 - -Signed-off-by: Martin George -Signed-off-by: Hannes Reinecke ---- - libmultipath/prioritizers/ontap.c | 6 ++++-- - 1 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/prioritizers/ontap.c b/libmultipath/prioritizers/ontap.c -index 0a629bc..1200114 100644 ---- a/libmultipath/prioritizers/ontap.c -+++ b/libmultipath/prioritizers/ontap.c -@@ -27,7 +27,7 @@ - #define INQUIRY_CMDLEN 6 - #define DEFAULT_PRIOVAL 10 - #define RESULTS_MAX 256 --#define SG_TIMEOUT 30000 -+#define SG_TIMEOUT 60000 - - #define pp_ontap_log(prio, fmt, args...) \ - condlog(prio, "%s: ontap prio: " fmt, dev, ##args) -@@ -194,7 +194,7 @@ static int ontap_prio(const char *dev, int fd) - - memset(&results, 0, sizeof (results)); - rc = send_gva(dev, fd, 0x41, results, &results_size); -- if (rc == 0) { -+ if (rc >= 0) { - tot_len = results[0] << 24 | results[1] << 16 | - results[2] << 8 | results[3]; - if (tot_len <= 8) { -@@ -214,6 +214,8 @@ static int ontap_prio(const char *dev, int fd) - is_iscsi_hardware = 1; - goto prio_select; - } -+ } else { -+ return 0; - } - - try_fcp_proxy: --- -1.5.2.4 - diff --git a/multipath-tools-more-debugging-output b/multipath-tools-more-debugging-output deleted file mode 100644 index 6edace8..0000000 --- a/multipath-tools-more-debugging-output +++ /dev/null @@ -1,85 +0,0 @@ -commit d3f2f760250ff40f31ea5ddab7d45c86ba32bab6 -Author: Hannes Reinecke -Date: Wed Jan 7 11:05:45 2009 +0100 - - Add more debugging output - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index c4a53ab..868dcc7 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -689,11 +689,15 @@ get_state (struct path * pp) - - if (!checker_selected(c)) { - select_checker(pp); -- if (!checker_selected(c)) -+ if (!checker_selected(c)) { -+ condlog(3, "%s: No checker selected", pp->dev); - return 1; -+ } - checker_set_fd(c, pp->fd); -- if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) -+ if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) { -+ condlog(3, "%s: checker init failed", pp->dev); - return 1; -+ } - } - pp->state = checker_check(c); - condlog(3, "%s: state = %i", pp->dev, pp->state); -@@ -711,8 +715,10 @@ get_prio (struct path * pp) - - if (!pp->prio) { - select_prio(pp); -- if (!pp->prio) -+ if (!pp->prio) { -+ condlog(3, "%s: no prio selected", pp->dev); - return 1; -+ } - } - pp->priority = prio_getprio(pp->prio, pp); - if (pp->priority < 0) { -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 3770566..a1d9632 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -282,6 +282,7 @@ update_multipath_status (struct multipath *mpp) - extern int - update_multipath_strings (struct multipath *mpp, vector pathvec) - { -+ condlog(4, "%s: %s", mpp->alias, __FUNCTION__); - free_multipath_attributes(mpp); - free_pgvec(mpp->pg, KEEP_PATHS); - mpp->pg = NULL; -@@ -477,6 +478,9 @@ verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec) - vector_del_slot(vecs->pathvec, j); - free_path(pp); - } -+ } else { -+ condlog(4, "%s: verified path %s dev_t %s", -+ mpp->alias, pp->dev, pp->dev_t); - } - } - return count; -diff --git a/multipathd/main.c b/multipathd/main.c -index c60d075..b39ba90 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -396,6 +396,8 @@ ev_add_path (char * devname, struct vectors * vecs) - mpp = pp->mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); - rescan: - if (mpp) { -+ condlog(4,"%s: adopting all paths for path %s", -+ mpp->alias, pp->dev); - if (adopt_paths(vecs->pathvec, mpp)) - return 1; /* leave path added to pathvec */ - -@@ -403,6 +405,7 @@ rescan: - mpp->action = ACT_RELOAD; - } - else { -+ condlog(4,"%s: creating new map", pp->dev); - if ((mpp = add_map_with_path(vecs, pp, 1))) - mpp->action = ACT_CREATE; - else diff --git a/multipath-tools-print-dm-tables b/multipath-tools-print-dm-tables deleted file mode 100644 index d486bdd..0000000 --- a/multipath-tools-print-dm-tables +++ /dev/null @@ -1,43 +0,0 @@ -commit 96f43ccaf6bf5288bfb94344e5c9a60ff5354083 -Author: Hannes Reinecke -Date: Fri Dec 19 09:39:52 2008 +0100 - - Print out maps in dmparser.c - - For debugging it's quite helpful to have the actual maps as - being sent to device-mapper printed out. - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c -index 0cef666..33b5cde 100644 ---- a/libmultipath/dmparser.c -+++ b/libmultipath/dmparser.c -@@ -107,6 +107,9 @@ assemble_map (struct multipath * mp, char * params, int len) - return 1; - } - snprintf(p, 1, "\n"); -+ -+ condlog(3, "%s: assembled map [%s]\n", mp->alias, params); -+ - return 0; - } - -@@ -128,6 +131,8 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp) - - p = params; - -+ condlog(3, "%s: disassemble map [%s]\n", mpp->alias, params); -+ - /* - * features - */ -@@ -354,6 +359,8 @@ disassemble_status (char * params, struct multipath * mpp) - - p = params; - -+ condlog(3, "%s: disassemble status [%s]\n", mpp->alias, params); -+ - /* - * features - */ diff --git a/multipath-tools-prio-weightedpath b/multipath-tools-prio-weightedpath deleted file mode 100644 index ac3f13a..0000000 --- a/multipath-tools-prio-weightedpath +++ /dev/null @@ -1,529 +0,0 @@ -commit 86bc28e5702babadf73a1c4395870da370efa257 -Author: Hannes Reinecke -Date: Fri Nov 21 14:03:38 2008 +0100 - - Static Load balancing prioritizer - - 'Weighted path' is a new path prioritizer for device mapper - multipath, where specific paths and the corresponding priority - values can be provided as arguments. - This prioritizer assigns the priority value provided in the - configuration file based on the comparison made between the - specified paths and the path instance for which this is called. - Paths can be specified as a regular expression of devname - of the path or as hbtl information of the path. - - Syntax: - weightedpath ... - - Examples: - prio "weightedpath hbtl 1:.:.:. 2 4:.:.:. 4" #All paths through SCSI 'H' as - '1' will take prio 2 and all paths with SCSI 'H' as 4 will take prio as 4. - - prio "weightedpath devname sda$ 10 sde$ 20" #Path sda takes prio 10 and - path sde takes prio 20. can be provided in multipath section. - - This prioritizer allows user to set static load balancing - for devices. Useful when user has prior knowledge of path - performance difference or unavailability of certain paths. - - References: 441007 - - Signed-off-by: Vijayakumar Balasubramanian - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 908156d..83da6e7 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -207,6 +207,12 @@ free_mpe (struct mpentry * mpe) - if (mpe->alias) - FREE(mpe->alias); - -+ if (mpe->prio_name) -+ FREE(mpe->prio_name); -+ -+ if (mpe->prio_arg) -+ FREE(mpe->prio_arg); -+ - FREE(mpe); - } - -@@ -291,6 +297,7 @@ merge_hwe (struct hwentry * hwe1, struct hwentry * hwe2) - merge_str(selector); - merge_str(checker_name); - merge_str(prio_name); -+ merge_str(prio_arg); - merge_str(bl_product); - merge_num(pgpolicy); - merge_num(pgfailback); -@@ -339,6 +346,9 @@ store_hwe (vector hwtable, struct hwentry * dhwe) - if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name))) - goto out; - -+ if (dhwe->prio_arg && !(hwe->prio_arg = set_param_str(dhwe->prio_arg))) -+ goto out; -+ - hwe->pgpolicy = dhwe->pgpolicy; - hwe->pgfailback = dhwe->pgfailback; - hwe->rr_weight = dhwe->rr_weight; -@@ -559,8 +569,10 @@ load_config (char * file) - !conf->hwhandler || !conf->bindings_file) - goto out; - -- if (!conf->prio_name) -+ if (!conf->prio_name) { - conf->prio_name = set_default(DEFAULT_PRIO); -+ conf->prio_arg = NULL; -+ } - - if (!conf->checker_name) - conf->checker_name = set_default(DEFAULT_CHECKER); -diff --git a/libmultipath/config.h b/libmultipath/config.h -index fb917f4..fc0e22d 100644 ---- a/libmultipath/config.h -+++ b/libmultipath/config.h -@@ -21,6 +21,7 @@ struct hwentry { - char * selector; - char * checker_name; - char * prio_name; -+ char * prio_arg; - - int pgpolicy; - int pgfailback; -@@ -37,6 +38,8 @@ struct mpentry { - char * getuid; - char * selector; - -+ char * prio_name; -+ char * prio_arg; - int pgpolicy; - int pgfailback; - int rr_weight; -@@ -75,6 +78,7 @@ struct config { - char * hwhandler; - char * bindings_file; - char * prio_name; -+ char * prio_arg; - char * checker_name; - - vector keywords; -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index 5794b11..9ba3961 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -4,6 +4,7 @@ - * Copyright (c) 2005 Benjamin Marzinski, Redhat - * Copyright (c) 2005 Kiyoshi Ueda, NEC - */ -+#include - #include "checkers.h" - #include "vector.h" - #include "hwtable.h" -@@ -106,11 +107,26 @@ def_getuid_callout_handler(vector strvec) - static int - def_prio_handler(vector strvec) - { -- conf->prio_name = set_value(strvec); -+ char *buff, *result, *temp; -+ char split_char[] = " \t"; - -- if (!conf->prio_name) -+ buff = set_value(strvec); -+ if (!buff) - return 1; -+ temp = buff; -+ -+ while ((result = strsep(&temp, split_char))) { -+ if (prio_lookup(result)) { -+ conf->prio_name = STRDUP(result); -+ if (temp) -+ conf->prio_arg = STRDUP(temp); -+ else -+ conf->prio_arg = NULL; -+ break; -+ } -+ } - -+ FREE(buff); - return 0; - } - -@@ -613,15 +629,29 @@ static int - hw_prio_handler(vector strvec) - { - struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); -+ char *buff, *result, *temp; -+ char split_char[] = " \t"; - - if (!hwe) - return 1; - -- hwe->prio_name = set_value(strvec); -- -- if (!hwe->prio_name) -+ buff = set_value(strvec); -+ if (!buff) - return 1; -+ temp = buff; -+ -+ while ((result = strsep(&temp, split_char))) { -+ if (prio_lookup(result)) { -+ conf->prio_name = STRDUP(result); -+ if (temp) -+ conf->prio_arg = STRDUP(temp); -+ else -+ conf->prio_arg = NULL; -+ break; -+ } -+ } - -+ FREE(buff); - return 0; - } - -@@ -967,6 +997,38 @@ mp_pg_timeout_handler(vector strvec) - return 0; - } - -+static int -+mp_prio_handler (vector strvec) -+{ -+ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); -+ char *buff, *result, *temp; -+ char split_char[] = " \t"; -+ -+ if (!mpe) -+ return 1; -+ -+ buff = set_value(strvec); -+ -+ if (!buff) -+ return 1; -+ -+ temp = buff; -+ -+ while ((result = strsep(&temp, split_char))) { -+ if (prio_lookup(result)) { -+ mpe->prio_name = STRDUP(result); -+ if (temp) -+ mpe->prio_arg = STRDUP(temp); -+ else -+ mpe->prio_arg = NULL; -+ break; -+ } -+ } -+ -+ FREE(buff); -+ return 0; -+} -+ - /* - * config file keywords printing - */ -@@ -1102,6 +1164,17 @@ snprint_mp_pg_timeout (char * buff, int len, void * data) - } - - static int -+snprint_mp_prio(char * buff, int len, void * data) -+{ -+ struct mpentry * mpe = (struct mpentry *)data; -+ -+ if (!mpe->prio_name) -+ return 0; -+ -+ return snprintf(buff, len, "%s", mpe->prio_name); -+} -+ -+static int - snprint_hw_vendor (char * buff, int len, void * data) - { - struct hwentry * hwe = (struct hwentry *)data; -@@ -1672,6 +1745,7 @@ init_keywords(void) - install_keyword("alias", &alias_handler, &snprint_mp_alias); - install_keyword("path_grouping_policy", &mp_pgpolicy_handler, &snprint_mp_path_grouping_policy); - install_keyword("path_selector", &mp_selector_handler, &snprint_mp_selector); -+ install_keyword("prio", &mp_prio_handler, &snprint_mp_prio); - install_keyword("failback", &mp_failback_handler, &snprint_mp_failback); - install_keyword("rr_weight", &mp_weight_handler, &snprint_mp_rr_weight); - install_keyword("no_path_retry", &mp_no_path_retry_handler, &snprint_mp_no_path_retry); -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 56186bd..c4a53ab 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -784,8 +784,11 @@ pathinfo (struct path *pp, vector hwtable, int mask) - * been successfully obtained before. - */ - if (mask & DI_PRIO && -- (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF)) -+ (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF)) { -+ if (!strlen(pp->wwid)) -+ get_uid(pp); - get_prio(pp); -+ } - - if (mask & DI_WWID && !strlen(pp->wwid)) - get_uid(pp); -diff --git a/libmultipath/prio.h b/libmultipath/prio.h -index deef02d..1d00725 100644 ---- a/libmultipath/prio.h -+++ b/libmultipath/prio.h -@@ -24,6 +24,7 @@ - #define PRIO_ONTAP "ontap" - #define PRIO_RANDOM "random" - #define PRIO_RDAC "rdac" -+#define PRIO_WEIGHTED_PATH "weightedpath" - - /* - * Value used to mark the fact prio was not defined -diff --git a/libmultipath/prioritizers/Makefile b/libmultipath/prioritizers/Makefile -index df42145..a569321 100644 ---- a/libmultipath/prioritizers/Makefile -+++ b/libmultipath/prioritizers/Makefile -@@ -12,7 +12,8 @@ LIBS = \ - libpriordac.so \ - libprioalua.so \ - libprioontap.so \ -- libpriohds.so -+ libpriohds.so \ -+ libprioweightedpath.so - - CFLAGS += -I.. - -diff --git a/libmultipath/prioritizers/weightedpath.c b/libmultipath/prioritizers/weightedpath.c -new file mode 100644 -index 0000000..d04d91e ---- /dev/null -+++ b/libmultipath/prioritizers/weightedpath.c -@@ -0,0 +1,99 @@ -+/* -+ * -+ * (C) Copyright 2008 Hewlett-Packard Development Company, L.P -+ * -+ * This file is released under the GPL -+ */ -+ -+/* -+ * Prioritizer for device mapper multipath, where specific paths and the -+ * corresponding priority values are provided as arguments. -+ * -+ * This prioritizer assigns the priority value provided in the configuration -+ * file based on the comparison made between the specified paths and the path -+ * instance for which this is called. -+ * Paths can be specified as a regular expression of devname of the path or -+ * as hbtl information of the path. -+ * -+ * Examples: -+ * prio "weightedpath hbtl 1:.:.:. 2 4:.:.:. 4" -+ * prio "weightedpath devname sda 10 sde 20" -+ * -+ * Returns zero as the default priority. -+ */ -+ -+#include -+#include -+ -+#include -+#include "weightedpath.h" -+#include -+#include -+#include -+#include -+#include -+ -+char *get_next_string(char **temp, char *split_char) -+{ -+ char *token = NULL; -+ token = strsep(temp, split_char); -+ while (token != NULL && !strcmp(token, "")) -+ token = strsep(temp, split_char); -+ return token; -+} -+ -+/* main priority routine */ -+int prio_path_weight(struct path *pp) -+{ -+ char path[FILE_NAME_SIZE]; -+ char *arg; -+ char *temp, *regex, *prio; -+ char split_char[] = " \t"; -+ int priority = DEFAULT_PRIORITY, path_found = 0; -+ regex_t pathe; -+ -+ /* Return default priority if there is no argument */ -+ if (!pp->prio_arg) -+ return priority; -+ -+ arg = temp = STRDUP(pp->prio_arg); -+ -+ regex = get_next_string(&temp, split_char); -+ -+ if (!strcmp(regex, HBTL)) { -+ sprintf(path, "%d:%d:%d:%d", pp->sg_id.host_no, -+ pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun); -+ } else if (!strcmp(regex, DEV_NAME)) { -+ strcpy(path, pp->dev); -+ } else { -+ condlog(0, "%s: %s - Invalid arguments", pp->dev, -+ pp->prio->name); -+ return priority; -+ } -+ -+ while (!path_found) { -+ if (!temp) -+ break; -+ if (!(regex = get_next_string(&temp, split_char))) -+ break; -+ if (!(prio = get_next_string(&temp, split_char))) -+ break; -+ -+ if (!regcomp(&pathe, regex, REG_EXTENDED|REG_NOSUB)) { -+ if (!regexec(&pathe, path, 0, NULL, 0)) { -+ path_found = 1; -+ priority = atoi(prio); -+ } -+ regfree(&pathe); -+ } -+ } -+ -+ FREE(arg); -+ return priority; -+} -+ -+int getprio(struct path *pp) -+{ -+ return prio_path_weight(pp); -+} -+ -diff --git a/libmultipath/prioritizers/weightedpath.h b/libmultipath/prioritizers/weightedpath.h -new file mode 100644 -index 0000000..141cdf7 ---- /dev/null -+++ b/libmultipath/prioritizers/weightedpath.h -@@ -0,0 +1,11 @@ -+#ifndef _WEIGHTED_PATH_H -+#define _WEIGHTED_PATH_H -+ -+#define PRIO_WEIGHTED_PATH "weightedpath" -+#define HBTL "hbtl" -+#define DEV_NAME "devname" -+#define DEFAULT_PRIORITY 0 -+ -+int prio_path_weight(struct path *pp); -+ -+#endif -diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c -index 5a16182..1fc7c40 100644 ---- a/libmultipath/propsel.c -+++ b/libmultipath/propsel.c -@@ -258,14 +258,28 @@ select_getuid (struct path * pp) - extern int - select_prio (struct path * pp) - { -+ struct mpentry * mpe; -+ -+ if ((mpe = find_mpe(pp->wwid))) { -+ if (mpe->prio_name) { -+ pp->prio = prio_lookup(mpe->prio_name); -+ pp->prio_arg = mpe->prio_arg; -+ condlog(3, "%s: prio = %s (LUN setting)", -+ pp->dev, pp->prio->name); -+ return 0; -+ } -+ } -+ - if (pp->hwe && pp->hwe->prio_name) { - pp->prio = prio_lookup(pp->hwe->prio_name); -+ pp->prio_arg = pp->hwe->prio_arg; - condlog(3, "%s: prio = %s (controller setting)", - pp->dev, pp->hwe->prio_name); - return 0; - } - if (conf->prio_name) { - pp->prio = prio_lookup(conf->prio_name); -+ pp->prio_arg = conf->prio_arg; - condlog(3, "%s: prio = %s (config file default)", - pp->dev, conf->prio_name); - return 0; -diff --git a/libmultipath/structs.h b/libmultipath/structs.h -index 658d6b2..75bd379 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -121,6 +121,7 @@ struct path { - int pgindex; - char * getuid; - struct prio * prio; -+ char * prio_arg; - struct checker checker; - struct multipath * mpp; - int fd; -diff --git a/multipath.conf.annotated b/multipath.conf.annotated -index a4c7e6a..740a334 100644 ---- a/multipath.conf.annotated -+++ b/multipath.conf.annotated -@@ -261,6 +261,18 @@ - # # default : 1000 - # # - # rr_min_io 100 -+# -+# # -+# #name : prio -+# #scope : multipath -+# #desc : the function to call to obtain a path weight. -+# # Weights are summed for each path group to -+# # determine the next PG to use case of failure. -+# #default : no callout, all paths equals -+# # Ex: -+# # prio alua -+# # prio "weightedpath devname sda 50 sde 10 sdc 50 sdf 10" -+# prio "weightedpath hbtl 1:.:.:. 2 4:.:.:. 4" - # } - # multipath { - # wwid 1DEC_____321816758474 -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index d3c37c8..8ac1f1c 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -151,6 +151,24 @@ Generate the path priority for Hitachi HDS Modular storage arrays. - Default value is \fBnone\fR. - .RE - .TP -+.B prio -+The default program and args to path priority routine. The specified -+routine should return a numeric value specifying the relative priority -+of this path. Higher number have a higher priority. -+.RS -+.TP 12 -+.B alua -+Generate the path priority based on ALUA status of the path. -+.TP 12 -+.B weightedpath ... -+.I hbtl -+regex can be of SCSI H:B:T:L format Ex: 1:0:.:. , *:0:0:. -+.I devname -+regex can be of device name format Ex: sda , sd.e -+Generate the path priority based on the regular expression and the -+priority provided as argument. -+.RE -+.TP - .B features - Specify any device-mapper features to be used. Syntax is - .I num list -@@ -327,6 +345,8 @@ section: - .TP - .B path_selector - .TP -+.B prio -+.TP - .B failback - .TP - .B no_path_retry -@@ -380,6 +400,8 @@ section: - .TP - .B path_checker - .TP -+.B prio -+.TP - .B features - .TP - .B prio_callout diff --git a/multipath-tools-quote-variable-in-mkinitrd-setup b/multipath-tools-quote-variable-in-mkinitrd-setup deleted file mode 100644 index bd86855..0000000 --- a/multipath-tools-quote-variable-in-mkinitrd-setup +++ /dev/null @@ -1,26 +0,0 @@ -commit 94ed8e8244e89700d702c54d8a791e190b3868df -Author: Hannes Reinecke -Date: Mon Nov 24 10:46:36 2008 +0100 - - Properly quote variables in mkinitrd scripts - - We should quote variables properly, otherwise we risk some script - syntax errors. - - References: 447966 - - Signed-off-by: Hannes Reinecke - -diff --git a/multipath/setup-multipath.sh b/multipath/setup-multipath.sh -index 1670071..bb9b244 100644 ---- a/multipath/setup-multipath.sh -+++ b/multipath/setup-multipath.sh -@@ -12,7 +12,7 @@ fi - if [ -x /sbin/multipath -a -x /sbin/dmsetup ] ; then - for bd in $blockdev ; do - update_blockdev $bd -- if [ $blockdriver = device-mapper ]; then -+ if [ "$blockdriver" = device-mapper ]; then - dm_uuid=$(dmsetup info -c --noheadings -o uuid -j $blockmajor -m $blockminor) - dm_creator=${dm_uuid%-*} - if [ "$dm_creator" = "mpath" ]; then diff --git a/multipath-tools-read-verbosity-level-from-conf b/multipath-tools-read-verbosity-level-from-conf deleted file mode 100644 index ed47601..0000000 --- a/multipath-tools-read-verbosity-level-from-conf +++ /dev/null @@ -1,110 +0,0 @@ -From 965522c700ea307029789a1485242835132cea77 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 14 Oct 2008 08:21:02 +0200 -Subject: [PATCH] Read the verbosity level from multipath.conf configuration file - -With this patch, multipathd can read the verbosity level from -the multipath.conf configuration file. -For example: -verbosity 5 - -References: 388284 - -Signed-off-by: Ritesh Raj Sarraf -Signed-off-by: Hannes Reinecke ---- - libmultipath/config.c | 2 +- - libmultipath/defaults.h | 1 + - libmultipath/dict.c | 20 ++++++++++++++++++++ - multipath/multipath.conf.5 | 5 +++++ - 4 files changed, 27 insertions(+), 1 deletions(-) - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 14bece1..d2585ed 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -423,7 +423,7 @@ load_config (char * file) - * internal defaults - */ - if (!conf->verbosity) -- conf->verbosity = 2; -+ conf->verbosity = DEFAULT_VERBOSITY; - - conf->dev_type = DEV_NONE; - conf->minio = 1000; -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index 87b155e..a943673 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -11,6 +11,7 @@ - #define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF - #define DEFAULT_PGTIMEOUT -PGTIMEOUT_NONE - #define DEFAULT_USER_FRIENDLY_NAMES 0 -+#define DEFAULT_VERBOSITY 2 - - #define DEFAULT_CHECKINT 5 - #define MAX_CHECKINT(a) (a << 2) -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index a5a294e..5794b11 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -33,6 +33,17 @@ polling_interval_handler(vector strvec) - } - - static int -+verbosity_handler(vector strvec) -+{ -+ char * buff; -+ -+ buff = VECTOR_SLOT(strvec, 1); -+ conf->verbosity = atoi(buff); -+ -+ return 0; -+} -+ -+static int - udev_dir_handler(vector strvec) - { - conf->udev_dir = set_value(strvec); -@@ -1327,6 +1338,14 @@ snprint_def_polling_interval (char * buff, int len, void * data) - } - - static int -+snprint_def_verbosity (char * buff, int len, void * data) -+{ -+ if (conf->checkint == DEFAULT_VERBOSITY) -+ return 0; -+ return snprintf(buff, len, "%i", conf->verbosity); -+} -+ -+static int - snprint_def_udev_dir (char * buff, int len, void * data) - { - if (!conf->udev_dir) -@@ -1572,6 +1591,7 @@ void - init_keywords(void) - { - install_keyword_root("defaults", NULL); -+ install_keyword("verbosity", &verbosity_handler, &snprint_def_verbosity); - install_keyword("polling_interval", &polling_interval_handler, &snprint_def_polling_interval); - install_keyword("udev_dir", &udev_dir_handler, &snprint_def_udev_dir); - install_keyword("multipath_dir", &multipath_dir_handler, &snprint_def_multipath_dir); -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index 90ef588..d3c37c8 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -74,6 +74,11 @@ interval between two path checks in seconds; default is - directory where udev creates its device nodes; default is - .I /dev - .TP -+.B verbosity -+default verbosity. Higher values increase the verbosity level. Valid -+levels are between 0 and 6; default is 2. -+.I /dev -+.TP - .B selector - The default path selector algorithm to use; they are offered by the - kernel multipath target. The only currently implemented is --- -1.5.2.4 - diff --git a/multipath-tools-reload-map-for-ro-changes b/multipath-tools-reload-map-for-ro-changes deleted file mode 100644 index 59ef73f..0000000 --- a/multipath-tools-reload-map-for-ro-changes +++ /dev/null @@ -1,262 +0,0 @@ -commit 3b88c4374cf2a204e14ffdaf85b2dbfdc4a1391a -Author: Hannes Reinecke -Date: Thu Dec 4 14:20:06 2008 +0100 - - Reload map for device read-only setting changes - - Whenever the read-only setting for a device changes we have - to reload the map. This patch implements the required cli command - and also a uevent handler if a uevent with 'DISK_RO=' setting - has been received. - - References: 440959 - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 3903b28..68178c3 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -672,3 +672,40 @@ out: - return NULL; - } - -+extern int reload_map(struct vectors *vecs, struct multipath *mpp) -+{ -+ char params[PARAMS_SIZE]; -+ int r; -+ -+ update_mpp_paths(mpp, vecs->pathvec); -+ -+ params[0] = '\0'; -+ if (setup_map(mpp, params, PARAMS_SIZE)) { -+ condlog(0, "%s: failed to setup map", mpp->alias); -+ return 1; -+ } -+ select_action(mpp, vecs->mpvec, 1); -+ -+ r = domap(mpp, params); -+ if (r == DOMAP_FAIL || r == DOMAP_RETRY) { -+ condlog(3, "%s: domap (%u) failure " -+ "for reload map", mpp->alias, r); -+ return 1; -+ } -+ if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) { -+ if (mpp->no_path_retry == NO_PATH_RETRY_FAIL) -+ dm_queue_if_no_path(mpp->alias, 0); -+ else -+ dm_queue_if_no_path(mpp->alias, 1); -+ } -+ if (mpp->pg_timeout != PGTIMEOUT_UNDEF) { -+ if (mpp->pg_timeout == -PGTIMEOUT_NONE) -+ dm_set_pg_timeout(mpp->alias, 0); -+ else -+ dm_set_pg_timeout(mpp->alias, mpp->pg_timeout); -+ } -+ -+ return 0; -+} -+ -+ -diff --git a/libmultipath/configure.h b/libmultipath/configure.h -index ec2800d..d0c06f2 100644 ---- a/libmultipath/configure.h -+++ b/libmultipath/configure.h -@@ -28,4 +28,5 @@ int domap (struct multipath * mpp, char * params); - int reinstate_paths (struct multipath *mpp); - int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload); - char * get_refwwid (char * dev, enum devtypes dev_type, vector pathvec); -+int reload_map(struct vectors *vecs, struct multipath *mpp); - -diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c -index 13986da..19a71ad 100644 ---- a/libmultipath/uevent.c -+++ b/libmultipath/uevent.c -@@ -341,3 +341,23 @@ uevent_get_minor(struct uevent *uev) - return minor; - } - -+extern int -+uevent_get_disk_ro(struct uevent *uev) -+{ -+ char *p, *q; -+ int i, ro = -1; -+ -+ for (i = 0; uev->envp[i] != NULL; i++) { -+ if (!strncmp(uev->envp[i], "DISK_RO", 6) && strlen(uev->envp[i]) > 7) { -+ p = uev->envp[i] + 8; -+ ro = strtoul(p, &q, 10); -+ if (p == q) { -+ condlog(2, "invalid read_only setting '%s'", p); -+ ro = -1; -+ } -+ break; -+ } -+ } -+ return ro; -+} -+ -diff --git a/libmultipath/uevent.h b/libmultipath/uevent.h -index 43d163b..ec6450b 100644 ---- a/libmultipath/uevent.h -+++ b/libmultipath/uevent.h -@@ -23,5 +23,6 @@ int uevent_listen(int (*store_uev)(struct uevent *, void * trigger_data), - void * trigger_data); - int uevent_get_major(struct uevent *uev); - int uevent_get_minor(struct uevent *uev); -+int uevent_get_disk_ro(struct uevent *uev); - - #endif /* _UEVENT_H */ -diff --git a/multipathd/cli.c b/multipathd/cli.c -index 2545e89..acc8cab 100644 ---- a/multipathd/cli.c -+++ b/multipathd/cli.c -@@ -156,6 +156,7 @@ load_keys (void) - r += add_key(keys, "reinstate", REINSTATE, 0); - r += add_key(keys, "fail", FAIL, 0); - r += add_key(keys, "resize", RESIZE, 0); -+ r += add_key(keys, "reload", RELOAD, 0); - r += add_key(keys, "paths", PATHS, 0); - r += add_key(keys, "maps", MAPS, 0); - r += add_key(keys, "multipaths", MAPS, 0); -@@ -427,6 +428,8 @@ cli_init (void) { - add_handler(RECONFIGURE, NULL); - add_handler(SUSPEND+MAP, NULL); - add_handler(RESUME+MAP, NULL); -+ add_handler(RESIZE+MAP, NULL); -+ add_handler(RELOAD+MAP, NULL); - add_handler(REINSTATE+PATH, NULL); - add_handler(FAIL+PATH, NULL); - -diff --git a/multipathd/cli.h b/multipathd/cli.h -index be14395..1fa4862 100644 ---- a/multipathd/cli.h -+++ b/multipathd/cli.h -@@ -8,6 +8,7 @@ enum { - __REINSTATE, - __FAIL, - __RESIZE, -+ __RELOAD, - __PATHS, - __MAPS, - __PATH, -@@ -33,6 +34,7 @@ enum { - #define REINSTATE (1 << __REINSTATE) - #define FAIL (1 << __FAIL) - #define RESIZE (1 << __RESIZE) -+#define RELOAD (1 << __RELOAD) - #define PATHS (1 << __PATHS) - #define MAPS (1 << __MAPS) - #define PATH (1 << __PATH) -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index 4f639b6..819dd87 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -460,6 +460,28 @@ out: - return err; - } - -+int -+cli_reload(void *v, char **reply, int *len, void *data) -+{ -+ struct vectors * vecs = (struct vectors *)data; -+ char * mapname = get_keyparam(v, MAP); -+ struct multipath *mpp; -+ int minor; -+ -+ condlog(2, "%s: reload map (operator)", mapname); -+ if (sscanf(mapname, "dm-%d", &minor) == 1) -+ mpp = find_mp_by_minor(vecs->mpvec, minor); -+ else -+ mpp = find_mp_by_alias(vecs->mpvec, mapname); -+ -+ if (!mpp) { -+ condlog(0, "%s: invalid map name. cannot reload", mapname); -+ return 1; -+ } -+ -+ return reload_map(vecs, mpp); -+} -+ - int resize_map(struct multipath *mpp, unsigned long long size, - struct vectors * vecs) - { -diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h -index b65f259..6e92a07 100644 ---- a/multipathd/cli_handlers.h -+++ b/multipathd/cli_handlers.h -@@ -17,6 +17,7 @@ int cli_del_map (void * v, char ** reply, int * len, void * data); - int cli_switch_group(void * v, char ** reply, int * len, void * data); - int cli_reconfigure(void * v, char ** reply, int * len, void * data); - int cli_resize(void * v, char ** reply, int * len, void * data); -+int cli_reload(void * v, char ** reply, int * len, void * data); - int cli_suspend(void * v, char ** reply, int * len, void * data); - int cli_resume(void * v, char ** reply, int * len, void * data); - int cli_reinstate(void * v, char ** reply, int * len, void * data); -diff --git a/multipathd/main.c b/multipathd/main.c -index 444494e..c60d075 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -572,6 +572,43 @@ out: - } - - static int -+uev_update_path (struct uevent *uev, struct vectors * vecs) -+{ -+ struct sysfs_device * dev; -+ int retval, ro; -+ -+ dev = sysfs_device_get(uev->devpath); -+ if (!dev) { -+ condlog(2, "%s: not found in sysfs", uev->devpath); -+ return 1; -+ } -+ ro = uevent_get_disk_ro(uev); -+ -+ if (ro >= 0) { -+ struct path * pp; -+ -+ condlog(2, "%s: update path write_protect to '%d' (uevent)", -+ uev->kernel, ro); -+ pp = find_path_by_dev(vecs->pathvec, uev->kernel); -+ if (!pp) { -+ condlog(0, "%s: spurious uevent, path not found", -+ uev->kernel); -+ return 1; -+ } -+ if (pp->mpp) -+ retval = reload_map(vecs, pp->mpp); -+ -+ condlog(2, "%s: map %s reloaded (retval %d)", -+ uev->kernel, pp->mpp->alias, retval); -+ -+ } -+ -+ sysfs_device_put(dev); -+ -+ return retval; -+} -+ -+static int - map_discovery (struct vectors * vecs) - { - struct multipath * mpp; -@@ -688,6 +725,10 @@ uev_trigger (struct uevent * uev, void * trigger_data) - r = uev_remove_path(uev, vecs); - goto out; - } -+ if (!strncmp(uev->action, "change", 6)) { -+ r = uev_update_path(uev, vecs); -+ goto out; -+ } - - out: - unlock(vecs->lock); -@@ -731,6 +772,7 @@ uxlsnrloop (void * ap) - set_handler_callback(SUSPEND+MAP, cli_suspend); - set_handler_callback(RESUME+MAP, cli_resume); - set_handler_callback(RESIZE+MAP, cli_resize); -+ set_handler_callback(RELOAD+MAP, cli_reload); - set_handler_callback(REINSTATE+PATH, cli_reinstate); - set_handler_callback(FAIL+PATH, cli_fail); - diff --git a/multipath-tools-remove-kdev_t b/multipath-tools-remove-kdev_t deleted file mode 100644 index ece43d2..0000000 --- a/multipath-tools-remove-kdev_t +++ /dev/null @@ -1,27 +0,0 @@ -From e70d95062c5aaa9218fc0b610ced88280df50650 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 18 Dec 2008 10:03:15 +0100 -Subject: [PATCH] Remove kdev_t.h include - -Pointless and giving the users the wrong impression. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/devmapper.c | 1 - - 1 files changed, 0 insertions(+), 1 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index a7ab41f..713db6a 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - #include - #include - --- -1.6.0.2 - diff --git a/multipath-tools-rework-sysfs-device-handling b/multipath-tools-rework-sysfs-device-handling deleted file mode 100644 index ef68b40..0000000 --- a/multipath-tools-rework-sysfs-device-handling +++ /dev/null @@ -1,449 +0,0 @@ -From e8f4746fa0aec8422022f52d917d6f82915128ce Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 20 Nov 2008 12:14:42 +0100 -Subject: [PATCH] Rework sysfs device handling in multipathd - -Relying on sysfs devices has the disadvantage that the device -might already been gone by the time we look at it. And we don't -actually need it for eg device-mapper events as we can get all -required information via the device-mapper ioctl. -So only access sysfs if we absolutely have to and try to get -the information from other places if possible. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/devmapper.c | 25 ++++++++++++ - libmultipath/devmapper.h | 1 + - libmultipath/uevent.c | 46 +++++++++++++++++++++- - libmultipath/uevent.h | 8 ++++ - multipathd/cli_handlers.c | 13 +++--- - multipathd/main.c | 94 +++++++++++++++++++++++++------------------- - multipathd/main.h | 2 +- - 7 files changed, 139 insertions(+), 50 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index bc4f9db..cde98eb 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -494,6 +494,31 @@ out: - } - - int -+dm_get_major (char * mapname) -+{ -+ int r = -1; -+ struct dm_task *dmt; -+ struct dm_info info; -+ -+ if (!(dmt = dm_task_create(DM_DEVICE_INFO))) -+ return 0; -+ -+ if (!dm_task_set_name(dmt, mapname)) -+ goto out; -+ -+ if (!dm_task_run(dmt)) -+ goto out; -+ -+ if (!dm_task_get_info(dmt, &info)) -+ goto out; -+ -+ r = info.major; -+out: -+ dm_task_destroy(dmt); -+ return r; -+} -+ -+int - dm_get_minor (char * mapname) - { - int r = -1; -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index b262efa..0c7b6b6 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -27,6 +27,7 @@ int dm_enablegroup(char * mapname, int index); - int dm_disablegroup(char * mapname, int index); - int dm_get_maps (vector mp); - int dm_geteventnr (char *name); -+int dm_get_major (char *name); - int dm_get_minor (char *name); - char * dm_mapname(int major, int minor); - int dm_remove_partmaps (const char * mapname); -diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c -index 99757fe..13986da 100644 ---- a/libmultipath/uevent.c -+++ b/libmultipath/uevent.c -@@ -262,10 +262,13 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data), - uev->envp[i] = NULL; - - condlog(3, "uevent '%s' from '%s'", uev->action, uev->devpath); -+ uev->kernel = strrchr(uev->devpath, '/'); -+ if (uev->kernel) -+ uev->kernel++; - - /* print payload environment */ - for (i = 0; uev->envp[i] != NULL; i++) -- condlog(3, "%s", uev->envp[i]); -+ condlog(5, "%s", uev->envp[i]); - - /* - * Queue uevent and poke service pthread. -@@ -297,3 +300,44 @@ exit: - - return 1; - } -+ -+extern int -+uevent_get_major(struct uevent *uev) -+{ -+ char *p, *q; -+ int i, major = -1; -+ -+ for (i = 0; uev->envp[i] != NULL; i++) { -+ if (!strncmp(uev->envp[i], "MAJOR", 5) && strlen(uev->envp[i]) > 6) { -+ p = uev->envp[i] + 6; -+ major = strtoul(p, &q, 10); -+ if (p == q) { -+ condlog(2, "invalid major '%s'", p); -+ major = -1; -+ } -+ break; -+ } -+ } -+ return major; -+} -+ -+extern int -+uevent_get_minor(struct uevent *uev) -+{ -+ char *p, *q; -+ int i, minor = -1; -+ -+ for (i = 0; uev->envp[i] != NULL; i++) { -+ if (!strncmp(uev->envp[i], "MINOR", 5) && strlen(uev->envp[i]) > 6) { -+ p = uev->envp[i] + 6; -+ minor = strtoul(p, &q, 10); -+ if (p == q) { -+ condlog(2, "invalid minor '%s'", p); -+ minor = -1; -+ } -+ break; -+ } -+ } -+ return minor; -+} -+ -diff --git a/libmultipath/uevent.h b/libmultipath/uevent.h -index 55ce42c..43d163b 100644 ---- a/libmultipath/uevent.h -+++ b/libmultipath/uevent.h -@@ -1,3 +1,6 @@ -+#ifndef _UEVENT_H -+#define _UEVENT_H -+ - /* environment buffer, the kernel's size in lib/kobject_uevent.c should fit in */ - #define HOTPLUG_BUFFER_SIZE 1024 - #define HOTPLUG_NUM_ENVP 32 -@@ -12,8 +15,13 @@ struct uevent { - char buffer[HOTPLUG_BUFFER_SIZE + OBJECT_SIZE]; - char *devpath; - char *action; -+ char *kernel; - char *envp[HOTPLUG_NUM_ENVP]; - }; - - int uevent_listen(int (*store_uev)(struct uevent *, void * trigger_data), - void * trigger_data); -+int uevent_get_major(struct uevent *uev); -+int uevent_get_minor(struct uevent *uev); -+ -+#endif /* _UEVENT_H */ -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index fca09ed..f9b0da4 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -372,9 +372,8 @@ cli_add_map (void * v, char ** reply, int * len, void * data) - { - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, MAP); -- int minor; -+ int major, minor; - char dev_path[PATH_SIZE]; -- struct sysfs_device *sysdev; - - condlog(2, "%s: add map (operator)", param); - -@@ -389,13 +388,13 @@ cli_add_map (void * v, char ** reply, int * len, void * data) - condlog(2, "%s: not a device mapper table", param); - return 0; - } -- sprintf(dev_path,"/block/dm-%d", minor); -- sysdev = sysfs_device_get(dev_path); -- if (!sysdev) { -- condlog(2, "%s: not found in sysfs", param); -+ major = dm_get_major(param); -+ if (major < 0) { -+ condlog(2, "%s: not a device mapper table", param); - return 0; - } -- return ev_add_map(sysdev, vecs); -+ sprintf(dev_path,"dm-%d", minor); -+ return ev_add_map(dev_path, major, minor, vecs); - } - - int -diff --git a/multipathd/main.c b/multipathd/main.c -index 6908902..bb396ec 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -46,6 +46,7 @@ - #include - #include - #include -+#include - - #include "main.h" - #include "pidfile.h" -@@ -212,32 +213,32 @@ flush_map(struct multipath * mpp, struct vectors * vecs) - } - - static int --uev_add_map (struct sysfs_device * dev, struct vectors * vecs) -+uev_add_map (struct uevent * uev, struct vectors * vecs) - { -- condlog(2, "%s: add map (uevent)", dev->kernel); -- return ev_add_map(dev, vecs); -+ int major, minor; -+ -+ condlog(2, "%s: add map (uevent)", uev->kernel); -+ major = uevent_get_major(uev); -+ minor = uevent_get_minor(uev); -+ return ev_add_map(uev->kernel, major, minor, vecs); - } - - int --ev_add_map (struct sysfs_device * dev, struct vectors * vecs) -+ev_add_map (char * dev, int major, int minor, struct vectors * vecs) - { - char * alias; -- char *dev_t; -- int major, minor; - char * refwwid; - struct multipath * mpp; - int map_present; - int r = 1; - -- dev_t = sysfs_attr_get_value(dev->devpath, "dev"); -- -- if (!dev_t || sscanf(dev_t, "%d:%d", &major, &minor) != 2) -- return 1; -- - alias = dm_mapname(major, minor); - -- if (!alias) -+ if (!alias) { -+ condlog(2, "%s: mapname not found for %d:%d", -+ dev, major, minor); - return 1; -+ } - - map_present = dm_map_present(alias); - -@@ -254,8 +255,7 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) - * if we create a multipath mapped device as a result - * of uev_add_path - */ -- condlog(0, "%s: devmap already registered", -- dev->kernel); -+ condlog(0, "%s: devmap already registered", dev); - return 0; - } - -@@ -264,10 +264,10 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) - */ - if (map_present && (mpp = add_map_without_path(vecs, minor, alias))) { - sync_map_state(mpp); -- condlog(2, "%s: devmap %s added", alias, dev->kernel); -+ condlog(2, "%s: devmap %s added", alias, dev); - return 0; - } -- refwwid = get_refwwid(dev->kernel, DEV_DEVMAP, vecs->pathvec); -+ refwwid = get_refwwid(dev, DEV_DEVMAP, vecs->pathvec); - - if (refwwid) { - r = coalesce_paths(vecs, NULL, refwwid, 0); -@@ -275,19 +275,19 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) - } - - if (!r) -- condlog(2, "%s: devmap %s added", alias, dev->kernel); -+ condlog(2, "%s: devmap %s added", alias, dev); - else -- condlog(0, "%s: uev_add_map %s failed", alias, dev->kernel); -+ condlog(0, "%s: uev_add_map %s failed", alias, dev); - - FREE(refwwid); - return r; - } - - static int --uev_remove_map (struct sysfs_device * dev, struct vectors * vecs) -+uev_remove_map (struct uevent * uev, struct vectors * vecs) - { -- condlog(2, "%s: remove map (uevent)", dev->kernel); -- return ev_remove_map(dev->kernel, vecs); -+ condlog(2, "%s: remove map (uevent)", uev->kernel); -+ return ev_remove_map(uev->kernel, vecs); - } - - int -@@ -308,13 +308,13 @@ ev_remove_map (char * devname, struct vectors * vecs) - } - - static int --uev_umount_map (struct sysfs_device * dev, struct vectors * vecs) -+uev_umount_map (struct uevent * uev, struct vectors * vecs) - { - struct multipath * mpp; - -- condlog(2, "%s: umount map (uevent)", dev->kernel); -+ condlog(2, "%s: umount map (uevent)", uev->kernel); - -- mpp = find_mp_by_str(vecs->mpvec, dev->kernel); -+ mpp = find_mp_by_str(vecs->mpvec, uev->kernel); - - if (!mpp) - return 0; -@@ -328,14 +328,21 @@ uev_umount_map (struct sysfs_device * dev, struct vectors * vecs) - return 0; - } - -+ - static int --uev_add_path (struct sysfs_device * dev, struct vectors * vecs) -+uev_add_path (struct uevent *uev, struct vectors * vecs) - { -+ struct sysfs_device * dev; -+ -+ dev = sysfs_device_get(uev->devpath); -+ if (!dev) { -+ condlog(2, "%s: not found in sysfs", uev->devpath); -+ return 1; -+ } - condlog(2, "%s: add path (uevent)", dev->kernel); - return (ev_add_path(dev->kernel, vecs) != 1)? 0 : 1; - } - -- - /* - * returns: - * 0: added -@@ -448,12 +455,19 @@ out: - } - - static int --uev_remove_path (struct sysfs_device * dev, struct vectors * vecs) -+uev_remove_path (struct uevent *uev, struct vectors * vecs) - { -+ struct sysfs_device * dev; - int retval; - -- condlog(2, "%s: remove path (uevent)", dev->kernel); -- retval = ev_remove_path(dev->kernel, vecs); -+ dev = sysfs_device_get(uev->devpath); -+ if (!dev) { -+ condlog(2, "%s: not found in sysfs", uev->devpath); -+ return 1; -+ } -+ condlog(2, "%s: remove path (uevent)", uev->kernel); -+ retval = ev_remove_path(uev->kernel, vecs); -+ - if (!retval) - sysfs_device_put(dev); - -@@ -625,7 +639,6 @@ int - uev_trigger (struct uevent * uev, void * trigger_data) - { - int r = 0; -- struct sysfs_device *sysdev; - struct vectors * vecs; - - vecs = (struct vectors *)trigger_data; -@@ -633,10 +646,6 @@ uev_trigger (struct uevent * uev, void * trigger_data) - if (uev_discard(uev->devpath)) - return 0; - -- sysdev = sysfs_device_get(uev->devpath); -- if(!sysdev) -- return 0; -- - lock(vecs->lock); - - /* -@@ -644,17 +653,17 @@ uev_trigger (struct uevent * uev, void * trigger_data) - * Add events are ignored here as the tables - * are not fully initialised then. - */ -- if (!strncmp(sysdev->kernel, "dm-", 3)) { -+ if (!strncmp(uev->kernel, "dm-", 3)) { - if (!strncmp(uev->action, "change", 6)) { -- r = uev_add_map(sysdev, vecs); -+ r = uev_add_map(uev, vecs); - goto out; - } - if (!strncmp(uev->action, "remove", 6)) { -- r = uev_remove_map(sysdev, vecs); -+ r = uev_remove_map(uev, vecs); - goto out; - } - if (!strncmp(uev->action, "umount", 6)) { -- r = uev_umount_map(sysdev, vecs); -+ r = uev_umount_map(uev, vecs); - goto out; - } - goto out; -@@ -664,15 +673,15 @@ uev_trigger (struct uevent * uev, void * trigger_data) - * path add/remove event - */ - if (filter_devnode(conf->blist_devnode, conf->elist_devnode, -- sysdev->kernel) > 0) -+ uev->kernel) > 0) - goto out; - - if (!strncmp(uev->action, "add", 3)) { -- r = uev_add_path(sysdev, vecs); -+ r = uev_add_path(uev, vecs); - goto out; - } - if (!strncmp(uev->action, "remove", 6)) { -- r = uev_remove_path(sysdev, vecs); -+ r = uev_remove_path(uev, vecs); - goto out; - } - -@@ -1383,6 +1392,9 @@ child (void * param) - FREE(vecs); - vecs = NULL; - -+ cleanup_checkers(); -+ cleanup_prio(); -+ - condlog(2, "--------shut down-------"); - - if (logsink) -diff --git a/multipathd/main.h b/multipathd/main.h -index d73cd70..5d6f1b8 100644 ---- a/multipathd/main.h -+++ b/multipathd/main.h -@@ -7,7 +7,7 @@ - int reconfigure (struct vectors *); - int ev_add_path (char *, struct vectors *); - int ev_remove_path (char *, struct vectors *); --int ev_add_map (struct sysfs_device *, struct vectors *); -+int ev_add_map (char *, int, int, struct vectors *); - int ev_remove_map (char *, struct vectors *); - void sync_map_state (struct multipath *); - --- -1.5.3.2 - diff --git a/multipath-tools-search-for-correct-hwe b/multipath-tools-search-for-correct-hwe deleted file mode 100644 index af3be14..0000000 --- a/multipath-tools-search-for-correct-hwe +++ /dev/null @@ -1,98 +0,0 @@ -From 90d210e6c277d6d822ed66a47d546a91703e4fd9 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 20 Nov 2008 12:33:39 +0100 -Subject: [PATCH] Search for correct hwe in update_multipath() - -When updating the multipath structure we only should update the -hardware entry if it doesn't exist anymore. And we should take -care of not selecting invalid entries in the paths vector as -the hardware entry for this is invalid, too. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/structs_vec.c | 52 ++++++++++++++++++++++++++++++++++++++----- - 1 files changed, 46 insertions(+), 6 deletions(-) - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 785a766..17cafd1 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -27,7 +27,7 @@ update_mpp_paths(struct multipath * mpp, vector pathvec) - struct path * pp; - int i,j; - -- if (!mpp->pg) -+ if (!mpp || !mpp->pg) - return 0; - - if (!mpp->paths && -@@ -188,13 +188,48 @@ static struct hwentry * - extract_hwe_from_path(struct multipath * mpp) - { - struct path * pp = NULL; -+ int pg_num = -1, p_num = -1, i; - struct pathgroup * pgp = NULL; - -- if (mpp && mpp->pg) -- pgp = VECTOR_SLOT(mpp->pg, 0); -+ condlog(3, "%s: searching paths for valid hwe", mpp->alias); - -- if (pgp && pgp->paths) -- pp = VECTOR_SLOT(pgp->paths, 0); -+ if (mpp && mpp->pg) { -+ vector_foreach_slot(mpp->pg, pgp, i) { -+ if (pgp->status == PGSTATE_ACTIVE || -+ pgp->status == PGSTATE_ENABLED) { -+ pg_num = i; -+ break; -+ } -+ } -+ if (pg_num >= 0) -+ pgp = VECTOR_SLOT(mpp->pg, pg_num); -+ } -+ -+ if (pgp && pgp->paths) { -+ vector_foreach_slot(pgp->paths, pp, i) { -+ if (pp->dmstate == PSTATE_FAILED) -+ continue; -+ if (strlen(pp->vendor_id) > 0 && -+ strlen(pp->product_id) > 0 && -+ strlen(pp->rev) > 0) { -+ p_num = i; -+ break; -+ } -+ } -+ if (p_num >= 0) -+ pp = VECTOR_SLOT(pgp->paths, i); -+ } -+ -+ if (pp) { -+ condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id); -+ condlog(3, "%s: product = %s", pp->dev, pp->product_id); -+ condlog(3, "%s: rev = %s", pp->dev, pp->rev); -+ if (!pp->hwe) { -+ condlog(3, "searching hwtable"); -+ pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, -+ pp->product_id, pp->rev); -+ } -+ } - - return pp?pp->hwe:NULL; - } -@@ -316,7 +351,12 @@ retry: - } - - //adopt_paths(vecs->pathvec, mpp); -- mpp->hwe = extract_hwe_from_path(mpp); -+ if (!mpp->hwe) -+ mpp->hwe = extract_hwe_from_path(mpp); -+ if (!mpp->hwe) { -+ condlog(3, "%s: no hardware entry found, using defaults", -+ mpp->alias); -+ } - select_rr_weight(mpp); - select_pgfailback(mpp); - set_no_path_retry(mpp); --- -1.5.3.2 - diff --git a/multipath-tools-set-max_fds-parameter-for-multipath b/multipath-tools-set-max_fds-parameter-for-multipath deleted file mode 100644 index a972490..0000000 --- a/multipath-tools-set-max_fds-parameter-for-multipath +++ /dev/null @@ -1,53 +0,0 @@ -From cce0922defb5c89c63ed42d2ea4a398d6a8c5a29 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Tue, 9 Dec 2008 12:26:49 +0100 -Subject: [PATCH] Set 'max_fds' parameter for multipath - -max_fds should be enabled for multipath, too. - -References: 457443 - -Signed-off-by: Hannes Reinecke ---- - multipath/main.c | 18 ++++++++++++++++++ - 1 files changed, 18 insertions(+), 0 deletions(-) - -diff --git a/multipath/main.c b/multipath/main.c -index ffa6eb5..49b5619 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -48,6 +48,9 @@ - #include - #include - #include -+#include -+#include -+#include - - int logsink; - -@@ -477,6 +480,21 @@ main (int argc, char *argv[]) - conf->dev_type = DEV_DEVMAP; - - } -+ if (conf->max_fds) { -+ struct rlimit fd_limit; -+ if (conf->max_fds > 0) { -+ fd_limit.rlim_cur = conf->max_fds; -+ fd_limit.rlim_max = conf->max_fds; -+ } -+ else { -+ fd_limit.rlim_cur = RLIM_INFINITY; -+ fd_limit.rlim_max = RLIM_INFINITY; -+ } -+ if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) -+ condlog(0, "can't set open fds limit to %d : %s\n", -+ conf->max_fds, strerror(errno)); -+ } -+ - dm_init(); - - if (conf->remove == FLUSH_ONE) { --- -1.6.0.2 - diff --git a/multipath-tools-shuffle-memarea-init b/multipath-tools-shuffle-memarea-init deleted file mode 100644 index 6720322..0000000 --- a/multipath-tools-shuffle-memarea-init +++ /dev/null @@ -1,38 +0,0 @@ -commit a8c6e0c6da02d83b86280dbd1162c44f8cefb53f -Author: Hannes Reinecke -Date: Wed Jan 7 10:59:46 2009 +0100 - - Shuffle to the call to memset in logarea_init() - - We should call memset only after we know the area has been - allocated. - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/log.c b/libmultipath/log.c -index 0dd1c22..0cf5047 100644 ---- a/libmultipath/log.c -+++ b/libmultipath/log.c -@@ -47,12 +47,11 @@ static int logarea_init (int size) - size = DEFAULT_AREA_SIZE; - - la->start = MALLOC(size); -- memset(la->start, 0, size); -- - if (!la->start) { - FREE(la); - return 1; - } -+ memset(la->start, 0, size); - - la->empty = 1; - la->end = la->start + size; -@@ -143,7 +142,7 @@ int log_enqueue (int prio, const char * fmt, va_list ap) - la->empty = 0; - msg = (struct logmsg *)la->tail; - msg->prio = prio; -- memcpy((void *)&msg->str, buff, strlen(buff)); -+ strcpy((void *)&msg->str, buff); - lastmsg->next = la->tail; - msg->next = la->head; - diff --git a/multipath-tools-sles11-alpha1-update b/multipath-tools-sles11-alpha1-update deleted file mode 100644 index 2100a52..0000000 --- a/multipath-tools-sles11-alpha1-update +++ /dev/null @@ -1,3626 +0,0 @@ ---- multipath-tools-0.4.8/Makefile.inc -+++ multipath-tools-0.4.8/Makefile.inc -@@ -13,7 +13,7 @@ - TOPDIR = .. - endif - --prefix = -+prefix = - exec_prefix = $(prefix) - bindir = $(exec_prefix)/sbin - libudevdir = ${prefix}/lib/udev ---- multipath-tools-0.4.8/kpartx/Makefile -+++ multipath-tools-0.4.8/kpartx/Makefile -@@ -15,21 +15,29 @@ - - $(EXEC): $(OBJS) - $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) -- $(GZIP) $(EXEC).8 > $(EXEC).8.gz -- -+ - install: $(EXEC) $(EXEC).8 - $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) -+ $(INSTALL_PROGRAM) -m 755 activate_dm_linear $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir) - $(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir) - $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d -- $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/ -+ $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules - $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) -- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)/lib/mkinitrd/scripts -+ $(INSTALL_PROGRAM) -m 755 boot-kpartx.sh $(DESTDIR)/lib/mkinitrd/scripts -+ $(INSTALL_PROGRAM) -m 755 setup-kpartx.sh $(DESTDIR)/lib/mkinitrd/scripts - - uninstall: - rm -f $(DESTDIR)$(bindir)/$(EXEC) -- rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz -+ rm -f $(DESTDIR)$(bindir)/activate_dm_linear -+ rm -f $(DESTDIR)$(libudevdir)/kpartx_id -+ rm -f $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules -+ rm -f $(DESTDIR)$(mandir)/$(EXEC).8 -+ rm -f $(DESTDIR)/lib/mkinitrd/scripts/boot-kpartx.sh -+ rm -f $(DESTDIR)/lib/mkinitrd/scripts/setup-kpartx.sh - - clean: -- rm -f core *.o $(EXEC) *.gz -+ rm -f core *.o $(EXEC) ---- multipath-tools-0.4.8/kpartx/activate_dm_linear -+++ multipath-tools-0.4.8/kpartx/activate_dm_linear -@@ -0,0 +1,72 @@ -+#!/bin/sh -+# -+# activate_dm_linear -+# -+# Activate a linear mapping on top of an existing block device. -+# This allows for partitions to be mapped via kpartx, so all -+# partitions on a device can be accessed. -+# -+ -+RULE=/etc/udev/rules.d/62-dm_linear.rules -+ -+if [ -z "$1" ] ; then -+ echo "Usage: $0 [-d] devname" -+ exit 1 -+fi -+ -+if [ "$1" == "-d" ] ; then -+ remove_only=1 -+ shift -+fi -+ -+if [ ! -b "$1" ] ; then -+ echo "$1 is not a block device" -+ exit 1 -+fi -+ -+dev=${1#/dev/} -+ -+if [ ! -d /sys/block/$dev ] ; then -+ echo "$1 is not a disk device" -+ exit 1 -+fi -+ -+blksize=$(/sbin/blockdev --getsize $1) -+if [ $? -ne 0 ] ; then -+ echo "blockdev --getsize $1 failed: $?" -+ exit 1 -+fi -+ -+for link in $(udevadm info -q symlink -p /block/$dev) ; do -+ case "$link" in -+ */by-id/ata*) -+ atalink=${link#*/by-id/ata-} -+ ;; -+ */by-id/scsi*) -+ scsilink=${link#*/by-id/scsi-} -+ ;; -+ esac -+done -+if [ "$atalink" ] ; then -+ # Remove existing rules -+ echo "/$atalink/d -+w -+q -+" | ed $RULE > /dev/null 2>&1 -+ [ "$remove_only" = 1 ] && exit 0 -+ cat >> $RULE < /dev/null 2>&1 -+ [ "$remove_only" = 1 ] && exit 0 -+ # And create a new one -+ cat >> $RULE < params + strlen(params)) -+ break; -+ /* Skip whitespaces */ -+ while(ptr && *ptr == ' ') ptr++; -+ if (!strncmp(ptr, FEATURE_NO_PART, strlen(FEATURE_NO_PART))) -+ return 1; -+ ptr = strchr(ptr, ' '); -+ } -+ return 0; -+} -+ ---- multipath-tools-0.4.8/kpartx/devmapper.h -+++ multipath-tools-0.4.8/kpartx/devmapper.h -@@ -7,3 +7,4 @@ - dev_t dm_get_first_dep(char *devname); - char * dm_mapuuid(int major, int minor); - int dm_devn (char * mapname, int *major, int *minor); -+int dm_no_partitions(int major, int minor); ---- multipath-tools-0.4.8/kpartx/kpartx.c -+++ multipath-tools-0.4.8/kpartx/kpartx.c -@@ -257,7 +257,7 @@ - } - - if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) { -- fprintf(stderr, "device mapper prerequisites not met\n"); -+ fprintf(stderr, "device mapper prerequisites not met\n"); - exit(1); - } - -@@ -314,8 +314,13 @@ - if (!uuid) - uuid = device + off; - -- if (!mapname) -+ if (!mapname) { - mapname = device + off; -+ } else if (dm_no_partitions((unsigned int)MAJOR(buf.st_rdev), -+ (unsigned int)MINOR(buf.st_rdev))) { -+ /* Feature 'no_partitions' is set, return */ -+ return 0; -+ } - - fd = open(device, O_RDONLY); - -@@ -423,7 +428,7 @@ - break; - - case ADD: -- for (j=0, c = 0; jregex, str, 0, NULL, 0)) -+ vector_foreach_slot (elist, ele, i) { -+ if (!regexec(&ele->regex, str, 0, NULL, 0)) - return 1; - } -- return 0; -+ return 0; - } - - int -@@ -194,11 +194,11 @@ - } - - #define LOG_BLIST(M) \ -- if (vendor && product) \ -+ if (vendor && product) \ - condlog(3, "%s: (%s:%s) %s", dev, vendor, product, (M)); \ -- else if (wwid) \ -- condlog(3, "%s: (%s) %s", dev, wwid, (M)); \ -- else \ -+ else if (wwid) \ -+ condlog(3, "%s: (%s) %s", dev, wwid, (M)); \ -+ else \ - condlog(3, "%s: %s", dev, (M)) - - void -@@ -300,7 +300,7 @@ - if (r > 0) - return r; - r = _filter_device(conf->blist_device, conf->elist_device, -- pp->vendor_id, pp->product_id); -+ pp->vendor_id, pp->product_id); - if (r > 0) - return r; - r = _filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid); ---- multipath-tools-0.4.8/libmultipath/callout.c -+++ multipath-tools-0.4.8/libmultipath/callout.c -@@ -83,8 +83,8 @@ - null_fd = open("/dev/null", O_WRONLY); - if (null_fd > 0) { - close(STDERR_FILENO); -- dup(null_fd); -- close(null_fd); -+ if (dup(null_fd) >= 0) -+ close(null_fd); - } - - retval = execv(argv[0], argv); ---- multipath-tools-0.4.8/libmultipath/config.c -+++ multipath-tools-0.4.8/libmultipath/config.c -@@ -50,42 +50,55 @@ - return ret; - } - -+static int -+hwe_regmatch (struct hwentry *hwe1, struct hwentry *hwe2) -+{ -+ regex_t vre, pre, rre; -+ int retval = 1; -+ -+ if (hwe1->vendor && -+ regcomp(&vre, hwe1->vendor, REG_EXTENDED|REG_NOSUB)) -+ goto out; -+ -+ if (hwe1->product && -+ regcomp(&pre, hwe1->product, REG_EXTENDED|REG_NOSUB)) -+ goto out_vre; -+ -+ if (hwe1->revision && -+ regcomp(&rre, hwe1->revision, REG_EXTENDED|REG_NOSUB)) -+ goto out_pre; -+ -+ if ((!hwe1->vendor || !regexec(&vre, hwe2->vendor, 0, NULL, 0)) && -+ (!hwe1->product || !regexec(&pre, hwe2->product, 0, NULL, 0)) && -+ (!hwe1->revision || !regexec(&rre, hwe2->revision, 0, NULL, 0))) -+ retval = 0; -+ -+ if (hwe1->revision) -+ regfree(&rre); -+out_pre: -+ if (hwe1->product) -+ regfree(&pre); -+out_vre: -+ if (hwe1->vendor) -+ regfree(&vre); -+out: -+ return retval; -+} -+ - struct hwentry * - find_hwe (vector hwtable, char * vendor, char * product, char * revision) - { - int i; -- struct hwentry *hwe, *ret = NULL; -- regex_t vre, pre, rre; -+ struct hwentry hwe, *tmp, *ret = NULL; - -- vector_foreach_slot (hwtable, hwe, i) { -- if (hwe->vendor && -- regcomp(&vre, hwe->vendor, REG_EXTENDED|REG_NOSUB)) -- break; -- if (hwe->product && -- regcomp(&pre, hwe->product, REG_EXTENDED|REG_NOSUB)) { -- regfree(&vre); -- break; -- } -- if (hwe->revision && -- regcomp(&rre, hwe->revision, REG_EXTENDED|REG_NOSUB)) { -- regfree(&vre); -- regfree(&pre); -- break; -- } -- if ((!hwe->vendor || !regexec(&vre, vendor, 0, NULL, 0)) && -- (!hwe->product || !regexec(&pre, product, 0, NULL, 0)) && -- (!hwe->revision || !regexec(&rre, revision, 0, NULL, 0))) -- ret = hwe; -- -- if (hwe->revision) -- regfree(&rre); -- if (hwe->product) -- regfree(&pre); -- if (hwe->vendor) -- regfree(&vre); -- -- if (ret) -- break; -+ hwe.vendor = vendor; -+ hwe.product = product; -+ hwe.revision = revision; -+ vector_foreach_slot (hwtable, tmp, i) { -+ if (hwe_regmatch(tmp, &hwe)) -+ continue; -+ ret = tmp; -+ break; - } - return ret; - } -@@ -289,25 +302,25 @@ - - if (find_hwe_strmatch(hwtable, dhwe)) - return 0; -- -+ - if (!(hwe = alloc_hwe())) - return 1; - - if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor))) - goto out; -- -+ - if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product))) - goto out; -- -+ - if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision))) - goto out; -- -+ - if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid))) - goto out; - - if (dhwe->features && !(hwe->features = set_param_str(dhwe->features))) - goto out; -- -+ - if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler))) - goto out; - -@@ -316,10 +329,10 @@ - - if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name))) - goto out; -- -+ - if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name))) - goto out; -- -+ - hwe->pgpolicy = dhwe->pgpolicy; - hwe->pgfailback = dhwe->pgfailback; - hwe->rr_weight = dhwe->rr_weight; -@@ -348,7 +361,7 @@ - vector_foreach_slot(hw, hwe1, i) { - j = i+1; - vector_foreach_slot_after(hw, hwe2, j) { -- if (hwe_strmatch(hwe1, hwe2)) -+ if (hwe_regmatch(hwe1, hwe2)) - continue; - /* dup */ - merge_hwe(hwe1, hwe2); -@@ -393,6 +406,9 @@ - if (conf->hwhandler) - FREE(conf->hwhandler); - -+ if (conf->bindings_file) -+ FREE(conf->bindings_file); -+ - free_blacklist(conf->blist_devnode); - free_blacklist(conf->blist_wwid); - free_blacklist_device(conf->blist_device); -@@ -425,7 +441,6 @@ - conf->dev_type = DEV_NONE; - conf->minio = 1000; - conf->max_fds = 0; -- conf->bindings_file = DEFAULT_BINDINGS_FILE; - conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR); - - /* -@@ -443,12 +458,15 @@ - /* - * read the config file - */ -+ set_current_keywords(&conf->keywords); -+ alloc_keywords(); - if (filepresent(file)) { -- set_current_keywords(&conf->keywords); - if (init_data(file, init_keywords)) { - condlog(0, "error parsing config file"); - goto out; - } -+ } else { -+ init_keywords(); - } - - /* -@@ -503,7 +521,6 @@ - - if (conf->mptable == NULL) { - conf->mptable = vector_alloc(); -- - if (!conf->mptable) - goto out; - } -@@ -522,9 +539,12 @@ - if (conf->hwhandler == NULL) - conf->hwhandler = set_default(DEFAULT_HWHANDLER); - -+ if (conf->bindings_file == NULL) -+ conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); -+ - if (!conf->selector || !conf->udev_dir || !conf->multipath_dir || - !conf->getuid || !conf->features || -- !conf->hwhandler) -+ !conf->hwhandler || !conf->bindings_file) - goto out; - - if (!conf->prio_name) ---- multipath-tools-0.4.8/libmultipath/configure.c -+++ multipath-tools-0.4.8/libmultipath/configure.c -@@ -162,7 +162,7 @@ - mpp->alias); - return; - } -- -+ - if (pathcount(mpp, PATH_UP) == 0) { - mpp->action = ACT_NOTHING; - condlog(3, "%s: set ACT_NOTHING (no usable path)", -@@ -272,7 +272,7 @@ - - if (!mpp || !mpp->pg) - return 0; -- -+ - vector_foreach_slot (mpp->pg, pgp, i) { - if (!pgp->paths) - continue; -@@ -402,7 +402,7 @@ - if (strlen(pp->dev)) - return 0; /* alive */ - } -- -+ - return 1; /* dead */ - } - -@@ -460,13 +460,13 @@ - remove_map(mpp, vecs, 0); - continue; - } -- -+ - for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) { - pp2 = VECTOR_SLOT(pathvec, i); - - if (strcmp(pp1->wwid, pp2->wwid)) - continue; -- -+ - if (!pp2->size) - continue; - ---- multipath-tools-0.4.8/libmultipath/defaults.h -+++ multipath-tools-0.4.8/libmultipath/defaults.h -@@ -1,4 +1,4 @@ --#define DEFAULT_GETUID "/lib/udev/scsi_id -g -u -s /block/%n" -+#define DEFAULT_GETUID "/lib/udev/scsi_id -g -u /dev/%n" - #define DEFAULT_UDEVDIR "/dev" - #define DEFAULT_MULTIPATHDIR "/lib/multipath" - #define DEFAULT_SELECTOR "round-robin 0" ---- multipath-tools-0.4.8/libmultipath/devmapper.c -+++ multipath-tools-0.4.8/libmultipath/devmapper.c -@@ -161,9 +161,9 @@ - goto out; - - dm_task_no_open_count(dmt); -- dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ -+ dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ - #ifdef LIBDM_API_FLUSH -- dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ -+ dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ - #endif - - r = dm_task_run (dmt); -@@ -340,11 +340,11 @@ - if (!dmt) - return 1; - -- if (!dm_task_set_name (dmt, name)) -- goto uuidout; -+ if (!dm_task_set_name (dmt, name)) -+ goto uuidout; - - if (!dm_task_run(dmt)) -- goto uuidout; -+ goto uuidout; - - uuidtmp = dm_task_get_uuid(dmt); - if (uuidtmp) { -@@ -466,7 +466,7 @@ - dm_task_destroy(dmt); - return r; - } -- -+ - int - dm_get_opencount (const char * mapname) - { -@@ -491,7 +491,7 @@ - dm_task_destroy(dmt); - return r; - } -- -+ - int - dm_get_minor (char * mapname) - { -@@ -516,7 +516,7 @@ - dm_task_destroy(dmt); - return r; - } -- -+ - extern int - dm_flush_map (const char * mapname) - { -@@ -534,7 +534,7 @@ - if (dm_get_opencount(mapname)) { - condlog(2, "%s: map in use", mapname); - return 1; -- } -+ } - - r = dm_simplecmd(DM_DEVICE_REMOVE, mapname); - -@@ -746,8 +746,8 @@ - vector_set_slot(mp, mpp); - mpp = NULL; - next: -- next = names->next; -- names = (void *) names + next; -+ next = names->next; -+ names = (void *) names + next; - } while (next); - - r = 0; -@@ -927,7 +927,7 @@ - */ - strstr(params, dev_t) - ) { -- /* -+ /* - * then it's a kpartx generated partition. - * remove it. - */ -@@ -957,7 +957,7 @@ - { - int r = 1; - struct dm_task *dmt = NULL; -- -+ - if (!mapname) - return 1; - -@@ -1045,7 +1045,7 @@ - */ - strstr(buff, dev_t) - ) { -- /* -+ /* - * then it's a kpartx generated partition. - * Rename it. - */ -@@ -1083,7 +1083,7 @@ - - if (!dm_task_set_newname(dmt, new)) - goto out; -- -+ - dm_task_no_open_count(dmt); - - if (!dm_task_run(dmt)) ---- multipath-tools-0.4.8/libmultipath/dict.c -+++ multipath-tools-0.4.8/libmultipath/dict.c -@@ -88,7 +88,7 @@ - - if (!conf->getuid) - return 1; -- -+ - return 0; - } - -@@ -267,6 +267,17 @@ - return 0; - } - -+static int -+bindings_file_handler(vector strvec) -+{ -+ conf->bindings_file = set_value(strvec); -+ -+ if (!conf->bindings_file) -+ return 1; -+ -+ return 0; -+} -+ - /* - * blacklist block handlers - */ -@@ -338,12 +349,12 @@ - static int - ble_except_wwid_handler(vector strvec) - { -- char * buff; -+ char * buff; - -- buff = set_value(strvec); -+ buff = set_value(strvec); - -- if (!buff) -- return 1; -+ if (!buff) -+ return 1; - - return store_ble(conf->elist_wwid, buff, ORIGIN_CONFIG); - } -@@ -453,7 +464,7 @@ - - if (!hwe) - return 1; -- -+ - hwe->vendor = set_value(strvec); - - if (!hwe->vendor) -@@ -469,7 +480,7 @@ - - if (!hwe) - return 1; -- -+ - hwe->product = set_value(strvec); - - if (!hwe->product) -@@ -527,7 +538,7 @@ - hw_selector_handler(vector strvec) - { - struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); -- -+ - if (!hwe) - return 1; - -@@ -559,7 +570,7 @@ - hw_features_handler(vector strvec) - { - struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); -- -+ - if (!hwe) - return 1; - -@@ -575,7 +586,7 @@ - hw_handler_handler(vector strvec) - { - struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); -- -+ - if (!hwe) - return 1; - -@@ -781,7 +792,7 @@ - if (!mpe) - return 1; - -- mpe->alias = set_value(strvec); -+ mpe->alias = set_value(strvec); - - if (!mpe->alias) - return 1; -@@ -813,7 +824,7 @@ - mp_selector_handler(vector strvec) - { - struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); -- -+ - if (!mpe) - return 1; - -@@ -981,7 +992,7 @@ - if (!mpe->pgpolicy) - return 0; - get_pgpolicy_name(str, POLICY_NAME_SIZE, mpe->pgpolicy); -- -+ - return snprintf(buff, len, "%s", str); - } - -@@ -1194,7 +1205,7 @@ - return 0; - - get_pgpolicy_name(str, POLICY_NAME_SIZE, hwe->pgpolicy); -- -+ - return snprintf(buff, len, "%s", str); - } - -@@ -1362,7 +1373,7 @@ - return 0; - - get_pgpolicy_name(str, POLICY_NAME_SIZE, conf->pgpolicy); -- -+ - return snprintf(buff, len, "%s", str); - } - -@@ -1454,7 +1465,7 @@ - return 0; - - if (conf->max_fds < 0) -- return snprintf(buff, len, "unlimited"); -+ return snprintf(buff, len, "unlimited"); - return snprintf(buff, len, "%d", conf->max_fds); - } - -@@ -1520,6 +1531,18 @@ - } - - static int -+snprint_def_bindings_file (char * buff, int len, void * data) -+{ -+ if (conf->bindings_file == NULL) -+ return 0; -+ if (strlen(conf->bindings_file) == strlen(DEFAULT_BINDINGS_FILE) && -+ !strcmp(conf->bindings_file, DEFAULT_BINDINGS_FILE)) -+ return 0; -+ -+ return snprintf(buff, len, "%s", conf->bindings_file); -+} -+ -+static int - snprint_ble_simple (char * buff, int len, void * data) - { - struct blentry * ble = (struct blentry *)data; -@@ -1534,7 +1557,7 @@ - - return snprintf(buff, len, "\"%s\"", bled->vendor); - } -- -+ - static int - snprint_bled_product (char * buff, int len, void * data) - { -@@ -1542,7 +1565,7 @@ - - return snprintf(buff, len, "\"%s\"", bled->product); - } -- -+ - #define __deprecated - - void -@@ -1566,6 +1589,7 @@ - install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry); - install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout); - install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names); -+ install_keyword("bindings_file", &bindings_file_handler, &snprint_def_bindings_file); - __deprecated install_keyword("default_selector", &def_selector_handler, NULL); - __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); - __deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL); ---- multipath-tools-0.4.8/libmultipath/discovery.c -+++ multipath-tools-0.4.8/libmultipath/discovery.c -@@ -70,7 +70,7 @@ - condlog(0, "path too small"); - return 1; - } -- -+ - if (strncmp(devname,"cciss",5) && !filepresent(path)) { - condlog(4, "path %s not present", path); - return 0; -@@ -179,7 +179,7 @@ - - return 0; - } -- -+ - int - sysfs_get_fc_nodename (struct sysfs_device * dev, char * node, - unsigned int host, unsigned int channel, -@@ -187,7 +187,7 @@ - { - char attr_path[SYSFS_PATH_SIZE], *attr; - -- if (safe_sprintf(attr_path, -+ if (safe_sprintf(attr_path, - "/class/fc_transport/target%i:%i:%i", - host, channel, target)) { - condlog(0, "attr_path too small"); -@@ -202,10 +202,7 @@ - - return 1; - } -- --/* -- * udev might be slow creating node files : wait -- */ -+ - static int - opennode (char * dev, int mode) - { -@@ -244,11 +241,11 @@ - condlog(0, "Cannot open /proc/partitions"); - return 1; - } -- -+ - while (!feof(fd)) { - int r = fscanf(fd,"%u %u %*d %s",&tmpmaj, &tmpmin, dev); - if (!r) { -- fscanf(fd,"%*s\n"); -+ r = fscanf(fd,"%*s\n"); - continue; - } - if (r != 3) -@@ -280,62 +277,62 @@ - do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, - void *resp, int mx_resp_len, int noisy) - { -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = -- { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -- unsigned char sense_b[SENSE_BUFF_LEN]; -- struct sg_io_hdr io_hdr; -- -- if (cmddt) -- inqCmdBlk[1] |= 2; -- if (evpd) -- inqCmdBlk[1] |= 1; -- inqCmdBlk[2] = (unsigned char) pg_op; -+ unsigned char inqCmdBlk[INQUIRY_CMDLEN] = -+ { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -+ unsigned char sense_b[SENSE_BUFF_LEN]; -+ struct sg_io_hdr io_hdr; -+ -+ if (cmddt) -+ inqCmdBlk[1] |= 2; -+ if (evpd) -+ inqCmdBlk[1] |= 1; -+ inqCmdBlk[2] = (unsigned char) pg_op; - inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); - inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_b); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = mx_resp_len; -- io_hdr.dxferp = resp; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sense_b; -- io_hdr.timeout = DEF_TIMEOUT; -- -- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -- return -1; -- -- /* treat SG_ERR here to get rid of sg_err.[ch] */ -- io_hdr.status &= 0x7e; -- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -- (0 == io_hdr.driver_status)) -- return 0; -- if ((SCSI_CHECK_CONDITION == io_hdr.status) || -- (SCSI_COMMAND_TERMINATED == io_hdr.status) || -- (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -- if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -- int sense_key; -- unsigned char * sense_buffer = io_hdr.sbp; -- if (sense_buffer[0] & 0x2) -- sense_key = sense_buffer[1] & 0xf; -- else -- sense_key = sense_buffer[2] & 0xf; -- if(RECOVERED_ERROR == sense_key) -- return 0; -- } -- } -- return -1; -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (inqCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sense_b); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = mx_resp_len; -+ io_hdr.dxferp = resp; -+ io_hdr.cmdp = inqCmdBlk; -+ io_hdr.sbp = sense_b; -+ io_hdr.timeout = DEF_TIMEOUT; -+ -+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -+ return -1; -+ -+ /* treat SG_ERR here to get rid of sg_err.[ch] */ -+ io_hdr.status &= 0x7e; -+ if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -+ (0 == io_hdr.driver_status)) -+ return 0; -+ if ((SCSI_CHECK_CONDITION == io_hdr.status) || -+ (SCSI_COMMAND_TERMINATED == io_hdr.status) || -+ (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -+ if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -+ int sense_key; -+ unsigned char * sense_buffer = io_hdr.sbp; -+ if (sense_buffer[0] & 0x2) -+ sense_key = sense_buffer[1] & 0xf; -+ else -+ sense_key = sense_buffer[2] & 0xf; -+ if(RECOVERED_ERROR == sense_key) -+ return 0; -+ } -+ } -+ return -1; - } - - static int - get_serial (char * str, int maxlen, int fd) - { -- int len = 0; -- char buff[MX_ALLOC_LEN + 1] = {0}; -+ int len = 0; -+ char buff[MX_ALLOC_LEN + 1] = {0}; - - if (fd < 0) -- return 1; -+ return 1; - - if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { - len = buff[3]; -@@ -347,7 +344,7 @@ - } - return 0; - } -- return 1; -+ return 1; - } - - static int -@@ -459,7 +456,7 @@ - - /* - * host / bus / target / lun -- */ -+ */ - basename(parent->devpath, attr_path); - pp->sg_id.lun = 0; - sscanf(attr_path, "%i.%i.%x", ---- multipath-tools-0.4.8/libmultipath/dmparser.c -+++ multipath-tools-0.4.8/libmultipath/dmparser.c -@@ -59,7 +59,7 @@ - minio = mp->minio; - p = mp->params; - freechar = sizeof(mp->params); -- -+ - shift = snprintf(p, freechar, "%s %s %i %i", - mp->features, mp->hwhandler, - VECTOR_SIZE(mp->pg), mp->bestpg); -@@ -70,7 +70,7 @@ - } - p += shift; - freechar -= shift; -- -+ - vector_foreach_slot (mp->pg, pgp, i) { - pgp = VECTOR_SLOT(mp->pg, i); - shift = snprintf(p, freechar, " %s %i 1", mp->selector, -@@ -184,11 +184,11 @@ - num_pg = atoi(word); - FREE(word); - -- if (num_pg > 0 && !mpp->pg) { -+ if (num_pg > 0 && !mpp->pg) - mpp->pg = vector_alloc(); -- if (!mpp->pg) -- return 1; -- } -+ -+ if (!mpp->pg) -+ return 1; - - /* - * first pg to try -@@ -221,7 +221,7 @@ - goto out; - - num_pg_args = atoi(word); -- -+ - if (merge_words(&mpp->selector, word, 1)) { - FREE(word); - goto out1; -@@ -239,7 +239,7 @@ - * paths - */ - pgp = alloc_pathgroup(); -- -+ - if (!pgp) - goto out; - ---- multipath-tools-0.4.8/libmultipath/hwtable.c -+++ multipath-tools-0.4.8/libmultipath/hwtable.c -@@ -172,7 +172,7 @@ - /* HP Smart Array */ - .vendor = "HP", - .product = "LOGICAL VOLUME.*", -- .getuid = "/lib/udev/scsi_id -n -g -u -s /block/%n", -+ .getuid = "/lib/udev/scsi_id -n -g -u /dev/%n", - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -214,7 +214,7 @@ - { - .vendor = "EMC", - .product = "SYMMETRIX", -- .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 -s /block/%n", -+ .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 /dev/%n", - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -533,7 +533,7 @@ - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = 128, - .checker_name = DIRECTIO, -- .prio_name = PRIO_NETAPP, -+ .prio_name = PRIO_ONTAP, - }, - /* - * IBM NSeries (NETAPP) controller family -@@ -554,7 +554,7 @@ - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = 128, - .checker_name = DIRECTIO, -- .prio_name = PRIO_NETAPP, -+ .prio_name = PRIO_ONTAP, - }, - /* - * Pillar Data controller family ---- multipath-tools-0.4.8/libmultipath/log.c -+++ multipath-tools-0.4.8/libmultipath/log.c -@@ -18,7 +18,7 @@ - static void dump_logarea (void) - { - struct logmsg * msg; -- -+ - logdbg(stderr, "\n==== area: start addr = %p, end addr = %p ====\n", - la->start, la->end); - logdbg(stderr, "|addr |next |prio|msg\n"); -@@ -34,12 +34,12 @@ - logdbg(stderr, "\n\n"); - } - #endif -- -+ - static int logarea_init (int size) - { - logdbg(stderr,"enter logarea_init\n"); - la = (struct logarea *)MALLOC(sizeof(struct logarea)); -- -+ - if (!la) - return 1; - -@@ -107,7 +107,7 @@ - lastmsg = (struct logmsg *)la->tail; - - if (!la->empty) { -- fwd = sizeof(struct logmsg) + -+ fwd = sizeof(struct logmsg) + - strlen((char *)&lastmsg->str) * sizeof(char) + 1; - la->tail += ALIGN(fwd, sizeof(void *)); - } -@@ -118,11 +118,11 @@ - /* not enough space on tail : rewind */ - if (la->head <= la->tail && len > (la->end - la->tail)) { - logdbg(stderr, "enqueue: rewind tail to %p\n", la->tail); -- if (la->head == la->start ) { -- logdbg(stderr, "enqueue: can not rewind tail, drop msg\n"); -- la->tail = lastmsg; -- return 1; /* can't reuse */ -- } -+ if (la->head == la->start ) { -+ logdbg(stderr, "enqueue: can not rewind tail, drop msg\n"); -+ la->tail = lastmsg; -+ return 1; /* can't reuse */ -+ } - la->tail = la->start; - - if (la->empty) ---- multipath-tools-0.4.8/libmultipath/log_pthread.c -+++ multipath-tools-0.4.8/libmultipath/log_pthread.c -@@ -53,17 +53,17 @@ - void log_thread_start (void) - { - pthread_attr_t attr; -- -+ - logdbg(stderr,"enter log_thread_start\n"); - - logq_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); - logev_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); - logev_cond = (pthread_cond_t *) malloc(sizeof(pthread_cond_t)); -- -+ - pthread_mutex_init(logq_lock, NULL); - pthread_mutex_init(logev_lock, NULL); - pthread_cond_init(logev_cond, NULL); -- -+ - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 64 * 1024); - -@@ -90,5 +90,11 @@ - pthread_mutex_destroy(logev_lock); - pthread_cond_destroy(logev_cond); - -+ free(logq_lock); -+ logq_lock = NULL; -+ free(logev_lock); -+ logev_lock = NULL; -+ free(logev_cond); -+ logev_cond = NULL; - free_logarea(); --} -+} ---- multipath-tools-0.4.8/libmultipath/parser.c -+++ multipath-tools-0.4.8/libmultipath/parser.c -@@ -1,11 +1,11 @@ --/* -+/* - * Part: Configuration file parser/reader. Place into the dynamic - * data structure representation the conf file -- * -+ * - * Version: $Id: parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $ -- * -+ * - * Author: Alexandre Cassen, -- * -+ * - * 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. -@@ -43,7 +43,7 @@ - - if (!keyword) - return 1; -- -+ - if (!vector_alloc_slot(keywords)) { - FREE(keyword); - return 1; -@@ -450,7 +450,7 @@ - break; - } - } -- -+ - free_strvec(strvec); - } - -@@ -458,16 +458,23 @@ - return r; - } - -+int alloc_keywords(void) -+{ -+ if (!keywords) -+ keywords = vector_alloc(); -+ -+ if (!keywords) -+ return 1; -+ -+ return 0; -+} -+ - /* Data initialization */ - int - init_data(char *conf_file, void (*init_keywords) (void)) - { - int r; - -- if (!keywords) -- keywords = vector_alloc(); -- if (!keywords) -- return 1; - stream = fopen(conf_file, "r"); - if (!stream) { - syslog(LOG_WARNING, "Configuration file open problem"); ---- multipath-tools-0.4.8/libmultipath/parser.h -+++ multipath-tools-0.4.8/libmultipath/parser.h -@@ -74,6 +74,7 @@ - extern int alloc_value_block(vector strvec, void (*alloc_func) (vector)); - extern void *set_value(vector strvec); - extern int process_stream(vector keywords); -+extern int alloc_keywords(void); - 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); ---- multipath-tools-0.4.8/libmultipath/pgpolicies.c -+++ multipath-tools-0.4.8/libmultipath/pgpolicies.c -@@ -67,7 +67,7 @@ - struct path * pp; - struct pathgroup * pgp; - struct path * pp2; -- -+ - if (!mp->pg) - mp->pg = vector_alloc(); - -@@ -103,12 +103,12 @@ - bitmap[i] = 1; - - for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) { -- -+ - if (bitmap[j]) - continue; - - pp2 = VECTOR_SLOT(mp->paths, j); -- -+ - if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name, - NODE_NAME_SIZE)) { - if (store_path(pgp->paths, pp2)) -@@ -140,7 +140,7 @@ - struct path * pp; - struct pathgroup * pgp; - struct path * pp2; -- -+ - if (!mp->pg) - mp->pg = vector_alloc(); - -@@ -172,16 +172,16 @@ - /* feed the first path */ - if (store_path(pgp->paths, pp)) - goto out1; -- -+ - bitmap[i] = 1; - - for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) { -- -+ - if (bitmap[j]) - continue; - - pp2 = VECTOR_SLOT(mp->paths, j); -- -+ - if (0 == strcmp(pp->serial, pp2->serial)) { - if (store_path(pgp->paths, pp2)) - goto out1; -@@ -211,7 +211,7 @@ - - if (!mp->pg) - mp->pg = vector_alloc(); -- -+ - if (!mp->pg) - return 1; - -@@ -224,7 +224,7 @@ - - if (store_pathgroup(mp->pg, pgp)) - goto out; -- -+ - if (store_path(pgp->paths, pp)) - goto out; - } -@@ -252,10 +252,10 @@ - return 1; - - pgp = alloc_pathgroup(); -- -+ - if (!pgp) - goto out; -- -+ - vector_free(pgp->paths); - pgp->paths = mp->paths; - mp->paths = NULL; -@@ -306,7 +306,7 @@ - - if (!pgp) - goto out; -- -+ - if (store_path(pgp->paths, VECTOR_SLOT(mp->paths, 0))) - goto out; - ---- multipath-tools-0.4.8/libmultipath/print.c -+++ multipath-tools-0.4.8/libmultipath/print.c -@@ -29,7 +29,7 @@ - #define PAD(x) while ((int)(c - s) < (x) && (c < (line + len - 1))) \ - *c++ = ' '; s = c - #define PRINT(var, size, format, args...) \ -- fwd = snprintf(var, size, format, ##args); \ -+ fwd = snprintf(var, size, format, ##args); \ - c += (fwd >= size) ? size : fwd; - - /* -@@ -60,7 +60,7 @@ - char fmt[6] = {}; - char units[] = {'K','M','G','T','P'}; - char *u = units; -- -+ - while (s >= 1024 && *u != 'P') { - s = s / 1024; - u++; -@@ -112,7 +112,7 @@ - int j = PROGRESS_LEN - i; - char * c = buff; - char * end = buff + len; -- -+ - while (i-- > 0) { - c += snprintf(c, len, "X"); - if ((len = (end - c)) <= 1) goto out; -@@ -129,7 +129,7 @@ - buff[c - buff + 1] = '\0'; - return (c - buff + 1); - } -- -+ - static int - snprint_failback (char * buff, size_t len, struct multipath * mpp) - { -@@ -239,7 +239,7 @@ - if (!pp) - return 0; - return snprintf(buff, len, "%s,%s", -- pp->vendor_id, pp->product_id); -+ pp->vendor_id, pp->product_id); - } - - static int -@@ -335,7 +335,7 @@ - snprint_vpr (char * buff, size_t len, struct path * pp) - { - return snprintf(buff, len, "%s,%s", -- pp->vendor_id, pp->product_id); -+ pp->vendor_id, pp->product_id); - } - - static int -@@ -530,10 +530,10 @@ - continue; - } - f++; -- -+ - if (!(data = mpd_lookup(*f))) - break; /* unknown wildcard */ -- -+ - PRINT(c, TAIL, data->header); - PAD(data->width); - } while (*f++); -@@ -565,10 +565,10 @@ - continue; - } - f++; -- -+ - if (!(data = mpd_lookup(*f))) - break; -- -+ - data->snprint(buff, MAX_FIELD_LEN, mpp); - PRINT(c, TAIL, buff); - PAD(data->width); -@@ -600,10 +600,10 @@ - continue; - } - f++; -- -+ - if (!(data = pd_lookup(*f))) - break; /* unknown wildcard */ -- -+ - PRINT(c, TAIL, data->header); - PAD(data->width); - } while (*f++); -@@ -635,10 +635,10 @@ - continue; - } - f++; -- -+ - if (!(data = pd_lookup(*f))) - break; -- -+ - data->snprint(buff, MAX_FIELD_LEN, pp); - PRINT(c, TAIL, buff); - PAD(data->width); -@@ -671,10 +671,10 @@ - continue; - } - f++; -- -+ - if (!(data = pgd_lookup(*f))) - break; -- -+ - data->snprint(buff, MAX_FIELD_LEN, pgp); - PRINT(c, TAIL, buff); - PAD(data->width); -@@ -718,7 +718,7 @@ - c += sprintf(c, "%%A: "); - - c += sprintf(c, "%%n"); -- -+ - if (strncmp(mpp->alias, mpp->wwid, WWID_SIZE)) - c += sprintf(c, " (%%w)"); - -@@ -890,7 +890,6 @@ - if (fwd > len) - return len; - return fwd; -- - } - - static int -@@ -956,7 +955,7 @@ - if ((len - fwd - threshold) <= 0) - return len; - fwd += snprintf(buff + fwd, len - fwd, "device node rules:\n" -- "- blacklist:\n"); -+ "- blacklist:\n"); - if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_devnode)) - return len; - -@@ -969,7 +968,7 @@ - if ((len - fwd - threshold) <= 0) - return len; - fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n" -- "- blacklist:\n"); -+ "- blacklist:\n"); - if (snprint_blacklist_group(buff, len, &fwd, &conf->blist_wwid) == 0) - return len; - -@@ -982,7 +981,7 @@ - if ((len - fwd - threshold) <= 0) - return len; - fwd += snprintf(buff + fwd, len - fwd, "device rules:\n" -- "- blacklist:\n"); -+ "- blacklist:\n"); - if (snprint_blacklist_devgroup(buff, len, &fwd, &conf->blist_device) == 0) - return len; - -@@ -1258,7 +1257,7 @@ - fprintf(stdout, "===== no paths =====\n"); - return; - } -- -+ - if (banner) - fprintf(stdout, "===== paths list =====\n"); - ---- multipath-tools-0.4.8/libmultipath/prio.h -+++ multipath-tools-0.4.8/libmultipath/prio.h -@@ -21,6 +21,7 @@ - #define PRIO_HDS "hds" - #define PRIO_HP_SW "hp_sw" - #define PRIO_NETAPP "netapp" -+#define PRIO_ONTAP "ontap" - #define PRIO_RANDOM "random" - #define PRIO_RDAC "rdac" - ---- multipath-tools-0.4.8/libmultipath/prioritizers/Makefile -+++ multipath-tools-0.4.8/libmultipath/prioritizers/Makefile -@@ -11,7 +11,7 @@ - libprioemc.so \ - libpriordac.so \ - libprioalua.so \ -- libprionetapp.so \ -+ libprioontap.so \ - libpriohds.so - - CFLAGS += -I.. ---- multipath-tools-0.4.8/libmultipath/prioritizers/alua.c -+++ multipath-tools-0.4.8/libmultipath/prioritizers/alua.c -@@ -23,6 +23,7 @@ - #define ALUA_PRIO_RTPG_FAILED 2 - #define ALUA_PRIO_GETAAS_FAILED 3 - #define ALUA_PRIO_TPGS_FAILED 4 -+#define ALUA_PRIO_NO_INFORMATION 5 - - int - get_alua_info(int fd) -@@ -54,13 +55,18 @@ - return -ALUA_PRIO_GETAAS_FAILED; - - condlog(3, "aas = [%s]", -- (aas_string[rc]) ? aas_string[rc] : "invalid/reserved"); -+ (rc < 4) ? aas_string[rc] : "invalid/reserved"); - return rc; - } - - int getprio (struct path * pp) - { -- int rc = get_alua_info(pp->fd); -+ int rc; -+ -+ if (pp->fd < 0) -+ return -ALUA_PRIO_NO_INFORMATION; -+ -+ rc = get_alua_info(pp->fd); - if (rc >= 0) { - switch(rc) { - case AAS_OPTIMIZED: ---- multipath-tools-0.4.8/libmultipath/prioritizers/alua_rtpg.c -+++ multipath-tools-0.4.8/libmultipath/prioritizers/alua_rtpg.c -@@ -74,7 +74,7 @@ - scsi_error(struct sg_io_hdr *hdr) - { - /* Treat SG_ERR here to get rid of sg_err.[ch] */ -- hdr->status &= 0x7e; -+ hdr->status &= 0x7e; - - if ( - (hdr->status == 0) && -@@ -125,18 +125,18 @@ - set_uint16(cmd.length, resplen); - PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); - -- memset(&hdr, 0, sizeof(hdr)); -- hdr.interface_id = 'S'; -- hdr.cmdp = (unsigned char *) &cmd; -- hdr.cmd_len = sizeof(cmd); -- hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- hdr.dxferp = resp; -- hdr.dxfer_len = resplen; -- hdr.sbp = sense; -- hdr.mx_sb_len = sizeof(sense); -- hdr.timeout = DEF_TIMEOUT; -- -- if (ioctl(fd, SG_IO, &hdr) < 0) { -+ memset(&hdr, 0, sizeof(hdr)); -+ hdr.interface_id = 'S'; -+ hdr.cmdp = (unsigned char *) &cmd; -+ hdr.cmd_len = sizeof(cmd); -+ hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ hdr.dxferp = resp; -+ hdr.dxfer_len = resplen; -+ hdr.sbp = sense; -+ hdr.mx_sb_len = sizeof(sense); -+ hdr.timeout = DEF_TIMEOUT; -+ -+ if (ioctl(fd, SG_IO, &hdr) < 0) { - PRINT_DEBUG("do_inquiry: IOCTL failed!\n"); - return -RTPG_INQUIRY_FAILED; - } -@@ -146,8 +146,8 @@ - return -RTPG_INQUIRY_FAILED; - } - PRINT_HEX((unsigned char *) resp, resplen); -- -- return 0; -+ -+ return 0; - } - - /* -@@ -160,6 +160,7 @@ - struct inquiry_data inq; - int rc; - -+ memset((unsigned char *)&inq, 0, sizeof(inq)); - rc = do_inquiry(fd, 0, 0x00, &inq, sizeof(inq)); - if (!rc) { - rc = inquiry_data_get_tpgs(&inq); -@@ -176,6 +177,7 @@ - struct vpd83_dscr * dscr; - int rc; - -+ memset(buf, 0, sizeof(buf)); - rc = do_inquiry(fd, 1, 0x83, buf, sizeof(buf)); - if (!rc) { - vpd83 = (struct vpd83_data *) buf; -@@ -221,19 +223,19 @@ - set_uint32(cmd.length, resplen); - PRINT_HEX((unsigned char *) &cmd, sizeof(cmd)); - -- memset(&hdr, 0, sizeof(hdr)); -+ memset(&hdr, 0, sizeof(hdr)); - hdr.interface_id = 'S'; -- hdr.cmdp = (unsigned char *) &cmd; -- hdr.cmd_len = sizeof(cmd); -- hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- hdr.dxferp = resp; -- hdr.dxfer_len = resplen; -- hdr.mx_sb_len = sizeof(sense); -- hdr.sbp = sense; -- hdr.timeout = DEF_TIMEOUT; -- -+ hdr.cmdp = (unsigned char *) &cmd; -+ hdr.cmd_len = sizeof(cmd); -+ hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ hdr.dxferp = resp; -+ hdr.dxfer_len = resplen; -+ hdr.mx_sb_len = sizeof(sense); -+ hdr.sbp = sense; -+ hdr.timeout = DEF_TIMEOUT; -+ - if (ioctl(fd, SG_IO, &hdr) < 0) -- return -RTPG_RTPG_FAILED; -+ return -RTPG_RTPG_FAILED; - - if (scsi_error(&hdr)) { - PRINT_DEBUG("do_rtpg: SCSI error!\n"); -@@ -241,8 +243,8 @@ - } - PRINT_HEX(resp, resplen); - -- return 0; --} -+ return 0; -+} - - int - get_asymmetric_access_state(int fd, unsigned int tpg) -@@ -261,6 +263,7 @@ - "%u bytes\n", buflen); - return -RTPG_RTPG_FAILED; - } -+ memset(buf, 0, buflen); - rc = do_rtpg(fd, buf, buflen); - if (rc < 0) - return rc; -@@ -274,11 +277,11 @@ - return -RTPG_RTPG_FAILED; - } - buflen = scsi_buflen; -+ memset(buf, 0, buflen); - rc = do_rtpg(fd, buf, buflen); - if (rc < 0) - goto out; - } -- - - tpgd = (struct rtpg_data *) buf; - rc = -RTPG_TPG_NOT_FOUND; -@@ -289,7 +292,7 @@ - "more than one entry with same port " - "group.\n"); - } else { -- PRINT_DEBUG("pref=%i\n", dscr->pref); -+ PRINT_DEBUG("pref=%i\n", dscr->b0); - rc = rtpg_tpg_dscr_get_aas(dscr); - } - } ---- multipath-tools-0.4.8/libmultipath/prioritizers/hds.c -+++ multipath-tools-0.4.8/libmultipath/prioritizers/hds.c -@@ -86,7 +86,7 @@ - int hds_modular_prio (const char *dev, int fd) - { - int k; -- char vendor[8]; -+ char vendor[9]; - char product[32]; - char serial[32]; - char ldev[32]; ---- multipath-tools-0.4.8/libmultipath/prioritizers/netapp.c -+++ multipath-tools-0.4.8/libmultipath/prioritizers/netapp.c -@@ -1,243 +0,0 @@ --/* -- * Copyright 2005 Network Appliance, Inc., All Rights Reserved -- * Author: David Wysochanski available at davidw@netapp.com -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * 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 v2 for more details. -- */ -- --#include --#include --#include --#include --#include --#include -- --#include --#include --#include -- --#define INQUIRY_CMD 0x12 --#define INQUIRY_CMDLEN 6 --#define DEFAULT_PRIOVAL 10 --#define RESULTS_MAX 256 --#define SG_TIMEOUT 30000 -- --#define pp_netapp_log(prio, fmt, args...) \ -- condlog(prio, "%s: netapp prio: " fmt, dev, ##args) -- --static void dump_cdb(unsigned char *cdb, int size) --{ -- int i; -- char buf[10*5+1]; -- char * p = &buf[0]; -- -- condlog(0, "- SCSI CDB: "); -- for (i=0; imasked_status, -- io_hdr->host_status, io_hdr->driver_status); -- if (io_hdr->sb_len_wr > 0) { -- condlog(0, "- SCSI sense data: "); -- for (i=0; isb_len_wr; i++) { -- p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ", -- io_hdr->sbp[i]); -- } -- condlog(0, "%s", buf); -- } --} -- --/* -- * Returns: -- * -1: error, errno set -- * 0: success -- */ --static int send_gva(const char *dev, int fd, unsigned char pg, -- unsigned char *results, int *results_size) --{ -- unsigned char sb[128]; -- unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa, -- pg, sizeof(sb), 0, 0}; -- struct sg_io_hdr io_hdr; -- int ret = -1; -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (cdb); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = *results_size; -- io_hdr.dxferp = results; -- io_hdr.cmdp = cdb; -- io_hdr.sbp = sb; -- io_hdr.timeout = SG_TIMEOUT; -- io_hdr.pack_id = 0; -- if (ioctl(fd, SG_IO, &io_hdr) < 0) { -- pp_netapp_log(0, "SG_IO ioctl failed, errno=%d", errno); -- dump_cdb(cdb, sizeof(cdb)); -- goto out; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- pp_netapp_log(0, "SCSI error"); -- dump_cdb(cdb, sizeof(cdb)); -- process_sg_error(&io_hdr); -- goto out; -- } -- -- if (results[4] != 0x0a || results[5] != 0x98 || -- results[6] != 0x0a ||results[7] != 0x01) { -- dump_cdb(cdb, sizeof(cdb)); -- pp_netapp_log(0, "GVA return wrong format "); -- pp_netapp_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x", -- results[4], results[5], results[6], results[7]); -- goto out; -- } -- ret = 0; -- out: -- return(ret); --} -- --/* -- * Retuns: -- * -1: Unable to obtain proxy info -- * 0: Device _not_ proxy path -- * 1: Device _is_ proxy path -- */ --static int get_proxy(const char *dev, int fd) --{ -- unsigned char results[256]; -- unsigned char sb[128]; -- unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0, -- sizeof(sb), 0}; -- struct sg_io_hdr io_hdr; -- int ret = -1; -- -- memset(&results, 0, sizeof (results)); -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (cdb); -- io_hdr.mx_sb_len = sizeof (sb); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = sizeof (results); -- io_hdr.dxferp = results; -- io_hdr.cmdp = cdb; -- io_hdr.sbp = sb; -- io_hdr.timeout = SG_TIMEOUT; -- io_hdr.pack_id = 0; -- if (ioctl(fd, SG_IO, &io_hdr) < 0) { -- pp_netapp_log(0, "ioctl sending inquiry command failed, " -- "errno=%d", errno); -- dump_cdb(cdb, sizeof(cdb)); -- goto out; -- } -- if (io_hdr.info & SG_INFO_OK_MASK) { -- pp_netapp_log(0, "SCSI error"); -- dump_cdb(cdb, sizeof(cdb)); -- process_sg_error(&io_hdr); -- goto out; -- } -- -- if (results[1] != 0xc1 || results[8] != 0x0a || -- results[9] != 0x98 || results[10] != 0x0a || -- results[11] != 0x0 || results[12] != 0xc1 || -- results[13] != 0x0) { -- pp_netapp_log(0,"proxy info page in unknown format - "); -- pp_netapp_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x " -- "0x%02x 0x%02x", -- results[8], results[9], results[10], -- results[11], results[12], results[13]); -- dump_cdb(cdb, sizeof(cdb)); -- goto out; -- } -- ret = (results[19] & 0x02) >> 1; -- -- out: -- return(ret); --} -- --/* -- * Returns priority of device based on device info. -- * -- * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol -- * 3: iSCSI HBA -- * 2: iSCSI software -- * 1: FCP proxy -- */ --static int netapp_prio(const char *dev, int fd) --{ -- unsigned char results[RESULTS_MAX]; -- int results_size=RESULTS_MAX; -- int rc; -- int is_proxy; -- int is_iscsi_software; -- int is_iscsi_hardware; -- int tot_len; -- -- is_iscsi_software = is_iscsi_hardware = is_proxy = 0; -- -- memset(&results, 0, sizeof (results)); -- rc = send_gva(dev, fd, 0x41, results, &results_size); -- if (rc == 0) { -- tot_len = results[0] << 24 | results[1] << 16 | -- results[2] << 8 | results[3]; -- if (tot_len <= 8) { -- goto try_fcp_proxy; -- } -- if (results[8] != 0x41) { -- pp_netapp_log(0, "GVA page 0x41 error - " -- "results[8] = 0x%x", results[8]); -- goto try_fcp_proxy; -- } -- if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) || -- (strncmp((char *)&results[12], "iswt", 4) == 0)) { -- is_iscsi_software = 1; -- goto prio_select; -- } -- else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) { -- is_iscsi_hardware = 1; -- goto prio_select; -- } -- } -- -- try_fcp_proxy: -- rc = get_proxy(dev, fd); -- if (rc >= 0) { -- is_proxy = rc; -- } -- -- prio_select: -- if (is_iscsi_hardware) { -- return 3; -- } else if (is_iscsi_software) { -- return 2; -- } else { -- if (is_proxy) { -- return 1; -- } else { -- /* Either non-proxy, or couldn't get proxy info */ -- return 4; -- } -- } --} -- --int getprio (struct path * pp) --{ -- return netapp_prio(pp->dev, pp->fd); --} ---- multipath-tools-0.4.8/libmultipath/prioritizers/netapp.h -+++ multipath-tools-0.4.8/libmultipath/prioritizers/netapp.h -@@ -1,7 +0,0 @@ --#ifndef _NETAPP_H --#define _NETAPP_H -- --#define PRIO_NETAPP "netapp" --int prio_netapp(struct path * pp); -- --#endif ---- multipath-tools-0.4.8/libmultipath/prioritizers/ontap.c -+++ multipath-tools-0.4.8/libmultipath/prioritizers/ontap.c -@@ -0,0 +1,243 @@ -+/* -+ * Copyright 2005 Network Appliance, Inc., All Rights Reserved -+ * Author: David Wysochanski available at davidw@netapp.com -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * 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 v2 for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define INQUIRY_CMD 0x12 -+#define INQUIRY_CMDLEN 6 -+#define DEFAULT_PRIOVAL 10 -+#define RESULTS_MAX 256 -+#define SG_TIMEOUT 30000 -+ -+#define pp_ontap_log(prio, fmt, args...) \ -+ condlog(prio, "%s: ontap prio: " fmt, dev, ##args) -+ -+static void dump_cdb(unsigned char *cdb, int size) -+{ -+ int i; -+ char buf[10*5+1]; -+ char * p = &buf[0]; -+ -+ condlog(0, "- SCSI CDB: "); -+ for (i=0; imasked_status, -+ io_hdr->host_status, io_hdr->driver_status); -+ if (io_hdr->sb_len_wr > 0) { -+ condlog(0, "- SCSI sense data: "); -+ for (i=0; isb_len_wr; i++) { -+ p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ", -+ io_hdr->sbp[i]); -+ } -+ condlog(0, "%s", buf); -+ } -+} -+ -+/* -+ * Returns: -+ * -1: error, errno set -+ * 0: success -+ */ -+static int send_gva(const char *dev, int fd, unsigned char pg, -+ unsigned char *results, int *results_size) -+{ -+ unsigned char sb[128]; -+ unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa, -+ pg, sizeof(sb), 0, 0}; -+ struct sg_io_hdr io_hdr; -+ int ret = -1; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (cdb); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = *results_size; -+ io_hdr.dxferp = results; -+ io_hdr.cmdp = cdb; -+ io_hdr.sbp = sb; -+ io_hdr.timeout = SG_TIMEOUT; -+ io_hdr.pack_id = 0; -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) { -+ pp_ontap_log(0, "SG_IO ioctl failed, errno=%d", errno); -+ dump_cdb(cdb, sizeof(cdb)); -+ goto out; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ pp_ontap_log(0, "SCSI error"); -+ dump_cdb(cdb, sizeof(cdb)); -+ process_sg_error(&io_hdr); -+ goto out; -+ } -+ -+ if (results[4] != 0x0a || results[5] != 0x98 || -+ results[6] != 0x0a ||results[7] != 0x01) { -+ dump_cdb(cdb, sizeof(cdb)); -+ pp_ontap_log(0, "GVA return wrong format "); -+ pp_ontap_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x", -+ results[4], results[5], results[6], results[7]); -+ goto out; -+ } -+ ret = 0; -+ out: -+ return(ret); -+} -+ -+/* -+ * Retuns: -+ * -1: Unable to obtain proxy info -+ * 0: Device _not_ proxy path -+ * 1: Device _is_ proxy path -+ */ -+static int get_proxy(const char *dev, int fd) -+{ -+ unsigned char results[256]; -+ unsigned char sb[128]; -+ unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0, -+ sizeof(sb), 0}; -+ struct sg_io_hdr io_hdr; -+ int ret = -1; -+ -+ memset(&results, 0, sizeof (results)); -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (cdb); -+ io_hdr.mx_sb_len = sizeof (sb); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = sizeof (results); -+ io_hdr.dxferp = results; -+ io_hdr.cmdp = cdb; -+ io_hdr.sbp = sb; -+ io_hdr.timeout = SG_TIMEOUT; -+ io_hdr.pack_id = 0; -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) { -+ pp_ontap_log(0, "ioctl sending inquiry command failed, " -+ "errno=%d", errno); -+ dump_cdb(cdb, sizeof(cdb)); -+ goto out; -+ } -+ if (io_hdr.info & SG_INFO_OK_MASK) { -+ pp_ontap_log(0, "SCSI error"); -+ dump_cdb(cdb, sizeof(cdb)); -+ process_sg_error(&io_hdr); -+ goto out; -+ } -+ -+ if (results[1] != 0xc1 || results[8] != 0x0a || -+ results[9] != 0x98 || results[10] != 0x0a || -+ results[11] != 0x0 || results[12] != 0xc1 || -+ results[13] != 0x0) { -+ pp_ontap_log(0,"proxy info page in unknown format - "); -+ pp_ontap_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x " -+ "0x%02x 0x%02x", -+ results[8], results[9], results[10], -+ results[11], results[12], results[13]); -+ dump_cdb(cdb, sizeof(cdb)); -+ goto out; -+ } -+ ret = (results[19] & 0x02) >> 1; -+ -+ out: -+ return(ret); -+} -+ -+/* -+ * Returns priority of device based on device info. -+ * -+ * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol -+ * 3: iSCSI HBA -+ * 2: iSCSI software -+ * 1: FCP proxy -+ */ -+static int ontap_prio(const char *dev, int fd) -+{ -+ unsigned char results[RESULTS_MAX]; -+ int results_size=RESULTS_MAX; -+ int rc; -+ int is_proxy; -+ int is_iscsi_software; -+ int is_iscsi_hardware; -+ int tot_len; -+ -+ is_iscsi_software = is_iscsi_hardware = is_proxy = 0; -+ -+ memset(&results, 0, sizeof (results)); -+ rc = send_gva(dev, fd, 0x41, results, &results_size); -+ if (rc == 0) { -+ tot_len = results[0] << 24 | results[1] << 16 | -+ results[2] << 8 | results[3]; -+ if (tot_len <= 8) { -+ goto try_fcp_proxy; -+ } -+ if (results[8] != 0x41) { -+ pp_ontap_log(0, "GVA page 0x41 error - " -+ "results[8] = 0x%x", results[8]); -+ goto try_fcp_proxy; -+ } -+ if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) || -+ (strncmp((char *)&results[12], "iswt", 4) == 0)) { -+ is_iscsi_software = 1; -+ goto prio_select; -+ } -+ else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) { -+ is_iscsi_hardware = 1; -+ goto prio_select; -+ } -+ } -+ -+ try_fcp_proxy: -+ rc = get_proxy(dev, fd); -+ if (rc >= 0) { -+ is_proxy = rc; -+ } -+ -+ prio_select: -+ if (is_iscsi_hardware) { -+ return 3; -+ } else if (is_iscsi_software) { -+ return 2; -+ } else { -+ if (is_proxy) { -+ return 1; -+ } else { -+ /* Either non-proxy, or couldn't get proxy info */ -+ return 4; -+ } -+ } -+} -+ -+int getprio (struct path * pp) -+{ -+ return ontap_prio(pp->dev, pp->fd); -+} ---- multipath-tools-0.4.8/libmultipath/prioritizers/ontap.h -+++ multipath-tools-0.4.8/libmultipath/prioritizers/ontap.h -@@ -0,0 +1,7 @@ -+#ifndef _ONTAP_H -+#define _ONTAP_H -+ -+#define PRIO_ONTAP "ontap" -+int prio_ontap(struct path * pp); -+ -+#endif ---- multipath-tools-0.4.8/libmultipath/prioritizers/rdac.c -+++ multipath-tools-0.4.8/libmultipath/prioritizers/rdac.c -@@ -39,9 +39,9 @@ - pp_rdac_log(0, "inquiry command indicates error"); - goto out; - } -- -+ - if (/* Verify the code page - right page & page identifier */ -- sense_buffer[1] != 0xc9 || -+ sense_buffer[1] != 0xc9 || - sense_buffer[3] != 0x2c || - sense_buffer[4] != 'v' || - sense_buffer[5] != 'a' || -@@ -49,24 +49,24 @@ - pp_rdac_log(0, "volume access control page in unknown format"); - goto out; - } -- -+ - if ( /* Current Volume Path Bit */ - ( sense_buffer[8] & 0x01) == 0x01 ) { -- /* -+ /* - * This volume was owned by the controller receiving - * the inquiry command. - */ -- ret |= 0x01; -+ ret |= 0x02; - } - - /* Volume Preferred Path Priority */ - switch ( sense_buffer[9] & 0x0F ) { - case 0x01: -- /* -+ /* - * Access to this volume is most preferred through - * this path and other paths with this value. - */ -- ret |= 0x02; -+ ret |= 0x04; - break; - case 0x02: - /* -@@ -74,12 +74,13 @@ - * as a secondary path. Typically this path would be used - * for fail-over situations. - */ -- /* Fallthrough */ -+ ret |= 0x01; -+ break; - default: - /* Reserved values */ - break; - } -- -+ - out: - return(ret); - } ---- multipath-tools-0.4.8/libmultipath/regex.c -+++ multipath-tools-0.4.8/libmultipath/regex.c -@@ -116,7 +116,7 @@ - /* True if `size1' is non-NULL and PTR is pointing anywhere inside - `string1' or just past its end. This works if PTR is NULL, which is - a good thing. */ --#define FIRST_STRING_P(ptr) \ -+#define FIRST_STRING_P(ptr) \ - (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) - - /* (Re)Allocate N items of type T using malloc, or fail. */ -@@ -188,7 +188,7 @@ - #define EXTRACT_NUMBER_AND_INCR(destination, source) \ - do { \ - EXTRACT_NUMBER (destination, source); \ -- (source) += 2; \ -+ (source) += 2; \ - } while (0) - - #undef assert -@@ -267,14 +267,14 @@ - #define PATFETCH(c) \ - do {if (p == pend) return REG_EEND; \ - c = (unsigned char) *p++; \ -- if (translate) c = translate[c]; \ -+ if (translate) c = translate[c]; \ - } while (0) - - /* Fetch the next character in the uncompiled pattern, with no - translation. */ - #define PATFETCH_RAW(c) \ - do {if (p == pend) return REG_EEND; \ -- c = (unsigned char) *p++; \ -+ c = (unsigned char) *p++; \ - } while (0) - - /* Go backwards one character in the pattern. */ -@@ -354,27 +354,27 @@ - correct places in the new one. If extending the buffer results in it - being larger than MAX_BUF_SIZE, then flag memory exhausted. */ - #define EXTEND_BUFFER() \ -- do { \ -+ do { \ - unsigned char *old_buffer = bufp->buffer; \ -- if (bufp->allocated == MAX_BUF_SIZE) \ -+ if (bufp->allocated == MAX_BUF_SIZE) \ - return REG_ESIZE; \ - bufp->allocated <<= 1; \ - if (bufp->allocated > MAX_BUF_SIZE) \ -- bufp->allocated = MAX_BUF_SIZE; \ -+ bufp->allocated = MAX_BUF_SIZE; \ - bufp->buffer = (unsigned char *) REALLOC(bufp->buffer, bufp->allocated);\ - if (bufp->buffer == NULL) \ - return REG_ESPACE; \ - /* If the buffer moved, move all the pointers into it. */ \ - if (old_buffer != bufp->buffer) \ - { \ -- b = (b - old_buffer) + bufp->buffer; \ -- begalt = (begalt - old_buffer) + bufp->buffer; \ -- if (fixup_alt_jump) \ -- fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ -- if (laststart) \ -- laststart = (laststart - old_buffer) + bufp->buffer; \ -- if (pending_exact) \ -- pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ -+ b = (b - old_buffer) + bufp->buffer; \ -+ begalt = (begalt - old_buffer) + bufp->buffer; \ -+ if (fixup_alt_jump) \ -+ fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ -+ if (laststart) \ -+ laststart = (laststart - old_buffer) + bufp->buffer; \ -+ if (pending_exact) \ -+ pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ - } \ - } while (0) - -@@ -428,20 +428,20 @@ - - - /* Get the next unsigned number in the uncompiled pattern. */ --#define GET_UNSIGNED_NUMBER(num) \ -+#define GET_UNSIGNED_NUMBER(num) \ - { if (p != pend) \ - { \ -- PATFETCH (c); \ -- while (ISDIGIT (c)) \ -- { \ -- if (num < 0) \ -- num = 0; \ -- num = num * 10 + c - '0'; \ -- if (p == pend) \ -- break; \ -- PATFETCH (c); \ -- } \ -- } \ -+ PATFETCH (c); \ -+ while (ISDIGIT (c)) \ -+ { \ -+ if (num < 0) \ -+ num = 0; \ -+ num = num * 10 + c - '0'; \ -+ if (p == pend) \ -+ break; \ -+ PATFETCH (c); \ -+ } \ -+ } \ - } - - #define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ -@@ -1524,14 +1524,14 @@ - ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ - ? 0 \ - : ((fail_stack).stack = (fail_stack_elt_t *) \ -- REGEX_REALLOCATE ((fail_stack).stack, \ -- (fail_stack).size * sizeof (fail_stack_elt_t), \ -- ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ -+ REGEX_REALLOCATE ((fail_stack).stack, \ -+ (fail_stack).size * sizeof (fail_stack_elt_t), \ -+ ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ - \ - (fail_stack).stack == NULL \ - ? 0 \ -- : ((fail_stack).size <<= 1, \ -- 1))) -+ : ((fail_stack).size <<= 1, \ -+ 1))) - - - /* Push PATTERN_OP on FAIL_STACK. -@@ -1577,7 +1577,7 @@ - is wide enough to hold a value of something to which pointer can \ - be assigned */ \ - s_reg_t this_reg; \ -- \ -+ \ - DEBUG_STATEMENT (failure_id++); \ - DEBUG_STATEMENT (nfailure_points_pushed++); \ - DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ -@@ -1663,7 +1663,7 @@ - - /* We actually push this many items. */ - #define NUM_FAILURE_ITEMS \ -- ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ -+ ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ - + NUM_NONREG_ITEMS) - - /* How many items can still be added to the stack without overflowing it. */ -@@ -2255,13 +2255,13 @@ - /* Call before fetching a character with *d. This switches over to - string2 if necessary. */ - #define PREFETCH() \ -- while (d == dend) \ -+ while (d == dend) \ - { \ - /* End of string2 => fail. */ \ -- if (dend == end_match_2) \ -- goto fail; \ -- /* End of string1 => advance to string2. */ \ -- d = string2; \ -+ if (dend == end_match_2) \ -+ goto fail; \ -+ /* End of string1 => advance to string2. */ \ -+ d = string2; \ - dend = end_match_2; \ - } - -@@ -2278,7 +2278,7 @@ - string2, look at the last character in string1. */ - #define WORDCHAR_P(d) \ - (SYNTAX ((d) == end1 ? *string2 \ -- : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ -+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ - == Sword) - - /* Test if the character before D and the one at D differ with respect ---- multipath-tools-0.4.8/libmultipath/structs.c -+++ multipath-tools-0.4.8/libmultipath/structs.c -@@ -22,7 +22,7 @@ - alloc_path (void) - { - struct path * pp; -- -+ - pp = (struct path *)MALLOC(sizeof(struct path)); - - if (pp) { -@@ -243,7 +243,7 @@ - { - int i; - struct multipath * mpp; -- -+ - if (!mpvec) - return NULL; - -@@ -262,7 +262,7 @@ - { - int i; - struct multipath * mpp; -- -+ - if (!mpvec) - return NULL; - -@@ -279,7 +279,7 @@ - int i; - int len; - struct multipath * mpp; -- -+ - if (!mpvec) - return NULL; - -@@ -287,7 +287,7 @@ - - if (!len) - return NULL; -- -+ - vector_foreach_slot (mpvec, mpp, i) { - if (strlen(mpp->alias) == len && - !strncmp(mpp->alias, alias, len)) -@@ -315,7 +315,7 @@ - - if (!pathvec) - return NULL; -- -+ - vector_foreach_slot (pathvec, pp, i) - if (!strcmp_chomp(pp->dev, dev)) - return pp; ---- multipath-tools-0.4.8/libmultipath/structs_vec.c -+++ multipath-tools-0.4.8/libmultipath/structs_vec.c -@@ -280,13 +280,13 @@ - retry: - if (dm_get_info(mpp->alias, &mpp->dmi)) { - /* Error accessing table */ -- condlog(3, "%s: cannot access table", mpp->alias); -+ condlog(3, "%s: cannot access table", mpp->alias); - goto out; - } - - if (!dm_map_present(mpp->alias)) { - /* Table has been removed */ -- condlog(3, "%s: table does not exist", mpp->alias); -+ condlog(3, "%s: table does not exist", mpp->alias); - goto out; - } - ---- multipath-tools-0.4.8/libmultipath/switchgroup.c -+++ multipath-tools-0.4.8/libmultipath/switchgroup.c -@@ -35,7 +35,7 @@ - - if (!mpp->pg) - return 1; -- -+ - vector_foreach_slot (mpp->pg, pgp, i) { - if (!pgp->paths) - continue; ---- multipath-tools-0.4.8/libmultipath/uevent.c -+++ multipath-tools-0.4.8/libmultipath/uevent.c -@@ -157,7 +157,7 @@ - } - - /* enable receiving of the sender credentials */ -- setsockopt(sock, SOL_SOCKET, SO_PASSCRED, -+ setsockopt(sock, SOL_SOCKET, SO_PASSCRED, - &feature_on, sizeof(feature_on)); - - } else { ---- multipath-tools-0.4.8/libmultipath/util.c -+++ multipath-tools-0.4.8/libmultipath/util.c -@@ -14,7 +14,7 @@ - { - int i; - char s1[PARAMS_SIZE],s2[PARAMS_SIZE]; -- -+ - if(!str1 || !str2) - return 1; - -@@ -67,7 +67,7 @@ - char * p; - int len; - int skip = 0; -- -+ - if (word) - *word = NULL; - ---- multipath-tools-0.4.8/libmultipath/uxsock.c -+++ multipath-tools-0.4.8/libmultipath/uxsock.c -@@ -26,17 +26,17 @@ - int ux_socket_connect(const char *name) - { - int fd; -- struct sockaddr_un addr; -+ struct sockaddr_un addr; - -- memset(&addr, 0, sizeof(addr)); -- addr.sun_family = AF_UNIX; -- strncpy(addr.sun_path, name, sizeof(addr.sun_path)); -+ memset(&addr, 0, sizeof(addr)); -+ addr.sun_family = AF_UNIX; -+ strncpy(addr.sun_path, name, sizeof(addr.sun_path)); - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - return -1; - } -- -+ - if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - close(fd); - return -1; -@@ -47,12 +47,13 @@ - - /* - * create a unix domain socket and start listening on it -- * return a file descriptor open on the socket -+ * return a file descriptor open on the socket - */ - int ux_socket_listen(const char *name) - { - int fd; -- struct sockaddr_un addr; -+ struct sockaddr_un addr; -+ - - /* get rid of any old socket */ - unlink(name); -@@ -60,16 +61,16 @@ - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) return -1; - -- memset(&addr, 0, sizeof(addr)); -- addr.sun_family = AF_UNIX; -- strncpy(addr.sun_path, name, sizeof(addr.sun_path)); -+ memset(&addr, 0, sizeof(addr)); -+ addr.sun_family = AF_UNIX; -+ strncpy(addr.sun_path, name, sizeof(addr.sun_path)); - -- if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { -+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - close(fd); - return -1; -- } -+ } - -- if (listen(fd, 10) == -1) { -+ if (listen(fd, 10) == -1) { - close(fd); - return -1; - } ---- multipath-tools-0.4.8/libmultipath/vector.c -+++ multipath-tools-0.4.8/libmultipath/vector.c -@@ -1,10 +1,10 @@ --/* -+/* - * Part: Vector structure manipulation. -- * -+ * - * Version: $Id: vector.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $ -- * -+ * - * Author: Alexandre Cassen, -- * -+ * - * 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. -@@ -23,7 +23,7 @@ - #include - #include "vector.h" - --/* -+/* - * Initialize vector struct. - * allocated 'size' slot elements then return vector. - */ -@@ -54,7 +54,7 @@ - vector_insert_slot(vector v, int slot, void *value) - { - int i; -- -+ - if (!vector_alloc_slot(v)) - return NULL; - ---- multipath-tools-0.4.8/libmultipath/waiter.c -+++ multipath-tools-0.4.8/libmultipath/waiter.c -@@ -58,7 +58,7 @@ - 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; -@@ -113,7 +113,7 @@ - } - - dm_task_no_open_count(waiter->dmt); -- -+ - /* accept wait interruption */ - set = unblock_signals(); - -@@ -154,7 +154,7 @@ - lock_cleanup_pop(waiter->vecs->lock); - - if (r) { -- condlog(2, "%s: event checker exit", -+ condlog(2, "%s: event checker exit", - waiter->mapname); - return -1; /* stop the thread */ - } ---- multipath-tools-0.4.8/multipath.conf.annotated -+++ multipath-tools-0.4.8/multipath.conf.annotated -@@ -134,6 +134,15 @@ - # # default : no - # user_friendly_names no - # -+# # -+# # name : bindings_file -+# # scope : multipath -+# # desc : The location of the bindings file that is used with -+# # the user_friendly_names option. -+# # values : -+# # default : "/var/lib/multipath/bindings" -+# bindings_file "/etc/multipath_bindings" -+# - #} - # - ## ---- multipath-tools-0.4.8/multipath/Makefile -+++ multipath-tools-0.4.8/multipath/Makefile -@@ -16,24 +16,27 @@ - - $(EXEC): $(OBJS) - $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) -- $(GZIP) $(EXEC).8 > $(EXEC).8.gz -- $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz - - install: - $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) -- $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ -+ $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir) -+ $(INSTALL_PROGRAM) -m 755 multipath.init.suse $(DESTDIR)$(rcdir)/boot.multipath - $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d -- $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/ -+ $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/71-multipath.rules - $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) -- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir) - $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) -- $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(man5dir) -+ $(INSTALL_PROGRAM) -d $(DESTDIR)/lib/mkinitrd/scripts -+ $(INSTALL_PROGRAM) -m 755 boot-multipath.sh $(DESTDIR)/lib/mkinitrd/scripts -+ $(INSTALL_PROGRAM) -m 755 setup-multipath.sh $(DESTDIR)/lib/mkinitrd/scripts - - uninstall: - rm $(DESTDIR)/etc/udev/rules.d/multipath.rules - rm $(DESTDIR)$(bindir)/$(EXEC) -- rm $(DESTDIR)$(mandir)/$(EXEC).8.gz -- rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz -+ rm -f $(DESTDIR)/lib/mkinitrd/scripts/boot-multipath.sh -+ rm -f $(DESTDIR)/lib/mkinitrd/scripts/setup-multipath.sh - - clean: -- rm -f core *.o $(EXEC) *.gz -+ rm -f core *.o $(EXEC) ---- multipath-tools-0.4.8/multipath/boot-multipath.sh -+++ multipath-tools-0.4.8/multipath/boot-multipath.sh -@@ -0,0 +1,39 @@ -+#!/bin/bash -+#%stage: block -+#%depends: dm -+#%provides: dmroot -+#%programs: /sbin/multipath /lib/multipath/* -+#%if: "$root_mpath" -+#%modules: dm-multipath dm-round-robin dm-emc dm-hp_sw dm-rdac -+# -+##### Multipath -+## -+## If the root device can be accessed using multiple device paths, -+## this initializes and waits for them -+## -+## Command line parameters -+## ----------------------- -+## -+## root_mpath=1 use multipath -+## mpath_status=off do not use multipath -+## -+ -+load_modules -+ -+# check for multipath parameter in /proc/cmdline -+mpath_status=$(get_param multipath) -+ -+mpath_list=$(sed -n '/multipath/p' /proc/modules) -+if [ -z "$mpath_list" ] ; then -+ mpath_status=off -+fi -+if [ "$mpath_status" != "off" ] ; then -+ # We are waiting for a device-mapper device -+ root_major=$(sed -n 's/\(.*\) device-mapper/\1/p' /proc/devices) -+ # Rescan for multipath -+ echo -n "Setup multipath devices: " -+ /sbin/multipath -v0 -+ wait_for_events -+ echo 'ok.' -+fi -+ ---- multipath-tools-0.4.8/multipath/main.c -+++ multipath-tools-0.4.8/multipath/main.c -@@ -79,6 +79,7 @@ - fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname); - fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); - fprintf (stderr, " %s -F [-v lvl]\n", progname); -+ fprintf (stderr, " %s -t\n", progname); - fprintf (stderr, " %s -h\n", progname); - fprintf (stderr, - "\n" -@@ -89,6 +90,7 @@ - " -f flush a multipath device map\n" \ - " -F flush all multipath device maps\n" \ - " -d dry run, do not create or update devmaps\n" \ -+ " -t dump internal hardware table\n" \ - " -r force devmap reload\n" \ - " -p policy failover|multibus|group_by_serial|group_by_prio\n" \ - " -b fil bindings file location\n" \ -@@ -241,14 +243,14 @@ - else - dev = conf->dev; - } -- -+ - /* - * if we have a blacklisted device parameter, exit early - */ -- if (dev && -+ if (dev && - (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0)) - goto out; -- -+ - /* - * scope limiting must be translated into a wwid - * failing the translation is fatal (by policy) -@@ -315,6 +317,55 @@ - return r; - } - -+static int -+dump_config (void) -+{ -+ char * c; -+ char * reply; -+ unsigned int maxlen = 256; -+ int again = 1; -+ -+ reply = MALLOC(maxlen); -+ -+ while (again) { -+ if (!reply) -+ return 1; -+ c = reply; -+ c += snprint_defaults(c, reply + maxlen - c); -+ again = ((c - reply) == maxlen); -+ if (again) { -+ reply = REALLOC(reply, maxlen *= 2); -+ continue; -+ } -+ c += snprint_blacklist(c, reply + maxlen - c); -+ again = ((c - reply) == maxlen); -+ if (again) { -+ reply = REALLOC(reply, maxlen *= 2); -+ continue; -+ } -+ c += snprint_blacklist_except(c, reply + maxlen - c); -+ again = ((c - reply) == maxlen); -+ if (again) { -+ reply = REALLOC(reply, maxlen *= 2); -+ continue; -+ } -+ c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable); -+ again = ((c - reply) == maxlen); -+ if (again) { -+ reply = REALLOC(reply, maxlen *= 2); -+ continue; -+ } -+ c += snprint_mptable(c, reply + maxlen - c, conf->mptable); -+ again = ((c - reply) == maxlen); -+ if (again) -+ reply = REALLOC(reply, maxlen *= 2); -+ } -+ -+ printf("%s", reply); -+ FREE(reply); -+ return 0; -+} -+ - int - main (int argc, char *argv[]) - { -@@ -346,7 +397,7 @@ - condlog(0, "multipath tools need sysfs mounted"); - exit(1); - } -- while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:r")) != EOF ) { -+ while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:rt")) != EOF ) { - switch(arg) { - case 1: printf("optarg : %s\n",optarg); - break; -@@ -387,23 +438,26 @@ - if (conf->pgpolicy_flag == -1) { - printf("'%s' is not a valid policy\n", optarg); - usage(argv[0]); -- } -+ } - break; - case 'r': - conf->force_reload = 1; - break; -+ case 't': -+ dump_config(); -+ goto out; - case 'h': - usage(argv[0]); - case ':': - fprintf(stderr, "Missing option arguement\n"); -- usage(argv[0]); -+ usage(argv[0]); - case '?': - fprintf(stderr, "Unknown switch: %s\n", optarg); - usage(argv[0]); - default: - usage(argv[0]); - } -- } -+ } - if (optind < argc) { - conf->dev = MALLOC(FILE_NAME_SIZE); - ---- multipath-tools-0.4.8/multipath/multipath.8 -+++ multipath-tools-0.4.8/multipath/multipath.8 -@@ -6,7 +6,7 @@ - .RB [\| \-v\ \c - .IR verbosity \|] - .RB [\| \-d \|] --.RB [\| \-h | \-l | \-ll | \-f | \-F \|] -+.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F \|] - .RB [\| \-p\ \c - .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] - .RB [\| device \|] -@@ -47,6 +47,9 @@ - .B \-F - flush all unused multipath device maps - .TP -+.B \-t -+print internal hardware table to stdout -+.TP - .BI \-p " policy" - force maps to specified policy: - .RS 1.2i -@@ -76,6 +79,9 @@ - .I device - may alternatively be a multipath mapname - .SH "SEE ALSO" -+.BR multipathd (8), -+.BR multipath.conf (5), -+.BR kpartx (8), - .BR udev (8), - .BR dmsetup (8) - .BR hotplug (8) ---- multipath-tools-0.4.8/multipath/multipath.conf.5 -+++ multipath-tools-0.4.8/multipath/multipath.conf.5 -@@ -147,13 +147,24 @@ - .RE - .TP - .B features --Specify any device-mapper features to be used. The most common of --these features is --.I "1 queue_if_no_path" --Note that this can also be set via the -+Specify any device-mapper features to be used. Syntax is -+.I num list -+where -+.I num -+is the number of features in -+.I list. -+Possible values for the feature list are -+.RS -+.TP 12 -+.B queue_if_no_path -+Queue IO if no path is active; identical to the - .I no_path_retry - keyword. - .TP -+.B no_partitions -+Disable automatic partitions generation via kpartx. -+.RE -+.TP - .B path_checker - The default method used to determine the paths' state. Possible values - are -@@ -225,6 +236,10 @@ - be overriden by any specific aliases in the \fImultipaths\fR section. - Default is - .I no -+.TP -+.B bindings_file -+The full pathname of the binding file to be used when the user_friendly_names option is set. Defaults to -+.I /var/lib/multipath/bindings - . - .SH "blacklist section" - The ---- multipath-tools-0.4.8/multipath/multipath.init.suse -+++ multipath-tools-0.4.8/multipath/multipath.init.suse -@@ -0,0 +1,137 @@ -+#! /bin/sh -+# Copyright (c) 2005 SuSE GmbH Nuernberg, Germany. -+# -+# Author: Hannes Reinecke -+# -+# init.d/boot.multipath -+# -+### BEGIN INIT INFO -+# Provides: boot.multipath -+# Required-Start: boot.device-mapper boot.udev -+# Required-Stop: boot.device-mapper boot.udev -+# Default-Start: B -+# Default-Stop: -+# Short-Description: Create multipath device targets -+# Description: Setup initial multipath device-mapper targets -+### END INIT INFO -+ -+PATH=/bin:/usr/bin:/sbin:/usr/sbin -+PROGRAM=/sbin/multipath -+ -+# Set the maximum number of open files -+MAX_OPEN_FDS=4096 -+ -+test -x $PROGRAM || exit 5 -+ -+# Shell functions sourced from /etc/rc.status: -+# rc_check check and set local and overall rc status -+# rc_status check and set local and overall rc status -+# rc_status -v ditto but be verbose in local rc status -+# rc_status -v -r ditto and clear the local rc status -+# rc_failed set local and overall rc status to failed -+# rc_reset clear local rc status (overall remains) -+# rc_exit exit appropriate to overall rc status -+. /etc/rc.status -+ -+# First reset status of this service -+rc_reset -+ -+# Return values acc. to LSB for all commands but status: -+# 0 - success -+# 1 - misc error -+# 2 - invalid or excess args -+# 3 - unimplemented feature (e.g. reload) -+# 4 - insufficient privilege -+# 5 - program not installed -+# 6 - program not configured -+# 7 - program is not running -+# -+# Note that starting an already running service, stopping -+# or restarting a not-running service as well as the restart -+# with force-reload (in case signalling is not supported) are -+# considered a success. -+ -+case "$1" in -+ start) -+ echo -n "Creating multipath targets:" -+ # Check whether multipath daemon is already running -+ if /sbin/multipathd -k"list paths" > /dev/null 2>&1 ; then -+ echo -n " (multipathd running)" -+ rc_status -v -+ rc_exit -+ fi -+ -+ # Load prerequisite module -+ modprobe dm-multipath -+ -+ # Be a chicken and flush all existing maps -+ $PROGRAM -F -+ -+ # Clear /dev/disk/by-name/ prior to start-up; multipath will -+ # recreate them. -+ rm -f /dev/disk/by-name/* 2>&1 >/dev/null -+ -+ # Set the maximum number of open files -+ if [ -n "$MAX_OPEN_FDS" ] ; then -+ ulimit -n $MAX_OPEN_FDS -+ fi -+ -+ # Start the program directly as checkproc doesn't work here -+ $PROGRAM -v 0 -+ -+ # Create all partitions which might have been missing -+ for map in $(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | sort -n +2 | sed -n 's/.*, \(.*\))/\1/p' ) ; do -+ wait=5 -+ while [ $wait -gt 0 ] ; do -+ [ -e /dev/dm-$map ] && break -+ wait=$((wait - 1)) -+ sleep 1; -+ done -+ if [ $wait -le 0 ] ; then -+ echo -n "timeout waiting for devices" -+ rc_failed 1 -+ break; -+ fi -+ /sbin/kpartx -a -p _part /dev/dm-$map -+ done -+ -+ # Remember status and be verbose -+ rc_status -v -+ sleep 1 -+ ;; -+ stop) -+ echo -n "Removing multipath targets:" -+ -+ # Remove all partition mappings -+ if /sbin/dmsetup ls | sed '/No devices/d' | grep -q -- -part; then -+ /sbin/dmsetup ls --target multipath --exec "/sbin/kpartx -d -p _part" 2> /dev/null -+ fi -+ -+ # Flush all existing maps -+ $PROGRAM -F -+ -+ rc_failed 0 -+ rc_status -v -+ ;; -+ status) -+ echo -n "Checking multipath targets: " -+ # Display active multipath tables -+ tblnum=$(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | wc --lines) -+ if [ "$tblnum" ] && [ $tblnum -gt 0 ] ; then -+ echo -n "($tblnum multipath devices) " -+ rc_failed 0 -+ else -+ rc_failed 3 -+ fi -+ rc_status -v -+ ;; -+ reload) -+ $0 stop -+ $0 start -+ ;; -+ *) -+ echo "Usage: $0 {start|stop|status}" -+ exit 1 -+ ;; -+esac -+rc_exit ---- multipath-tools-0.4.8/multipath/setup-multipath.sh -+++ multipath-tools-0.4.8/multipath/setup-multipath.sh -@@ -0,0 +1,45 @@ -+#!/bin/bash -+# -+#%stage: devicemapper -+#%provides: dmroot -+# -+# force multipath and dm usage if multipath was forced -+if use_script multipath; then -+ root_mpath=1 -+ root_dm=1 -+fi -+ -+if [ -x /sbin/multipath -a -x /sbin/dmsetup ] ; then -+ for bd in $blockdev ; do -+ update_blockdev $bd -+ if [ $blockdriver = device-mapper ]; then -+ dm_uuid=$(dmsetup info -c --noheadings -o uuid -j $blockmajor -m $blockminor) -+ dm_creator=${dm_uuid%-*} -+ if [ "$dm_creator" = "mpath" ]; then -+ tmp_root_dm=1 # multipath needs dm -+ root_mpath=1 -+ fi -+ fi -+ done -+fi -+ -+if use_script multipath; then -+ if [ -f /etc/multipath.conf ] ; then -+ cp -a /etc/multipath.conf $tmp_mnt/etc -+ fi -+ if [ -f /var/lib/multipath/bindings ] ; then -+ mkdir -p /var/lib/multipath -+ cp -a /var/lib/multipath/bindings $tmp_mnt/var/lib/multipath -+ fi -+ if [ -e /etc/udev/rules.d/71-multipath.rules ]; then -+ cp /etc/udev/rules.d/71-multipath.rules $tmp_mnt/etc/udev/rules.d -+ fi -+ if [ -e /etc/udev/rules.d/72-multipath-compat.rules ]; then -+ cp /etc/udev/rules.d/72-multipath-compat.rules $tmp_mnt/etc/udev/rules.d -+ fi -+ if [ -d /lib/multipath ]; then -+ mkdir $tmp_mnt/lib/multipath -+ fi -+fi -+ -+save_var root_mpath ---- multipath-tools-0.4.8/multipathd/Makefile -+++ multipath-tools-0.4.8/multipathd/Makefile -@@ -29,20 +29,19 @@ - - $(EXEC): $(OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXEC) $(OBJS) -- $(GZIP) $(EXEC).8 > $(EXEC).8.gz - - install: - $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir) -+ $(INSTALL_PROGRAM) -m 755 multipathd.init.suse $(DESTDIR)$(rcdir)/multipathd - $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) -- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir) - - uninstall: - rm -f $(DESTDIR)$(bindir)/$(EXEC) - rm -f $(DESTDIR)$(rcdir)/$(EXEC) -- rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz - - clean: -- rm -f core *.o $(EXEC) *.gz -+ rm -f core *.o $(EXEC) - ---- multipath-tools-0.4.8/multipathd/main.c -+++ multipath-tools-0.4.8/multipathd/main.c -@@ -944,19 +944,25 @@ - enable_group(pp); - } - else if (newstate == PATH_UP || newstate == PATH_GHOST) { -- LOG_MSG(4, checker_message(&pp->checker)); -- /* -- * double the next check delay. -- * max at conf->max_checkint -- */ -- if (pp->checkint < (conf->max_checkint / 2)) -- pp->checkint = 2 * pp->checkint; -- else -- pp->checkint = conf->max_checkint; -+ if (pp->dmstate == PSTATE_FAILED || -+ pp->dmstate == PSTATE_UNDEF) { -+ /* Clear IO errors */ -+ reinstate_path(pp, 0); -+ } else { -+ LOG_MSG(4, checker_message(&pp->checker)); -+ /* -+ * double the next check delay. -+ * max at conf->max_checkint -+ */ -+ if (pp->checkint < (conf->max_checkint / 2)) -+ pp->checkint = 2 * pp->checkint; -+ else -+ pp->checkint = conf->max_checkint; - -- pp->tick = pp->checkint; -- condlog(4, "%s: delay next check %is", -+ pp->tick = pp->checkint; -+ condlog(4, "%s: delay next check %is", - pp->dev_t, pp->tick); -+ } - } - else if (newstate == PATH_DOWN) - LOG_MSG(2, checker_message(&pp->checker)); -@@ -1341,9 +1347,7 @@ - /* - * exit path - */ -- lock(vecs->lock); - remove_maps_and_stop_waiters(vecs); -- free_pathvec(vecs->pathvec, FREE_PATHS); - - pthread_cancel(check_thr); - pthread_cancel(uevent_thr); -@@ -1357,6 +1361,9 @@ - handlers = NULL; - free_polls(); - -+ lock(vecs->lock); -+ free_pathvec(vecs->pathvec, FREE_PATHS); -+ vecs->pathvec = NULL; - unlock(vecs->lock); - pthread_mutex_destroy(vecs->lock); - FREE(vecs->lock); -@@ -1421,15 +1428,28 @@ - } - - close(STDIN_FILENO); -- dup(in_fd); -+ if (dup(in_fd) < 0) { -+ fprintf(stderr, "cannot duplicate /dev/null for input" -+ ": %s\n", strerror(errno)); -+ _exit(0); -+ } - close(STDOUT_FILENO); -- dup(out_fd); -+ if (dup(out_fd) < 0) { -+ fprintf(stderr, "cannot duplicate /dev/console for output" -+ ": %s\n", strerror(errno)); -+ _exit(0); -+ } - close(STDERR_FILENO); -- dup(out_fd); -- -+ if (dup(out_fd) < 0) { -+ fprintf(stderr, "cannot duplicate /dev/console for error" -+ ": %s\n", strerror(errno)); -+ _exit(0); -+ } - close(in_fd); - close(out_fd); -- chdir("/"); -+ if (chdir("/") < 0) -+ fprintf(stderr, "cannot chdir to '/', continuing\n"); -+ - umask(0); - return 0; - } -@@ -1451,7 +1471,9 @@ - } - - /* make sure we don't lock any path */ -- chdir("/"); -+ if (chdir("/") < 0) -+ fprintf(stderr, "couldn't chdir to '/', continuing\n"); -+ - umask(umask(077) | 022); - - conf = alloc_config(); ---- multipath-tools-0.4.8/multipathd/multipathd.init.suse -+++ multipath-tools-0.4.8/multipathd/multipathd.init.suse -@@ -12,10 +12,11 @@ - ### BEGIN INIT INFO - # Provides: multipathd - # Required-Start: $syslog --# Required-Stop: -+# Required-Stop: $syslog - # Default-Start: 3 5 - # Default-Stop: 0 1 2 4 6 --# Description: Starts multipath daemon -+# Short-Description: Starts multipath daemon -+# Description: Starts the multipath daemon - ### END INIT INFO - - PATH=/bin:/usr/bin:/sbin:/usr/sbin ---- multipath-tools-0.4.8/multipathd/uxlsnr.c -+++ multipath-tools-0.4.8/multipathd/uxlsnr.c -@@ -168,5 +168,6 @@ - } - } - -+ close(ux_sock); - return NULL; - } diff --git a/multipath-tools-sles11-alpha3-update b/multipath-tools-sles11-alpha3-update deleted file mode 100644 index f154b00..0000000 --- a/multipath-tools-sles11-alpha3-update +++ /dev/null @@ -1,156 +0,0 @@ -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index 0b39297..87b155e 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -1,4 +1,4 @@ --#define DEFAULT_GETUID "/lib/udev/scsi_id -g -u /dev/%n" -+#define DEFAULT_GETUID "/lib/udev/scsi_id -g -u -d /dev/%n" - #define DEFAULT_UDEVDIR "/dev" - #define DEFAULT_MULTIPATHDIR "/lib/multipath" - #define DEFAULT_SELECTOR "round-robin 0" -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index 48f9b1a..3f45257 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -172,7 +172,7 @@ static struct hwentry default_hw[] = { - /* HP Smart Array */ - .vendor = "HP", - .product = "LOGICAL VOLUME.*", -- .getuid = "/lib/udev/scsi_id -n -g -u /dev/%n", -+ .getuid = "/lib/udev/scsi_id -n -g -u -d /dev/%n", - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -214,7 +214,7 @@ static struct hwentry default_hw[] = { - { - .vendor = "EMC", - .product = "SYMMETRIX", -- .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 /dev/%n", -+ .getuid = "/lib/udev/scsi_id -g -u -ppre-spc3-83 -d /dev/%n", - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -@@ -337,6 +337,22 @@ static struct hwentry default_hw[] = { - .prio_name = PRIO_RDAC, - }, - { -+ /* IBM DS3400 */ -+ .vendor = "IBM", -+ .product = "1726-4xx", -+ .getuid = DEFAULT_GETUID, -+ .features = "1 queue_if_no_path", -+ .hwhandler = "1 rdac", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = 300, -+ .minio = DEFAULT_MINIO, -+ .checker_name = RDAC, -+ .prio_name = PRIO_RDAC, -+ }, -+ { - /* IBM DS4400 / FAStT700 */ - .vendor = "IBM", - .product = "1742", -@@ -514,6 +530,22 @@ static struct hwentry default_hw[] = { - .checker_name = DIRECTIO, - .prio_name = DEFAULT_PRIO, - }, -+ { -+ /* IBM IPR */ -+ .vendor = "IBM", -+ .product = "IPR.*", -+ .getuid = DEFAULT_GETUID, -+ .features = "1 queue_if_no_path", -+ .hwhandler = "1 alua", -+ .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 = TUR, -+ .prio_name = PRIO_ALUA, -+ }, - /* - * NETAPP controller family - * -@@ -679,7 +711,7 @@ static struct hwentry default_hw[] = { - { - .vendor = "PIVOT3", - .product = "RAIGE VOLUME", -- .getuid = "/sbin/scsi_id -p 0x80 -g -u -s /block/%n", -+ .getuid = "/lib/udev/scsi_id -p 0x80 -g -u -d /dev/%n", - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, -diff --git a/libmultipath/uxsock.c b/libmultipath/uxsock.c -index f70e2f5..7bfc5d2 100644 ---- a/libmultipath/uxsock.c -+++ b/libmultipath/uxsock.c -@@ -54,7 +54,6 @@ int ux_socket_listen(const char *name) - int fd; - struct sockaddr_un addr; - -- - /* get rid of any old socket */ - unlink(name); - -diff --git a/multipath.conf.annotated b/multipath.conf.annotated -index dda9e4c..a4c7e6a 100644 ---- a/multipath.conf.annotated -+++ b/multipath.conf.annotated -@@ -49,7 +49,7 @@ - # # path identifier. Absolute path required - # # default : /lib/udev/scsi_id -g -u -s - # # --# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" -+# getuid_callout "/lib/udev/scsi_id -g -u -d /dev/%n" - # - # # - # # name : prio -@@ -312,7 +312,7 @@ - # # path identifier. Absolute path required - # # default : /lib/udev/scsi_id -g -u -s - # # --# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" -+# getuid_callout "/lib/udev/scsi_id -g -u -d /dev/%n" - # - # # - # # name : prio -diff --git a/multipath.conf.synthetic b/multipath.conf.synthetic -index 33f820b..6459f56 100644 ---- a/multipath.conf.synthetic -+++ b/multipath.conf.synthetic -@@ -7,7 +7,7 @@ - # polling_interval 10 - # selector "round-robin 0" - # path_grouping_policy multibus --# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" -+# getuid_callout "/lib/udev/scsi_id -g -u -d /dev/%n" - # prio const - # path_checker directio - # rr_min_io 100 -@@ -53,7 +53,7 @@ - # vendor "COMPAQ " - # product "HSV110 (C)COMPAQ" - # path_grouping_policy multibus --# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n" -+# getuid_callout "/lib/udev/scsi_id -g -u -d /dev/%n" - # path_checker directio - # path_selector "round-robin 0" - # hardware_handler "0" -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index fc9d3da..90ef588 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -109,7 +109,7 @@ Default value is \fImultibus\fR. - The default program and args to callout to obtain a unique path - identifier. Should be specified with an absolute path. Default value - is --.I /lib/udev/scsi_id -g -u -s -+.I /lib/udev/scsi_id -g -u -d /dev/%n - .TP - .B prio_callout - The default program and args to callout to obtain a path priority diff --git a/multipath-tools-sles11-valgrind-fixes b/multipath-tools-sles11-valgrind-fixes deleted file mode 100644 index 7ce1626..0000000 --- a/multipath-tools-sles11-valgrind-fixes +++ /dev/null @@ -1,644 +0,0 @@ -diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c -index 5132081..2640281 100644 ---- a/libmultipath/checkers.c -+++ b/libmultipath/checkers.c -@@ -40,6 +40,14 @@ struct checker * alloc_checker (void) - - void free_checker (struct checker * c) - { -+ condlog(3, "unloading %s checker", c->name); -+ list_del(&c->node); -+ if (c->handle) { -+ if (dlclose(c->handle) != 0) { -+ condlog(0, "Cannot unload checker %s: %s", -+ c->name, dlerror()); -+ } -+ } - free(c); - } - -@@ -49,8 +57,7 @@ void cleanup_checkers (void) - struct checker * checker_temp; - - list_for_each_entry_safe(checker_loop, checker_temp, &checkers, node) { -- list_del(&checker_loop->node); -- free(checker_loop); -+ free_checker(checker_loop); - } - } - -@@ -68,7 +75,6 @@ struct checker * checker_lookup (char * name) - struct checker * add_checker (char * name) - { - char libname[LIB_CHECKER_NAMELEN]; -- void * handle; - struct checker * c; - char *errstr; - -@@ -78,31 +84,31 @@ struct checker * add_checker (char * name) - snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so", - conf->multipath_dir, name); - condlog(3, "loading %s checker", libname); -- handle = dlopen(libname, RTLD_NOW); -+ c->handle = dlopen(libname, RTLD_NOW); - errstr = dlerror(); - if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -- if (!handle) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!c->handle) - goto out; - -- c->check = (int (*)(struct checker *)) dlsym(handle, "libcheck_check"); -+ c->check = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_check"); - errstr = dlerror(); - if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); - if (!c->check) - goto out; - -- c->init = (int (*)(struct checker *)) dlsym(handle, "libcheck_init"); -+ c->init = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_init"); - errstr = dlerror(); - if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); - if (!c->init) - goto out; - -- c->free = (void (*)(struct checker *)) dlsym(handle, "libcheck_free"); -+ c->free = (void (*)(struct checker *)) dlsym(c->handle, "libcheck_free"); - errstr = dlerror(); - if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); - if (!c->free) - goto out; - -@@ -199,4 +205,5 @@ void checker_get (struct checker * dst, char * name) - dst->check = src->check; - dst->init = src->init; - dst->free = src->free; -+ dst->handle = NULL; - } -diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h -index e735250..da09d6c 100644 ---- a/libmultipath/checkers.h -+++ b/libmultipath/checkers.h -@@ -94,6 +94,7 @@ enum path_check_state { - - struct checker { - struct list_head node; -+ void *handle; - int fd; - int sync; - int disable; -@@ -111,6 +112,7 @@ struct checker { - - char * checker_state_name (int); - int init_checkers (void); -+void cleanup_checkers (void); - struct checker * add_checker (char *); - struct checker * checker_lookup (char *); - int checker_init (struct checker *, void **); -diff --git a/libmultipath/checkers/emc_clariion.c b/libmultipath/checkers/emc_clariion.c -index 9eac31d..03c1354 100644 ---- a/libmultipath/checkers/emc_clariion.c -+++ b/libmultipath/checkers/emc_clariion.c -@@ -102,6 +102,8 @@ int libcheck_check (struct checker * c) - int ret; - - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ memset(sense_buffer, 0, 128); -+ memset(sb, 0, SENSE_BUFF_LEN); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (inqCmdBlk); - io_hdr.mx_sb_len = sizeof (sb); -@@ -128,7 +130,7 @@ int libcheck_check (struct checker * c) - } - - if ( /* Effective initiator type */ -- sense_buffer[27] != 0x03 -+ sense_buffer[27] != 0x03 - /* - * Failover mode should be set to 1 (PNR failover mode) - * or 4 (ALUA failover mode). -@@ -155,7 +157,7 @@ int libcheck_check (struct checker * c) - "or LUNZ"); - return PATH_DOWN; - } -- -+ - /* - * store the LUN WWN there and compare that it indeed did not - * change in between, to protect against the path suddenly -@@ -171,28 +173,29 @@ int libcheck_check (struct checker * c) - memcpy(ct->wwn, &sense_buffer[10], 16); - ct->wwn_set = 1; - } -- -+ - /* - * Issue read on active path to determine if inactive snapshot. - */ - if (sense_buffer[4] == 2) {/* if active path */ - unsigned char buf[4096]; - -+ memset(buf, 0, 4096); - ret = sg_read(c->fd, &buf[0], sbb = &sb[0]); - if (ret == PATH_DOWN) { - hexadecimal_to_ascii(ct->wwn, wwnstr); - - /* -- * Check for inactive snapshot LU this way. Must -+ * Check for inactive snapshot LU this way. Must - * fail these. -- */ -+ */ - if (((sbb[2]&0xf) == 5) && (sbb[12] == 0x25) && - (sbb[13]==1)) { - /* -- * Do this so that we can fail even the -- * passive paths which will return -+ * Do this so that we can fail even the -+ * passive paths which will return - * 02/04/03 not 05/25/01 on read. -- */ -+ */ - SET_INACTIVE_SNAP(c); - MSG(c, "emc_clariion_checker: Active " - "path to inactive snapshot WWN %s.", -@@ -206,10 +209,10 @@ int libcheck_check (struct checker * c) - MSG(c, "emc_clariion_checker: Active path is " - "healthy."); - /* -- * Remove the path from the set of paths to inactive -- * snapshot LUs if it was in this list since the -- * snapshot is no longer inactive. -- */ -+ * Remove the path from the set of paths to inactive -+ * snapshot LUs if it was in this list since the -+ * snapshot is no longer inactive. -+ */ - CLR_INACTIVE_SNAP(c); - } - } else { -@@ -221,7 +224,7 @@ int libcheck_check (struct checker * c) - ret = PATH_DOWN; - } else { - MSG(c, -- "emc_clariion_checker: Passive path is healthy."); -+ "emc_clariion_checker: Passive path is healthy."); - ret = PATH_UP; /* not ghost */ - } - } -diff --git a/libmultipath/checkers/hp_sw.c b/libmultipath/checkers/hp_sw.c -index 7509307..3f28d85 100644 ---- a/libmultipath/checkers/hp_sw.c -+++ b/libmultipath/checkers/hp_sw.c -@@ -48,75 +48,76 @@ static int - do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, - void *resp, int mx_resp_len, int noisy) - { -- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = -- { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -- unsigned char sense_b[SENSE_BUFF_LEN]; -- struct sg_io_hdr io_hdr; -- -- if (cmddt) -- inqCmdBlk[1] |= 2; -- if (evpd) -- inqCmdBlk[1] |= 1; -- inqCmdBlk[2] = (unsigned char) pg_op; -+ unsigned char inqCmdBlk[INQUIRY_CMDLEN] = -+ { INQUIRY_CMD, 0, 0, 0, 0, 0 }; -+ unsigned char sense_b[SENSE_BUFF_LEN]; -+ struct sg_io_hdr io_hdr; -+ -+ if (cmddt) -+ inqCmdBlk[1] |= 2; -+ if (evpd) -+ inqCmdBlk[1] |= 1; -+ inqCmdBlk[2] = (unsigned char) pg_op; - inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); - inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (inqCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_b); -- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -- io_hdr.dxfer_len = mx_resp_len; -- io_hdr.dxferp = resp; -- io_hdr.cmdp = inqCmdBlk; -- io_hdr.sbp = sense_b; -- io_hdr.timeout = DEF_TIMEOUT; -- -- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -- return 1; -- -- /* treat SG_ERR here to get rid of sg_err.[ch] */ -- io_hdr.status &= 0x7e; -- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -- (0 == io_hdr.driver_status)) -- return 0; -- if ((SCSI_CHECK_CONDITION == io_hdr.status) || -- (SCSI_COMMAND_TERMINATED == io_hdr.status) || -- (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -- if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -- int sense_key; -- unsigned char * sense_buffer = io_hdr.sbp; -- if (sense_buffer[0] & 0x2) -- sense_key = sense_buffer[1] & 0xf; -- else -- sense_key = sense_buffer[2] & 0xf; -- if(RECOVERED_ERROR == sense_key) -- return 0; -- } -- } -- return 1; -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ memset(sense_b, 0, SENSE_BUFF_LEN); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (inqCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sense_b); -+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; -+ io_hdr.dxfer_len = mx_resp_len; -+ io_hdr.dxferp = resp; -+ io_hdr.cmdp = inqCmdBlk; -+ io_hdr.sbp = sense_b; -+ io_hdr.timeout = DEF_TIMEOUT; -+ -+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) -+ return 1; -+ -+ /* treat SG_ERR here to get rid of sg_err.[ch] */ -+ io_hdr.status &= 0x7e; -+ if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && -+ (0 == io_hdr.driver_status)) -+ return 0; -+ if ((SCSI_CHECK_CONDITION == io_hdr.status) || -+ (SCSI_COMMAND_TERMINATED == io_hdr.status) || -+ (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { -+ if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { -+ int sense_key; -+ unsigned char * sense_buffer = io_hdr.sbp; -+ if (sense_buffer[0] & 0x2) -+ sense_key = sense_buffer[1] & 0xf; -+ else -+ sense_key = sense_buffer[2] & 0xf; -+ if(RECOVERED_ERROR == sense_key) -+ return 0; -+ } -+ } -+ return 1; - } - - static int - do_tur (int fd) - { -- unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -- struct sg_io_hdr io_hdr; -- unsigned char sense_buffer[32]; -- -- memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -- io_hdr.interface_id = 'S'; -- io_hdr.cmd_len = sizeof (turCmdBlk); -- io_hdr.mx_sb_len = sizeof (sense_buffer); -- io_hdr.dxfer_direction = SG_DXFER_NONE; -- io_hdr.cmdp = turCmdBlk; -- io_hdr.sbp = sense_buffer; -- io_hdr.timeout = DEF_TIMEOUT; -- io_hdr.pack_id = 0; -- -- if (ioctl(fd, SG_IO, &io_hdr) < 0) -+ unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; -+ struct sg_io_hdr io_hdr; -+ unsigned char sense_buffer[32]; -+ -+ memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ io_hdr.interface_id = 'S'; -+ io_hdr.cmd_len = sizeof (turCmdBlk); -+ io_hdr.mx_sb_len = sizeof (sense_buffer); -+ io_hdr.dxfer_direction = SG_DXFER_NONE; -+ io_hdr.cmdp = turCmdBlk; -+ io_hdr.sbp = sense_buffer; -+ io_hdr.timeout = DEF_TIMEOUT; -+ io_hdr.pack_id = 0; -+ -+ if (ioctl(fd, SG_IO, &io_hdr) < 0) - return 1; - -- if (io_hdr.info & SG_INFO_OK_MASK) -+ if (io_hdr.info & SG_INFO_OK_MASK) - return 1; - - return 0; -@@ -134,8 +135,8 @@ libcheck_check (struct checker * c) - - if (do_tur(c->fd)) { - MSG(c, MSG_HP_SW_GHOST); -- return PATH_GHOST; -- } -+ return PATH_GHOST; -+ } - MSG(c, MSG_HP_SW_UP); - return PATH_UP; - } -diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c -index 0086125..c4c7b8f 100644 ---- a/libmultipath/checkers/rdac.c -+++ b/libmultipath/checkers/rdac.c -@@ -52,6 +52,7 @@ do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len) - inqCmdBlk[2] = (unsigned char) pg_op; - inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ memset(sense_b, 0, SENSE_BUFF_LEN); - - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (inqCmdBlk); -@@ -100,6 +101,7 @@ libcheck_check (struct checker * c) - { - struct volume_access_inq inq; - -+ memset(&inq, 0, sizeof(struct volume_access_inq)); - if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq))) { - MSG(c, MSG_RDAC_DOWN); - return PATH_DOWN; -diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c -index 43b846d..820a2e3 100644 ---- a/libmultipath/checkers/tur.c -+++ b/libmultipath/checkers/tur.c -@@ -47,6 +47,7 @@ libcheck_check (struct checker * c) - - retry: - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ memset(&sense_buffer, 0, 32); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (turCmdBlk); - io_hdr.mx_sb_len = sizeof (sense_buffer); -diff --git a/libmultipath/config.c b/libmultipath/config.c -index cf134e4..908156d 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -150,9 +150,6 @@ free_hwe (struct hwentry * hwe) - if (hwe->revision) - FREE(hwe->revision); - -- if (hwe->selector) -- FREE(hwe->selector); -- - if (hwe->getuid) - FREE(hwe->getuid); - -@@ -162,6 +159,15 @@ free_hwe (struct hwentry * hwe) - if (hwe->hwhandler) - FREE(hwe->hwhandler); - -+ if (hwe->selector) -+ FREE(hwe->selector); -+ -+ if (hwe->checker_name) -+ FREE(hwe->checker_name); -+ -+ if (hwe->prio_name) -+ FREE(hwe->prio_name); -+ - if (hwe->bl_product) - FREE(hwe->bl_product); - -@@ -409,6 +415,12 @@ free_config (struct config * conf) - if (conf->bindings_file) - FREE(conf->bindings_file); - -+ if (conf->prio_name) -+ FREE(conf->prio_name); -+ -+ if (conf->checker_name) -+ FREE(conf->checker_name); -+ - free_blacklist(conf->blist_devnode); - free_blacklist(conf->blist_wwid); - free_blacklist_device(conf->blist_device); -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 9929e19..20d0684 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -232,6 +232,7 @@ devt2devname (char *devname, char *devt) - char block_path[FILE_NAME_SIZE]; - struct stat statbuf; - -+ memset(block_path, 0, FILE_NAME_SIZE); - if (sscanf(devt, "%u:%u", &major, &minor) != 2) { - condlog(0, "Invalid device number %s", devt); - return 1; -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 46ae2ec..7467411 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -111,19 +111,22 @@ snprint_ro (char * buff, size_t len, struct multipath * mpp) - static int - snprint_progress (char * buff, size_t len, int cur, int total) - { -- int i = PROGRESS_LEN * cur / total; -- int j = PROGRESS_LEN - i; - char * c = buff; - char * end = buff + len; - -- while (i-- > 0) { -- c += snprintf(c, len, "X"); -- if ((len = (end - c)) <= 1) goto out; -- } -+ if (total > 0) { -+ int i = PROGRESS_LEN * cur / total; -+ int j = PROGRESS_LEN - i; -+ -+ while (i-- > 0) { -+ c += snprintf(c, len, "X"); -+ if ((len = (end - c)) <= 1) goto out; -+ } - -- while (j-- > 0) { -- c += snprintf(c, len, "."); -- if ((len = (end - c)) <= 1) goto out; -+ while (j-- > 0) { -+ c += snprintf(c, len, "."); -+ if ((len = (end - c)) <= 1) goto out; -+ } - } - - c += snprintf(c, len, " %i/%i", cur, total); -@@ -705,6 +708,7 @@ print_multipath_topology (struct multipath * mpp, int verbosity) - { - char buff[MAX_LINE_LEN * MAX_LINES] = {}; - -+ memset(&buff[0], 0, MAX_LINE_LEN * MAX_LINES); - snprint_multipath_topology(&buff[0], MAX_LINE_LEN * MAX_LINES, - mpp, verbosity); - printf("%s", buff); -diff --git a/libmultipath/prio.c b/libmultipath/prio.c -index c9d2873..352e9ca 100644 ---- a/libmultipath/prio.c -+++ b/libmultipath/prio.c -@@ -24,6 +24,14 @@ struct prio * alloc_prio (void) - - void free_prio (struct prio * p) - { -+ condlog(3, "unloading %s prioritizer", p->name); -+ list_del(&p->node); -+ if (p->handle) { -+ if (dlclose(p->handle) != 0) { -+ condlog(0, "Cannot unload prioritizer %s: %s", -+ p->name, dlerror()); -+ } -+ } - free(p); - } - -@@ -33,8 +41,7 @@ void cleanup_prio(void) - struct prio * prio_temp; - - list_for_each_entry_safe(prio_loop, prio_temp, &prioritizers, node) { -- list_del(&prio_loop->node); -- free(prio_loop); -+ free_prio(prio_loop); - } - } - -@@ -52,7 +59,6 @@ struct prio * prio_lookup (char * name) - struct prio * add_prio (char * name) - { - char libname[LIB_PRIO_NAMELEN]; -- void * handle; - struct prio * p; - char *errstr; - -@@ -62,16 +68,16 @@ struct prio * add_prio (char * name) - snprintf(libname, LIB_PRIO_NAMELEN, "%s/libprio%s.so", - conf->multipath_dir, name); - condlog(3, "loading %s prioritizer", libname); -- handle = dlopen(libname, RTLD_NOW); -+ p->handle = dlopen(libname, RTLD_NOW); - errstr = dlerror(); - if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -- if (!handle) -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ if (!p->handle) - goto out; -- p->getprio = (int (*)(struct path *)) dlsym(handle, "getprio"); -+ p->getprio = (int (*)(struct path *)) dlsym(p->handle, "getprio"); - errstr = dlerror(); - if (errstr != NULL) -- condlog(0, "A dynamic linking error occurred: (%s)", errstr); -+ condlog(0, "A dynamic linking error occurred: (%s)", errstr); - if (!p->getprio) - goto out; - snprintf(p->name, PRIO_NAME_LEN, "%s", name); -diff --git a/libmultipath/prio.h b/libmultipath/prio.h -index 4eea703..deef02d 100644 ---- a/libmultipath/prio.h -+++ b/libmultipath/prio.h -@@ -37,12 +37,14 @@ - #define PRIO_NAME_LEN 16 - - struct prio { -+ void *handle; - struct list_head node; - char name[PRIO_NAME_LEN]; - int (*getprio)(struct path *); - }; - - int init_prio (void); -+void cleanup_prio(void); - struct prio * add_prio (char *); - struct prio * prio_lookup (char *); - int prio_getprio (struct prio *, struct path *); -diff --git a/libmultipath/prioritizers/alua_rtpg.c b/libmultipath/prioritizers/alua_rtpg.c -index 59df788..498de62 100644 ---- a/libmultipath/prioritizers/alua_rtpg.c -+++ b/libmultipath/prioritizers/alua_rtpg.c -@@ -265,8 +265,10 @@ get_asymmetric_access_state(int fd, unsigned int tpg) - } - memset(buf, 0, buflen); - rc = do_rtpg(fd, buf, buflen); -- if (rc < 0) -+ if (rc < 0) { -+ free(buf); - return rc; -+ } - scsi_buflen = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; - if (buflen < (scsi_buflen + 4)) { - free(buf); -diff --git a/libmultipath/prioritizers/emc.c b/libmultipath/prioritizers/emc.c -index 61d7a77..c3301b2 100644 ---- a/libmultipath/prioritizers/emc.c -+++ b/libmultipath/prioritizers/emc.c -@@ -18,8 +18,9 @@ int emc_clariion_prio(const char *dev, int fd) - unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0, - sizeof(sb), 0}; - struct sg_io_hdr io_hdr; -- int ret = 0; -+ int ret = PRIO_UNDEF; - -+ memset(&sense_buffer, 0, 256); - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (inqCmdBlk); -@@ -45,9 +46,9 @@ int emc_clariion_prio(const char *dev, int fd) - pp_emc_log(0, "path unit report page in unknown format"); - goto out; - } -- -+ - if ( /* Effective initiator type */ -- sense_buffer[27] != 0x03 -+ sense_buffer[27] != 0x03 - /* - * Failover mode should be set to 1 (PNR failover mode) - * or 4 (ALUA failover mode). -@@ -68,7 +69,7 @@ int emc_clariion_prio(const char *dev, int fd) - /* Note this will switch to the default priority group, even if - * it is not the currently active one. */ - ret = (sense_buffer[5] == sense_buffer[8]) ? 1 : 0; -- -+ - out: - return(ret); - } -diff --git a/libmultipath/prioritizers/hds.c b/libmultipath/prioritizers/hds.c -index f3d4cb3..d56a46a 100644 ---- a/libmultipath/prioritizers/hds.c -+++ b/libmultipath/prioritizers/hds.c -@@ -104,6 +104,7 @@ int hds_modular_prio (const char *dev, int fd) - } - - memset (&io_hdr, 0, sizeof (sg_io_hdr_t)); -+ memset (inqBuff, 0, INQ_REPLY_LEN); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (inqCmdBlk); - io_hdr.mx_sb_len = sizeof (sense_buffer); -diff --git a/libmultipath/prioritizers/ontap.c b/libmultipath/prioritizers/ontap.c -index 1200114..4d7c128 100644 ---- a/libmultipath/prioritizers/ontap.c -+++ b/libmultipath/prioritizers/ontap.c -@@ -79,6 +79,7 @@ static int send_gva(const char *dev, int fd, unsigned char pg, - int ret = -1; - - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ memset(results, 0, *results_size); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (cdb); - io_hdr.mx_sb_len = sizeof (sb); -diff --git a/libmultipath/prioritizers/rdac.c b/libmultipath/prioritizers/rdac.c -index 7eafc31..b514bdd 100644 ---- a/libmultipath/prioritizers/rdac.c -+++ b/libmultipath/prioritizers/rdac.c -@@ -21,6 +21,7 @@ int rdac_prio(const char *dev, int fd) - int ret = 0; - - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ memset(sense_buffer, 0, 256); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (inqCmdBlk); - io_hdr.mx_sb_len = sizeof (sb); diff --git a/multipath-tools-split-off-IBM-ESS b/multipath-tools-split-off-IBM-ESS deleted file mode 100644 index 91f1e29..0000000 --- a/multipath-tools-split-off-IBM-ESS +++ /dev/null @@ -1,42 +0,0 @@ -commit 38a29e437712a01dcb027371a948b110cd54196e -Author: Hannes Reinecke -Date: Wed Dec 3 10:38:04 2008 +0100 - - Split off IBM ESS entries - - For some reason the regular expression doesn't work properly. - So split off the two entries. - - References: bnc#439763 - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index bf8c611..d742d6d 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -507,7 +507,23 @@ static struct hwentry default_hw[] = { - { - /* IBM ESS F20 aka Shark */ - .vendor = "IBM", -- .product = "2105(800|F20)", -+ .product = "2105800", -+ .getuid = DEFAULT_GETUID, -+ .features = "1 queue_if_no_path", -+ .hwhandler = DEFAULT_HWHANDLER, -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_SERIAL, -+ .pgfailback = FAILBACK_UNDEF, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = NO_PATH_RETRY_UNDEF, -+ .minio = DEFAULT_MINIO, -+ .checker_name = TUR, -+ .prio_name = DEFAULT_PRIO, -+ }, -+ { -+ /* IBM ESS F20 aka Shark */ -+ .vendor = "IBM", -+ .product = "2105F20", - .getuid = DEFAULT_GETUID, - .features = "1 queue_if_no_path", - .hwhandler = DEFAULT_HWHANDLER, diff --git a/multipath-tools-start-xdr_setsite b/multipath-tools-start-xdr_setsite deleted file mode 100644 index efead34..0000000 --- a/multipath-tools-start-xdr_setsite +++ /dev/null @@ -1,23 +0,0 @@ -commit 5b86869d6e83660fa9f004313497b67d67c78bea -Author: Hannes Reinecke -Date: Mon Dec 1 10:01:40 2008 +0100 - - Add Should-Start entry for IBM xDR - - IBM's xDR solution requires a should-start entry. - - Signed-off-by: Hannes Reinecke - -diff --git a/multipath/multipath.init.suse b/multipath/multipath.init.suse -index 7dd7031..4f2d8b0 100755 ---- a/multipath/multipath.init.suse -+++ b/multipath/multipath.init.suse -@@ -9,6 +9,8 @@ - # Required-Start: boot.device-mapper boot.udev - # Required-Stop: boot.device-mapper boot.udev - # Default-Start: B -+# Should-Start: boot.xdrsetsite -+# Should-Stop: boot.xdrsetsite - # Default-Stop: - # Short-Description: Create multipath device targets - # Description: Setup initial multipath device-mapper targets diff --git a/multipath-tools-sysfs-subdir-reformat b/multipath-tools-sysfs-subdir-reformat deleted file mode 100644 index ad7851b..0000000 --- a/multipath-tools-sysfs-subdir-reformat +++ /dev/null @@ -1,39 +0,0 @@ -From ac44cbe83f16eafc3de5a56fa275aabd5783ce7c Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Wed, 29 Oct 2008 16:58:52 +0100 -Subject: [PATCH] Fixup %n to handle '!' special case - -The kernel name may contain an '!', which should be translated -into a '/'. So do it here. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/callout.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/callout.c b/libmultipath/callout.c -index 4dd33c5..59ac694 100644 ---- a/libmultipath/callout.c -+++ b/libmultipath/callout.c -@@ -131,6 +131,7 @@ apply_format (char * string, char * cmd, struct path * pp) - char * pos; - char * dst; - char * p; -+ char * q; - int len; - int myfree; - -@@ -169,6 +170,10 @@ apply_format (char * string, char * cmd, struct path * pp) - return 1; - - snprintf(p, len, "%s", pp->dev); -+ for (q = p; q < p + len; q++) { -+ if (q && *q == '!') -+ *q = '/'; -+ } - p += len - 1; - break; - case 'd': --- -1.5.4.5 - diff --git a/multipath-tools-update-dev_loss_tmo-handling b/multipath-tools-update-dev_loss_tmo-handling deleted file mode 100644 index 669f5b9..0000000 --- a/multipath-tools-update-dev_loss_tmo-handling +++ /dev/null @@ -1,165 +0,0 @@ -commit 56f63c78a2f6446d283cfeb6884b6f730a712488 -Author: Hannes Reinecke -Date: Wed Jan 21 14:44:48 2009 +0100 - - Update dev_loss_tmo handling - - The original implementation didn't update the hwe-specific settings - and failed to detect the correct rport. So fixing it. - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index d8d1e30..c37247a 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -212,12 +212,10 @@ sysfs_get_fc_nodename (struct sysfs_device * dev, char * node, - int - sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo) - { -+ char *rport; - char attr_path[SYSFS_PATH_SIZE]; -- char host_path[SYSFS_PATH_SIZE]; - char attr_value[NAME_SIZE]; -- DIR *host_dir, *rport_dir; -- struct dirent *host_ent, *rport_ent; -- int host, channel, lun, port, num; -+ int host, num; - int rport_channel = -1; - int rport_id = -1; - -@@ -226,74 +224,48 @@ sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo) - return 0; - } - -- if (safe_sprintf(host_path, "/sys/class/fc_host/host%i/device", -- pp->sg_id.host_no)) { -- condlog(0, "host_path too small"); -- return 1; -- } -- if (!(host_dir = opendir(host_path))) { -- condlog(3, "host %d not a FC HBA", pp->sg_id.host_no); -+ if (!pp->sysdev) { -+ condlog(3, "%s: no sysfs device set", pp->dev); - return 0; - } - -- while (rport_channel < 0 && rport_id < 0 && -- (host_ent = readdir(host_dir))) { -- if (sscanf(host_ent->d_name, "rport-%d:%d-%d", -- &host, &port, &num) != 3) -- continue; -- -- if (host != pp->sg_id.host_no) -- continue; -- -- if (safe_sprintf(attr_path, "%s/%s", -- host_path, host_ent->d_name)) { -- condlog(0, "target_path too small"); -- continue; -- } -- -- if (!(rport_dir = opendir(attr_path))) { -- condlog(1, "cannot open rport path '%s'", attr_path); -- continue; -- } -- -- while ((rport_ent = readdir(rport_dir))) { -- if (sscanf(rport_ent->d_name, "target%d:%d:%d", -- &host, &channel, &lun) != 3) -- continue; -- -- if (host != pp->sg_id.host_no && -- channel != pp->sg_id.channel && -- lun != pp->sg_id.scsi_id) -- continue; -+ condlog(4, "%s: checking rport for %s", pp->dev, -+ pp->sysdev ? pp->sysdev->devpath : NULL); - -- rport_channel = port; -- rport_id = num; -- break; -- } -+ rport = strstr(pp->sysdev->devpath, "rport"); -+ if (!rport || sscanf(rport, "rport-%d:%d-%d/%*s", -+ &host, &rport_channel, &rport_id) != 3) { -+ condlog(3, "%s: Invalid devpath %s", -+ pp->dev, pp->sysdev->devpath); -+ return 1; - } - - if (rport_channel < 0 && rport_id < 0) { -- condlog(1, "No rport found"); -+ condlog(3, "%s: No rport found", pp->dev); - return 0; - } - -+ condlog(4, "%s: using rport-%d:%d-%d for target%d:%d:%d", pp->dev, -+ host, rport_channel, rport_id, -+ pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id); -+ - if (safe_sprintf(attr_path, - "/class/fc_remote_ports/rport-%d:%d-%d", -- pp->sg_id.host_no, rport_channel, rport_id)) { -- condlog(0, "attr_path too small"); -+ host, rport_channel, rport_id)) { -+ condlog(1, "attr_path too small"); - return 0; - } - -+ condlog(4, "%s: set dev_loss_tmo to %d, fast_io_fail to %d", -+ pp->dev, dev_loss_tmo, fast_io_fail_tmo); -+ - if (dev_loss_tmo < 0) - sprintf(attr_value, "%d", 0); - else - sprintf(attr_value, "%d", dev_loss_tmo); - num = sysfs_attr_set_value(attr_path, "dev_loss_tmo", - attr_value, strlen(attr_value)); -- if (num > 0) -- condlog(4, "%s: set dev_loss_tmo to %d", pp->dev, -- dev_loss_tmo); -- else -+ if (num <= 0) - condlog(4, "%s: failed to set dev_loss_tmo (%d)", - pp->dev, errno); - -@@ -303,10 +275,7 @@ sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo) - sprintf(attr_value, "%d", fast_io_fail_tmo); - num = sysfs_attr_set_value(attr_path, "fast_io_fail_tmo", - attr_value, strlen(attr_value)); -- if (num > 0) -- condlog(4, "%s: set fast_io_fail_tmo to %d", pp->dev, -- fast_io_fail_tmo); -- else -+ if (num <= 0) - condlog(4, "%s: failed to set fast_io_fail_tmo (%d)", - pp->dev, errno); - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 1632c9d..6cc7a93 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -479,12 +479,16 @@ verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec) - free_path(pp); - } - } else { -- if (pp->hwe) -- sysfs_set_fc_values(pp, pp->hwe->dev_loss_tmo, -- pp->hwe->fast_io_fail_tmo); -- else -- sysfs_set_fc_values(pp, conf->dev_loss_tmo, -- conf->fast_io_fail_tmo); -+ int dev_loss_tmo = conf->dev_loss_tmo; -+ int fast_io_fail_tmo = conf->fast_io_fail_tmo; -+ -+ if (pp->hwe && pp->hwe->dev_loss_tmo > 0) -+ dev_loss_tmo = pp->hwe->dev_loss_tmo; -+ if (pp->hwe && pp->hwe->fast_io_fail_tmo > 0) -+ fast_io_fail_tmo = pp->hwe->fast_io_fail_tmo; -+ -+ sysfs_set_fc_values(pp, dev_loss_tmo, -+ fast_io_fail_tmo); - condlog(4, "%s: verified path %s dev_t %s", - mpp->alias, pp->dev, pp->dev_t); - } diff --git a/multipath-tools-update-hp-hwtable b/multipath-tools-update-hp-hwtable deleted file mode 100644 index c3a56dd..0000000 --- a/multipath-tools-update-hp-hwtable +++ /dev/null @@ -1,128 +0,0 @@ -commit 73af31edbba5588dafce75fa8267b14f36b545b0 -Author: Hannes Reinecke -Date: Tue Nov 11 13:44:09 2008 +0100 - - Update hardware table for new HP arrays - - References: 442133 - - Signed-off-by: Vijayakumar Balasubramanian - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index fda131c..bf8c611 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -122,7 +122,7 @@ static struct hwentry default_hw[] = { - .pgfailback = FAILBACK_UNDEF, - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = 12, -- .minio = DEFAULT_MINIO, -+ .minio = 100, - .checker_name = HP_SW, - .prio_name = PRIO_HP_SW, - }, -@@ -138,26 +138,11 @@ static struct hwentry default_hw[] = { - .pgfailback = -FAILBACK_IMMEDIATE, - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = 12, -- .minio = DEFAULT_MINIO, -+ .minio = 100, - .checker_name = TUR, - .prio_name = PRIO_ALUA, - }, - { -- .vendor = "HP", -- .product = "MSA2000s*", -- .getuid = "/sbin/cciss_id %n", -- .features = DEFAULT_FEATURES, -- .hwhandler = DEFAULT_HWHANDLER, -- .selector = DEFAULT_SELECTOR, -- .pgpolicy = GROUP_BY_PRIO, -- .pgfailback = -FAILBACK_IMMEDIATE, -- .rr_weight = RR_WEIGHT_NONE, -- .no_path_retry = 12, -- .minio = DEFAULT_MINIO, -- .checker_name = TUR, -- .prio_name = DEFAULT_PRIO, -- }, -- { - /* EVA 3000/5000 with new firmware, EVA 4000/6000/8000 */ - .vendor = "(COMPAQ|HP)", - .product = "HSV1[01]1|HSV2[01]0|HSV300", -@@ -169,14 +154,14 @@ static struct hwentry default_hw[] = { - .pgfailback = -FAILBACK_IMMEDIATE, - .rr_weight = RR_WEIGHT_NONE, - .no_path_retry = 12, -- .minio = DEFAULT_MINIO, -+ .minio = 100, - .checker_name = TUR, - .prio_name = PRIO_ALUA, - }, - { -- /* HP MSA2000 product family */ -+ /* HP MSA2000 product family with old firmware */ - .vendor = "HP", -- .product = "MSA2[02]12*", -+ .product = "MSA2[02]12fc|MSA2012i", - .getuid = DEFAULT_GETUID, - .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, -@@ -184,12 +169,46 @@ static struct hwentry default_hw[] = { - .pgpolicy = MULTIBUS, - .pgfailback = -FAILBACK_IMMEDIATE, - .rr_weight = RR_WEIGHT_NONE, -- .no_path_retry = 12, -- .minio = DEFAULT_MINIO, -+ .no_path_retry = 18, -+ .minio = 100, - .checker_name = TUR, - .prio_name = DEFAULT_PRIO, - }, - { -+ /* HP MSA2000 product family with new firmware */ -+ .vendor = "HP", -+ .product = "MSA2012sa|MSA23(12|24)(fc|i|sa)", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = DEFAULT_HWHANDLER, -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = 18, -+ .minio = 100, -+ .checker_name = TUR, -+ .prio_name = PRIO_ALUA, -+ }, -+ -+ { -+ /* HP SVSP */ -+ .vendor = "HP", -+ .product = "HSVX700", -+ .getuid = DEFAULT_GETUID, -+ .features = DEFAULT_FEATURES, -+ .hwhandler = "1 alua", -+ .selector = DEFAULT_SELECTOR, -+ .pgpolicy = GROUP_BY_PRIO, -+ .pgfailback = -FAILBACK_IMMEDIATE, -+ .rr_weight = RR_WEIGHT_NONE, -+ .no_path_retry = 12, -+ .minio = 100, -+ .checker_name = TUR, -+ .prio_name = PRIO_ALUA, -+ }, -+ -+ { - /* HP Smart Array */ - .vendor = "HP", - .product = "LOGICAL VOLUME.*", -@@ -294,7 +313,7 @@ static struct hwentry default_hw[] = { - .vendor = "(HITACHI|HP)", - .product = "OPEN-.*", - .getuid = DEFAULT_GETUID, -- .features = "1 queue_if_no_path", -+ .features = DEFAULT_FEATURES, - .hwhandler = DEFAULT_HWHANDLER, - .selector = DEFAULT_SELECTOR, - .pgpolicy = MULTIBUS, diff --git a/multipath-tools-update-sdev_state-handling b/multipath-tools-update-sdev_state-handling deleted file mode 100644 index 303f833..0000000 --- a/multipath-tools-update-sdev_state-handling +++ /dev/null @@ -1,123 +0,0 @@ -commit bff69e33ca279de49c5cebc33107c99cbf2c4bea -Author: Hannes Reinecke -Date: Wed Jan 21 14:59:30 2009 +0100 - - Fix up sdev_state handling - - Before trying to access any path checker of priority callouts we - really should check the sdev state; only when in 'running' the - callout is likely to succeed. So modify the handling to properly - check the sdev_state and return a proper error for failure state. - - References: 458393 - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index c37247a..c09e7ed 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -661,6 +661,44 @@ common_sysfs_pathinfo (struct path * pp, struct sysfs_device *dev) - return 0; - } - -+static int sysfs_get_sdev_state(struct path *pp) -+{ -+ struct sysfs_device *parent; -+ char dev_state[32]; -+ -+ /* check device state */ -+ if (!pp->sysdev) { -+ condlog(3, "%s: no sysfs device", pp->dev); -+ return PATH_WILD; -+ } -+ parent = sysfs_device_get_parent(pp->sysdev); -+ if (!parent) { -+ condlog(3, "%s: no parent for '%s'", -+ pp->dev, pp->sysdev->devpath); -+ return PATH_WILD; -+ } -+ if (!strncmp(parent->kernel, "block", 5)) { -+ parent = sysfs_device_get_parent(parent); -+ } -+ if (!parent) { -+ condlog(3, "%s: no block device for '%s'", -+ pp->dev, parent->devpath); -+ return PATH_WILD; -+ } -+ if (!sysfs_get_state(parent, dev_state, 32)) { -+ if (!strncmp(dev_state, "blocked", 7)) { -+ condlog(3, "%s: device blocked", pp->dev); -+ return PATH_UNCHECKED; -+ } else if (!strncmp(dev_state, "running", 7)) { -+ return PATH_UP; -+ } -+ condlog(3, "%s: device in state %s", -+ pp->dev, dev_state); -+ return PATH_DOWN; -+ } -+ return PATH_WILD; -+} -+ - struct sysfs_device *sysfs_device_from_path(struct path *pp) - { - char sysdev[FILE_NAME_SIZE]; -@@ -762,20 +800,12 @@ get_state (struct path * pp) - condlog(3, "%s: get_state", pp->dev); - - if (pp->bus == SYSFS_BUS_SCSI && pp->sysdev) { -- struct sysfs_device *parent; -- char dev_state[32]; -- -- /* check device state */ -- parent = sysfs_device_get_parent(pp->sysdev); -- if (parent && !strncmp(parent->kernel, "block", 5)) -- parent = sysfs_device_get_parent(parent); -- if (parent && !sysfs_get_state(parent, dev_state, 32)) { -- if (!strncmp(dev_state, "blocked", 7)) { -- condlog(3, "%s: device blocked", pp->dev); -- pp->state = PATH_DOWN; -- pp->priority = 0; -- return 0; -- } -+ /* Check the sdev state before accessing it */ -+ pp->state = sysfs_get_sdev_state(pp); -+ if (pp->state == PATH_UNCHECKED || pp->state == PATH_DOWN) { -+ /* Further checking pointless */ -+ pp->priority = 0; -+ return 0; - } - } - if (!checker_selected(c)) { -@@ -801,23 +831,17 @@ get_state (struct path * pp) - static int - get_prio (struct path * pp) - { -+ int path_state; -+ - if (!pp) - return 0; - -- if (pp->bus == SYSFS_BUS_SCSI && pp->sysdev) { -- struct sysfs_device *parent; -- char dev_state[32]; -- -- /* check device state */ -- parent = sysfs_device_get_parent(pp->sysdev); -- if (parent && !strncmp(parent->kernel, "block", 5)) -- parent = sysfs_device_get_parent(parent); -- if (parent && !sysfs_get_state(parent, dev_state, 32)) { -- if (!strncmp(dev_state, "blocked", 7)) { -- condlog(3, "%s: device blocked", pp->dev); -- pp->priority = PRIO_UNDEF; -- return 0; -- } -+ if (pp->bus == SYSFS_BUS_SCSI) { -+ /* Check the sdev state before accessing it */ -+ path_state = sysfs_get_sdev_state(pp); -+ if (path_state == PATH_DOWN || path_state == PATH_UNCHECKED) { -+ pp->priority = PRIO_UNDEF; -+ return 0; - } - } - diff --git a/multipath-tools-use-MALLOC-FREE-for-checker b/multipath-tools-use-MALLOC-FREE-for-checker deleted file mode 100644 index 065ff65..0000000 --- a/multipath-tools-use-MALLOC-FREE-for-checker +++ /dev/null @@ -1,62 +0,0 @@ -From 0f7c86b8ba073570acc7fa31c9f52adc2cf4ac8f Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 8 Jan 2009 09:12:36 +0100 -Subject: [PATCH] Use MALLOC/FREE for checker and prio allocation - -We should be using the proper defines for malloc/free to -ease tracking of memory leaks. - -Signed-off-by: Konrad Rzeszutek -Signed-off-by: Hannes Reinecke ---- - libmultipath/checkers.c | 4 ++-- - libmultipath/prio.c | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c -index 231b408..45ef531 100644 ---- a/libmultipath/checkers.c -+++ b/libmultipath/checkers.c -@@ -38,7 +38,7 @@ struct checker * alloc_checker (void) - { - struct checker *c; - -- c = zalloc(sizeof(struct checker)); -+ c = MALLOC(sizeof(struct checker)); - if (c) - INIT_LIST_HEAD(&c->node); - return c; -@@ -54,7 +54,7 @@ void free_checker (struct checker * c) - c->name, dlerror()); - } - } -- free(c); -+ FREE(c); - } - - void cleanup_checkers (void) -diff --git a/libmultipath/prio.c b/libmultipath/prio.c -index 1b9f51b..5e01f54 100644 ---- a/libmultipath/prio.c -+++ b/libmultipath/prio.c -@@ -22,7 +22,7 @@ struct prio * alloc_prio (void) - { - struct prio *p; - -- p = zalloc(sizeof(struct prio)); -+ p = MALLOC(sizeof(struct prio)); - if (p) - INIT_LIST_HEAD(&p->node); - return p; -@@ -38,7 +38,7 @@ void free_prio (struct prio * p) - p->name, dlerror()); - } - } -- free(p); -+ FREE(p); - } - - void cleanup_prio(void) --- -1.6.0.2 - diff --git a/multipath-tools-use-default-for-dev_loss_tmo b/multipath-tools-use-default-for-dev_loss_tmo deleted file mode 100644 index eda2491..0000000 --- a/multipath-tools-use-default-for-dev_loss_tmo +++ /dev/null @@ -1,58 +0,0 @@ -commit 9751659f37b9bf19ece7849e7186f67a6760c31a -Author: Hannes Reinecke -Date: Thu Jan 15 12:01:33 2009 +0100 - - Use defaults for dev_loss_tmo and fast_io_fail_tmo - - We should be using some sensible defaults. So using '10' for - dev_loss_tmo and '5' for fast_io_fail_tmo. - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index ea7ad99..58485c6 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -463,8 +463,8 @@ load_config (char * file) - conf->dev_type = DEV_NONE; - conf->minio = 1000; - conf->max_fds = 0; -- conf->dev_loss_tmo = 0; -- conf->fast_io_fail_tmo = 0; -+ conf->dev_loss_tmo = DEFAULT_DEV_LOSS_TMO; -+ conf->fast_io_fail_tmo = DEFAULT_FAST_IO_FAIL; - conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR); - - /* -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index a943673..4a55ff9 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -12,6 +12,8 @@ - #define DEFAULT_PGTIMEOUT -PGTIMEOUT_NONE - #define DEFAULT_USER_FRIENDLY_NAMES 0 - #define DEFAULT_VERBOSITY 2 -+#define DEFAULT_DEV_LOSS_TMO 10 -+#define DEFAULT_FAST_IO_FAIL 5 - - #define DEFAULT_CHECKINT 5 - #define MAX_CHECKINT(a) (a << 2) -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index 926ff69..d29a3b6 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -265,12 +265,12 @@ The full pathname of the binding file to be used when the user_friendly_names op - .I /var/lib/multipath/bindings - .TP - .B dev_loss_tmo --The default dev_loss_tmo setting for an FC remote port in seconds. If an rport has vanished from the fabric all devices on that port will be removed from sysfs after this timeout. -+The default dev_loss_tmo setting for an FC remote port in seconds. If an rport has vanished from the fabric all devices on that port will be removed from sysfs after this timeout. Default is 10. - .TP - .B fast_io_fail_tmo - The default fast_io_fail_tmo setting for an FC remote port in seconds. If an rport has vanished from the fabric all I/O to the devices on that port will be terminated after this timeout. Should be smaller than - .B dev_loss_tmo --setting. -+setting. Default is 5. - . - .SH "blacklist section" - The diff --git a/multipath-tools-use-pthread_join b/multipath-tools-use-pthread_join deleted file mode 100644 index e20ace2..0000000 --- a/multipath-tools-use-pthread_join +++ /dev/null @@ -1,31 +0,0 @@ -From c61cebec5c538a95cf641984357259dc616e5760 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Wed, 29 Oct 2008 13:54:36 +0100 -Subject: [PATCH] multipathd crashes on shutdown - -And again pthread programming has proven to be difficult. -We really should wait for the thread to actually exit before -continuing and free up all of its resources. - -References: 437245 - -Signed-off-by: Hannes Reinecke ---- - libmultipath/log_pthread.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c -index 5a97db6..9e9aebe 100644 ---- a/libmultipath/log_pthread.c -+++ b/libmultipath/log_pthread.c -@@ -83,6 +83,7 @@ void log_thread_stop (void) - pthread_mutex_lock(logq_lock); - pthread_cancel(log_thr); - pthread_mutex_unlock(logq_lock); -+ pthread_join(log_thr, NULL); - - flush_logqueue(); - --- -1.5.4.5 - diff --git a/multipath-tools-use-sys-dev b/multipath-tools-use-sys-dev deleted file mode 100644 index 041ad35..0000000 --- a/multipath-tools-use-sys-dev +++ /dev/null @@ -1,103 +0,0 @@ -From 734cf32be1f4bf3fa57bbdcc83147f92c4199b54 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Thu, 20 Nov 2008 09:00:39 +0100 -Subject: [PATCH] Use /sys/dev for reverse lookup - -Newer kernels provide /sys/dev for reverse lookup of major:minor -numbers. Also some error checking is in order here. - -Signed-off-by: Hannes Reinecke ---- - libmultipath/discovery.c | 35 ++++++++++++++++++++++++++++++----- - 1 files changed, 30 insertions(+), 5 deletions(-) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 20d0684..56186bd 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -152,11 +152,11 @@ sysfs_get_dev (struct sysfs_device * dev, char * buff, size_t len) - - attr = sysfs_attr_get_value(dev->devpath, "dev"); - if (!attr) { -- condlog(3, "%s: no 'dev' attribute in sysfs", dev->kernel); -+ condlog(3, "%s: no 'dev' attribute in sysfs", dev->devpath); - return 1; - } - if (strlcpy(buff, attr, len) != strlen(attr)) { -- condlog(3, "%s: overflow in 'dev' attribute", dev->kernel); -+ condlog(3, "%s: overflow in 'dev' attribute", dev->devpath); - return 2; - } - return 0; -@@ -169,13 +169,18 @@ sysfs_get_size (struct sysfs_device * dev, unsigned long long * size) - int r; - - attr = sysfs_attr_get_value(dev->devpath, "size"); -- if (!attr) -+ if (!attr) { -+ condlog(3, "%s: No size attribute in sysfs", dev->devpath); - return 1; -+ } - - r = sscanf(attr, "%llu\n", size); - -- if (r != 1) -+ if (r != 1) { -+ condlog(3, "%s: Cannot parse size attribute '%s'", -+ dev->devpath, attr); - return 1; -+ } - - return 0; - } -@@ -232,12 +237,30 @@ devt2devname (char *devname, char *devt) - char block_path[FILE_NAME_SIZE]; - struct stat statbuf; - -- memset(block_path, 0, FILE_NAME_SIZE); - if (sscanf(devt, "%u:%u", &major, &minor) != 2) { - condlog(0, "Invalid device number %s", devt); - return 1; - } - -+ sprintf(block_path,"/sys/dev/%u:%u", major, minor); -+ if (stat(block_path, &statbuf) == 0) { -+ /* Newer kernels have /sys/dev */ -+ if (S_ISLNK(statbuf.st_mode) && -+ readlink(block_path, dev, FILE_NAME_SIZE) > 0) { -+ char *p = strrchr(dev, '/'); -+ -+ if (!p) { -+ condlog(0, "No sysfs entry for %s\n", -+ block_path); -+ return 1; -+ } -+ p++; -+ strncpy(devname, p, FILE_NAME_SIZE); -+ return 0; -+ } -+ } -+ memset(block_path, 0, FILE_NAME_SIZE); -+ - if (!(fd = fopen("/proc/partitions", "r"))) { - condlog(0, "Cannot open /proc/partitions"); - return 1; -@@ -271,6 +294,7 @@ devt2devname (char *devname, char *devt) - condlog(0, "sysfs entry %s is not a directory\n", block_path); - return 1; - } -+ strncpy(devname, dev, FILE_NAME_SIZE); - return 0; - } - -@@ -291,6 +315,7 @@ do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, - inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); - inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff); - memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); -+ memset(sense_b, 0, SENSE_BUFF_LEN); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof (inqCmdBlk); - io_hdr.mx_sb_len = sizeof (sense_b); --- -1.5.3.2 - diff --git a/multipath-tools-zero-lines-in-print.c b/multipath-tools-zero-lines-in-print.c deleted file mode 100644 index 656a2dd..0000000 --- a/multipath-tools-zero-lines-in-print.c +++ /dev/null @@ -1,40 +0,0 @@ -commit 8fe887aa6875dfbb5057c9b1e4e8c91445700de5 -Author: Hannes Reinecke -Date: Fri Nov 14 10:02:56 2008 +0100 - - libmultipath: zero out lines in print.c - - static declaration of line within a function doesn't place them in - the bss segment, hence they are not zeroed automatically. - Gives funny effects occasionally. - - Signed-off-by: Hannes Reinecke - -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 6d80248..46ae2ec 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -1246,6 +1246,7 @@ print_path (struct path * pp, char * style) - { - char line[MAX_LINE_LEN]; - -+ memset(&line[0], 0, MAX_LINE_LEN); - snprint_path(&line[0], MAX_LINE_LEN, style, pp); - printf("%s", line); - } -@@ -1255,6 +1256,7 @@ print_multipath (struct multipath * mpp, char * style) - { - char line[MAX_LINE_LEN]; - -+ memset(&line[0], 0, MAX_LINE_LEN); - snprint_multipath(&line[0], MAX_LINE_LEN, style, mpp); - printf("%s", line); - } -@@ -1264,6 +1266,7 @@ print_pathgroup (struct pathgroup * pgp, char * style) - { - char line[MAX_LINE_LEN]; - -+ memset(&line[0], 0, MAX_LINE_LEN); - snprint_pathgroup(&line[0], MAX_LINE_LEN, style, pgp); - printf("%s", line); - } diff --git a/multipath-tools.changes b/multipath-tools.changes index 62db643..94972eb 100644 --- a/multipath-tools.changes +++ b/multipath-tools.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Fri Aug 21 15:49:47 CEST 2009 - hare@suse.de + +- Update to latest upstream git version +- Merge in SLES11 fixes +- Build package from git tree +- Implement '-u' option for kpartx (bnc#517442) + ------------------------------------------------------------------- Fri Jun 19 10:35:46 CEST 2009 - coolo@novell.com diff --git a/multipath-tools.spec b/multipath-tools.spec index c87d7ab..c0657a5 100644 --- a/multipath-tools.spec +++ b/multipath-tools.spec @@ -21,80 +21,17 @@ Name: multipath-tools BuildRequires: device-mapper-devel libaio-devel readline-devel Url: http://christophe.varoqui.free.fr/ -License: BSD 3-clause (or similar) ; GPL v2 or later ; LGPL v2.1 or later ; Public Domain, Freeware ; MIT License (or similar) +License: BSD 3-clause (or similar) ; GPL v2 or later ; LGPL v2.1 or later ; Public Domain, Freeware ; MIT License (or similar) Group: System/Base Requires: device-mapper kpartx -PreReq: %insserv_prereq %fillup_prereq coreutils grep diffutils +PreReq: %insserv_prereq %fillup_prereq coreutils grep AutoReqProv: on Version: 0.4.8 -Release: 41 +Release: 42 Summary: Tools to Manage Multipathed Devices with the device-mapper Source: multipath-tools-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build -Patch0: %{name}-git-update -Patch1: %{name}-sles11-alpha1-update -Patch2: %{name}-sles11-alpha3-update -Patch3: %{name}-check-get_inq-return-values -Patch4: %{name}-implement-map-resize -Patch5: %{name}-add-show-status-cmd -Patch6: %{name}-add-compellent-hwtable-entry -Patch7: %{name}-increase-bindings-file-lock-timeout -Patch8: %{name}-fixes-for-show-paths-format -Patch9: %{name}-add-show-wildcards-cmd -Patch10: %{name}-fopen-returns-NULL -Patch11: %{name}-read-verbosity-level-from-conf -Patch12: %{name}-kpartx-doesnt-remove-loop-device -Patch13: %{name}-missing-fixes-for-ontap -Patch14: %{name}-add-IBM-storage-to-hwtable -Patch15: %{name}-increase-loop-buffer-size -Patch16: %{name}-include-device-handler-modules -Patch17: %{name}-use-pthread_join -Patch18: %{name}-fixup-scsi_id-for-cciss -Patch19: %{name}-sysfs-subdir-reformat -Patch20: %{name}-dont-check-valid-context-in-get_state -Patch21: %{name}-link-directio-against-libaio -Patch22: %{name}-check-for-empty-mpvecs -Patch23: %{name}-dmraid-uuid-in-uppercase -Patch24: %{name}-handle-arguments-from-init-file -Patch25: %{name}-update-hp-hwtable -Patch26: %{name}-zero-lines-in-print.c -Patch27: %{name}-sles11-valgrind-fixes -Patch28: %{name}-adapt-to-new-sysfs-layout -Patch29: %{name}-basename-return-value -Patch30: %{name}-always-allocate-alias -Patch31: %{name}-use-sys-dev -Patch32: %{name}-rework-sysfs-device-handling -Patch33: %{name}-search-for-correct-hwe -Patch34: %{name}-make-params-local -Patch35: %{name}-allow-zero-paths -Patch36: %{name}-prio-weightedpath -Patch37: %{name}-crash-in-update-multipath -Patch38: %{name}-split-off-IBM-ESS -Patch39: %{name}-reload-map-for-ro-changes -Patch40: %{name}-set-max_fds-parameter-for-multipath -Patch41: %{name}-enhance-error-for-checkers -Patch42: %{name}-fix-weightedpath-merge-error -Patch43: %{name}-remove-kdev_t -Patch44: %{name}-add-missing-unlock-on-exit -Patch45: %{name}-fix-sysfs_attr_get_value -Patch46: %{name}-more-debugging-output -Patch47: %{name}-use-MALLOC-FREE-for-checker -Patch48: %{name}-do-not-reinitialize-prio-and-checker-list -Patch49: %{name}-display-checker-name-on-failure -Patch50: %{name}-dont-run-checkers-for-blocked-devices -Patch51: %{name}-implement-sysfs-attr-set-value -Patch52: %{name}-implement-dev_loss_tmo -Patch53: %{name}-use-default-for-dev_loss_tmo -Patch54: %{name}-print-dm-tables -Patch55: %{name}-shuffle-memarea-init -Patch56: %{name}-start-xdr_setsite -Patch57: %{name}-add-new-MSA-to-hwtable -Patch58: %{name}-quote-variable-in-mkinitrd-setup -Patch59: %{name}-update-dev_loss_tmo-handling -Patch60: %{name}-fix-directio-error-messages -Patch61: %{name}-update-sdev_state-handling -Patch62: %{name}-check-vector-defines -Patch63: %{name}-dont-access-blocked-devices-in-checkerloop +Patch0: %{name}-%{version}-opensuse-11.2.diff.bz2 %description This package provides the tools to manage multipathed devices by @@ -118,7 +55,7 @@ Authors: Christophe Varoqui %package -n kpartx -License: BSD 3-clause (or similar) ; GPL v2 or later ; LGPL v2.1 or later ; Public Domain, Freeware ; MIT License (or similar) +License: BSD 3-clause (or similar) ; GPL v2 or later ; LGPL v2.1 or later ; Public Domain, Freeware ; MIT License (or similar) Summary: Manages partition tables on device-mapper devices Group: System/Base Requires: device-mapper @@ -136,69 +73,6 @@ Authors: %prep %setup -n multipath-tools-%{version} %patch0 -p1 -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 -%patch25 -p1 -%patch26 -p1 -%patch27 -p1 -%patch28 -p1 -%patch29 -p1 -%patch30 -p1 -%patch31 -p1 -%patch32 -p1 -%patch33 -p1 -%patch34 -p1 -%patch35 -p1 -%patch36 -p1 -%patch37 -p1 -%patch38 -p1 -%patch39 -p1 -%patch40 -p1 -%patch41 -p1 -%patch42 -p1 -%patch43 -p1 -%patch44 -p1 -%patch45 -p1 -%patch46 -p1 -%patch47 -p1 -%patch48 -p1 -%patch49 -p1 -%patch50 -p1 -%patch51 -p1 -%patch52 -p1 -%patch53 -p1 -%patch54 -p1 -%patch55 -p1 -%patch56 -p1 -%patch57 -p1 -%patch58 -p1 -%patch59 -p1 -%patch60 -p1 -%patch61 -p1 -%patch62 -p1 -%patch63 -p1 %build # This package failed when testing with -Wl,-as-needed being default. @@ -235,7 +109,8 @@ exit 0 %config /etc/init.d/multipathd %config /etc/init.d/boot.multipath %config /etc/udev/rules.d/71-multipath.rules -/lib/multipath +/%{_lib}/libmultipath.so +/%{_lib}/multipath /sbin/multipath /sbin/multipathd %attr (0700, root, root) /var/cache/multipath @@ -263,327 +138,3 @@ exit 0 %{_mandir}/man8/kpartx.8* %changelog -* Fri Jun 19 2009 coolo@novell.com -- disable as-needed for this package as it fails to build with it -* Mon Jan 26 2009 hare@suse.de -- Don't access blocked devices in checkerloop() -- Check for validity in VECTOR_XXX defines (bnc#469269,bnc#457465) -* Fri Jan 23 2009 hare@suse.de -- Update dev_loss_tmo handling (bnc#458393) -- Fix directio error messages -- Update sdev_state handling -* Mon Jan 19 2009 hare@suse.de -- Add new HP machines to hardware table (bnc#442133) -- Print device-mapper tables for debugging -- Properly quote variables in mkinitrd scripts (bnc#447966) -- shuffle call to memarea_init -- Add xdr_setsite in init scripts (bnc#459529) -* Tue Jan 13 2009 hare@suse.de -- Do not run checkers or prioritizers on blocked devices - (bnc#464155) -- Implement dev_loss_tmo and fast_io_fail_tmo (bnc#464155) -- Use default values for dev_loss_tmo and fast_io_fail_tmo -- Display checker and prio name on failure -- Add more debugging output -* Mon Jan 12 2009 hare@suse.de -- Set max_fds setting for multipath (bnc#457443) -- Enhance error messages for checker and prio loading (bnc#456214) -- Fix merge errors for prio_weightedpath (bnc#441007) -- Fix sysfs_attr_get_value (bnc#456747) -- Do not reinitialize prio and checker lists after config file - has been parsed (bnc#464373) -- Minor cleanups -* Thu Dec 04 2008 hare@suse.de -- Split off IBM ESS hwtable entries (bnc#439763) -- Reload map when device R/O setting changes (bnc#440959) -* Fri Nov 21 2008 hare@suse.de -- Add 'Weighted Paths' prioritizer (bnc#441007) -- Fix crashes in update_multipath -* Thu Nov 20 2008 hare@suse.de -- Valgrind fixes - * Add missing initialisation - * Always allocate memory for alias - * Check return value of basename -- Adapt to new sysfs layout (bnc#435215, bnc#445041) -- Use /sys/dev to speedup reverse lookups -- Rework sysfs device handling (bnc#435215, bnc#438031) -- Search for correct hardware entry during reconfigure (bnc#435688) -- Use local variables for device mapper params -- Allow zero paths for multipath maps -* Mon Nov 17 2008 hare@suse.de -- Update HP hardware table (bnc#442133) -- Zero out lines in print.c (bnc#445023) -* Mon Nov 10 2008 hare@suse.de -- Check for empty mpvecs in mpvec_garbage_collector() (bnc#437245) -- dmraid uuid starts with 'DMRAID' (bnc#439439) -- Handle arguments to multipathd from the init file -* Thu Nov 06 2008 ro@suse.de -- commenting multiline rpm macros is dangerous (read broken) - remove percent sign in commented macro lines -* Mon Nov 03 2008 hare@suse.de -- Use pthread_join() during shutdown to avoid crash (bnc#437245) -- Fixup '%%n' to handle '!' kernel device name syntax (bnc#435172) -- Use correct commandline for cciss scsi_id callouts (bnc#435172) -- Do not check for valid mp context in get_state() (bnc#433659) -- Link directio checker against libaio (bnc#433659) -- Use regmatch when checking for duplicates in hwtable (bnc#439763) -* Mon Oct 27 2008 hare@suse.de -- Patches from mainline: - * Increase bindings file lock timeout - * Fixes for 'show paths format' - * Add 'show wildcards' cli cmd - * Add support for IBM storage devices -- fopen() returns NULL on failure (bnc#432598) -- Read verbosity level from configuration file (bnc#388284) -- kpartx -l does not remove it's loop device (bnc#417266) -- Missing fixes for libprio ontap.c (bnc#426975) -- Increase buffer size in find_loop_by_file (bnc#436428) -- Include SCSI device handler modules for initrd (bnc#431877) -* Fri Sep 26 2008 hare@suse.de -- Implement map resize (FATE#302007) -- Handle cciss devices correctly (bnc#419123) -* Wed Sep 24 2008 ro@suse.de -- use udevadm info instead of udevinfo -* Wed Sep 03 2008 hare@suse.de -- Merge in fixes from upstream: - * Add IBM IPR to hardware table (bnc#419086) - * Add IBM DS4300 to hardware table - * Fix settings for scsi_id changes -- Call mkinitrd_setup during %%post and %%postun (bnc#413709) -* Thu Aug 28 2008 ro@suse.de -- fix init scripts -* Wed Jul 23 2008 hare@suse.de -- Update to version 0.4.8 -- Include changes from SLES10 -- Include mkinitrd scriptlets -* Wed May 28 2008 hare@suse.de -- Calculate correct partition offset in kpartx (bnc#394658) -* Fri May 09 2008 hare@suse.de -- Fixup kpartx rules (bnc#387667) -* Tue Apr 29 2008 hare@suse.de -- Merge in fixes from upstream -- Merge fixes from SLES10 SP2 -* Wed Sep 19 2007 hare@suse.de -- Fixup generated dm_linear udev rules (#218122) -* Thu Aug 30 2007 hare@suse.de -- Rework dm_linear; udev rules should only be - created if the feature was activated (#302422) -* Fri Aug 10 2007 hare@suse.de -- Implement dm_linear (#218122) -* Thu Aug 02 2007 hare@suse.de -- Merge in latest fixes from upstream -- Remove local patches; merge with upstream -- Fix kpartx handling of extended partitions -- Use underscores for partition names (#293792) -* Mon May 21 2007 hare@suse.de -- Rework udev handling -- Split off kpartx package -* Mon May 14 2007 hare@suse.de -- Merge in latest fixes from upstream -- Add all SuSE specific files to git repository. -* Fri May 11 2007 hare@suse.de -- Include latest changes from upstream -- Remove libsysfs (242766) -- Handle extended partitions for kpartx -* Mon Dec 04 2006 dmueller@suse.de -- don't build as root -* Fri Nov 17 2006 hare@suse.de -- integrate upstream fixes -- update udev rule for YaST2 dmraid support (217807]) -* Mon Nov 06 2006 hare@suse.de -- Really fixup udev rule (216167). -* Fri Oct 20 2006 ro@suse.de -- make it build -* Mon Sep 25 2006 hare@suse.de -- update to latest fixes from git tree -- remove fixes integrated in upstream -- fixup udev rule (#203688) -* Thu Sep 14 2006 ro@suse.de -- use device-mapper-devel in BuildRequires -* Thu Aug 31 2006 hare@suse.de -- include latest fixes from git tree -- update kpartx_id and udev rules to work - with dmraid. -- Fix return value for multipath -l -* Thu Aug 17 2006 ro@suse.de -- workaround problem in git-patch - normal patch can't do a "rename", so copy file first -* Tue Jul 11 2006 hare@suse.de -- Update to official version 0.4.7 -- Refactor git update to apply to 0.4.7 -* Wed Jun 28 2006 hare@suse.de -- Remove blacklisting of dasd device node, - use product_blacklist instead (#188688) -* Mon Jun 12 2006 hare@suse.de -- Add 72-multipath-compat.rules to create 'by-name' - symlink again for compability (#183663) -* Fri Jun 02 2006 hare@suse.de -- Merge in fixed from upstream - - Set device-mapper name correctly (#181127) -* Thu Jun 01 2006 hare@suse.de -- Merge in fixes from upstream - - Fixup aliasing handling - - Fix string length in pp_alua -- Use correct regexp patterns for hwtable (#177842) -- Fixup 71-multipath.rules to work correctly with the - updated device-mapper online/offline events (#176516 - LTC23961) -- Add kpartx_id for the updated 71-multipath.rules -* Mon May 22 2006 schwab@suse.de -- Don't strip binaries. -* Tue May 02 2006 hare@suse.de -- Merge in fixes from upstream - - Merged local patches - - Added hds_modular prioritizer -- Remove merged patches -- Allow for setting of maximum number of open files (#149979) -- Implement 'stop' for init scripts -* Mon Apr 10 2006 hare@suse.de -- Lowering priority for pp_tpc -- Split off DS6000 to fixup priority handler (#161347) -* Wed Apr 05 2006 hare@suse.de -- Disable debug messages in pp_tpc. -* Wed Mar 29 2006 hare@suse.de -- Explicitely create partitions at boot time (#159927) -* Thu Mar 23 2006 hare@suse.de -- Add hwtable entry for IBM 3526. -* Tue Mar 14 2006 hare@suse.de -- Fix another typo in mpath_id. -* Tue Mar 14 2006 hare@suse.de -- Fix typo in mpath_id. -* Mon Mar 13 2006 hare@suse.de -- Fix autobuild warnings. -- Include some minor fixed from upstream. -* Thu Mar 09 2006 hare@suse.de -- Add mpath_id program to call kpartx only on multipathed - devices (#149995 - LTC21557). -- Include latest fixes from upstream. -* Wed Feb 08 2006 hare@suse.de -- Add device blacklisting (#85778) -- Further manpage installation fixes (#146179, #147053, #147911) -* Wed Jan 25 2006 mls@suse.de -- converted neededforbuild to BuildRequires -* Thu Jan 19 2006 hare@suse.de -- Fix manpage installation. -* Tue Jan 17 2006 hare@suse.de -- Include latest git fixes -- Remove old patches which are now upstream -- Add new hwtable entry for shark (#142176) -* Fri Dec 16 2005 hare@suse.de -- Fix dependencies for /etc/init.d/boot.multipath -- Fix kpartx rules to generate proper partition names. -* Wed Dec 07 2005 hare@suse.de -- Update to multipath-tools-0.4.6 -- Include latest git fixes -- Port patches from SLES9 SP3 -* Mon Oct 31 2005 dmueller@suse.de -- don't build as root -* Mon Sep 05 2005 matz@suse.de -- Fix broken usage of self-defined syscall [#114933]. -* Fri Aug 26 2005 hare@suse.de -- Fix kpartx DASD partition support -* Thu Aug 04 2005 hare@suse.de -- Add 'directio' path checker -- Add support for S/390 DASD (PAV enablement). -- Update to package from SLES9 -* Thu Jun 23 2005 lmb@suse.de -- LUs with a WWN containing "fd" were blacklisted (#93562). -* Thu Jun 16 2005 lmb@suse.de -- Remove stray newline character from /dev/disk/by-name/ entries - (#85798, #86763) -- Clear /dev/disk/by-name/ on boot. (#85978) -- scsi_id now handles EMC Symmetrix; remove work-around for #86760. -* Wed Jun 15 2005 meissner@suse.de -- use RPM_OPT_FLAGS. -* Mon Jun 13 2005 ro@suse.de -- neededforbuild: udev -> sysfsutils -* Tue Jun 07 2005 lmb@suse.de -- Import fixes from upstream. -- Hardware table updates for IBM ESS and EMC CX (#81688). -- Reinstate paths correctly after failure/restore cycle (#85781, - [#86444]). -- Create map names again and fix segfault in devmap_name (#85798). -* Tue May 24 2005 hare@suse.de -- Fix segmentation fault with EMC Symmetrix (#85614). -- Update EMC Symmetrix entry in hwtable. -* Mon May 23 2005 hare@suse.de -- Add hwtable entry for IBM DS6000. (#63903) -- Do a rescan for devices if multipath command line option is set. -* Fri May 20 2005 hare@suse.de -- Fix devmap_name to use mapname and return proper status (#84748). -* Thu May 12 2005 lmb@suse.de -- Don't complain about default prio callout command (#81695). -- Reflect recent changes in boot.multipath as well as multipathd init - scripts. -- Actually fail paths when they are detected to be failed by multipathd - (#81679). -- killproc/startproc/checkproc can't be used with multipathd because of - the way the daemon switches to its own namespace (#80443). -* Mon May 09 2005 hare@suse.de -- Use proper path checker for SGI TPC arrays. -- Update hwtable entries for SGI TP9400 and SGI TP9500. -- Write correct PID file (#80443). -* Mon Apr 25 2005 lmb@suse.de -- Update to 0.4.4: pp_alua now licensed as GPL (#78628). -- multipath-tools-oom-adj.patch: oom_adj to a valid value. -* Thu Apr 21 2005 lmb@suse.de -- Update to 0.4.4-pre18 which fixes the multipathd to initialize - correctly in the absence of a configuration file (79239). -* Wed Apr 20 2005 lmb@suse.de -- Put multipath cache back into /dev because /var might not be mounted. -- Correct hwtable entry SGI TP9400, TP9500 and IBM 3542. -* Wed Apr 20 2005 lmb@suse.de -- Update to 0.4.4-pre16 -- Build against device-mapper.1.01.xx correctly. -* Tue Apr 19 2005 lmb@suse.de -- Build w/o device-mapper update again. -* Mon Apr 18 2005 lmb@suse.de -- Update to 0.4.4-pre14 -- Build versus device-mapper-1.01.01 to prevent deadlocks in - kernel-space. -- Fix devmap_name to work with udev. -- Fix startup of multipathd w/o configuration file present. -* Fri Apr 15 2005 lmb@suse.de -- Add path priority checker for EMC CLARiiON and make necessary - adjustments so that it gets called by default (#62491). -- Set the default udev dir to '/dev' -* Fri Apr 15 2005 hare@suse.de -- Fix to allocate default strings (#78056) -- Fix default entry for TPC9500. -* Wed Apr 13 2005 hare@suse.de -- Added pp_alua path priority checker. -- Update to multipath-tools-0.4.4-pre12. -* Mon Apr 11 2005 hare@suse.de -- Update to multipath-tools-0.4.4-pre10. -* Fri Apr 08 2005 hare@suse.de -- Update multipath to handle only true multipath devices (#62491). -- Update kpartx to use the device mapper target name if available. -- Add boot.multipath script for early set up of multipath targets. -* Thu Mar 31 2005 hare@suse.de -- Update devmap_name to select targets by table type (#62493). -* Tue Jan 25 2005 lmb@suse.de -- Update to 0.4.2 and fix some bugs + add support for the extended DM - multipath kernel module. (#47491) -* Thu Nov 11 2004 hare@suse.de -- Fix bugs to make it work on S/390 (#47491). -* Fri Nov 05 2004 hare@suse.de -- Update to version 0.3.6 (#47491). -- Fix multipath init script -- Install configuration file example. -- Install multipathd in /sbin instead of /usr/bin. -* Tue Jul 20 2004 fehr@suse.de -- updated README mp-tools-issues.pdf (see #40640) -* Wed Jun 09 2004 fehr@suse.de -- added pdf with README to package (see #40640) -* Thu Jun 03 2004 fehr@suse.de -- updated to version 0.2.1 -- removed patches zero-currpath.patch and rm-newline-in-name.patch - already contained in 0.2.1 -* Thu Jun 03 2004 fehr@suse.de -- added patch zero-currpath.patch (see bugzilla #40640) -* Wed May 26 2004 uli@suse.de -- fixed to build on s390x -* Wed May 26 2004 fehr@suse.de -- added patch rm-newline-in-name.patch (see bugzilla #40640) -* Tue May 25 2004 fehr@suse.de -- created initial version of a SuSE package from version 0.2.0 of - multipath tools