From f9b9d824c6c6cb70b5962a0a48f8ce8d41676dc7 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Fri, 6 Mar 2009 19:04:48 +0000 Subject: [PATCH] Session and connection reinstation fixes for cases when they are shutting down and request for reinstation comes. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@692 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/conn.c | 3 ++- iscsi-scst/kernel/iscsi.h | 6 ++++-- iscsi-scst/kernel/nthread.c | 25 +++++++++++++++++++------ iscsi-scst/kernel/session.c | 6 ++++-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index 40e05db89..238464fbc 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -394,6 +394,7 @@ int conn_free(struct iscsi_conn *conn) sBUG_ON(!list_empty(&conn->write_list)); sBUG_ON(!list_empty(&conn->written_list)); sBUG_ON(conn->conn_reinst_successor != NULL); + sBUG_ON(!conn->conn_shutting_down); if (conn->conn_reinstating) { struct iscsi_conn *c; @@ -504,7 +505,7 @@ int conn_add(struct iscsi_session *session, struct iscsi_kern_conn_info *info) bool reinstatement = false; conn = conn_lookup(session, info->cid); - if (conn != NULL) { + if ((conn != NULL) && !conn->conn_shutting_down) { /* conn reinstatement */ reinstatement = true; } else if (!list_empty(&session->conn_list)) { diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index 6049cf787..a57fc6242 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -114,9 +114,10 @@ struct iscsi_session { struct list_head session_list_entry; - /* All don't need any protection */ + /* All protected by target_mutex, where necessary */ struct iscsi_session *sess_reinst_successor; unsigned int sess_reinstating:1; + unsigned int sess_shutting_down:1; /* All don't need any protection */ char *initiator_name; @@ -218,9 +219,10 @@ struct iscsi_conn { struct list_head conn_list_entry; /* list entry in session conn_list */ - /* All don't need any protection */ + /* All protected by target_mutex, where necessary */ struct iscsi_conn *conn_reinst_successor; unsigned int conn_reinstating:1; + unsigned int conn_shutting_down:1; struct completion ready_to_free; diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 5a629d538..98336ec02 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -358,10 +358,11 @@ static void close_conn(struct iscsi_conn *conn) { struct iscsi_session *session = conn->session; struct iscsi_target *target = conn->target; + struct iscsi_conn *c; typeof(jiffies) start_waiting = jiffies; typeof(jiffies) shut_start_waiting = start_waiting; bool pending_reported = 0, wait_expired = 0, shut_expired = 0; - bool free_sess; + bool reinst; #define CONN_PENDING_TIMEOUT ((typeof(jiffies))10*HZ) #define CONN_WAIT_TIMEOUT ((typeof(jiffies))10*HZ) @@ -385,7 +386,22 @@ static void close_conn(struct iscsi_conn *conn) RCV_SHUTDOWN|SEND_SHUTDOWN); } - if (conn->conn_reinst_successor != NULL) { + mutex_lock(&session->target->target_mutex); + + conn->conn_shutting_down = 1; + reinst = (conn->conn_reinst_successor != NULL); + + session->sess_shutting_down = 1; + list_for_each_entry(c, &session->conn_list, conn_list_entry) { + if (!c->conn_shutting_down) { + session->sess_shutting_down = 0; + break; + } + } + + mutex_unlock(&session->target->target_mutex); + + if (reinst) { int rc; int lun = 0; @@ -525,14 +541,11 @@ static void close_conn(struct iscsi_conn *conn) mutex_lock(&target->target_mutex); - free_sess = (conn->conn_reinst_successor == NULL); conn->conn_reinst_successor = NULL; - conn_free(conn); - if (free_sess) { + if (list_empty(&session->conn_list)) { sBUG_ON(session->sess_reinst_successor != NULL); - /* ToDo: this is incompatible with MC/S */ session_free(session); } diff --git a/iscsi-scst/kernel/session.c b/iscsi-scst/kernel/session.c index f81688d88..821ad9469 100644 --- a/iscsi-scst/kernel/session.c +++ b/iscsi-scst/kernel/session.c @@ -184,8 +184,10 @@ int session_add(struct iscsi_target *target, i.id.tsih = 0; if ((sid.id64 == i.id64) && (strcmp(info->initiator_name, session->initiator_name) == 0)) { - /* session reinstatement */ - old_sess = session; + if (!session->sess_shutting_down) { + /* session reinstatement */ + old_sess = session; + } break; } }