diff options
author | Haggai Eran <haggaie@mellanox.com> | 2015-10-22 08:20:09 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2015-10-28 12:32:48 -0400 |
commit | 4be74b42a6d05a74a21362010cd3920fa17f63c7 (patch) | |
tree | 1a55242de7505cc90b30d13c79cabc6324ad264c | |
parent | 565edd1d555513ab5d67a847d50d7c14c82ef6c3 (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.c | 94 |
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); | |||
110 | static LIST_HEAD(listen_any_list); | 112 | static LIST_HEAD(listen_any_list); |
111 | static DEFINE_MUTEX(lock); | 113 | static DEFINE_MUTEX(lock); |
112 | static struct workqueue_struct *cma_wq; | 114 | static struct workqueue_struct *cma_wq; |
113 | static DEFINE_IDR(tcp_ps); | 115 | static int cma_pernet_id; |
114 | static DEFINE_IDR(udp_ps); | ||
115 | static DEFINE_IDR(ipoib_ps); | ||
116 | static DEFINE_IDR(ib_ps); | ||
117 | 116 | ||
118 | static struct idr *cma_idr(enum rdma_port_space ps) | 117 | struct cma_pernet { |
118 | struct idr tcp_ps; | ||
119 | struct idr udp_ps; | ||
120 | struct idr ipoib_ps; | ||
121 | struct idr ib_ps; | ||
122 | }; | ||
123 | |||
124 | static struct cma_pernet *cma_pernet(struct net *net) | ||
125 | { | ||
126 | return net_generic(net, cma_pernet_id); | ||
127 | } | ||
128 | |||
129 | static 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 | ||
148 | static int cma_ps_alloc(enum rdma_port_space ps, | 161 | static 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 | ||
156 | static struct rdma_bind_list *cma_ps_find(enum rdma_port_space ps, int snum) | 169 | static 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 | ||
163 | static void cma_ps_remove(enum rdma_port_space ps, int snum) | 177 | static 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; |
2719 | retry: | 2734 | retry: |
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 | ||
4022 | static 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 | |||
4034 | static 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 | |||
4044 | static 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 | |||
4007 | static int __init cma_init(void) | 4051 | static 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); |
4080 | err_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 | ||
4050 | module_init(cma_init); | 4096 | module_init(cma_init); |