When disk_revalidate_zone_resources() detects a capacity change, -ENODEV is returned, failing the disk revalidation. However, since a capacity change may happen due to a storage element removal being executed concurrently to blk_revalidate_disk_zones(), we can simply retry the revalidation to capture the new zone state with the new capacity without failing the revalidation. Retrying the revalidation is driven by disk_revalidate_zone_resources() returning -EAGAIN when a new valid capacity is detected. And to avoid getting stuck in an infinite loop revalidating zones, retries are limited to 2. Signed-off-by: Damien Le Moal --- block/blk-zoned.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index e7f20b5262c7..96e922b7a126 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -2175,7 +2175,11 @@ static int disk_revalidate_zone_resources(struct gendisk *disk, if (args->capacity != capacity) { pr_warn("%s: Capacity has changed (%llu -> %llu)\n", disk->disk_name, args->capacity, capacity); - ret = -ENODEV; + /* Force a retry if we have a valid (non-zero) capacity. */ + if (capacity) + ret = -EAGAIN; + else + ret = -ENODEV; goto unfreeze; } @@ -2491,6 +2495,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk) .data = &args, }; unsigned int noio_flag; + int retries = 2; int ret; if (WARN_ON_ONCE(!blk_queue_is_zoned(disk->queue))) @@ -2502,6 +2507,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk) */ mutex_lock(&disk->zone_revalidate_mutex); +again: ret = disk_revalidate_capacity(disk, &args); if (ret) goto unlock; @@ -2546,10 +2552,18 @@ int blk_revalidate_disk_zones(struct gendisk *disk) return 0; free_args: - pr_warn("%s: failed to revalidate zones\n", disk->disk_name); - kfree(args.zones_state); + if (ret == -EAGAIN) { + if (retries) { + memset(&args, 0, sizeof(args)); + retries--; + goto again; + } + ret = -ENODEV; + } + + pr_warn("%s: failed to revalidate zones\n", disk->disk_name); unlock: mutex_unlock(&disk->zone_revalidate_mutex); -- 2.55.0