Fixes deadlock on iSCSI session freeing. Reported by andy yan <andyysj@gmail.com>

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@718 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-03-25 13:03:29 +00:00
parent bc96b052d5
commit 8ff3e56ef6
3 changed files with 17 additions and 5 deletions

View File

@@ -122,6 +122,7 @@ struct iscsi_session {
struct iscsi_session *sess_reinst_successor;
unsigned int sess_reinstating:1;
unsigned int sess_shutting_down:1;
unsigned int deleted_from_session_list:1;
/* All don't need any protection */
char *initiator_name;

View File

@@ -552,6 +552,17 @@ static void close_conn(struct iscsi_conn *conn)
if (list_empty(&session->conn_list)) {
sBUG_ON(session->sess_reinst_successor != NULL);
list_del(&session->session_list_entry);
session->deleted_from_session_list = 1;
mutex_unlock(&target->target_mutex);
if (session->scst_sess != NULL) {
scst_unregister_session(session->scst_sess, 1, NULL);
session->scst_sess = NULL;
}
mutex_lock(&target->target_mutex);
session_free(session);
}

View File

@@ -215,8 +215,7 @@ int session_free(struct iscsi_session *session)
for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++)
sBUG_ON(!list_empty(&session->cmnd_hash[i]));
if (session->scst_sess != NULL)
scst_unregister_session(session->scst_sess, 1, NULL);
sBUG_ON(session->scst_sess != NULL);
if (session->sess_reinst_successor != NULL)
sess_enable_reinstated_sess(session->sess_reinst_successor);
@@ -233,7 +232,8 @@ int session_free(struct iscsi_session *session)
}
}
list_del(&session->session_list_entry);
if (!session->deleted_from_session_list)
list_del(&session->session_list_entry);
kfree(session->initiator_name);
kfree(session);
@@ -267,10 +267,10 @@ static void iscsi_session_info_show(struct seq_file *seq,
list_for_each_entry(session, &target->session_list,
session_list_entry) {
seq_printf(seq, "\tsid:%llx initiator:%s reinstating %d\n",
seq_printf(seq, "\tsid:%llx initiator:%s (reinstating %s)\n",
(long long unsigned int)session->sid,
session->initiator_name,
session->sess_reinstating);
session->sess_reinstating ? "yes" : "no");
conn_info_show(seq, session);
}
return;