Skip to content

Commit 9dd44c7

Browse files
damien-lemoalaxboe
authored andcommitted
null_blk: Fix zoned command handling
For write operations issued to a null_blk device with zoned mode enabled, the state and write pointer position of the zone targeted by the command should be checked before badblocks and memory backing are handled as the write may be first failed due to, for instance, a sector position not aligned with the zone write pointer. This order of checking for errors reflects more accuratly the behavior of physical zoned devices. 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 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. null_process_cmd() is called directly from null_handle_cmd() for regular null devices, resulting in no functional change for these type of devices. To have symmetric names, the function null_handle_zoned() is renamed to null_process_zoned_cmd(). Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Chaitanya Kulkarni <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent d56deb1 commit 9dd44c7

File tree

3 files changed

+47
-27
lines changed

3 files changed

+47
-27
lines changed

drivers/block/null_blk.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,18 @@ struct nullb {
8585
char disk_name[DISK_NAME_LEN];
8686
};
8787

88+
blk_status_t null_process_cmd(struct nullb_cmd *cmd,
89+
enum req_opf op, sector_t sector,
90+
unsigned int nr_sectors);
91+
8892
#ifdef CONFIG_BLK_DEV_ZONED
8993
int null_zone_init(struct nullb_device *dev);
9094
void null_zone_exit(struct nullb_device *dev);
9195
int null_report_zones(struct gendisk *disk, sector_t sector,
9296
unsigned int nr_zones, report_zones_cb cb, void *data);
93-
blk_status_t null_handle_zoned(struct nullb_cmd *cmd,
94-
enum req_opf op, sector_t sector,
95-
sector_t nr_sectors);
97+
blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd,
98+
enum req_opf op, sector_t sector,
99+
sector_t nr_sectors);
96100
size_t null_zone_valid_read_len(struct nullb *nullb,
97101
sector_t sector, unsigned int len);
98102
#else
@@ -102,9 +106,8 @@ static inline int null_zone_init(struct nullb_device *dev)
102106
return -EINVAL;
103107
}
104108
static inline void null_zone_exit(struct nullb_device *dev) {}
105-
static inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd,
106-
enum req_opf op, sector_t sector,
107-
sector_t nr_sectors)
109+
static inline blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd,
110+
enum req_opf op, sector_t sector, sector_t nr_sectors)
108111
{
109112
return BLK_STS_NOTSUPP;
110113
}

drivers/block/null_blk_main.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,25 @@ static inline void nullb_complete_cmd(struct nullb_cmd *cmd)
12761276
}
12771277
}
12781278

1279+
blk_status_t null_process_cmd(struct nullb_cmd *cmd,
1280+
enum req_opf op, sector_t sector,
1281+
unsigned int nr_sectors)
1282+
{
1283+
struct nullb_device *dev = cmd->nq->dev;
1284+
blk_status_t ret;
1285+
1286+
if (dev->badblocks.shift != -1) {
1287+
ret = null_handle_badblocks(cmd, sector, nr_sectors);
1288+
if (ret != BLK_STS_OK)
1289+
return ret;
1290+
}
1291+
1292+
if (dev->memory_backed)
1293+
return null_handle_memory_backed(cmd, op);
1294+
1295+
return BLK_STS_OK;
1296+
}
1297+
12791298
static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
12801299
sector_t nr_sectors, enum req_opf op)
12811300
{
@@ -1294,17 +1313,11 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
12941313
goto out;
12951314
}
12961315

1297-
if (nullb->dev->badblocks.shift != -1) {
1298-
cmd->error = null_handle_badblocks(cmd, sector, nr_sectors);
1299-
if (cmd->error != BLK_STS_OK)
1300-
goto out;
1301-
}
1302-
1303-
if (dev->memory_backed)
1304-
cmd->error = null_handle_memory_backed(cmd, op);
1305-
1306-
if (!cmd->error && dev->zoned)
1307-
cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
1316+
if (dev->zoned)
1317+
cmd->error = null_process_zoned_cmd(cmd, op,
1318+
sector, nr_sectors);
1319+
else
1320+
cmd->error = null_process_cmd(cmd, op, sector, nr_sectors);
13081321

13091322
out:
13101323
nullb_complete_cmd(cmd);

drivers/block/null_blk_zoned.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,16 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
126126
struct nullb_device *dev = cmd->nq->dev;
127127
unsigned int zno = null_zone_no(dev, sector);
128128
struct blk_zone *zone = &dev->zones[zno];
129+
blk_status_t ret;
130+
131+
trace_nullb_zone_op(cmd, zno, zone->cond);
132+
133+
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
134+
return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
129135

130136
switch (zone->cond) {
131137
case BLK_ZONE_COND_FULL:
132138
/* Cannot write to a full zone */
133-
cmd->error = BLK_STS_IOERR;
134139
return BLK_STS_IOERR;
135140
case BLK_ZONE_COND_EMPTY:
136141
case BLK_ZONE_COND_IMP_OPEN:
@@ -143,19 +148,18 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
143148
if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
144149
zone->cond = BLK_ZONE_COND_IMP_OPEN;
145150

151+
ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
152+
if (ret != BLK_STS_OK)
153+
return ret;
154+
146155
zone->wp += nr_sectors;
147156
if (zone->wp == zone->start + zone->len)
148157
zone->cond = BLK_ZONE_COND_FULL;
149-
break;
150-
case BLK_ZONE_COND_NOT_WP:
151-
break;
158+
return BLK_STS_OK;
152159
default:
153160
/* Invalid zone condition */
154161
return BLK_STS_IOERR;
155162
}
156-
157-
trace_nullb_zone_op(cmd, zno, zone->cond);
158-
return BLK_STS_OK;
159163
}
160164

161165
static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
@@ -216,8 +220,8 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
216220
return BLK_STS_OK;
217221
}
218222

219-
blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op,
220-
sector_t sector, sector_t nr_sectors)
223+
blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_opf op,
224+
sector_t sector, sector_t nr_sectors)
221225
{
222226
switch (op) {
223227
case REQ_OP_WRITE:
@@ -229,6 +233,6 @@ blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op,
229233
case REQ_OP_ZONE_FINISH:
230234
return null_zone_mgmt(cmd, op, sector);
231235
default:
232-
return BLK_STS_OK;
236+
return null_process_cmd(cmd, op, sector, nr_sectors);
233237
}
234238
}

0 commit comments

Comments
 (0)