Skip to content

Commit

Permalink
nvmet: add error log support for bdev backend
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chaitanya Kulkarni authored and Christoph Hellwig committed Dec 13, 2018
1 parent 2da6e00 commit 3b031d1
Showing 1 changed file with 72 additions and 12 deletions.
84 changes: 72 additions & 12 deletions drivers/nvme/target/io-cmd-bdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct nvmet_req *req = bio->bi_private;

nvmet_req_complete(req,
bio->bi_status ? NVME_SC_INTERNAL | NVME_SC_DNR : 0);

nvmet_req_complete(req, blk_to_nvme_status(req, bio->bi_status));
if (bio != &req->b.inline_bio)
bio_put(bio);
}
Expand Down Expand Up @@ -136,18 +192,21 @@ u16 nvmet_bdev_flush(struct nvmet_req *req)
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 nvmet_ns *ns = req->ns;
int ret;

ret = __blkdev_issue_discard(ns->bdev,
le64_to_cpu(range->slba) << (ns->blksize_shift - 9),
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
GFP_KERNEL, 0, bio);
if (ret && ret != -EOPNOTSUPP)
return NVME_SC_INTERNAL | NVME_SC_DNR;
return 0;

if (ret)
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)
Expand All @@ -163,7 +222,7 @@ static void nvmet_bdev_execute_discard(struct nvmet_req *req)
if (status)
break;

status = nvmet_bdev_discard_range(req->ns, &range, &bio);
status = nvmet_bdev_discard_range(req, &range, &bio);
if (status)
break;
}
Expand Down Expand Up @@ -204,16 +263,16 @@ static void nvmet_bdev_execute_write_zeroes(struct nvmet_req *req)
u16 status = NVME_SC_SUCCESS;
sector_t sector;
sector_t nr_sector;
int ret;

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

if (__blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
GFP_KERNEL, &bio, 0))
status = NVME_SC_INTERNAL | NVME_SC_DNR;

ret = __blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
GFP_KERNEL, &bio, 0);
status = blk_to_nvme_status(req, errno_to_blk_status(ret));
if (bio) {
bio->bi_private = req;
bio->bi_end_io = nvmet_bio_done;
Expand Down Expand Up @@ -248,6 +307,7 @@ u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
default:
pr_err("unhandled cmd %d on qid %d\n", cmd->common.opcode,
req->sq->qid);
req->error_loc = offsetof(struct nvme_common_command, opcode);
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
}
}

0 comments on commit 3b031d1

Please sign in to comment.