Linux Sound subsystem development
 help / color / mirror / Atom feed
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 v5 11/11] ALSA: virtio-snd: fix dsnoop capture with staged buffers
Date: Wed, 28 Oct 2026 00:13:37 +0000	[thread overview]
Message-ID: <sashiko-outbox-187263@kernel.org> (raw)
In-Reply-To: <20261027234334.32551-12-mynameisjune111@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ALSA: virtio-snd: un-armed paused stop on read XRUN in virtsnd_pcm_cp_ack()
--

commit ceb71ae8baa14854bd1fb36ae47981ac52e944e5
Author: Joonho Lee <mynameisjune111@gmail.com>

ALSA: virtio-snd: fix dsnoop capture with staged buffers

This commit adds free-running capture mode support for staged capture buffers
when stop_threshold equals the boundary, allowing dsnoop clients to consume
the mmap ring without triggering capacity rejections. It also handles transitions
back to bounded capture and arms synchronous stop on paused XRUN paths.

> 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
[ ... ]
> @@ -508,24 +511,54 @@ int virtsnd_pcm_msg_send(struct virtio_pcm_substream *vss, unsigned long offset,
>  	return 0;
>  }
>  
[ ... ]
> +/* 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;
> +}
[ ... ]
> diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
> index d50924b792f65..cbf4e479d295f 100644
> --- a/sound/virtio/virtio_pcm_ops.c
> +++ b/sound/virtio/virtio_pcm_ops.c
[ ... ]
> @@ -1314,8 +1348,14 @@ static int virtsnd_pcm_cp_ack(struct snd_pcm_substream *substream)
>  	struct virtsnd_pcm_transfer transfer = {};
>  	int rc;
>  
> -	if (vss->capture_staging)
> -		return virtsnd_pcm_capture_staged_ack(vss, runtime);
> +	if (vss->capture_staging) {
> +		rc = virtsnd_pcm_capture_staged_ack(vss, runtime);
> +		if (rc == -EPIPE) {
> +			guard(spinlock_irqsave)(&vss->lock);
> +			virtsnd_pcm_capture_arm_paused_stop(vss);
> +		}
> +		return rc;
> +	}

[Severity: Medium]
Can a paused staged-capture stream still enter SNDRV_PCM_STATE_XRUN during a
partial read without arming vss->stopped and runtime->stop_operating?

If a staged-capture stream is paused in SNDRV_PCM_STATE_PAUSED with unread
frames in the ring (where outstanding < vss->buffer_bytes), and userspace
lowers runtime->stop_threshold via snd_pcm_sw_params() from boundary to a
bounded threshold smaller than the frames that will remain after a partial
read, snd_pcm_sw_params() does not call snd_pcm_update_state() because
snd_pcm_running(substream) is false while paused.

When userspace then performs a partial read through __snd_pcm_lib_xfer() that
leaves remaining avail >= runtime->stop_threshold:

  __snd_pcm_lib_xfer()
    pcm_lib_apply_appl_ptr()
      virtsnd_pcm_cp_ack()
        virtsnd_pcm_capture_staged_ack()
          virtsnd_pcm_capture_refresh_mode_locked()

virtsnd_pcm_capture_refresh_mode_locked() in sound/virtio/virtio_pcm_msg.c
only checks outstanding >= vss->buffer_bytes when transitioning from
free-running to bounded mode, so virtsnd_pcm_capture_staged_ack() succeeds
with rc == 0. Because virtsnd_pcm_cp_ack() in sound/virtio/virtio_pcm_ops.c
only calls virtsnd_pcm_capture_arm_paused_stop(vss) when rc == -EPIPE, it
returns 0 without setting vss->stopped or runtime->stop_operating.

Immediately afterward at the end of __snd_pcm_lib_xfer() in
sound/core/pcm_lib.c:

  _end_unlock:
    runtime->twake = 0;
    if (xfer > 0 && err >= 0)
        snd_pcm_update_state(substream, runtime);

snd_pcm_update_state() sees avail >= runtime->stop_threshold and calls
__snd_pcm_xrun() -> snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN). Because
snd_pcm_running() is false in SNDRV_PCM_STATE_PAUSED, snd_pcm_do_stop() skips
trigger(STOP) and does not set runtime->stop_operating = true.

On the subsequent recovery call to snd_pcm_prepare(), snd_pcm_sync_stop() is
skipped and virtsnd_pcm_prepare() in sound/virtio/virtio_pcm_ops.c fails with
-EBADFD on vss->stopped (in pause-restart mode) or
virtsnd_pcm_msg_pending_num(vss) (in native pause mode):

  scoped_guard(spinlock_irqsave, &vss->lock)
      stopped = vss->stopped;
  if (stopped) {
      dev_err(&vdev->dev, "SID %u: stream release failed\n",
              vss->sid);
      substream->runtime->stop_operating = true;
      return -EBADFD;
  }

  if (!vss->suspended) {
      if (virtsnd_pcm_msg_pending_num(vss)) {
          dev_err(&vdev->dev, "SID %u: invalid I/O queue state\n",
                  vss->sid);
          return -EBADFD;
      }

Should virtsnd_pcm_cp_ack() also check whether a paused stream has remaining
capture avail >= runtime->stop_threshold (or check stop_threshold in
virtsnd_pcm_capture_staged_ack()) so virtsnd_pcm_capture_arm_paused_stop() is
armed before snd_pcm_update_state() moves the paused stream to
SNDRV_PCM_STATE_XRUN?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261027234334.32551-1-mynameisjune111@gmail.com?part=11

      reply	other threads:[~2026-10-28  0:13 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-27 23:43 [PATCH v5 00/11] ALSA: virtio: staged capture and dsnoop recovery Joonho Lee
2026-10-27 23:43 ` [PATCH v5 01/11] ALSA: virtio: Propagate PCM send failures through ACK Joonho Lee
2026-10-28  0:09   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 02/11] ALSA: virtio: Recover PCM state after a failed start Joonho Lee
2026-10-28  0:18   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 03/11] ALSA: virtio: Retain queued messages through device reset Joonho Lee
2026-10-28  0:15   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 04/11] ALSA: virtio: Keep PCM DMA buffers alive through device ownership Joonho Lee
2026-10-27 23:59   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 05/11] ALSA: virtio: Keep control payloads alive through DMA completion Joonho Lee
2026-10-27 23:55   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 06/11] ALSA: virtio: wait through signals for PCM teardown Joonho Lee
2026-10-28  0:07   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 07/11] ALSA: virtio: stage VZ capture and restart paused streams Joonho Lee
2026-10-28  0:19   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 08/11] ALSA: virtio: account staged capture reads before RX refill Joonho Lee
2026-10-27 23:43 ` [PATCH v5 09/11] ALSA: virtio: prioritize staged capture period work Joonho Lee
2026-10-28  0:03   ` sashiko-bot
2026-10-27 23:43 ` [PATCH v5 10/11] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-10-27 23:43 ` [PATCH v5 11/11] ALSA: virtio-snd: fix dsnoop capture with staged buffers Joonho Lee
2026-10-28  0:13   ` 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-187263@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