From e2bb771ae8b4041afe6320c0c85b763074746cf4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 9 Jun 2011 20:43:59 +0200 Subject: [PATCH] --- yaml --- r: 254004 b: refs/heads/master c: fdd514e16bb2531c0c61ae8a1f87740ce217f630 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/block/genhd.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 08fe2a5f04ad..f2b40a5bb800 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c3af54afbac3675337cedf326b7b127ffa7f7327 +refs/heads/master: fdd514e16bb2531c0c61ae8a1f87740ce217f630 diff --git a/trunk/block/genhd.c b/trunk/block/genhd.c index ab0731d8976d..3608289c8ecd 100644 --- a/trunk/block/genhd.c +++ b/trunk/block/genhd.c @@ -1371,6 +1371,7 @@ struct disk_events { struct gendisk *disk; /* the associated disk */ spinlock_t lock; + struct mutex block_mutex; /* protects blocking */ int block; /* event blocking depth */ unsigned int pending; /* events already sent out */ unsigned int clearing; /* events being cleared */ @@ -1438,12 +1439,20 @@ void disk_block_events(struct gendisk *disk) if (!ev) return; + /* + * Outer mutex ensures that the first blocker completes canceling + * the event work before further blockers are allowed to finish. + */ + mutex_lock(&ev->block_mutex); + spin_lock_irqsave(&ev->lock, flags); cancel = !ev->block++; spin_unlock_irqrestore(&ev->lock, flags); if (cancel) cancel_delayed_work_sync(&disk->ev->dwork); + + mutex_unlock(&ev->block_mutex); } static void __disk_unblock_events(struct gendisk *disk, bool check_now) @@ -1751,6 +1760,7 @@ static void disk_add_events(struct gendisk *disk) INIT_LIST_HEAD(&ev->node); ev->disk = disk; spin_lock_init(&ev->lock); + mutex_init(&ev->block_mutex); ev->block = 1; ev->poll_msecs = -1; INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn);