Skip to content

Commit 9e67600

Browse files
gulamsmartinkpetersen
authored andcommitted
scsi: iscsi: Fix race condition between login and sync thread
A kernel panic was observed due to a timing issue between the sync thread and the initiator processing a login response from the target. The session reopen can be invoked both from the session sync thread when iscsid restarts and from iscsid through the error handler. Before the initiator receives the response to a login, another reopen request can be sent from the error handler/sync session. When the initial login response is subsequently processed, the connection has been closed and the socket has been released. To fix this a new connection state, ISCSI_CONN_BOUND, is added: - Set the connection state value to ISCSI_CONN_DOWN upon iscsi_if_ep_disconnect() and iscsi_if_stop_conn() - Set the connection state to the newly created value ISCSI_CONN_BOUND after bind connection (transport->bind_conn()) - In iscsi_set_param(), return -ENOTCONN if the connection state is not either ISCSI_CONN_BOUND or ISCSI_CONN_UP Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Mike Christie <[email protected]> Signed-off-by: Gulam Mohamed <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]> index 91074fd..f4bf62b 100644
1 parent 36fa766 commit 9e67600

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed

drivers/scsi/scsi_transport_iscsi.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2471,6 +2471,7 @@ static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag)
24712471
*/
24722472
mutex_lock(&conn_mutex);
24732473
conn->transport->stop_conn(conn, flag);
2474+
conn->state = ISCSI_CONN_DOWN;
24742475
mutex_unlock(&conn_mutex);
24752476

24762477
}
@@ -2894,6 +2895,13 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
28942895
default:
28952896
err = transport->set_param(conn, ev->u.set_param.param,
28962897
data, ev->u.set_param.len);
2898+
if ((conn->state == ISCSI_CONN_BOUND) ||
2899+
(conn->state == ISCSI_CONN_UP)) {
2900+
err = transport->set_param(conn, ev->u.set_param.param,
2901+
data, ev->u.set_param.len);
2902+
} else {
2903+
return -ENOTCONN;
2904+
}
28972905
}
28982906

28992907
return err;
@@ -2953,6 +2961,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
29532961
mutex_lock(&conn->ep_mutex);
29542962
conn->ep = NULL;
29552963
mutex_unlock(&conn->ep_mutex);
2964+
conn->state = ISCSI_CONN_DOWN;
29562965
}
29572966

29582967
transport->ep_disconnect(ep);
@@ -3713,6 +3722,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
37133722
ev->r.retcode = transport->bind_conn(session, conn,
37143723
ev->u.b_conn.transport_eph,
37153724
ev->u.b_conn.is_leading);
3725+
if (!ev->r.retcode)
3726+
conn->state = ISCSI_CONN_BOUND;
37163727
mutex_unlock(&conn_mutex);
37173728

37183729
if (ev->r.retcode || !transport->ep_connect)
@@ -3944,7 +3955,8 @@ iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);
39443955
static const char *const connection_state_names[] = {
39453956
[ISCSI_CONN_UP] = "up",
39463957
[ISCSI_CONN_DOWN] = "down",
3947-
[ISCSI_CONN_FAILED] = "failed"
3958+
[ISCSI_CONN_FAILED] = "failed",
3959+
[ISCSI_CONN_BOUND] = "bound"
39483960
};
39493961

39503962
static ssize_t show_conn_state(struct device *dev,

include/scsi/scsi_transport_iscsi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ enum iscsi_connection_state {
193193
ISCSI_CONN_UP = 0,
194194
ISCSI_CONN_DOWN,
195195
ISCSI_CONN_FAILED,
196+
ISCSI_CONN_BOUND,
196197
};
197198

198199
struct iscsi_cls_conn {

0 commit comments

Comments
 (0)