summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Cassel <cassel@kernel.org>2026-10-22 11:22:01 +0200
committerJens Axboe <axboe@kernel.dk>2026-11-03 07:11:35 -0700
commit973bf587d79f061beffdd392e77012a07f25fcd6 (patch)
treee979e42af96c8eae6a68c76d1360b3d79b4d6cff
parent6f2b59737bf9cf3623719857ac149f0d431db109 (diff)
null_blk: don't finish zones to set them read-only or offline
null_set_zone_cond() calls null_finish_zone() to release the zone resources held by a zone before setting it read-only or offline. For an empty or closed zone, null_finish_zone() first runs the zone resource checks, which can close an unrelated implicitly open zone, or fail. As the error is ignored, a failure for a closed zone leaks nr_zones_closed, permanently lowering the effective active zone limit. Setting a zone read-only or offline requires no zone resources, so release the zone resources held by the zone directly instead, using a new helper, null_release_zone_resources(). Fixes: d3a5738849e0 ("null_blk: support read-only and offline zone conditions") Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Niklas Cassel <cassel@kernel.org> Link: https://patch.msgid.link/20261022092158.2248831-7-cassel@kernel.org Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/block/null_blk/zoned.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c
index ecdc8d68ca2a..015f5d304c7c 100644
--- a/drivers/block/null_blk/zoned.c
+++ b/drivers/block/null_blk/zoned.c
@@ -744,6 +744,33 @@ blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_op op,
}
/*
+ * Release the zone resources held by a zone, before changing the condition of
+ * the zone to a condition that does not hold any zone resources.
+ */
+static void null_release_zone_resources(struct nullb_device *dev,
+ struct nullb_zone *zone)
+{
+ if (!dev->need_zone_res_mgmt)
+ return;
+
+ spin_lock(&dev->zone_res_lock);
+ switch (zone->cond) {
+ case BLK_ZONE_COND_IMP_OPEN:
+ dev->nr_zones_imp_open--;
+ break;
+ case BLK_ZONE_COND_EXP_OPEN:
+ dev->nr_zones_exp_open--;
+ break;
+ case BLK_ZONE_COND_CLOSED:
+ dev->nr_zones_closed--;
+ break;
+ default:
+ break;
+ }
+ spin_unlock(&dev->zone_res_lock);
+}
+
+/*
* Set a zone in the read-only or offline condition.
*/
static void null_set_zone_cond(struct nullb_device *dev,
@@ -759,8 +786,8 @@ static void null_set_zone_cond(struct nullb_device *dev,
* If the read-only condition is requested again to zones already in
* read-only condition, restore back normal empty condition. Do the same
* if the offline condition is requested for offline zones. Otherwise,
- * set the specified zone condition to the zones. Finish the zones
- * beforehand to free up zone resources.
+ * set the specified zone condition to the zones. Release the zone
+ * resources held by the zones beforehand.
*/
if (zone->cond == cond) {
zone->cond = BLK_ZONE_COND_EMPTY;
@@ -768,9 +795,7 @@ static void null_set_zone_cond(struct nullb_device *dev,
if (dev->memory_backed)
null_handle_discard(dev, zone->start, zone->len);
} else {
- if (zone->cond != BLK_ZONE_COND_READONLY &&
- zone->cond != BLK_ZONE_COND_OFFLINE)
- null_finish_zone(dev, zone);
+ null_release_zone_resources(dev, zone);
zone->cond = cond;
zone->wp = NULL_ZONE_INVALID_WP;
}