diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2006-07-24 16:47:26 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-07-28 12:48:32 -0400 |
commit | 1c83469d36a9dd30dbf1fb9fc5ca3be3a0e64ff4 (patch) | |
tree | d20c53420f6596ebd6500562b294ef820a190887 /drivers/scsi | |
parent | 7ea8b82847293c2311cf08fc3ed31ab0e452a27e (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.c | 67 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 12 |
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 | ||
1042 | static void | 1042 | static void |
1043 | iscsi_conn_restore_callbacks(struct iscsi_conn *conn) | 1043 | iscsi_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 | ||
1935 | static void | 1934 | static void |
1935 | iscsi_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 | |||
1951 | static void | ||
1936 | iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) | 1952 | iscsi_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 | ||
1985 | static void | ||
1986 | iscsi_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 | |||
1968 | static int | 1994 | static int |
1969 | iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | 1995 | iscsi_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 | ||
2016 | static void | ||
2017 | iscsi_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 | |||
2031 | static void | ||
2032 | iscsi_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 */ |
2049 | static void | 2043 | static void |
2050 | iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, | 2044 | iscsi_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 | */ |