From c682d02ebf89177ec22375c833f06d07c485e2cf Mon Sep 17 00:00:00 2001 From: Yan Burman Date: Wed, 10 Sep 2014 08:53:00 +0000 Subject: [PATCH] isert: Fix possible deadlock when calling cancel_work_sync() on the workqueue we are running from Signed-off-by: Yan Burman git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/iser@5789 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/isert-scst/iser.h | 1 + iscsi-scst/kernel/isert-scst/iser_rdma.c | 28 +++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/iscsi-scst/kernel/isert-scst/iser.h b/iscsi-scst/kernel/isert-scst/iser.h index e0ba95d6c..d4cde7d98 100644 --- a/iscsi-scst/kernel/isert-scst/iser.h +++ b/iscsi-scst/kernel/isert-scst/iser.h @@ -161,6 +161,7 @@ struct isert_connection { unsigned long flags; struct work_struct close_work; + struct work_struct drain_work; struct isert_wr drain_wr; struct kref kref; diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index 710ab8a6b..4e402520a 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -486,6 +486,32 @@ static const char *wr_status_str(enum ib_wc_status status) } } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void isert_conn_drained_do_work(void *ctx) +#else +static void isert_conn_drained_do_work(struct work_struct *work) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct isert_connection *isert_conn = ctx; +#else + struct isert_connection *isert_conn = + container_of(work, struct isert_connection, drain_work); +#endif + + isert_conn_free(isert_conn); +} + +static void isert_sched_conn_drained(struct isert_connection *isert_conn) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&isert_conn->drain_work, isert_conn_drained_do_work, isert_conn); +#else + INIT_WORK(&isert_conn->drain_work, isert_conn_drained_do_work); +#endif + isert_conn_queue_work(&isert_conn->drain_work); +} + static void isert_handle_wc_error(struct ib_wc *wc) { struct isert_wr *wr = _u64_to_ptr(wc->wr_id); @@ -505,7 +531,7 @@ static void isert_handle_wc_error(struct ib_wc *wc) /* notify upper layer */ if (!test_bit(ISERT_CONNECTION_ABORTED, &isert_conn->flags)) isert_connection_closed(&isert_conn->iscsi); - isert_conn_free(isert_conn); + isert_sched_conn_drained(isert_conn); } else { isert_pdu_err(&isert_pdu->iscsi); }