aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaggai Eran <haggaie@mellanox.com>2015-10-22 08:20:09 -0400
committerDoug Ledford <dledford@redhat.com>2015-10-28 12:32:48 -0400
commit4be74b42a6d05a74a21362010cd3920fa17f63c7 (patch)
tree1a55242de7505cc90b30d13c79cabc6324ad264c
parent565edd1d555513ab5d67a847d50d7c14c82ef6c3 (diff)
IB/cma: Separate port allocation to network namespaces
Keep a struct for each network namespace containing the IDRs for the RDMA CM port spaces. The struct is created dynamically using the generic_net mechanism. This patch is internal infrastructure work for the following patches. In this patch, init_net is statically used as the network namespace for the new port-space API. Signed-off-by: Haggai Eran <haggaie@mellanox.com> Signed-off-by: Yotam Kenneth <yotamke@mellanox.com> Signed-off-by: Shachar Raindel <raindel@mellanox.com> Signed-off-by: Guy Shapiro <guysh@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/core/cma.c94
1 files changed, 70 insertions, 24 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 80a8b469a9a8..ac03c32ca7f1 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -44,6 +44,8 @@
44#include <linux/module.h> 44#include <linux/module.h>
45#include <net/route.h> 45#include <net/route.h>
46 46
47#include <net/net_namespace.h>
48#include <net/netns/generic.h>
47#include <net/tcp.h> 49#include <net/tcp.h>
48#include <net/ipv6.h> 50#include <net/ipv6.h>
49#include <net/ip_fib.h> 51#include <net/ip_fib.h>
@@ -110,22 +112,33 @@ static LIST_HEAD(dev_list);
110static LIST_HEAD(listen_any_list); 112static LIST_HEAD(listen_any_list);
111static DEFINE_MUTEX(lock); 113static DEFINE_MUTEX(lock);
112static struct workqueue_struct *cma_wq; 114static struct workqueue_struct *cma_wq;
113static DEFINE_IDR(tcp_ps); 115static int cma_pernet_id;
114static DEFINE_IDR(udp_ps);
115static DEFINE_IDR(ipoib_ps);
116static DEFINE_IDR(ib_ps);
117 116
118static struct idr *cma_idr(enum rdma_port_space ps) 117struct cma_pernet {
118 struct idr tcp_ps;
119 struct idr udp_ps;
120 struct idr ipoib_ps;
121 struct idr ib_ps;
122};
123
124static struct cma_pernet *cma_pernet(struct net *net)
125{
126 return net_generic(net, cma_pernet_id);
127}
128
129static struct idr *cma_pernet_idr(struct net *net, enum rdma_port_space ps)
119{ 130{
131 struct cma_pernet *pernet = cma_pernet(net);
132
120 switch (ps) { 133 switch (ps) {
121 case RDMA_PS_TCP: 134 case RDMA_PS_TCP:
122 return &tcp_ps; 135 return &pernet->tcp_ps;
123 case RDMA_PS_UDP: 136 case RDMA_PS_UDP:
124 return &udp_ps; 137 return &pernet->udp_ps;
125 case RDMA_PS_IPOIB: 138 case RDMA_PS_IPOIB:
126 return &ipoib_ps; 139 return &pernet->ipoib_ps;
127 case RDMA_PS_IB: 140 case RDMA_PS_IB:
128 return &ib_ps; 141 return &pernet->ib_ps;
129 default: 142 default:
130 return NULL; 143 return NULL;
131 } 144 }
@@ -145,24 +158,25 @@ struct rdma_bind_list {
145 unsigned short port; 158 unsigned short port;
146}; 159};
147 160
148static int cma_ps_alloc(enum rdma_port_space ps, 161static int cma_ps_alloc(struct net *net, enum rdma_port_space ps,
149 struct rdma_bind_list *bind_list, int snum) 162 struct rdma_bind_list *bind_list, int snum)
150{ 163{
151 struct idr *idr = cma_idr(ps); 164 struct idr *idr = cma_pernet_idr(net, ps);
152 165
153 return idr_alloc(idr, bind_list, snum, snum + 1, GFP_KERNEL); 166 return idr_alloc(idr, bind_list, snum, snum + 1, GFP_KERNEL);
154} 167}
155 168
156static struct rdma_bind_list *cma_ps_find(enum rdma_port_space ps, int snum) 169static struct rdma_bind_list *cma_ps_find(struct net *net,
170 enum rdma_port_space ps, int snum)
157{ 171{
158 struct idr *idr = cma_idr(ps); 172 struct idr *idr = cma_pernet_idr(net, ps);
159 173
160 return idr_find(idr, snum); 174 return idr_find(idr, snum);
161} 175}
162 176
163static void cma_ps_remove(enum rdma_port_space ps, int snum) 177static void cma_ps_remove(struct net *net, enum rdma_port_space ps, int snum)
164{ 178{
165 struct idr *idr = cma_idr(ps); 179 struct idr *idr = cma_pernet_idr(net, ps);
166 180
167 idr_remove(idr, snum); 181 idr_remove(idr, snum);
168} 182}
@@ -1325,7 +1339,8 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
1325 } 1339 }
1326 } 1340 }
1327 1341
1328 bind_list = cma_ps_find(rdma_ps_from_service_id(req.service_id), 1342 bind_list = cma_ps_find(&init_net,
1343 rdma_ps_from_service_id(req.service_id),
1329 cma_port_from_service_id(req.service_id)); 1344 cma_port_from_service_id(req.service_id));
1330 id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev); 1345 id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev);
1331 if (IS_ERR(id_priv) && *net_dev) { 1346 if (IS_ERR(id_priv) && *net_dev) {
@@ -1403,7 +1418,7 @@ static void cma_release_port(struct rdma_id_private *id_priv)
1403 mutex_lock(&lock); 1418 mutex_lock(&lock);
1404 hlist_del(&id_priv->node); 1419 hlist_del(&id_priv->node);
1405 if (hlist_empty(&bind_list->owners)) { 1420 if (hlist_empty(&bind_list->owners)) {
1406 cma_ps_remove(bind_list->ps, bind_list->port); 1421 cma_ps_remove(&init_net, bind_list->ps, bind_list->port);
1407 kfree(bind_list); 1422 kfree(bind_list);
1408 } 1423 }
1409 mutex_unlock(&lock); 1424 mutex_unlock(&lock);
@@ -2693,7 +2708,7 @@ static int cma_alloc_port(enum rdma_port_space ps,
2693 if (!bind_list) 2708 if (!bind_list)
2694 return -ENOMEM; 2709 return -ENOMEM;
2695 2710
2696 ret = cma_ps_alloc(ps, bind_list, snum); 2711 ret = cma_ps_alloc(&init_net, ps, bind_list, snum);
2697 if (ret < 0) 2712 if (ret < 0)
2698 goto err; 2713 goto err;
2699 2714
@@ -2718,7 +2733,7 @@ static int cma_alloc_any_port(enum rdma_port_space ps,
2718 rover = prandom_u32() % remaining + low; 2733 rover = prandom_u32() % remaining + low;
2719retry: 2734retry:
2720 if (last_used_port != rover && 2735 if (last_used_port != rover &&
2721 !cma_ps_find(ps, (unsigned short)rover)) { 2736 !cma_ps_find(&init_net, ps, (unsigned short)rover)) {
2722 int ret = cma_alloc_port(ps, id_priv, rover); 2737 int ret = cma_alloc_port(ps, id_priv, rover);
2723 /* 2738 /*
2724 * Remember previously used port number in order to avoid 2739 * Remember previously used port number in order to avoid
@@ -2784,7 +2799,7 @@ static int cma_use_port(enum rdma_port_space ps,
2784 if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) 2799 if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
2785 return -EACCES; 2800 return -EACCES;
2786 2801
2787 bind_list = cma_ps_find(ps, snum); 2802 bind_list = cma_ps_find(&init_net, ps, snum);
2788 if (!bind_list) { 2803 if (!bind_list) {
2789 ret = cma_alloc_port(ps, id_priv, snum); 2804 ret = cma_alloc_port(ps, id_priv, snum);
2790 } else { 2805 } else {
@@ -4004,6 +4019,35 @@ static const struct ibnl_client_cbs cma_cb_table[] = {
4004 .module = THIS_MODULE }, 4019 .module = THIS_MODULE },
4005}; 4020};
4006 4021
4022static int cma_init_net(struct net *net)
4023{
4024 struct cma_pernet *pernet = cma_pernet(net);
4025
4026 idr_init(&pernet->tcp_ps);
4027 idr_init(&pernet->udp_ps);
4028 idr_init(&pernet->ipoib_ps);
4029 idr_init(&pernet->ib_ps);
4030
4031 return 0;
4032}
4033
4034static void cma_exit_net(struct net *net)
4035{
4036 struct cma_pernet *pernet = cma_pernet(net);
4037
4038 idr_destroy(&pernet->tcp_ps);
4039 idr_destroy(&pernet->udp_ps);
4040 idr_destroy(&pernet->ipoib_ps);
4041 idr_destroy(&pernet->ib_ps);
4042}
4043
4044static struct pernet_operations cma_pernet_operations = {
4045 .init = cma_init_net,
4046 .exit = cma_exit_net,
4047 .id = &cma_pernet_id,
4048 .size = sizeof(struct cma_pernet),
4049};
4050
4007static int __init cma_init(void) 4051static int __init cma_init(void)
4008{ 4052{
4009 int ret; 4053 int ret;
@@ -4012,6 +4056,10 @@ static int __init cma_init(void)
4012 if (!cma_wq) 4056 if (!cma_wq)
4013 return -ENOMEM; 4057 return -ENOMEM;
4014 4058
4059 ret = register_pernet_subsys(&cma_pernet_operations);
4060 if (ret)
4061 goto err_wq;
4062
4015 ib_sa_register_client(&sa_client); 4063 ib_sa_register_client(&sa_client);
4016 rdma_addr_register_client(&addr_client); 4064 rdma_addr_register_client(&addr_client);
4017 register_netdevice_notifier(&cma_nb); 4065 register_netdevice_notifier(&cma_nb);
@@ -4029,6 +4077,7 @@ err:
4029 unregister_netdevice_notifier(&cma_nb); 4077 unregister_netdevice_notifier(&cma_nb);
4030 rdma_addr_unregister_client(&addr_client); 4078 rdma_addr_unregister_client(&addr_client);
4031 ib_sa_unregister_client(&sa_client); 4079 ib_sa_unregister_client(&sa_client);
4080err_wq:
4032 destroy_workqueue(cma_wq); 4081 destroy_workqueue(cma_wq);
4033 return ret; 4082 return ret;
4034} 4083}
@@ -4040,11 +4089,8 @@ static void __exit cma_cleanup(void)
4040 unregister_netdevice_notifier(&cma_nb); 4089 unregister_netdevice_notifier(&cma_nb);
4041 rdma_addr_unregister_client(&addr_client); 4090 rdma_addr_unregister_client(&addr_client);
4042 ib_sa_unregister_client(&sa_client); 4091 ib_sa_unregister_client(&sa_client);
4092 unregister_pernet_subsys(&cma_pernet_operations);
4043 destroy_workqueue(cma_wq); 4093 destroy_workqueue(cma_wq);
4044 idr_destroy(&tcp_ps);
4045 idr_destroy(&udp_ps);
4046 idr_destroy(&ipoib_ps);
4047 idr_destroy(&ib_ps);
4048} 4094}
4049 4095
4050module_init(cma_init); 4096module_init(cma_init);