From: Oliver Neukum <oliver@neukum.org>
To: J <jhnlmn@yahoo.com>, linux-usb-devel@lists.sourceforge.net
Cc: linux-kernel@vger.kernel.org
Subject: Re: Possible race condition in usb-serial.c
Date: Wed, 20 Dec 2006 21:43:54 +0100 [thread overview]
Message-ID: <200612202143.55778.oliver@neukum.org> (raw)
In-Reply-To: <20061220193231.39261.qmail@web32911.mail.mud.yahoo.com>
[-- Attachment #1: Type: text/plain, Size: 1498 bytes --]
Am Mittwoch, 20. Dezember 2006 20:32 schrieb J:
> I am currently trying to fix a legacy 2.4 based USB
> driver and I am having various races,
> serial_open/usb_serial_disconnect is the most lively.
> I am not asking your help in fixing this old 2.4 junk
> (in fact I already fixed it using a global semaphore
> to protect serial_table).
Please send in a patch for 2.4. It's very important to have a
very reliable ultraconservative tested kernel available.
> But I still want to understand how the latest and
> greatest 2.6 driver is supposed to work so I can
> adopt some of the changes. At first I thought that
> the ref-counting will help, but then found that
> it does not fix much! The race is as lively
> as ever.
I suppose the last time I looked at that code, khubd still took
BKL. Or I overlooked the race. I have no serial devices since
the cell phone broke.
> Also I found that BKL/lock_kernel is compiled out in
> my configuration because it is not an SMP build.
>
> I see that in 2.6 BKL/lock_kernel are also optional
> for non-SMP builds. Is it true?
> If yes, then again, how this is supposed to work
> and avoid races?
Look closer. If you build with preemption, taking BKL disables preemption.
BKL is effective only until you schedule. On UP, without preemption
ordinary kernel code will not reenter. You need no lock that doesn't guard
against interrupts unless you schedule under these narrow conditions.
Could you test the attached patch against 2.6?
Regards
Oliver
[-- Attachment #2: usbserialtablerace.diff --]
[-- Type: text/x-diff, Size: 2557 bytes --]
--- drivers/usb/serial/usb-serial.c.alt 2006-12-17 14:57:40.000000000 +0100
+++ drivers/usb/serial/usb-serial.c 2006-12-20 18:22:41.000000000 +0100
@@ -59,6 +59,7 @@
static int debug;
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
+static DECLARE_MUTEX(table_lock); /* lock for serial_table */
static LIST_HEAD(usb_serial_driver_list);
struct usb_serial *usb_serial_get_by_index(unsigned index)
@@ -176,7 +177,9 @@
dbg("%s", __FUNCTION__);
/* get the serial object associated with this tty pointer */
+ mutex_lock(&table_lock);
serial = usb_serial_get_by_index(tty->index);
+ mutex_unlock(&table_lock);
if (!serial) {
tty->driver_data = NULL;
return -ENODEV;
@@ -265,7 +268,9 @@
}
mutex_unlock(&port->mutex);
+ mutex_lock(&table_lock);
usb_serial_put(port->serial);
+ mutex_unlock(&table_lock);
}
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
@@ -771,7 +776,9 @@
num_ports = type->num_ports;
}
+ mutex_lock(&table_lock);
if (get_free_serial (serial, num_ports, &minor) == NULL) {
+ mutex_unlock(&table_lock);
dev_err(&interface->dev, "No more free serial devices\n");
kfree (serial);
return -ENOMEM;
@@ -921,6 +928,7 @@
if (retval > 0) {
/* quietly accept this device, but don't bind to a serial port
* as it's about to disappear */
+ mutex_unlock(&table_lock);
goto exit;
}
}
@@ -941,6 +949,7 @@
"continuing\n");
}
+ mutex_unlock(&table_lock);
usb_serial_console_init (debug, minor);
exit:
@@ -980,6 +989,7 @@
/* return the minor range that this device had */
return_serial (serial);
+ mutex_unlock(&table_lock);
/* free up any memory that we allocated */
for (i = 0; i < serial->num_port_pointers; ++i)
@@ -999,6 +1009,7 @@
dbg ("%s", __FUNCTION__);
usb_set_intfdata (interface, NULL);
+ mutex_lock(&table_lock);
if (serial) {
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
@@ -1009,6 +1020,7 @@
* cause it to be cleaned up */
usb_serial_put(serial);
}
+ mutex_unlock(&table_lock);
dev_info(dev, "device disconnected\n");
}
@@ -1060,6 +1072,7 @@
usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
usb_serial_tty_driver->init_termios = tty_std_termios;
usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ init_MUTEX(&table_lock);
tty_set_operations(usb_serial_tty_driver, &serial_ops);
result = tty_register_driver(usb_serial_tty_driver);
if (result) {
next prev parent reply other threads:[~2006-12-20 20:42 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-19 19:21 Possible race condition in usb-serial.c J
2006-12-19 20:15 ` Oliver Neukum
2006-12-19 22:33 ` J
2006-12-20 9:47 ` Oliver Neukum
2006-12-20 15:10 ` [linux-usb-devel] " Alan Stern
2006-12-20 21:02 ` Oliver Neukum
2006-12-20 19:32 ` J
2006-12-20 20:43 ` Greg KH
2006-12-20 22:39 ` J
2006-12-20 22:52 ` Greg KH
2006-12-20 20:43 ` Oliver Neukum [this message]
2006-12-20 22:24 ` J
2006-12-22 18:14 ` Oliver Neukum
2006-12-22 19:08 ` J
2006-12-22 19:59 ` Oliver Neukum
2006-12-22 20:51 ` J
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=200612202143.55778.oliver@neukum.org \
--to=oliver@neukum.org \
--cc=jhnlmn@yahoo.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb-devel@lists.sourceforge.net \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox