Commit 4a971e84 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: control: Use deferred fasync helper

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.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 96b09709
...@@ -109,7 +109,7 @@ struct snd_ctl_file { ...@@ -109,7 +109,7 @@ struct snd_ctl_file {
int preferred_subdevice[SND_CTL_SUBDEV_ITEMS]; int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
wait_queue_head_t change_sleep; wait_queue_head_t change_sleep;
spinlock_t read_lock; spinlock_t read_lock;
struct fasync_struct *fasync; struct snd_fasync *fasync;
int subscribed; /* read interface is activated */ int subscribed; /* read interface is activated */
struct list_head events; /* waiting events for read */ struct list_head events; /* waiting events for read */
}; };
......
...@@ -127,6 +127,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file) ...@@ -127,6 +127,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
if (control->vd[idx].owner == ctl) if (control->vd[idx].owner == ctl)
control->vd[idx].owner = NULL; control->vd[idx].owner = NULL;
up_write(&card->controls_rwsem); up_write(&card->controls_rwsem);
snd_fasync_free(ctl->fasync);
snd_ctl_empty_read_queue(ctl); snd_ctl_empty_read_queue(ctl);
put_pid(ctl->pid); put_pid(ctl->pid);
kfree(ctl); kfree(ctl);
...@@ -181,7 +182,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, ...@@ -181,7 +182,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
_found: _found:
wake_up(&ctl->change_sleep); wake_up(&ctl->change_sleep);
spin_unlock(&ctl->read_lock); 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); read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
} }
...@@ -2134,7 +2135,7 @@ static int snd_ctl_fasync(int fd, struct file * file, int on) ...@@ -2134,7 +2135,7 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
struct snd_ctl_file *ctl; struct snd_ctl_file *ctl;
ctl = file->private_data; 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; /* return the preferred subdevice number if already assigned;
...@@ -2302,7 +2303,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) ...@@ -2302,7 +2303,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
read_lock_irqsave(&card->ctl_files_rwlock, flags); read_lock_irqsave(&card->ctl_files_rwlock, flags);
list_for_each_entry(ctl, &card->ctl_files, list) { list_for_each_entry(ctl, &card->ctl_files, list) {
wake_up(&ctl->change_sleep); 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); read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment