All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans Verkuil <hverkuil@xs4all.nl>
To: Arnd Bergmann <arnd@arndb.de>
Cc: linux-kernel@vger.kernel.org,
	Mauro Carvalho Chehab <m.chehab@samsung.com>,
	linux-media@vger.kernel.org
Subject: Re: [PATCH, RFC 07/30] [media] radio-cadet: avoid interruptible_sleep_on race
Date: Fri, 07 Feb 2014 12:35:54 +0100	[thread overview]
Message-ID: <52F4C51A.90002@xs4all.nl> (raw)
In-Reply-To: <55674412.rAimUmdW3X@wuerfel>

On 02/07/2014 11:17 AM, Arnd Bergmann wrote:
> On Friday 07 February 2014 10:32:28 Hans Verkuil wrote:
>>         mutex_lock(&dev->lock);
>>         if (dev->rdsstat == 0)
>>                 cadet_start_rds(dev);
>> -       if (dev->rdsin == dev->rdsout) {
>> +       while (dev->rdsin == dev->rdsout) {
>>                 if (file->f_flags & O_NONBLOCK) {
>>                         i = -EWOULDBLOCK;
>>                         goto unlock;
>>                 }
>>                 mutex_unlock(&dev->lock);
>> -               interruptible_sleep_on(&dev->read_queue);
>> +               if (wait_event_interruptible(&dev->read_queue,
>> +                                            dev->rdsin != dev->rdsout))
>> +                       return -EINTR;
>>                 mutex_lock(&dev->lock);
>>         }
>>         while (i < count && dev->rdsin != dev->rdsout)
>>
> 
> This will normally work, but now the mutex is no longer
> protecting the shared access to the dev->rdsin and
> dev->rdsout variables, which was evidently the intention
> of the author of the original code.
> 
> AFAICT, the possible result is a similar race as before:
> if once CPU changes dev->rdsin after the process in
> cadet_read dropped the lock, the wakeup may get lost.
> 
> It's quite possible this race never happens in practice,
> but the code is probably still wrong.
> 
> If you think we don't actually need the lock to check
> "dev->rdsin != dev->rdsout", the code can be simplified
> further, to
> 
> 	if ((dev->rdsin == dev->rdsout) && (file->f_flags & O_NONBLOCK)) {
> 	        return -EWOULDBLOCK;
> 	i = wait_event_interruptible(&dev->read_queue, dev->rdsin != dev->rdsout);
> 	if (i)
> 		return i;
> 	
> 	Arnd
> 

OK, let's try again. This patch is getting bigger and bigger, but it is always
nice to know that your ISA card that almost no one else in the world has is really,
really working well. :-)

Regards,

	Hans

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 545c04c..d27e8b2 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -270,6 +270,16 @@ reset_rds:
 	outb(inb(dev->io + 1) & 0x7f, dev->io + 1);
 }
 
+static bool cadet_has_rds_data(struct cadet *dev)
+{
+	bool result;
+	
+	mutex_lock(&dev->lock);
+	result = dev->rdsin != dev->rdsout;
+	mutex_unlock(&dev->lock);
+	return result;
+}
+
 
 static void cadet_handler(unsigned long data)
 {
@@ -279,13 +289,12 @@ static void cadet_handler(unsigned long data)
 	if (mutex_trylock(&dev->lock)) {
 		outb(0x3, dev->io);       /* Select RDS Decoder Control */
 		if ((inb(dev->io + 1) & 0x20) != 0)
-			printk(KERN_CRIT "cadet: RDS fifo overflow\n");
+			pr_err("cadet: RDS fifo overflow\n");
 		outb(0x80, dev->io);      /* Select RDS fifo */
+
 		while ((inb(dev->io) & 0x80) != 0) {
 			dev->rdsbuf[dev->rdsin] = inb(dev->io + 1);
-			if (dev->rdsin + 1 == dev->rdsout)
-				printk(KERN_WARNING "cadet: RDS buffer overflow\n");
-			else
+			if (dev->rdsin + 1 != dev->rdsout)
 				dev->rdsin++;
 		}
 		mutex_unlock(&dev->lock);
@@ -294,7 +303,7 @@ static void cadet_handler(unsigned long data)
 	/*
 	 * Service pending read
 	 */
-	if (dev->rdsin != dev->rdsout)
+	if (cadet_has_rds_data(dev))
 		wake_up_interruptible(&dev->read_queue);
 
 	/*
@@ -327,22 +336,21 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
 	mutex_lock(&dev->lock);
 	if (dev->rdsstat == 0)
 		cadet_start_rds(dev);
-	if (dev->rdsin == dev->rdsout) {
-		if (file->f_flags & O_NONBLOCK) {
-			i = -EWOULDBLOCK;
-			goto unlock;
-		}
-		mutex_unlock(&dev->lock);
-		interruptible_sleep_on(&dev->read_queue);
-		mutex_lock(&dev->lock);
-	}
+	mutex_unlock(&dev->lock);
+
+	if (!cadet_has_rds_data(dev) && (file->f_flags & O_NONBLOCK))
+		return -EWOULDBLOCK;
+	i = wait_event_interruptible(dev->read_queue, cadet_has_rds_data(dev));
+	if (i)
+		return i;
+
+	mutex_lock(&dev->lock);
 	while (i < count && dev->rdsin != dev->rdsout)
 		readbuf[i++] = dev->rdsbuf[dev->rdsout++];
+	mutex_unlock(&dev->lock);
 
 	if (i && copy_to_user(data, readbuf, i))
-		i = -EFAULT;
-unlock:
-	mutex_unlock(&dev->lock);
+		return -EFAULT;
 	return i;
 }
 
@@ -352,7 +360,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 {
 	strlcpy(v->driver, "ADS Cadet", sizeof(v->driver));
 	strlcpy(v->card, "ADS Cadet", sizeof(v->card));
-	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
+	strlcpy(v->bus_info, "ISA:radio-cadet", sizeof(v->bus_info));
 	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
 			  V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE;
 	v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -491,7 +499,7 @@ static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait
 			cadet_start_rds(dev);
 		mutex_unlock(&dev->lock);
 	}
-	if (dev->rdsin != dev->rdsout)
+	if (cadet_has_rds_data(dev))
 		res |= POLLIN | POLLRDNORM;
 	return res;
 }


  reply	other threads:[~2014-02-07 11:36 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-02 12:07 [PATCH, RFC 00/30] sleep_on removal Arnd Bergmann
2014-01-02 12:07 ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 01/30] ataflop: fix sleep_on races Arnd Bergmann
2014-01-02 12:27   ` Fwd: " Geert Uytterhoeven
2014-01-05  1:39     ` Michael Schmitz
2014-01-02 12:07 ` [PATCH, RFC 02/30] scsi: atari_scsi: fix sleep_on race Arnd Bergmann
2014-01-02 12:26   ` Fwd: " Geert Uytterhoeven
2014-01-05  1:35     ` Michael Schmitz
2014-01-12  1:40       ` Michael Schmitz
2014-01-12 20:00         ` Arnd Bergmann
2014-01-13  7:35           ` Michael Schmitz
2014-01-27  8:28           ` Michael Schmitz
2014-01-29 14:53             ` Arnd Bergmann
2014-01-30  7:54               ` schmitz
2014-01-30  7:57             ` Geert Uytterhoeven
2014-01-30  8:08               ` schmitz
2014-01-30  8:27                 ` Geert Uytterhoeven
2014-01-30  8:06             ` schmitz
2014-01-13  8:20         ` schmitz
2014-01-14  8:29         ` Michael Schmitz
2014-01-19 22:04           ` Michael Schmitz
2014-01-28  7:52     ` [PATCH 0/3] m68k/atari - Atari NCR5380 SCSI driver fixes Michael Schmitz
2014-01-28  8:02       ` Geert Uytterhoeven
2014-01-28  7:52     ` [PATCH 1/3] m68k/atari - atari_scsi: fix wait_event completion conditions Michael Schmitz
2014-01-28  7:52     ` [PATCH 2/3] m68k/atari - atari_scsi: change abort/reset return codes Michael Schmitz
2014-01-28  7:52     ` [PATCH 3/3] m68k/atari - atari_scsi lock fixes: punt if deadlocked Michael Schmitz
2014-01-28 23:55   ` [PATCH 0/3] m68k/atari - Atari NCR5380 SCSI driver fixes (resent) Michael Schmitz
2014-01-28 23:55   ` [PATCH 1/3] m68k/atari - atari_scsi: fix wait_event completion conditions Michael Schmitz
2014-01-28 23:55   ` [PATCH 2/3] m68k/atari - atari_scsi: change abort/reset return codes Michael Schmitz
2014-01-28 23:55   ` [PATCH 3/3] m68k/atari - atari_scsi lock fixes: punt if deadlocked Michael Schmitz
2014-01-02 12:07 ` [PATCH, RFC 03/30] DAC960: remove sleep_on usage Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 04/30] swim3: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 05/30] [media] omap_vout: avoid sleep_on race Arnd Bergmann
2014-01-17 10:23   ` Hans Verkuil
2014-02-26  9:03     ` Arnd Bergmann
2014-02-26  9:56       ` Hans Verkuil
2014-01-02 12:07 ` [PATCH, RFC 06/30] [media] usbvision: remove bogus sleep_on_timeout Arnd Bergmann
2014-01-17 10:26   ` Hans Verkuil
2014-01-02 12:07 ` [PATCH, RFC 07/30] [media] radio-cadet: avoid interruptible_sleep_on race Arnd Bergmann
2014-01-17 10:47   ` Hans Verkuil
2014-01-17 14:28     ` Arnd Bergmann
2014-02-07  9:32       ` Hans Verkuil
2014-02-07  9:47         ` Hans Verkuil
2014-02-07 10:17         ` Arnd Bergmann
2014-02-07 11:35           ` Hans Verkuil [this message]
2014-02-09 20:53             ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 08/30] [media] arv: fix sleep_on race Arnd Bergmann
2014-01-17 10:51   ` Hans Verkuil
2014-02-07  9:16     ` Hans Verkuil
2014-02-26  8:57       ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 09/30] staging: serqt_usb2: don't use sleep_on Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 10/30] staging: gdm72xx: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 11/30] staging: panel: " Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 12/30] parport: " Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 13/30] cris: sync_serial: remove interruptible_sleep_on Arnd Bergmann
2014-01-09  9:52   ` Jesper Nilsson
2014-01-02 12:07 ` [PATCH, RFC 14/30] tty/amiserial: avoid interruptible_sleep_on Arnd Bergmann
2014-01-02 12:27   ` Fwd: " Geert Uytterhoeven
2014-01-02 12:07 ` [PATCH, RFC 15/30] usbserial: stop using interruptible_sleep_on Arnd Bergmann
2014-01-02 21:36   ` Johan Hovold
2014-01-03 14:01     ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 16/30] tty: synclink: avoid sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 17/30] atm: nicstar: remove interruptible_sleep_on_timeout Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 18/30] atm: firestream: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 19/30] isdn: pcbit: " Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 20/30] isdn: hisax/elsa: fix sleep_on race in elsa FSM Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 21/30] isdn: divert, hysdn: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 15:01   ` Sergei Shtylyov
2014-01-02 16:48     ` Arnd Bergmann
2014-01-02 23:00       ` Sergei Shtylyov
2014-01-02 12:07 ` [PATCH, RFC 22/30] isdn: fix multiple sleep_on races Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 23/30] oss: msnd_pinnacle: avoid interruptible_sleep_on_timeout Arnd Bergmann
2014-01-02 12:07   ` Arnd Bergmann
2014-01-14 15:16   ` Takashi Iwai
2014-01-02 12:07 ` [PATCH, RFC 24/30] oss: midibuf: fix sleep_on races Arnd Bergmann
2014-01-02 12:07   ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 25/30] oss: vwsnd: avoid interruptible_sleep_on Arnd Bergmann
2014-01-02 12:07   ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 26/30] oss: dmasound: kill SLEEP() macro to avoid race Arnd Bergmann
2014-01-02 12:07   ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 27/30] oss: remove last sleep_on users Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 28/30] sgi-xp: open-code interruptible_sleep_on_timeout Arnd Bergmann
2014-01-02 16:04   ` Robin Holt
2014-01-02 12:07 ` [PATCH, RFC 29/30] char: nwbutton: open-code interruptible_sleep_on Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 30/30] sched: remove sleep_on() and friends Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52F4C51A.90002@xs4all.nl \
    --to=hverkuil@xs4all.nl \
    --cc=arnd@arndb.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=m.chehab@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.