From ca455204c1cf0deae41e493ceadd253e6afd35d6 Mon Sep 17 00:00:00 2001 From: Ofir Gal Date: Thu, 30 Jan 2025 14:26:41 +1300 Subject: [PATCH] net: introduce helper sendpages_ok() BugLink: https://bugs.launchpad.net/bugs/2093871 Network drivers are using sendpage_ok() to check the first page of an iterator in order to disable MSG_SPLICE_PAGES. The iterator can represent list of contiguous pages. When MSG_SPLICE_PAGES is enabled skb_splice_from_iter() is being used, it requires all pages in the iterator to be sendable. Therefore it needs to check that each page is sendable. The patch introduces a helper sendpages_ok(), it returns true if all the contiguous pages are sendable. Drivers who want to send contiguous pages with MSG_SPLICE_PAGES may use this helper to check whether the page list is OK. If the helper does not return true, the driver should remove MSG_SPLICE_PAGES flag. Reviewed-by: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Ofir Gal Acked-by: Jakub Kicinski Link: https://lore.kernel.org/r/20240718084515.3833733-2-ofir.gal@volumez.com Signed-off-by: Jens Axboe (cherry picked from commit 23a55f4492fcf868d068da31a2cd30c15f46207d) Signed-off-by: Matthew Ruffell Acked-by: Koichiro Den Acked-by: Manuel Diewald Signed-off-by: Koichiro Den --- include/linux/net.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/linux/net.h b/include/linux/net.h index c9b4a63791a4..4d4c2b2439ee 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -323,6 +323,25 @@ static inline bool sendpage_ok(struct page *page) return !PageSlab(page) && page_count(page) >= 1; } +/* + * Check sendpage_ok on contiguous pages. + */ +static inline bool sendpages_ok(struct page *page, size_t len, size_t offset) +{ + struct page *p = page + (offset >> PAGE_SHIFT); + size_t count = 0; + + while (count < len) { + if (!sendpage_ok(p)) + return false; + + p++; + count += PAGE_SIZE; + } + + return true; +} + int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t len); int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,