Linux virtualization list
 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 v17 10/12] ALSA: virtio: serialize staged capture lifecycle and defer paused XRUNs
Date: Thu, 05 Nov 2026 07:41:43 +0000	[thread overview]
Message-ID: <sashiko-outbox-198691@kernel.org> (raw)
In-Reply-To: <20261105070845.6449-11-mynameisjune111@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ALSA: virtio: missing xfer_xrun latch in virtsnd_pcm_transfer_failed()
--

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

ALSA: virtio: serialize staged capture lifecycle and defer paused XRUNs

This commit introduces request-owned RX staging for capture streams,
serializes PCM lifecycle operations with lifecycle_lock, and defers XRUN
handling for paused linked streams until resume.

> diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
> index 706d59d8c7201..36f8128a3f30c 100644
> --- a/sound/virtio/virtio_pcm_ops.c
> +++ b/sound/virtio/virtio_pcm_ops.c

[ ... ]

> @@ -637,132 +1739,515 @@ static void virtsnd_pcm_transfer_failed(struct virtio_pcm_substream *vss)
>  	vss->substream->runtime->stop_operating = true;
>  }
>  
> +/* Caller holds vss->lock; a paused ACK must not trigger linked XRUN. */
> +static int virtsnd_pcm_ack_xrun_locked(struct virtio_pcm_substream *vss,
> +				       struct snd_pcm_runtime *runtime)
> +{
> +	vss->xfer_xrun = true;
> +	if (runtime->state == SNDRV_PCM_STATE_PAUSED) {
> +		vss->xfer_enabled = false;
> +		runtime->stop_operating = true;
> +		virtsnd_pcm_schedule_period_elapsed(vss);
> +		return -EBADFD;
> +	}
> +	return -EPIPE;
> +}
> +
> +static int virtsnd_pcm_pb_ack_locked(struct snd_pcm_substream *substream)
> +{
> +	struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss);
> +	struct virtsnd_pcm_transfer transfer = {};
> +	bool paused;
> +	int rc;
> +
> +	scoped_guard(spinlock_irqsave, &queue->lock) {
> +		guard(spinlock)(&vss->lock);
> +		paused = runtime->state == SNDRV_PCM_STATE_PAUSED;
> +		if (vss->preparing)
> +			return -EBADFD;
> +		/* A latched XRUN must not re-arm sync_stop once teardown began. */
> +		if (vss->stopped && vss->xfer_xrun)
> +			return -EBADFD;
> +		if (vss->xfer_xrun) {
> +			rc = virtsnd_pcm_ack_xrun_locked(vss, runtime);
> +		} else {
> +			if (!vss->prepared || vss->stopped)
> +				return -EBADFD;
> +			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) {
> +			if (paused)
> +				rc = virtsnd_pcm_ack_xrun_locked(vss, runtime);
> +			else
> +				virtsnd_pcm_transfer_failed(vss);
> +		} else {
> +			vss->pcm_indirect = transfer.indirect;
> +		}
> +	}

[ ... ]

> +static int virtsnd_pcm_cp_ack_locked(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 snd_pcm_runtime *runtime = substream->runtime;
> +	struct virtsnd_pcm_transfer transfer = {};
> +	bool paused;
> +	int rc;
> +
> +	if (vss->capture_staging) {
> +		rc = virtsnd_pcm_capture_staged_ack(vss, runtime);
> +		if (rc == -EPIPE) {
> +			guard(spinlock_irqsave)(&vss->lock);
> +			virtsnd_pcm_transfer_failed(vss);
> +		}
> +		return rc;
> +	}
> +
> +	scoped_guard(spinlock_irqsave, &queue->lock) {
> +		guard(spinlock)(&vss->lock);
> +		paused = runtime->state == SNDRV_PCM_STATE_PAUSED;
> +		if (vss->preparing)
> +			return -EBADFD;
> +		/* A latched XRUN must not re-arm sync_stop once teardown began. */
> +		if (vss->stopped && vss->xfer_xrun)
> +			return -EBADFD;
> +		if (vss->xfer_xrun) {
> +			rc = virtsnd_pcm_ack_xrun_locked(vss, runtime);
> +		} else {
> +			if (!vss->prepared ||
> +			    (vss->stopped &&
> +			     runtime->state != SNDRV_PCM_STATE_DRAINING))
> +				return -EBADFD;
> +			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) {
> +			if (paused)
> +				rc = virtsnd_pcm_ack_xrun_locked(vss, runtime);
> +			else
> +				virtsnd_pcm_transfer_failed(vss);
> +		} else {
> +			vss->pcm_indirect = transfer.indirect;
> +		}
> +	}

[Severity: Medium]
Should virtsnd_pcm_transfer_failed() in sound/virtio/virtio_pcm_ops.c also
latch vss->xfer_xrun = true?

When a non-paused indirect playback or capture ACK transfer fails in
virtsnd_pcm_pb_ack_locked() or virtsnd_pcm_cp_ack_locked() (for example,
when snd_pcm_indirect_playback_transfer() or
snd_pcm_indirect_capture_transfer() returns -EPIPE on a negative appl_ptr
diff, or virtsnd_pcm_msg_send() sets transfer.error), the error path calls
virtsnd_pcm_transfer_failed():

    static void virtsnd_pcm_transfer_failed(struct virtio_pcm_substream *vss)
    {
            vss->xfer_enabled = false;
            vss->stopped = true;
            vss->substream->runtime->stop_operating = true;
    }

Unlike the paused path (which calls virtsnd_pcm_ack_xrun_locked()) and the
staged capture path (where virtsnd_pcm_capture_staged_ack() calls
virtsnd_pcm_ack_xrun_locked() before virtsnd_pcm_transfer_failed()),
virtsnd_pcm_transfer_failed() leaves vss->xfer_xrun false while vss->prepared
and vss->stopped are true.

Because vss->xfer_xrun is not set:

1. In sound/virtio/virtio_pcm_msg.c, in-flight non-empty RX completions
arriving in virtsnd_pcm_msg_complete() for a non-staged capture stream bypass
the early retirement check:

    if (vss->direction == SNDRV_PCM_STREAM_CAPTURE &&
        (!vss->prepared || vss->xfer_xrun ||
         (vss->stopped && written_bytes <= sizeof(*msg->status)))) {

and continue copying data and advancing vss->hw_ptr and
vss->capture_copied_total after the failed ACK rolled back vss->pcm_indirect
and appl_ptr.

2. If the capture stream is in SNDRV_PCM_STATE_DRAINING, the stopped-plus-XRUN
admission check (if (vss->stopped && vss->xfer_xrun) return -EBADFD) in
virtsnd_pcm_cp_ack_locked() is not armed.

3. Any call to virtsnd_pcm_pb_pointer() or virtsnd_pcm_cp_pointer() before
teardown (such as across the stream lock drop when locking a linked group in
__snd_pcm_xrun()) does not see vss->xfer_xrun set, so it invokes
snd_pcm_indirect_playback_pointer() or snd_pcm_indirect_capture_pointer()
instead of returning SNDRV_PCM_POS_XRUN.

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

  reply	other threads:[~2026-11-05  7:41 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05  7:08 [PATCH v17 00/12] ALSA: virtio: fix capture lifetime and accounting Joonho Lee
2026-11-05  7:08 ` [PATCH v17 01/12] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-11-05  7:12   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 02/12] ALSA: pcm: report partial progress under the stream lock Joonho Lee
2026-11-05  7:14   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 03/12] ALSA: pcm: add an optional reset operation " Joonho Lee
2026-11-05  7:14   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 04/12] ALSA: virtio: Propagate PCM send failures through ACK Joonho Lee
2026-11-05  7:37   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 05/12] ALSA: virtio: Recover PCM state after a failed start Joonho Lee
2026-11-05  7:33   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 06/12] ALSA: virtio: Retain queued messages through device reset Joonho Lee
2026-11-05  7:39   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 07/12] ALSA: virtio: retain PCM DMA buffers and validate capture completions Joonho Lee
2026-11-05  7:43   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 08/12] ALSA: virtio: Keep control payloads alive through DMA completion Joonho Lee
2026-11-05  7:19   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 09/12] ALSA: virtio: wait through signals for PCM teardown Joonho Lee
2026-11-05  7:29   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 10/12] ALSA: virtio: serialize staged capture lifecycle and defer paused XRUNs Joonho Lee
2026-11-05  7:41   ` sashiko-bot [this message]
2026-11-05  7:08 ` [PATCH v17 11/12] ALSA: virtio: prioritize staged capture period work Joonho Lee
2026-11-05  7:24   ` sashiko-bot
2026-11-05  7:08 ` [PATCH v17 12/12] docs: describe virtio-sound capture options Joonho Lee
2026-11-05  7:20   ` sashiko-bot

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