Skip to content

Commit bf58ef1

Browse files
damien-lemoalgregkh
authored andcommitted
block: freeze queue when updating zone resources
commit bba4322 upstream. Modify disk_update_zone_resources() to freeze the device queue before updating the number of zones, zone capacity and other zone related resources. The locking order resulting from the call to queue_limits_commit_update_frozen() is preserved, that is, the queue limits lock is first taken by calling queue_limits_start_update() before freezing the queue, and the queue is unfrozen after executing queue_limits_commit_update(), which replaces the call to queue_limits_commit_update_frozen(). This change ensures that there are no in-flights I/Os when the zone resources are updated due to a zone revalidation. In case of error when the limits are applied, directly call disk_free_zone_resources() from disk_update_zone_resources() while the disk queue is still frozen to avoid needing to freeze & unfreeze the queue again in blk_revalidate_disk_zones(), thus simplifying that function code a little. Fixes: 0b83c86 ("block: Prevent potential deadlock in blk_revalidate_disk_zones()") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ce909de commit bf58ef1

1 file changed

Lines changed: 24 additions & 18 deletions

File tree

block/blk-zoned.c

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,8 +1516,13 @@ static int disk_update_zone_resources(struct gendisk *disk,
15161516
{
15171517
struct request_queue *q = disk->queue;
15181518
unsigned int nr_seq_zones, nr_conv_zones;
1519-
unsigned int pool_size;
1519+
unsigned int pool_size, memflags;
15201520
struct queue_limits lim;
1521+
int ret = 0;
1522+
1523+
lim = queue_limits_start_update(q);
1524+
1525+
memflags = blk_mq_freeze_queue(q);
15211526

15221527
disk->nr_zones = args->nr_zones;
15231528
disk->zone_capacity = args->zone_capacity;
@@ -1527,11 +1532,10 @@ static int disk_update_zone_resources(struct gendisk *disk,
15271532
if (nr_conv_zones >= disk->nr_zones) {
15281533
pr_warn("%s: Invalid number of conventional zones %u / %u\n",
15291534
disk->disk_name, nr_conv_zones, disk->nr_zones);
1530-
return -ENODEV;
1535+
ret = -ENODEV;
1536+
goto unfreeze;
15311537
}
15321538

1533-
lim = queue_limits_start_update(q);
1534-
15351539
/*
15361540
* Some devices can advertize zone resource limits that are larger than
15371541
* the number of sequential zones of the zoned block device, e.g. a
@@ -1568,7 +1572,15 @@ static int disk_update_zone_resources(struct gendisk *disk,
15681572
}
15691573

15701574
commit:
1571-
return queue_limits_commit_update_frozen(q, &lim);
1575+
ret = queue_limits_commit_update(q, &lim);
1576+
1577+
unfreeze:
1578+
if (ret)
1579+
disk_free_zone_resources(disk);
1580+
1581+
blk_mq_unfreeze_queue(q, memflags);
1582+
1583+
return ret;
15721584
}
15731585

15741586
static int blk_revalidate_conv_zone(struct blk_zone *zone, unsigned int idx,
@@ -1733,7 +1745,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
17331745
sector_t zone_sectors = q->limits.chunk_sectors;
17341746
sector_t capacity = get_capacity(disk);
17351747
struct blk_revalidate_zone_args args = { };
1736-
unsigned int noio_flag;
1748+
unsigned int memflags, noio_flag;
17371749
int ret = -ENOMEM;
17381750

17391751
if (WARN_ON_ONCE(!blk_queue_is_zoned(q)))
@@ -1783,20 +1795,14 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
17831795
ret = -ENODEV;
17841796
}
17851797

1786-
/*
1787-
* Set the new disk zone parameters only once the queue is frozen and
1788-
* all I/Os are completed.
1789-
*/
17901798
if (ret > 0)
1791-
ret = disk_update_zone_resources(disk, &args);
1792-
else
1793-
pr_warn("%s: failed to revalidate zones\n", disk->disk_name);
1794-
if (ret) {
1795-
unsigned int memflags = blk_mq_freeze_queue(q);
1799+
return disk_update_zone_resources(disk, &args);
17961800

1797-
disk_free_zone_resources(disk);
1798-
blk_mq_unfreeze_queue(q, memflags);
1799-
}
1801+
pr_warn("%s: failed to revalidate zones\n", disk->disk_name);
1802+
1803+
memflags = blk_mq_freeze_queue(q);
1804+
disk_free_zone_resources(disk);
1805+
blk_mq_unfreeze_queue(q, memflags);
18001806

18011807
return ret;
18021808
}

0 commit comments

Comments
 (0)