device-mapper-multipath/0001-RH-fix-async-tur.patch

243 lines
6.7 KiB
Diff
Raw Normal View History

---
libmultipath/checkers/tur.c | 85 +++++++++++++++++++++++++++++++++-----------
libmultipath/discovery.c | 1
2 files changed, 65 insertions(+), 21 deletions(-)
Index: multipath-tools-120123/libmultipath/checkers/tur.c
===================================================================
--- multipath-tools-120123.orig/libmultipath/checkers/tur.c
+++ multipath-tools-120123/libmultipath/checkers/tur.c
@@ -35,10 +35,15 @@ struct tur_checker_context {
dev_t devt;
int state;
int running;
- time_t timeout;
+ int fd;
+ unsigned int timeout;
+ time_t time;
pthread_t thread;
pthread_mutex_t lock;
pthread_cond_t active;
+ pthread_spinlock_t hldr_lock;
+ int holders;
+ char message[CHECKER_MSG_LEN];
};
#define TUR_DEVT(c) major((c)->devt), minor((c)->devt)
@@ -53,28 +58,49 @@ int libcheck_init (struct checker * c)
memset(ct, 0, sizeof(struct tur_checker_context));
ct->state = PATH_UNCHECKED;
+ ct->fd = -1;
+ ct->holders = 1;
pthread_cond_init(&ct->active, NULL);
pthread_mutex_init(&ct->lock, NULL);
+ pthread_spin_init(&ct->hldr_lock, PTHREAD_PROCESS_PRIVATE);
c->context = ct;
return 0;
}
+void cleanup_context(struct tur_checker_context *ct)
+{
+ pthread_mutex_destroy(&ct->lock);
+ pthread_cond_destroy(&ct->active);
+ pthread_spin_destroy(&ct->hldr_lock);
+ free(ct);
+}
+
void libcheck_free (struct checker * c)
{
if (c->context) {
struct tur_checker_context *ct = c->context;
+ int holders;
+ pthread_t thread;
- pthread_mutex_destroy(&ct->lock);
- pthread_cond_destroy(&ct->active);
- free(c->context);
+ pthread_spin_lock(&ct->hldr_lock);
+ ct->holders--;
+ holders = ct->holders;
+ thread = ct->thread;
+ pthread_spin_unlock(&ct->hldr_lock);
+ if (holders)
+ pthread_cancel(thread);
+ else
+ cleanup_context(ct);
c->context = NULL;
}
return;
}
+#define TUR_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args);
+
int
-tur_check (struct checker * c)
+tur_check(int fd, unsigned int timeout, char *msg)
{
struct sg_io_hdr io_hdr;
unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
@@ -90,10 +116,10 @@ tur_check (struct checker * c)
io_hdr.dxfer_direction = SG_DXFER_NONE;
io_hdr.cmdp = turCmdBlk;
io_hdr.sbp = sense_buffer;
- io_hdr.timeout = c->timeout;
+ io_hdr.timeout = timeout;
io_hdr.pack_id = 0;
- if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
- MSG(c, MSG_TUR_DOWN);
+ if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+ TUR_MSG(msg, MSG_TUR_DOWN);
return PATH_DOWN;
}
if ((io_hdr.status & 0x7e) == 0x18) {
@@ -101,7 +127,7 @@ tur_check (struct checker * c)
* SCSI-3 arrays might return
* reservation conflict on TUR
*/
- MSG(c, MSG_TUR_UP);
+ TUR_MSG(msg, MSG_TUR_UP);
return PATH_UP;
}
if (io_hdr.info & SG_INFO_OK_MASK) {
@@ -146,14 +172,14 @@ tur_check (struct checker * c)
* LOGICAL UNIT NOT ACCESSIBLE,
* TARGET PORT IN STANDBY STATE
*/
- MSG(c, MSG_TUR_GHOST);
+ TUR_MSG(msg, MSG_TUR_GHOST);
return PATH_GHOST;
}
}
- MSG(c, MSG_TUR_DOWN);
+ TUR_MSG(msg, MSG_TUR_DOWN);
return PATH_DOWN;
}
- MSG(c, MSG_TUR_UP);
+ TUR_MSG(msg, MSG_TUR_UP);
return PATH_UP;
}
@@ -162,18 +188,25 @@ tur_check (struct checker * c)
void cleanup_func(void *data)
{
+ int holders;
struct tur_checker_context *ct = data;
+ pthread_spin_lock(&ct->hldr_lock);
+ ct->holders--;
+ holders = ct->holders;
ct->thread = 0;
+ pthread_spin_unlock(&ct->hldr_lock);
+ if (!holders)
+ cleanup_context(ct);
}
void *tur_thread(void *ctx)
{
- struct checker *c = ctx;
- struct tur_checker_context *ct = c->context;
+ struct tur_checker_context *ct = ctx;
int state;
condlog(3, "%d:%d: tur checker starting up", TUR_DEVT(ct));
+ ct->message[0] = '\0';
/* This thread can be canceled, so setup clean up */
tur_thread_cleanup_push(ct)
@@ -182,7 +215,7 @@ void *tur_thread(void *ctx)
ct->state = PATH_PENDING;
pthread_mutex_unlock(&ct->lock);
- state = tur_check(c);
+ state = tur_check(ct->fd, ct->timeout, ct->message);
/* TUR checker done */
pthread_mutex_lock(&ct->lock);
@@ -213,7 +246,7 @@ void tur_set_async_timeout(struct checke
struct timeval now;
gettimeofday(&now, NULL);
- ct->timeout = now.tv_sec + c->timeout;
+ ct->time = now.tv_sec + c->timeout;
}
int tur_check_async_timeout(struct checker *c)
@@ -222,7 +255,7 @@ int tur_check_async_timeout(struct check
struct timeval now;
gettimeofday(&now, NULL);
- return (now.tv_sec > ct->timeout);
+ return (now.tv_sec > ct->time);
}
extern int
@@ -242,7 +275,7 @@ libcheck_check (struct checker * c)
ct->devt = sb.st_rdev;
if (c->sync)
- return tur_check(c);
+ return tur_check(c->fd, c->timeout, c->message);
/*
* Async mode
@@ -276,6 +309,8 @@ libcheck_check (struct checker * c)
/* TUR checker done */
ct->running = 0;
tur_status = ct->state;
+ strncpy(c->message, ct->message, CHECKER_MSG_LEN);
+ c->message[CHECKER_MSG_LEN - 1] = '\0';
}
pthread_mutex_unlock(&ct->lock);
} else {
@@ -284,24 +319,32 @@ libcheck_check (struct checker * c)
pthread_mutex_unlock(&ct->lock);
condlog(3, "%d:%d: tur thread not responding, "
"using sync mode", TUR_DEVT(ct));
- return tur_check(c);
+ return tur_check(c->fd, c->timeout, c->message);
}
/* Start new TUR checker */
ct->state = PATH_UNCHECKED;
+ ct->fd = c->fd;
+ ct->timeout = c->timeout;
+ pthread_spin_lock(&ct->hldr_lock);
+ ct->holders++;
+ pthread_spin_unlock(&ct->hldr_lock);
tur_set_async_timeout(c);
setup_thread_attr(&attr, 32 * 1024, 1);
- r = pthread_create(&ct->thread, &attr, tur_thread, c);
+ r = pthread_create(&ct->thread, &attr, tur_thread, ct);
if (r) {
pthread_mutex_unlock(&ct->lock);
ct->thread = 0;
+ ct->holders--;
condlog(3, "%d:%d: failed to start tur thread, using"
" sync mode", TUR_DEVT(ct));
- return tur_check(c);
+ return tur_check(c->fd, c->timeout, c->message);
}
pthread_attr_destroy(&attr);
tur_timeout(&tsp);
r = pthread_cond_timedwait(&ct->active, &ct->lock, &tsp);
tur_status = ct->state;
+ strncpy(c->message, ct->message,CHECKER_MSG_LEN);
+ c->message[CHECKER_MSG_LEN -1] = '\0';
pthread_mutex_unlock(&ct->lock);
if (ct->thread &&
(tur_status == PATH_PENDING || tur_status == PATH_UNCHECKED)) {
Index: multipath-tools-120123/libmultipath/discovery.c
===================================================================
--- multipath-tools-120123.orig/libmultipath/discovery.c
+++ multipath-tools-120123/libmultipath/discovery.c
@@ -842,6 +842,7 @@ get_state (struct path * pp, int daemon)
}
checker_set_fd(c, pp->fd);
if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) {
+ memset(c, 0x0, sizeof(struct checker));
condlog(3, "%s: checker init failed", pp->dev);
return PATH_UNCHECKED;
}