All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Longjun Tang" <lange_tang@163.com>
Cc: virtualization@lists.linux.dev,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH 3/3] virtio_net: add rx_timeouts per-queue statistic
Date: Tue, 10 Nov 2026 09:43:54 +0000	[thread overview]
Message-ID: <sashiko-outbox-206799@kernel.org> (raw)
In-Reply-To: <20261109094310.103979-4-lange_tang@163.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] virtio_net: data race and lost rx_timeouts events via
  rq->watchdog.stalled
- [Medium] virtio_net: race between virtnet_rx_watchdog() and RX queue
  pause/reset
--

commit 4a62fe0fe638e28583b6ebe514a0626f687513ee
Author: Longjun Tang <tanglongjun@kylinos.cn>

virtio_net: add rx_timeouts per-queue statistic

This commit adds an rx_timeouts per-queue RX statistic exposed via ethtool
that is incremented in virtnet_receive() when rq->watchdog.stalled is set.

> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index ec7c248080c57..feb6bfbb1c5a8 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c

[ ... ]

> @@ -2983,6 +2985,12 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
>  		u64_stats_add(item, u64_stats_read(src));
>  	}
>  
> +	/* Count a stall recovered by this poll. */
> +	if (rq->watchdog.stalled) {
> +		u64_stats_inc(&rq->stats.rx_timeouts);
> +		rq->watchdog.stalled = false;
> +	}
> +
>  	u64_stats_add(&rq->stats.packets, u64_stats_read(&stats.packets));
>  	u64_stats_add(&rq->stats.bytes, u64_stats_read(&stats.bytes));
>  	u64_stats_add(&rq->stats.alloc_fail, u64_stats_read(&stats.alloc_fail));

[Severity: Medium]
Does passing timeout events through the plain boolean rq->watchdog.stalled
race with virtnet_rx_watchdog() and lose rx_timeouts increments?

CPU0 (timer softirq)              CPU1 (NAPI poll)
virtnet_rx_watchdog()             virtnet_receive()
                                    if (rq->watchdog.stalled)
                                      u64_stats_inc(&rq->stats.rx_timeouts)
  rq->watchdog.stalled = true;
                                      rq->watchdog.stalled = false;
                                        <-- data race / lost timeout

Because virtnet_rx_watchdog() writes rq->watchdog.stalled = true on each
timeout and virtnet_receive() reads and clears it without atomic operations,
concurrent execution triggers a KCSAN data race and can clobber a newly
detected stall.  Counting in virtnet_receive() also leaves rx_timeouts at 0
while NAPI remains wedged, collapses multiple watchdog expirations before a
poll into a single increment, loses the count if the device is reopened via
virtnet_rx_watchdog_init_queue() before NAPI runs, and clears stalled even
when virtnet_poll() is called with budget == 0 (such as via netpoll) without
draining packets.

[Severity: Medium]
Can virtnet_rx_watchdog() also race with RX queue pause, resize, and reset?

CPU0                              CPU1 (timer softirq)
virtnet_rx_resize()               virtnet_rx_watchdog()
  virtnet_rx_pause(vi, rq)
  virtqueue_resize(rq->vq, ...)
    virtqueue_resize_split()
      vring_free(&vq->vq)
                                    virtqueue_poll(rq->vq, last_used)
                                      <-- use-after-free / OOB read
      virtqueue_vring_attach_split()

commit "virtio_net: introduce an RX queue watchdog for stuck detection"
starts vi->rx_watchdog in virtnet_open() and only stops it in
virtnet_close(), while virtnet_rx_pause() only disables rq->napi and cancels
rq->dim:

drivers/net/virtio_net.c:virtnet_rx_pause() {
	bool running = netif_running(vi->dev);

	if (running) {
		virtnet_napi_disable(rq);
		virtnet_cancel_dim(vi, &rq->dim);
	}
}

When virtnet_rx_resize() or virtnet_rq_bind_xsk_pool() pauses a queue to
resize or reset rq->vq, virtnet_rx_watchdog() continues polling rq->vq every
second and can read freed vring memory or index past a newly shrunk packed
descriptor ring, or call virtqueue_napi_schedule() while rq->vq is being
reset.  Because neither path reinitializes rq->watchdog after resetting
vq->last_used_idx, any rq->watchdog.stalled state left from before the
reset is also consumed by virtnet_receive() on resume and falsely increments
rq->stats.rx_timeouts.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261109094310.103979-1-lange_tang@163.com?part=3

  reply	other threads:[~2026-11-10  9:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09  9:43 [PATCH 0/3] virtio_net: introduce an RX queue watchdog for stuck detection Longjun Tang
2026-11-09  9:43 ` [PATCH 1/3] virtio: add virtqueue_get_last_used_idx() helper Longjun Tang
2026-11-10  9:43   ` sashiko-bot
2026-11-12 16:51   ` Jakub Kicinski
2026-11-12 22:50   ` Michael S. Tsirkin
2026-11-09  9:43 ` [PATCH 2/3] virtio_net: introduce an RX queue watchdog for stuck detection Longjun Tang
2026-11-10  9:43   ` sashiko-bot
2026-11-12 16:53   ` Jakub Kicinski
2026-11-12 22:51   ` Michael S. Tsirkin
2026-11-09  9:43 ` [PATCH 3/3] virtio_net: add rx_timeouts per-queue statistic Longjun Tang
2026-11-10  9:43   ` sashiko-bot [this message]
2026-11-12 22:52   ` Michael S. Tsirkin

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=sashiko-outbox-206799@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=eperezma@redhat.com \
    --cc=lange_tang@163.com \
    --cc=mst@redhat.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=virtualization@lists.linux.dev \
    /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.