io_uring/zcrx: grab a net device

Zerocopy receive needs a net device to bind to its rx queue and dma map
buffers. As a preparation to following patches, resolve a net device
from the if_idx parameter with no functional changes otherwise.

Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: David Wei <dw@davidwei.uk>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Link: https://lore.kernel.org/r/20250215000947.789731-4-dw@davidwei.uk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Pavel Begunkov 2025-02-14 16:09:38 -08:00 committed by Jens Axboe
parent cf96310c5f
commit 035af94b39
2 changed files with 33 additions and 0 deletions

View file

@ -3,6 +3,8 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/io_uring.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <uapi/linux/io_uring.h>
@ -128,13 +130,28 @@ static struct io_zcrx_ifq *io_zcrx_ifq_alloc(struct io_ring_ctx *ctx)
ifq->if_rxq = -1;
ifq->ctx = ctx;
spin_lock_init(&ifq->lock);
return ifq;
}
static void io_zcrx_drop_netdev(struct io_zcrx_ifq *ifq)
{
spin_lock(&ifq->lock);
if (ifq->netdev) {
netdev_put(ifq->netdev, &ifq->netdev_tracker);
ifq->netdev = NULL;
}
spin_unlock(&ifq->lock);
}
static void io_zcrx_ifq_free(struct io_zcrx_ifq *ifq)
{
io_zcrx_drop_netdev(ifq);
if (ifq->area)
io_zcrx_free_area(ifq->area);
if (ifq->dev)
put_device(ifq->dev);
io_free_rbuf_ring(ifq);
kfree(ifq);
@ -195,6 +212,17 @@ int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
ifq->rq_entries = reg.rq_entries;
ifq->if_rxq = reg.if_rxq;
ret = -ENODEV;
ifq->netdev = netdev_get_by_index(current->nsproxy->net_ns, reg.if_idx,
&ifq->netdev_tracker, GFP_KERNEL);
if (!ifq->netdev)
goto err;
ifq->dev = ifq->netdev->dev.parent;
if (!ifq->dev)
return -EOPNOTSUPP;
get_device(ifq->dev);
reg.offsets.rqes = sizeof(struct io_uring);
reg.offsets.head = offsetof(struct io_uring, head);
reg.offsets.tail = offsetof(struct io_uring, tail);

View file

@ -4,6 +4,7 @@
#include <linux/io_uring_types.h>
#include <net/page_pool/types.h>
#include <net/net_trackers.h>
struct io_zcrx_area {
struct net_iov_area nia;
@ -27,6 +28,10 @@ struct io_zcrx_ifq {
u32 rq_entries;
u32 if_rxq;
struct device *dev;
struct net_device *netdev;
netdevice_tracker netdev_tracker;
spinlock_t lock;
};
#if defined(CONFIG_IO_URING_ZCRX)