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>
This commit is contained in:
parent
2da6e00580
commit
3b031d1599
@ -44,13 +44,69 @@ void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts)
|
||||||
|
{
|
||||||
|
u16 status = NVME_SC_SUCCESS;
|
||||||
|
|
||||||
|
if (likely(blk_sts == BLK_STS_OK))
|
||||||
|
return status;
|
||||||
|
/*
|
||||||
|
* Right now there exists M : 1 mapping between block layer error
|
||||||
|
* to the NVMe status code (see nvme_error_status()). For consistency,
|
||||||
|
* when we reverse map we use most appropriate NVMe Status code from
|
||||||
|
* the group of the NVMe staus codes used in the nvme_error_status().
|
||||||
|
*/
|
||||||
|
switch (blk_sts) {
|
||||||
|
case BLK_STS_NOSPC:
|
||||||
|
status = NVME_SC_CAP_EXCEEDED | NVME_SC_DNR;
|
||||||
|
req->error_loc = offsetof(struct nvme_rw_command, length);
|
||||||
|
break;
|
||||||
|
case BLK_STS_TARGET:
|
||||||
|
status = NVME_SC_LBA_RANGE | NVME_SC_DNR;
|
||||||
|
req->error_loc = offsetof(struct nvme_rw_command, slba);
|
||||||
|
break;
|
||||||
|
case BLK_STS_NOTSUPP:
|
||||||
|
req->error_loc = offsetof(struct nvme_common_command, opcode);
|
||||||
|
switch (req->cmd->common.opcode) {
|
||||||
|
case nvme_cmd_dsm:
|
||||||
|
case nvme_cmd_write_zeroes:
|
||||||
|
status = NVME_SC_ONCS_NOT_SUPPORTED | NVME_SC_DNR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BLK_STS_MEDIUM:
|
||||||
|
status = NVME_SC_ACCESS_DENIED;
|
||||||
|
req->error_loc = offsetof(struct nvme_rw_command, nsid);
|
||||||
|
break;
|
||||||
|
case BLK_STS_IOERR:
|
||||||
|
/* fallthru */
|
||||||
|
default:
|
||||||
|
status = NVME_SC_INTERNAL | NVME_SC_DNR;
|
||||||
|
req->error_loc = offsetof(struct nvme_common_command, opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (req->cmd->common.opcode) {
|
||||||
|
case nvme_cmd_read:
|
||||||
|
case nvme_cmd_write:
|
||||||
|
req->error_slba = le64_to_cpu(req->cmd->rw.slba);
|
||||||
|
break;
|
||||||
|
case nvme_cmd_write_zeroes:
|
||||||
|
req->error_slba =
|
||||||
|
le64_to_cpu(req->cmd->write_zeroes.slba);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
req->error_slba = 0;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static void nvmet_bio_done(struct bio *bio)
|
static void nvmet_bio_done(struct bio *bio)
|
||||||
{
|
{
|
||||||
struct nvmet_req *req = bio->bi_private;
|
struct nvmet_req *req = bio->bi_private;
|
||||||
|
|
||||||
nvmet_req_complete(req,
|
nvmet_req_complete(req, blk_to_nvme_status(req, bio->bi_status));
|
||||||
bio->bi_status ? NVME_SC_INTERNAL | NVME_SC_DNR : 0);
|
|
||||||
|
|
||||||
if (bio != &req->b.inline_bio)
|
if (bio != &req->b.inline_bio)
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
}
|
}
|
||||||
@ -136,18 +192,21 @@ u16 nvmet_bdev_flush(struct nvmet_req *req)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 nvmet_bdev_discard_range(struct nvmet_ns *ns,
|
static u16 nvmet_bdev_discard_range(struct nvmet_req *req,
|
||||||
struct nvme_dsm_range *range, struct bio **bio)
|
struct nvme_dsm_range *range, struct bio **bio)
|
||||||
{
|
{
|
||||||
|
struct nvmet_ns *ns = req->ns;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = __blkdev_issue_discard(ns->bdev,
|
ret = __blkdev_issue_discard(ns->bdev,
|
||||||
le64_to_cpu(range->slba) << (ns->blksize_shift - 9),
|
le64_to_cpu(range->slba) << (ns->blksize_shift - 9),
|
||||||
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
|
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
|
||||||
GFP_KERNEL, 0, bio);
|
GFP_KERNEL, 0, bio);
|
||||||
if (ret && ret != -EOPNOTSUPP)
|
|
||||||
return NVME_SC_INTERNAL | NVME_SC_DNR;
|
if (ret)
|
||||||
return 0;
|
req->error_slba = le64_to_cpu(range->slba);
|
||||||
|
|
||||||
|
return blk_to_nvme_status(req, errno_to_blk_status(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nvmet_bdev_execute_discard(struct nvmet_req *req)
|
static void nvmet_bdev_execute_discard(struct nvmet_req *req)
|
||||||
@ -163,7 +222,7 @@ static void nvmet_bdev_execute_discard(struct nvmet_req *req)
|
|||||||
if (status)
|
if (status)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
status = nvmet_bdev_discard_range(req->ns, &range, &bio);
|
status = nvmet_bdev_discard_range(req, &range, &bio);
|
||||||
if (status)
|
if (status)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -204,16 +263,16 @@ static void nvmet_bdev_execute_write_zeroes(struct nvmet_req *req)
|
|||||||
u16 status = NVME_SC_SUCCESS;
|
u16 status = NVME_SC_SUCCESS;
|
||||||
sector_t sector;
|
sector_t sector;
|
||||||
sector_t nr_sector;
|
sector_t nr_sector;
|
||||||
|
int ret;
|
||||||
|
|
||||||
sector = le64_to_cpu(write_zeroes->slba) <<
|
sector = le64_to_cpu(write_zeroes->slba) <<
|
||||||
(req->ns->blksize_shift - 9);
|
(req->ns->blksize_shift - 9);
|
||||||
nr_sector = (((sector_t)le16_to_cpu(write_zeroes->length) + 1) <<
|
nr_sector = (((sector_t)le16_to_cpu(write_zeroes->length) + 1) <<
|
||||||
(req->ns->blksize_shift - 9));
|
(req->ns->blksize_shift - 9));
|
||||||
|
|
||||||
if (__blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
|
ret = __blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
|
||||||
GFP_KERNEL, &bio, 0))
|
GFP_KERNEL, &bio, 0);
|
||||||
status = NVME_SC_INTERNAL | NVME_SC_DNR;
|
status = blk_to_nvme_status(req, errno_to_blk_status(ret));
|
||||||
|
|
||||||
if (bio) {
|
if (bio) {
|
||||||
bio->bi_private = req;
|
bio->bi_private = req;
|
||||||
bio->bi_end_io = nvmet_bio_done;
|
bio->bi_end_io = nvmet_bio_done;
|
||||||
@ -248,6 +307,7 @@ u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
|
|||||||
default:
|
default:
|
||||||
pr_err("unhandled cmd %d on qid %d\n", cmd->common.opcode,
|
pr_err("unhandled cmd %d on qid %d\n", cmd->common.opcode,
|
||||||
req->sq->qid);
|
req->sq->qid);
|
||||||
|
req->error_loc = offsetof(struct nvme_common_command, opcode);
|
||||||
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
|
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user