diff options
author | Alan Stern | 2012-03-02 03:51:00 -0600 |
---|---|---|
committer | Greg Kroah-Hartman | 2012-03-19 10:57:59 -0500 |
commit | 25705e3a3e9f91280b51124a28e74418aff00c7d (patch) | |
tree | 4ae031ef034ef5fba5866821e08204a3826644d6 /block | |
parent | aaa136d348dc723f45667aa8b39eb58c7e7c4383 (diff) | |
download | kernel-common-25705e3a3e9f91280b51124a28e74418aff00c7d.tar.gz kernel-common-25705e3a3e9f91280b51124a28e74418aff00c7d.tar.xz kernel-common-25705e3a3e9f91280b51124a28e74418aff00c7d.zip |
Block: use a freezable workqueue for disk-event polling
commit 62d3c5439c534b0e6c653fc63e6d8c67be3a57b1 upstream.
This patch (as1519) fixes a bug in the block layer's disk-events
polling. The polling is done by a work routine queued on the
system_nrt_wq workqueue. Since that workqueue isn't freezable, the
polling continues even in the middle of a system sleep transition.
Obviously, polling a suspended drive for media changes and such isn't
a good thing to do; in the case of USB mass-storage devices it can
lead to real problems requiring device resets and even re-enumeration.
The patch fixes things by creating a new system-wide, non-reentrant,
freezable workqueue and using it for disk-events polling.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'block')
-rw-r--r-- | block/genhd.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/block/genhd.c b/block/genhd.c index 091429d2c7c..f6ecddb7995 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -1487,9 +1487,9 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now) | |||
1487 | intv = disk_events_poll_jiffies(disk); | 1487 | intv = disk_events_poll_jiffies(disk); |
1488 | set_timer_slack(&ev->dwork.timer, intv / 4); | 1488 | set_timer_slack(&ev->dwork.timer, intv / 4); |
1489 | if (check_now) | 1489 | if (check_now) |
1490 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); | 1490 | queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0); |
1491 | else if (intv) | 1491 | else if (intv) |
1492 | queue_delayed_work(system_nrt_wq, &ev->dwork, intv); | 1492 | queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv); |
1493 | out_unlock: | 1493 | out_unlock: |
1494 | spin_unlock_irqrestore(&ev->lock, flags); | 1494 | spin_unlock_irqrestore(&ev->lock, flags); |
1495 | } | 1495 | } |
@@ -1530,7 +1530,7 @@ void disk_check_events(struct gendisk *disk) | |||
1530 | spin_lock_irqsave(&ev->lock, flags); | 1530 | spin_lock_irqsave(&ev->lock, flags); |
1531 | if (!ev->block) { | 1531 | if (!ev->block) { |
1532 | cancel_delayed_work(&ev->dwork); | 1532 | cancel_delayed_work(&ev->dwork); |
1533 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); | 1533 | queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0); |
1534 | } | 1534 | } |
1535 | spin_unlock_irqrestore(&ev->lock, flags); | 1535 | spin_unlock_irqrestore(&ev->lock, flags); |
1536 | } | 1536 | } |
@@ -1568,7 +1568,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask) | |||
1568 | 1568 | ||
1569 | /* uncondtionally schedule event check and wait for it to finish */ | 1569 | /* uncondtionally schedule event check and wait for it to finish */ |
1570 | disk_block_events(disk); | 1570 | disk_block_events(disk); |
1571 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); | 1571 | queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0); |
1572 | flush_delayed_work(&ev->dwork); | 1572 | flush_delayed_work(&ev->dwork); |
1573 | __disk_unblock_events(disk, false); | 1573 | __disk_unblock_events(disk, false); |
1574 | 1574 | ||
@@ -1605,7 +1605,7 @@ static void disk_events_workfn(struct work_struct *work) | |||
1605 | 1605 | ||
1606 | intv = disk_events_poll_jiffies(disk); | 1606 | intv = disk_events_poll_jiffies(disk); |
1607 | if (!ev->block && intv) | 1607 | if (!ev->block && intv) |
1608 | queue_delayed_work(system_nrt_wq, &ev->dwork, intv); | 1608 | queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv); |
1609 | 1609 | ||
1610 | spin_unlock_irq(&ev->lock); | 1610 | spin_unlock_irq(&ev->lock); |
1611 | 1611 | ||