aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/genhd.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/block/genhd.c b/block/genhd.c
index 9a289d7c84bb..3993ebf4135f 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -35,6 +35,8 @@ static DEFINE_IDR(ext_devt_idr);
35 35
36static struct device_type disk_type; 36static struct device_type disk_type;
37 37
38static void disk_check_events(struct disk_events *ev,
39 unsigned int *clearing_ptr);
38static void disk_alloc_events(struct gendisk *disk); 40static void disk_alloc_events(struct gendisk *disk);
39static void disk_add_events(struct gendisk *disk); 41static void disk_add_events(struct gendisk *disk);
40static void disk_del_events(struct gendisk *disk); 42static void disk_del_events(struct gendisk *disk);
@@ -1549,6 +1551,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
1549 const struct block_device_operations *bdops = disk->fops; 1551 const struct block_device_operations *bdops = disk->fops;
1550 struct disk_events *ev = disk->ev; 1552 struct disk_events *ev = disk->ev;
1551 unsigned int pending; 1553 unsigned int pending;
1554 unsigned int clearing = mask;
1552 1555
1553 if (!ev) { 1556 if (!ev) {
1554 /* for drivers still using the old ->media_changed method */ 1557 /* for drivers still using the old ->media_changed method */
@@ -1558,34 +1561,53 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
1558 return 0; 1561 return 0;
1559 } 1562 }
1560 1563
1561 /* tell the workfn about the events being cleared */ 1564 disk_block_events(disk);
1565
1566 /*
1567 * store the union of mask and ev->clearing on the stack so that the
1568 * race with disk_flush_events does not cause ambiguity (ev->clearing
1569 * can still be modified even if events are blocked).
1570 */
1562 spin_lock_irq(&ev->lock); 1571 spin_lock_irq(&ev->lock);
1563 ev->clearing |= mask; 1572 clearing |= ev->clearing;
1573 ev->clearing = 0;
1564 spin_unlock_irq(&ev->lock); 1574 spin_unlock_irq(&ev->lock);
1565 1575
1566 /* uncondtionally schedule event check and wait for it to finish */ 1576 disk_check_events(ev, &clearing);
1567 disk_block_events(disk); 1577 /*
1568 queue_delayed_work(system_freezable_wq, &ev->dwork, 0); 1578 * if ev->clearing is not 0, the disk_flush_events got called in the
1569 flush_delayed_work(&ev->dwork); 1579 * middle of this function, so we want to run the workfn without delay.
1570 __disk_unblock_events(disk, false); 1580 */
1581 __disk_unblock_events(disk, ev->clearing ? true : false);
1571 1582
1572 /* then, fetch and clear pending events */ 1583 /* then, fetch and clear pending events */
1573 spin_lock_irq(&ev->lock); 1584 spin_lock_irq(&ev->lock);
1574 WARN_ON_ONCE(ev->clearing & mask); /* cleared by workfn */
1575 pending = ev->pending & mask; 1585 pending = ev->pending & mask;
1576 ev->pending &= ~mask; 1586 ev->pending &= ~mask;
1577 spin_unlock_irq(&ev->lock); 1587 spin_unlock_irq(&ev->lock);
1588 WARN_ON_ONCE(clearing & mask);
1578 1589
1579 return pending; 1590 return pending;
1580} 1591}
1581 1592
1593/*
1594 * Separate this part out so that a different pointer for clearing_ptr can be
1595 * passed in for disk_clear_events.
1596 */
1582static void disk_events_workfn(struct work_struct *work) 1597static void disk_events_workfn(struct work_struct *work)
1583{ 1598{
1584 struct delayed_work *dwork = to_delayed_work(work); 1599 struct delayed_work *dwork = to_delayed_work(work);
1585 struct disk_events *ev = container_of(dwork, struct disk_events, dwork); 1600 struct disk_events *ev = container_of(dwork, struct disk_events, dwork);
1601
1602 disk_check_events(ev, &ev->clearing);
1603}
1604
1605static void disk_check_events(struct disk_events *ev,
1606 unsigned int *clearing_ptr)
1607{
1586 struct gendisk *disk = ev->disk; 1608 struct gendisk *disk = ev->disk;
1587 char *envp[ARRAY_SIZE(disk_uevents) + 1] = { }; 1609 char *envp[ARRAY_SIZE(disk_uevents) + 1] = { };
1588 unsigned int clearing = ev->clearing; 1610 unsigned int clearing = *clearing_ptr;
1589 unsigned int events; 1611 unsigned int events;
1590 unsigned long intv; 1612 unsigned long intv;
1591 int nr_events = 0, i; 1613 int nr_events = 0, i;
@@ -1598,7 +1620,7 @@ static void disk_events_workfn(struct work_struct *work)
1598 1620
1599 events &= ~ev->pending; 1621 events &= ~ev->pending;
1600 ev->pending |= events; 1622 ev->pending |= events;
1601 ev->clearing &= ~clearing; 1623 *clearing_ptr &= ~clearing;
1602 1624
1603 intv = disk_events_poll_jiffies(disk); 1625 intv = disk_events_poll_jiffies(disk);
1604 if (!ev->block && intv) 1626 if (!ev->block && intv)