+ if (mode & FMODE_EXCL) {
+ WARN_ON_ONCE(!holder);
+
+ ret = -ENOMEM;
+ claiming = bdget_disk(disk, 0);
+ if (!claiming)
+ goto put_disk;
+ ret = bd_prepare_to_claim(bdev, claiming, holder);
+ if (ret)
+ goto put_claiming;
+ }
+
+ disk_block_events(disk);
+
+ mutex_lock(&bdev->bd_mutex);
+ ret =__blkdev_get(bdev, disk, partno, mode);
+ if (!(mode & FMODE_EXCL)) {
+ ; /* nothing to do here */
+ } else if (ret) {
+ bd_abort_claiming(bdev, claiming, holder);
+ } else {
+ bd_finish_claiming(bdev, claiming, holder);
+
+ /*
+ * Block event polling for write claims if requested. Any write
+ * holder makes the write_holder state stick until all are
+ * released. This is good enough and tracking individual
+ * writeable reference is too fragile given the way @mode is
+ * used in blkdev_get/put().
+ */
+ if ((mode & FMODE_WRITE) && !bdev->bd_write_holder &&
+ (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) {
+ bdev->bd_write_holder = true;
+ unblock_events = false;
+ }
+ }
+ mutex_unlock(&bdev->bd_mutex);
+
+ if (unblock_events)
+ disk_unblock_events(disk);
+
+put_claiming:
+ if (mode & FMODE_EXCL)
+ bdput(claiming);
+put_disk:
+ if (ret)
+ put_disk_and_module(disk);
+ if (ret == -ERESTARTSYS)
+ goto retry;