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 v15 10/12] ALSA: virtio: add staged capture and serialize PCM lifecycle accounting
Date: Thu, 05 Nov 2026 00:44:30 +0000 [thread overview]
Message-ID: <sashiko-outbox-198370@kernel.org> (raw)
In-Reply-To: <20261105000915.15177-11-mynameisjune111@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ALSA: virtio: staged capture ACK and pointer bypass prepared check in DRAINING
--
commit 50d3f0b4df898e1d66fc877101e4baac71884d78
Author: Joonho Lee <mynameisjune111@gmail.com>
ALSA: virtio: add staged capture and serialize PCM lifecycle accounting
This commit adds an opt-in staged capture mode using request-owned RX
buffers with monotonic byte accounting for shared capture clients. It also
serializes PCM lifecycle transitions with lifecycle_lock and coordinates
pointer, reset, and ACK admission under the PCM stream lock.
> diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
> index 706d59d8c7201..a60f960287e2e 100644
> --- a/sound/virtio/virtio_pcm_ops.c
> +++ b/sound/virtio/virtio_pcm_ops.c
[ ... ]
> @@ -601,14 +1513,69 @@ static snd_pcm_uframes_t
> virtsnd_pcm_cp_pointer(struct snd_pcm_substream *substream)
> {
> struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
> + struct snd_pcm_runtime *runtime = substream->runtime;
> + size_t hw_ptr = 0;
> + u64 total;
> + bool free_running;
> + bool xrun;
>
> - scoped_guard(spinlock_irqsave, &vss->lock)
> - if (vss->xfer_xrun)
> + if (vss->capture_staging) {
> + scoped_guard(spinlock_irqsave, &vss->lock) {
> + if (!vss->runtime_active || vss->preparing || vss->suspended ||
> + (!vss->prepared && runtime->state != SNDRV_PCM_STATE_DRAINING &&
> + !(runtime->state == SNDRV_PCM_STATE_PAUSED &&
> + virtsnd_pcm_pause_restart_enabled(vss) &&
> + vss->pause_restart_state == VIRTSND_PCM_PAUSE_RESTART_RELEASED)))
> + return SNDRV_PCM_POS_XRUN;
[ ... ]
> @@ -647,86 +1658,176 @@ static int virtsnd_pcm_ack_state(struct snd_pcm_substream *substream)
[ ... ]
> +static int virtsnd_pcm_capture_staged_ack(struct virtio_pcm_substream *vss,
> + struct snd_pcm_runtime *runtime)
> +{
> + struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss);
> + int rc = 0;
> +
> + /*
> + * The RX callback holds the queue lock while draining completions.
> + * Account ALSA's read under the substream lock alone so completions later
> + * in that drain observe the newly released ring space.
> + */
> + scoped_guard(spinlock_irqsave, &vss->lock) {
> + snd_pcm_uframes_t appl_ptr;
> + snd_pcm_uframes_t appl_diff;
> + snd_pcm_uframes_t ack_frames;
> + snd_pcm_sframes_t diff;
> + size_t bytes;
> + u64 outstanding;
> + u64 next_acked_total;
> + bool free_running;
> +
> + if (!vss->runtime_active || vss->preparing || !runtime || !runtime->control ||
> + !runtime->dma_area || vss->suspended)
> return -EBADFD;
> - if (vss->stopped)
> + /* Preserve DRAINING tails only when no transfer XRUN is latched. */
> + 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 (vss->xfer_xrun)
> + return -EPIPE;
> + if (!vss->prepared && runtime->state != SNDRV_PCM_STATE_DRAINING &&
> + !(runtime->state == SNDRV_PCM_STATE_PAUSED &&
> + virtsnd_pcm_pause_restart_enabled(vss) &&
> + vss->pause_restart_state == VIRTSND_PCM_PAUSE_RESTART_RELEASED))
> + return -EBADFD;
> + if (vss->stopped && runtime->state != SNDRV_PCM_STATE_DRAINING &&
> + !(runtime->state == SNDRV_PCM_STATE_PAUSED &&
> + virtsnd_pcm_pause_restart_enabled(vss) &&
> + vss->pause_restart_state == VIRTSND_PCM_PAUSE_RESTART_RELEASED))
> + return -EBADFD;
[Severity: Medium]
Should virtsnd_pcm_cp_pointer() and virtsnd_pcm_capture_staged_ack()
exempt SNDRV_PCM_STATE_DRAINING from the !vss->prepared check?
When a capture stream enters SNDRV_PCM_STATE_DRAINING via
snd_pcm_drain() -> snd_pcm_do_drain_init() -> snd_pcm_do_stop() ->
virtsnd_pcm_trigger(SNDRV_PCM_TRIGGER_STOP), the driver sets
vss->stopped = true and vss->xfer_enabled = false while keeping
vss->prepared = true. Unlike SNDRV_PCM_STATE_PAUSED under
capture_pause_restart (which sends VIRTIO_SND_R_PCM_RELEASE and sets
vss->prepared = false), an active draining capture epoch always keeps
vss->prepared = true until teardown retires it.
If userspace subsequently calls snd_pcm_prepare() on a draining staged
capture stream, snd_pcm_do_prepare() leaves runtime->state as
SNDRV_PCM_STATE_DRAINING while invoking snd_pcm_sync_stop() ->
virtsnd_pcm_sync_stop() -> virtsnd_pcm_sync_stop_locked():
sound/virtio/virtio_pcm_ops.c:virtsnd_pcm_sync_stop_locked() {
scoped_guard(pcm_stream_lock_irqsave, substream) {
guard(spinlock_irqsave)(&vss->lock);
preparing = vss->preparing;
vss->preparing = true;
vss->prepared = false;
vss->xfer_enabled = false;
}
rc = virtsnd_pcm_release_locked(substream);
scoped_guard(pcm_stream_lock_irqsave, substream) {
guard(spinlock_irqsave)(&vss->lock);
vss->preparing = preparing;
}
return rc;
}
Once virtsnd_pcm_sync_stop_locked() returns, vss->prepared and
vss->stopped are both false and vss->preparing is restored to false,
while runtime->state is still SNDRV_PCM_STATE_DRAINING. In the window
before virtsnd_pcm_prepare_locked() takes the PCM stream lock (or
permanently if virtsnd_pcm_prepare_locked() fails before
virtsnd_pcm_dev_prepare(), such as on -ECANCELED or a
virtsnd_pcm_dev_set_params() error, where virtsnd_pcm_prepare() resets
vss->preparing = false), concurrent SNDRV_PCM_IOCTL_SYNC_PTR or
SNDRV_PCM_IOCTL_HWSYNC calls bypass the !vss->prepared check and proceed
on the released, unprepared epoch.
By comparison, the non-staged path in virtsnd_pcm_cp_ack_locked() only
exempts SNDRV_PCM_STATE_DRAINING from vss->stopped and unconditionally
rejects !vss->prepared:
if (!vss->prepared ||
(vss->stopped &&
runtime->state != SNDRV_PCM_STATE_DRAINING))
return -EBADFD;
Should virtsnd_pcm_cp_pointer() and virtsnd_pcm_capture_staged_ack()
likewise require vss->prepared to be true unless the stream is in the
pause-restart released state?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105000915.15177-1-mynameisjune111@gmail.com?part=10
next prev parent reply other threads:[~2026-11-05 0:44 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 0:09 [PATCH v15 00/12] ALSA: virtio: staged capture recovery and PCM ACK handoff Joonho Lee
2026-11-05 0:09 ` [PATCH v15 01/12] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-11-05 0:09 ` [PATCH v15 02/12] ALSA: pcm: report partial progress under the stream lock Joonho Lee
2026-11-05 0:09 ` [PATCH v15 03/12] ALSA: pcm: add an optional reset operation " Joonho Lee
2026-11-05 0:09 ` [PATCH v15 04/12] ALSA: virtio: Propagate PCM send failures through ACK Joonho Lee
2026-11-05 0:09 ` [PATCH v15 05/12] ALSA: virtio: Recover PCM state after a failed start Joonho Lee
2026-11-05 0:09 ` [PATCH v15 06/12] ALSA: virtio: Retain queued messages through device reset Joonho Lee
2026-11-05 0:09 ` [PATCH v15 07/12] ALSA: virtio: Keep PCM DMA buffers alive through device ownership Joonho Lee
2026-11-05 0:35 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 08/12] ALSA: virtio: Keep control payloads alive through DMA completion Joonho Lee
2026-11-05 0:09 ` [PATCH v15 09/12] ALSA: virtio: wait through signals for PCM teardown Joonho Lee
2026-11-05 0:09 ` [PATCH v15 10/12] ALSA: virtio: add staged capture and serialize PCM lifecycle accounting Joonho Lee
2026-11-05 0:44 ` sashiko-bot [this message]
2026-11-05 0:09 ` [PATCH v15 11/12] ALSA: virtio: prioritize staged capture period work Joonho Lee
2026-11-05 0:09 ` [PATCH v15 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-198370@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