diff --git a/libcheckers/checkers.c b/libcheckers/checkers.c index 53770a6..1c08864 100644 --- a/libcheckers/checkers.c +++ b/libcheckers/checkers.c @@ -17,6 +17,7 @@ static struct checker checkers[] = { .context = NULL, .check = directio, .init = directio_init, + .size_scxt = directio_size_scxt, .free = directio_free }, { @@ -26,6 +27,7 @@ static struct checker checkers[] = { .context = NULL, .check = tur, .init = tur_init, + .size_scxt = tur_size_scxt, .free = tur_free }, { @@ -35,6 +37,7 @@ static struct checker checkers[] = { .context = NULL, .check = hp_sw, .init = hp_sw_init, + .size_scxt = hp_sw_size_scxt, .free = hp_sw_free }, { @@ -44,6 +47,7 @@ static struct checker checkers[] = { .context = NULL, .check = emc_clariion, .init = emc_clariion_init, + .size_scxt = emc_clariion_size_scxt, .free = emc_clariion_free }, { @@ -53,9 +57,10 @@ static struct checker checkers[] = { .context = NULL, .check = readsector0, .init = readsector0_init, + .size_scxt = readsector0_size_scxt, .free = readsector0_free }, - {0, "", "", NULL, NULL, NULL, NULL}, + {0, "", "", NULL, NULL, NULL, NULL, NULL}, }; void checker_set_fd (struct checker * c, int fd) @@ -75,8 +80,14 @@ struct checker * checker_lookup (char * return NULL; } -int checker_init (struct checker * c) +unsigned long checker_size_scxt (struct checker * c) { + return c->size_scxt(); +} + +int checker_init (struct checker * c, void * mpctxt) +{ + c->mpcontext = mpctxt; return c->init(c); } @@ -127,5 +138,6 @@ void checker_get (struct checker * dst, strncpy(dst->message, src->message, CHECKER_MSG_LEN); dst->check = src->check; dst->init = src->init; + dst->size_scxt = src->size_scxt; dst->free = src->free; } diff --git a/libcheckers/checkers.h b/libcheckers/checkers.h index 219dfaf..b0282eb 100644 --- a/libcheckers/checkers.h +++ b/libcheckers/checkers.h @@ -83,14 +83,18 @@ struct checker { 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 */ + unsigned long (*size_scxt)(void); /* get size for shared context */ void (*free)(struct checker *); /* to free the context */ }; #define MSG(c, a) snprintf((c)->message, CHECKER_MSG_LEN, a); -int checker_init (struct checker *); +int checker_init (struct checker *, void *); +unsigned long checker_size_scxt (struct checker *); void checker_put (struct checker *); void checker_reset (struct checker * c); void checker_set_fd (struct checker *, int); diff --git a/libcheckers/directio.c b/libcheckers/directio.c index b53c1c3..819af37 100644 --- a/libcheckers/directio.c +++ b/libcheckers/directio.c @@ -59,6 +59,11 @@ out: return 1; } +unsigned long directio_size_scxt (void) +{ + return 0; +} + void directio_free (struct checker * c) { struct directio_context * ct = (struct directio_context *)c->context; diff --git a/libcheckers/directio.h b/libcheckers/directio.h index 1865b1f..5e9e6df 100644 --- a/libcheckers/directio.h +++ b/libcheckers/directio.h @@ -3,6 +3,7 @@ int directio (struct checker *); int directio_init (struct checker *); +unsigned long directio_size_scxt (void); void directio_free (struct checker *); #endif /* _DIRECTIO_H */ diff --git a/libcheckers/emc_clariion.c b/libcheckers/emc_clariion.c index a883e3d..f60026b 100644 --- a/libcheckers/emc_clariion.c +++ b/libcheckers/emc_clariion.c @@ -33,6 +33,11 @@ int emc_clariion_init (struct checker * return 0; } +unsigned long emc_clariion_size_scxt (void) +{ + return 0; +} + void emc_clariion_free (struct checker * c) { free(c->context); diff --git a/libcheckers/emc_clariion.h b/libcheckers/emc_clariion.h index a1018a6..0cac45d 100644 --- a/libcheckers/emc_clariion.h +++ b/libcheckers/emc_clariion.h @@ -3,6 +3,7 @@ int emc_clariion (struct checker *); int emc_clariion_init (struct checker *); +unsigned long emc_clariion_size_scxt (void); void emc_clariion_free (struct checker *); #endif /* _EMC_CLARIION_H */ diff --git a/libcheckers/hp_sw.c b/libcheckers/hp_sw.c index b9731ff..58e0011 100644 --- a/libcheckers/hp_sw.c +++ b/libcheckers/hp_sw.c @@ -39,6 +39,11 @@ int hp_sw_init (struct checker * c) return 0; } +unsigned long hp_sw_size_scxt (void) +{ + return 0; +} + void hp_sw_free (struct checker * c) { return; diff --git a/libcheckers/hp_sw.h b/libcheckers/hp_sw.h index 3be0d8e..46dad47 100644 --- a/libcheckers/hp_sw.h +++ b/libcheckers/hp_sw.h @@ -3,6 +3,7 @@ int hp_sw (struct checker *); int hp_sw_init (struct checker *); +unsigned long hp_sw_size_scxt (void); void hp_sw_free (struct checker *); #endif /* _HP_SW_H */ diff --git a/libcheckers/readsector0.c b/libcheckers/readsector0.c index dd18528..f76c34e 100644 --- a/libcheckers/readsector0.c +++ b/libcheckers/readsector0.c @@ -14,6 +14,7 @@ #include "checkers.h" #include "../libmultipath/sg_include.h" +#include "../libmultipath/debug.h" #define SENSE_BUFF_LEN 32 @@ -29,12 +30,18 @@ int readsector0_init (struct checker * c return 0; } +unsigned long readsector0_size_scxt (void) +{ + return 0; +} + void readsector0_free (struct checker * c) { return; } int +//sg_read (int sg_fd, unsigned char * buff) sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff) { /* defaults */ @@ -45,10 +52,12 @@ sg_read (int sg_fd, unsigned char * buff 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; + int retry_count=3; memset(rdCmd, 0, cdbsz); sz_ind = 1; @@ -74,6 +83,8 @@ sg_read (int sg_fd, unsigned char * buff 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) { @@ -88,6 +99,16 @@ sg_read (int sg_fd, unsigned char * buff (0 == io_hdr.driver_status)) { return PATH_UP; } else { + /* + * Retry if UNIT_ATTENTION check condition. + */ + if ((sbb[2]&0xf) == 6) { + condlog(4, "readsector0_checker: Read error. " + "Sense data are 0x%x/0x%x/0x%x.", + sbb[2]&0xf, sbb[12], sbb[13]); + if (--retry_count) + goto retry; + } return PATH_DOWN; } } @@ -95,8 +116,8 @@ sg_read (int sg_fd, unsigned char * buff extern int readsector0 (struct checker * c) { - unsigned char buf[512]; unsigned char sbuf[SENSE_BUFF_LEN]; + unsigned char buf[512]; int ret; ret = sg_read(c->fd, &buf[0], &sbuf[0]); diff --git a/libcheckers/readsector0.h b/libcheckers/readsector0.h index 0f5d654..da1aefa 100644 --- a/libcheckers/readsector0.h +++ b/libcheckers/readsector0.h @@ -1,8 +1,12 @@ #ifndef _READSECTOR0_H #define _READSECTOR0_H +#define SENSE_BUFF_LEN 32 + int readsector0 (struct checker *); int readsector0_init (struct checker *); +unsigned long readsector0_size_scxt (void); void readsector0_free (struct checker *); +int sg_read (int, unsigned char *, unsigned char *); #endif /* _READSECTOR0_H */ diff --git a/libcheckers/tur.c b/libcheckers/tur.c index e79bc0a..b2077c8 100644 --- a/libcheckers/tur.c +++ b/libcheckers/tur.c @@ -32,6 +32,11 @@ int tur_init (struct checker * c) return 0; } +unsigned long tur_size_scxt (void) +{ + return 0; +} + void tur_free (struct checker * c) { return; diff --git a/libcheckers/tur.h b/libcheckers/tur.h index a2e8c88..4de44fd 100644 --- a/libcheckers/tur.h +++ b/libcheckers/tur.h @@ -3,6 +3,7 @@ int tur (struct checker *); int tur_init (struct checker *); +unsigned long tur_size_scxt (void); void tur_free (struct checker *); #endif /* _TUR_H */ diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index f21e5bc..e995a98 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -610,15 +610,37 @@ static int get_state (struct path * pp) { struct checker * c = &pp->checker; + void * mpctxt = NULL; + int size; +#if DAEMON + /* + * Avoid initializing path checker for multipathd path checker thread + * until we have linked path to its mpp in order to get mpp shared + * context area for path checkers. + */ + if (!pp->mpp) + return 0; +#endif if (!checker_selected(c)) { select_checker(pp); if (!checker_selected(c)) return 1; checker_set_fd(c, pp->fd); - if (checker_init(c)) + if (pp->mpp) { + if (!pp->mpp->mpcontext) { + size = checker_size_scxt(c); + if (size) + mpctxt = pp->mpp->mpcontext = + zalloc(size); + } + else + mpctxt = pp->mpp->mpcontext; + } + if (checker_init(c, mpctxt)) return 1; } + pp->state = checker_check(c); condlog(3, "%s: state = %i", pp->dev, pp->state); if (pp->state == PATH_DOWN) @@ -706,7 +728,7 @@ pathinfo (struct path *pp, vector hwtabl * been successfully obtained before. */ if (mask & DI_PRIO && - (pp->state != PATH_DOWN || pp->priority != PRIO_UNDEF)) + (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF)) get_prio(pp); if (mask & DI_WWID && !strlen(pp->wwid)) diff --git a/libmultipath/structs.c b/libmultipath/structs.c index db3f824..d104a09 100644 --- a/libmultipath/structs.c +++ b/libmultipath/structs.c @@ -117,8 +117,10 @@ alloc_multipath (void) mpp = (struct multipath *)MALLOC(sizeof(struct multipath)); - if (mpp) + if (mpp) { mpp->bestpg = 1; + mpp->mpcontext = NULL; + } return mpp; } @@ -180,6 +182,9 @@ free_multipath (struct multipath * mpp, free_pathvec(mpp->paths, free_paths); free_pgvec(mpp->pg, free_paths); + + FREE_PTR(mpp->mpcontext); + FREE(mpp); } diff --git a/libmultipath/structs.h b/libmultipath/structs.h index 7db7faa..77dd4af 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -154,6 +154,9 @@ struct multipath { unsigned int stat_map_loads; unsigned int stat_total_queueing_time; unsigned int stat_queueing_timeouts; + + /* checkers shared data */ + void * mpcontext; }; struct pathgroup {