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 v14 04/12] ALSA: virtio: Propagate PCM send failures through ACK
Date: Wed, 04 Nov 2026 03:02:43 +0000	[thread overview]
Message-ID: <sashiko-outbox-196563@kernel.org> (raw)
In-Reply-To: <20261104021745.57733-5-mynameisjune111@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ALSA: virtio: ack callbacks re-arm stop_operating when stopped with xfer_xrun
--

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

ALSA: virtio: Propagate PCM send failures through ACK

This commit propagates message submission errors from virtsnd_pcm_msg_send()
through the indirect PCM transfer and ACK callbacks, arming stop_operating and
returning -EPIPE on transfer failure. It also adds prepared and preparing state
tracking to gate ACK callbacks across substream teardown, prepare, and reset.

> diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
> index 1091100a4c982..629c738873c9e 100644
> --- a/sound/virtio/virtio_pcm_ops.c
> +++ b/sound/virtio/virtio_pcm_ops.c
[ ... ]
> @@ -461,41 +530,165 @@ virtsnd_pcm_cp_pointer(struct snd_pcm_substream *substream)
[ ... ]
> +/* Caller holds vss->lock. */
> +static void virtsnd_pcm_transfer_failed(struct virtio_pcm_substream *vss)
> +{
> +	vss->xfer_enabled = false;
> +	vss->stopped = true;
> +	vss->substream->runtime->stop_operating = true;
> +}
[ ... ]
>  static int virtsnd_pcm_pb_ack(struct snd_pcm_substream *substream)
>  {
>  	struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
>  	struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss);
> +	struct virtsnd_pcm_transfer transfer = {};
> +	int rc;
> +
> +	rc = virtsnd_pcm_ack_state(substream);
> +	if (rc)
> +		return rc;
>  
> -	guard(spinlock_irqsave)(&queue->lock);
> -	guard(spinlock)(&vss->lock);
> +	scoped_guard(spinlock_irqsave, &queue->lock) {
> +		guard(spinlock)(&vss->lock);
> +		if (vss->preparing || !vss->prepared)
> +			return -EBADFD;
> +		if (vss->stopped && !vss->xfer_xrun)
> +			return -EBADFD;
> +		if (vss->xfer_xrun) {
> +			rc = -EPIPE;
> +		} else {
> +			transfer.indirect = vss->pcm_indirect;
> +			rc = snd_pcm_indirect_playback_transfer(substream,
> +							       &transfer.indirect,
> +							       virtsnd_pcm_trans_copy);
> +			if (!rc)
> +				rc = transfer.error;
> +		}
> +		if (rc)
> +			virtsnd_pcm_transfer_failed(vss);
> +		else
> +			vss->pcm_indirect = transfer.indirect;
> +	}
[ ... ]
>  static int virtsnd_pcm_cp_ack(struct snd_pcm_substream *substream)
>  {
>  	struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
>  	struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss);
> +	struct virtsnd_pcm_transfer transfer = {};
> +	int rc;
> +
> +	rc = virtsnd_pcm_ack_state(substream);
> +	if (rc)
> +		return rc;
>  
> -	guard(spinlock_irqsave)(&queue->lock);
> -	guard(spinlock)(&vss->lock);
> +	scoped_guard(spinlock_irqsave, &queue->lock) {
> +		guard(spinlock)(&vss->lock);
> +		if (vss->preparing || !vss->prepared)
> +			return -EBADFD;
> +		if (vss->stopped && !vss->xfer_xrun &&
> +		    substream->runtime->state != SNDRV_PCM_STATE_DRAINING)
> +			return -EBADFD;
> +		if (vss->xfer_xrun) {
> +			rc = -EPIPE;
> +		} else {
> +			transfer.indirect = vss->pcm_indirect;
> +			rc = snd_pcm_indirect_capture_transfer(substream,
> +							       &transfer.indirect,
> +							       virtsnd_pcm_trans_copy);
> +			if (!rc)
> +				rc = transfer.error;
> +		}
> +		if (rc)
> +			virtsnd_pcm_transfer_failed(vss);

[Severity: Medium]
As reported by Sashiko on v13 [1], in virtsnd_pcm_pb_ack() and
virtsnd_pcm_cp_ack(), can a substream with both vss->stopped and
vss->xfer_xrun set bypass the stopped check during teardown or prepare,
re-arm runtime->stop_operating, and trigger a spurious transition to
SNDRV_PCM_STATE_XRUN?

Both virtsnd_pcm_pb_ack() and virtsnd_pcm_cp_ack() gate the vss->stopped
check on !vss->xfer_xrun:

	if (vss->stopped && !vss->xfer_xrun)
		return -EBADFD;
	if (vss->xfer_xrun) {
		rc = -EPIPE;
	}

When the device reports VIRTIO_SND_EVT_PCM_XRUN, virtsnd_pcm_event() sets
vss->xfer_xrun = true, and neither virtsnd_pcm_trigger(SNDRV_PCM_TRIGGER_STOP)
nor virtsnd_pcm_sync_stop() clears vss->xfer_xrun.

If a linked substream is in SNDRV_PCM_STATE_PREPARED (for example, after
snd_pcm_undo_start() stopped it following an XRUN event) or
SNDRV_PCM_STATE_DRAINING (for a capture stream stopped by snd_pcm_drain()),
and snd_pcm_prepare() runs:

snd_pcm_do_prepare(s)
  snd_pcm_sync_stop(s, true)
    s->runtime->stop_operating = false;
    virtsnd_pcm_sync_stop(s)
      virtsnd_pcm_block_ack(s)

Before virtsnd_pcm_block_ack() acquires the PCM stream lock, a concurrent
SNDRV_PCM_IOCTL_SYNC_PTR on s can run pcm_lib_apply_appl_ptr() and invoke
virtsnd_pcm_pb_ack() or virtsnd_pcm_cp_ack(). Because vss->stopped and
vss->xfer_xrun are both true, the ACK callback skips the -EBADFD return,
calls virtsnd_pcm_transfer_failed() to set s->runtime->stop_operating = true
and vss->stopped = true again, and returns -EPIPE so pcm_lib_apply_appl_ptr()
calls __snd_pcm_xrun(s).

If a later linked substream in the group fails prepare, earlier substreams in
the group are left in SNDRV_PCM_STATE_XRUN. If prepare succeeds,
s->runtime->stop_operating remains true on the prepared stream, and a
subsequent snd_pcm_suspend_all() while s is still in SNDRV_PCM_STATE_PREPARED
will call virtsnd_pcm_sync_stop() -> virtsnd_pcm_block_ack() with
vss->stopped == false, leaving vss->preparing = true.

In the later commit in this series ("ALSA: virtio: add staged capture and
serialize PCM lifecycle accounting"), snd_pcm_do_prepare() still calls
snd_pcm_sync_stop() before substream->ops->prepare(), virtsnd_pcm_sync_stop()
returns 0 for SNDRV_PCM_STATE_PREPARED (and virtsnd_pcm_sync_stop_locked()
restores vss->preparing = false before returning while leaving
vss->xfer_xrun = true), virtsnd_pcm_ack_state() drops the
buffer_accessing < 0 check, and virtsnd_pcm_pb_ack_locked() and
virtsnd_pcm_cp_ack_locked() check vss->xfer_xrun before
!vss->prepared || vss->stopped, so this race window remains.

Should virtsnd_pcm_pb_ack() and virtsnd_pcm_cp_ack() check vss->stopped and
return -EBADFD before checking vss->xfer_xrun, or avoid calling
virtsnd_pcm_transfer_failed() when vss->stopped is already set?

[1] https://lore.kernel.org/r/20261103080821.16983-2-mynameisjune111@gmail.com

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

  reply	other threads:[~2026-11-04  3:02 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-04  2:17 [PATCH v14 00/12] ALSA: virtio: staged capture recovery and PCM RESET synchronization Joonho Lee
2026-11-04  2:17 ` [PATCH v14 01/12] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-11-04  2:17 ` [PATCH v14 02/12] ALSA: pcm: report partial progress under the stream lock Joonho Lee
2026-11-04  2:17 ` [PATCH v14 03/12] ALSA: pcm: add an optional reset operation " Joonho Lee
2026-11-04  2:17 ` [PATCH v14 04/12] ALSA: virtio: Propagate PCM send failures through ACK Joonho Lee
2026-11-04  3:02   ` sashiko-bot [this message]
2026-11-04  2:17 ` [PATCH v14 05/12] ALSA: virtio: Recover PCM state after a failed start Joonho Lee
2026-11-04  2:17 ` [PATCH v14 06/12] ALSA: virtio: Retain queued messages through device reset Joonho Lee
2026-11-04  2:17 ` [PATCH v14 07/12] ALSA: virtio: Keep PCM DMA buffers alive through device ownership Joonho Lee
2026-11-04  2:17 ` [PATCH v14 08/12] ALSA: virtio: Keep control payloads alive through DMA completion Joonho Lee
2026-11-04  2:17 ` [PATCH v14 09/12] ALSA: virtio: wait through signals for PCM teardown Joonho Lee
2026-11-04  2:17 ` [PATCH v14 10/12] ALSA: virtio: add staged capture and serialize PCM lifecycle accounting Joonho Lee
2026-11-04  2:17 ` [PATCH v14 11/12] ALSA: virtio: prioritize staged capture period work Joonho Lee
2026-11-04  2:17 ` [PATCH v14 12/12] docs: describe virtio-sound capture options Joonho Lee

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-196563@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