diff options
| -rw-r--r-- | block/genhd.c | 55 |
1 files changed, 24 insertions, 31 deletions
diff --git a/block/genhd.c b/block/genhd.c index 3f0933077642..ab0731d8976d 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
| @@ -1414,22 +1414,36 @@ static unsigned long disk_events_poll_jiffies(struct gendisk *disk) | |||
| 1414 | return msecs_to_jiffies(intv_msecs); | 1414 | return msecs_to_jiffies(intv_msecs); |
| 1415 | } | 1415 | } |
| 1416 | 1416 | ||
| 1417 | static void __disk_block_events(struct gendisk *disk, bool sync) | 1417 | /** |
| 1418 | * disk_block_events - block and flush disk event checking | ||
| 1419 | * @disk: disk to block events for | ||
| 1420 | * | ||
| 1421 | * On return from this function, it is guaranteed that event checking | ||
| 1422 | * isn't in progress and won't happen until unblocked by | ||
| 1423 | * disk_unblock_events(). Events blocking is counted and the actual | ||
| 1424 | * unblocking happens after the matching number of unblocks are done. | ||
| 1425 | * | ||
| 1426 | * Note that this intentionally does not block event checking from | ||
| 1427 | * disk_clear_events(). | ||
| 1428 | * | ||
| 1429 | * CONTEXT: | ||
| 1430 | * Might sleep. | ||
| 1431 | */ | ||
| 1432 | void disk_block_events(struct gendisk *disk) | ||
| 1418 | { | 1433 | { |
| 1419 | struct disk_events *ev = disk->ev; | 1434 | struct disk_events *ev = disk->ev; |
| 1420 | unsigned long flags; | 1435 | unsigned long flags; |
| 1421 | bool cancel; | 1436 | bool cancel; |
| 1422 | 1437 | ||
| 1438 | if (!ev) | ||
| 1439 | return; | ||
| 1440 | |||
| 1423 | spin_lock_irqsave(&ev->lock, flags); | 1441 | spin_lock_irqsave(&ev->lock, flags); |
| 1424 | cancel = !ev->block++; | 1442 | cancel = !ev->block++; |
| 1425 | spin_unlock_irqrestore(&ev->lock, flags); | 1443 | spin_unlock_irqrestore(&ev->lock, flags); |
| 1426 | 1444 | ||
| 1427 | if (cancel) { | 1445 | if (cancel) |
| 1428 | if (sync) | 1446 | cancel_delayed_work_sync(&disk->ev->dwork); |
| 1429 | cancel_delayed_work_sync(&disk->ev->dwork); | ||
| 1430 | else | ||
| 1431 | cancel_delayed_work(&disk->ev->dwork); | ||
| 1432 | } | ||
| 1433 | } | 1447 | } |
| 1434 | 1448 | ||
| 1435 | static void __disk_unblock_events(struct gendisk *disk, bool check_now) | 1449 | static void __disk_unblock_events(struct gendisk *disk, bool check_now) |
| @@ -1461,27 +1475,6 @@ out_unlock: | |||
| 1461 | } | 1475 | } |
| 1462 | 1476 | ||
| 1463 | /** | 1477 | /** |
| 1464 | * disk_block_events - block and flush disk event checking | ||
| 1465 | * @disk: disk to block events for | ||
| 1466 | * | ||
| 1467 | * On return from this function, it is guaranteed that event checking | ||
| 1468 | * isn't in progress and won't happen until unblocked by | ||
| 1469 | * disk_unblock_events(). Events blocking is counted and the actual | ||
| 1470 | * unblocking happens after the matching number of unblocks are done. | ||
| 1471 | * | ||
| 1472 | * Note that this intentionally does not block event checking from | ||
| 1473 | * disk_clear_events(). | ||
| 1474 | * | ||
| 1475 | * CONTEXT: | ||
| 1476 | * Might sleep. | ||
| 1477 | */ | ||
| 1478 | void disk_block_events(struct gendisk *disk) | ||
| 1479 | { | ||
| 1480 | if (disk->ev) | ||
| 1481 | __disk_block_events(disk, true); | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | /** | ||
| 1485 | * disk_unblock_events - unblock disk event checking | 1478 | * disk_unblock_events - unblock disk event checking |
| 1486 | * @disk: disk to unblock events for | 1479 | * @disk: disk to unblock events for |
| 1487 | * | 1480 | * |
| @@ -1554,7 +1547,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask) | |||
| 1554 | spin_unlock_irq(&ev->lock); | 1547 | spin_unlock_irq(&ev->lock); |
| 1555 | 1548 | ||
| 1556 | /* uncondtionally schedule event check and wait for it to finish */ | 1549 | /* uncondtionally schedule event check and wait for it to finish */ |
| 1557 | __disk_block_events(disk, true); | 1550 | disk_block_events(disk); |
| 1558 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); | 1551 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); |
| 1559 | flush_delayed_work(&ev->dwork); | 1552 | flush_delayed_work(&ev->dwork); |
| 1560 | __disk_unblock_events(disk, false); | 1553 | __disk_unblock_events(disk, false); |
| @@ -1672,7 +1665,7 @@ static ssize_t disk_events_poll_msecs_store(struct device *dev, | |||
| 1672 | if (intv < 0 && intv != -1) | 1665 | if (intv < 0 && intv != -1) |
| 1673 | return -EINVAL; | 1666 | return -EINVAL; |
| 1674 | 1667 | ||
| 1675 | __disk_block_events(disk, true); | 1668 | disk_block_events(disk); |
| 1676 | disk->ev->poll_msecs = intv; | 1669 | disk->ev->poll_msecs = intv; |
| 1677 | __disk_unblock_events(disk, true); | 1670 | __disk_unblock_events(disk, true); |
| 1678 | 1671 | ||
| @@ -1778,7 +1771,7 @@ static void disk_del_events(struct gendisk *disk) | |||
| 1778 | if (!disk->ev) | 1771 | if (!disk->ev) |
| 1779 | return; | 1772 | return; |
| 1780 | 1773 | ||
| 1781 | __disk_block_events(disk, true); | 1774 | disk_block_events(disk); |
| 1782 | 1775 | ||
| 1783 | mutex_lock(&disk_events_mutex); | 1776 | mutex_lock(&disk_events_mutex); |
| 1784 | list_del_init(&disk->ev->node); | 1777 | list_del_init(&disk->ev->node); |
