diff options
author | Ariel Nahum <arieln@mellanox.com> | 2014-07-31 12:27:49 +0200 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-08-02 00:10:05 +0200 |
commit | 504130c039f917aba8b145fe8ea99be95e662fca (patch) | |
tree | 601a9605d25be528f8e60c9e9161d6c30d06181f /drivers/infiniband/ulp/iser/iscsi_iser.c | |
parent | IB/iser: Remove redundant return code in iser_free_ib_conn_res() (diff) | |
download | linux-504130c039f917aba8b145fe8ea99be95e662fca.tar.xz linux-504130c039f917aba8b145fe8ea99be95e662fca.zip |
IB/iser: Protect iser state machine with a mutex
The iser connection state lookups and transitions are not fully protected.
Some transitions are protected with a spinlock, and in some cases the
state is accessed unprotected due to specific assumptions of the flow.
Introduce a new mutex to protect the connection state access. We use a
mutex since we need to also include a scheduling operations executed
under the state lock.
Each state transition/condition and its corresponding action will be
protected with the state mutex.
The rdma_cm events handler acquires the mutex when handling connection
events. Since iser connection state can transition to DOWN
concurrently during connection establishment, we bailout from
addr/route resolution events when the state is not PENDING.
This addresses a scenario where ep_poll retries expire during CMA
connection establishment. In this case ep_disconnect is invoked while
CMA events keep coming (address/route resolution, connected, etc...).
Signed-off-by: Ariel Nahum <arieln@mellanox.com>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/ulp/iser/iscsi_iser.c')
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index d7acd4b62d6e..3dc853c9e4bf 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -632,10 +632,13 @@ iscsi_iser_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) msecs_to_jiffies(timeout_ms)); /* if conn establishment failed, return error code to iscsi */ - if (!rc && - (ib_conn->state == ISER_CONN_TERMINATING || - ib_conn->state == ISER_CONN_DOWN)) - rc = -1; + if (rc == 0) { + mutex_lock(&ib_conn->state_mutex); + if (ib_conn->state == ISER_CONN_TERMINATING || + ib_conn->state == ISER_CONN_DOWN) + rc = -1; + mutex_unlock(&ib_conn->state_mutex); + } iser_info("ib conn %p rc = %d\n", ib_conn, rc); @@ -654,6 +657,7 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep) ib_conn = ep->dd_data; iser_info("ep %p ib conn %p state %d\n", ep, ib_conn, ib_conn->state); + mutex_lock(&ib_conn->state_mutex); iser_conn_terminate(ib_conn); /* @@ -664,7 +668,10 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep) if (ib_conn->iscsi_conn) { INIT_WORK(&ib_conn->release_work, iser_release_work); queue_work(release_wq, &ib_conn->release_work); + mutex_unlock(&ib_conn->state_mutex); } else { + ib_conn->state = ISER_CONN_DOWN; + mutex_unlock(&ib_conn->state_mutex); iser_conn_release(ib_conn); } iscsi_destroy_endpoint(ep); |