UPSTREAM: loop: refactor queue limits updates
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. Change-Id: I25ec61812c8660124635ba331370a09392fc7269 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> (cherry picked from commit b38c8be255e89ffcdeb817407222d2de0b573a41) Signed-off-by: Bart Van Assche <bvanassche@google.com>
This commit is contained in:
committed by
Bart Van Assche
parent
b0477a0759
commit
d2eefa734f
+20
-16
@@ -977,12 +977,12 @@ static unsigned int loop_default_blocksize(struct loop_device *lo,
|
|||||||
return SECTOR_SIZE;
|
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 file *file = lo->lo_backing_file;
|
||||||
struct inode *inode = file->f_mapping->host;
|
struct inode *inode = file->f_mapping->host;
|
||||||
struct block_device *backing_bdev = NULL;
|
struct block_device *backing_bdev = NULL;
|
||||||
struct queue_limits lim;
|
|
||||||
u32 granularity = 0, max_discard_sectors = 0;
|
u32 granularity = 0, max_discard_sectors = 0;
|
||||||
|
|
||||||
if (S_ISBLK(inode->i_mode))
|
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);
|
loop_get_discard_config(lo, &granularity, &max_discard_sectors);
|
||||||
|
|
||||||
lim = queue_limits_start_update(lo->lo_queue);
|
lim->logical_block_size = bsize;
|
||||||
lim.logical_block_size = bsize;
|
lim->physical_block_size = bsize;
|
||||||
lim.physical_block_size = bsize;
|
lim->io_min = bsize;
|
||||||
lim.io_min = bsize;
|
lim->features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_ROTATIONAL);
|
||||||
lim.features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_ROTATIONAL);
|
|
||||||
if (file->f_op->fsync && !(lo->lo_flags & LO_FLAGS_READ_ONLY))
|
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))
|
if (backing_bdev && !bdev_nonrot(backing_bdev))
|
||||||
lim.features |= BLK_FEAT_ROTATIONAL;
|
lim->features |= BLK_FEAT_ROTATIONAL;
|
||||||
lim.max_hw_discard_sectors = max_discard_sectors;
|
lim->max_hw_discard_sectors = max_discard_sectors;
|
||||||
lim.max_write_zeroes_sectors = max_discard_sectors;
|
lim->max_write_zeroes_sectors = max_discard_sectors;
|
||||||
if (max_discard_sectors)
|
if (max_discard_sectors)
|
||||||
lim.discard_granularity = granularity;
|
lim->discard_granularity = granularity;
|
||||||
else
|
else
|
||||||
lim.discard_granularity = 0;
|
lim->discard_granularity = 0;
|
||||||
return queue_limits_commit_update(lo->lo_queue, &lim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int loop_configure(struct loop_device *lo, blk_mode_t mode,
|
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 file *file = fget(config->fd);
|
||||||
struct address_space *mapping;
|
struct address_space *mapping;
|
||||||
|
struct queue_limits lim;
|
||||||
int error;
|
int error;
|
||||||
loff_t size;
|
loff_t size;
|
||||||
bool partscan;
|
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);
|
lo->old_gfp_mask = mapping_gfp_mask(mapping);
|
||||||
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
|
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)
|
if (error)
|
||||||
goto out_unlock;
|
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)
|
static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
struct queue_limits lim;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (lo->lo_state != Lo_bound)
|
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);
|
invalidate_bdev(lo->lo_device);
|
||||||
|
|
||||||
blk_mq_freeze_queue(lo->lo_queue);
|
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);
|
loop_update_dio(lo);
|
||||||
blk_mq_unfreeze_queue(lo->lo_queue);
|
blk_mq_unfreeze_queue(lo->lo_queue);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user