[PATCH 5/8] SUNRPC: fold svc_tcp_sock_process_cmsg() into its only caller

Chuck Lever <[email protected]> Wed, 05 Aug 2026 14:30:56 -0400
Newsgroups gmane.linux.nfs,gmane.linux.network
Message-ID <[email protected]>
svc_tcp_sock_process_cmsg() switches on the TLS record type.
svc_tcp_sock_recv_cmsg() now returns -EAGAIN for every record type
except an alert before it calls the helper. The case 0,
TLS_RECORD_TYPE_DATA, and default arms are unreachable. The DATA arm
is inert twice over. It clears MSG_EOR in the msghdr local to
svc_tcp_sock_recv_cmsg(), and that msghdr is discarded on return.
svc_tcp_sock_recvmsg() has already cleared the flag in the caller's
msghdr. Deriving the record type a second time inside the helper also
fires trace_tls_contenttype() twice for every alert.

Move the alert handling into svc_tcp_sock_recv_cmsg() and delete the
helper. The DATA arm's account of MSG_EOR moves to
svc_tcp_sock_recvmsg(), where the flag is now cleared.

Signed-off-by: Chuck Lever <[email protected]>
---
 net/sunrpc/svcsock.c | 58 ++++++++++++++++------------------------------------
 1 file changed, 18 insertions(+), 40 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d8e836e0832e..6ed136dff0a4 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -271,45 +271,6 @@ svc_tcp_sock_drain_record(struct socket *sock)
 	}
 }
 
-static int
-svc_tcp_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
-			  struct cmsghdr *cmsg, int ret)
-{
-	u8 content_type = tls_get_record_type(sock->sk, cmsg);
-	u8 level, description;
-
-	switch (content_type) {
-	case 0:
-		break;
-	case TLS_RECORD_TYPE_DATA:
-		/* TLS sets EOR at the end of each application data
-		 * record, even though there might be more frames
-		 * waiting to be decrypted.
-		 */
-		msg->msg_flags &= ~MSG_EOR;
-		break;
-	case TLS_RECORD_TYPE_ALERT:
-		tls_alert_recv(sock->sk, msg, &level, &description);
-		/* RFC 8446 Section 6: every alert but a closure alert is
-		 * an error alert, whatever the legacy AlertLevel octet
-		 * says.
-		 */
-		switch (description) {
-		case TLS_ALERT_DESC_CLOSE_NOTIFY:
-		case TLS_ALERT_DESC_USER_CANCELED:
-			ret = -EAGAIN;
-			break;
-		default:
-			ret = -ENOTCONN;
-		}
-		break;
-	default:
-		/* discard this record type */
-		ret = -EAGAIN;
-	}
-	return ret;
-}
-
 static int
 svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags)
 {
@@ -327,6 +288,7 @@ svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags)
 		.msg_control = &u,
 		.msg_controllen = sizeof(u),
 	};
+	u8 level, description;
 	int ret;
 
 	iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1,
@@ -358,7 +320,19 @@ svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags)
 		if (ret != sizeof(alert) || !(msg.msg_flags & MSG_EOR))
 			return -EBADMSG;
 		iov_iter_revert(&msg.msg_iter, ret);
-		ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN);
+		tls_alert_recv(sock->sk, &msg, &level, &description);
+		/* RFC 8446 Section 6: every alert but a closure alert is
+		 * an error alert, whatever the legacy AlertLevel octet
+		 * says.
+		 */
+		switch (description) {
+		case TLS_ALERT_DESC_CLOSE_NOTIFY:
+		case TLS_ALERT_DESC_USER_CANCELED:
+			ret = -EAGAIN;
+			break;
+		default:
+			ret = -ENOTCONN;
+		}
 	}
 	return ret;
 }
@@ -371,6 +345,10 @@ svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg)
 
 	ret = sock_recvmsg(sock, msg, MSG_DONTWAIT);
 	if (msg->msg_flags & MSG_CTRUNC) {
+		/* TLS sets EOR at the end of each application data
+		 * record, even though there might be more frames
+		 * waiting to be decrypted.
+		 */
 		msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR);
 		if (ret == 0 || ret == -EIO) {
 			ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags);

-- 
2.54.0