From: Chuck Lever <chuck.lever@xxxxxxxxxx> I noticed that server-side TLS always sends the RPC record marker as a separate 4-byte TLS record. This is très inefficace. It seems to be due to commit 987c7b1d094d ("SUNRPC: Remove redundant socket flags from svc_tcp_sendmsg()"), which removed the MSG_* flags from svc_tcp_sendmsg() in favor of using tcp_sock_set_cork. TLS, which rides on top of TCP, ignores the socket's cork setting. Client-side RPC also uses tcp_sock_set_cork, but it still sets MSG_MORE. I don't see similar uncoalesced TLS record traffic there. Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- net/sunrpc/svcsock.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 03a4f5615086..28deb4acc392 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1086,9 +1086,9 @@ static int svc_tcp_sendmsg(struct socket *sock, struct xdr_buf *xdr, .iov_len = sizeof(marker), }; struct msghdr msg = { - .msg_flags = 0, + .msg_flags = MSG_MORE, }; - int ret; + int flags, ret; *sentp = 0; ret = xdr_alloc_bvec(xdr, GFP_KERNEL); @@ -1101,8 +1101,8 @@ static int svc_tcp_sendmsg(struct socket *sock, struct xdr_buf *xdr, *sentp += ret; if (ret != rm.iov_len) return -EAGAIN; - - ret = svc_tcp_send_kvec(sock, head, 0); + flags = head->iov_len < xdr->len ? MSG_MORE | MSG_SENDPAGE_NOTLAST : 0; + ret = svc_tcp_send_kvec(sock, head, flags); if (ret < 0) return ret; *sentp += ret; @@ -1117,10 +1117,12 @@ static int svc_tcp_sendmsg(struct socket *sock, struct xdr_buf *xdr, offset = offset_in_page(xdr->page_base); remaining = xdr->page_len; while (remaining > 0) { + if (remaining <= PAGE_SIZE && tail->iov_len == 0) + flags = 0; len = min(remaining, bvec->bv_len - offset); ret = kernel_sendpage(sock, bvec->bv_page, bvec->bv_offset + offset, - len, 0); + len, flags); if (ret < 0) return ret; *sentp += ret;