--- libmultipath/prio.c | 34 ++++++++++++++++- libmultipath/prio.h | 7 +++ libmultipath/prioritizers/alua.c | 62 +++++++++++++++++++++++-------- libmultipath/prioritizers/alua_rtpg.c | 22 +++++++++-- libmultipath/prioritizers/alua_rtpg.h | 4 +- libmultipath/prioritizers/const.c | 4 ++ libmultipath/prioritizers/datacore.c | 3 + libmultipath/prioritizers/def_func.h | 11 +++++ libmultipath/prioritizers/emc.c | 4 ++ libmultipath/prioritizers/hds.c | 4 ++ libmultipath/prioritizers/hp_sw.c | 4 ++ libmultipath/prioritizers/iet.c | 4 ++ libmultipath/prioritizers/ontap.c | 4 ++ libmultipath/prioritizers/random.c | 4 ++ libmultipath/prioritizers/rdac.c | 4 ++ libmultipath/prioritizers/weightedpath.c | 3 + libmultipath/propsel.c | 4 +- multipathd/main.c | 24 ++++++++---- 18 files changed, 174 insertions(+), 32 deletions(-) Index: multipath-tools-130222/libmultipath/prio.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prio.c +++ multipath-tools-130222/libmultipath/prio.c @@ -112,9 +112,24 @@ struct prio * add_prio (char * name) p->getprio = (int (*)(struct path *, char *)) 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 with getprio: (%s)", errstr); if (!p->getprio) goto out; + + p->initprio = (int (*)(struct prio *)) dlsym(p->handle, "initprio"); + errstr = dlerror(); + if (errstr != NULL) + condlog(0, "A dynamic linking error occurred with initprio: (%s)", errstr); + if (!p->initprio) + goto out; + + p->freeprio = (int (*)(struct prio *)) dlsym(p->handle, "freeprio"); + errstr = dlerror(); + if (errstr != NULL) + condlog(0, "A dynamic linking error occurred with freeprio: (%s)", errstr); + if (!p->freeprio) + goto out; + list_add(&p->node, &prioritizers); return p; out: @@ -122,6 +137,13 @@ out: return NULL; } +int prio_init (struct prio * p) +{ + if (!p || !p->initprio) + return 1; + return p->initprio(p); +} + int prio_getprio (struct prio * p, struct path * pp) { return p->getprio(pp, p->args); @@ -156,8 +178,16 @@ void prio_get (struct prio * dst, char * strncpy(dst->name, src->name, PRIO_NAME_LEN); if (args) strncpy(dst->args, args, PRIO_ARGS_LEN); + dst->initprio = src->initprio; dst->getprio = src->getprio; + dst->freeprio = src->freeprio; dst->handle = NULL; + dst->context = NULL; + + if (dst->initprio(dst) != 0){ + memset(dst, 0x0, sizeof(struct prio)); + return; + } src->refcount++; } @@ -173,6 +203,8 @@ void prio_put (struct prio * dst) src = NULL; else src = prio_lookup(dst->name); + if (dst->freeprio) + dst->freeprio(dst); memset(dst, 0x0, sizeof(struct prio)); free_prio(src); } Index: multipath-tools-130222/libmultipath/prio.h =================================================================== --- multipath-tools-130222.orig/libmultipath/prio.h +++ multipath-tools-130222/libmultipath/prio.h @@ -46,9 +46,15 @@ struct prio { void *handle; int refcount; struct list_head node; + void * context; char name[PRIO_NAME_LEN]; char args[PRIO_ARGS_LEN]; + int (*initprio)(struct prio * p); + /* You are allowed to call initprio multiple times without calling + * freeprio. Doing so will reinitialize it (possibly skipping + * allocations) */ int (*getprio)(struct path *, char *); + int (*freeprio)(struct prio * p); }; unsigned int get_prio_timeout(unsigned int default_timeout); @@ -57,6 +63,7 @@ void cleanup_prio (void); struct prio * add_prio (char *); struct prio * prio_lookup (char *); int prio_getprio (struct prio *, struct path *); +int prio_init (struct prio *); void prio_get (struct prio *, char *, char *); void prio_put (struct prio *); int prio_selected (struct prio *); Index: multipath-tools-130222/libmultipath/prioritizers/alua.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c +++ multipath-tools-130222/libmultipath/prioritizers/alua.c @@ -37,6 +37,12 @@ static const char * aas_string[] = { [AAS_TRANSITIONING] = "transitioning between states", }; +struct alua_context { + int tpg_support; + int tpg; + int buflen; +}; + static const char *aas_print_string(int rc) { rc &= 0x7f; @@ -51,25 +57,26 @@ static const char *aas_print_string(int } int -get_alua_info(int fd) +get_alua_info(int fd, struct alua_context *ct) { int rc; - int tpg; int aas; - 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; + if (ct->tpg_support <= 0 || ct->tpg < 0) { + ct->tpg_support = get_target_port_group_support(fd); + if (ct->tpg_support < 0) + return -ALUA_PRIO_TPGS_FAILED; + + if (ct->tpg_support == TPGS_NONE) + return -ALUA_PRIO_NOT_SUPPORTED; + + ct->tpg = get_target_port_group(fd, &ct->buflen); + if (ct->tpg < 0) + return -ALUA_PRIO_RTPG_FAILED; + } - condlog(3, "reported target port group is %i", tpg); - rc = get_asymmetric_access_state(fd, tpg); + condlog(3, "reported target port group is %i", ct->tpg); + rc = get_asymmetric_access_state(fd, ct->tpg, &ct->buflen); if (rc < 0) return -ALUA_PRIO_GETAAS_FAILED; aas = (rc & 0x0f); @@ -88,7 +95,7 @@ int getprio (struct path * pp, char * ar if (pp->fd < 0) return -ALUA_PRIO_NO_INFORMATION; - rc = get_alua_info(pp->fd); + rc = get_alua_info(pp->fd, pp->prio.context); if (rc >= 0) { aas = (rc & 0x0f); priopath = (rc & 0x80); @@ -128,3 +135,28 @@ int getprio (struct path * pp, char * ar } return rc; } + +int initprio(struct prio *p) +{ + if (!p->context) { + struct alua_context *ct; + + ct = malloc(sizeof(struct alua_context)); + if (!ct) + return 1; + p->context = ct; + } + memset(p->context, 0, sizeof(struct alua_context)); + return 0; +} + + +int freeprio(struct prio *p) +{ + if (p->context) { + free(p->context); + p->context = NULL; + } + return 0; +} + Index: multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/alua_rtpg.c +++ multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c @@ -171,7 +171,7 @@ get_target_port_group_support(int fd) } int -get_target_port_group(int fd) +get_target_port_group(int fd, int *buflen_ptr) { unsigned char *buf; struct vpd83_data * vpd83; @@ -179,7 +179,12 @@ get_target_port_group(int fd) int rc; int buflen, scsi_buflen; - buflen = 128; /* Lets start from 128 */ + if (!buflen_ptr || *buflen_ptr == 0) { + buflen = 128; /* Lets start from 128 */ + if (buflen_ptr) + *buflen_ptr = 128; + } else + buflen = *buflen_ptr; buf = (unsigned char *)malloc(buflen); if (!buf) { PRINT_DEBUG("malloc failed: could not allocate" @@ -202,6 +207,8 @@ get_target_port_group(int fd) return -RTPG_RTPG_FAILED; } buflen = scsi_buflen; + if (buflen_ptr) + *buflen_ptr = buflen; memset(buf, 0, buflen); rc = do_inquiry(fd, 1, 0x83, buf, buflen); if (rc < 0) @@ -269,7 +276,7 @@ do_rtpg(int fd, void* resp, long resplen } int -get_asymmetric_access_state(int fd, unsigned int tpg) +get_asymmetric_access_state(int fd, unsigned int tpg, int *buflen_ptr) { unsigned char *buf; struct rtpg_data * tpgd; @@ -278,7 +285,12 @@ get_asymmetric_access_state(int fd, unsi int buflen; uint32_t scsi_buflen; - buflen = 128; /* Initial value from old code */ + if (!buflen_ptr || *buflen_ptr == 0) { + buflen = 128; /* Initial value from old code */ + if (buflen_ptr) + *buflen_ptr = 128; + } else + buflen = *buflen_ptr; buf = (unsigned char *)malloc(buflen); if (!buf) { PRINT_DEBUG ("malloc failed: could not allocate" @@ -299,6 +311,8 @@ get_asymmetric_access_state(int fd, unsi return -RTPG_RTPG_FAILED; } buflen = scsi_buflen; + if (buflen_ptr) + *buflen_ptr = buflen; memset(buf, 0, buflen); rc = do_rtpg(fd, buf, buflen); if (rc < 0) Index: multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.h =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/alua_rtpg.h +++ multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.h @@ -23,8 +23,8 @@ #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); +int get_target_port_group(int fd, int *buflen_ptr); +int get_asymmetric_access_state(int fd, unsigned int tpg, int *buflen_ptr); #endif /* __RTPG_H__ */ Index: multipath-tools-130222/libmultipath/prioritizers/const.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/const.c +++ multipath-tools-130222/libmultipath/prioritizers/const.c @@ -1,8 +1,12 @@ #include #include +#include "def_func.h" int getprio (struct path * pp, char * args) { return 1; } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/datacore.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/datacore.c +++ multipath-tools-130222/libmultipath/prioritizers/datacore.c @@ -25,6 +25,7 @@ #include #include #include +#include "def_func.h" #define INQ_REPLY_LEN 255 #define INQ_CMD_CODE 0x12 @@ -111,3 +112,5 @@ int getprio (struct path * pp, char * ar return datacore_prio(pp->dev, pp->fd, args); } +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/def_func.h =================================================================== --- /dev/null +++ multipath-tools-130222/libmultipath/prioritizers/def_func.h @@ -0,0 +1,11 @@ +#ifndef _DEF_FUNC_H +#define _DEF_FUNC_H + +#include "prio.h" + +#define declare_nop_prio(name) \ +int name (struct prio *p) \ +{ \ + return 0; \ +} +#endif /* _DEF_FUNC_H */ Index: multipath-tools-130222/libmultipath/prioritizers/emc.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/emc.c +++ multipath-tools-130222/libmultipath/prioritizers/emc.c @@ -6,6 +6,7 @@ #include #include #include +#include "def_func.h" #define INQUIRY_CMD 0x12 #define INQUIRY_CMDLEN 6 @@ -85,3 +86,6 @@ int getprio (struct path * pp, char * ar { return emc_clariion_prio(pp->dev, pp->fd); } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/hds.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/hds.c +++ multipath-tools-130222/libmultipath/prioritizers/hds.c @@ -76,6 +76,7 @@ #include #include #include +#include "def_func.h" #define INQ_REPLY_LEN 255 #define INQ_CMD_CODE 0x12 @@ -170,3 +171,6 @@ int getprio (struct path * pp, char * ar { return hds_modular_prio(pp->dev, pp->fd); } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/hp_sw.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/hp_sw.c +++ multipath-tools-130222/libmultipath/prioritizers/hp_sw.c @@ -16,6 +16,7 @@ #include #include #include +#include "def_func.h" #define TUR_CMD_LEN 6 #define SCSI_CHECK_CONDITION 0x2 @@ -99,3 +100,6 @@ int getprio (struct path * pp, char * ar { return hp_sw_prio(pp->dev, pp->fd); } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/iet.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/iet.c +++ multipath-tools-130222/libmultipath/prioritizers/iet.c @@ -9,6 +9,7 @@ #include #include #include +#include "def_func.h" // // This prioritizer suits iSCSI needs, makes it possible to prefer one path. @@ -141,3 +142,6 @@ int getprio(struct path * pp, char * arg { return iet_prio(pp->dev, args); } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/ontap.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/ontap.c +++ multipath-tools-130222/libmultipath/prioritizers/ontap.c @@ -23,6 +23,7 @@ #include #include #include +#include "def_func.h" #define INQUIRY_CMD 0x12 #define INQUIRY_CMDLEN 6 @@ -245,3 +246,6 @@ int getprio (struct path * pp, char * ar { return ontap_prio(pp->dev, pp->fd); } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/random.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/random.c +++ multipath-tools-130222/libmultipath/prioritizers/random.c @@ -4,6 +4,7 @@ #include #include +#include "def_func.h" int getprio (struct path * pp, char * args) { @@ -13,3 +14,6 @@ int getprio (struct path * pp, char * ar srand((unsigned int)tv.tv_usec); return 1+(int) (10.0*rand()/(RAND_MAX+1.0)); } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/rdac.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/rdac.c +++ multipath-tools-130222/libmultipath/prioritizers/rdac.c @@ -6,6 +6,7 @@ #include #include #include +#include "def_func.h" #define INQUIRY_CMD 0x12 #define INQUIRY_CMDLEN 6 @@ -95,3 +96,6 @@ int getprio (struct path * pp, char * ar { return rdac_prio(pp->dev, pp->fd); } + +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/prioritizers/weightedpath.c =================================================================== --- multipath-tools-130222.orig/libmultipath/prioritizers/weightedpath.c +++ multipath-tools-130222/libmultipath/prioritizers/weightedpath.c @@ -32,6 +32,7 @@ #include #include #include +#include "def_func.h" char *get_next_string(char **temp, char *split_char) { @@ -104,3 +105,5 @@ int getprio(struct path *pp, char *args) return prio_path_weight(pp, args); } +declare_nop_prio(initprio) +declare_nop_prio(freeprio) Index: multipath-tools-130222/libmultipath/propsel.c =================================================================== --- multipath-tools-130222.orig/libmultipath/propsel.c +++ multipath-tools-130222/libmultipath/propsel.c @@ -401,10 +401,10 @@ detect_prio(struct path * pp) if (get_target_port_group_support(pp->fd) <= 0) return; - ret = get_target_port_group(pp->fd); + ret = get_target_port_group(pp->fd, NULL); if (ret < 0) return; - if (get_asymmetric_access_state(pp->fd, ret) < 0) + if (get_asymmetric_access_state(pp->fd, ret, NULL) < 0) return; prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS); } Index: multipath-tools-130222/multipathd/main.c =================================================================== --- multipath-tools-130222.orig/multipathd/main.c +++ multipath-tools-130222/multipathd/main.c @@ -700,20 +700,23 @@ static int uev_update_path (struct uevent *uev, struct vectors * vecs) { int ro, retval = 0; + struct path * pp; + + pp = find_path_by_dev(vecs->pathvec, uev->kernel); + if (!pp) { + condlog(0, "%s: spurious uevent, path not found", + uev->kernel); + return 1; + } + /* reinit the prio values on change event, in case something is + * different */ + prio_init(&pp->prio); 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, 0); @@ -1218,6 +1221,11 @@ check_path (struct vectors * vecs, struc } if(newstate == PATH_UP || newstate == PATH_GHOST){ + /* + * Reinitialize the prioritizer, in case something + * changed. + */ + prio_init(&pp->prio); if ( pp->mpp && pp->mpp->prflag ){ /* * Check Persistent Reservation.