diff options
author | Sean Hefty <sean.hefty@intel.com> | 2006-09-01 18:33:55 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-09-22 18:22:49 -0400 |
commit | 61a73c708f37295892176bc911b178278df6a091 (patch) | |
tree | caa11f34a88a687f6699373f24bd93733b048f10 /drivers/infiniband | |
parent | f94b533d091a42da92d908eb7b3f9ade1923f90d (diff) |
RDMA/cma: Protect against adding device during destruction
Closes a window where address resolution can attach an rdma_cm_id to a
device during destruction of the rdma_cm_id. This can result in the
rdma_cm_id remaining in the device list after its memory has been
freed.
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/cma.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index e88a7c652ca0..488fa1d642a7 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -279,7 +279,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) | |||
279 | default: | 279 | default: |
280 | return -ENODEV; | 280 | return -ENODEV; |
281 | } | 281 | } |
282 | mutex_lock(&lock); | 282 | |
283 | list_for_each_entry(cma_dev, &dev_list, list) { | 283 | list_for_each_entry(cma_dev, &dev_list, list) { |
284 | ret = ib_find_cached_gid(cma_dev->device, &gid, | 284 | ret = ib_find_cached_gid(cma_dev->device, &gid, |
285 | &id_priv->id.port_num, NULL); | 285 | &id_priv->id.port_num, NULL); |
@@ -288,7 +288,6 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) | |||
288 | break; | 288 | break; |
289 | } | 289 | } |
290 | } | 290 | } |
291 | mutex_unlock(&lock); | ||
292 | return ret; | 291 | return ret; |
293 | } | 292 | } |
294 | 293 | ||
@@ -712,7 +711,9 @@ void rdma_destroy_id(struct rdma_cm_id *id) | |||
712 | state = cma_exch(id_priv, CMA_DESTROYING); | 711 | state = cma_exch(id_priv, CMA_DESTROYING); |
713 | cma_cancel_operation(id_priv, state); | 712 | cma_cancel_operation(id_priv, state); |
714 | 713 | ||
714 | mutex_lock(&lock); | ||
715 | if (id_priv->cma_dev) { | 715 | if (id_priv->cma_dev) { |
716 | mutex_unlock(&lock); | ||
716 | switch (rdma_node_get_transport(id->device->node_type)) { | 717 | switch (rdma_node_get_transport(id->device->node_type)) { |
717 | case RDMA_TRANSPORT_IB: | 718 | case RDMA_TRANSPORT_IB: |
718 | if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) | 719 | if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) |
@@ -727,8 +728,8 @@ void rdma_destroy_id(struct rdma_cm_id *id) | |||
727 | } | 728 | } |
728 | mutex_lock(&lock); | 729 | mutex_lock(&lock); |
729 | cma_detach_from_dev(id_priv); | 730 | cma_detach_from_dev(id_priv); |
730 | mutex_unlock(&lock); | ||
731 | } | 731 | } |
732 | mutex_unlock(&lock); | ||
732 | 733 | ||
733 | cma_release_port(id_priv); | 734 | cma_release_port(id_priv); |
734 | cma_deref_id(id_priv); | 735 | cma_deref_id(id_priv); |
@@ -925,7 +926,9 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
925 | } | 926 | } |
926 | 927 | ||
927 | atomic_inc(&conn_id->dev_remove); | 928 | atomic_inc(&conn_id->dev_remove); |
929 | mutex_lock(&lock); | ||
928 | ret = cma_acquire_dev(conn_id); | 930 | ret = cma_acquire_dev(conn_id); |
931 | mutex_unlock(&lock); | ||
929 | if (ret) { | 932 | if (ret) { |
930 | ret = -ENODEV; | 933 | ret = -ENODEV; |
931 | cma_release_remove(conn_id); | 934 | cma_release_remove(conn_id); |
@@ -1097,7 +1100,9 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, | |||
1097 | goto out; | 1100 | goto out; |
1098 | } | 1101 | } |
1099 | 1102 | ||
1103 | mutex_lock(&lock); | ||
1100 | ret = cma_acquire_dev(conn_id); | 1104 | ret = cma_acquire_dev(conn_id); |
1105 | mutex_unlock(&lock); | ||
1101 | if (ret) { | 1106 | if (ret) { |
1102 | cma_release_remove(conn_id); | 1107 | cma_release_remove(conn_id); |
1103 | rdma_destroy_id(new_cm_id); | 1108 | rdma_destroy_id(new_cm_id); |
@@ -1507,16 +1512,26 @@ static void addr_handler(int status, struct sockaddr *src_addr, | |||
1507 | enum rdma_cm_event_type event; | 1512 | enum rdma_cm_event_type event; |
1508 | 1513 | ||
1509 | atomic_inc(&id_priv->dev_remove); | 1514 | atomic_inc(&id_priv->dev_remove); |
1510 | if (!id_priv->cma_dev && !status) | 1515 | |
1516 | /* | ||
1517 | * Grab mutex to block rdma_destroy_id() from removing the device while | ||
1518 | * we're trying to acquire it. | ||
1519 | */ | ||
1520 | mutex_lock(&lock); | ||
1521 | if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) { | ||
1522 | mutex_unlock(&lock); | ||
1523 | goto out; | ||
1524 | } | ||
1525 | |||
1526 | if (!status && !id_priv->cma_dev) | ||
1511 | status = cma_acquire_dev(id_priv); | 1527 | status = cma_acquire_dev(id_priv); |
1528 | mutex_unlock(&lock); | ||
1512 | 1529 | ||
1513 | if (status) { | 1530 | if (status) { |
1514 | if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND)) | 1531 | if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND)) |
1515 | goto out; | 1532 | goto out; |
1516 | event = RDMA_CM_EVENT_ADDR_ERROR; | 1533 | event = RDMA_CM_EVENT_ADDR_ERROR; |
1517 | } else { | 1534 | } else { |
1518 | if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) | ||
1519 | goto out; | ||
1520 | memcpy(&id_priv->id.route.addr.src_addr, src_addr, | 1535 | memcpy(&id_priv->id.route.addr.src_addr, src_addr, |
1521 | ip_addr_size(src_addr)); | 1536 | ip_addr_size(src_addr)); |
1522 | event = RDMA_CM_EVENT_ADDR_RESOLVED; | 1537 | event = RDMA_CM_EVENT_ADDR_RESOLVED; |
@@ -1740,8 +1755,11 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) | |||
1740 | 1755 | ||
1741 | if (!cma_any_addr(addr)) { | 1756 | if (!cma_any_addr(addr)) { |
1742 | ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); | 1757 | ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); |
1743 | if (!ret) | 1758 | if (!ret) { |
1759 | mutex_lock(&lock); | ||
1744 | ret = cma_acquire_dev(id_priv); | 1760 | ret = cma_acquire_dev(id_priv); |
1761 | mutex_unlock(&lock); | ||
1762 | } | ||
1745 | if (ret) | 1763 | if (ret) |
1746 | goto err; | 1764 | goto err; |
1747 | } | 1765 | } |