Message ID | 20240530132629.4180932-2-ofir.gal@volumez.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/4] net: introduce helper sendpages_ok() | expand |
On 5/30/24 15:26, Ofir Gal wrote: > 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. > > Signed-off-by: Ofir Gal <ofir.gal@volumez.com> > --- > include/linux/net.h | 20 ++++++++++++++++++++ > 1 file changed, 20 insertions(+) > > diff --git a/include/linux/net.h b/include/linux/net.h > index 688320b79fcc..b33bdc3e2031 100644 > --- a/include/linux/net.h > +++ b/include/linux/net.h > @@ -322,6 +322,26 @@ 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) > +{ > + unsigned int pagecount; > + size_t page_offset; > + int k; > + > + page = page + offset / PAGE_SIZE; > + page_offset = offset % PAGE_SIZE; > + pagecount = DIV_ROUND_UP(len + page_offset, PAGE_SIZE); > + Don't we miss the first page for offset > PAGE_SIZE? I'd rather check for all pages from 'page' up to (offset + len), just to be on the safe side. > + for (k = 0; k < pagecount; k++) > + if (!sendpage_ok(page + k)) > + return false; > + > + 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, Cheers, Hannes
On 03/06/2024 10:18, Hannes Reinecke wrote: > On 5/30/24 15:26, Ofir Gal wrote: >> 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. >> >> Signed-off-by: Ofir Gal <ofir.gal@volumez.com> >> --- >> include/linux/net.h | 20 ++++++++++++++++++++ >> 1 file changed, 20 insertions(+) >> >> diff --git a/include/linux/net.h b/include/linux/net.h >> index 688320b79fcc..b33bdc3e2031 100644 >> --- a/include/linux/net.h >> +++ b/include/linux/net.h >> @@ -322,6 +322,26 @@ 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) >> +{ >> + unsigned int pagecount; >> + size_t page_offset; >> + int k; >> + >> + page = page + offset / PAGE_SIZE; >> + page_offset = offset % PAGE_SIZE; >> + pagecount = DIV_ROUND_UP(len + page_offset, PAGE_SIZE); >> + > Don't we miss the first page for offset > PAGE_SIZE? > I'd rather check for all pages from 'page' up to (offset + len), just > to be on the safe side. We do, I copied the logic from iov_iter_extract_bvec_pages() to be aligned with how skb_splice_from_iter() splits the pages. I don't think we need to check a page we won't send, but I don't mind to be on the safeside. >> + for (k = 0; k < pagecount; k++) >> + if (!sendpage_ok(page + k)) >> + return false; >> + >> + 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, > > Cheers, > > Hannes
diff --git a/include/linux/net.h b/include/linux/net.h index 688320b79fcc..b33bdc3e2031 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -322,6 +322,26 @@ 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) +{ + unsigned int pagecount; + size_t page_offset; + int k; + + page = page + offset / PAGE_SIZE; + page_offset = offset % PAGE_SIZE; + pagecount = DIV_ROUND_UP(len + page_offset, PAGE_SIZE); + + for (k = 0; k < pagecount; k++) + if (!sendpage_ok(page + k)) + return false; + + 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,
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. Signed-off-by: Ofir Gal <ofir.gal@volumez.com> --- include/linux/net.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)