aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-07-24 16:47:26 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-07-28 12:48:32 -0400
commit1c83469d36a9dd30dbf1fb9fc5ca3be3a0e64ff4 (patch)
treed20c53420f6596ebd6500562b294ef820a190887 /drivers/scsi
parent7ea8b82847293c2311cf08fc3ed31ab0e452a27e (diff)
[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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c67
-rw-r--r--drivers/scsi/libiscsi.c12
2 files changed, 32 insertions, 47 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7d784596a1ea..b6c68be6b866 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1040,9 +1040,8 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn)
1040} 1040}
1041 1041
1042static void 1042static void
1043iscsi_conn_restore_callbacks(struct iscsi_conn *conn) 1043iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
1044{ 1044{
1045 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1046 struct sock *sk = tcp_conn->sock->sk; 1045 struct sock *sk = tcp_conn->sock->sk;
1047 1046
1048 /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */ 1047 /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
@@ -1933,6 +1932,23 @@ tcp_conn_alloc_fail:
1933} 1932}
1934 1933
1935static void 1934static void
1935iscsi_tcp_release_conn(struct iscsi_conn *conn)
1936{
1937 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1938
1939 if (!tcp_conn->sock)
1940 return;
1941
1942 sock_hold(tcp_conn->sock->sk);
1943 iscsi_conn_restore_callbacks(tcp_conn);
1944 sock_put(tcp_conn->sock->sk);
1945
1946 sock_release(tcp_conn->sock);
1947 tcp_conn->sock = NULL;
1948 conn->recv_lock = NULL;
1949}
1950
1951static void
1936iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) 1952iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
1937{ 1953{
1938 struct iscsi_conn *conn = cls_conn->dd_data; 1954 struct iscsi_conn *conn = cls_conn->dd_data;
@@ -1942,6 +1958,7 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
1942 if (conn->hdrdgst_en || conn->datadgst_en) 1958 if (conn->hdrdgst_en || conn->datadgst_en)
1943 digest = 1; 1959 digest = 1;
1944 1960
1961 iscsi_tcp_release_conn(conn);
1945 iscsi_conn_teardown(cls_conn); 1962 iscsi_conn_teardown(cls_conn);
1946 1963
1947 /* now free tcp_conn */ 1964 /* now free tcp_conn */
@@ -1965,6 +1982,15 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
1965 kfree(tcp_conn); 1982 kfree(tcp_conn);
1966} 1983}
1967 1984
1985static void
1986iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
1987{
1988 struct iscsi_conn *conn = cls_conn->dd_data;
1989
1990 iscsi_conn_stop(cls_conn, flag);
1991 iscsi_tcp_release_conn(conn);
1992}
1993
1968static int 1994static int
1969iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, 1995iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
1970 struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, 1996 struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
@@ -2013,38 +2039,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
2013 return 0; 2039 return 0;
2014} 2040}
2015 2041
2016static void
2017iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
2018{
2019 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
2020 struct sock *sk;
2021
2022 if (!tcp_conn->sock)
2023 return;
2024
2025 sk = tcp_conn->sock->sk;
2026 write_lock_bh(&sk->sk_callback_lock);
2027 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
2028 write_unlock_bh(&sk->sk_callback_lock);
2029}
2030
2031static void
2032iscsi_tcp_terminate_conn(struct iscsi_conn *conn)
2033{
2034 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
2035
2036 if (!tcp_conn->sock)
2037 return;
2038
2039 sock_hold(tcp_conn->sock->sk);
2040 iscsi_conn_restore_callbacks(conn);
2041 sock_put(tcp_conn->sock->sk);
2042
2043 sock_release(tcp_conn->sock);
2044 tcp_conn->sock = NULL;
2045 conn->recv_lock = NULL;
2046}
2047
2048/* called with host lock */ 2042/* called with host lock */
2049static void 2043static void
2050iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, 2044iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
@@ -2413,10 +2407,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
2413 .get_conn_param = iscsi_tcp_conn_get_param, 2407 .get_conn_param = iscsi_tcp_conn_get_param,
2414 .get_session_param = iscsi_session_get_param, 2408 .get_session_param = iscsi_session_get_param,
2415 .start_conn = iscsi_conn_start, 2409 .start_conn = iscsi_conn_start,
2416 .stop_conn = iscsi_conn_stop, 2410 .stop_conn = iscsi_tcp_conn_stop,
2417 /* these are called as part of conn recovery */
2418 .suspend_conn_recv = iscsi_tcp_suspend_conn_rx,
2419 .terminate_conn = iscsi_tcp_terminate_conn,
2420 /* IO */ 2411 /* IO */
2421 .send_pdu = iscsi_conn_send_pdu, 2412 .send_pdu = iscsi_conn_send_pdu,
2422 .get_stats = iscsi_conn_get_stats, 2413 .get_stats = iscsi_conn_get_stats,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 4e2ca8f7d9a1..36f520b9260e 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1440,12 +1440,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
1440 1440
1441 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); 1441 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1442 mutex_lock(&conn->xmitmutex); 1442 mutex_lock(&conn->xmitmutex);
1443 if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
1444 if (session->tt->suspend_conn_recv)
1445 session->tt->suspend_conn_recv(conn);
1446
1447 session->tt->terminate_conn(conn);
1448 }
1449 1443
1450 spin_lock_bh(&session->lock); 1444 spin_lock_bh(&session->lock);
1451 conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; 1445 conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
@@ -1622,8 +1616,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
1622 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); 1616 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1623 spin_unlock_bh(&session->lock); 1617 spin_unlock_bh(&session->lock);
1624 1618
1625 if (session->tt->suspend_conn_recv) 1619 write_lock_bh(conn->recv_lock);
1626 session->tt->suspend_conn_recv(conn); 1620 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
1621 write_unlock_bh(conn->recv_lock);
1627 1622
1628 mutex_lock(&conn->xmitmutex); 1623 mutex_lock(&conn->xmitmutex);
1629 /* 1624 /*
@@ -1642,7 +1637,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
1642 } 1637 }
1643 } 1638 }
1644 1639
1645 session->tt->terminate_conn(conn);
1646 /* 1640 /*
1647 * flush queues. 1641 * flush queues.
1648 */ 1642 */