summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Le Moal <dlemoal@kernel.org>2026-09-08 17:57:40 +0900
committerJens Axboe <axboe@kernel.dk>2026-09-15 06:53:06 -0600
commitdf5de259ba5cd4802242cbc57fcb8c038fcf79f9 (patch)
tree866957f20a5bbc208d3697077243c3185c3881a3
parentc0832c20104e2427e2c2fa0d953891be46207d4c (diff)
downloadlinux-next-df5de259ba5cd4802242cbc57fcb8c038fcf79f9.tar.gz
linux-next-df5de259ba5cd4802242cbc57fcb8c038fcf79f9.zip
block: retry zone revalidation on capacity change
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 <dlemoal@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@kernel.org> Link: https://patch.msgid.link/20260908085745.1082697-12-dlemoal@kernel.org Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/blk-zoned.c20
1 files 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);