diff options
Diffstat (limited to 'net/rds/tcp.c')
| -rw-r--r-- | net/rds/tcp.c | 18 | 
1 files changed, 16 insertions, 2 deletions
diff --git a/net/rds/tcp.c b/net/rds/tcp.c index 5327d130c4b5..73ee2771093d 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c @@ -487,14 +487,27 @@ struct rds_tcp_net {  /* All module specific customizations to the RDS-TCP socket should be done in   * rds_tcp_tune() and applied after socket creation.   */ -void rds_tcp_tune(struct socket *sock) +bool rds_tcp_tune(struct socket *sock)  {  	struct sock *sk = sock->sk;  	struct net *net = sock_net(sk); -	struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid); +	struct rds_tcp_net *rtn;  	tcp_sock_set_nodelay(sock->sk);  	lock_sock(sk); +	/* TCP timer functions might access net namespace even after +	 * a process which created this net namespace terminated. +	 */ +	if (!sk->sk_net_refcnt) { +		if (!maybe_get_net(net)) { +			release_sock(sk); +			return false; +		} +		sk->sk_net_refcnt = 1; +		netns_tracker_alloc(net, &sk->ns_tracker, GFP_KERNEL); +		sock_inuse_add(net, 1); +	} +	rtn = net_generic(net, rds_tcp_netid);  	if (rtn->sndbuf_size > 0) {  		sk->sk_sndbuf = rtn->sndbuf_size;  		sk->sk_userlocks |= SOCK_SNDBUF_LOCK; @@ -504,6 +517,7 @@ void rds_tcp_tune(struct socket *sock)  		sk->sk_userlocks |= SOCK_RCVBUF_LOCK;  	}  	release_sock(sk); +	return true;  }  static void rds_tcp_accept_worker(struct work_struct *work)  | 
