From e9008a5b12dfd2fb54ff892605543d07841e7d2a Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 11 Sep 2012 20:38:57 +0000 Subject: [PATCH] Fix possible BUG_ON() on multiple forced commands release git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4513 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/iscsi.c | 26 +++++++++++++++++++++++++- iscsi-scst/kernel/iscsi.h | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 190670a50..d6b502728 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -542,7 +542,30 @@ void req_cmnd_release_force(struct iscsi_cmnd *req) TRACE_ENTRY(); - TRACE_MGMT_DBG("req %p", req); + if (req->force_release_done) { + /* + * There are some scenarios when this function can be called + * more, than once, for the same req. For instance, dropped + * command in iscsi_push_cmnd() and then for it + * iscsi_fail_data_waiting_cmnd() during closing (aborting) this + * connection or from iscsi_check_tm_data_wait_timeouts(). + */ + TRACE_MGMT_DBG("Double force release for req %p", req); + + EXTRACHECKS_BUG_ON(!req->release_called); + sBUG_ON(req->hashed); + sBUG_ON(req->cmd_req); + sBUG_ON(req->main_rsp != NULL); + sBUG_ON(!list_empty(&req->rx_ddigest_cmd_list)); + sBUG_ON(!list_empty(&req->rsp_cmd_list)); + sBUG_ON(req->pending); + + cmnd_put(req); + goto out; + } else + TRACE_MGMT_DBG("req %p", req); + + req->force_release_done = 1; sBUG_ON(req == conn->read_cmnd); @@ -601,6 +624,7 @@ void req_cmnd_release_force(struct iscsi_cmnd *req) req_cmnd_release(req); +out: TRACE_EXIT(); return; } diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index cf0faf99a..06a6d84d3 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -384,6 +384,7 @@ struct iscsi_cmnd { * req_cmnd_release() supposed to be called only once. */ unsigned int data_out_in_data_receiving:1; + unsigned int force_release_done:1; #ifdef CONFIG_SCST_EXTRACHECKS unsigned int on_rx_digest_list:1; unsigned int release_called:1;