* [RFC PATCH 0/2] ALSA: pcm: preserve capture tail during drain
@ 2026-10-14 3:30 Joonho Lee
2026-10-14 3:30 ` [RFC PATCH 1/2] ALSA: pcm: allow capture reads while draining Joonho Lee
2026-10-14 3:30 ` [RFC PATCH 2/2] ALSA: pcm: refresh capture pointers before drain Joonho Lee
0 siblings, 2 replies; 3+ messages in thread
From: Joonho Lee @ 2026-10-14 3:30 UTC (permalink / raw)
To: Takashi Iwai, Jaroslav Kysela; +Cc: linux-sound, linux-kernel, linux-api
Base: d58a3ac9b1719fdf8ce9d286be606128aeebf1aa
("ALSA: virtio: Keep control payloads alive through DMA completion")
Local tip of the five submitted v3 patches; not an upstream commit.
Previous series: <cover.1791881787.git.mynameisjune111@gmail.com>
Link: https://lore.kernel.org/all/cover.1791881787.git.mynameisjune111@gmail.com/
This is a follow-up RFC, not a replacement or v4 of that five-patch series.
The submitted v3 fixes ACK error propagation, failed START recovery, and
message/buffer lifetime through completion and reset. It does not add the
VZ capture profile or the ALSA core drain handling in these companion RFCs.
This series proposes two changes to capture drain handling:
1. Permit capture transfer calls while the runtime is DRAINING, so buffered
tail frames remain readable instead of returning -EBADFD at the state
check. Playback access rules remain unchanged.
2. Refresh active capture hardware pointers before the linked group enters
DRAINING, so a final subperiod tail is accounted. Hold the link read lock
across the initial operation and take each member's stream lock for its
pointer refresh. Propagate pointer errors before the drain transition.
These are ALSA core changes, not VZ quirks. They apply with all VZ options
disabled and can affect other capture drivers, including linked-stream drain
ordering. No new ioctl is added, but applications can observe buffered data
where the previous state check rejected a read. The appropriate core drain
semantics and locking scope need review independently of VZ support.
Dependencies
Apply these two patches in order on v3. They do not depend on the companion
STOP/RELEASE wait patch. The VZ capture RFC requires all three prerequisites.
The base is pinned for reproducibility; this is not a claim that the core
changes are inherently dependent on virtio-snd lifetime fixes.
Validation and limits
The complete local candidate (v3 plus all four RFC patches) was freshly
built on 2026-10-14 as an ARM64 KASAN Image and installed module set with
W=1, release 7.3.0-rc6-snd-lifetime-kasan. No old kernel objects were reused.
There were no build errors or warnings in the changed sound paths; 517
-Woverride-init warnings remain in two unchanged ARM64 base files.
This is a rebuild of the pinned candidate, not a rebase to a newer upstream
or sound maintainer tree.
With this kernel under ordinary TCG, no-query short-tail drain returns
1023 frames (FNV-1a64 20d61b4edef6d535) and 2047 frames
(af2de207e4d27535); drop returns zero. Each run also passes a following
capture with fatal-overrun checking, playback drain guard and teardown.
Earlier W=1 core builds included patch 1 alone. The separate historical
linked-pointer-error fixture used an earlier stable virtio-snd module to
isolate the core change; it is not one of the ten current candidate cases.
The QEMU 11.1.2 fixture includes backend reset cleanup changes as well as
fault injection. These are integrated candidate results, not standalone
v3 or isolated-patch proof, and not stock-QEMU, VZ or hardware acceptance.
Earlier runs failed follow-on capture with ring saturation and overruns;
those logs remain retained. Final passes do not establish a permanent fix
for load or clock/scheduling sensitivity.
Physical ALSA devices and the full range of linked capture/playback groups
remain untested. Historical AirPods capture does not isolate core drain
semantics. Playback access rules remain unchanged, but the shared drain
entry locking/order changes also need review for playback-led groups.
Reproducer
A source-only bundle contains the pinned base/v3/RFC preparation recipe,
kernel builder, QEMU patch stack, guest probes and all ten runtime commands.
See qemu/README.txt and qemu/VALIDATION-RESULTS.txt in that bundle. The final
runtime set passed under ordinary TCG; no KASAN/BUG/WARNING/oops/panic was
matched. The 24 Python harness tests and relocated source comparison also
passed. Existing v3 patches are included only as build prerequisites, not
for resubmission. Reproducer source (pinned commit):
https://github.com/whatisyourname0/virtio-snd-reproducer/tree/7a9876738bdc70ce669f02ec31fe8968eb0ee4fc/rfc/vz-capture-20261014
The source bundle includes qemu/README.txt with the full build/run recipe,
qemu/VALIDATION-RESULTS.txt and checksums. Downloaded public files were
verified against the tested source package. Bundled RFC mail drafts are
reproduction snapshots; these emails are the submission copies.
Questions for review
- Is reading buffered capture data in DRAINING the intended ALSA contract,
or should the driver expose that tail through a different transition?
- Is drain entry the correct place to refresh capture pointers, including
when draining a paused stream or a linked capture/playback group?
- Is the proposed link-lock/member-lock scope appropriate when a pointer
error can stop the group? Which other driver or linked-stream cases
should be required before treating this as a general core fix?
Joonho Lee (2):
ALSA: pcm: allow capture reads while draining
ALSA: pcm: refresh capture pointers before drain
sound/core/pcm_lib.c | 10 +++++++---
sound/core/pcm_native.c | 32 +++++++++++++++++++++++++-------
2 files changed, 32 insertions(+), 10 deletions(-)
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 1/2] ALSA: pcm: allow capture reads while draining
2026-10-14 3:30 [RFC PATCH 0/2] ALSA: pcm: preserve capture tail during drain Joonho Lee
@ 2026-10-14 3:30 ` Joonho Lee
2026-10-14 3:30 ` [RFC PATCH 2/2] ALSA: pcm: refresh capture pointers before drain Joonho Lee
1 sibling, 0 replies; 3+ messages in thread
From: Joonho Lee @ 2026-10-14 3:30 UTC (permalink / raw)
To: Takashi Iwai, Jaroslav Kysela; +Cc: linux-sound, linux-kernel, linux-api
Allow capture transfer calls in DRAINING so already captured tail frames
remain readable until drain completes.
Assisted-by: LLM
Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>
---
sound/core/pcm_lib.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 4d665b4148d7..de952f639d3b 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2208,13 +2208,17 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
return 0;
}
-static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+static int pcm_accessible_state(struct snd_pcm_substream *substream)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
switch (runtime->state) {
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PAUSED:
return 0;
+ case SNDRV_PCM_STATE_DRAINING:
+ return substream->stream == SNDRV_PCM_STREAM_CAPTURE ? 0 : -EBADFD;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
case SNDRV_PCM_STATE_SUSPENDED:
@@ -2320,7 +2324,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
nonblock = !!(substream->f_flags & O_NONBLOCK);
snd_pcm_stream_lock_irq(substream);
- err = pcm_accessible_state(runtime);
+ err = pcm_accessible_state(substream);
if (err < 0)
goto _end_unlock;
@@ -2388,7 +2392,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
atomic_dec(&runtime->buffer_accessing);
if (err < 0)
goto _end_unlock;
- err = pcm_accessible_state(runtime);
+ err = pcm_accessible_state(substream);
if (err < 0)
goto _end_unlock;
appl_ptr += frames;
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [RFC PATCH 2/2] ALSA: pcm: refresh capture pointers before drain
2026-10-14 3:30 [RFC PATCH 0/2] ALSA: pcm: preserve capture tail during drain Joonho Lee
2026-10-14 3:30 ` [RFC PATCH 1/2] ALSA: pcm: allow capture reads while draining Joonho Lee
@ 2026-10-14 3:30 ` Joonho Lee
1 sibling, 0 replies; 3+ messages in thread
From: Joonho Lee @ 2026-10-14 3:30 UTC (permalink / raw)
To: Takashi Iwai, Jaroslav Kysela; +Cc: linux-sound, linux-kernel, linux-api
Refresh active capture pointers before the drain transition so the final
captured tail is accounted before reads finish.
Assisted-by: LLM
Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>
---
sound/core/pcm_native.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index defbb2977efe..622ae7be2d04 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2176,14 +2176,32 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
} else if (substream->f_flags & O_NONBLOCK)
nonblock = 1;
- snd_pcm_stream_lock_irq(substream);
- /* resume pause */
- if (runtime->state == SNDRV_PCM_STATE_PAUSED)
- snd_pcm_pause(substream, false);
+ /* Keep linked runtimes alive until the initial drain action completes. */
+ scoped_guard(rwsem_read, &snd_pcm_link_rwsem) {
+ snd_pcm_stream_lock_irq(substream);
+ /* Resume before refreshing capture positions. */
+ if (runtime->state == SNDRV_PCM_STATE_PAUSED)
+ snd_pcm_pause(substream, false);
+ snd_pcm_stream_unlock_irq(substream);
+
+ /* A pointer error may stop the group: hold only this member's lock. */
+ snd_pcm_group_for_each_entry(s, substream) {
+ if (s->stream != SNDRV_PCM_STREAM_CAPTURE)
+ continue;
+ scoped_guard(pcm_stream_lock_irq, s) {
+ if (s->runtime->state == SNDRV_PCM_STATE_RUNNING)
+ result = snd_pcm_update_hw_ptr(s);
+ }
+ if (result < 0)
+ break;
+ }
- /* pre-start/stop - all running streams are changed to DRAINING state */
- result = snd_pcm_action(&snd_pcm_action_drain_init, substream,
- ACTION_ARG_IGNORE);
+ snd_pcm_stream_lock_irq(substream);
+ /* Change the stable group to DRAINING only after all refreshes. */
+ if (result >= 0)
+ result = snd_pcm_action(&snd_pcm_action_drain_init,
+ substream, ACTION_ARG_IGNORE);
+ }
if (result < 0)
goto unlock;
/* in non-blocking, we don't wait in ioctl but let caller poll */
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-14 3:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 3:30 [RFC PATCH 0/2] ALSA: pcm: preserve capture tail during drain Joonho Lee
2026-10-14 3:30 ` [RFC PATCH 1/2] ALSA: pcm: allow capture reads while draining Joonho Lee
2026-10-14 3:30 ` [RFC PATCH 2/2] ALSA: pcm: refresh capture pointers before drain Joonho Lee
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox