Commit fd78874b authored by Keith Busch's avatar Keith Busch Committed by Jens Axboe

null_blk: use zone status for max active/open

The block layer provides special status codes when requests go beyond
the zone resource limits. Use these codes instead of the generic IOERR
for requests that exceed the max active or open limits the null_blk
device was configured with so that applications know how these special
conditions should be handled.
Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
Reviewed-by: default avatarNiklas Cassel <niklas.cassel@wdc.com>
Cc: Damien Le Moal <damien.lemoal@wdc.com>
Cc: Niklas Cassel <niklas.cassel@wdc.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent cb3a92da
...@@ -220,29 +220,34 @@ static void null_close_first_imp_zone(struct nullb_device *dev) ...@@ -220,29 +220,34 @@ static void null_close_first_imp_zone(struct nullb_device *dev)
} }
} }
static bool null_can_set_active(struct nullb_device *dev) static blk_status_t null_check_active(struct nullb_device *dev)
{ {
if (!dev->zone_max_active) if (!dev->zone_max_active)
return true; return BLK_STS_OK;
if (dev->nr_zones_exp_open + dev->nr_zones_imp_open +
dev->nr_zones_closed < dev->zone_max_active)
return BLK_STS_OK;
return dev->nr_zones_exp_open + dev->nr_zones_imp_open + return BLK_STS_ZONE_ACTIVE_RESOURCE;
dev->nr_zones_closed < dev->zone_max_active;
} }
static bool null_can_open(struct nullb_device *dev) static blk_status_t null_check_open(struct nullb_device *dev)
{ {
if (!dev->zone_max_open) if (!dev->zone_max_open)
return true; return BLK_STS_OK;
if (dev->nr_zones_exp_open + dev->nr_zones_imp_open < dev->zone_max_open) if (dev->nr_zones_exp_open + dev->nr_zones_imp_open < dev->zone_max_open)
return true; return BLK_STS_OK;
if (dev->nr_zones_imp_open && null_can_set_active(dev)) { if (dev->nr_zones_imp_open) {
if (null_check_active(dev) == BLK_STS_OK) {
null_close_first_imp_zone(dev); null_close_first_imp_zone(dev);
return true; return BLK_STS_OK;
}
} }
return false; return BLK_STS_ZONE_OPEN_RESOURCE;
} }
/* /*
...@@ -258,19 +263,22 @@ static bool null_can_open(struct nullb_device *dev) ...@@ -258,19 +263,22 @@ static bool null_can_open(struct nullb_device *dev)
* it is not certain that closing an implicit open zone will allow a new zone * it is not certain that closing an implicit open zone will allow a new zone
* to be opened, since we might already be at the active limit capacity. * to be opened, since we might already be at the active limit capacity.
*/ */
static bool null_has_zone_resources(struct nullb_device *dev, struct blk_zone *zone) static blk_status_t null_check_zone_resources(struct nullb_device *dev, struct blk_zone *zone)
{ {
blk_status_t ret;
switch (zone->cond) { switch (zone->cond) {
case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_EMPTY:
if (!null_can_set_active(dev)) ret = null_check_active(dev);
return false; if (ret != BLK_STS_OK)
return ret;
fallthrough; fallthrough;
case BLK_ZONE_COND_CLOSED: case BLK_ZONE_COND_CLOSED:
return null_can_open(dev); return null_check_open(dev);
default: default:
/* Should never be called for other states */ /* Should never be called for other states */
WARN_ON(1); WARN_ON(1);
return false; return BLK_STS_IOERR;
} }
} }
...@@ -293,8 +301,9 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector, ...@@ -293,8 +301,9 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
return BLK_STS_IOERR; return BLK_STS_IOERR;
case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_EMPTY:
case BLK_ZONE_COND_CLOSED: case BLK_ZONE_COND_CLOSED:
if (!null_has_zone_resources(dev, zone)) ret = null_check_zone_resources(dev, zone);
return BLK_STS_IOERR; if (ret != BLK_STS_OK)
return ret;
break; break;
case BLK_ZONE_COND_IMP_OPEN: case BLK_ZONE_COND_IMP_OPEN:
case BLK_ZONE_COND_EXP_OPEN: case BLK_ZONE_COND_EXP_OPEN:
...@@ -349,6 +358,8 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector, ...@@ -349,6 +358,8 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zone) static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zone)
{ {
blk_status_t ret;
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
return BLK_STS_IOERR; return BLK_STS_IOERR;
...@@ -357,15 +368,17 @@ static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zo ...@@ -357,15 +368,17 @@ static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zo
/* open operation on exp open is not an error */ /* open operation on exp open is not an error */
return BLK_STS_OK; return BLK_STS_OK;
case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_EMPTY:
if (!null_has_zone_resources(dev, zone)) ret = null_check_zone_resources(dev, zone);
return BLK_STS_IOERR; if (ret != BLK_STS_OK)
return ret;
break; break;
case BLK_ZONE_COND_IMP_OPEN: case BLK_ZONE_COND_IMP_OPEN:
dev->nr_zones_imp_open--; dev->nr_zones_imp_open--;
break; break;
case BLK_ZONE_COND_CLOSED: case BLK_ZONE_COND_CLOSED:
if (!null_has_zone_resources(dev, zone)) ret = null_check_zone_resources(dev, zone);
return BLK_STS_IOERR; if (ret != BLK_STS_OK)
return ret;
dev->nr_zones_closed--; dev->nr_zones_closed--;
break; break;
case BLK_ZONE_COND_FULL: case BLK_ZONE_COND_FULL:
...@@ -381,6 +394,8 @@ static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zo ...@@ -381,6 +394,8 @@ static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zo
static blk_status_t null_finish_zone(struct nullb_device *dev, struct blk_zone *zone) static blk_status_t null_finish_zone(struct nullb_device *dev, struct blk_zone *zone)
{ {
blk_status_t ret;
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
return BLK_STS_IOERR; return BLK_STS_IOERR;
...@@ -389,8 +404,9 @@ static blk_status_t null_finish_zone(struct nullb_device *dev, struct blk_zone * ...@@ -389,8 +404,9 @@ static blk_status_t null_finish_zone(struct nullb_device *dev, struct blk_zone *
/* finish operation on full is not an error */ /* finish operation on full is not an error */
return BLK_STS_OK; return BLK_STS_OK;
case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_EMPTY:
if (!null_has_zone_resources(dev, zone)) ret = null_check_zone_resources(dev, zone);
return BLK_STS_IOERR; if (ret != BLK_STS_OK)
return ret;
break; break;
case BLK_ZONE_COND_IMP_OPEN: case BLK_ZONE_COND_IMP_OPEN:
dev->nr_zones_imp_open--; dev->nr_zones_imp_open--;
...@@ -399,8 +415,9 @@ static blk_status_t null_finish_zone(struct nullb_device *dev, struct blk_zone * ...@@ -399,8 +415,9 @@ static blk_status_t null_finish_zone(struct nullb_device *dev, struct blk_zone *
dev->nr_zones_exp_open--; dev->nr_zones_exp_open--;
break; break;
case BLK_ZONE_COND_CLOSED: case BLK_ZONE_COND_CLOSED:
if (!null_has_zone_resources(dev, zone)) ret = null_check_zone_resources(dev, zone);
return BLK_STS_IOERR; if (ret != BLK_STS_OK)
return ret;
dev->nr_zones_closed--; dev->nr_zones_closed--;
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment