aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/genhd.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/block/genhd.c b/block/genhd.c
index ab0731d8976d..3608289c8ecd 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1371,6 +1371,7 @@ struct disk_events {
1371 struct gendisk *disk; /* the associated disk */ 1371 struct gendisk *disk; /* the associated disk */
1372 spinlock_t lock; 1372 spinlock_t lock;
1373 1373
1374 struct mutex block_mutex; /* protects blocking */
1374 int block; /* event blocking depth */ 1375 int block; /* event blocking depth */
1375 unsigned int pending; /* events already sent out */ 1376 unsigned int pending; /* events already sent out */
1376 unsigned int clearing; /* events being cleared */ 1377 unsigned int clearing; /* events being cleared */
@@ -1438,12 +1439,20 @@ void disk_block_events(struct gendisk *disk)
1438 if (!ev) 1439 if (!ev)
1439 return; 1440 return;
1440 1441
1442 /*
1443 * Outer mutex ensures that the first blocker completes canceling
1444 * the event work before further blockers are allowed to finish.
1445 */
1446 mutex_lock(&ev->block_mutex);
1447
1441 spin_lock_irqsave(&ev->lock, flags); 1448 spin_lock_irqsave(&ev->lock, flags);
1442 cancel = !ev->block++; 1449 cancel = !ev->block++;
1443 spin_unlock_irqrestore(&ev->lock, flags); 1450 spin_unlock_irqrestore(&ev->lock, flags);
1444 1451
1445 if (cancel) 1452 if (cancel)
1446 cancel_delayed_work_sync(&disk->ev->dwork); 1453 cancel_delayed_work_sync(&disk->ev->dwork);
1454
1455 mutex_unlock(&ev->block_mutex);
1447} 1456}
1448 1457
1449static void __disk_unblock_events(struct gendisk *disk, bool check_now) 1458static void __disk_unblock_events(struct gendisk *disk, bool check_now)
@@ -1751,6 +1760,7 @@ static void disk_add_events(struct gendisk *disk)
1751 INIT_LIST_HEAD(&ev->node); 1760 INIT_LIST_HEAD(&ev->node);
1752 ev->disk = disk; 1761 ev->disk = disk;
1753 spin_lock_init(&ev->lock); 1762 spin_lock_init(&ev->lock);
1763 mutex_init(&ev->block_mutex);
1754 ev->block = 1; 1764 ev->block = 1;
1755 ev->poll_msecs = -1; 1765 ev->poll_msecs = -1;
1756 INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn); 1766 INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn);