aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorAlan Stern2012-03-02 03:51:00 -0600
committerGreg Kroah-Hartman2012-03-19 10:57:59 -0500
commit25705e3a3e9f91280b51124a28e74418aff00c7d (patch)
tree4ae031ef034ef5fba5866821e08204a3826644d6 /block
parentaaa136d348dc723f45667aa8b39eb58c7e7c4383 (diff)
downloadkernel-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.c10
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);
1493out_unlock: 1493out_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