diff options
author | Trond Myklebust <trondmy@gmail.com> | 2019-01-03 09:04:45 -0500 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2019-01-08 12:44:51 -0500 |
commit | 6a829eb8619fbdde6d7d627ad582fe119805f39d (patch) | |
tree | ed35a8545101f3c88de6142f16455e3603a66624 /net/sunrpc/xprtsock.c | |
parent | 6e17f58c486d9554341f70aa5b63b8fbed07b3fa (diff) |
SUNRPC: Fix TCP receive code on archs with flush_dcache_page()
After receiving data into the page cache, we need to call flush_dcache_page()
for the architectures that define it.
Fixes: 277e4ab7d530b ("SUNRPC: Simplify TCP receive code by switching...")
Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: stable@vger.kernel.org # v4.20
Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 13559e6a460b..7754aa3e434f 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <net/udp.h> | 48 | #include <net/udp.h> |
49 | #include <net/tcp.h> | 49 | #include <net/tcp.h> |
50 | #include <linux/bvec.h> | 50 | #include <linux/bvec.h> |
51 | #include <linux/highmem.h> | ||
51 | #include <linux/uio.h> | 52 | #include <linux/uio.h> |
52 | 53 | ||
53 | #include <trace/events/sunrpc.h> | 54 | #include <trace/events/sunrpc.h> |
@@ -376,6 +377,26 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags, | |||
376 | return sock_recvmsg(sock, msg, flags); | 377 | return sock_recvmsg(sock, msg, flags); |
377 | } | 378 | } |
378 | 379 | ||
380 | #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
381 | static void | ||
382 | xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek) | ||
383 | { | ||
384 | struct bvec_iter bi = { | ||
385 | .bi_size = count, | ||
386 | }; | ||
387 | struct bio_vec bv; | ||
388 | |||
389 | bvec_iter_advance(bvec, &bi, seek & PAGE_MASK); | ||
390 | for_each_bvec(bv, bvec, bi, bi) | ||
391 | flush_dcache_page(bv.bv_page); | ||
392 | } | ||
393 | #else | ||
394 | static inline void | ||
395 | xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek) | ||
396 | { | ||
397 | } | ||
398 | #endif | ||
399 | |||
379 | static ssize_t | 400 | static ssize_t |
380 | xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, | 401 | xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, |
381 | struct xdr_buf *buf, size_t count, size_t seek, size_t *read) | 402 | struct xdr_buf *buf, size_t count, size_t seek, size_t *read) |
@@ -409,6 +430,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, | |||
409 | seek + buf->page_base); | 430 | seek + buf->page_base); |
410 | if (ret <= 0) | 431 | if (ret <= 0) |
411 | goto sock_err; | 432 | goto sock_err; |
433 | xs_flush_bvec(buf->bvec, ret, seek + buf->page_base); | ||
412 | offset += ret - buf->page_base; | 434 | offset += ret - buf->page_base; |
413 | if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC)) | 435 | if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC)) |
414 | goto out; | 436 | goto out; |