[PATCH v3 3/5] ALSA: pcm: Add the file to the card while looking up the minor

From: Cen Zhang

Date: Fri Oct 30 2026 - 04:04:51 EST


Use snd_lookup_minor_data_file() and snd_lookup_oss_minor_data_file() in
the native and OSS PCM opens, so that the file is on the card before the
PCM minor can be unregistered. The opens then no longer need the extra
card reference from the lookup.

Without that reference, a failed open also no longer reads pcm->card
after it has removed its file, which would race with a remove that waits
for the files before freeing the PCM.

Signed-off-by: Cen Zhang <zzzccc427@xxxxxxxxx>
---
sound/core/oss/pcm_oss.c | 19 ++++++-------------
sound/core/pcm_native.c | 37 +++++++++++++++----------------------
2 files changed, 21 insertions(+), 35 deletions(-)

diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index e8df27d09b97..2d99df900f76 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2497,15 +2497,12 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)

nonseekable_open(inode, file);

- pcm = snd_lookup_oss_minor_data(iminor(inode),
- SNDRV_OSS_DEVICE_TYPE_PCM);
- if (pcm == NULL) {
- err = -ENODEV;
- goto __error1;
- }
- err = snd_card_file_add(pcm->card, file);
- if (err < 0)
- goto __error1;
+ pcm = snd_lookup_oss_minor_data_file(iminor(inode),
+ SNDRV_OSS_DEVICE_TYPE_PCM, file);
+ if (IS_ERR(pcm))
+ return PTR_ERR(pcm);
+ if (!pcm)
+ return -ENODEV;
if (!try_module_get(pcm->card->module)) {
err = -ENODEV;
goto __error2;
@@ -2558,16 +2555,12 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
mutex_unlock(&pcm->open_mutex);
if (err < 0)
goto __error;
- snd_card_unref(pcm->card);
return err;

__error:
module_put(pcm->card->module);
__error2:
snd_card_file_remove(pcm->card, file);
- __error1:
- if (pcm)
- snd_card_unref(pcm->card);
return err;
}

diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 35152fae74ca..89bfe1f358ee 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2938,45 +2938,39 @@ static int snd_pcm_open_file(struct file *file,
static int snd_pcm_playback_open(struct inode *inode, struct file *file)
{
struct snd_pcm *pcm;
- int err;

nonseekable_open(inode, file);

- pcm = snd_lookup_minor_data(iminor(inode),
- SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
- err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
- if (pcm)
- snd_card_unref(pcm->card);
- return err;
+ pcm = snd_lookup_minor_data_file(iminor(inode),
+ SNDRV_DEVICE_TYPE_PCM_PLAYBACK, file);
+ if (IS_ERR(pcm))
+ return PTR_ERR(pcm);
+ if (!pcm)
+ return -ENODEV;
+ return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
}

static int snd_pcm_capture_open(struct inode *inode, struct file *file)
{
struct snd_pcm *pcm;
- int err;

nonseekable_open(inode, file);

- pcm = snd_lookup_minor_data(iminor(inode),
- SNDRV_DEVICE_TYPE_PCM_CAPTURE);
- err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
- if (pcm)
- snd_card_unref(pcm->card);
- return err;
+ pcm = snd_lookup_minor_data_file(iminor(inode),
+ SNDRV_DEVICE_TYPE_PCM_CAPTURE, file);
+ if (IS_ERR(pcm))
+ return PTR_ERR(pcm);
+ if (!pcm)
+ return -ENODEV;
+ return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
}

+/* called with the file added to the card by snd_lookup_minor_data_file() */
static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
{
int err;
wait_queue_entry_t wait;

- if (pcm == NULL) {
- err = -ENODEV;
- goto __error1;
- }
- err = snd_card_file_add(pcm->card, file);
- if (err < 0)
- goto __error1;
if (!try_module_get(pcm->card->module)) {
err = -ENODEV;
goto __error2;
@@ -3018,7 +3012,6 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
module_put(pcm->card->module);
__error2:
snd_card_file_remove(pcm->card, file);
- __error1:
return err;
}

--
2.43.0