Skip to content

Commit 3b031d1

Browse files
ChaitanayaKulkarniChristoph Hellwig
authored andcommitted
nvmet: add error log support for bdev backend
This patch adds the support for the block device backend to populate the error log entries. Here we map the blk_status_t to the NVMe status. Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent 2da6e00 commit 3b031d1

File tree

1 file changed

+72
-12
lines changed

1 file changed

+72
-12
lines changed

drivers/nvme/target/io-cmd-bdev.c

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,69 @@ void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
4444
}
4545
}
4646

47+
static u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts)
48+
{
49+
u16 status = NVME_SC_SUCCESS;
50+
51+
if (likely(blk_sts == BLK_STS_OK))
52+
return status;
53+
/*
54+
* Right now there exists M : 1 mapping between block layer error
55+
* to the NVMe status code (see nvme_error_status()). For consistency,
56+
* when we reverse map we use most appropriate NVMe Status code from
57+
* the group of the NVMe staus codes used in the nvme_error_status().
58+
*/
59+
switch (blk_sts) {
60+
case BLK_STS_NOSPC:
61+
status = NVME_SC_CAP_EXCEEDED | NVME_SC_DNR;
62+
req->error_loc = offsetof(struct nvme_rw_command, length);
63+
break;
64+
case BLK_STS_TARGET:
65+
status = NVME_SC_LBA_RANGE | NVME_SC_DNR;
66+
req->error_loc = offsetof(struct nvme_rw_command, slba);
67+
break;
68+
case BLK_STS_NOTSUPP:
69+
req->error_loc = offsetof(struct nvme_common_command, opcode);
70+
switch (req->cmd->common.opcode) {
71+
case nvme_cmd_dsm:
72+
case nvme_cmd_write_zeroes:
73+
status = NVME_SC_ONCS_NOT_SUPPORTED | NVME_SC_DNR;
74+
break;
75+
default:
76+
status = NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
77+
}
78+
break;
79+
case BLK_STS_MEDIUM:
80+
status = NVME_SC_ACCESS_DENIED;
81+
req->error_loc = offsetof(struct nvme_rw_command, nsid);
82+
break;
83+
case BLK_STS_IOERR:
84+
/* fallthru */
85+
default:
86+
status = NVME_SC_INTERNAL | NVME_SC_DNR;
87+
req->error_loc = offsetof(struct nvme_common_command, opcode);
88+
}
89+
90+
switch (req->cmd->common.opcode) {
91+
case nvme_cmd_read:
92+
case nvme_cmd_write:
93+
req->error_slba = le64_to_cpu(req->cmd->rw.slba);
94+
break;
95+
case nvme_cmd_write_zeroes:
96+
req->error_slba =
97+
le64_to_cpu(req->cmd->write_zeroes.slba);
98+
break;
99+
default:
100+
req->error_slba = 0;
101+
}
102+
return status;
103+
}
104+
47105
static void nvmet_bio_done(struct bio *bio)
48106
{
49107
struct nvmet_req *req = bio->bi_private;
50108

51-
nvmet_req_complete(req,
52-
bio->bi_status ? NVME_SC_INTERNAL | NVME_SC_DNR : 0);
53-
109+
nvmet_req_complete(req, blk_to_nvme_status(req, bio->bi_status));
54110
if (bio != &req->b.inline_bio)
55111
bio_put(bio);
56112
}
@@ -136,18 +192,21 @@ u16 nvmet_bdev_flush(struct nvmet_req *req)
136192
return 0;
137193
}
138194

139-
static u16 nvmet_bdev_discard_range(struct nvmet_ns *ns,
195+
static u16 nvmet_bdev_discard_range(struct nvmet_req *req,
140196
struct nvme_dsm_range *range, struct bio **bio)
141197
{
198+
struct nvmet_ns *ns = req->ns;
142199
int ret;
143200

144201
ret = __blkdev_issue_discard(ns->bdev,
145202
le64_to_cpu(range->slba) << (ns->blksize_shift - 9),
146203
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
147204
GFP_KERNEL, 0, bio);
148-
if (ret && ret != -EOPNOTSUPP)
149-
return NVME_SC_INTERNAL | NVME_SC_DNR;
150-
return 0;
205+
206+
if (ret)
207+
req->error_slba = le64_to_cpu(range->slba);
208+
209+
return blk_to_nvme_status(req, errno_to_blk_status(ret));
151210
}
152211

153212
static void nvmet_bdev_execute_discard(struct nvmet_req *req)
@@ -163,7 +222,7 @@ static void nvmet_bdev_execute_discard(struct nvmet_req *req)
163222
if (status)
164223
break;
165224

166-
status = nvmet_bdev_discard_range(req->ns, &range, &bio);
225+
status = nvmet_bdev_discard_range(req, &range, &bio);
167226
if (status)
168227
break;
169228
}
@@ -204,16 +263,16 @@ static void nvmet_bdev_execute_write_zeroes(struct nvmet_req *req)
204263
u16 status = NVME_SC_SUCCESS;
205264
sector_t sector;
206265
sector_t nr_sector;
266+
int ret;
207267

208268
sector = le64_to_cpu(write_zeroes->slba) <<
209269
(req->ns->blksize_shift - 9);
210270
nr_sector = (((sector_t)le16_to_cpu(write_zeroes->length) + 1) <<
211271
(req->ns->blksize_shift - 9));
212272

213-
if (__blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
214-
GFP_KERNEL, &bio, 0))
215-
status = NVME_SC_INTERNAL | NVME_SC_DNR;
216-
273+
ret = __blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
274+
GFP_KERNEL, &bio, 0);
275+
status = blk_to_nvme_status(req, errno_to_blk_status(ret));
217276
if (bio) {
218277
bio->bi_private = req;
219278
bio->bi_end_io = nvmet_bio_done;
@@ -248,6 +307,7 @@ u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
248307
default:
249308
pr_err("unhandled cmd %d on qid %d\n", cmd->common.opcode,
250309
req->sq->qid);
310+
req->error_loc = offsetof(struct nvme_common_command, opcode);
251311
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
252312
}
253313
}

0 commit comments

Comments
 (0)