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 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.