From: "Michael S. Tsirkin" <mst@redhat.com>
To: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Cc: netdev@vger.kernel.org, Jason Wang <jasowang@redhat.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
virtualization@lists.linux-foundation.org
Subject: Re: [PATCH v1] virtio_net: fix missing dma unmap for resize
Date: Tue, 12 Dec 2023 03:26:41 -0500 [thread overview]
Message-ID: <20231212032514-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20231212081141.39757-1-xuanzhuo@linux.alibaba.com>
On Tue, Dec 12, 2023 at 04:11:41PM +0800, Xuan Zhuo wrote:
> 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 295525e29a5b("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: 295525e29a5b ("virtio_net: merge dma operations when filling mergeable buffers")
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>
> v1: rename to virtnet_rq_free_buf_check_dma()
The fact that we check does not matter what matters is
that we unmap. I'd change the name to reflect that.
>
> drivers/net/virtio_net.c | 60 ++++++++++++++++++++--------------------
> 1 file changed, 30 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index d16f592c2061..58ebbffeb952 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -334,7 +334,6 @@ struct virtio_net_common_hdr {
> };
> };
>
> -static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf);
> static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
>
> 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)
> return p;
> }
>
> +static void virtnet_rq_free_buf(struct virtnet_info *vi,
> + struct receive_queue *rq, void *buf)
> +{
> + if (vi->mergeable_rx_bufs)
> + put_page(virt_to_head_page(buf));
> + else if (vi->big_packets)
> + give_pages(rq, buf);
> + else
> + put_page(virt_to_head_page(buf));
> +}
> +
> static void enable_delayed_refill(struct virtnet_info *vi)
> {
> spin_lock_bh(&vi->refill_lock);
> @@ -634,17 +644,6 @@ static void *virtnet_rq_get_buf(struct receive_queue *rq, u32 *len, void **ctx)
> return buf;
> }
>
> -static void *virtnet_rq_detach_unused_buf(struct receive_queue *rq)
> -{
> - void *buf;
> -
> - buf = virtqueue_detach_unused_buf(rq->vq);
> - if (buf && rq->do_dma)
> - virtnet_rq_unmap(rq, buf, 0);
> -
> - return buf;
> -}
> -
> static void virtnet_rq_init_one_sg(struct receive_queue *rq, void *buf, u32 len)
> {
> struct virtnet_rq_dma *dma;
> @@ -744,6 +743,20 @@ static void virtnet_rq_set_premapped(struct virtnet_info *vi)
> }
> }
>
> +static void virtnet_rq_free_buf_check_dma(struct virtqueue *vq, void *buf)
> +{
> + struct virtnet_info *vi = vq->vdev->priv;
> + struct receive_queue *rq;
> + int i = vq2rxq(vq);
> +
> + rq = &vi->rq[i];
> +
> + if (rq->do_dma)
> + virtnet_rq_unmap(rq, buf, 0);
> +
> + virtnet_rq_free_buf(vi, rq, buf);
> +}
> +
> static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
> {
> unsigned int len;
> @@ -1764,7 +1777,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
> if (unlikely(len < vi->hdr_len + ETH_HLEN)) {
> pr_debug("%s: short packet %i\n", dev->name, len);
> DEV_STATS_INC(dev, rx_length_errors);
> - virtnet_rq_free_unused_buf(rq->vq, buf);
> + virtnet_rq_free_buf(vi, rq, buf);
> return;
> }
>
> @@ -2392,7 +2405,7 @@ static int virtnet_rx_resize(struct virtnet_info *vi,
> if (running)
> napi_disable(&rq->napi);
>
> - err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_free_unused_buf);
> + err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_free_buf_check_dma);
> if (err)
> netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: %d\n", qindex, err);
>
> @@ -4031,19 +4044,6 @@ static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
> xdp_return_frame(ptr_to_xdp(buf));
> }
>
> -static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf)
> -{
> - struct virtnet_info *vi = vq->vdev->priv;
> - int i = vq2rxq(vq);
> -
> - if (vi->mergeable_rx_bufs)
> - put_page(virt_to_head_page(buf));
> - else if (vi->big_packets)
> - give_pages(&vi->rq[i], buf);
> - else
> - put_page(virt_to_head_page(buf));
> -}
> -
> static void free_unused_bufs(struct virtnet_info *vi)
> {
> void *buf;
> @@ -4057,10 +4057,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
> }
>
> for (i = 0; i < vi->max_queue_pairs; i++) {
> - struct receive_queue *rq = &vi->rq[i];
> + struct virtqueue *vq = vi->rq[i].vq;
>
> - while ((buf = virtnet_rq_detach_unused_buf(rq)) != NULL)
> - virtnet_rq_free_unused_buf(rq->vq, buf);
> + while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
> + virtnet_rq_free_buf_check_dma(vq, buf);
> cond_resched();
> }
> }
> --
> 2.32.0.3.g01195cf9f
next prev parent reply other threads:[~2023-12-12 8:26 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-12 8:11 [PATCH v1] virtio_net: fix missing dma unmap for resize Xuan Zhuo
2023-12-12 8:26 ` Michael S. Tsirkin [this message]
2023-12-26 5:57 ` Xuan Zhuo
2023-12-26 8:57 ` Michael S. Tsirkin
2023-12-26 8:59 ` Xuan Zhuo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231212032514-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jasowang@redhat.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=virtualization@lists.linux-foundation.org \
--cc=xuanzhuo@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.