iscsi-scst: fix possible recursive locking

cmnd_done() called from cmnd_put() can take cmd_list_lock, so it must
not be called under it.

Reported and tested by David Chen <david.chen@osnexus.com>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6821 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2016-03-02 04:13:42 +00:00
parent 068bc3f41e
commit 83d0cb0f46
+15 -15
View File
@@ -81,7 +81,6 @@ again:
spin_lock_bh(&conn->cmd_list_lock);
list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
struct iscsi_cmnd *rsp;
int restart = 0;
TRACE_CONN_CLOSE_DBG("cmd %p, scst_state %x, "
"r2t_len_to_receive %d, ref_cnt %d, parent_req %p, "
@@ -98,6 +97,12 @@ again:
if (cmnd_get_check(cmnd))
continue;
/*
* If we don't unlock here, we are risking to get into
* recursive deadlock in cmnd_done() called from cmnd_put()
*/
spin_unlock_bh(&conn->cmd_list_lock);
for (i = 0; i < cmnd->sg_cnt; i++) {
struct page *page = sg_page(&cmnd->sg[i]);
@@ -106,18 +111,12 @@ again:
atomic_read(&page->_count));
if (page->net_priv != NULL) {
if (restart == 0) {
spin_unlock_bh(&conn->cmd_list_lock);
restart = 1;
}
while (page->net_priv != NULL)
iscsi_put_page_callback(page);
}
}
cmnd_put(cmnd);
if (restart)
goto again;
goto again;
}
list_for_each_entry(rsp, &cmnd->rsp_cmd_list,
@@ -133,6 +132,13 @@ again:
if (cmnd_get_check(rsp))
continue;
/*
* If we don't unlock here, we are risking to
* get into recursive deadlock in cmnd_done()
* called from cmnd_put()
*/
spin_unlock_bh(&conn->cmd_list_lock);
for (i = 0; i < rsp->sg_cnt; i++) {
struct page *page =
sg_page(&rsp->sg[i]);
@@ -143,18 +149,12 @@ again:
atomic_read(&page->_count));
if (page->net_priv != NULL) {
if (restart == 0) {
spin_unlock_bh(&conn->cmd_list_lock);
restart = 1;
}
while (page->net_priv != NULL)
iscsi_put_page_callback(page);
}
}
cmnd_put(rsp);
if (restart)
goto again;
goto again;
}
}
}