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

isdn: divert, hysdn: fix interruptible_sleep_on race

These two drivers use identical code for their procfs status
file handling, which contains a small race against status
data becoming available while reading the file.

This uses wait_event_interruptible instead to fix this
particular race and eventually get rid of all sleep_on
instances. There seems to be another race involving
multiple concurrent readers of the same procfs file, which
I don't try to fix here.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Karsten Keil <isdn@linux-pingi.de>
Cc: netdev@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arnd Bergmann and committed by
David S. Miller
c11da83b c728cc88

+8 -6
+4 -3
drivers/isdn/divert/divert_procfs.c
··· 86 86 struct divert_info *inf; 87 87 int len; 88 88 89 - if (!*((struct divert_info **) file->private_data)) { 89 + if (!(inf = *((struct divert_info **) file->private_data))) { 90 90 if (file->f_flags & O_NONBLOCK) 91 91 return -EAGAIN; 92 - interruptible_sleep_on(&(rd_queue)); 92 + wait_event_interruptible(rd_queue, (inf = 93 + *((struct divert_info **) file->private_data))); 93 94 } 94 - if (!(inf = *((struct divert_info **) file->private_data))) 95 + if (!inf) 95 96 return (0); 96 97 97 98 inf->usage_cnt--; /* new usage count */
+4 -3
drivers/isdn/hysdn/hysdn_proclog.c
··· 175 175 int len; 176 176 hysdn_card *card = PDE_DATA(file_inode(file)); 177 177 178 - if (!*((struct log_data **) file->private_data)) { 178 + if (!(inf = *((struct log_data **) file->private_data))) { 179 179 struct procdata *pd = card->proclog; 180 180 if (file->f_flags & O_NONBLOCK) 181 181 return (-EAGAIN); 182 182 183 - interruptible_sleep_on(&(pd->rd_queue)); 183 + wait_event_interruptible(pd->rd_queue, (inf = 184 + *((struct log_data **) file->private_data))); 184 185 } 185 - if (!(inf = *((struct log_data **) file->private_data))) 186 + if (!inf) 186 187 return (0); 187 188 188 189 inf->usage_cnt--; /* new usage count */