Re: [PATCH net-next v2 2/3] net: devmem: embed net_iov_area in binding

From: Mina Almasry

Date: Mon Sep 14 2026 - 17:54:09 EST


On Fri, Sep 11, 2026 at 8:45 AM Stanislav Fomichev <sdf.kernel@xxxxxxxxx> wrote:
>
> After replacing the gen_pool with a binding-level freelist, devmem no
> longer needs a separate chunk owner object. There is only one
> net_iov_area for the binding, so store it directly in struct
> net_devmem_dmabuf_binding.
>
> Derive the binding from net_iov_owner() with container_of(), matching the
> pattern used by io_uring zcrx. This removes the leftover
> dmabuf_genpool_chunk_owner wrapper and its allocation/free path.
>
> Signed-off-by: Stanislav Fomichev <sdf@xxxxxxxxxxx>
> ---
> net/core/devmem.c | 41 ++++++++++-------------------------------
> net/core/devmem.h | 26 +++++++-------------------
> 2 files changed, 17 insertions(+), 50 deletions(-)
>
> diff --git a/net/core/devmem.c b/net/core/devmem.c
> index 4883eb7f3a95..7949f8425bcd 100644
> --- a/net/core/devmem.c
> +++ b/net/core/devmem.c
> @@ -29,15 +29,6 @@ static DEFINE_XARRAY_FLAGS(net_devmem_dmabuf_bindings, XA_FLAGS_ALLOC1);
>
> static const struct memory_provider_ops dmabuf_devmem_ops;
>
> -static void
> -net_devmem_dmabuf_free_chunk_owner(struct dmabuf_genpool_chunk_owner *owner)
> -{
> - if (owner) {
> - kvfree(owner->area.niovs);
> - kfree(owner);
> - }
> -}
> -
> static void net_devmem_dmabuf_binding_release(struct percpu_ref *ref)
> {
> struct net_devmem_dmabuf_binding *binding =
> @@ -55,7 +46,7 @@ void __net_devmem_dmabuf_binding_free(struct work_struct *wq)
> "can't destroy dmabuf binding. total=%zu, free=%zu",
> binding->total_niovs, binding->free_count);
>
> - net_devmem_dmabuf_free_chunk_owner(binding->chunk_owner);
> + kvfree(binding->area.niovs);
> dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt,
> binding->direction);
> dma_buf_detach(binding->dmabuf, binding->attachment);
> @@ -271,23 +262,14 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
> }
> binding->total_niovs = total_niovs;
>
> - owner = kzalloc_node(sizeof(*owner), GFP_KERNEL,
> - dev_to_node(&dev->dev));
> - if (!owner) {
> + binding->area.num_niovs = total_niovs;
> + binding->area.niovs = kvmalloc_objs(*binding->area.niovs,
> + binding->area.num_niovs);
> + if (!binding->area.niovs) {
> err = -ENOMEM;
> goto err_free_freelist;
> }
>
> - owner->area.num_niovs = total_niovs;
> - owner->binding = binding;
> - owner->area.niovs = kvmalloc_objs(*owner->area.niovs,
> - owner->area.num_niovs);
> - if (!owner->area.niovs) {
> - err = -ENOMEM;
> - goto err_free_owner;
> - }
> - binding->chunk_owner = owner;
> -
> niov_idx = 0;
> for_each_sgtable_dma_sg(binding->sgt, sg, sg_idx) {
> dma_addr_t dma_addr = sg_dma_address(sg);
> @@ -296,8 +278,8 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
> size_t nr_niovs = len >> niov_shift;
>
> for (i = 0; i < nr_niovs; i++, niov_idx++) {
> - niov = &owner->area.niovs[niov_idx];
> - net_iov_init(niov, &owner->area, NET_IOV_DMABUF);
> + niov = &binding->area.niovs[niov_idx];
> + net_iov_init(niov, &binding->area, NET_IOV_DMABUF);
> page_pool_set_dma_addr_netmem(net_iov_to_netmem(niov),
> dma_addr);
> if (direction == DMA_TO_DEVICE)
> @@ -311,17 +293,14 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
> binding, xa_limit_32b, &id_alloc_next,
> GFP_KERNEL);
> if (err < 0)
> - goto err_free_chunk_owner;
> + goto err_free_niovs;
>
> list_add(&binding->list, &priv->bindings);
>
> return binding;
>
> -err_free_chunk_owner:
> - net_devmem_dmabuf_free_chunk_owner(binding->chunk_owner);
> - goto err_free_freelist;
> -err_free_owner:
> - kfree(owner);
> +err_free_niovs:
> + kvfree(binding->area.niovs);
> err_free_freelist:
> kvfree(binding->freelist);
> err_tx_vec:
> diff --git a/net/core/devmem.h b/net/core/devmem.h
> index a5ee2d8d9169..20a3eb90ea7f 100644
> --- a/net/core/devmem.h
> +++ b/net/core/devmem.h
> @@ -14,9 +14,9 @@
> #include <net/netdev_netlink.h>
>
> struct netlink_ext_ack;
> -struct dmabuf_genpool_chunk_owner;
>
> struct net_devmem_dmabuf_binding {
> + struct net_iov_area area;
> struct dma_buf *dmabuf;
> struct dma_buf_attachment *attachment;
> struct sg_table *sgt;
> @@ -27,7 +27,6 @@ struct net_devmem_dmabuf_binding {
> * dereferenced.
> */
> void *vdev;
> - struct dmabuf_genpool_chunk_owner *chunk_owner;
> /* Protect dev */
> struct mutex lock;
>
> @@ -83,11 +82,6 @@ struct net_devmem_dmabuf_binding {
> };
>
> #if defined(CONFIG_NET_DEVMEM)
> -struct dmabuf_genpool_chunk_owner {
> - struct net_iov_area area;
> - struct net_devmem_dmabuf_binding *binding;
> -};
> -
> void __net_devmem_dmabuf_binding_free(struct work_struct *wq);
> struct net_devmem_dmabuf_binding *
> net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
> @@ -102,18 +96,12 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
> struct net_devmem_dmabuf_binding *binding,
> struct netlink_ext_ack *extack);
>
> -static inline struct dmabuf_genpool_chunk_owner *
> -net_devmem_iov_to_chunk_owner(const struct net_iov *niov)
> -{
> - struct net_iov_area *owner = net_iov_owner(niov);
> -
> - return container_of(owner, struct dmabuf_genpool_chunk_owner, area);
> -}
> -
> static inline struct net_devmem_dmabuf_binding *
> net_devmem_iov_binding(const struct net_iov *niov)
> {
> - return net_devmem_iov_to_chunk_owner(niov)->binding;
> + struct net_iov_area *owner = net_iov_owner(niov);
> +

Not worth a local var anymore tbh.

Reviewed-by: Mina Almasry <almasrymina@xxxxxxxxxx>



--
Thanks,
Mina