mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 21:21:28 +00:00
- Fix for iSCSI RFC violation: TARGET COLD RESET must close all connections/sessions, not only the current one
- Cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@648 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user