]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ALSA: control: Use deferred fasync helper
authorTakashi Iwai <tiwai@suse.de>
Thu, 28 Jul 2022 12:59:45 +0000 (14:59 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Aug 2022 09:38:21 +0000 (11:38 +0200)
[ Upstream commit 4a971e84a7ae10a38d875cd2d4e487c8d1682ca3 ]

For avoiding the potential deadlock via kill_fasync() call, use the
new fasync helpers to defer the invocation from the control API.  Note
that it's merely a workaround.

Another note: although we haven't received reports about the deadlock
with the control API, the deadlock is still potentially possible, and
it's better to align the behavior with other core APIs (PCM and
timer); so let's move altogether.

Link: https://lore.kernel.org/r/20220728125945.29533-5-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/sound/control.h
sound/core/control.c

index 77d9fa10812d01dcc35f0b24b6fc5a66cbe9bb94..41bd72ffd23226361b32bc8cd0da806d5f4c652a 100644 (file)
@@ -103,7 +103,7 @@ struct snd_ctl_file {
        int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
        wait_queue_head_t change_sleep;
        spinlock_t read_lock;
-       struct fasync_struct *fasync;
+       struct snd_fasync *fasync;
        int subscribed;                 /* read interface is activated */
        struct list_head events;        /* waiting events for read */
 };
index 3b44378b9dec9edb1595dae8282b835a946e6ae7..732eb515d2f59a6b5d854c47b9c660e91c038c3d 100644 (file)
@@ -121,6 +121,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
                        if (control->vd[idx].owner == ctl)
                                control->vd[idx].owner = NULL;
        up_write(&card->controls_rwsem);
+       snd_fasync_free(ctl->fasync);
        snd_ctl_empty_read_queue(ctl);
        put_pid(ctl->pid);
        kfree(ctl);
@@ -175,7 +176,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
        _found:
                wake_up(&ctl->change_sleep);
                spin_unlock(&ctl->read_lock);
-               kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
+               snd_kill_fasync(ctl->fasync, SIGIO, POLL_IN);
        }
        read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
 }
@@ -1941,7 +1942,7 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
        struct snd_ctl_file *ctl;
 
        ctl = file->private_data;
-       return fasync_helper(fd, file, on, &ctl->fasync);
+       return snd_fasync_helper(fd, file, on, &ctl->fasync);
 }
 
 /* return the preferred subdevice number if already assigned;
@@ -2015,7 +2016,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
        read_lock_irqsave(&card->ctl_files_rwlock, flags);
        list_for_each_entry(ctl, &card->ctl_files, list) {
                wake_up(&ctl->change_sleep);
-               kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
+               snd_kill_fasync(ctl->fasync, SIGIO, POLL_ERR);
        }
        read_unlock_irqrestore(&card->ctl_files_rwlock, flags);