Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Haggai Eran and committed by
Doug Ledford
4be74b42 565edd1d

+70 -24
+70 -24
drivers/infiniband/core/cma.c
··· 44 44 #include <linux/module.h> 45 45 #include <net/route.h> 46 46 47 + #include <net/net_namespace.h> 48 + #include <net/netns/generic.h> 47 49 #include <net/tcp.h> 48 50 #include <net/ipv6.h> 49 51 #include <net/ip_fib.h> ··· 112 110 static LIST_HEAD(listen_any_list); 113 111 static DEFINE_MUTEX(lock); 114 112 static struct workqueue_struct *cma_wq; 115 - static DEFINE_IDR(tcp_ps); 116 - static DEFINE_IDR(udp_ps); 117 - static DEFINE_IDR(ipoib_ps); 118 - static DEFINE_IDR(ib_ps); 113 + static int cma_pernet_id; 119 114 120 - static struct idr *cma_idr(enum rdma_port_space ps) 115 + struct cma_pernet { 116 + struct idr tcp_ps; 117 + struct idr udp_ps; 118 + struct idr ipoib_ps; 119 + struct idr ib_ps; 120 + }; 121 + 122 + static struct cma_pernet *cma_pernet(struct net *net) 121 123 { 124 + return net_generic(net, cma_pernet_id); 125 + } 126 + 127 + static struct idr *cma_pernet_idr(struct net *net, enum rdma_port_space ps) 128 + { 129 + struct cma_pernet *pernet = cma_pernet(net); 130 + 122 131 switch (ps) { 123 132 case RDMA_PS_TCP: 124 - return &tcp_ps; 133 + return &pernet->tcp_ps; 125 134 case RDMA_PS_UDP: 126 - return &udp_ps; 135 + return &pernet->udp_ps; 127 136 case RDMA_PS_IPOIB: 128 - return &ipoib_ps; 137 + return &pernet->ipoib_ps; 129 138 case RDMA_PS_IB: 130 - return &ib_ps; 139 + return &pernet->ib_ps; 131 140 default: 132 141 return NULL; 133 142 } ··· 158 145 unsigned short port; 159 146 }; 160 147 161 - static int cma_ps_alloc(enum rdma_port_space ps, 148 + static int cma_ps_alloc(struct net *net, enum rdma_port_space ps, 162 149 struct rdma_bind_list *bind_list, int snum) 163 150 { 164 - struct idr *idr = cma_idr(ps); 151 + struct idr *idr = cma_pernet_idr(net, ps); 165 152 166 153 return idr_alloc(idr, bind_list, snum, snum + 1, GFP_KERNEL); 167 154 } 168 155 169 - static struct rdma_bind_list *cma_ps_find(enum rdma_port_space ps, int snum) 156 + static struct rdma_bind_list *cma_ps_find(struct net *net, 157 + enum rdma_port_space ps, int snum) 170 158 { 171 - struct idr *idr = cma_idr(ps); 159 + struct idr *idr = cma_pernet_idr(net, ps); 172 160 173 161 return idr_find(idr, snum); 174 162 } 175 163 176 - static void cma_ps_remove(enum rdma_port_space ps, int snum) 164 + static void cma_ps_remove(struct net *net, enum rdma_port_space ps, int snum) 177 165 { 178 - struct idr *idr = cma_idr(ps); 166 + struct idr *idr = cma_pernet_idr(net, ps); 179 167 180 168 idr_remove(idr, snum); 181 169 } ··· 1339 1325 } 1340 1326 } 1341 1327 1342 - bind_list = cma_ps_find(rdma_ps_from_service_id(req.service_id), 1328 + bind_list = cma_ps_find(&init_net, 1329 + rdma_ps_from_service_id(req.service_id), 1343 1330 cma_port_from_service_id(req.service_id)); 1344 1331 id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev); 1345 1332 if (IS_ERR(id_priv) && *net_dev) { ··· 1418 1403 mutex_lock(&lock); 1419 1404 hlist_del(&id_priv->node); 1420 1405 if (hlist_empty(&bind_list->owners)) { 1421 - cma_ps_remove(bind_list->ps, bind_list->port); 1406 + cma_ps_remove(&init_net, bind_list->ps, bind_list->port); 1422 1407 kfree(bind_list); 1423 1408 } 1424 1409 mutex_unlock(&lock); ··· 2708 2693 if (!bind_list) 2709 2694 return -ENOMEM; 2710 2695 2711 - ret = cma_ps_alloc(ps, bind_list, snum); 2696 + ret = cma_ps_alloc(&init_net, ps, bind_list, snum); 2712 2697 if (ret < 0) 2713 2698 goto err; 2714 2699 ··· 2733 2718 rover = prandom_u32() % remaining + low; 2734 2719 retry: 2735 2720 if (last_used_port != rover && 2736 - !cma_ps_find(ps, (unsigned short)rover)) { 2721 + !cma_ps_find(&init_net, ps, (unsigned short)rover)) { 2737 2722 int ret = cma_alloc_port(ps, id_priv, rover); 2738 2723 /* 2739 2724 * Remember previously used port number in order to avoid ··· 2799 2784 if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) 2800 2785 return -EACCES; 2801 2786 2802 - bind_list = cma_ps_find(ps, snum); 2787 + bind_list = cma_ps_find(&init_net, ps, snum); 2803 2788 if (!bind_list) { 2804 2789 ret = cma_alloc_port(ps, id_priv, snum); 2805 2790 } else { ··· 4019 4004 .module = THIS_MODULE }, 4020 4005 }; 4021 4006 4007 + static int cma_init_net(struct net *net) 4008 + { 4009 + struct cma_pernet *pernet = cma_pernet(net); 4010 + 4011 + idr_init(&pernet->tcp_ps); 4012 + idr_init(&pernet->udp_ps); 4013 + idr_init(&pernet->ipoib_ps); 4014 + idr_init(&pernet->ib_ps); 4015 + 4016 + return 0; 4017 + } 4018 + 4019 + static void cma_exit_net(struct net *net) 4020 + { 4021 + struct cma_pernet *pernet = cma_pernet(net); 4022 + 4023 + idr_destroy(&pernet->tcp_ps); 4024 + idr_destroy(&pernet->udp_ps); 4025 + idr_destroy(&pernet->ipoib_ps); 4026 + idr_destroy(&pernet->ib_ps); 4027 + } 4028 + 4029 + static struct pernet_operations cma_pernet_operations = { 4030 + .init = cma_init_net, 4031 + .exit = cma_exit_net, 4032 + .id = &cma_pernet_id, 4033 + .size = sizeof(struct cma_pernet), 4034 + }; 4035 + 4022 4036 static int __init cma_init(void) 4023 4037 { 4024 4038 int ret; ··· 4055 4011 cma_wq = create_singlethread_workqueue("rdma_cm"); 4056 4012 if (!cma_wq) 4057 4013 return -ENOMEM; 4014 + 4015 + ret = register_pernet_subsys(&cma_pernet_operations); 4016 + if (ret) 4017 + goto err_wq; 4058 4018 4059 4019 ib_sa_register_client(&sa_client); 4060 4020 rdma_addr_register_client(&addr_client); ··· 4077 4029 unregister_netdevice_notifier(&cma_nb); 4078 4030 rdma_addr_unregister_client(&addr_client); 4079 4031 ib_sa_unregister_client(&sa_client); 4032 + err_wq: 4080 4033 destroy_workqueue(cma_wq); 4081 4034 return ret; 4082 4035 } ··· 4089 4040 unregister_netdevice_notifier(&cma_nb); 4090 4041 rdma_addr_unregister_client(&addr_client); 4091 4042 ib_sa_unregister_client(&sa_client); 4043 + unregister_pernet_subsys(&cma_pernet_operations); 4092 4044 destroy_workqueue(cma_wq); 4093 - idr_destroy(&tcp_ps); 4094 - idr_destroy(&udp_ps); 4095 - idr_destroy(&ipoib_ps); 4096 - idr_destroy(&ib_ps); 4097 4045 } 4098 4046 4099 4047 module_init(cma_init);