Inter-revision diff: patch 12

Comparing v1 (message) to v2 (message)

--- v1
+++ v2
@@ -1,98 +1,354 @@
-Make the RDAC checker use the async checker framework.
+The TUR checker now just exports the message table and the
+"libcheck_async_func" symbol. This converts it into an instance of
+the generic async checker model.
+
+With this change, struct checker_context isn't used any more and
+can be removed.
 
 Signed-off-by: Martin Wilck <mwilck@suse.com>
 ---
- libmultipath/checkers/rdac.c | 30 ++++++++++--------------------
- 1 file changed, 10 insertions(+), 20 deletions(-)
+ libmultipath/checkers.h     |   3 -
+ libmultipath/checkers/tur.c | 253 +++---------------------------------
+ 2 files changed, 15 insertions(+), 241 deletions(-)
 
-diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c
-index 87b8872..a477fb5 100644
---- a/libmultipath/checkers/rdac.c
-+++ b/libmultipath/checkers/rdac.c
-@@ -1,8 +1,6 @@
- /*
-  * Copyright (c) 2005 Christophe Varoqui
+diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
+index 05dbd7c..4846ea9 100644
+--- a/libmultipath/checkers.h
++++ b/libmultipath/checkers.h
+@@ -180,9 +180,6 @@ void checker_set_async (struct checker *);
+ void checker_set_fd (struct checker *, int);
+ void checker_enable (struct checker *);
+ void checker_disable(struct checker *);
+-struct checker_context {
+-	struct checker_class *cls;
+-};
+ int checker_get_state(struct checker *c);
+ bool checker_need_wait(struct checker *c);
+ void checker_check (struct checker *, int);
+diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
+index 6791172..62460cb 100644
+--- a/libmultipath/checkers/tur.c
++++ b/libmultipath/checkers/tur.c
+@@ -3,87 +3,29 @@
+  *
+  * Copyright (c) 2004 Christophe Varoqui
   */
--#include <stdio.h>
 -#include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-@@ -15,6 +13,7 @@
- #include "debug.h"
- 
+-#include <string.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include <unistd.h>
+-#include <fcntl.h>
+ #include <sys/ioctl.h>
+-#include <sys/sysmacros.h>
++#include <sys/types.h>
++
+ #include <errno.h>
+-#include <sys/time.h>
+ 
+ #include "checkers.h"
+-#include "debug.h"
++#include "async_checker.h"
  #include "sg_include.h"
-+#include "async_checker.h"
- 
- #define INQUIRY_CMDLEN		6
- #define INQUIRY_CMD		0x12
-@@ -55,11 +54,7 @@ struct control_mode_page {
- 	unsigned char dontcare1[6];
+-#include "runner.h"
+ 
+ #define TUR_CMD_LEN 6
+ #define HEAVY_CHECK_COUNT       10
+-#define MAX_NR_TIMEOUTS 1
+ 
+ enum {
+-	MSG_TUR_RUNNING = CHECKER_FIRST_MSGID,
+-	MSG_TUR_TIMEOUT,
+-	MSG_TUR_FAILED,
+-	MSG_TUR_TRANSITIONING,
++	MSG_TUR_TRANSITIONING = CHECKER_FIRST_MSGID,
  };
  
--struct rdac_checker_context {
--	void * dummy;
+ #define IDX_(x) (MSG_ ## x - CHECKER_FIRST_MSGID)
+ const char *libcheck_msgtable[] = {
+-	[IDX_(TUR_RUNNING)] = " still running",
+-	[IDX_(TUR_TIMEOUT)] = " timed out",
+-	[IDX_(TUR_FAILED)] = " failed to initialize",
+ 	[IDX_(TUR_TRANSITIONING)] = " reports path is transitioning",
+ 	NULL,
+ };
+ 
+-struct tur_data {
+-	int fd;
+-	dev_t devt;
+-	unsigned int timeout;
+-	int state;
+-	short msgid;
 -};
 -
--int libcheck_init (struct checker * c)
-+int libcheck_init(struct checker *c)
- {
- 	unsigned char cmd[MODE_SEN_SEL_CMDLEN];
- 	unsigned char sense_b[SENSE_BUFF_LEN];
-@@ -133,11 +128,6 @@ out:
- 	return 0;
- }
- 
--void libcheck_free(__attribute__((unused)) struct checker *c)
--{
--	return;
--}
--
- static int
- do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len,
-        unsigned int timeout)
-@@ -288,15 +278,15 @@ checker_msg_string(const struct volume_access_inq *inq)
- 	}
- }
- 
--int libcheck_check(struct checker * c)
+-struct tur_checker_context {
+-	struct checker_context chkr;
+-	int last_runner_state;
+-	unsigned int nr_timeouts;
+-	struct runner_context *rtx;
+-	struct tur_data tdata;
+-};
+-
+-int libcheck_init(struct checker *c)
+-{
+-	struct tur_checker_context *tcc;
+-	struct stat sb;
+-
+-	tcc = calloc(1, sizeof(*tcc));
+-	tcc->tdata.state = PATH_UNCHECKED;
+-	tcc->tdata.fd = -1;
+-	if (fstat(c->fd, &sb) == 0)
+-		tcc->tdata.devt = sb.st_rdev;
+-	tcc->chkr.cls = c->cls;
+-	c->context = tcc;
+-	return 0;
+-}
+-
+-void libcheck_free (struct checker * c)
+-{
+-	struct tur_checker_context *tcc = c->context;
+-
+-	if (!tcc)
+-		return;
+-	c->context = NULL;
+-	if (tcc->rtx)
+-		release_runner(tcc->rtx);
+-	free(tcc);
+-}
+-
+-static int
+-tur_check(int fd, unsigned int timeout, short *msgid)
 +int libcheck_async_func(struct runner_data *rdata)
  {
- 	struct volume_access_inq inq;
- 	int ret, inqfail;
- 
- 	inqfail = 0;
- 	memset(&inq, 0, sizeof(struct volume_access_inq));
--	ret = do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq),
--		     c->timeout);
-+	ret = do_inq(rdata->fd, 0xC9, &inq, sizeof(struct volume_access_inq),
-+		     rdata->timeout);
- 	if (ret != PATH_UP) {
- 		inqfail = 1;
- 		goto done;
-@@ -340,17 +330,17 @@ int libcheck_check(struct checker * c)
- done:
- 	switch (ret) {
- 	case PATH_WILD:
--		c->msgid = CHECKER_MSGID_UNSUPPORTED;
-+		rdata->msgid = CHECKER_MSGID_UNSUPPORTED;
- 		break;
- 	case PATH_DOWN:
--		c->msgid = (inqfail ? RDAC_MSGID_INQUIRY_FAILED :
--			    checker_msg_string(&inq));
-+		rdata->msgid = (inqfail ? RDAC_MSGID_INQUIRY_FAILED
-+					: checker_msg_string(&inq));
- 		break;
- 	case PATH_UP:
--		c->msgid = CHECKER_MSGID_UP;
+ 	struct sg_io_hdr io_hdr;
+ 	unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
+@@ -99,14 +41,14 @@ retry:
+ 	io_hdr.dxfer_direction = SG_DXFER_NONE;
+ 	io_hdr.cmdp = turCmdBlk;
+ 	io_hdr.sbp = sense_buffer;
+-	io_hdr.timeout = timeout * 1000;
++	io_hdr.timeout = rdata->timeout * 1000;
+ 	io_hdr.pack_id = 0;
+-	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
++	if (ioctl(rdata->fd, SG_IO, &io_hdr) < 0) {
+ 		if (errno == ENOTTY) {
+-			*msgid = CHECKER_MSGID_UNSUPPORTED;
++			rdata->msgid = CHECKER_MSGID_UNSUPPORTED;
+ 			return PATH_WILD;
+ 		}
+-		*msgid = CHECKER_MSGID_DOWN;
++		rdata->msgid = CHECKER_MSGID_DOWN;
+ 		return PATH_DOWN;
+ 	}
+ 	if ((io_hdr.status & 0x7e) == 0x18) {
+@@ -114,7 +56,7 @@ retry:
+ 		 * SCSI-3 arrays might return
+ 		 * reservation conflict on TUR
+ 		 */
+-		*msgid = CHECKER_MSGID_UP;
 +		rdata->msgid = CHECKER_MSGID_UP;
- 		break;
- 	case PATH_GHOST:
--		c->msgid = CHECKER_MSGID_GHOST;
-+		rdata->msgid = CHECKER_MSGID_GHOST;
- 		break;
+ 		return PATH_UP;
  	}
- 
+ 	if (io_hdr.info & SG_INFO_OK_MASK) {
+@@ -159,14 +101,14 @@ retry:
+ 				 * LOGICAL UNIT NOT ACCESSIBLE,
+ 				 * TARGET PORT IN STANDBY STATE
+ 				 */
+-				*msgid = CHECKER_MSGID_GHOST;
++				rdata->msgid = CHECKER_MSGID_GHOST;
+ 				return PATH_GHOST;
+ 			} else if (asc == 0x04 && ascq == 0x0a) {
+ 				/*
+ 				 * LOGICAL UNIT NOT ACCESSIBLE,
+ 				 * ASYMMETRIC ACCESS STATE TRANSITION
+ 				 */
+-				*msgid = MSG_TUR_TRANSITIONING;
++				rdata->msgid = MSG_TUR_TRANSITIONING;
+ 				return PATH_PENDING;
+ 			}
+ 		} else if (key == 0x5) {
+@@ -176,178 +118,13 @@ retry:
+ 				 * LUN NOT SUPPORTED: unmapped at target.
+ 				 * Signals pp->disconnected, becomes PATH_DOWN.
+ 				 */
+-				*msgid = CHECKER_MSGID_DISCONNECTED;
++				rdata->msgid = CHECKER_MSGID_DISCONNECTED;
+ 				return PATH_DISCONNECTED;
+ 			}
+ 		}
+-		*msgid = CHECKER_MSGID_DOWN;
++		rdata->msgid = CHECKER_MSGID_DOWN;
+ 		return PATH_DOWN;
+ 	}
+-	*msgid = CHECKER_MSGID_UP;
++	rdata->msgid = CHECKER_MSGID_UP;
+ 	return PATH_UP;
+ }
+-
+-/*
+- * Test code for "zombie tur thread" handling.
+- * Compile e.g. with CFLAGS=-DTUR_TEST_MAJOR=8
+- * Additional parameters can be configure with the macros below.
+- *
+- * Everty nth started TUR thread will hang in non-cancellable state
+- * for given number of seconds, for device given by major/minor.
+- */
+-#ifdef TUR_TEST_MAJOR
+-
+-#ifndef TUR_TEST_MINOR
+-#define TUR_TEST_MINOR 0
+-#endif
+-#ifndef TUR_SLEEP_INTERVAL
+-#define TUR_SLEEP_INTERVAL 3
+-#endif
+-#ifndef TUR_SLEEP_SECS
+-#define TUR_SLEEP_SECS 60
+-#endif
+-
+-static void tur_deep_sleep(const struct tur_data *tdata)
+-{
+-	static int sleep_cnt;
+-	const struct timespec ts = { .tv_sec = TUR_SLEEP_SECS, .tv_nsec = 0 };
+-	int oldstate;
+-
+-	if (tdata->devt != makedev(TUR_TEST_MAJOR, TUR_TEST_MINOR) ||
+-	    ++sleep_cnt % TUR_SLEEP_INTERVAL == 0)
+-		return;
+-
+-	condlog(3, "tur thread going to sleep for %ld seconds", ts.tv_sec);
+-	if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)
+-		condlog(0, "pthread_setcancelstate: %m");
+-	if (nanosleep(&ts, NULL) != 0)
+-		condlog(0, "nanosleep: %m");
+-	condlog(3, "tur zombie thread woke up");
+-	if (pthread_setcancelstate(oldstate, NULL) != 0)
+-		condlog(0, "pthread_setcancelstate (2): %m");
+-	pthread_testcancel();
+-}
+-#else
+-#define tur_deep_sleep(x) do {} while (0)
+-#endif /* TUR_TEST_MAJOR */
+-
+-void runner_callback(void *arg)
+-{
+-	struct tur_data *tdata = arg;
+-	int state;
+-
+-	condlog(4, "%d:%d : tur checker starting up", major(tdata->devt),
+-		minor(tdata->devt));
+-
+-	tur_deep_sleep(tdata);
+-	state = tur_check(tdata->fd, tdata->timeout, &tdata->msgid);
+-	tdata->state = state;
+-	pthread_testcancel();
+-	condlog(4, "%d:%d : tur checker finished, state %s", major(tdata->devt),
+-		minor(tdata->devt), checker_state_name(state));
+-}
+-
+-static int check_runner_state(struct tur_checker_context *tcc)
+-{
+-	struct runner_context *rtx = tcc->rtx;
+-	int rc;
+-
+-	rc = check_runner(rtx, &tcc->tdata, sizeof(tcc->tdata));
+-	switch (rc) {
+-	case RUNNER_DEAD:
+-		tcc->tdata.state = PATH_TIMEOUT;
+-		tcc->tdata.msgid = MSG_TUR_TIMEOUT;
+-		/* fallthrough */
+-	case RUNNER_DONE:
+-		release_runner(tcc->rtx);
+-		tcc->rtx = NULL;
+-		tcc->last_runner_state = rc;
+-		tcc->nr_timeouts = 0;
+-		condlog(rc == RUNNER_DONE ? 4 : 3,
+-			"%d:%d : tur checker finished, state %s, runner state %s",
+-			major(tcc->tdata.devt), minor(tcc->tdata.devt),
+-			checker_state_name(tcc->tdata.state),
+-			runner_state_name(rc));
+-		break;
+-	case RUNNER_CANCELLED:
+-		tcc->last_runner_state = rc;
+-		tcc->tdata.state = PATH_TIMEOUT;
+-		tcc->tdata.msgid = MSG_TUR_TIMEOUT;
+-		if (tcc->nr_timeouts < MAX_NR_TIMEOUTS) {
+-			condlog(3, "%d:%d : tur checker timed out, releasing it",
+-				major(tcc->tdata.devt), minor(tcc->tdata.devt));
+-			tcc->nr_timeouts++;
+-			release_runner(tcc->rtx);
+-			tcc->rtx = NULL;
+-		} else if (tcc->nr_timeouts == MAX_NR_TIMEOUTS) {
+-			tcc->nr_timeouts++;
+-			condlog(3, "%d:%d : tur checker timed out, waiting for it",
+-				major(tcc->tdata.devt), minor(tcc->tdata.devt));
+-		}
+-		break;
+-	default:
+-		condlog(4, "%d:%d : tur checker still running",
+-			major(tcc->tdata.devt), minor(tcc->tdata.devt));
+-		tcc->tdata.msgid = MSG_TUR_RUNNING;
+-		break;
+-	}
+-	return rc;
+-}
+-
+-bool libcheck_need_wait(struct checker *c)
+-{
+-	struct tur_checker_context *ct = c->context;
+-
+-	return ct && ct->rtx;
+-}
+-
+-int libcheck_pending(struct checker *c)
+-{
+-	struct tur_checker_context *ct = c->context;
+-	/* The if path checker isn't running, just return the exiting value. */
+-	if (!ct || !ct->rtx)
+-		return c->path_state;
+-
+-	/* This may nullify ct->rtx */
+-	check_runner_state(ct);
+-	c->msgid = ct->tdata.msgid;
+-	return ct->tdata.state;
+-}
+-
+-int libcheck_check(struct checker * c)
+-{
+-	struct tur_checker_context *ct = c->context;
+-
+-	if (!ct)
+-		return PATH_UNCHECKED;
+-
+-	if (checker_is_sync(c))
+-		return tur_check(c->fd, c->timeout, &c->msgid);
+-
+-	/* Handle the case that the checker just completed */
+-	if (ct->rtx) {
+-		check_runner_state(ct);
+-		c->msgid = ct->tdata.msgid;
+-		return ct->tdata.state;
+-	}
+-
+-	/* create new checker thread */
+-	ct->tdata.fd = c->fd;
+-	ct->tdata.timeout = c->timeout;
+-
+-	ct->tdata.state = PATH_PENDING;
+-	ct->tdata.msgid = MSG_TUR_RUNNING;
+-	condlog(3, "%d:%d : starting checker", major(ct->tdata.devt),
+-		minor(ct->tdata.devt));
+-	ct->rtx = get_runner(runner_callback, &ct->tdata, sizeof(ct->tdata),
+-			     1000000 * c->timeout);
+-
+-	if (ct->rtx) {
+-		c->msgid = ct->tdata.msgid;
+-		return ct->tdata.state;
+-	} else {
+-		condlog(3, "%d:%d : failed to start tur thread, using sync mode",
+-			major(ct->tdata.devt), minor(ct->tdata.devt));
+-		return tur_check(c->fd, c->timeout, &c->msgid);
+-	}
+-}
 -- 
 2.54.0
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help