Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sound: oss: vwsnd: avoid interruptible_sleep_on

Interruptible_sleep_on is racy and we want to remove it. This replaces
the use in the vwsnd driver with an open-coded prepare_to_wait
loop that fixes the race between concurrent open() and close() calls,
and also drops the global mutex while waiting here, which restores
the original behavior that was changed during the BKL removal.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Arnd Bergmann and committed by
Takashi Iwai
7bd6972a 1a215765

+10 -4
+10 -4
sound/oss/vwsnd.c
··· 2921 2921 vwsnd_dev_t *devc; 2922 2922 int minor = iminor(inode); 2923 2923 int sw_samplefmt; 2924 + DEFINE_WAIT(wait); 2924 2925 2925 2926 DBGE("(inode=0x%p, file=0x%p)\n", inode, file); 2926 2927 ··· 2938 2937 } 2939 2938 2940 2939 mutex_lock(&devc->open_mutex); 2941 - while (devc->open_mode & file->f_mode) { 2940 + while (1) { 2941 + prepare_to_wait(&devc->open_wait, &wait, TASK_INTERRUPTIBLE); 2942 + if (!(devc->open_mode & file->f_mode)) 2943 + break; 2944 + 2942 2945 mutex_unlock(&devc->open_mutex); 2946 + mutex_unlock(&vwsnd_mutex); 2943 2947 if (file->f_flags & O_NONBLOCK) { 2944 2948 DEC_USE_COUNT; 2945 - mutex_unlock(&vwsnd_mutex); 2946 2949 return -EBUSY; 2947 2950 } 2948 - interruptible_sleep_on(&devc->open_wait); 2951 + schedule(); 2949 2952 if (signal_pending(current)) { 2950 2953 DEC_USE_COUNT; 2951 - mutex_unlock(&vwsnd_mutex); 2952 2954 return -ERESTARTSYS; 2953 2955 } 2956 + mutex_lock(&vwsnd_mutex); 2954 2957 mutex_lock(&devc->open_mutex); 2955 2958 } 2959 + finish_wait(&devc->open_wait, &wait); 2956 2960 devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); 2957 2961 mutex_unlock(&devc->open_mutex); 2958 2962