From mboxrd@z Thu Jan 1 00:00:00 1970 From: Martin Wilck Subject: [PATCH 6/8] libmultipath: test code for "zombie" TUR threads Date: Wed, 10 Oct 2018 22:05:04 +0200 Message-ID: <20181010200506.15796-7-mwilck@suse.com> References: <20181010200506.15796-1-mwilck@suse.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <20181010200506.15796-1-mwilck@suse.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com To: Christophe Varoqui Cc: dm-devel@redhat.com, Martin Wilck List-Id: dm-devel.ids This patch adds test code that simulates hanging, non-cancellable TUR threads, for testing multipathd's behavior in that situation. Compile libmultipath with CFLAGS=-DTUR_TEST_MAJOR=8 to activate the test code. Without that flag, the patch has no effect. Signed-off-by: Martin Wilck --- libmultipath/checkers/tur.c | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c index b2a21707..a986a244 100644 --- a/libmultipath/checkers/tur.c +++ b/libmultipath/checkers/tur.c @@ -196,6 +196,50 @@ static void cleanup_func(void *data) rcu_unregister_thread(); } +/* + * 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_checker_context *ct) +{ + static int sleep_cnt; + const struct timespec ts = { .tv_sec = TUR_SLEEP_SECS, .tv_nsec = 0 }; + int oldstate; + + if (ct->devt != makedev(TUR_TEST_MAJOR, TUR_TEST_MINOR) || + ++sleep_cnt % TUR_SLEEP_INTERVAL != 0) + return; + + condlog(1, "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(1, "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 */ + static void *tur_thread(void *ctx) { struct tur_checker_context *ct = ctx; @@ -209,6 +253,7 @@ static void *tur_thread(void *ctx) condlog(3, "%d:%d : tur checker starting up", major(ct->devt), minor(ct->devt)); + tur_deep_sleep(ct); state = tur_check(ct->fd, ct->timeout, msg); pthread_testcancel(); -- 2.19.0