aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-07-01 10:17:47 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-07-01 10:17:47 -0400
commit85ef06d1d252f6a2e73b678591ab71caad4667bb (patch)
treedc5cbc4f2e54f5b5b3f8653a595799e5fe0f2f18 /block
parent04bf7869ca0fd12009aee301cac2264a36df4d98 (diff)
block: flush MEDIA_CHANGE from drivers on close(2)
Currently, only open(2) is defined as the 'clearing' point. It has two roles - first, it's an acknowledgement from userland indicating that the event has been received and kernel can clear pending states and proceed to generate more events. Secondly, it's passed on to device drivers as a hint indicating that a synchronization point has been reached and it might want to take a deeper look at the device. The latter currently is only used by sr which uses two different mechanisms - GET_EVENT_MEDIA_STATUS_NOTIFICATION and TEST_UNIT_READY to discover events, where the former is lighter weight and safe to be used repeatedly but may not provide full coverage. Among other things, GET_EVENT can't detect media removal while TUR can. This patch makes close(2) - blkdev_put() - indicate clearing hint for MEDIA_CHANGE to drivers. disk_check_events() is renamed to disk_flush_events() and updated to take @mask for events to flush which is or'd to ev->clearing and will be passed to the driver on the next ->check_events() invocation. This change makes sr generate MEDIA_CHANGE when media is ejected from userland - e.g. with eject(1). Note: Given the current usage, it seems @clearing hint is needlessly complex. disk_clear_events() can simply clear all events and the hint can be boolean @flush. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'block')
-rw-r--r--block/genhd.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/block/genhd.c b/block/genhd.c
index 82d97c3594a8..fbd7605a5865 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1500,30 +1500,32 @@ void disk_unblock_events(struct gendisk *disk)
1500} 1500}
1501 1501
1502/** 1502/**
1503 * disk_check_events - schedule immediate event checking 1503 * disk_flush_events - schedule immediate event checking and flushing
1504 * @disk: disk to check events for 1504 * @disk: disk to check and flush events for
1505 * @mask: events to flush
1505 * 1506 *
1506 * Schedule immediate event checking on @disk if not blocked. 1507 * Schedule immediate event checking on @disk if not blocked. Events in
1508 * @mask are scheduled to be cleared from the driver. Note that this
1509 * doesn't clear the events from @disk->ev.
1507 * 1510 *
1508 * CONTEXT: 1511 * CONTEXT:
1509 * Don't care. Safe to call from irq context. 1512 * If @mask is non-zero must be called with bdev->bd_mutex held.
1510 */ 1513 */
1511void disk_check_events(struct gendisk *disk) 1514void disk_flush_events(struct gendisk *disk, unsigned int mask)
1512{ 1515{
1513 struct disk_events *ev = disk->ev; 1516 struct disk_events *ev = disk->ev;
1514 unsigned long flags;
1515 1517
1516 if (!ev) 1518 if (!ev)
1517 return; 1519 return;
1518 1520
1519 spin_lock_irqsave(&ev->lock, flags); 1521 spin_lock_irq(&ev->lock);
1522 ev->clearing |= mask;
1520 if (!ev->block) { 1523 if (!ev->block) {
1521 cancel_delayed_work(&ev->dwork); 1524 cancel_delayed_work(&ev->dwork);
1522 queue_delayed_work(system_nrt_wq, &ev->dwork, 0); 1525 queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
1523 } 1526 }
1524 spin_unlock_irqrestore(&ev->lock, flags); 1527 spin_unlock_irq(&ev->lock);
1525} 1528}
1526EXPORT_SYMBOL_GPL(disk_check_events);
1527 1529
1528/** 1530/**
1529 * disk_clear_events - synchronously check, clear and return pending events 1531 * disk_clear_events - synchronously check, clear and return pending events
@@ -1713,7 +1715,7 @@ static int disk_events_set_dfl_poll_msecs(const char *val,
1713 mutex_lock(&disk_events_mutex); 1715 mutex_lock(&disk_events_mutex);
1714 1716
1715 list_for_each_entry(ev, &disk_events, node) 1717 list_for_each_entry(ev, &disk_events, node)
1716 disk_check_events(ev->disk); 1718 disk_flush_events(ev->disk, 0);
1717 1719
1718 mutex_unlock(&disk_events_mutex); 1720 mutex_unlock(&disk_events_mutex);
1719 1721