diff options
author | np <np@FreeBSD.org> | 2017-03-03 17:53:22 +0000 |
---|---|---|
committer | np <np@FreeBSD.org> | 2017-03-03 17:53:22 +0000 |
commit | 5d4ddfe3d2e697a2ce2caf79054ce7bc1e9f7c51 (patch) | |
tree | f6ff6d458031c44d9d5fa9b46745f41f8651c4ba /sys/ofed | |
parent | 6d2c1dafbda3f830d0ce6e298c655a5cd15fb543 (diff) | |
download | FreeBSD-src-5d4ddfe3d2e697a2ce2caf79054ce7bc1e9f7c51.zip FreeBSD-src-5d4ddfe3d2e697a2ce2caf79054ce7bc1e9f7c51.tar.gz |
MFC r314400:
cxgbe/iw_cxgbe: fix various double-close panics with iWARP sockets.
Sockets representing the TCP endpoints for iWARP connections are
allocated by the ibcore module. Before this revision they were closed
either by the ibcore module or the iw_cxgbe hardware driver depending on
the state transitions during connection teardown. This is error prone
and there were cases where both iw_cxgbe and ibcore closed the socket
leading to double-free panics. The fix is to let ibcore close the
sockets it creates and never do it in the driver.
- Use sodisconnect instead of soclose (preceded by solinger = 0) in the
driver to tear down an RDMA connection abruptly. This does what's
intended without releasing the socket's fd reference.
- Close the socket in ibcore when the iWARP iw_cm_id is destroyed. This
works for all kinds of sockets: clients that initiate connections,
listeners, and sockets accepted off of listeners.
Sponsored by: Chelsio Communications
Diffstat (limited to 'sys/ofed')
-rw-r--r-- | sys/ofed/drivers/infiniband/core/cma.c | 2 | ||||
-rw-r--r-- | sys/ofed/drivers/infiniband/core/iwcm.c | 27 |
2 files changed, 10 insertions, 19 deletions
diff --git a/sys/ofed/drivers/infiniband/core/cma.c b/sys/ofed/drivers/infiniband/core/cma.c index 27e6194..f860c42 100644 --- a/sys/ofed/drivers/infiniband/core/cma.c +++ b/sys/ofed/drivers/infiniband/core/cma.c @@ -1049,8 +1049,6 @@ static void cma_release_port(struct rdma_id_private *id_priv) kfree(bind_list); } mutex_unlock(&lock); - if (id_priv->sock) - sock_release(id_priv->sock); } static void cma_leave_mc_groups(struct rdma_id_private *id_priv) diff --git a/sys/ofed/drivers/infiniband/core/iwcm.c b/sys/ofed/drivers/infiniband/core/iwcm.c index 3651063..fa6b674 100644 --- a/sys/ofed/drivers/infiniband/core/iwcm.c +++ b/sys/ofed/drivers/infiniband/core/iwcm.c @@ -528,24 +528,15 @@ iw_init_sock(struct iw_cm_id *cm_id) } static int -iw_close_socket(struct iw_cm_id *cm_id, int close) +iw_uninit_socket(struct iw_cm_id *cm_id) { struct socket *so = cm_id->so; - int rc; - SOCK_LOCK(so); soupcall_clear(so, SO_RCV); SOCK_UNLOCK(so); - if (close) - rc = soclose(so); - else - rc = soshutdown(so, SHUT_WR | SHUT_RD); - - cm_id->so = NULL; - - return rc; + return (0); } static int @@ -554,18 +545,17 @@ iw_create_listen(struct iw_cm_id *cm_id, int backlog) int rc; iw_init_sock(cm_id); - rc = solisten(cm_id->so, backlog, curthread); + rc = -solisten(cm_id->so, backlog, curthread); if (rc != 0) - iw_close_socket(cm_id, 0); - return rc; + iw_uninit_socket(cm_id); + return (rc); } static int iw_destroy_listen(struct iw_cm_id *cm_id) { - int rc; - rc = iw_close_socket(cm_id, 0); - return rc; + + return (iw_uninit_socket(cm_id)); } @@ -663,6 +653,9 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id) wait_for_completion(&cm_id_priv->destroy_comp); + if (cm_id->so) + sock_release(cm_id->so); + free_cm_id(cm_id_priv); } EXPORT_SYMBOL(iw_destroy_cm_id); |