[PATCH 3/5] SUNRPC: Flush a received record's pages once it is complete
Chuck Lever <[email protected]>
| Newsgroups | org.kernel.vger.linux-nfs,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
svc_tcp_read_msg() flushes the destination pages after every receive. A record that arrives in several pieces is therefore flushed once per piece. A page spanning two pieces is flushed twice. Nothing reads the message body before the record is complete, so no reader needs the intermediate flushes. Flush every page of the record in one pass from svc_tcp_recvfrom(), once the last fragment has arrived. Remove svc_flush_bvec() and its ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE guard. The guard avoided setting up a bvec iterator, and a plain walk of rq_pages compiles away on its own where flush_dcache_page() is an empty inline. Signed-off-by: Chuck Lever <[email protected]> --- net/sunrpc/svcsock.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index ae1f3c474f8b..c7b94bd1898b 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -334,25 +334,6 @@ svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg) return ret; } -#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE -static void svc_flush_bvec(const struct bio_vec *bvec, size_t size, size_t seek) -{ - struct bvec_iter bi = { - .bi_size = size + seek, - }; - struct bio_vec bv; - - bvec_iter_advance(bvec, &bi, seek & PAGE_MASK); - for_each_bvec(bv, bvec, bi, bi) - flush_dcache_page(bv.bv_page); -} -#else -static inline void svc_flush_bvec(const struct bio_vec *bvec, size_t size, - size_t seek) -{ -} -#endif - /* * Read from @rqstp's transport socket. The incoming message fills whole * pages in @rqstp's rq_pages array until the last page of the message @@ -380,8 +361,6 @@ static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen, buflen -= seek; } len = svc_tcp_sock_recvmsg(svsk, &msg); - if (len > 0) - svc_flush_bvec(bvec, len, seek); /* If we read a full record, then assume there may be more * data to read (stream based sockets only!) @@ -1156,6 +1135,19 @@ static void svc_tcp_fragment_received(struct svc_sock *svsk) svsk->sk_marker = xdr_zero; } +/* + * Nothing reads the message body before the record is complete, so + * a single flush after the last fragment is enough. + */ +static void svc_tcp_flush_pages(struct svc_sock *svsk, + struct svc_rqst *rqstp) +{ + unsigned int pg, pages = DIV_ROUND_UP(svsk->sk_datalen, PAGE_SIZE); + + for (pg = 0; pg < pages; pg++) + flush_dcache_page(rqstp->rq_pages[pg]); +} + /** * svc_tcp_recvfrom - Receive data from a TCP socket * @rqstp: request structure into which to receive an RPC Call @@ -1202,6 +1194,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) if (svsk->sk_datalen < 8) goto err_nuts; + svc_tcp_flush_pages(svsk, rqstp); + rqstp->rq_arg.len = svsk->sk_datalen; rqstp->rq_arg.page_base = 0; if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { -- 2.54.0