diff options
| author | Niklas Cassel <cassel@kernel.org> | 2026-10-22 11:22:01 +0200 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2026-11-03 07:11:35 -0700 |
| commit | 973bf587d79f061beffdd392e77012a07f25fcd6 (patch) | |
| tree | e979e42af96c8eae6a68c76d1360b3d79b4d6cff | |
| parent | 6f2b59737bf9cf3623719857ac149f0d431db109 (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.c | 35 |
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; } |
