Skip to content

Commit 467fa15

Browse files
sowminivdavem330
authored andcommitted
RDS-TCP: Support multiple RDS-TCP listen endpoints, one per netns.
Register pernet subsys init/stop functions that will set up and tear down per-net RDS-TCP listen endpoints. Unregister pernet subusys functions on 'modprobe -r' to clean up these end points. Enable keepalive on both accept and connect socket endpoints. The keepalive timer expiration will ensure that client socket endpoints will be removed as appropriate from the netns when an interface is removed from a namespace. Register a device notifier callback that will clean up all sockets (and thus avoid the need to wait for keepalive timeout) when the loopback device is unregistered from the netns indicating that the netns is getting deleted. Signed-off-by: Sowmini Varadhan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d5a8ac2 commit 467fa15

File tree

4 files changed

+162
-50
lines changed

4 files changed

+162
-50
lines changed

net/rds/tcp.c

+145-16
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#include <linux/in.h>
3636
#include <linux/module.h>
3737
#include <net/tcp.h>
38+
#include <net/net_namespace.h>
39+
#include <net/netns/generic.h>
40+
#include <net/tcp.h>
3841

3942
#include "rds.h"
4043
#include "tcp.h"
@@ -250,16 +253,7 @@ static void rds_tcp_destroy_conns(void)
250253
}
251254
}
252255

253-
static void rds_tcp_exit(void)
254-
{
255-
rds_info_deregister_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
256-
rds_tcp_listen_stop();
257-
rds_tcp_destroy_conns();
258-
rds_trans_unregister(&rds_tcp_transport);
259-
rds_tcp_recv_exit();
260-
kmem_cache_destroy(rds_tcp_conn_slab);
261-
}
262-
module_exit(rds_tcp_exit);
256+
static void rds_tcp_exit(void);
263257

264258
struct rds_transport rds_tcp_transport = {
265259
.laddr_check = rds_tcp_laddr_check,
@@ -281,6 +275,136 @@ struct rds_transport rds_tcp_transport = {
281275
.t_prefer_loopback = 1,
282276
};
283277

278+
static int rds_tcp_netid;
279+
280+
/* per-network namespace private data for this module */
281+
struct rds_tcp_net {
282+
struct socket *rds_tcp_listen_sock;
283+
struct work_struct rds_tcp_accept_w;
284+
};
285+
286+
static void rds_tcp_accept_worker(struct work_struct *work)
287+
{
288+
struct rds_tcp_net *rtn = container_of(work,
289+
struct rds_tcp_net,
290+
rds_tcp_accept_w);
291+
292+
while (rds_tcp_accept_one(rtn->rds_tcp_listen_sock) == 0)
293+
cond_resched();
294+
}
295+
296+
void rds_tcp_accept_work(struct sock *sk)
297+
{
298+
struct net *net = sock_net(sk);
299+
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
300+
301+
queue_work(rds_wq, &rtn->rds_tcp_accept_w);
302+
}
303+
304+
static __net_init int rds_tcp_init_net(struct net *net)
305+
{
306+
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
307+
308+
rtn->rds_tcp_listen_sock = rds_tcp_listen_init(net);
309+
if (!rtn->rds_tcp_listen_sock) {
310+
pr_warn("could not set up listen sock\n");
311+
return -EAFNOSUPPORT;
312+
}
313+
INIT_WORK(&rtn->rds_tcp_accept_w, rds_tcp_accept_worker);
314+
return 0;
315+
}
316+
317+
static void __net_exit rds_tcp_exit_net(struct net *net)
318+
{
319+
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
320+
321+
/* If rds_tcp_exit_net() is called as a result of netns deletion,
322+
* the rds_tcp_kill_sock() device notifier would already have cleaned
323+
* up the listen socket, thus there is no work to do in this function.
324+
*
325+
* If rds_tcp_exit_net() is called as a result of module unload,
326+
* i.e., due to rds_tcp_exit() -> unregister_pernet_subsys(), then
327+
* we do need to clean up the listen socket here.
328+
*/
329+
if (rtn->rds_tcp_listen_sock) {
330+
rds_tcp_listen_stop(rtn->rds_tcp_listen_sock);
331+
rtn->rds_tcp_listen_sock = NULL;
332+
flush_work(&rtn->rds_tcp_accept_w);
333+
}
334+
}
335+
336+
static struct pernet_operations rds_tcp_net_ops = {
337+
.init = rds_tcp_init_net,
338+
.exit = rds_tcp_exit_net,
339+
.id = &rds_tcp_netid,
340+
.size = sizeof(struct rds_tcp_net),
341+
};
342+
343+
static void rds_tcp_kill_sock(struct net *net)
344+
{
345+
struct rds_tcp_connection *tc, *_tc;
346+
struct sock *sk;
347+
LIST_HEAD(tmp_list);
348+
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
349+
350+
rds_tcp_listen_stop(rtn->rds_tcp_listen_sock);
351+
rtn->rds_tcp_listen_sock = NULL;
352+
flush_work(&rtn->rds_tcp_accept_w);
353+
spin_lock_irq(&rds_tcp_conn_lock);
354+
list_for_each_entry_safe(tc, _tc, &rds_tcp_conn_list, t_tcp_node) {
355+
struct net *c_net = read_pnet(&tc->conn->c_net);
356+
357+
if (net != c_net || !tc->t_sock)
358+
continue;
359+
list_move_tail(&tc->t_tcp_node, &tmp_list);
360+
}
361+
spin_unlock_irq(&rds_tcp_conn_lock);
362+
list_for_each_entry_safe(tc, _tc, &tmp_list, t_tcp_node) {
363+
sk = tc->t_sock->sk;
364+
sk->sk_prot->disconnect(sk, 0);
365+
tcp_done(sk);
366+
if (tc->conn->c_passive)
367+
rds_conn_destroy(tc->conn->c_passive);
368+
rds_conn_destroy(tc->conn);
369+
}
370+
}
371+
372+
static int rds_tcp_dev_event(struct notifier_block *this,
373+
unsigned long event, void *ptr)
374+
{
375+
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
376+
377+
/* rds-tcp registers as a pernet subys, so the ->exit will only
378+
* get invoked after network acitivity has quiesced. We need to
379+
* clean up all sockets to quiesce network activity, and use
380+
* the unregistration of the per-net loopback device as a trigger
381+
* to start that cleanup.
382+
*/
383+
if (event == NETDEV_UNREGISTER_FINAL &&
384+
dev->ifindex == LOOPBACK_IFINDEX)
385+
rds_tcp_kill_sock(dev_net(dev));
386+
387+
return NOTIFY_DONE;
388+
}
389+
390+
static struct notifier_block rds_tcp_dev_notifier = {
391+
.notifier_call = rds_tcp_dev_event,
392+
.priority = -10, /* must be called after other network notifiers */
393+
};
394+
395+
static void rds_tcp_exit(void)
396+
{
397+
rds_info_deregister_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
398+
unregister_pernet_subsys(&rds_tcp_net_ops);
399+
if (unregister_netdevice_notifier(&rds_tcp_dev_notifier))
400+
pr_warn("could not unregister rds_tcp_dev_notifier\n");
401+
rds_tcp_destroy_conns();
402+
rds_trans_unregister(&rds_tcp_transport);
403+
rds_tcp_recv_exit();
404+
kmem_cache_destroy(rds_tcp_conn_slab);
405+
}
406+
module_exit(rds_tcp_exit);
407+
284408
static int rds_tcp_init(void)
285409
{
286410
int ret;
@@ -293,6 +417,16 @@ static int rds_tcp_init(void)
293417
goto out;
294418
}
295419

420+
ret = register_netdevice_notifier(&rds_tcp_dev_notifier);
421+
if (ret) {
422+
pr_warn("could not register rds_tcp_dev_notifier\n");
423+
goto out;
424+
}
425+
426+
ret = register_pernet_subsys(&rds_tcp_net_ops);
427+
if (ret)
428+
goto out_slab;
429+
296430
ret = rds_tcp_recv_init();
297431
if (ret)
298432
goto out_slab;
@@ -301,19 +435,14 @@ static int rds_tcp_init(void)
301435
if (ret)
302436
goto out_recv;
303437

304-
ret = rds_tcp_listen_init();
305-
if (ret)
306-
goto out_register;
307-
308438
rds_info_register_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
309439

310440
goto out;
311441

312-
out_register:
313-
rds_trans_unregister(&rds_tcp_transport);
314442
out_recv:
315443
rds_tcp_recv_exit();
316444
out_slab:
445+
unregister_pernet_subsys(&rds_tcp_net_ops);
317446
kmem_cache_destroy(rds_tcp_conn_slab);
318447
out:
319448
return ret;

net/rds/tcp.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,19 @@ u32 rds_tcp_snd_nxt(struct rds_tcp_connection *tc);
5252
u32 rds_tcp_snd_una(struct rds_tcp_connection *tc);
5353
u64 rds_tcp_map_seq(struct rds_tcp_connection *tc, u32 seq);
5454
extern struct rds_transport rds_tcp_transport;
55+
void rds_tcp_accept_work(struct sock *sk);
5556

5657
/* tcp_connect.c */
5758
int rds_tcp_conn_connect(struct rds_connection *conn);
5859
void rds_tcp_conn_shutdown(struct rds_connection *conn);
5960
void rds_tcp_state_change(struct sock *sk);
6061

6162
/* tcp_listen.c */
62-
int rds_tcp_listen_init(void);
63-
void rds_tcp_listen_stop(void);
63+
struct socket *rds_tcp_listen_init(struct net *);
64+
void rds_tcp_listen_stop(struct socket *);
6465
void rds_tcp_listen_data_ready(struct sock *sk);
66+
int rds_tcp_accept_one(struct socket *sock);
67+
int rds_tcp_keepalive(struct socket *sock);
6568

6669
/* tcp_recv.c */
6770
int rds_tcp_recv_init(void);

net/rds/tcp_connect.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,12 @@ int rds_tcp_conn_connect(struct rds_connection *conn)
112112
rdsdebug("connect to address %pI4 returned %d\n", &conn->c_faddr, ret);
113113
if (ret == -EINPROGRESS)
114114
ret = 0;
115-
if (ret == 0)
115+
if (ret == 0) {
116+
rds_tcp_keepalive(sock);
116117
sock = NULL;
117-
else
118+
} else {
118119
rds_tcp_restore_callbacks(sock, conn->c_transport_data);
120+
}
119121

120122
out:
121123
if (sock)

net/rds/tcp_listen.c

+8-30
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,7 @@
3838
#include "rds.h"
3939
#include "tcp.h"
4040

41-
/*
42-
* cheesy, but simple..
43-
*/
44-
static void rds_tcp_accept_worker(struct work_struct *work);
45-
static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker);
46-
static struct socket *rds_tcp_listen_sock;
47-
48-
static int rds_tcp_keepalive(struct socket *sock)
41+
int rds_tcp_keepalive(struct socket *sock)
4942
{
5043
/* values below based on xs_udp_default_timeout */
5144
int keepidle = 5; /* send a probe 'keepidle' secs after last data */
@@ -77,7 +70,7 @@ static int rds_tcp_keepalive(struct socket *sock)
7770
return ret;
7871
}
7972

80-
static int rds_tcp_accept_one(struct socket *sock)
73+
int rds_tcp_accept_one(struct socket *sock)
8174
{
8275
struct socket *new_sock = NULL;
8376
struct rds_connection *conn;
@@ -150,12 +143,6 @@ static int rds_tcp_accept_one(struct socket *sock)
150143
return ret;
151144
}
152145

153-
static void rds_tcp_accept_worker(struct work_struct *work)
154-
{
155-
while (rds_tcp_accept_one(rds_tcp_listen_sock) == 0)
156-
cond_resched();
157-
}
158-
159146
void rds_tcp_listen_data_ready(struct sock *sk)
160147
{
161148
void (*ready)(struct sock *sk);
@@ -176,26 +163,20 @@ void rds_tcp_listen_data_ready(struct sock *sk)
176163
* socket
177164
*/
178165
if (sk->sk_state == TCP_LISTEN)
179-
queue_work(rds_wq, &rds_tcp_listen_work);
166+
rds_tcp_accept_work(sk);
180167

181168
out:
182169
read_unlock(&sk->sk_callback_lock);
183170
ready(sk);
184171
}
185172

186-
int rds_tcp_listen_init(void)
173+
struct socket *rds_tcp_listen_init(struct net *net)
187174
{
188175
struct sockaddr_in sin;
189176
struct socket *sock = NULL;
190177
int ret;
191178

192-
/* MUST call sock_create_kern directly so that we avoid get_net()
193-
* in sk_alloc(). Doing a get_net() will result in cleanup_net()
194-
* never getting invoked, which will leave sock and other things
195-
* in limbo.
196-
*/
197-
ret = sock_create_kern(current->nsproxy->net_ns, PF_INET,
198-
SOCK_STREAM, IPPROTO_TCP, &sock);
179+
ret = sock_create_kern(net, PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
199180
if (ret < 0)
200181
goto out;
201182

@@ -219,17 +200,15 @@ int rds_tcp_listen_init(void)
219200
if (ret < 0)
220201
goto out;
221202

222-
rds_tcp_listen_sock = sock;
223-
sock = NULL;
203+
return sock;
224204
out:
225205
if (sock)
226206
sock_release(sock);
227-
return ret;
207+
return NULL;
228208
}
229209

230-
void rds_tcp_listen_stop(void)
210+
void rds_tcp_listen_stop(struct socket *sock)
231211
{
232-
struct socket *sock = rds_tcp_listen_sock;
233212
struct sock *sk;
234213

235214
if (!sock)
@@ -250,5 +229,4 @@ void rds_tcp_listen_stop(void)
250229
/* wait for accepts to stop and close the socket */
251230
flush_workqueue(rds_wq);
252231
sock_release(sock);
253-
rds_tcp_listen_sock = NULL;
254232
}

0 commit comments

Comments
 (0)