iser-target: release stale iser connections
When receiving a new iser connect request we serialize the pending requests by adding the newly created iser connection to the np accept list and let the login thread process the connect request one by one (np_accept_wait). In case we received a disconnect request before the iser_conn has begun processing (still linked in np_accept_list) we should detach it from the list and clean it up and not have the login thread process a stale connection. We do it only when the connection state is not already terminating (initiator driven disconnect) as this might lead us to access np_accept_mutex after the np was released in live shutdown scenarios. Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Jenny Falkovich <jennyf@mellanox.com> Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
9253e667ab
commit
2f1b6b7d9a
|
@ -65,6 +65,8 @@ static int
|
|||
isert_rdma_accept(struct isert_conn *isert_conn);
|
||||
struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
|
||||
|
||||
static void isert_release_work(struct work_struct *work);
|
||||
|
||||
static inline bool
|
||||
isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
|
||||
{
|
||||
|
@ -648,6 +650,7 @@ isert_init_conn(struct isert_conn *isert_conn)
|
|||
mutex_init(&isert_conn->mutex);
|
||||
spin_lock_init(&isert_conn->pool_lock);
|
||||
INIT_LIST_HEAD(&isert_conn->fr_pool);
|
||||
INIT_WORK(&isert_conn->release_work, isert_release_work);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -925,6 +928,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
|
|||
{
|
||||
struct isert_np *isert_np = cma_id->context;
|
||||
struct isert_conn *isert_conn;
|
||||
bool terminating = false;
|
||||
|
||||
if (isert_np->np_cm_id == cma_id)
|
||||
return isert_np_cma_handler(cma_id->context, event);
|
||||
|
@ -932,12 +936,25 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
|
|||
isert_conn = cma_id->qp->qp_context;
|
||||
|
||||
mutex_lock(&isert_conn->mutex);
|
||||
terminating = (isert_conn->state == ISER_CONN_TERMINATING);
|
||||
isert_conn_terminate(isert_conn);
|
||||
mutex_unlock(&isert_conn->mutex);
|
||||
|
||||
isert_info("conn %p completing wait\n", isert_conn);
|
||||
complete(&isert_conn->wait);
|
||||
|
||||
if (terminating)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&isert_np->np_accept_mutex);
|
||||
if (!list_empty(&isert_conn->accept_node)) {
|
||||
list_del_init(&isert_conn->accept_node);
|
||||
isert_put_conn(isert_conn);
|
||||
queue_work(isert_release_wq, &isert_conn->release_work);
|
||||
}
|
||||
mutex_unlock(&isert_np->np_accept_mutex);
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3368,7 +3385,6 @@ static void isert_wait_conn(struct iscsi_conn *conn)
|
|||
isert_wait4flush(isert_conn);
|
||||
isert_wait4logout(isert_conn);
|
||||
|
||||
INIT_WORK(&isert_conn->release_work, isert_release_work);
|
||||
queue_work(isert_release_wq, &isert_conn->release_work);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue