[RFC net-next 03/20] net/smc: refactor smc_setsockopt

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux