diff options
Diffstat (limited to 'net/smc')
| -rw-r--r-- | net/smc/af_smc.c | 25 | ||||
| -rw-r--r-- | net/smc/smc_cdc.c | 3 | ||||
| -rw-r--r-- | net/smc/smc_core.c | 2 | 
3 files changed, 24 insertions, 6 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index a4cccdfdc00a..50c38b624f77 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -2657,16 +2657,14 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)  {  	struct sock *sk = sock->sk;  	struct smc_sock *smc; -	int rc = -EPIPE; +	int rc;  	smc = smc_sk(sk);  	lock_sock(sk); -	if ((sk->sk_state != SMC_ACTIVE) && -	    (sk->sk_state != SMC_APPCLOSEWAIT1) && -	    (sk->sk_state != SMC_INIT)) -		goto out; +	/* SMC does not support connect with fastopen */  	if (msg->msg_flags & MSG_FASTOPEN) { +		/* not connected yet, fallback */  		if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) {  			rc = smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP);  			if (rc) @@ -2675,6 +2673,11 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)  			rc = -EINVAL;  			goto out;  		} +	} else if ((sk->sk_state != SMC_ACTIVE) && +		   (sk->sk_state != SMC_APPCLOSEWAIT1) && +		   (sk->sk_state != SMC_INIT)) { +		rc = -EPIPE; +		goto out;  	}  	if (smc->use_fallback) { @@ -3267,6 +3270,17 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,  			sk_common_release(sk);  			goto out;  		} + +		/* smc_clcsock_release() does not wait smc->clcsock->sk's +		 * destruction;  its sk_state might not be TCP_CLOSE after +		 * smc->sk is close()d, and TCP timers can be fired later, +		 * which need net ref. +		 */ +		sk = smc->clcsock->sk; +		__netns_tracker_free(net, &sk->ns_tracker, false); +		sk->sk_net_refcnt = 1; +		get_net_track(net, &sk->ns_tracker, GFP_KERNEL); +		sock_inuse_add(net, 1);  	} else {  		smc->clcsock = clcsock;  	} @@ -3498,6 +3512,7 @@ out_pnet:  out_nl:  	smc_nl_exit();  out_ism: +	smc_clc_exit();  	smc_ism_exit();  out_pernet_subsys_stat:  	unregister_pernet_subsys(&smc_net_stat_ops); diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c index 53f63bfbaf5f..89105e95b452 100644 --- a/net/smc/smc_cdc.c +++ b/net/smc/smc_cdc.c @@ -114,6 +114,9 @@ int smc_cdc_msg_send(struct smc_connection *conn,  	union smc_host_cursor cfed;  	int rc; +	if (unlikely(!READ_ONCE(conn->sndbuf_desc))) +		return -ENOBUFS; +  	smc_cdc_add_pending_send(conn, pend);  	conn->tx_cdc_seq++; diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index d52060b2680c..454356771cda 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -1464,7 +1464,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)  	if (lgr->terminating)  		return;	/* lgr already terminating */  	/* cancel free_work sync, will terminate when lgr->freeing is set */ -	cancel_delayed_work_sync(&lgr->free_work); +	cancel_delayed_work(&lgr->free_work);  	lgr->terminating = 1;  	/* kill remaining link group connections */  |