> Once tcp_zerocopy_receive() maps an order-0 RX fragment page into a
> userspace VMA via vm_insert_pages(), vm_insert_pages() increments
> page->_refcount, which prevents the page from being recycled back into
> its page_pool when the RX SKB is freed. However, while the RX SKB still
> holds its fragment reference, the page remains marked as a page_pool
> page (page_pool_page_is_pp(page) == true) inside the userspace VMA, so
> subsequent GUP callers such as sendmsg(MSG_ZEROCOPY) or vmsplice() can
> encounter a page_pool page while holding only a raw struct page
> reference.
> 
> Establish the invariant that pp_ref_count is only incremented by callers
> that already hold an active pp_ref_count (>= 1) on that netmem, and a
> raw page_ref_count is never converted into a pp_ref_count:
> - In can_map_frag(), require !skb_cloned(skb), page_pool_ref_count == 1,
>   and page_ref_count == 1 for page_pool pages so the fragment being
>   mapped holds the sole reference to the page; cloned SKBs or page_pool
>   pages with additional references (including drivers holding an
>   undrained fragment bias) fall back to copying.
> - In tcp_zerocopy_receive(), convert the fragment's sole pp_ref_count
>   into a regular page reference and detach the page from its page_pool
>   via get_page(page) + napi_pp_put_page(page_to_netmem(page)) before
>   queueing the page for vm_insert_pages(). If vm_insert_pages()
>   subsequently fails, the detached page remains referenced by the RX SKB
>   via its regular page reference and is freed back to the page allocator
>   when the SKB is consumed.
> 
> Signed-off-by: Mina Almasry <[email protected]>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review ยท 
https://sashiko.dev/#/patchset/[email protected]?part=3


Reply via email to