[RFC mm v5 1/2] page_pool: check nmdesc->pp to see its usage as page pool for net_iov not page-backed

From: Byungchul Park

Date: Mon Nov 03 2025 - 02:53:40 EST


Currently, the condition 'page->pp_magic == PP_SIGNATURE' is used to
determine if a page belongs to a page pool. However, with the planned
removal of ->pp_magic, we will instead leverage the page_type in struct
page, such as PGTY_netpp, for this purpose.

That works for page-backed network memory. However, for net_iov not
page-backed, the identification cannot be based on the page_type.
Instead, nmdesc->pp can be used to see if it belongs to a page pool, by
making sure nmdesc->pp is NULL otherwise.

For net_iov not page-backed, initialize it using nmdesc->pp = NULL in
net_devmem_bind_dmabuf() and using kvmalloc_array(__GFP_ZERO) in
io_zcrx_create_area() so that netmem_is_pp() can check if nmdesc->pp is
!NULL to confirm its usage as page pool.

Signed-off-by: Byungchul Park <byungchul@xxxxxx>
Reviewed-by: Mina Almasry <almasrymina@xxxxxxxxxx>
---
net/core/devmem.c | 1 +
net/core/netmem_priv.h | 8 ++++++++
net/core/page_pool.c | 16 ++++++++++++++--
3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/net/core/devmem.c b/net/core/devmem.c
index d9de31a6cc7f..f81b700f1fd1 100644
--- a/net/core/devmem.c
+++ b/net/core/devmem.c
@@ -291,6 +291,7 @@ net_devmem_bind_dmabuf(struct net_device *dev,
niov = &owner->area.niovs[i];
niov->type = NET_IOV_DMABUF;
niov->owner = &owner->area;
+ niov->desc.pp = NULL;
page_pool_set_dma_addr_netmem(net_iov_to_netmem(niov),
net_devmem_get_dma_addr(niov));
if (direction == DMA_TO_DEVICE)
diff --git a/net/core/netmem_priv.h b/net/core/netmem_priv.h
index 23175cb2bd86..5561fd556bc5 100644
--- a/net/core/netmem_priv.h
+++ b/net/core/netmem_priv.h
@@ -22,6 +22,14 @@ static inline void netmem_clear_pp_magic(netmem_ref netmem)

static inline bool netmem_is_pp(netmem_ref netmem)
{
+ /* net_iov may be part of a page pool. For net_iov, ->pp in
+ * net_iov.desc can be used to determine if the pages belong to
+ * a page pool. Ensure that the ->pp either points to its page
+ * pool or is set to NULL if it does not.
+ */
+ if (netmem_is_net_iov(netmem))
+ return !!netmem_to_nmdesc(netmem)->pp;
+
return (netmem_get_pp_magic(netmem) & PP_MAGIC_MASK) == PP_SIGNATURE;
}

diff --git a/net/core/page_pool.c b/net/core/page_pool.c
index 1a5edec485f1..2756b78754b0 100644
--- a/net/core/page_pool.c
+++ b/net/core/page_pool.c
@@ -699,7 +699,13 @@ s32 page_pool_inflight(const struct page_pool *pool, bool strict)
void page_pool_set_pp_info(struct page_pool *pool, netmem_ref netmem)
{
netmem_set_pp(netmem, pool);
- netmem_or_pp_magic(netmem, PP_SIGNATURE);
+
+ /* For page-backed, pp_magic is used to identify if it's pp.
+ * For net_iov, it's ensured nmdesc->pp is non-NULL if it's pp
+ * and nmdesc->pp is NULL if it's not.
+ */
+ if (!netmem_is_net_iov(netmem))
+ netmem_or_pp_magic(netmem, PP_SIGNATURE);

/* Ensuring all pages have been split into one fragment initially:
* page_pool_set_pp_info() is only called once for every page when it
@@ -714,7 +720,13 @@ void page_pool_set_pp_info(struct page_pool *pool, netmem_ref netmem)

void page_pool_clear_pp_info(netmem_ref netmem)
{
- netmem_clear_pp_magic(netmem);
+ /* For page-backed, pp_magic is used to identify if it's pp.
+ * For net_iov, it's ensured nmdesc->pp is non-NULL if it's pp
+ * and nmdesc->pp is NULL if it's not.
+ */
+ if (!netmem_is_net_iov(netmem))
+ netmem_clear_pp_magic(netmem);
+
netmem_set_pp(netmem, NULL);
}

--
2.17.1