Skip to content

Commit f12ecf5

Browse files
isilenceaxboe
authored andcommitted
io_uring/zcrx: fix late dma unmap for a dead dev
There is a problem with page pools not dma-unmapping immediately when the device is going down, and delaying it until the page pool is destroyed, which is not allowed (see links). That just got fixed for normal page pools, and we need to address memory providers as well. Unmap pages in the memory provider uninstall callback, and protect it with a new lock. There is also a gap between when a dma mapping is created and the mp is installed, so if the device is killed in between, io_uring would be holding on to dma mappings to a dead device with no one to call ->uninstall. Move it to page pool init and rely on ->is_mapped to make sure it's only done once. Link: https://lore.kernel.org/lkml/8067f204-1380-4d37-8ffd-007fc6f26738@kernel.org/T/ Link: https://lore.kernel.org/all/20250409-page-pool-track-dma-v9-0-6a9ef2e0cba8@redhat.com/ Fixes: 34a3e60 ("io_uring/zcrx: implement zerocopy receive pp memory provider") Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/ef9b7db249b14f6e0b570a1bb77ff177389f881c.1744965853.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent b419bed commit f12ecf5

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

io_uring/zcrx.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,21 @@ static void __io_zcrx_unmap_area(struct io_zcrx_ifq *ifq,
5151

5252
static void io_zcrx_unmap_area(struct io_zcrx_ifq *ifq, struct io_zcrx_area *area)
5353
{
54+
guard(mutex)(&ifq->dma_lock);
55+
5456
if (area->is_mapped)
5557
__io_zcrx_unmap_area(ifq, area, area->nia.num_niovs);
58+
area->is_mapped = false;
5659
}
5760

5861
static int io_zcrx_map_area(struct io_zcrx_ifq *ifq, struct io_zcrx_area *area)
5962
{
6063
int i;
6164

65+
guard(mutex)(&ifq->dma_lock);
66+
if (area->is_mapped)
67+
return 0;
68+
6269
for (i = 0; i < area->nia.num_niovs; i++) {
6370
struct net_iov *niov = &area->nia.niovs[i];
6471
dma_addr_t dma;
@@ -280,6 +287,7 @@ static struct io_zcrx_ifq *io_zcrx_ifq_alloc(struct io_ring_ctx *ctx)
280287
ifq->ctx = ctx;
281288
spin_lock_init(&ifq->lock);
282289
spin_lock_init(&ifq->rq_lock);
290+
mutex_init(&ifq->dma_lock);
283291
return ifq;
284292
}
285293

@@ -329,6 +337,7 @@ static void io_zcrx_ifq_free(struct io_zcrx_ifq *ifq)
329337
put_device(ifq->dev);
330338

331339
io_free_rbuf_ring(ifq);
340+
mutex_destroy(&ifq->dma_lock);
332341
kfree(ifq);
333342
}
334343

@@ -400,10 +409,6 @@ int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
400409
goto err;
401410
get_device(ifq->dev);
402411

403-
ret = io_zcrx_map_area(ifq, ifq->area);
404-
if (ret)
405-
goto err;
406-
407412
mp_param.mp_ops = &io_uring_pp_zc_ops;
408413
mp_param.mp_priv = ifq;
409414
ret = net_mp_open_rxq(ifq->netdev, reg.if_rxq, &mp_param);
@@ -624,6 +629,7 @@ static bool io_pp_zc_release_netmem(struct page_pool *pp, netmem_ref netmem)
624629
static int io_pp_zc_init(struct page_pool *pp)
625630
{
626631
struct io_zcrx_ifq *ifq = io_pp_to_ifq(pp);
632+
int ret;
627633

628634
if (WARN_ON_ONCE(!ifq))
629635
return -EINVAL;
@@ -636,6 +642,10 @@ static int io_pp_zc_init(struct page_pool *pp)
636642
if (pp->p.dma_dir != DMA_FROM_DEVICE)
637643
return -EOPNOTSUPP;
638644

645+
ret = io_zcrx_map_area(ifq, ifq->area);
646+
if (ret)
647+
return ret;
648+
639649
percpu_ref_get(&ifq->ctx->refs);
640650
return 0;
641651
}
@@ -671,6 +681,9 @@ static void io_pp_uninstall(void *mp_priv, struct netdev_rx_queue *rxq)
671681
struct io_zcrx_ifq *ifq = mp_priv;
672682

673683
io_zcrx_drop_netdev(ifq);
684+
if (ifq->area)
685+
io_zcrx_unmap_area(ifq, ifq->area);
686+
674687
p->mp_ops = NULL;
675688
p->mp_priv = NULL;
676689
}

io_uring/zcrx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct io_zcrx_ifq {
3838
struct net_device *netdev;
3939
netdevice_tracker netdev_tracker;
4040
spinlock_t lock;
41+
struct mutex dma_lock;
4142
};
4243

4344
#if defined(CONFIG_IO_URING_ZCRX)

0 commit comments

Comments
 (0)