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.
Signed-off-by: Martin Wilck <[email protected]> --- libmultipath/checkers/tur.c | 251 +++--------------------------------- 1 file changed, 15 insertions(+), 236 deletions(-) diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c index 6791172..757767a 100644 --- a/libmultipath/checkers/tur.c +++ b/libmultipath/checkers/tur.c @@ -3,87 +3,31 @@ * * 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_FAILED = CHECKER_FIRST_MSGID, MSG_TUR_TRANSITIONING, }; #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 +43,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 +58,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 +103,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 +120,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
