- Fix for iSCSI RFC violation: TARGET COLD RESET must close all connections/sessions...
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 29 Jan 2009 18:25:45 +0000 (18:25 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 29 Jan 2009 18:25:45 +0000 (18:25 +0000)
 - Cleanups

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@648 d57e44dd-8a1f-0410-8b47-8ef2f437770f

iscsi-scst/kernel/iscsi.c
iscsi-scst/kernel/iscsi.h
iscsi-scst/kernel/nthread.c
iscsi-scst/kernel/session.c
iscsi-scst/kernel/target.c

index 64a38d9..d2eb2b7 100644 (file)
@@ -100,6 +100,7 @@ static inline void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd)
        cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
        scst_restart_cmd(cmnd->scst_cmd, SCST_PREPROCESS_STATUS_SUCCESS,
                SCST_CONTEXT_THREAD);
+       return;
 }
 
 static inline void iscsi_restart_waiting_cmnd(struct iscsi_cmnd *cmnd)
@@ -112,6 +113,7 @@ static inline void iscsi_restart_waiting_cmnd(struct iscsi_cmnd *cmnd)
        cmnd->data_waiting = 0;
 
        iscsi_restart_cmnd(cmnd);
+       return;
 }
 
 static inline void iscsi_fail_waiting_cmnd(struct iscsi_cmnd *cmnd)
@@ -758,6 +760,7 @@ static void iscsi_cmnd_reject(struct iscsi_cmnd *req, int reason)
                                         ISCSI_INIT_WRITE_WAKE);
 
        cmnd_prepare_get_rejected_cmd_data(req);
+       return;
 }
 
 static inline int iscsi_get_allowed_cmds(struct iscsi_session *sess)
@@ -802,6 +805,7 @@ static void __update_stat_sn(struct iscsi_cmnd *cmnd)
                /* free pdu resources */
                cmnd->conn->exp_stat_sn = exp_stat_sn;
        }
+       return;
 }
 
 static inline void update_stat_sn(struct iscsi_cmnd *cmnd)
@@ -809,6 +813,7 @@ static inline void update_stat_sn(struct iscsi_cmnd *cmnd)
        spin_lock(&cmnd->conn->session->sn_lock);
        __update_stat_sn(cmnd);
        spin_unlock(&cmnd->conn->session->sn_lock);
+       return;
 }
 
 /* Called under sn_lock */
@@ -932,6 +937,7 @@ static void cmnd_remove_hash(struct iscsi_cmnd *cmnd)
        }
 
        spin_unlock(&session->cmnd_hash_lock);
+       return;
 }
 
 static void cmnd_prepare_get_rejected_cmd_data(struct iscsi_cmnd *cmnd)
@@ -1997,6 +2003,7 @@ static void noop_out_exec(struct iscsi_cmnd *req)
                req_cmnd_release(req);
        } else
                cmnd_put(req);
+       return;
 }
 
 static void logout_exec(struct iscsi_cmnd *req)
@@ -2019,6 +2026,7 @@ static void logout_exec(struct iscsi_cmnd *req)
        iscsi_cmnd_init_write(rsp,
                ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
        req_cmnd_release(req);
+       return;
 }
 
 static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd)
@@ -2094,6 +2102,7 @@ static void __cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd,
 
        conn->write_offset = offset;
        conn->write_size += size;
+       return;
 }
 
 static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
@@ -2107,6 +2116,7 @@ static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
        sBUG_ON(cmnd->sg == NULL);
        sBUG_ON(cmnd->bufflen != size);
        __cmnd_send_pdu(conn, cmnd, 0, size);
+       return;
 }
 
 /*
@@ -2125,6 +2135,7 @@ static void set_cork(struct socket *sock, int on)
        sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK,
                              (void __force __user *)&opt, sizeof(opt));
        set_fs(oldfs);
+       return;
 }
 
 void cmnd_tx_start(struct iscsi_cmnd *cmnd)
@@ -2190,14 +2201,16 @@ void cmnd_tx_start(struct iscsi_cmnd *cmnd)
        /* move this? */
        conn->write_size = (conn->write_size + 3) & -4;
        iscsi_dump_pdu(&cmnd->pdu);
+       return;
 }
 
 void cmnd_tx_end(struct iscsi_cmnd *cmnd)
 {
        struct iscsi_conn *conn = cmnd->conn;
 
-       TRACE_DBG("%p:%x (should_close_conn %d)", cmnd, cmnd_opcode(cmnd),
-               cmnd->should_close_conn);
+       TRACE_DBG("%p:%x (should_close_conn %d, should_close_all_conn %d)",
+               cmnd, cmnd_opcode(cmnd), cmnd->should_close_conn,
+               cmnd->should_close_all_conn);
 
        switch (cmnd_opcode(cmnd)) {
        case ISCSI_OP_NOOP_IN:
@@ -2216,13 +2229,22 @@ void cmnd_tx_end(struct iscsi_cmnd *cmnd)
                break;
        }
 
-       if (cmnd->should_close_conn) {
-               PRINT_INFO("Closing connection at initiator %s request",
-                       conn->session->initiator_name);
-               mark_conn_closed(conn);
+       if (unlikely(cmnd->should_close_conn)) {
+               if (cmnd->should_close_all_conn) {
+                       PRINT_INFO("Closing all connections for target %x at "
+                               "initiator's %s request",
+                               cmnd->conn->session->target->tid,
+                               conn->session->initiator_name);
+                       target_del_all_sess(cmnd->conn->session->target, false);
+               } else {
+                       PRINT_INFO("Closing connection at initiator's %s "
+                               "request", conn->session->initiator_name);
+                       mark_conn_closed(conn);
+               }
        }
 
        set_cork(cmnd->conn->sock, 0);
+       return;
 }
 
 /*
@@ -2807,8 +2829,10 @@ static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
        rsp_hdr->itt = req_hdr->itt;
        rsp_hdr->response = status;
 
-       if (fn == ISCSI_FUNCTION_TARGET_COLD_RESET)
+       if (fn == ISCSI_FUNCTION_TARGET_COLD_RESET) {
                rsp->should_close_conn = 1;
+               rsp->should_close_all_conn = 1;
+       }
 
        sBUG_ON(sess->tm_rsp != NULL);
 
@@ -2946,6 +2970,7 @@ static void iscsi_stop_threads(void)
                list_del(&t->threads_list_entry);
                kfree(t);
        }
+       return;
 }
 
 static int __init iscsi_init(void)
index 750db9c..fbfca4f 100644 (file)
@@ -261,6 +261,7 @@ struct iscsi_cmnd {
         */
        unsigned int hashed:1;
        unsigned int should_close_conn:1;
+       unsigned int should_close_all_conn:1;
        unsigned int pending:1;
        unsigned int own_sg:1;
        unsigned int on_write_list:1;
@@ -391,6 +392,7 @@ extern int istwr(void *arg);
 struct iscsi_target *target_lookup_by_id(u32);
 extern int target_add(struct target_info *);
 extern int target_del(u32 id);
+extern void target_del_all_sess(struct iscsi_target *target, bool deleting);
 extern void target_del_all(void);
 
 /* config.c */
index 4109963..9ce66ef 100644 (file)
@@ -219,6 +219,7 @@ static void free_pending_commands(struct iscsi_conn *conn)
                }
        } while (req_freed);
        spin_unlock(&session->sn_lock);
+       return;
 }
 
 static void free_orphaned_pending_commands(struct iscsi_conn *conn)
@@ -257,6 +258,7 @@ static void free_orphaned_pending_commands(struct iscsi_conn *conn)
                }
        } while (req_freed);
        spin_unlock(&session->sn_lock);
+       return;
 }
 
 #ifdef CONFIG_SCST_DEBUG
@@ -323,6 +325,7 @@ static void trace_conn_close(struct iscsi_conn *conn)
 #endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
        }
        spin_unlock_bh(&conn->cmd_list_lock);
+       return;
 }
 #else /* CONFIG_SCST_DEBUG */
 static void trace_conn_close(struct iscsi_conn *conn) {}
@@ -545,6 +548,7 @@ static inline void iscsi_conn_init_read(struct iscsi_conn *conn,
        conn->read_msg.msg_iov = conn->read_iov;
        conn->read_msg.msg_iovlen = 1;
        conn->read_size = (len + 3) & -4;
+       return;
 }
 
 static void iscsi_conn_read_ahs(struct iscsi_conn *conn,
@@ -555,6 +559,7 @@ static void iscsi_conn_read_ahs(struct iscsi_conn *conn,
        sBUG_ON(cmnd->pdu.ahs == NULL);
        iscsi_conn_init_read(conn, (void __force __user *)cmnd->pdu.ahs,
                cmnd->pdu.ahssize);
+       return;
 }
 
 static struct iscsi_cmnd *iscsi_get_send_cmnd(struct iscsi_conn *conn)
@@ -923,6 +928,7 @@ static inline void __iscsi_get_page_callback(struct iscsi_cmnd *cmd)
                TRACE_NET_PAGE("getting cmd %p", cmd);
                cmnd_get(cmd);
        }
+       return;
 }
 
 void iscsi_get_page_callback(struct page *page)
@@ -933,6 +939,7 @@ void iscsi_get_page_callback(struct page *page)
                atomic_read(&page->_count));
 
        __iscsi_get_page_callback(cmd);
+       return;
 }
 
 static inline void __iscsi_put_page_callback(struct iscsi_cmnd *cmd)
@@ -950,6 +957,7 @@ static inline void __iscsi_put_page_callback(struct iscsi_cmnd *cmd)
                }
                cmnd_put(cmd);
        }
+       return;
 }
 
 void iscsi_put_page_callback(struct page *page)
@@ -960,6 +968,7 @@ void iscsi_put_page_callback(struct page *page)
                atomic_read(&page->_count));
 
        __iscsi_put_page_callback(cmd);
+       return;
 }
 
 static void check_net_priv(struct iscsi_cmnd *cmd, struct page *page)
@@ -969,6 +978,7 @@ static void check_net_priv(struct iscsi_cmnd *cmd, struct page *page)
                        "%p (page %p)", page->net_priv, page);
                page->net_priv = NULL;
        }
+       return;
 }
 #else
 static inline void check_net_priv(struct iscsi_cmnd *cmd, struct page *page) {}
index 8ada3f4..0e3ef40 100644 (file)
@@ -183,12 +183,13 @@ 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:%llu initiator:%s shutting down %d\n",
+               seq_printf(seq, "\tsid:%llx initiator:%s shutting down %d\n",
                        (long long unsigned int)session->sid,
                        session->initiator_name,
                        session->shutting_down);
                conn_info_show(seq, session);
        }
+       return;
 }
 
 static int iscsi_sessions_info_show(struct seq_file *seq, void *v)
index dd1648e..278dcdf 100644 (file)
@@ -216,16 +216,20 @@ out:
 }
 
 static void target_del_session(struct iscsi_target *target,
-                              struct iscsi_session *session)
+       struct iscsi_session *session, bool deleting)
 {
+       int flags = ISCSI_CONN_ACTIVE_CLOSE;
+
+       if (deleting)
+               flags |= ISCSI_CONN_DELETING;
+
        TRACE_MGMT_DBG("Cleaning up session %p", session);
        if (!list_empty(&session->conn_list)) {
                struct iscsi_conn *conn, *tc;
                list_for_each_entry_safe(conn, tc, &session->conn_list,
                                         conn_list_entry) {
                        TRACE_MGMT_DBG("Mark conn %p closing", conn);
-                       __mark_conn_closed(conn,
-                               ISCSI_CONN_ACTIVE_CLOSE|ISCSI_CONN_DELETING);
+                       __mark_conn_closed(conn, flags);
                }
        } else {
                TRACE_MGMT_DBG("Freeing session %p without connections",
@@ -234,6 +238,25 @@ static void target_del_session(struct iscsi_target *target,
        }
 }
 
+/* target_mutex supposed to be locked */
+void target_del_all_sess(struct iscsi_target *target, bool deleting)
+{
+       struct iscsi_session *session, *ts;
+
+       TRACE_ENTRY();
+
+       if (!list_empty(&target->session_list)) {
+               TRACE_MGMT_DBG("Deleting all sessions from target %p", target);
+               list_for_each_entry_safe(session, ts, &target->session_list,
+                                               session_list_entry) {
+                       target_del_session(target, session, deleting);
+               }
+       }
+
+       TRACE_EXIT();
+       return;
+}
+
 void target_del_all(void)
 {
        struct iscsi_target *target, *t;
@@ -251,16 +274,9 @@ void target_del_all(void)
 
                list_for_each_entry_safe(target, t, &target_list,
                                         target_list_entry) {
-                       struct iscsi_session *session, *ts;
                        mutex_lock(&target->target_mutex);
                        if (!list_empty(&target->session_list)) {
-                               TRACE_MGMT_DBG("Cleaning up target %p",
-                                              target);
-                               list_for_each_entry_safe(session, ts,
-                                               &target->session_list,
-                                               session_list_entry) {
-                                       target_del_session(target, session);
-                               }
+                               target_del_all_sess(target, true);
                                mutex_unlock(&target->target_mutex);
                        } else {
                                TRACE_MGMT_DBG("Deleting target %p", target);