>It would be nice to avoid adding another workqueue.
Here's an updated patch that exports the work queue in ib_addr and has the CMA
make use of that one.
Thanks for the feedback - please respond if there are any other issues.
Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>
Index: include/rdma/ib_addr.h
===================================================================
--- include/rdma/ib_addr.h (revision 4651)
+++ include/rdma/ib_addr.h (working copy)
@@ -30,9 +30,13 @@
#if !defined(IB_ADDR_H)
#define IB_ADDR_H
+#include <linux/in.h>
+#include <linux/in6.h>
#include <linux/socket.h>
#include <rdma/ib_verbs.h>
+extern struct workqueue_struct *rdma_wq;
+
struct ib_addr {
union ib_gid sgid;
union ib_gid dgid;
@@ -68,5 +72,11 @@
void ib_addr_cancel(struct ib_addr *addr);
+static inline int ip_addr_size(struct sockaddr *addr)
+{
+ return addr->sa_family == AF_INET6 ?
+ sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+}
+
#endif /* IB_ADDR_H */
Index: core/addr.c
===================================================================
--- core/addr.c (revision 4651)
+++ core/addr.c (working copy)
@@ -27,8 +27,6 @@
* notice, one of the license notices in the documentation
* and/or other materials provided with the distribution.
*/
-#include <linux/in.h>
-#include <linux/in6.h>
#include <linux/inetdevice.h>
#include <linux/workqueue.h>
#include <net/arp.h>
@@ -57,7 +55,8 @@
static DECLARE_MUTEX(mutex);
static LIST_HEAD(req_list);
static DECLARE_WORK(work, process_req, NULL);
-static struct workqueue_struct *wq;
+struct workqueue_struct *rdma_wq;
+EXPORT_SYMBOL(rdma_wq);
static u16 addr_get_pkey(struct net_device *dev)
{
@@ -90,7 +89,7 @@
if ((long)delay <= 0)
delay = 1;
- queue_delayed_work(wq, &work, delay);
+ queue_delayed_work(rdma_wq, &work, delay);
}
static void queue_req(struct addr_req *req)
@@ -258,8 +257,8 @@
memset(req, 0, sizeof *req);
if (src_addr)
- req->src_addr = *src_addr;
- req->dst_addr = *dst_addr;
+ memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr));
+ memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr));
req->addr = addr;
req->callback = callback;
req->context = context;
@@ -333,8 +332,8 @@
static int addr_init(void)
{
- wq = create_singlethread_workqueue("ib_addr");
- if (!wq)
+ rdma_wq = create_singlethread_workqueue("rdma_wq");
+ if (!rdma_wq)
return -ENOMEM;
dev_add_pack(&addr_arp);
@@ -344,7 +343,7 @@
static void addr_cleanup(void)
{
dev_remove_pack(&addr_arp);
- destroy_workqueue(wq);
+ destroy_workqueue(rdma_wq);
}
module_init(addr_init);
Index: core/cma.c
===================================================================
--- core/cma.c (revision 4651)
+++ core/cma.c (working copy)
@@ -421,6 +421,12 @@
}
}
+static inline int cma_loopback_addr(struct sockaddr *addr)
+{
+ return ((struct sockaddr_in *) addr)->sin_addr.s_addr ==
+ ntohl(INADDR_LOOPBACK);
+}
+
static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
u8 *ip_ver, __u16 *port,
union cma_ip_addr **src, union cma_ip_addr **dst)
@@ -1070,6 +1076,35 @@
}
EXPORT_SYMBOL(rdma_resolve_route);
+static int cma_bind_loopback(struct rdma_id_private *id_priv)
+{
+ struct cma_device *cma_dev;
+ int ret;
+
+ down(&mutex);
+ if (list_empty(&dev_list)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ cma_dev = list_entry(dev_list.next, struct cma_device, list);
+ ret = ib_get_cached_gid(cma_dev->device, 1, 0,
+ &id_priv->id.route.addr.addr.ibaddr.sgid);
+ if (ret)
+ goto out;
+
+ ret = ib_get_cached_pkey(cma_dev->device, 1, 0,
+ &id_priv->id.route.addr.addr.ibaddr.pkey);
+ if (ret)
+ goto out;
+
+ id_priv->id.port_num = 1;
+ cma_attach_to_dev(id_priv, cma_dev);
+out:
+ up(&mutex);
+ return ret;
+}
+
static void addr_handler(int status, struct sockaddr *src_addr,
struct ib_addr *ibaddr, void *context)
{
@@ -1092,7 +1127,8 @@
} else {
if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
goto out;
- id_priv->id.route.addr.src_addr = *src_addr;
+ memcpy(&id_priv->id.route.addr.src_addr, src_addr,
+ ip_addr_size(src_addr));
event = RDMA_CM_EVENT_ADDR_RESOLVED;
}
@@ -1108,6 +1144,57 @@
cma_deref_id(id_priv);
}
+static void loopback_addr_handler(void *data)
+{
+ struct rdma_id_private *id_priv = data;
+
+ atomic_inc(&id_priv->dev_remove);
+
+ if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
+ goto out;
+
+ if (cma_notify_user(id_priv, RDMA_CM_EVENT_ADDR_RESOLVED, 0, NULL, 0)) {
+ cma_exch(id_priv, CMA_DESTROYING);
+ cma_release_remove(id_priv);
+ cma_deref_id(id_priv);
+ rdma_destroy_id(&id_priv->id);
+ return;
+ }
+out:
+ cma_release_remove(id_priv);
+ cma_deref_id(id_priv);
+}
+
+static int cma_resolve_loopback(struct rdma_id_private *id_priv,
+ struct sockaddr *src_addr, enum cma_state state)
+{
+ struct work_struct *work;
+ int ret;
+
+ work = kmalloc(sizeof *work, GFP_KERNEL);
+ if (!work)
+ return -ENOMEM;
+
+ if (state == CMA_IDLE) {
+ ret = cma_bind_loopback(id_priv);
+ if (ret)
+ goto err;
+ id_priv->id.route.addr.addr.ibaddr.dgid =
+ id_priv->id.route.addr.addr.ibaddr.sgid;
+ if (!src_addr || cma_any_addr(src_addr))
+ src_addr = &id_priv->id.route.addr.dst_addr;
+ memcpy(&id_priv->id.route.addr.src_addr, src_addr,
+ ip_addr_size(src_addr));
+ }
+
+ INIT_WORK(work, loopback_addr_handler, id_priv);
+ queue_work(rdma_wq, work);
+ return 0;
+err:
+ kfree(work);
+ return ret;
+}
+
int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
struct sockaddr *dst_addr, int timeout_ms)
{
@@ -1126,9 +1213,13 @@
return -EINVAL;
atomic_inc(&id_priv->refcount);
- id->route.addr.dst_addr = *dst_addr;
- ret = ib_resolve_addr(src_addr, dst_addr, &id->route.addr.addr.ibaddr,
- timeout_ms, addr_handler, id_priv);
+ memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
+ if (cma_loopback_addr(dst_addr))
+ ret = cma_resolve_loopback(id_priv, src_addr, expected_state);
+ else
+ ret = ib_resolve_addr(src_addr, dst_addr,
+ &id->route.addr.addr.ibaddr,
+ timeout_ms, addr_handler, id_priv);
if (ret)
goto err;
@@ -1143,7 +1234,7 @@
int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
{
struct rdma_id_private *id_priv;
- struct ib_addr *ibaddr = &id->route.addr.addr.ibaddr;
+ struct ib_addr *ibaddr;
int ret;
if (addr->sa_family != AF_INET)
@@ -1154,9 +1245,11 @@
return -EINVAL;
if (cma_any_addr(addr)) {
- id->route.addr.src_addr = *addr;
ret = 0;
+ } else if (cma_loopback_addr(addr)) {
+ ret = cma_bind_loopback(id_priv);
} else {
+ ibaddr = &id->route.addr.addr.ibaddr;
ret = ib_translate_addr(addr, &ibaddr->sgid, &ibaddr->pkey);
if (!ret)
ret = cma_acquire_ib_dev(id_priv, &ibaddr->sgid);
@@ -1165,7 +1258,7 @@
if (ret)
goto err;
- id->route.addr.src_addr = *addr;
+ memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
return 0;
err:
cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general
To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general