Skip to content

Commit b228ba1

Browse files
committed
null_blk: fix zoned support for non-rq based operation
The supported added for zones in null_blk seem to assume that only rq based operation is possible. But this depends on the queue_mode setting, if this is set to 0, then cmd->bio is what we need to be operating on. Right now any attempt to load null_blk with queue_mode=0 will insta-crash, since cmd->rq is NULL and null_handle_cmd() assumes it to always be set. Make the zoned code deal with bio's instead, or pass in the appropriate sector/nr_sectors instead. Fixes: ca4b2a0 ("null_blk: add zone support") Tested-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 01c5f85 commit b228ba1

File tree

3 files changed

+62
-34
lines changed

3 files changed

+62
-34
lines changed

drivers/block/null_blk.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,25 @@ struct nullb {
8787
#ifdef CONFIG_BLK_DEV_ZONED
8888
int null_zone_init(struct nullb_device *dev);
8989
void null_zone_exit(struct nullb_device *dev);
90-
blk_status_t null_zone_report(struct nullb *nullb,
91-
struct nullb_cmd *cmd);
92-
void null_zone_write(struct nullb_cmd *cmd);
93-
void null_zone_reset(struct nullb_cmd *cmd);
90+
blk_status_t null_zone_report(struct nullb *nullb, struct bio *bio);
91+
void null_zone_write(struct nullb_cmd *cmd, sector_t sector,
92+
unsigned int nr_sectors);
93+
void null_zone_reset(struct nullb_cmd *cmd, sector_t sector);
9494
#else
9595
static inline int null_zone_init(struct nullb_device *dev)
9696
{
9797
return -EINVAL;
9898
}
9999
static inline void null_zone_exit(struct nullb_device *dev) {}
100100
static inline blk_status_t null_zone_report(struct nullb *nullb,
101-
struct nullb_cmd *cmd)
101+
struct bio *bio)
102102
{
103103
return BLK_STS_NOTSUPP;
104104
}
105-
static inline void null_zone_write(struct nullb_cmd *cmd) {}
106-
static inline void null_zone_reset(struct nullb_cmd *cmd) {}
105+
static inline void null_zone_write(struct nullb_cmd *cmd, sector_t sector,
106+
unsigned int nr_sectors)
107+
{
108+
}
109+
static inline void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) {}
107110
#endif /* CONFIG_BLK_DEV_ZONED */
108111
#endif /* __NULL_BLK_H */

drivers/block/null_blk_main.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,16 +1157,33 @@ static void null_restart_queue_async(struct nullb *nullb)
11571157
}
11581158
}
11591159

1160+
static bool cmd_report_zone(struct nullb *nullb, struct nullb_cmd *cmd)
1161+
{
1162+
struct nullb_device *dev = cmd->nq->dev;
1163+
1164+
if (dev->queue_mode == NULL_Q_BIO) {
1165+
if (bio_op(cmd->bio) == REQ_OP_ZONE_REPORT) {
1166+
cmd->error = null_zone_report(nullb, cmd->bio);
1167+
return true;
1168+
}
1169+
} else {
1170+
if (req_op(cmd->rq) == REQ_OP_ZONE_REPORT) {
1171+
cmd->error = null_zone_report(nullb, cmd->rq->bio);
1172+
return true;
1173+
}
1174+
}
1175+
1176+
return false;
1177+
}
1178+
11601179
static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
11611180
{
11621181
struct nullb_device *dev = cmd->nq->dev;
11631182
struct nullb *nullb = dev->nullb;
11641183
int err = 0;
11651184

1166-
if (req_op(cmd->rq) == REQ_OP_ZONE_REPORT) {
1167-
cmd->error = null_zone_report(nullb, cmd);
1185+
if (cmd_report_zone(nullb, cmd))
11681186
goto out;
1169-
}
11701187

11711188
if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) {
11721189
struct request *rq = cmd->rq;
@@ -1234,10 +1251,24 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
12341251
cmd->error = errno_to_blk_status(err);
12351252

12361253
if (!cmd->error && dev->zoned) {
1237-
if (req_op(cmd->rq) == REQ_OP_WRITE)
1238-
null_zone_write(cmd);
1239-
else if (req_op(cmd->rq) == REQ_OP_ZONE_RESET)
1240-
null_zone_reset(cmd);
1254+
sector_t sector;
1255+
unsigned int nr_sectors;
1256+
int op;
1257+
1258+
if (dev->queue_mode == NULL_Q_BIO) {
1259+
op = bio_op(cmd->bio);
1260+
sector = cmd->bio->bi_iter.bi_sector;
1261+
nr_sectors = cmd->bio->bi_iter.bi_size >> 9;
1262+
} else {
1263+
op = req_op(cmd->rq);
1264+
sector = blk_rq_pos(cmd->rq);
1265+
nr_sectors = blk_rq_sectors(cmd->rq);
1266+
}
1267+
1268+
if (op == REQ_OP_WRITE)
1269+
null_zone_write(cmd, sector, nr_sectors);
1270+
else if (op == REQ_OP_ZONE_RESET)
1271+
null_zone_reset(cmd, sector);
12411272
}
12421273
out:
12431274
/* Complete IO by inline, softirq or timer */

drivers/block/null_blk_zoned.c

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ void null_zone_exit(struct nullb_device *dev)
4848
kvfree(dev->zones);
4949
}
5050

51-
static void null_zone_fill_rq(struct nullb_device *dev, struct request *rq,
52-
unsigned int zno, unsigned int nr_zones)
51+
static void null_zone_fill_bio(struct nullb_device *dev, struct bio *bio,
52+
unsigned int zno, unsigned int nr_zones)
5353
{
5454
struct blk_zone_report_hdr *hdr = NULL;
5555
struct bio_vec bvec;
5656
struct bvec_iter iter;
5757
void *addr;
5858
unsigned int zones_to_cpy;
5959

60-
bio_for_each_segment(bvec, rq->bio, iter) {
60+
bio_for_each_segment(bvec, bio, iter) {
6161
addr = kmap_atomic(bvec.bv_page);
6262

6363
zones_to_cpy = bvec.bv_len / sizeof(struct blk_zone);
@@ -84,29 +84,24 @@ static void null_zone_fill_rq(struct nullb_device *dev, struct request *rq,
8484
}
8585
}
8686

87-
blk_status_t null_zone_report(struct nullb *nullb,
88-
struct nullb_cmd *cmd)
87+
blk_status_t null_zone_report(struct nullb *nullb, struct bio *bio)
8988
{
9089
struct nullb_device *dev = nullb->dev;
91-
struct request *rq = cmd->rq;
92-
unsigned int zno = null_zone_no(dev, blk_rq_pos(rq));
90+
unsigned int zno = null_zone_no(dev, bio->bi_iter.bi_sector);
9391
unsigned int nr_zones = dev->nr_zones - zno;
94-
unsigned int max_zones = (blk_rq_bytes(rq) /
95-
sizeof(struct blk_zone)) - 1;
92+
unsigned int max_zones;
9693

94+
max_zones = (bio->bi_iter.bi_size / sizeof(struct blk_zone)) - 1;
9795
nr_zones = min_t(unsigned int, nr_zones, max_zones);
98-
99-
null_zone_fill_rq(nullb->dev, rq, zno, nr_zones);
96+
null_zone_fill_bio(nullb->dev, bio, zno, nr_zones);
10097

10198
return BLK_STS_OK;
10299
}
103100

104-
void null_zone_write(struct nullb_cmd *cmd)
101+
void null_zone_write(struct nullb_cmd *cmd, sector_t sector,
102+
unsigned int nr_sectors)
105103
{
106104
struct nullb_device *dev = cmd->nq->dev;
107-
struct request *rq = cmd->rq;
108-
sector_t sector = blk_rq_pos(rq);
109-
unsigned int rq_sectors = blk_rq_sectors(rq);
110105
unsigned int zno = null_zone_no(dev, sector);
111106
struct blk_zone *zone = &dev->zones[zno];
112107

@@ -118,15 +113,15 @@ void null_zone_write(struct nullb_cmd *cmd)
118113
case BLK_ZONE_COND_EMPTY:
119114
case BLK_ZONE_COND_IMP_OPEN:
120115
/* Writes must be at the write pointer position */
121-
if (blk_rq_pos(rq) != zone->wp) {
116+
if (sector != zone->wp) {
122117
cmd->error = BLK_STS_IOERR;
123118
break;
124119
}
125120

126121
if (zone->cond == BLK_ZONE_COND_EMPTY)
127122
zone->cond = BLK_ZONE_COND_IMP_OPEN;
128123

129-
zone->wp += rq_sectors;
124+
zone->wp += nr_sectors;
130125
if (zone->wp == zone->start + zone->len)
131126
zone->cond = BLK_ZONE_COND_FULL;
132127
break;
@@ -137,11 +132,10 @@ void null_zone_write(struct nullb_cmd *cmd)
137132
}
138133
}
139134

140-
void null_zone_reset(struct nullb_cmd *cmd)
135+
void null_zone_reset(struct nullb_cmd *cmd, sector_t sector)
141136
{
142137
struct nullb_device *dev = cmd->nq->dev;
143-
struct request *rq = cmd->rq;
144-
unsigned int zno = null_zone_no(dev, blk_rq_pos(rq));
138+
unsigned int zno = null_zone_no(dev, sector);
145139
struct blk_zone *zone = &dev->zones[zno];
146140

147141
zone->cond = BLK_ZONE_COND_EMPTY;

0 commit comments

Comments
 (0)