Skip to content

Commit e18e157

Browse files
committed
SUNRPC: Send RPC message on TCP with a single sock_sendmsg() call
There is now enough infrastructure in place to combine the stream record marker into the biovec array used to send each outgoing RPC message on TCP. The whole message can be more efficiently sent with a single call to sock_sendmsg() using a bio_vec iterator. Note that this also helps with RPC-with-TLS: the TLS implementation can now clearly see where the upper layer message boundaries are. Before, it would send each component of the xdr_buf (record marker, head, page payload, tail) in separate TLS records. Suggested-by: David Howells <[email protected]> Reviewed-by: David Howells <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 2eb2b93 commit e18e157

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

include/linux/sunrpc/svcsock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ struct svc_sock {
3838
/* Number of queued send requests */
3939
atomic_t sk_sendqlen;
4040

41+
struct page_frag_cache sk_frag_cache;
42+
4143
struct completion sk_handshake_done;
4244

4345
struct page * sk_pages[RPCSVC_MAXPAGES]; /* received data */

net/sunrpc/svcsock.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,31 +1213,30 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
12131213
static int svc_tcp_sendmsg(struct svc_sock *svsk, struct svc_rqst *rqstp,
12141214
rpc_fraghdr marker, unsigned int *sentp)
12151215
{
1216-
struct kvec rm = {
1217-
.iov_base = &marker,
1218-
.iov_len = sizeof(marker),
1219-
};
12201216
struct msghdr msg = {
1221-
.msg_flags = MSG_MORE,
1217+
.msg_flags = MSG_SPLICE_PAGES,
12221218
};
12231219
unsigned int count;
1220+
void *buf;
12241221
int ret;
12251222

12261223
*sentp = 0;
12271224

1228-
ret = kernel_sendmsg(svsk->sk_sock, &msg, &rm, 1, rm.iov_len);
1229-
if (ret < 0)
1230-
return ret;
1231-
*sentp += ret;
1232-
if (ret != rm.iov_len)
1233-
return -EAGAIN;
1225+
/* The stream record marker is copied into a temporary page
1226+
* fragment buffer so that it can be included in rq_bvec.
1227+
*/
1228+
buf = page_frag_alloc(&svsk->sk_frag_cache, sizeof(marker),
1229+
GFP_KERNEL);
1230+
if (!buf)
1231+
return -ENOMEM;
1232+
memcpy(buf, &marker, sizeof(marker));
1233+
bvec_set_virt(rqstp->rq_bvec, buf, sizeof(marker));
12341234

1235-
count = xdr_buf_to_bvec(rqstp->rq_bvec, ARRAY_SIZE(rqstp->rq_bvec),
1236-
&rqstp->rq_res);
1235+
count = xdr_buf_to_bvec(rqstp->rq_bvec + 1,
1236+
ARRAY_SIZE(rqstp->rq_bvec) - 1, &rqstp->rq_res);
12371237

1238-
msg.msg_flags = MSG_SPLICE_PAGES;
12391238
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, rqstp->rq_bvec,
1240-
count, rqstp->rq_res.len);
1239+
1 + count, sizeof(marker) + rqstp->rq_res.len);
12411240
ret = sock_sendmsg(svsk->sk_sock, &msg);
12421241
if (ret < 0)
12431242
return ret;
@@ -1616,6 +1615,7 @@ static void svc_tcp_sock_detach(struct svc_xprt *xprt)
16161615
static void svc_sock_free(struct svc_xprt *xprt)
16171616
{
16181617
struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
1618+
struct page_frag_cache *pfc = &svsk->sk_frag_cache;
16191619
struct socket *sock = svsk->sk_sock;
16201620

16211621
trace_svcsock_free(svsk, sock);
@@ -1625,5 +1625,8 @@ static void svc_sock_free(struct svc_xprt *xprt)
16251625
sockfd_put(sock);
16261626
else
16271627
sock_release(sock);
1628+
if (pfc->va)
1629+
__page_frag_cache_drain(virt_to_head_page(pfc->va),
1630+
pfc->pagecnt_bias);
16281631
kfree(svsk);
16291632
}

0 commit comments

Comments
 (0)