[SCSI] iscsi bugfixes: fix oops when iser is flushing io

When we enter recovery and flush the running commands
we cannot freee the connection before flushing the commands.
Some commands may have a reference to the connection
that needs to be released before. iscsi_stop was forcing
the term and suspend too early and was causing a oops
in iser, so this patch removes those callbacks all together
and allows the LLD to handle that detail.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Mike Christie
2006-07-24 15:47:26 -05:00
committed by James Bottomley
parent 7ea8b82847
commit 1c83469d36
4 changed files with 34 additions and 71 deletions

View File

@@ -1040,9 +1040,8 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn)
}
static void
iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct sock *sk = tcp_conn->sock->sk;
/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
@@ -1932,6 +1931,23 @@ tcp_conn_alloc_fail:
return NULL;
}
static void
iscsi_tcp_release_conn(struct iscsi_conn *conn)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
if (!tcp_conn->sock)
return;
sock_hold(tcp_conn->sock->sk);
iscsi_conn_restore_callbacks(tcp_conn);
sock_put(tcp_conn->sock->sk);
sock_release(tcp_conn->sock);
tcp_conn->sock = NULL;
conn->recv_lock = NULL;
}
static void
iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
{
@@ -1942,6 +1958,7 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
if (conn->hdrdgst_en || conn->datadgst_en)
digest = 1;
iscsi_tcp_release_conn(conn);
iscsi_conn_teardown(cls_conn);
/* now free tcp_conn */
@@ -1965,6 +1982,15 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
kfree(tcp_conn);
}
static void
iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
{
struct iscsi_conn *conn = cls_conn->dd_data;
iscsi_conn_stop(cls_conn, flag);
iscsi_tcp_release_conn(conn);
}
static int
iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
@@ -2013,38 +2039,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
return 0;
}
static void
iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct sock *sk;
if (!tcp_conn->sock)
return;
sk = tcp_conn->sock->sk;
write_lock_bh(&sk->sk_callback_lock);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
write_unlock_bh(&sk->sk_callback_lock);
}
static void
iscsi_tcp_terminate_conn(struct iscsi_conn *conn)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
if (!tcp_conn->sock)
return;
sock_hold(tcp_conn->sock->sk);
iscsi_conn_restore_callbacks(conn);
sock_put(tcp_conn->sock->sk);
sock_release(tcp_conn->sock);
tcp_conn->sock = NULL;
conn->recv_lock = NULL;
}
/* called with host lock */
static void
iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
@@ -2413,10 +2407,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
.get_conn_param = iscsi_tcp_conn_get_param,
.get_session_param = iscsi_session_get_param,
.start_conn = iscsi_conn_start,
.stop_conn = iscsi_conn_stop,
/* these are called as part of conn recovery */
.suspend_conn_recv = iscsi_tcp_suspend_conn_rx,
.terminate_conn = iscsi_tcp_terminate_conn,
.stop_conn = iscsi_tcp_conn_stop,
/* IO */
.send_pdu = iscsi_conn_send_pdu,
.get_stats = iscsi_conn_get_stats,