Merge branch 'for-3.1/core' of git://git.kernel.dk/linux-block
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / block_dev.c
index 9fb0b15..c62fb84 100644 (file)
@@ -1448,6 +1448,8 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
 
 int blkdev_put(struct block_device *bdev, fmode_t mode)
 {
+       mutex_lock(&bdev->bd_mutex);
+
        if (mode & FMODE_EXCL) {
                bool bdev_free;
 
@@ -1456,7 +1458,6 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
                 * are protected with bdev_lock.  bd_mutex is to
                 * synchronize disk_holder unlinking.
                 */
-               mutex_lock(&bdev->bd_mutex);
                spin_lock(&bdev_lock);
 
                WARN_ON_ONCE(--bdev->bd_holders < 0);
@@ -1474,17 +1475,21 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
                 * If this was the last claim, remove holder link and
                 * unblock evpoll if it was a write holder.
                 */
-               if (bdev_free) {
-                       if (bdev->bd_write_holder) {
-                               disk_unblock_events(bdev->bd_disk);
-                               disk_check_events(bdev->bd_disk);
-                               bdev->bd_write_holder = false;
-                       }
+               if (bdev_free && bdev->bd_write_holder) {
+                       disk_unblock_events(bdev->bd_disk);
+                       bdev->bd_write_holder = false;
                }
-
-               mutex_unlock(&bdev->bd_mutex);
        }
 
+       /*
+        * Trigger event checking and tell drivers to flush MEDIA_CHANGE
+        * event.  This is to ensure detection of media removal commanded
+        * from userland - e.g. eject(1).
+        */
+       disk_flush_events(bdev->bd_disk, DISK_EVENT_MEDIA_CHANGE);
+
+       mutex_unlock(&bdev->bd_mutex);
+
        return __blkdev_put(bdev, mode, 0);
 }
 EXPORT_SYMBOL(blkdev_put);