Module Name: src Committed By: riastradh Date: Tue Jun 1 21:19:03 UTC 2021
Modified Files: src/sys/dev/audio: audio.c Log Message: audio(4): Insert mixers and audioctls into sc_files on open too. This is necessary so that on detach we set file->dying before any operations, particularly audioclose, try to acquire a psref by the time the audio softc is gone. Candidate fix for PR kern/56164. To generate a diff of this commit: cvs rdiff -u -r1.100 -r1.101 src/sys/dev/audio/audio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/audio/audio.c diff -u src/sys/dev/audio/audio.c:1.100 src/sys/dev/audio/audio.c:1.101 --- src/sys/dev/audio/audio.c:1.100 Tue Jun 1 21:15:37 2021 +++ src/sys/dev/audio/audio.c Tue Jun 1 21:19:03 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: audio.c,v 1.100 2021/06/01 21:15:37 riastradh Exp $ */ +/* $NetBSD: audio.c,v 1.101 2021/06/01 21:19:03 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -138,7 +138,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.100 2021/06/01 21:15:37 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.101 2021/06/01 21:19:03 riastradh Exp $"); #ifdef _KERNEL_OPT #include "audio.h" @@ -1343,11 +1343,19 @@ audiodetach(device_t self, int flags) /* * Clean up all open instances. - * Here, we no longer need any locks to traverse sc_files. */ + mutex_enter(sc->sc_lock); while ((file = SLIST_FIRST(&sc->sc_files)) != NULL) { - audio_unlink(sc, file); + mutex_enter(sc->sc_intr_lock); + SLIST_REMOVE_HEAD(&sc->sc_files, entry); + mutex_exit(sc->sc_intr_lock); + if (file->ptrack || file->rtrack) { + mutex_exit(sc->sc_lock); + audio_unlink(sc, file); + mutex_enter(sc->sc_lock); + } } + mutex_exit(sc->sc_lock); pmf_event_deregister(self, PMFE_AUDIO_VOLUME_DOWN, audio_volume_down, true); @@ -1739,6 +1747,11 @@ audioclose(struct file *fp) bound = curlwp_bind(); sc = audio_sc_acquire_fromfile(file, &sc_ref); if (sc) { + mutex_enter(sc->sc_lock); + mutex_enter(sc->sc_intr_lock); + SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); switch (AUDIODEV(dev)) { case SOUND_DEVICE: case AUDIO_DEVICE: @@ -2596,10 +2609,6 @@ audio_unlink(struct audio_softc *sc, aud device_active(sc->sc_dev, DVA_SYSTEM); - mutex_enter(sc->sc_intr_lock); - SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); - mutex_exit(sc->sc_intr_lock); - if (file->ptrack) { TRACET(3, file->ptrack, "dropframes=%" PRIu64, file->ptrack->dropframes); @@ -3517,7 +3526,17 @@ audioctl_open(dev_t dev, struct audio_so af->sc = sc; af->dev = dev; - /* Not necessary to insert sc_files. */ + mutex_enter(sc->sc_lock); + if (sc->sc_dying) { + mutex_exit(sc->sc_lock); + kmem_free(af, sizeof(*af)); + fd_abort(curproc, fp, fd); + return ENXIO; + } + mutex_enter(sc->sc_intr_lock); + SLIST_INSERT_HEAD(&sc->sc_files, af, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); error = fd_clone(fp, fd, flags, &audio_fileops, af); KASSERTMSG(error == EMOVEFD, "error=%d", error); @@ -8133,6 +8152,18 @@ mixer_open(dev_t dev, struct audio_softc af->sc = sc; af->dev = dev; + mutex_enter(sc->sc_lock); + if (sc->sc_dying) { + mutex_exit(sc->sc_lock); + kmem_free(af, sizeof(*af)); + fd_abort(curproc, fp, fd); + return ENXIO; + } + mutex_enter(sc->sc_intr_lock); + SLIST_INSERT_HEAD(&sc->sc_files, af, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); + error = fd_clone(fp, fd, flags, &audio_fileops, af); KASSERT(error == EMOVEFD);