diff options
author | Ursula Braun | 2018-04-26 17:18:23 +0200 |
---|---|---|
committer | David S. Miller | 2018-04-27 14:02:52 -0400 |
commit | abb190f194d082cbb7520e692d78d3ddf050e7b1 (patch) | |
tree | cd5aa5a266ed465ffaf10810a058234d672fb8fe /net/smc/af_smc.c | |
parent | 01d2f7e2cdd31becffafa0cb82809a5e36558ec0 (diff) |
net/smc: handle sockopt TCP_DEFER_ACCEPT
If sockopt TCP_DEFER_ACCEPT is set, the accept is delayed till
data is available.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc/af_smc.c')
-rw-r--r-- | net/smc/af_smc.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 9d8b381281e3..20aa4175b9f8 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -1044,6 +1044,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock, if (lsmc->sk.sk_state != SMC_LISTEN) { rc = -EINVAL; + release_sock(sk); goto out; } @@ -1071,9 +1072,29 @@ static int smc_accept(struct socket *sock, struct socket *new_sock, if (!rc) rc = sock_error(nsk); + release_sock(sk); + if (rc) + goto out; + + if (lsmc->sockopt_defer_accept && !(flags & O_NONBLOCK)) { + /* wait till data arrives on the socket */ + timeo = msecs_to_jiffies(lsmc->sockopt_defer_accept * + MSEC_PER_SEC); + if (smc_sk(nsk)->use_fallback) { + struct sock *clcsk = smc_sk(nsk)->clcsock->sk; + + lock_sock(clcsk); + if (skb_queue_empty(&clcsk->sk_receive_queue)) + sk_wait_data(clcsk, &timeo, NULL); + release_sock(clcsk); + } else if (!atomic_read(&smc_sk(nsk)->conn.bytes_to_rcv)) { + lock_sock(nsk); + smc_rx_wait_data(smc_sk(nsk), &timeo); + release_sock(nsk); + } + } out: - release_sock(sk); sock_put(sk); /* sock_hold above */ return rc; } @@ -1340,6 +1361,9 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, 0); } break; + case TCP_DEFER_ACCEPT: + smc->sockopt_defer_accept = val; + break; default: break; } |