mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 22:02:02 +00:00
iov_iter: optimize page_copy_sane()
commit 6daef95b8c
upstream.
Avoid cache line miss dereferencing struct page if we can.
page_copy_sane() mostly deals with order-0 pages.
Extra cache line miss is visible on TCP recvmsg() calls dealing
with GRO packets (typically 45 page frags are attached to one skb).
Bringing the 45 struct pages into cpu cache while copying the data
is not free, since the freeing of the skb (and associated
page frags put_page()) can happen after cache lines have been evicted.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Cc: Matthew Wilcox <willy@infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
866f011181
commit
627bb2d93b
1 changed files with 15 additions and 2 deletions
|
@ -817,8 +817,21 @@ EXPORT_SYMBOL(_copy_from_iter_full_nocache);
|
|||
|
||||
static inline bool page_copy_sane(struct page *page, size_t offset, size_t n)
|
||||
{
|
||||
struct page *head = compound_head(page);
|
||||
size_t v = n + offset + page_address(page) - page_address(head);
|
||||
struct page *head;
|
||||
size_t v = n + offset;
|
||||
|
||||
/*
|
||||
* The general case needs to access the page order in order
|
||||
* to compute the page size.
|
||||
* However, we mostly deal with order-0 pages and thus can
|
||||
* avoid a possible cache line miss for requests that fit all
|
||||
* page orders.
|
||||
*/
|
||||
if (n <= v && v <= PAGE_SIZE)
|
||||
return true;
|
||||
|
||||
head = compound_head(page);
|
||||
v += (page - head) << PAGE_SHIFT;
|
||||
|
||||
if (likely(n <= v && v <= (PAGE_SIZE << compound_order(head))))
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue