]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
loop: refactor queue limits updates
authorChristoph Hellwig <hch@lst.de>
Fri, 10 Jan 2025 05:47:18 +0000 (06:47 +0100)
committerJens Axboe <axboe@kernel.dk>
Fri, 10 Jan 2025 14:29:24 +0000 (07:29 -0700)
Replace loop_reconfigure_limits with a slightly less encompassing
loop_update_limits that expects the caller to acquire and commit the
queue limits to prepare for sorting out the freeze vs limits lock
ordering.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
Link: https://lore.kernel.org/r/20250110054726.1499538-11-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/loop.c

index 836a53eef4b4e409c4d69e8801b3ddb1942259f8..560d6d5879d6f2344b2c5c44220114ba9832bb80 100644 (file)
@@ -977,12 +977,12 @@ static unsigned int loop_default_blocksize(struct loop_device *lo,
        return SECTOR_SIZE;
 }
 
-static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
+static void loop_update_limits(struct loop_device *lo, struct queue_limits *lim,
+               unsigned int bsize)
 {
        struct file *file = lo->lo_backing_file;
        struct inode *inode = file->f_mapping->host;
        struct block_device *backing_bdev = NULL;
-       struct queue_limits lim;
        u32 granularity = 0, max_discard_sectors = 0;
 
        if (S_ISBLK(inode->i_mode))
@@ -995,22 +995,20 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
 
        loop_get_discard_config(lo, &granularity, &max_discard_sectors);
 
-       lim = queue_limits_start_update(lo->lo_queue);
-       lim.logical_block_size = bsize;
-       lim.physical_block_size = bsize;
-       lim.io_min = bsize;
-       lim.features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_ROTATIONAL);
+       lim->logical_block_size = bsize;
+       lim->physical_block_size = bsize;
+       lim->io_min = bsize;
+       lim->features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_ROTATIONAL);
        if (file->f_op->fsync && !(lo->lo_flags & LO_FLAGS_READ_ONLY))
-               lim.features |= BLK_FEAT_WRITE_CACHE;
+               lim->features |= BLK_FEAT_WRITE_CACHE;
        if (backing_bdev && !bdev_nonrot(backing_bdev))
-               lim.features |= BLK_FEAT_ROTATIONAL;
-       lim.max_hw_discard_sectors = max_discard_sectors;
-       lim.max_write_zeroes_sectors = max_discard_sectors;
+               lim->features |= BLK_FEAT_ROTATIONAL;
+       lim->max_hw_discard_sectors = max_discard_sectors;
+       lim->max_write_zeroes_sectors = max_discard_sectors;
        if (max_discard_sectors)
-               lim.discard_granularity = granularity;
+               lim->discard_granularity = granularity;
        else
-               lim.discard_granularity = 0;
-       return queue_limits_commit_update(lo->lo_queue, &lim);
+               lim->discard_granularity = 0;
 }
 
 static int loop_configure(struct loop_device *lo, blk_mode_t mode,
@@ -1019,6 +1017,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
 {
        struct file *file = fget(config->fd);
        struct address_space *mapping;
+       struct queue_limits lim;
        int error;
        loff_t size;
        bool partscan;
@@ -1090,7 +1089,9 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
        lo->old_gfp_mask = mapping_gfp_mask(mapping);
        mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
 
-       error = loop_reconfigure_limits(lo, config->block_size);
+       lim = queue_limits_start_update(lo->lo_queue);
+       loop_update_limits(lo, &lim, config->block_size);
+       error = queue_limits_commit_update(lo->lo_queue, &lim);
        if (error)
                goto out_unlock;
 
@@ -1458,6 +1459,7 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)
 
 static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
 {
+       struct queue_limits lim;
        int err = 0;
 
        if (lo->lo_state != Lo_bound)
@@ -1470,7 +1472,9 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
        invalidate_bdev(lo->lo_device);
 
        blk_mq_freeze_queue(lo->lo_queue);
-       err = loop_reconfigure_limits(lo, arg);
+       lim = queue_limits_start_update(lo->lo_queue);
+       loop_update_limits(lo, &lim, arg);
+       err = queue_limits_commit_update(lo->lo_queue, &lim);
        loop_update_dio(lo);
        blk_mq_unfreeze_queue(lo->lo_queue);