From: "D. Wythe" <alibuda@xxxxxxxxxxxxxxxxx> Refactoring the processing of socket options in SMC, extracting common processing functions and unsupported options. Signed-off-by: D. Wythe <alibuda@xxxxxxxxxxxxxxxxx> --- net/smc/af_smc.c | 101 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 38 deletions(-) diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index bdb6dd7..e87af68 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -3038,58 +3038,40 @@ static int __smc_setsockopt(struct socket *sock, int level, int optname, return rc; } -static int smc_setsockopt(struct socket *sock, int level, int optname, - sockptr_t optval, unsigned int optlen) +/* When an unsupported sockopt is found, + * SMC should try it best to fallback. If fallback is not possible, + * an error should be explicitly returned. + */ +static inline bool smc_is_unsupport_tcp_sockopt(int optname) +{ + switch (optname) { + case TCP_FASTOPEN: + case TCP_FASTOPEN_CONNECT: + case TCP_FASTOPEN_KEY: + case TCP_FASTOPEN_NO_COOKIE: + return true; + } + return false; +} + +static int smc_setsockopt_common(struct socket *sock, int level, int optname, + sockptr_t optval, unsigned int optlen) { struct sock *sk = sock->sk; struct smc_sock *smc; - int val, rc; - - if (level == SOL_TCP && optname == TCP_ULP) - return -EOPNOTSUPP; - else if (level == SOL_SMC) - return __smc_setsockopt(sock, level, optname, optval, optlen); + int val, rc = 0; smc = smc_sk(sk); - /* generic setsockopts reaching us here always apply to the - * CLC socket - */ - mutex_lock(&smc->clcsock_release_lock); - if (!smc->clcsock) { - mutex_unlock(&smc->clcsock_release_lock); - return -EBADF; - } - if (unlikely(!smc->clcsock->ops->setsockopt)) - rc = -EOPNOTSUPP; - else - rc = smc->clcsock->ops->setsockopt(smc->clcsock, level, optname, - optval, optlen); - if (smc->clcsock->sk->sk_err) { - sk->sk_err = smc->clcsock->sk->sk_err; - sk_error_report(sk); - } - mutex_unlock(&smc->clcsock_release_lock); - if (optlen < sizeof(int)) return -EINVAL; if (copy_from_sockptr(&val, optval, sizeof(int))) return -EFAULT; lock_sock(sk); - if (rc || smc->use_fallback) + if (smc->use_fallback) goto out; switch (optname) { - case TCP_FASTOPEN: - case TCP_FASTOPEN_CONNECT: - case TCP_FASTOPEN_KEY: - case TCP_FASTOPEN_NO_COOKIE: - /* option not supported by SMC */ - if (smc_sk_state(sk) == SMC_INIT && !smc->connect_nonblock) - rc = smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP); - else - rc = -EINVAL; - break; case TCP_NODELAY: if (smc_sk_state(sk) != SMC_INIT && smc_sk_state(sk) != SMC_LISTEN && @@ -3116,6 +3098,13 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, smc->sockopt_defer_accept = val; break; default: + if (smc_is_unsupport_tcp_sockopt(optname)) { + /* option not supported by SMC */ + if (smc_sk_state(sk) == SMC_INIT && !smc->connect_nonblock) + rc = smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP); + else + rc = -EINVAL; + } break; } out: @@ -3124,6 +3113,42 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, return rc; } +static int smc_setsockopt(struct socket *sock, int level, int optname, + sockptr_t optval, unsigned int optlen) +{ + struct sock *sk = sock->sk; + struct smc_sock *smc; + int rc; + + if (level == SOL_TCP && optname == TCP_ULP) + return -EOPNOTSUPP; + else if (level == SOL_SMC) + return __smc_setsockopt(sock, level, optname, optval, optlen); + + smc = smc_sk(sk); + + /* generic setsockopts reaching us here always apply to the + * CLC socket + */ + mutex_lock(&smc->clcsock_release_lock); + if (!smc->clcsock) { + mutex_unlock(&smc->clcsock_release_lock); + return -EBADF; + } + if (unlikely(!smc->clcsock->ops->setsockopt)) + rc = -EOPNOTSUPP; + else + rc = smc->clcsock->ops->setsockopt(smc->clcsock, level, optname, + optval, optlen); + if (smc->clcsock->sk->sk_err) { + sk->sk_err = smc->clcsock->sk->sk_err; + sk_error_report(sk); + } + mutex_unlock(&smc->clcsock_release_lock); + + return rc ?: smc_setsockopt_common(sock, level, optname, optval, optlen); +} + static int smc_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { -- 1.8.3.1