block: remove bdev_handle completely
authorChristian Brauner <brauner@kernel.org>
Tue, 23 Jan 2024 13:26:49 +0000 (14:26 +0100)
committerChristian Brauner <brauner@kernel.org>
Sun, 25 Feb 2024 11:05:28 +0000 (12:05 +0100)
We just need to use the holder to indicate whether a block device open
was exclusive or not. We did use to do that before but had to give that
up once we switched to struct bdev_handle. Before struct bdev_handle we
only stashed stuff in file->private_data if this was an exclusive open
but after struct bdev_handle we always set file->private_data to a
struct bdev_handle and so we had to use bdev_handle->mode or
bdev_handle->holder. Now that we don't use struct bdev_handle anymore we
can revert back to the old behavior.

Link: https://lore.kernel.org/r/20240123-vfs-bdev-file-v2-32-adbd023e19cc@kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <brauner@kernel.org>
block/bdev.c
block/blk.h
block/fops.c

index efecc9b97e1eca8543eb74451f9883ab33f8304d..140093c99bdcf810cc75e397e1fa18aab260d216 100644 (file)
@@ -717,6 +717,13 @@ int bdev_permission(dev_t dev, blk_mode_t mode, void *holder)
        if (mode & BLK_OPEN_RESTRICT_WRITES && !holder)
                return -EINVAL;
 
+       /*
+        * We're using error pointers to indicate to ->release() when we
+        * failed to open that block device. Also this doesn't make sense.
+        */
+       if (WARN_ON_ONCE(IS_ERR(holder)))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -799,7 +806,7 @@ static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode)
                bdev->bd_writers++;
 }
 
-static void bdev_yield_write_access(struct file *bdev_file, blk_mode_t mode)
+static void bdev_yield_write_access(struct file *bdev_file)
 {
        struct block_device *bdev;
 
@@ -808,7 +815,7 @@ static void bdev_yield_write_access(struct file *bdev_file, blk_mode_t mode)
 
        bdev = file_bdev(bdev_file);
        /* Yield exclusive or shared write access. */
-       if (mode & BLK_OPEN_WRITE) {
+       if (bdev_file->f_mode & FMODE_WRITE) {
                if (bdev_writes_blocked(bdev))
                        bdev_unblock_writes(bdev);
                else
@@ -836,25 +843,18 @@ static void bdev_yield_write_access(struct file *bdev_file, blk_mode_t mode)
 int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
              const struct blk_holder_ops *hops, struct file *bdev_file)
 {
-       struct bdev_handle *handle;
        bool unblock_events = true;
        struct gendisk *disk = bdev->bd_disk;
        int ret;
 
-       handle = kmalloc(sizeof(struct bdev_handle), GFP_KERNEL);
-       if (!handle)
-               return -ENOMEM;
-
        if (holder) {
                mode |= BLK_OPEN_EXCL;
                ret = bd_prepare_to_claim(bdev, holder, hops);
                if (ret)
-                       goto free_handle;
+                       return ret;
        } else {
-               if (WARN_ON_ONCE(mode & BLK_OPEN_EXCL)) {
-                       ret = -EIO;
-                       goto free_handle;
-               }
+               if (WARN_ON_ONCE(mode & BLK_OPEN_EXCL))
+                       return -EIO;
        }
 
        disk_block_events(disk);
@@ -895,8 +895,6 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
 
        if (unblock_events)
                disk_unblock_events(disk);
-       handle->holder = holder;
-       handle->mode = mode;
 
        bdev_file->f_flags |= O_LARGEFILE;
        bdev_file->f_mode |= FMODE_BUF_RASYNC | FMODE_CAN_ODIRECT;
@@ -904,7 +902,7 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
                bdev_file->f_mode |= FMODE_NOWAIT;
        bdev_file->f_mapping = bdev->bd_inode->i_mapping;
        bdev_file->f_wb_err = filemap_sample_wb_err(bdev_file->f_mapping);
-       bdev_file->private_data = handle;
+       bdev_file->private_data = holder;
 
        return 0;
 put_module:
@@ -914,8 +912,6 @@ abort_claiming:
                bd_abort_claiming(bdev, holder);
        mutex_unlock(&disk->open_mutex);
        disk_unblock_events(disk);
-free_handle:
-       kfree(handle);
        return ret;
 }
 
@@ -976,7 +972,8 @@ struct file *bdev_file_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
 
        ret = bdev_open(bdev, mode, holder, hops, bdev_file);
        if (ret) {
-               blkdev_put_no_open(bdev);
+               /* We failed to open the block device. Let ->release() know. */
+               bdev_file->private_data = ERR_PTR(ret);
                fput(bdev_file);
                return ERR_PTR(ret);
        }
@@ -1011,9 +1008,13 @@ EXPORT_SYMBOL(bdev_file_open_by_path);
 void bdev_release(struct file *bdev_file)
 {
        struct block_device *bdev = file_bdev(bdev_file);
-       struct bdev_handle *handle = bdev_file->private_data;
+       void *holder = bdev_file->private_data;
        struct gendisk *disk = bdev->bd_disk;
 
+       /* We failed to open that block device. */
+       if (IS_ERR(holder))
+               goto put_no_open;
+
        /*
         * Sync early if it looks like we're the last one.  If someone else
         * opens the block device between now and the decrement of bd_openers
@@ -1025,10 +1026,10 @@ void bdev_release(struct file *bdev_file)
                sync_blockdev(bdev);
 
        mutex_lock(&disk->open_mutex);
-       bdev_yield_write_access(bdev_file, handle->mode);
+       bdev_yield_write_access(bdev_file);
 
-       if (handle->holder)
-               bd_end_claim(bdev, handle->holder);
+       if (holder)
+               bd_end_claim(bdev, holder);
 
        /*
         * Trigger event checking and tell drivers to flush MEDIA_CHANGE
@@ -1044,8 +1045,8 @@ void bdev_release(struct file *bdev_file)
        mutex_unlock(&disk->open_mutex);
 
        module_put(disk->fops->owner);
+put_no_open:
        blkdev_put_no_open(bdev);
-       kfree(handle);
 }
 
 /**
index 7ca24814f3a0dbdb43560d40a001836f84897a82..f02b25f22e8b341556e36a55b2df5c29c1383906 100644 (file)
@@ -25,11 +25,6 @@ struct blk_flush_queue {
        struct request          *flush_rq;
 };
 
-struct bdev_handle {
-       void *holder;
-       blk_mode_t mode;
-};
-
 bool is_flush_rq(struct request *req);
 
 struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
index aab9b89e4c77d82d88822f7cc01552a13966c7a0..029e787f01197138d36760e4317389792a98bf05 100644 (file)
@@ -569,18 +569,17 @@ static int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
 blk_mode_t file_to_blk_mode(struct file *file)
 {
        blk_mode_t mode = 0;
-       struct bdev_handle *handle = file->private_data;
 
        if (file->f_mode & FMODE_READ)
                mode |= BLK_OPEN_READ;
        if (file->f_mode & FMODE_WRITE)
                mode |= BLK_OPEN_WRITE;
        /*
-        * do_dentry_open() clears O_EXCL from f_flags, use handle->mode to
-        * determine whether the open was exclusive for already open files.
+        * do_dentry_open() clears O_EXCL from f_flags, use file->private_data
+        * to determine whether the open was exclusive for already open files.
         */
-       if (handle)
-               mode |= handle->mode & BLK_OPEN_EXCL;
+       if (file->private_data)
+               mode |= BLK_OPEN_EXCL;
        else if (file->f_flags & O_EXCL)
                mode |= BLK_OPEN_EXCL;
        if (file->f_flags & O_NDELAY)
@@ -601,12 +600,13 @@ static int blkdev_open(struct inode *inode, struct file *filp)
 {
        struct block_device *bdev;
        blk_mode_t mode;
-       void *holder;
        int ret;
 
        mode = file_to_blk_mode(filp);
-       holder = mode & BLK_OPEN_EXCL ? filp : NULL;
-       ret = bdev_permission(inode->i_rdev, mode, holder);
+       /* Use the file as the holder. */
+       if (mode & BLK_OPEN_EXCL)
+               filp->private_data = filp;
+       ret = bdev_permission(inode->i_rdev, mode, filp->private_data);
        if (ret)
                return ret;
 
@@ -614,7 +614,7 @@ static int blkdev_open(struct inode *inode, struct file *filp)
        if (!bdev)
                return -ENXIO;
 
-       ret = bdev_open(bdev, mode, holder, NULL, filp);
+       ret = bdev_open(bdev, mode, filp->private_data, NULL, filp);
        if (ret)
                blkdev_put_no_open(bdev);
        return ret;
@@ -622,8 +622,7 @@ static int blkdev_open(struct inode *inode, struct file *filp)
 
 static int blkdev_release(struct inode *inode, struct file *filp)
 {
-       if (filp->private_data)
-               bdev_release(filp);
+       bdev_release(filp);
        return 0;
 }