CHROMIUM: block: Remove deadlock in disk_clear_events
authorDerek Basehore <dbasehore@chromium.org>
Thu, 11 Oct 2012 21:18:34 +0000 (14:18 -0700)
committerGerrit <chrome-bot@google.com>
Fri, 12 Oct 2012 01:28:29 +0000 (18:28 -0700)
In disk_clear_events, do not put work on system_nrt_freezable_wq. Instead, put
it on system_nrt_wq.

There is a race between probing a usb and suspending the device. Since probing a
usb calls disk_clear_events, which puts work on a frozen workqueue, probing
cannot finish after the workqueue is frozen. However, suspending cannot finish
until the usb probe is finished, so we get a deadlock.

BUG=chrome-os-partner:14892, chromium-os:35228
TEST=suspend resume with usb device plugged in

Change-Id: Ife0103207c84eab162c93781d0d986eae50475d8
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/35324
Reviewed-by: Mandeep Singh Baines <msb@chromium.org>
block/genhd.c

index 9cf5583..9c528d8 100644 (file)
@@ -1563,7 +1563,13 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
 
        /* uncondtionally schedule event check and wait for it to finish */
        disk_block_events(disk);
-       queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+       /* We need to put the work on system_nrt_wq here since there is a
+        * deadlock that happens while probing a usb device while suspending. If
+        * we put work on a freezable worqueue here, a usb probe will wait here
+        * until the workqueue is unfrozen during suspend. Since suspend waits
+        * on all probes to complete, we have a deadlock
+        */
+       queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
        flush_delayed_work(&ev->dwork);
        __disk_unblock_events(disk, false);