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....@acronis.com> --- fs/fuse/kio/pcs/pcs_sock_io.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 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..20f088d36d6d 100644 --- a/fs/fuse/kio/pcs/pcs_sock_io.c +++ b/fs/fuse/kio/pcs/pcs_sock_io.c @@ -143,16 +143,32 @@ 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 */ + BUG_ON(it->bvec->bv_len > PAGE_SIZE); + + 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) -----Original Message----- From: Alexey Kuznetsov <kuz...@acronis.com <mailto:kuz...@acronis.com>> Date: Monday, 17 April 2023 at 10:31 PM To: Devel <devel@openvz.org <mailto:devel@openvz.org>>, Konstantin Khorenko <khore...@virtuozzo.com <mailto:khore...@virtuozzo.com>>, Kui Liu <kui....@acronis.com <mailto:kui....@acronis.com>> Subject: [PATCH RH9] fuse: pcs: do not use sendpage on pages which cannot be sendpaged Use the same approach as in iscsi iscsi_tcp_segment_map() which makes the same operation in the same context. In vz7 we added iov_iter_get_pages() infrastructure ourselves and we did it in safe way. We checked page before doing any manipulations on it right in core of iov_iter_get_pages() and terminated iov_iter_get_pages() if the page looked dubious. We cannot make this now because this function is used in many places over kernel and not all the places are sensitive to origin of pages but all of them definitely will crash if iov_iter_get_pages() returns error. This patch will work for now. I still believe this place deserves further investigation. It smells like mainstream could be wrong. Look at my comment in code for the reasons of doubts. Affects: #PSBM-146821, #PSBM-146846 https://jira.vzint.dev/browse/PSBM-146821 <https://jira.vzint.dev/browse/PSBM-146821> https://jira.vzint.dev/browse/PSBM-146846 <https://jira.vzint.dev/browse/PSBM-146846> Signed-off-by: Alexey Kuznetsov <kuz...@acronis.com <mailto:kuz...@acronis.com>>
0001-fuse-kio-do-not-use-sendpage-on-pages-which-cannot-b.patch
Description: 0001-fuse-kio-do-not-use-sendpage-on-pages-which-cannot-b.patch
_______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel