From 102603f46d467372f34803412efd7a046bfe9773 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 21 Apr 2009 18:25:46 +0000 Subject: [PATCH] We can't mark sess as shutting down in close_conn(), because at that time it might have pending commands. Otherwise, in case of reinstatement it might lead to data corruption, because commands in being reinstated session can be executed after commands in the new session. Found out by Hari Subramanian git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@792 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/nthread.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 0ed8dcb10..88d427ba7 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -336,8 +336,25 @@ void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd) { struct iscsi_conn *conn = (struct iscsi_conn *)priv; struct iscsi_session *sess = conn->session; + struct iscsi_conn *c; mutex_lock(&sess->target->target_mutex); + + /* + * We can't mark sess as shutting down earlier, because until + * now it might have pending commands. Otherwise, in case of + * reinstatement it might lead to data corruption, because + * commands in being reinstated session can be executed + * after commands in the new session. + */ + sess->sess_shutting_down = 1; + list_for_each_entry(c, &sess->conn_list, conn_list_entry) { + if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &c->conn_aflags)) { + sess->sess_shutting_down = 0; + break; + } + } + if (conn->conn_reinst_successor != NULL) { sBUG_ON(!test_bit(ISCSI_CONN_REINSTATING, &conn->conn_reinst_successor->conn_aflags)); @@ -365,7 +382,6 @@ 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; @@ -398,14 +414,6 @@ static void close_conn(struct iscsi_conn *conn) set_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags); reinst = (conn->conn_reinst_successor != NULL); - session->sess_shutting_down = 1; - list_for_each_entry(c, &session->conn_list, conn_list_entry) { - if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &c->conn_aflags)) { - session->sess_shutting_down = 0; - break; - } - } - mutex_unlock(&session->target->target_mutex); if (reinst) {