@@ -85,6 +85,29 @@ struct nullb {
char disk_name[DISK_NAME_LEN];
};
+blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
+ sector_t sector, sector_t nr_sectors);
+blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_opf op);
+
+static inline blk_status_t null_process_cmd(struct nullb_cmd *cmd,
+ enum req_opf op, sector_t sector,
+ unsigned int nr_sectors)
+{
+ struct nullb_device *dev = cmd->nq->dev;
+ blk_status_t ret;
+
+ if (dev->badblocks.shift != -1) {
+ ret = null_handle_badblocks(cmd, sector, nr_sectors);
+ if (ret != BLK_STS_OK)
+ return ret;
+ }
+
+ if (dev->memory_backed)
+ return null_handle_memory_backed(cmd, op);
+
+ return BLK_STS_OK;
+}
+
#ifdef CONFIG_BLK_DEV_ZONED
int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q);
int null_register_zoned_dev(struct nullb *nullb);
@@ -1214,9 +1214,8 @@ static inline blk_status_t null_handle_throttled(struct nullb_cmd *cmd)
return sts;
}
-static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
- sector_t sector,
- sector_t nr_sectors)
+blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
+ sector_t sector, sector_t nr_sectors)
{
struct badblocks *bb = &cmd->nq->dev->badblocks;
sector_t first_bad;
@@ -1228,12 +1227,14 @@ static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
return BLK_STS_OK;
}
-static inline blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd,
- enum req_opf op)
+blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_opf op)
{
struct nullb_device *dev = cmd->nq->dev;
int err;
+ if (!dev->memory_backed)
+ return BLK_STS_OK;
+
if (dev->queue_mode == NULL_Q_BIO)
err = null_handle_bio(cmd);
else
@@ -1286,17 +1287,12 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
goto out;
}
- if (nullb->dev->badblocks.shift != -1) {
- cmd->error = null_handle_badblocks(cmd, sector, nr_sectors);
- if (cmd->error != BLK_STS_OK)
- goto out;
+ if (dev->zoned) {
+ cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
+ goto out;
}
- if (dev->memory_backed)
- cmd->error = null_handle_memory_backed(cmd, op);
-
- if (!cmd->error && dev->zoned)
- cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
+ cmd->error = null_process_cmd(cmd, op, sector, nr_sectors);
out:
nullb_complete_cmd(cmd);
@@ -138,11 +138,14 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
struct nullb_device *dev = cmd->nq->dev;
unsigned int zno = null_zone_no(dev, sector);
struct blk_zone *zone = &dev->zones[zno];
+ blk_status_t ret;
+
+ if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
+ return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
switch (zone->cond) {
case BLK_ZONE_COND_FULL:
/* Cannot write to a full zone */
- cmd->error = BLK_STS_IOERR;
return BLK_STS_IOERR;
case BLK_ZONE_COND_EMPTY:
case BLK_ZONE_COND_IMP_OPEN:
@@ -155,17 +158,18 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
zone->cond = BLK_ZONE_COND_IMP_OPEN;
+ ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
+ if (ret != BLK_STS_OK)
+ return ret;
+
zone->wp += nr_sectors;
if (zone->wp == zone->start + zone->len)
zone->cond = BLK_ZONE_COND_FULL;
- break;
- case BLK_ZONE_COND_NOT_WP:
- break;
+ return BLK_STS_OK;
default:
/* Invalid zone condition */
return BLK_STS_IOERR;
}
- return BLK_STS_OK;
}
static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
@@ -236,6 +240,6 @@ blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op,
case REQ_OP_ZONE_FINISH:
return null_zone_mgmt(cmd, op, sector);
default:
- return BLK_STS_OK;
+ return null_process_cmd(cmd, op, sector, nr_sectors);
}
}
For writes operations issued to a null_blk device with zoned mode enabled, the state and write pointer position of the zone targeted by the write command should be checked before badblocks and memory backing is handled as the write may be first failed due to, for instance, a sector position not aligned with the zone write pointer. This als reflects more accuratly the behavior of a physical zoned device. Furthermore, the write pointer position of the target zone should be incremented only and only if no errors are reported by badblocks and memory backing handling. To fix this, introduce the small inline helper function null_process_cmd() which execute null_handle_badblocks() and null_handle_memory_backed() and use this function in null_zone_write() to correctly handle write requests to zoned null devices depending on the type and state of the write target zone. Also call this function in null_handle_zoned() to process read requests to zoned null devices. This new helper is called from null_handle_cmd() only for regular null devices, resulting in no functional change for these. Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com> --- drivers/block/null_blk.h | 23 +++++++++++++++++++++++ drivers/block/null_blk_main.c | 24 ++++++++++-------------- drivers/block/null_blk_zoned.c | 16 ++++++++++------ 3 files changed, 43 insertions(+), 20 deletions(-)