net: skbuff: add napi_pp_get_page() and use it in tcp_recvmsg_dmabuf()

While napi_pp_put_page() releases a page_pool pp_ref_count reference on
a netmem, no symmetric helper existed to acquire one, forcing callers
like tcp_recvmsg_dmabuf() to open-code atomic_long_inc() on
niov->desc.pp_ref_count.

Add napi_pp_get_page() to pair symmetrically with napi_pp_put_page(),
and use WARN_ON_ONCE(!napi_pp_get_page(netmem)) in tcp_recvmsg_dmabuf()
to match WARN_ON_ONCE(!napi_pp_put_page(netmem)) in
tcp_release_user_frags().

Assisted-by: LLM
Signed-off-by: Mina Almasry <almasrymina@google.com>
Link: https://patch.msgid.link/20261014173945.373295-3-almasrymina@google.com
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Mina Almasry 2026-10-14 17:37:16 +00:00 committed by Paolo Abeni
parent a868720467
commit 729a47b803
3 changed files with 37 additions and 2 deletions

View File

@ -9,6 +9,8 @@
#include <linux/skbuff.h>
bool napi_pp_get_page(netmem_ref netmem);
/**
* __skb_frag_ref - take an addition reference on a paged fragment.
* @frag: the paged fragment

View File

@ -1026,6 +1026,15 @@ int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
EXPORT_SYMBOL(skb_cow_data_for_xdp);
#if IS_ENABLED(CONFIG_PAGE_POOL)
/**
* napi_pp_put_page - release a page_pool reference on a netmem
* @netmem: netmem to unreference
*
* Drops a page_pool reference (pp_ref_count) on @netmem if it belongs to a
* page_pool. Counterpart to napi_pp_get_page().
*
* Return: true if @netmem belongs to a page_pool, false otherwise.
*/
bool napi_pp_put_page(netmem_ref netmem)
{
netmem = netmem_compound_head(netmem);
@ -1038,6 +1047,28 @@ bool napi_pp_put_page(netmem_ref netmem)
return true;
}
EXPORT_SYMBOL(napi_pp_put_page);
/**
* napi_pp_get_page - acquire a page_pool reference on a netmem
* @netmem: netmem to reference
*
* Acquires a page_pool reference (pp_ref_count) on @netmem if it belongs to a
* page_pool. Counterpart to napi_pp_put_page().
*
* Return: true if @netmem belongs to a page_pool, false otherwise.
*/
bool napi_pp_get_page(netmem_ref netmem)
{
netmem = netmem_compound_head(netmem);
if (unlikely(!netmem_is_pp(netmem)))
return false;
page_pool_ref_netmem(netmem);
return true;
}
EXPORT_SYMBOL(napi_pp_get_page);
#endif
static bool skb_pp_recycle(struct sk_buff *skb, void *data)

View File

@ -254,6 +254,7 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/skbuff.h>
#include <linux/skbuff_ref.h>
#include <linux/splice.h>
#include <linux/net.h>
#include <linux/socket.h>
@ -2559,6 +2560,7 @@ static int tcp_recvmsg_dmabuf(struct sock *sk, const struct sk_buff *skb,
*/
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
netmem_ref netmem = skb_frag_netmem(frag);
struct net_iov *niov;
u64 frag_offset;
int end;
@ -2612,8 +2614,8 @@ static int tcp_recvmsg_dmabuf(struct sock *sk, const struct sk_buff *skb,
if (err)
goto out;
atomic_long_inc(&niov->desc.pp_ref_count);
tcp_xa_pool.netmems[tcp_xa_pool.idx++] = skb_frag_netmem(frag);
WARN_ON_ONCE(!napi_pp_get_page(netmem));
tcp_xa_pool.netmems[tcp_xa_pool.idx++] = netmem;
sent += copy;