Merge tag 'io_uring-bio-cache.5-2021-08-30' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / fs / block_dev.c
index 3c7fb71..45df6cb 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/uaccess.h>
 #include <linux/suspend.h>
 #include "internal.h"
+#include "../block/blk.h"
 
 struct bdev_inode {
        struct block_device bdev;
@@ -688,7 +689,8 @@ static loff_t block_llseek(struct file *file, loff_t offset, int whence)
        return retval;
 }
        
-int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
+static int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
+               int datasync)
 {
        struct inode *bd_inode = bdev_file_inode(filp);
        struct block_device *bdev = I_BDEV(bd_inode);
@@ -709,7 +711,6 @@ int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 
        return error;
 }
-EXPORT_SYMBOL(blkdev_fsync);
 
 /**
  * bdev_read_page() - Start reading a page from a block device
@@ -803,7 +804,6 @@ static struct inode *bdev_alloc_inode(struct super_block *sb)
        if (!ei)
                return NULL;
        memset(&ei->bdev, 0, sizeof(ei->bdev));
-       ei->bdev.bd_bdi = &noop_backing_dev_info;
        return &ei->vfs_inode;
 }
 
@@ -814,8 +814,15 @@ static void bdev_free_inode(struct inode *inode)
        free_percpu(bdev->bd_stats);
        kfree(bdev->bd_meta_info);
 
-       if (!bdev_is_partition(bdev))
+       if (!bdev_is_partition(bdev)) {
+               if (bdev->bd_disk && bdev->bd_disk->bdi)
+                       bdi_put(bdev->bd_disk->bdi);
                kfree(bdev->bd_disk);
+       }
+
+       if (MAJOR(bdev->bd_dev) == BLOCK_EXT_MAJOR)
+               blk_free_ext_minor(MINOR(bdev->bd_dev));
+
        kmem_cache_free(bdev_cachep, BDEV_I(inode));
 }
 
@@ -828,16 +835,9 @@ static void init_once(void *data)
 
 static void bdev_evict_inode(struct inode *inode)
 {
-       struct block_device *bdev = &BDEV_I(inode)->bdev;
        truncate_inode_pages_final(&inode->i_data);
        invalidate_inode_buffers(inode); /* is it needed here? */
        clear_inode(inode);
-       /* Detach inode from wb early as bdi_put() may free bdi->wb */
-       inode_detach_wb(inode);
-       if (bdev->bd_bdi != &noop_backing_dev_info) {
-               bdi_put(bdev->bd_bdi);
-               bdev->bd_bdi = &noop_backing_dev_info;
-       }
 }
 
 static const struct super_operations bdev_sops = {
@@ -904,9 +904,6 @@ struct block_device *bdev_alloc(struct gendisk *disk, u8 partno)
        bdev->bd_disk = disk;
        bdev->bd_partno = partno;
        bdev->bd_inode = inode;
-#ifdef CONFIG_SYSFS
-       INIT_LIST_HEAD(&bdev->bd_holder_disks);
-#endif
        bdev->bd_stats = alloc_percpu(struct disk_stats);
        if (!bdev->bd_stats) {
                iput(inode);
@@ -923,31 +920,6 @@ void bdev_add(struct block_device *bdev, dev_t dev)
        insert_inode_hash(bdev->bd_inode);
 }
 
-static struct block_device *bdget(dev_t dev)
-{
-       struct inode *inode;
-
-       inode = ilookup(blockdev_superblock, dev);
-       if (!inode)
-               return NULL;
-       return &BDEV_I(inode)->bdev;
-}
-
-/**
- * bdgrab -- Grab a reference to an already referenced block device
- * @bdev:      Block device to grab a reference to.
- *
- * Returns the block_device with an additional reference when successful,
- * or NULL if the inode is already beeing freed.
- */
-struct block_device *bdgrab(struct block_device *bdev)
-{
-       if (!igrab(bdev->bd_inode))
-               return NULL;
-       return bdev;
-}
-EXPORT_SYMBOL(bdgrab);
-
 long nr_blockdev_pages(void)
 {
        struct inode *inode;
@@ -961,12 +933,6 @@ long nr_blockdev_pages(void)
        return ret;
 }
 
-void bdput(struct block_device *bdev)
-{
-       iput(bdev->bd_inode);
-}
-EXPORT_SYMBOL(bdput);
 /**
  * bd_may_claim - test whether a block device can be claimed
  * @bdev: block device of interest
@@ -1096,148 +1062,6 @@ void bd_abort_claiming(struct block_device *bdev, void *holder)
 }
 EXPORT_SYMBOL(bd_abort_claiming);
 
-#ifdef CONFIG_SYSFS
-struct bd_holder_disk {
-       struct list_head        list;
-       struct gendisk          *disk;
-       int                     refcnt;
-};
-
-static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev,
-                                                 struct gendisk *disk)
-{
-       struct bd_holder_disk *holder;
-
-       list_for_each_entry(holder, &bdev->bd_holder_disks, list)
-               if (holder->disk == disk)
-                       return holder;
-       return NULL;
-}
-
-static int add_symlink(struct kobject *from, struct kobject *to)
-{
-       return sysfs_create_link(from, to, kobject_name(to));
-}
-
-static void del_symlink(struct kobject *from, struct kobject *to)
-{
-       sysfs_remove_link(from, kobject_name(to));
-}
-
-/**
- * bd_link_disk_holder - create symlinks between holding disk and slave bdev
- * @bdev: the claimed slave bdev
- * @disk: the holding disk
- *
- * DON'T USE THIS UNLESS YOU'RE ALREADY USING IT.
- *
- * This functions creates the following sysfs symlinks.
- *
- * - from "slaves" directory of the holder @disk to the claimed @bdev
- * - from "holders" directory of the @bdev to the holder @disk
- *
- * For example, if /dev/dm-0 maps to /dev/sda and disk for dm-0 is
- * passed to bd_link_disk_holder(), then:
- *
- *   /sys/block/dm-0/slaves/sda --> /sys/block/sda
- *   /sys/block/sda/holders/dm-0 --> /sys/block/dm-0
- *
- * The caller must have claimed @bdev before calling this function and
- * ensure that both @bdev and @disk are valid during the creation and
- * lifetime of these symlinks.
- *
- * CONTEXT:
- * Might sleep.
- *
- * RETURNS:
- * 0 on success, -errno on failure.
- */
-int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
-{
-       struct bd_holder_disk *holder;
-       int ret = 0;
-
-       mutex_lock(&bdev->bd_disk->open_mutex);
-
-       WARN_ON_ONCE(!bdev->bd_holder);
-
-       /* FIXME: remove the following once add_disk() handles errors */
-       if (WARN_ON(!disk->slave_dir || !bdev->bd_holder_dir))
-               goto out_unlock;
-
-       holder = bd_find_holder_disk(bdev, disk);
-       if (holder) {
-               holder->refcnt++;
-               goto out_unlock;
-       }
-
-       holder = kzalloc(sizeof(*holder), GFP_KERNEL);
-       if (!holder) {
-               ret = -ENOMEM;
-               goto out_unlock;
-       }
-
-       INIT_LIST_HEAD(&holder->list);
-       holder->disk = disk;
-       holder->refcnt = 1;
-
-       ret = add_symlink(disk->slave_dir, bdev_kobj(bdev));
-       if (ret)
-               goto out_free;
-
-       ret = add_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
-       if (ret)
-               goto out_del;
-       /*
-        * bdev could be deleted beneath us which would implicitly destroy
-        * the holder directory.  Hold on to it.
-        */
-       kobject_get(bdev->bd_holder_dir);
-
-       list_add(&holder->list, &bdev->bd_holder_disks);
-       goto out_unlock;
-
-out_del:
-       del_symlink(disk->slave_dir, bdev_kobj(bdev));
-out_free:
-       kfree(holder);
-out_unlock:
-       mutex_unlock(&bdev->bd_disk->open_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(bd_link_disk_holder);
-
-/**
- * bd_unlink_disk_holder - destroy symlinks created by bd_link_disk_holder()
- * @bdev: the calimed slave bdev
- * @disk: the holding disk
- *
- * DON'T USE THIS UNLESS YOU'RE ALREADY USING IT.
- *
- * CONTEXT:
- * Might sleep.
- */
-void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
-{
-       struct bd_holder_disk *holder;
-
-       mutex_lock(&bdev->bd_disk->open_mutex);
-
-       holder = bd_find_holder_disk(bdev, disk);
-
-       if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) {
-               del_symlink(disk->slave_dir, bdev_kobj(bdev));
-               del_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
-               kobject_put(bdev->bd_holder_dir);
-               list_del_init(&holder->list);
-               kfree(holder);
-       }
-
-       mutex_unlock(&bdev->bd_disk->open_mutex);
-}
-EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
-#endif
-
 static void blkdev_flush_mapping(struct block_device *bdev)
 {
        WARN_ON_ONCE(bdev->bd_holders);
@@ -1262,11 +1086,8 @@ static int blkdev_get_whole(struct block_device *bdev, fmode_t mode)
                }
        }
 
-       if (!bdev->bd_openers) {
+       if (!bdev->bd_openers)
                set_init_blocksize(bdev);
-               if (bdev->bd_bdi == &noop_backing_dev_info)
-                       bdev->bd_bdi = bdi_get(disk->queue->backing_dev_info);
-       }
        if (test_bit(GD_NEED_PART_SCAN, &disk->state))
                bdev_disk_changed(disk, false);
        bdev->bd_openers++;
@@ -1284,16 +1105,14 @@ static void blkdev_put_whole(struct block_device *bdev, fmode_t mode)
 static int blkdev_get_part(struct block_device *part, fmode_t mode)
 {
        struct gendisk *disk = part->bd_disk;
-       struct block_device *whole;
        int ret;
 
        if (part->bd_openers)
                goto done;
 
-       whole = bdgrab(disk->part0);
-       ret = blkdev_get_whole(whole, mode);
+       ret = blkdev_get_whole(bdev_whole(part), mode);
        if (ret)
-               goto out_put_whole;
+               return ret;
 
        ret = -ENXIO;
        if (!bdev_nr_sectors(part))
@@ -1301,16 +1120,12 @@ static int blkdev_get_part(struct block_device *part, fmode_t mode)
 
        disk->open_partitions++;
        set_init_blocksize(part);
-       if (part->bd_bdi == &noop_backing_dev_info)
-               part->bd_bdi = bdi_get(disk->queue->backing_dev_info);
 done:
        part->bd_openers++;
        return 0;
 
 out_blkdev_put:
-       blkdev_put_whole(whole, mode);
-out_put_whole:
-       bdput(whole);
+       blkdev_put_whole(bdev_whole(part), mode);
        return ret;
 }
 
@@ -1323,42 +1138,42 @@ static void blkdev_put_part(struct block_device *part, fmode_t mode)
        blkdev_flush_mapping(part);
        whole->bd_disk->open_partitions--;
        blkdev_put_whole(whole, mode);
-       bdput(whole);
 }
 
 struct block_device *blkdev_get_no_open(dev_t dev)
 {
        struct block_device *bdev;
-       struct gendisk *disk;
+       struct inode *inode;
 
-       bdev = bdget(dev);
-       if (!bdev) {
+       inode = ilookup(blockdev_superblock, dev);
+       if (!inode) {
                blk_request_module(dev);
-               bdev = bdget(dev);
-               if (!bdev)
+               inode = ilookup(blockdev_superblock, dev);
+               if (!inode)
                        return NULL;
        }
 
-       disk = bdev->bd_disk;
-       if (!kobject_get_unless_zero(&disk_to_dev(disk)->kobj))
-               goto bdput;
-       if ((disk->flags & (GENHD_FL_UP | GENHD_FL_HIDDEN)) != GENHD_FL_UP)
-               goto put_disk;
-       if (!try_module_get(bdev->bd_disk->fops->owner))
-               goto put_disk;
+       /* switch from the inode reference to a device mode one: */
+       bdev = &BDEV_I(inode)->bdev;
+       if (!kobject_get_unless_zero(&bdev->bd_device.kobj))
+               bdev = NULL;
+       iput(inode);
+
+       if (!bdev)
+               return NULL;
+       if ((bdev->bd_disk->flags & GENHD_FL_HIDDEN) ||
+           !try_module_get(bdev->bd_disk->fops->owner)) {
+               put_device(&bdev->bd_device);
+               return NULL;
+       }
+
        return bdev;
-put_disk:
-       put_disk(disk);
-bdput:
-       bdput(bdev);
-       return NULL;
 }
 
 void blkdev_put_no_open(struct block_device *bdev)
 {
        module_put(bdev->bd_disk->fops->owner);
-       put_disk(bdev->bd_disk);
-       bdput(bdev);
+       put_device(&bdev->bd_device);
 }
 
 /**
@@ -1411,7 +1226,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
 
        mutex_lock(&disk->open_mutex);
        ret = -ENXIO;
-       if (!(disk->flags & GENHD_FL_UP))
+       if (!disk_live(disk))
                goto abort_claiming;
        if (bdev_is_partition(bdev))
                ret = blkdev_get_part(bdev, mode);