diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index 42bd843ef..40e05db89 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -32,32 +32,36 @@ static void print_conn_state(char *p, size_t size, struct iscsi_conn *conn) switch (conn->rd_state) { case ISCSI_CONN_RD_STATE_PROCESSING: - snprintf(p, size, "%s", "read_processing "); + size -= scnprintf(p, size, "%s", "read_processing "); printed = 1; break; case ISCSI_CONN_RD_STATE_IN_LIST: - snprintf(p, size, "%s", "in_read_list "); + size -= scnprintf(p, size, "%s", "in_read_list "); printed = 1; break; } switch (conn->wr_state) { case ISCSI_CONN_WR_STATE_PROCESSING: - snprintf(p, size, "%s", "write_processing "); + size -= scnprintf(p, size, "%s", "write_processing "); printed = 1; break; case ISCSI_CONN_WR_STATE_IN_LIST: - snprintf(p, size, "%s", "in_write_list "); + size -= scnprintf(p, size, "%s", "in_write_list "); printed = 1; break; case ISCSI_CONN_WR_STATE_SPACE_WAIT: - snprintf(p, size, "%s", "space_waiting "); + size -= scnprintf(p, size, "%s", "space_waiting "); printed = 1; break; } - if (!printed) + if (conn->conn_reinstating) + snprintf(p, size, "%s", "reinstating "); + else if (!printed) snprintf(p, size, "%s", "established idle "); + + return; } static void print_digest_state(char *p, size_t size, unsigned long flags) @@ -184,7 +188,7 @@ void mark_conn_closed(struct iscsi_conn *conn) __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE); } -static void iscsi_state_change(struct sock *sk) +static void __iscsi_state_change(struct sock *sk) { struct iscsi_conn *conn = sk->sk_user_data; @@ -202,9 +206,17 @@ static void iscsi_state_change(struct sock *sk) } else iscsi_make_conn_rd_active(conn); + TRACE_EXIT(); + return; +} + +static void iscsi_state_change(struct sock *sk) +{ + struct iscsi_conn *conn = sk->sk_user_data; + + __iscsi_state_change(sk); conn->old_state_change(sk); - TRACE_EXIT(); return; } @@ -308,7 +320,11 @@ void __iscsi_socket_bind(struct iscsi_conn *conn) write_unlock_bh(&conn->sock->sk->sk_callback_lock); - iscsi_make_conn_rd_active(conn); + /* + * Check, if conn was closed while we were initializing it. + * This function will make conn rd_active, if necessary. + */ + __iscsi_state_change(conn->sock->sk); return; } @@ -501,7 +517,8 @@ int conn_add(struct iscsi_session *session, struct iscsi_kern_conn_info *info) goto out; if (reinstatement) { - TRACE_MGMT_DBG("Reinstating conn %p", conn); + TRACE_MGMT_DBG("Reinstating conn (old %p, new %p)", conn, + new_conn); conn->conn_reinst_successor = new_conn; new_conn->conn_reinstating = 1; __mark_conn_closed(conn, 0); diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index bc717fa4f..5a629d538 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -526,6 +526,7 @@ static void close_conn(struct iscsi_conn *conn) mutex_lock(&target->target_mutex); free_sess = (conn->conn_reinst_successor == NULL); + conn->conn_reinst_successor = NULL; conn_free(conn); diff --git a/iscsi-scst/usr/conn.c b/iscsi-scst/usr/conn.c index f5c22960e..38d396abf 100644 --- a/iscsi-scst/usr/conn.c +++ b/iscsi-scst/usr/conn.c @@ -57,7 +57,7 @@ void conn_pass_to_kern(struct connection *conn, int fd) { int err; - log_debug(1, "fd %d, cid %u, stat_sn %u, exp_stat_sn %u sid%" PRIx64, + log_debug(1, "fd %d, cid %u, stat_sn %u, exp_stat_sn %u sid %" PRIx64, fd, conn->cid, conn->stat_sn, conn->exp_stat_sn, conn->sid.id64); err = kernel_conn_create(conn->tid, conn->sess->sid.id64, conn->cid, @@ -65,9 +65,7 @@ void conn_pass_to_kern(struct connection *conn, int fd) conn->session_param[key_header_digest].val, conn->session_param[key_data_digest].val); - if (err == 0) - conn->sess->kern_conn_cnt++; - else + if (err != 0) log_error("kernel_conn_create() failed: %s", strerror(errno)); /* We don't need to return err, because we are going to close conn anyway */ diff --git a/iscsi-scst/usr/event.c b/iscsi-scst/usr/event.c index ec6bf400b..07ab17083 100644 --- a/iscsi-scst/usr/event.c +++ b/iscsi-scst/usr/event.c @@ -80,6 +80,7 @@ static int nl_read(int fd, void *data, int len) void handle_iscsi_events(int fd) { struct session *session; + struct connection *conn; struct iscsi_kern_event event; int res; @@ -98,13 +99,22 @@ retry: switch (event.state) { case E_CONN_CLOSE: - if (!(session = session_find_id(event.tid, event.sid))) { - log_warning("session %#" PRIx64 " not found?", event.sid); + session = session_find_id(event.tid, event.sid); + if (session == NULL) { + log_error("Session %#" PRIx64 " not found", event.sid); goto retry; } - session->kern_conn_cnt--; - if ((session->kern_conn_cnt == 0) && list_empty(&session->conn_list)) + conn = conn_find(session, event.cid); + if (conn == NULL) { + log_error("Connection %x for session %#" PRIx64 " not " + "found", event.cid, event.sid); + goto retry; + } + + conn_free(conn); + + if (list_empty(&session->conn_list)) session_free(session); break; default: diff --git a/iscsi-scst/usr/iscsi_scstd.c b/iscsi-scst/usr/iscsi_scstd.c index 9720dac37..6b663af11 100644 --- a/iscsi-scst/usr/iscsi_scstd.c +++ b/iscsi-scst/usr/iscsi_scstd.c @@ -568,7 +568,6 @@ static void event_loop(int timeout) if (conn->state == STATE_CLOSE) { log_debug(0, "closing conn %p", conn); conn_free_pdu(conn); - conn_free(conn); close(pollfd->fd); pollfd->fd = -1; incoming[i] = NULL; diff --git a/iscsi-scst/usr/iscsid.h b/iscsi-scst/usr/iscsid.h index b96b95518..4396dc66a 100644 --- a/iscsi-scst/usr/iscsid.h +++ b/iscsi-scst/usr/iscsid.h @@ -58,7 +58,6 @@ struct session { struct target *target; union iscsi_sid sid; - int kern_conn_cnt; struct __qelem conn_list; };