Skip to content

Commit 3ffd05c

Browse files
fengidrigregkh
authored andcommitted
virtio_net: fix missing dma unmap for resize
[ Upstream commit 2311e06 ] For rq, we have three cases getting buffers from virtio core: 1. virtqueue_get_buf{,_ctx} 2. virtqueue_detach_unused_buf 3. callback for virtqueue_resize But in commit 295525e("virtio_net: merge dma operations when filling mergeable buffers"), I missed the dma unmap for the #3 case. That will leak some memory, because I did not release the pages referred by the unused buffers. If we do such script, we will make the system OOM. while true do ethtool -G ens4 rx 128 ethtool -G ens4 rx 256 free -m done Fixes: 295525e ("virtio_net: merge dma operations when filling mergeable buffers") Signed-off-by: Xuan Zhuo <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent e2e5c2a commit 3ffd05c

File tree

1 file changed

+30
-30
lines changed

1 file changed

+30
-30
lines changed

drivers/net/virtio_net.c

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@ struct virtio_net_common_hdr {
334334
};
335335
};
336336

337-
static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf);
338337
static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
339338

340339
static bool is_xdp_frame(void *ptr)
@@ -408,6 +407,17 @@ static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask)
408407
return p;
409408
}
410409

410+
static void virtnet_rq_free_buf(struct virtnet_info *vi,
411+
struct receive_queue *rq, void *buf)
412+
{
413+
if (vi->mergeable_rx_bufs)
414+
put_page(virt_to_head_page(buf));
415+
else if (vi->big_packets)
416+
give_pages(rq, buf);
417+
else
418+
put_page(virt_to_head_page(buf));
419+
}
420+
411421
static void enable_delayed_refill(struct virtnet_info *vi)
412422
{
413423
spin_lock_bh(&vi->refill_lock);
@@ -634,17 +644,6 @@ static void *virtnet_rq_get_buf(struct receive_queue *rq, u32 *len, void **ctx)
634644
return buf;
635645
}
636646

637-
static void *virtnet_rq_detach_unused_buf(struct receive_queue *rq)
638-
{
639-
void *buf;
640-
641-
buf = virtqueue_detach_unused_buf(rq->vq);
642-
if (buf && rq->do_dma)
643-
virtnet_rq_unmap(rq, buf, 0);
644-
645-
return buf;
646-
}
647-
648647
static void virtnet_rq_init_one_sg(struct receive_queue *rq, void *buf, u32 len)
649648
{
650649
struct virtnet_rq_dma *dma;
@@ -744,6 +743,20 @@ static void virtnet_rq_set_premapped(struct virtnet_info *vi)
744743
}
745744
}
746745

746+
static void virtnet_rq_unmap_free_buf(struct virtqueue *vq, void *buf)
747+
{
748+
struct virtnet_info *vi = vq->vdev->priv;
749+
struct receive_queue *rq;
750+
int i = vq2rxq(vq);
751+
752+
rq = &vi->rq[i];
753+
754+
if (rq->do_dma)
755+
virtnet_rq_unmap(rq, buf, 0);
756+
757+
virtnet_rq_free_buf(vi, rq, buf);
758+
}
759+
747760
static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
748761
{
749762
unsigned int len;
@@ -1764,7 +1777,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
17641777
if (unlikely(len < vi->hdr_len + ETH_HLEN)) {
17651778
pr_debug("%s: short packet %i\n", dev->name, len);
17661779
DEV_STATS_INC(dev, rx_length_errors);
1767-
virtnet_rq_free_unused_buf(rq->vq, buf);
1780+
virtnet_rq_free_buf(vi, rq, buf);
17681781
return;
17691782
}
17701783

@@ -2392,7 +2405,7 @@ static int virtnet_rx_resize(struct virtnet_info *vi,
23922405
if (running)
23932406
napi_disable(&rq->napi);
23942407

2395-
err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_free_unused_buf);
2408+
err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf);
23962409
if (err)
23972410
netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: %d\n", qindex, err);
23982411

@@ -4031,19 +4044,6 @@ static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
40314044
xdp_return_frame(ptr_to_xdp(buf));
40324045
}
40334046

4034-
static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf)
4035-
{
4036-
struct virtnet_info *vi = vq->vdev->priv;
4037-
int i = vq2rxq(vq);
4038-
4039-
if (vi->mergeable_rx_bufs)
4040-
put_page(virt_to_head_page(buf));
4041-
else if (vi->big_packets)
4042-
give_pages(&vi->rq[i], buf);
4043-
else
4044-
put_page(virt_to_head_page(buf));
4045-
}
4046-
40474047
static void free_unused_bufs(struct virtnet_info *vi)
40484048
{
40494049
void *buf;
@@ -4057,10 +4057,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
40574057
}
40584058

40594059
for (i = 0; i < vi->max_queue_pairs; i++) {
4060-
struct receive_queue *rq = &vi->rq[i];
4060+
struct virtqueue *vq = vi->rq[i].vq;
40614061

4062-
while ((buf = virtnet_rq_detach_unused_buf(rq)) != NULL)
4063-
virtnet_rq_free_unused_buf(rq->vq, buf);
4062+
while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
4063+
virtnet_rq_unmap_free_buf(vq, buf);
40644064
cond_resched();
40654065
}
40664066
}

0 commit comments

Comments
 (0)