Re: [PATCH] usb: usbfs: Fix deadlock of khubd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Mar 06, 2010 at 08:52:24AM -0800, Dmitry Torokhov wrote:
> On Sat, Mar 06, 2010 at 11:27:01AM -0500, Alan Stern wrote:
> > On Sat, 6 Mar 2010, Oliver Neukum wrote:
> > 
> > > Am Samstag, 6. März 2010 16:34:31 schrieb Alan Stern:
> > > > On Sat, 6 Mar 2010, Oliver Neukum wrote:
> > > 
> > > > > The caller of usbfs_conn_disc_event() already holds usbfs_mutex.
> > > > > Don't take it again.
> > > > 
> > > > That's not true.  The caller holds usbfs_mutex only when the action is 
> > > > USB_DEVICE_REMOVE.  Not when the action is USB_DEVICE_ADD or USB_BUS_*.
> > > 
> > > Right. That's what you get for wanting a quick fix. What do you
> > > propose?
> > 
> > Guard conndiscevcnt and file->private_data with a separate static 
> > mutex instead of usbfs_mutex.
> > 
> 
> If you think it is important use atomic here, however I do not think it
> is realistically needed. If we have 2 devices appearing and disappearing
> at the same time we may "skip" version but still anyone issuing select()
> before that will get woken up and will see both in /proc.
> 
> > Incidentally, what's supposed to happen if more than one thread tries
> > to poll the same file descriptor simultaneously?  Do you really want
> > the first thread to wait only until the first event while the second
> > thread is forced to wait for a second event?
> 
> I think it is like with read and write - if userspace does not do proper
> locking while accessing the same fd it gets to hold both pieces. So
> again, no reason for using mutex there either.
> 
> Also, if you use file->f_version you would not need kallocing that
> single integer and then having to free it. See how it is done in input.
> 

OK, the patch below unwedges vmware-usb-arbitrator that tries to access
/proc/bus/input/devices (it doers what input core does now), however
khubd is still wedged with the following lockdep output:

[  222.934310] usb 5-1: new full speed USB device using uhci_hcd and address 2
[  223.099666] usb 5-1: New USB device found, idVendor=04b3, idProduct=3016
[  223.099670] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  223.099674] usb 5-1: Product: USB 1.1 2 port downstream low-power hub
[  223.099676] usb 5-1: Manufacturer: Lite-On Tech
[  223.103137] hub 5-1:1.0: USB hub found
[  223.104336] hub 5-1:1.0: 4 ports detected
[  223.383357] usb 5-1.3: new low speed USB device using uhci_hcd and address 3
[  223.517352] usb 5-1.3: New USB device found, idVendor=04b3, idProduct=3018
[  223.517356] usb 5-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  223.517360] usb 5-1.3: Product: IBM USB Keyboard with UltraNav
[  223.517362] usb 5-1.3: Manufacturer: Lite-On Tech
[  223.536770] input: Lite-On Tech IBM USB Keyboard with UltraNav as /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1.3/5-1.3:1.0/input/input12
[  223.540879] generic-usb 0003:04B3:3018.0001: input,hidraw0: USB HID v1.10 Keyboard [Lite-On Tech IBM USB Keyboard with UltraNav] on usb-0000:00:1d.0-1.3/input0
[  223.569291] input: Lite-On Tech IBM USB Keyboard with UltraNav as /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1.3/5-1.3:1.1/input/input13
[  223.569535] generic-usb 0003:04B3:3018.0002: input,hidraw1: USB HID v1.10 Device [Lite-On Tech IBM USB Keyboard with UltraNav] on usb-0000:00:1d.0-1.3/input1
[  223.750369] usb 5-1.4: new low speed USB device using uhci_hcd and address 4
[  223.897343] usb 5-1.4: New USB device found, idVendor=06cb, idProduct=0009
[  223.897347] usb 5-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  223.897350] usb 5-1.4: Product: Composite TouchPad / TrackPoint
[  223.897353] usb 5-1.4: Manufacturer: Synaptics Inc.
[  223.919655] input: Synaptics Inc. Composite TouchPad / TrackPoint as /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1.4/5-1.4:1.0/input/input14
[  223.919836] generic-usb 0003:06CB:0009.0003: input,hidraw2: USB HID v1.00 Mouse [Synaptics Inc. Composite TouchPad / TrackPoint] on usb-0000:00:1d.0-1.4/input0
[  223.940807] input: Synaptics Inc. Composite TouchPad / TrackPoint as /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1.4/5-1.4:1.1/input/input15
[  223.941089] generic-usb 0003:06CB:0009.0004: input,hidraw3: USB HID v1.00 Mouse [Synaptics Inc. Composite TouchPad / TrackPoint] on usb-0000:00:1d.0-1.4/input1
[  248.704305] usb 5-1: USB disconnect, address 2
[  248.704317] usb 5-1.3: USB disconnect, address 3
[  248.727933] 
[  248.727935] =======================================================
[  248.727939] [ INFO: possible circular locking dependency detected ]
[  248.727942] 2.6.33 #233
[  248.727943] -------------------------------------------------------
[  248.727946] khubd/27 is trying to acquire lock:
[  248.727948]  ((usb_notifier_list).rwsem){.+.+.+}, at: [<ffffffff8106f480>] __blocking_notifier_call_chain+0x40/0x80
[  248.727959] 
[  248.727959] but task is already holding lock:
[  248.727961]  (usbfs_mutex){+.+...}, at: [<ffffffff8136e83a>] usb_notify_remove_device+0x1a/0x50
[  248.727969] 
[  248.727970] which lock already depends on the new lock.
[  248.727971] 
[  248.727973] 
[  248.727974] the existing dependency chain (in reverse order) is:
[  248.727977] 
[  248.727977] -> #1 (usbfs_mutex){+.+...}:
[  248.727982]        [<ffffffff8107f222>] check_prev_add+0x242/0x570
[  248.727988]        [<ffffffff8107fba4>] validate_chain+0x654/0x750
[  248.727992]        [<ffffffff8107ffc7>] __lock_acquire+0x327/0x4c0
[  248.727996]        [<ffffffff810801f9>] lock_acquire+0x99/0x140
[  248.728001]        [<ffffffff81478375>] __mutex_lock_common+0x65/0x4a0
[  248.728006]        [<ffffffff8147888e>] mutex_lock_nested+0x3e/0x50
[  248.728008]        [<ffffffff8136f9b2>] usbfs_conn_disc_event+0x12/0x40
[  248.728008]        [<ffffffff813710a4>] usbfs_notify+0xa4/0x240
[  248.728008]        [<ffffffff8147df47>] notifier_call_chain+0x47/0x90
[  248.728008]        [<ffffffff8106f495>] __blocking_notifier_call_chain+0x55/0x80
[  248.728008]        [<ffffffff8106f4d1>] blocking_notifier_call_chain+0x11/0x20
[  248.728008]        [<ffffffff8136e7f8>] usb_notify_add_bus+0x18/0x20
[  248.728008]        [<ffffffff8135f089>] usb_register_bus+0x69/0xd0
[  248.728008]        [<ffffffff81360fd8>] usb_add_hcd+0xa8/0x420
[  248.728008]        [<ffffffff8136fcfd>] usb_hcd_pci_probe+0x15d/0x310
[  248.728008]        [<ffffffff8124d1b2>] local_pci_probe+0x12/0x20
[  248.728008]        [<ffffffff8124e9e0>] pci_device_probe+0x80/0xb0
[  248.728008]        [<ffffffff81303bd7>] really_probe+0x67/0x170
[  248.728008]        [<ffffffff81303d20>] driver_probe_device+0x40/0x70
[  248.728008]        [<ffffffff81303deb>] __driver_attach+0x9b/0xa0
[  248.728008]        [<ffffffff81303054>] bus_for_each_dev+0x64/0x90
[  248.728008]        [<ffffffff81303a59>] driver_attach+0x19/0x20
[  248.728008]        [<ffffffff8130331c>] bus_add_driver+0xdc/0x280
[  248.728008]        [<ffffffff813040ff>] driver_register+0x6f/0x130
[  248.728008]        [<ffffffff8124e351>] __pci_register_driver+0x61/0xe0
[  248.728008]        [<ffffffff818bb25e>] ehci_hcd_init+0x68/0x76
[  248.728008]        [<ffffffff810001d7>] do_one_initcall+0x37/0x190
[  248.728008]        [<ffffffff8189274e>] do_basic_setup+0x54/0x66
[  248.728008]        [<ffffffff818927f5>] kernel_init+0x95/0x10d
[  248.728008]        [<ffffffff81003dd4>] kernel_thread_helper+0x4/0x10
[  248.728008] 
[  248.728008] -> #0 ((usb_notifier_list).rwsem){.+.+.+}:
[  248.728008]        [<ffffffff8107f51e>] check_prev_add+0x53e/0x570
[  248.728008]        [<ffffffff8107fba4>] validate_chain+0x654/0x750
[  248.728008]        [<ffffffff8107ffc7>] __lock_acquire+0x327/0x4c0
[  248.728008]        [<ffffffff810801f9>] lock_acquire+0x99/0x140
[  248.728008]        [<ffffffff81478be2>] down_read+0x42/0x60
[  248.728008]        [<ffffffff8106f480>] __blocking_notifier_call_chain+0x40/0x80
[  248.728008]        [<ffffffff8106f4d1>] blocking_notifier_call_chain+0x11/0x20
[  248.728008]        [<ffffffff8136e84e>] usb_notify_remove_device+0x2e/0x50
[  248.728008]        [<ffffffff8136e931>] generic_disconnect+0x11/0x30
[  248.728008]        [<ffffffff81365e49>] usb_unbind_device+0x29/0x50
[  248.728008]        [<ffffffff813038c0>] __device_release_driver+0x70/0xe0
[  248.728008]        [<ffffffff81303a28>] device_release_driver+0x28/0x40
[  248.728008]        [<ffffffff81302a8c>] bus_remove_device+0xac/0xe0
[  248.728008]        [<ffffffff81300df7>] device_del+0x127/0x1a0
[  248.728008]        [<ffffffff8135bfbc>] usb_disconnect+0xec/0x160
[  248.728008]        [<ffffffff8135bf87>] usb_disconnect+0xb7/0x160
[  248.728008]        [<ffffffff8135c77e>] hub_port_connect_change+0x8e/0x9f0
[  248.728008]        [<ffffffff8135e2f3>] hub_events+0x3c3/0x580
[  248.728008]        [<ffffffff8135e505>] hub_thread+0x55/0x190
[  248.728008]        [<ffffffff8106908e>] kthread+0x8e/0xa0
[  248.728008]        [<ffffffff81003dd4>] kernel_thread_helper+0x4/0x10
[  248.728008] 
[  248.728008] other info that might help us debug this:
[  248.728008] 
[  248.728008] 1 lock held by khubd/27:
[  248.728216]  #0:  (usbfs_mutex){+.+...}, at: [<ffffffff8136e83a>] usb_notify_remove_device+0x1a/0x50
[  248.728218] 
[  248.728218] stack backtrace:
[  248.728218] Pid: 27, comm: khubd Tainted: P           2.6.33 #233
[  248.728218] Call Trace:
[  248.728218]  [<ffffffff8107db69>] print_circular_bug+0xe9/0xf0
[  248.728218]  [<ffffffff8107f51e>] check_prev_add+0x53e/0x570
[  248.728218]  [<ffffffff8107ffc7>] ? __lock_acquire+0x327/0x4c0
[  248.728218]  [<ffffffff8107fba4>] validate_chain+0x654/0x750
[  248.728218]  [<ffffffff8107ffc7>] ? __lock_acquire+0x327/0x4c0
[  248.728218]  [<ffffffff8107ffc7>] __lock_acquire+0x327/0x4c0
[  248.728218]  [<ffffffff810801f9>] lock_acquire+0x99/0x140
[  248.728218]  [<ffffffff8106f480>] ? __blocking_notifier_call_chain+0x40/0x80
[  248.728218]  [<ffffffff81478680>] ? __mutex_lock_common+0x370/0x4a0
[  248.728218]  [<ffffffff8136e83a>] ? usb_notify_remove_device+0x1a/0x50
[  248.728218]  [<ffffffff81478be2>] down_read+0x42/0x60
[  248.728218]  [<ffffffff8106f480>] ? __blocking_notifier_call_chain+0x40/0x80
[  248.728218]  [<ffffffff8106f480>] __blocking_notifier_call_chain+0x40/0x80
[  248.728218]  [<ffffffff8106f4d1>] blocking_notifier_call_chain+0x11/0x20
[  248.728218]  [<ffffffff8136e84e>] usb_notify_remove_device+0x2e/0x50
[  248.728218]  [<ffffffff8136e931>] generic_disconnect+0x11/0x30
[  248.728218]  [<ffffffff81365e49>] usb_unbind_device+0x29/0x50
[  248.728218]  [<ffffffff813038c0>] __device_release_driver+0x70/0xe0
[  248.728218]  [<ffffffff81303a28>] device_release_driver+0x28/0x40
[  248.728218]  [<ffffffff81302a8c>] bus_remove_device+0xac/0xe0
[  248.728218]  [<ffffffff81300df7>] device_del+0x127/0x1a0
[  248.728218]  [<ffffffff8135bfbc>] usb_disconnect+0xec/0x160
[  248.728218]  [<ffffffff8135bf87>] usb_disconnect+0xb7/0x160
[  248.728218]  [<ffffffff8135c77e>] hub_port_connect_change+0x8e/0x9f0
[  248.728218]  [<ffffffff81478309>] ? mutex_unlock+0x9/0x10
[  248.728218]  [<ffffffff8135e2f3>] hub_events+0x3c3/0x580
[  248.728218]  [<ffffffff8147a2ed>] ? _raw_spin_unlock_irqrestore+0x5d/0x70
[  248.728218]  [<ffffffff8135e505>] hub_thread+0x55/0x190
[  248.728218]  [<ffffffff810695a0>] ? autoremove_wake_function+0x0/0x40
[  248.728218]  [<ffffffff8135e4b0>] ? hub_thread+0x0/0x190
[  248.728218]  [<ffffffff8106908e>] kthread+0x8e/0xa0
[  248.728218]  [<ffffffff81003dd4>] kernel_thread_helper+0x4/0x10
[  248.728218]  [<ffffffff8147aa80>] ? restore_args+0x0/0x30
[  248.728218]  [<ffffffff81069000>] ? kthread+0x0/0xa0
[  248.728218]  [<ffffffff81003dd0>] ? kernel_thread_helper+0x0/0x10
[  480.551213] INFO: task khubd:27 blocked for more than 120 seconds.
[  480.551223] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  480.551231] khubd         D 0000000000000202     0    27      2 0x00000000
[  480.551247]  ffff88011ba29960 0000000000000046 ffff88000260eec0 ffff88011ba20000
[  480.551290]  ffff88011ba28000 ffff88011ba29fd8 ffff88011ba29fd8 ffff88011ba20000
[  480.551306]  ffff88011ba29fd8 0000000000013d80 0000000000013d80 0000000000013d80
[  480.551328] Call Trace:
[  480.551349]  [<ffffffff814784b1>] __mutex_lock_common+0x1a1/0x4a0
[  480.551365]  [<ffffffff8136f9b2>] ? usbfs_conn_disc_event+0x12/0x40
[  480.551380]  [<ffffffff8107eb7d>] ? trace_hardirqs_on+0xd/0x10
[  480.551394]  [<ffffffff8136f9b2>] ? usbfs_conn_disc_event+0x12/0x40
[  480.551410]  [<ffffffff8147888e>] mutex_lock_nested+0x3e/0x50
[  480.551421]  [<ffffffff8136f9b2>] usbfs_conn_disc_event+0x12/0x40
[  480.551434]  [<ffffffff813710a4>] usbfs_notify+0xa4/0x240
[  480.551447]  [<ffffffff8147df47>] notifier_call_chain+0x47/0x90
[  480.551460]  [<ffffffff8106f495>] __blocking_notifier_call_chain+0x55/0x80
[  480.551473]  [<ffffffff8106f4d1>] blocking_notifier_call_chain+0x11/0x20
[  480.551484]  [<ffffffff8136e84e>] usb_notify_remove_device+0x2e/0x50
[  480.551495]  [<ffffffff8136e931>] generic_disconnect+0x11/0x30
[  480.551509]  [<ffffffff81365e49>] usb_unbind_device+0x29/0x50
[  480.551523]  [<ffffffff813038c0>] __device_release_driver+0x70/0xe0
[  480.551536]  [<ffffffff81303a28>] device_release_driver+0x28/0x40
[  480.551550]  [<ffffffff81302a8c>] bus_remove_device+0xac/0xe0
[  480.551562]  [<ffffffff81300df7>] device_del+0x127/0x1a0
[  480.551574]  [<ffffffff8135bfbc>] usb_disconnect+0xec/0x160
[  480.551586]  [<ffffffff8135bf87>] usb_disconnect+0xb7/0x160
[  480.551598]  [<ffffffff8135c77e>] hub_port_connect_change+0x8e/0x9f0
[  480.551610]  [<ffffffff81478309>] ? mutex_unlock+0x9/0x10
[  480.551625]  [<ffffffff8135e2f3>] hub_events+0x3c3/0x580
[  480.551638]  [<ffffffff8147a2ed>] ? _raw_spin_unlock_irqrestore+0x5d/0x70
[  480.551651]  [<ffffffff8135e505>] hub_thread+0x55/0x190
[  480.551666]  [<ffffffff810695a0>] ? autoremove_wake_function+0x0/0x40
[  480.551678]  [<ffffffff8135e4b0>] ? hub_thread+0x0/0x190
[  480.551689]  [<ffffffff8106908e>] kthread+0x8e/0xa0
[  480.551707]  [<ffffffff81003dd4>] kernel_thread_helper+0x4/0x10
[  480.551721]  [<ffffffff8147aa80>] ? restore_args+0x0/0x30
[  480.551735]  [<ffffffff81069000>] ? kthread+0x0/0xa0
[  480.551746]  [<ffffffff81003dd0>] ? kernel_thread_helper+0x0/0x10

-- 
Dmitry

USB: simplify /proc/bus/usb/devices handling

From: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>

There is no need to allocate a single integer for usbfs state counter
in file structure, just use f_version. Also, there is not need for
locking, if program decides to poll from 2 threads on the same descriptor
it gets to hold both pieces, same as with read and write.

Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx>
---

 drivers/usb/core/devices.c |   41 ++++-------------------------------------
 1 files changed, 4 insertions(+), 37 deletions(-)


diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index c83c975..b776bef 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -628,46 +628,15 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
 	return total_written;
 }
 
-/* Kernel lock for "lastev" protection */
 static unsigned int usb_device_poll(struct file *file,
 				    struct poll_table_struct *wait)
 {
-	struct usb_device_status *st;
-	unsigned int mask = 0;
-
-	mutex_lock(&usbfs_mutex);
-	st = file->private_data;
-	if (!st) {
-		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-		if (!st) {
-			mutex_unlock(&usbfs_mutex);
-			return POLLIN;
-		}
-
-		st->lastev = conndiscevcnt;
-		file->private_data = st;
-		mask = POLLIN;
+	poll_wait(file, &deviceconndiscwq, wait);
+	if (file->f_version != conndiscevcnt) {
+		file->f_version = conndiscevcnt;
+		return POLLIN | POLLRDNORM;
 	}
 
-	if (file->f_mode & FMODE_READ)
-		poll_wait(file, &deviceconndiscwq, wait);
-	if (st->lastev != conndiscevcnt)
-		mask |= POLLIN;
-	st->lastev = conndiscevcnt;
-	mutex_unlock(&usbfs_mutex);
-	return mask;
-}
-
-static int usb_device_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static int usb_device_release(struct inode *inode, struct file *file)
-{
-	kfree(file->private_data);
-	file->private_data = NULL;
 	return 0;
 }
 
@@ -699,6 +668,4 @@ const struct file_operations usbfs_devices_fops = {
 	.llseek =	usb_device_lseek,
 	.read =		usb_device_read,
 	.poll =		usb_device_poll,
-	.open =		usb_device_open,
-	.release =	usb_device_release,
 };
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux