diff options
author | Krishna Kumar <krkumar2@in.ibm.com> | 2006-09-29 14:51:49 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-10-02 17:52:15 -0400 |
commit | 6e35aabee125999f4b3c01326f5339fa74a89259 (patch) | |
tree | 8cc49d3d79b5dda31b0b947e80b55cd1d42b0583 /drivers | |
parent | 675a027c3db25a439f6ea744bb0c284f983dbfb9 (diff) |
RDMA/cma: Fix device removal race
The race is as follows:
A process : cma_process_remove() calls cma_remove_id_dev(),
which sets id state to CMA_DEVICE_REMOVAL and
calls wait_event(dev_remove).
B process : cma_req_handler() had incremented dev_remove,
and calls cma_acquire_ib_dev() and on failure
calls cma_release_remove(), which does a
wake_up of cma_process_remove(). Then
cma_req_handler() calls rdma_destroy_id();
A Process : cma_remove_id_dev() gets woken and checks the
state of id, and since it is still (wrongly)
CMA_DEVICE_REMOVAL, it calls notify_user(id)
and if that fails, the caller - cma_process_remove()
calls rdma_destroy_id(id). Two processes can
call rdma_destroy_id(), resulting in one
de-referencing kfreed id_priv.
Fix is for process B to set CMA_DESTROYING in cma_req_handler()
so that process A will return instead of doing a rdma_destroy_id().
Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/core/cma.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 69bb0892e887..f383a4f50ab0 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -932,6 +932,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
932 | mutex_unlock(&lock); | 932 | mutex_unlock(&lock); |
933 | if (ret) { | 933 | if (ret) { |
934 | ret = -ENODEV; | 934 | ret = -ENODEV; |
935 | cma_exch(conn_id, CMA_DESTROYING); | ||
935 | cma_release_remove(conn_id); | 936 | cma_release_remove(conn_id); |
936 | rdma_destroy_id(&conn_id->id); | 937 | rdma_destroy_id(&conn_id->id); |
937 | goto out; | 938 | goto out; |