block: turn bdev->bd_openers into an atomic_t
authorChristoph Hellwig <hch@lst.de>
Wed, 30 Mar 2022 05:29:07 +0000 (07:29 +0200)
committerJens Axboe <axboe@kernel.dk>
Mon, 18 Apr 2022 12:54:09 +0000 (06:54 -0600)
All manipulation of bd_openers is under disk->open_mutex and will remain
so for the foreseeable future.  But at least one place reads it without
the lock (blkdev_get) and there are more to be added.  So make sure the
compiler does not do turn the increments and decrements into non-atomic
sequences by using an atomic_t.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20220330052917.2566582-6-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/bdev.c
block/partitions/core.c
include/linux/blk_types.h
include/linux/blkdev.h

index 13de871..7bf88e5 100644 (file)
@@ -673,17 +673,17 @@ static int blkdev_get_whole(struct block_device *bdev, fmode_t mode)
                }
        }
 
-       if (!bdev->bd_openers)
+       if (!atomic_read(&bdev->bd_openers))
                set_init_blocksize(bdev);
        if (test_bit(GD_NEED_PART_SCAN, &disk->state))
                bdev_disk_changed(disk, false);
-       bdev->bd_openers++;
+       atomic_inc(&bdev->bd_openers);
        return 0;
 }
 
 static void blkdev_put_whole(struct block_device *bdev, fmode_t mode)
 {
-       if (!--bdev->bd_openers)
+       if (atomic_dec_and_test(&bdev->bd_openers))
                blkdev_flush_mapping(bdev);
        if (bdev->bd_disk->fops->release)
                bdev->bd_disk->fops->release(bdev->bd_disk, mode);
@@ -694,7 +694,7 @@ static int blkdev_get_part(struct block_device *part, fmode_t mode)
        struct gendisk *disk = part->bd_disk;
        int ret;
 
-       if (part->bd_openers)
+       if (atomic_read(&part->bd_openers))
                goto done;
 
        ret = blkdev_get_whole(bdev_whole(part), mode);
@@ -708,7 +708,7 @@ static int blkdev_get_part(struct block_device *part, fmode_t mode)
        disk->open_partitions++;
        set_init_blocksize(part);
 done:
-       part->bd_openers++;
+       atomic_inc(&part->bd_openers);
        return 0;
 
 out_blkdev_put:
@@ -720,7 +720,7 @@ static void blkdev_put_part(struct block_device *part, fmode_t mode)
 {
        struct block_device *whole = bdev_whole(part);
 
-       if (--part->bd_openers)
+       if (!atomic_dec_and_test(&part->bd_openers))
                return;
        blkdev_flush_mapping(part);
        whole->bd_disk->open_partitions--;
@@ -899,7 +899,7 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
         * of the world and we want to avoid long (could be several minute)
         * syncs while holding the mutex.
         */
-       if (bdev->bd_openers == 1)
+       if (atomic_read(&bdev->bd_openers) == 1)
                sync_blockdev(bdev);
 
        mutex_lock(&disk->open_mutex);
@@ -1044,7 +1044,7 @@ void sync_bdevs(bool wait)
                bdev = I_BDEV(inode);
 
                mutex_lock(&bdev->bd_disk->open_mutex);
-               if (!bdev->bd_openers) {
+               if (!atomic_read(&bdev->bd_openers)) {
                        ; /* skip */
                } else if (wait) {
                        /*
index 70dec1c..8a0ec92 100644 (file)
@@ -478,7 +478,7 @@ int bdev_del_partition(struct gendisk *disk, int partno)
                goto out_unlock;
 
        ret = -EBUSY;
-       if (part->bd_openers)
+       if (atomic_read(&part->bd_openers))
                goto out_unlock;
 
        delete_partition(part);
index 4968cb1..c622744 100644 (file)
@@ -44,7 +44,7 @@ struct block_device {
        unsigned long           bd_stamp;
        bool                    bd_read_only;   /* read-only policy */
        dev_t                   bd_dev;
-       int                     bd_openers;
+       atomic_t                bd_openers;
        struct inode *          bd_inode;       /* will die */
        struct super_block *    bd_super;
        void *                  bd_claiming;
index 436645b..afad3d1 100644 (file)
@@ -188,7 +188,7 @@ static inline bool disk_live(struct gendisk *disk)
  */
 static inline unsigned int disk_openers(struct gendisk *disk)
 {
-       return disk->part0->bd_openers;
+       return atomic_read(&disk->part0->bd_openers);
 }
 
 /*