From 026739d4d498d2fa0c3219e0676d18fac7195de8 Mon Sep 17 00:00:00 2001 From: mlelstv Date: Sun, 5 Jun 2016 04:48:17 +0000 Subject: [PATCH] When stopping a callout, wait until the cleanup thread has processed them. --- sys/dev/iscsi/iscsi_globals.h | 14 ++++++++--- sys/dev/iscsi/iscsi_ioctl.c | 44 ++++++++++++++++++++++++++++------- sys/dev/iscsi/iscsi_utils.c | 3 ++- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/sys/dev/iscsi/iscsi_globals.h b/sys/dev/iscsi/iscsi_globals.h index d01b2a0435e0..51aab4c01bbd 100644 --- a/sys/dev/iscsi/iscsi_globals.h +++ b/sys/dev/iscsi/iscsi_globals.h @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_globals.h,v 1.16 2016/06/01 05:13:07 mlelstv Exp $ */ +/* $NetBSD: iscsi_globals.h,v 1.17 2016/06/05 04:48:17 mlelstv Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -185,6 +185,14 @@ typedef enum { PDUDISP_WAIT /* Waiting for acknowledge */ } pdu_disp_t; +/* Timeout state */ + +typedef enum { + TOUT_NONE, /* Initial */ + TOUT_ARMED, /* callout is scheduled */ + TOUT_QUEUED, /* put into timeout queue */ + TOUT_BUSY /* cleanup thread working */ +} tout_state_t; typedef struct connection_s connection_t; typedef struct session_s session_t; @@ -253,7 +261,7 @@ struct ccb_s { struct callout timeout; /* To make sure it isn't lost */ TAILQ_ENTRY(ccb_s) tchain; - bool timedout; + tout_state_t timedout; int num_timeouts; /* How often we've sent out SNACK without answer */ int total_tries; @@ -374,7 +382,7 @@ struct connection_s { struct callout timeout; /* Timeout for checking if connection is dead */ TAILQ_ENTRY(connection_s) tchain; - bool timedout; + tout_state_t timedout; int num_timeouts; /* How often we've sent out a NOP without answer */ uint32_t idle_timeout_val; diff --git a/sys/dev/iscsi/iscsi_ioctl.c b/sys/dev/iscsi/iscsi_ioctl.c index 218ecc523f35..dcdcf450bbd1 100644 --- a/sys/dev/iscsi/iscsi_ioctl.c +++ b/sys/dev/iscsi/iscsi_ioctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_ioctl.c,v 1.17 2016/06/03 06:55:16 mlelstv Exp $ */ +/* $NetBSD: iscsi_ioctl.c,v 1.18 2016/06/05 04:48:17 mlelstv Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -1577,7 +1577,7 @@ connection_timeout_co(void *par) connection_t *conn = par; mutex_enter(&iscsi_cleanup_mtx); - conn->timedout = true; + conn->timedout = TOUT_QUEUED; TAILQ_INSERT_TAIL(&iscsi_timeout_conn_list, conn, tchain); mutex_exit(&iscsi_cleanup_mtx); iscsi_notify_cleanup(); @@ -1586,7 +1586,12 @@ connection_timeout_co(void *par) void connection_timeout_start(connection_t *conn, int ticks) { - callout_schedule(&conn->timeout, ticks); + mutex_enter(&iscsi_cleanup_mtx); + if (conn->timedout != TOUT_QUEUED) { + conn->timedout = TOUT_ARMED; + callout_schedule(&conn->timeout, ticks); + } + mutex_exit(&iscsi_cleanup_mtx); } void @@ -1594,10 +1599,14 @@ connection_timeout_stop(connection_t *conn) { callout_halt(&conn->timeout, NULL); mutex_enter(&iscsi_cleanup_mtx); - if (conn->timedout) { + if (conn->timedout == TOUT_QUEUED) { TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, tchain); - conn->timedout = false; + conn->timedout = TOUT_NONE; } + if (curlwp != iscsi_cleanproc) { + while (conn->timedout == TOUT_BUSY) + kpause("connbusy", false, 1, &iscsi_cleanup_mtx); + } mutex_exit(&iscsi_cleanup_mtx); } @@ -1607,7 +1616,7 @@ ccb_timeout_co(void *par) ccb_t *ccb = par; mutex_enter(&iscsi_cleanup_mtx); - ccb->timedout = true; + ccb->timedout = TOUT_QUEUED; TAILQ_INSERT_TAIL(&iscsi_timeout_ccb_list, ccb, tchain); mutex_exit(&iscsi_cleanup_mtx); iscsi_notify_cleanup(); @@ -1616,7 +1625,12 @@ ccb_timeout_co(void *par) void ccb_timeout_start(ccb_t *ccb, int ticks) { - callout_schedule(&ccb->timeout, ticks); + mutex_enter(&iscsi_cleanup_mtx); + if (ccb->timedout != TOUT_QUEUED) { + ccb->timedout = TOUT_ARMED; + callout_schedule(&ccb->timeout, ticks); + } + mutex_exit(&iscsi_cleanup_mtx); } void @@ -1624,10 +1638,14 @@ ccb_timeout_stop(ccb_t *ccb) { callout_halt(&ccb->timeout, NULL); mutex_enter(&iscsi_cleanup_mtx); - if (ccb->timedout) { + if (ccb->timedout == TOUT_QUEUED) { TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, tchain); - ccb->timedout = false; + ccb->timedout = TOUT_NONE; } + if (curlwp != iscsi_cleanproc) { + while (ccb->timedout == TOUT_BUSY) + kpause("ccbbusy", false, 1, &iscsi_cleanup_mtx); + } mutex_exit(&iscsi_cleanup_mtx); } @@ -1727,16 +1745,24 @@ iscsi_cleanup_thread(void *par) /* handle ccb timeouts */ while ((ccb = TAILQ_FIRST(&iscsi_timeout_ccb_list)) != NULL) { TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, tchain); + KASSERT(ccb->timedout == TOUT_QUEUED); + ccb->timedout = TOUT_BUSY; mutex_exit(&iscsi_cleanup_mtx); ccb_timeout(ccb); mutex_enter(&iscsi_cleanup_mtx); + if (ccb->timedout == TOUT_BUSY) + ccb->timedout = TOUT_NONE; } /* handle connection timeouts */ while ((conn = TAILQ_FIRST(&iscsi_timeout_conn_list)) != NULL) { TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, tchain); + KASSERT(conn->timedout == TOUT_QUEUED); + conn->timedout = TOUT_BUSY; mutex_exit(&iscsi_cleanup_mtx); connection_timeout(conn); mutex_enter(&iscsi_cleanup_mtx); + if (conn->timedout == TOUT_BUSY) + conn->timedout = TOUT_NONE; } /* if timed out, not woken up */ diff --git a/sys/dev/iscsi/iscsi_utils.c b/sys/dev/iscsi/iscsi_utils.c index a06863afbc06..422580a585b4 100644 --- a/sys/dev/iscsi/iscsi_utils.c +++ b/sys/dev/iscsi/iscsi_utils.c @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_utils.c,v 1.12 2016/06/05 04:36:05 mlelstv Exp $ */ +/* $NetBSD: iscsi_utils.c,v 1.13 2016/06/05 04:48:17 mlelstv Exp $ */ /*- * Copyright (c) 2004,2005,2006,2008 The NetBSD Foundation, Inc. @@ -239,6 +239,7 @@ get_ccb(connection_t *conn, bool waitok) mutex_exit(&sess->lock); ccb->flags = 0; + ccb->timedout = TOUT_NONE; ccb->xs = NULL; ccb->temp_data = NULL; ccb->text_data = NULL;