From 19487feafb6b5c55bebd2a1f979217277a8157f8 Mon Sep 17 00:00:00 2001
From: Liu Kui <Kui.Liu@acronis.com>
Date: Wed, 19 Apr 2023 18:49:03 +0800
Subject: [PATCH RH9 v2] fuse/kio: do not use sendpage on pages which cannot be
 sendpaged

It looks like the new API iov_iter_get_pages is not safe for use
when trying to get a page from a bvec to be sent by kernel_sendpage().
So just revert back our own implentation where we check the page
before making get_page(), if the page can't be sendpage, fall back
to copy mode.

Affects: #PSBM-146821, #PSBM-146846
https://jira.vzint.dev/browse/PSBM-146821
https://jira.vzint.dev/browse/PSBM-146846
Signed-off-by: Liu Kui <Kui.Liu@acronis.com>
---
 fs/fuse/kio/pcs/pcs_sock_io.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/fs/fuse/kio/pcs/pcs_sock_io.c b/fs/fuse/kio/pcs/pcs_sock_io.c
index 552b82ab398b..710940eafa34 100644
--- a/fs/fuse/kio/pcs/pcs_sock_io.c
+++ b/fs/fuse/kio/pcs/pcs_sock_io.c
@@ -143,16 +143,30 @@ static int do_send_one_seg(struct socket *sock, struct iov_iter *it, size_t left
 	}
 
 	if (iov_iter_is_bvec(it)) {
-		/* Zerocopy */
 		size_t offset;
 		ssize_t len;
 		struct page *page;
 
-		len = iov_iter_get_pages(it, &page, size, 1, &offset);
-		BUG_ON(len <= 0);
-
-		ret = kernel_sendpage(sock, page, offset, len, flags);
-		put_page(page);
+		/* Only support single page bvec here */
+		page = it->bvec->bv_page;
+		offset = it->bvec->bv_offset + it->iov_offset;
+		len = min(size, it->bvec->bv_len - it->iov_offset);
+
+		if (sendpage_ok(page)) {
+			/* Zero copy */
+			get_page(page);
+			ret = kernel_sendpage(sock, page, offset, len, flags);
+			put_page(page);
+		} else {
+			/* Fall back to copy mode */
+			struct msghdr msg = { .msg_flags = flags };
+			struct kvec kv;
+
+			kv.iov_base = kmap(page) + offset;
+			kv.iov_len = len;
+			ret = kernel_sendmsg(sock, &msg, &kv, 1, size);
+			kunmap(page);
+		}
 	}
 
 out:
-- 
2.32.0 (Apple Git-132)

