From: sashiko-bot@kernel.org
To: "Joonho Lee" <mynameisjune111@gmail.com>, linux-sound@vger.kernel.org
Cc: virtualization@lists.linux.dev,
"Michael S. Tsirkin" <mst@redhat.com>,
"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH v2 2/2] ALSA: virtio-snd: fix dsnoop capture with staged buffers
Date: Sun, 25 Oct 2026 05:36:37 +0000 [thread overview]
Message-ID: <sashiko-outbox-184086@kernel.org> (raw)
In-Reply-To: <20261025051301.54640-3-mynameisjune111@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ALSA: virtio-snd: unlatched XRUN in virtsnd_pcm_trigger() on pause release
--
commit 84dba89c8170c6b6702f2442748d799772bffa04
Author: Joonho Lee <mynameisjune111@gmail.com>
ALSA: virtio-snd: fix dsnoop capture with staged buffers
This commit adds free-running staged-capture policy handling when
stop_threshold equals boundary so dsnoop capture streams do not fail with
ring_capacity rejections. It also reconstructs unread ring occupancy when
returning from free-running to bounded capture mode and returns -EPIPE if
outstanding unacknowledged data already fills the ring.
> diff --git a/sound/virtio/virtio_pcm_msg.c b/sound/virtio/virtio_pcm_msg.c
> index 663f7695b5be8..e7258bce2e6f0 100644
> --- a/sound/virtio/virtio_pcm_msg.c
> +++ b/sound/virtio/virtio_pcm_msg.c
[ ... ]
> +/* Caller holds vss->lock. */
> +int virtsnd_pcm_capture_refresh_mode_locked(struct virtio_pcm_substream *vss,
> + bool *free_running)
> +{
> + struct snd_pcm_runtime *runtime;
> + snd_pcm_uframes_t stop_threshold;
> + u64 outstanding;
> + bool new_free_running;
> +
> + if (!vss->capture_staging || !vss->runtime_active || !vss->substream)
> + return -EBADFD;
> +
> + runtime = vss->substream->runtime;
> + if (!runtime || !vss->buffer_bytes || !vss->capture_boundary)
> + return -EBADFD;
> +
> + /* Validate the currently committed policy before observing a transition. */
> + if (!virtsnd_pcm_capture_counters_valid(vss))
> + return -EIO;
> +
> + stop_threshold = READ_ONCE(runtime->stop_threshold);
> + new_free_running = stop_threshold == vss->capture_boundary;
> + if (new_free_running != vss->capture_free_running) {
> + outstanding = vss->capture_copied_total -
> + vss->capture_acked_total;
> + if (new_free_running) {
> + vss->capture_ready = 0;
> + } else {
> + if (outstanding >= vss->buffer_bytes)
> + return -EPIPE;
> + vss->capture_ready = outstanding;
> + }
> + vss->capture_free_running = new_free_running;
> + }
> +
> + *free_running = new_free_running;
> + return 0;
> +}
[ ... ]
> +int virtsnd_pcm_capture_send(struct virtio_pcm_substream *vss)
> +{
> + bool free_running;
> + int rc;
> +
> + rc = virtsnd_pcm_capture_refresh_mode_locked(vss, &free_running);
> + if (rc)
> + return rc;
> +
> + return virtsnd_pcm_capture_enqueue(vss, free_running);
> +}
[Severity: Medium]
Can a staged capture substream get stuck in SNDRV_PCM_STATE_PAUSED with
vss->stopped = true and vss->xfer_xrun = false when
virtsnd_pcm_capture_refresh_mode_locked() returns -EPIPE during pause
release?
Suppose a staged capture stream (with virtsnd_capture_pause_restart=false)
runs in free-running mode until capture_copied_total - capture_acked_total >=
vss->buffer_bytes, is paused via SNDRV_PCM_IOCTL_PAUSE(1), and then has
stop_threshold updated below boundary via snd_pcm_sw_params(). Because the
substream is in SNDRV_PCM_STATE_PAUSED, snd_pcm_running(substream) is false
and snd_pcm_sw_params() skips snd_pcm_update_state().
When the stream is subsequently resumed via SNDRV_PCM_IOCTL_PAUSE(0),
snd_pcm_do_pause() calls virtsnd_pcm_trigger(substream,
SNDRV_PCM_TRIGGER_PAUSE_RELEASE), which calls virtsnd_pcm_capture_send() ->
virtsnd_pcm_capture_refresh_mode_locked() and receives -EPIPE:
sound/virtio/virtio_pcm_ops.c:virtsnd_pcm_trigger() {
...
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
...
if (vss->direction == SNDRV_PCM_STREAM_CAPTURE) {
if (vss->capture_staging) {
if (!vss->runtime_active)
rc = -EBADFD;
else
rc = virtsnd_pcm_capture_send(vss);
} else {
rc = virtsnd_pcm_msg_send(vss, 0,
vss->buffer_bytes);
}
}
if (rc) {
vss->stopped = true;
substream->runtime->stop_operating = true;
return rc;
}
}
Unlike snd_pcm_do_start(), snd_pcm_do_pause() does not transition
runtime->state to SNDRV_PCM_STATE_XRUN on -EPIPE; snd_pcm_action_single()
invokes snd_pcm_undo_pause() and leaves runtime->state in
SNDRV_PCM_STATE_PAUSED.
In sound/virtio/virtio_pcm.c:virtsnd_pcm_period_elapsed(), transitioning a
paused staged-capture stream to SNDRV_PCM_STATE_XRUN relies on vss->xfer_xrun
being latched and vss->elapsed_period being scheduled:
sound/virtio/virtio_pcm.c:virtsnd_pcm_period_elapsed() {
...
if (!snd_pcm_running(substream)) {
scoped_guard(spinlock_irqsave, &vss->lock) {
runtime = substream->runtime;
paused_xrun = runtime &&
runtime->state == SNDRV_PCM_STATE_PAUSED &&
vss->runtime_active && vss->xfer_xrun;
}
if (paused_xrun) {
/* Wake readers without sending STOP for a paused stream. */
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
}
return;
}
}
Because virtsnd_pcm_trigger() sets vss->stopped = true without setting
vss->xfer_xrun = true or scheduling vss->elapsed_period (unlike the
virtsnd_pcm_pause_restart_start() -> virtsnd_pcm_pause_restart_fail() path),
won't any reader blocked in wait_for_avail() remain asleep in
SNDRV_PCM_STATE_PAUSED while subsequent pause-release attempts fail with
-EBADFD?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261025051301.54640-1-mynameisjune111@gmail.com?part=2
prev parent reply other threads:[~2026-10-25 5:36 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-25 5:12 [PATCH v2 0/2] ALSA: virtio-snd: fix dsnoop capture with staged buffers Joonho Lee
2026-10-25 5:13 ` [PATCH v2 1/2] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-10-25 5:18 ` sashiko-bot
2026-10-25 5:13 ` [PATCH v2 2/2] ALSA: virtio-snd: fix dsnoop capture with staged buffers Joonho Lee
2026-10-25 5:36 ` sashiko-bot [this message]
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-184086@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=eperezma@redhat.com \
--cc=linux-sound@vger.kernel.org \
--cc=mst@redhat.com \
--cc=mynameisjune111@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox