diff --git a/block/bdev.c b/block/bdev.c index 9b73487a91ca..28b0d40c362f 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -1195,6 +1195,39 @@ void bdev_release(struct file *bdev_file) blkdev_put_no_open(bdev); } +/** + * bdev_yield_claim - give up the holder claim on an open block device + * @bdev_file: open block device + * + * Yield the holder and any write access for @bdev_file without closing it, so + * the caller can still act on the device - e.g. bdev_allow_freeze() it - before + * the final bdev_fput(). bdev_fput() yields too, so calling it afterwards is + * safe. + */ +void bdev_yield_claim(struct file *bdev_file) +{ + struct block_device *bdev; + struct gendisk *disk; + + if (!bdev_file->private_data) + return; + + bdev = file_bdev(bdev_file); + disk = bdev->bd_disk; + + mutex_lock(&disk->open_mutex); + bdev_yield_write_access(bdev_file); + bd_yield_claim(bdev_file); + /* + * Tell release we already gave up our hold on the + * device and if write restrictions are available that + * we already gave up write access to the device. + */ + bdev_file->private_data = BDEV_I(bdev_file->f_mapping->host); + mutex_unlock(&disk->open_mutex); +} +EXPORT_SYMBOL_GPL(bdev_yield_claim); + /** * bdev_fput - yield claim to the block device and put the file * @bdev_file: open block device @@ -1208,22 +1241,7 @@ void bdev_fput(struct file *bdev_file) if (WARN_ON_ONCE(bdev_file->f_op != &def_blk_fops)) return; - if (bdev_file->private_data) { - struct block_device *bdev = file_bdev(bdev_file); - struct gendisk *disk = bdev->bd_disk; - - mutex_lock(&disk->open_mutex); - bdev_yield_write_access(bdev_file); - bd_yield_claim(bdev_file); - /* - * Tell release we already gave up our hold on the - * device and if write restrictions are available that - * we already gave up write access to the device. - */ - bdev_file->private_data = BDEV_I(bdev_file->f_mapping->host); - mutex_unlock(&disk->open_mutex); - } - + bdev_yield_claim(bdev_file); fput(bdev_file); } EXPORT_SYMBOL(bdev_fput); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c419117be083..f4e5eca5a91f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1840,6 +1840,7 @@ int bdev_thaw(struct block_device *bdev); int bdev_deny_freeze(struct block_device *bdev); void bdev_allow_freeze(struct block_device *bdev); void bdev_fput(struct file *bdev_file); +void bdev_yield_claim(struct file *bdev_file); struct io_comp_batch { struct rq_list req_list;