[PATCH v2 12/19] libmultipath: convert TUR checker to an async checker instance

Martin Wilck <[email protected]>
Newsgroups dev.linux.lists.dm-devel
Message-ID <[email protected]>
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 <[email protected]>
---
 libmultipath/checkers.h     |   3 -
 libmultipath/checkers/tur.c | 253 +++---------------------------------
 2 files changed, 15 insertions(+), 241 deletions(-)

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 <stdlib.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 "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,
 };
 
 #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;
-};
-
-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 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;
 		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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.