vhost/nvme: factor out task completion function

This clarifies the bdev_io completion callbacks, since they can now
assume that they always have a valid bdev_io. All call sites that
originally passed NULL for bdev_io now set an appropriate status code in
the task and complete it with the new spdk_vhost_nvme_task_complete()
function.

Change-Id: Id74aafb28e83e135bbb0a410ff9766dc1b9ece50
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/410080
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Daniel Verkamp 2018-05-04 12:59:34 -07:00
parent 27a2d1d04d
commit 1d168901c6

View File

@ -109,7 +109,7 @@ struct spdk_vhost_nvme_task {
/* parent pointer. */ /* parent pointer. */
struct spdk_vhost_nvme_task *parent; struct spdk_vhost_nvme_task *parent;
bool success; uint8_t dnr;
uint8_t sct; uint8_t sct;
uint8_t sc; uint8_t sc;
uint32_t num_children; uint32_t num_children;
@ -308,53 +308,34 @@ spdk_nvme_cq_signal_fd(struct spdk_vhost_nvme_dev *nvme)
} }
static void static void
blk_request_complete_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) spdk_vhost_nvme_task_complete(struct spdk_vhost_nvme_task *task)
{ {
struct spdk_vhost_nvme_task *task = cb_arg;
struct spdk_vhost_nvme_dev *nvme = task->nvme; struct spdk_vhost_nvme_dev *nvme = task->nvme;
uint16_t cqid;
struct spdk_nvme_cpl cqe = {0}; struct spdk_nvme_cpl cqe = {0};
struct spdk_vhost_nvme_cq *cq; struct spdk_vhost_nvme_cq *cq;
struct spdk_vhost_nvme_sq *sq; struct spdk_vhost_nvme_sq *sq;
struct spdk_nvme_cmd *cmd = &task->cmd; struct spdk_nvme_cmd *cmd = &task->cmd;
int sc, sct; uint16_t cqid = task->cqid;
uint16_t sqid = task->sqid;
cqid = task->cqid;
cq = spdk_vhost_nvme_get_cq_from_qid(nvme, cqid); cq = spdk_vhost_nvme_get_cq_from_qid(nvme, cqid);
sq = spdk_vhost_nvme_get_sq_from_qid(nvme, task->sqid); sq = spdk_vhost_nvme_get_sq_from_qid(nvme, sqid);
if (spdk_unlikely(!cq || !sq)) { if (spdk_unlikely(!cq || !sq)) {
spdk_bdev_free_io(bdev_io);
return; return;
} }
task->success = success;
if (spdk_unlikely(!success && bdev_io)) {
spdk_bdev_io_get_nvme_status(bdev_io, &sct, &sc);
task->sct = sct;
task->sc = sc;
}
if (spdk_likely(bdev_io)) {
spdk_bdev_free_io(bdev_io);
}
cq->guest_signaled_cq_head = nvme->dbbuf_dbs[cq_offset(cqid, 1)]; cq->guest_signaled_cq_head = nvme->dbbuf_dbs[cq_offset(cqid, 1)];
if (spdk_unlikely(nvme_cq_is_full(cq))) { if (spdk_unlikely(nvme_cq_is_full(cq))) {
STAILQ_INSERT_TAIL(&cq->cq_full_waited_tasks, task, stailq); STAILQ_INSERT_TAIL(&cq->cq_full_waited_tasks, task, stailq);
return; return;
} }
cqe.sqid = task->sqid; cqe.sqid = sqid;
cqe.sqhd = sq->sq_head; cqe.sqhd = sq->sq_head;
cqe.cid = cmd->cid; cqe.cid = cmd->cid;
cqe.status.sct = 0; cqe.status.dnr = task->dnr;
cqe.status.sc = 0; cqe.status.sct = task->sct;
if (spdk_unlikely(!success)) { cqe.status.sc = task->sc;
cqe.status.sct = task->sct;
cqe.status.sc = task->sc;
cqe.status.dnr = 1;
SPDK_ERRLOG("I/O error, sector %u\n", cmd->cdw10);
}
cqe.status.p = !cq->phase; cqe.status.p = !cq->phase;
cq->cq_cqe[cq->cq_head] = cqe; cq->cq_cqe[cq->cq_head] = cqe;
spdk_smp_wmb(); spdk_smp_wmb();
@ -369,23 +350,51 @@ blk_request_complete_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg
STAILQ_INSERT_TAIL(&nvme->free_tasks, task, stailq); STAILQ_INSERT_TAIL(&nvme->free_tasks, task, stailq);
} }
static void
blk_request_complete_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
struct spdk_vhost_nvme_task *task = cb_arg;
struct spdk_nvme_cmd *cmd = &task->cmd;
int sc, sct;
assert(bdev_io != NULL);
spdk_bdev_io_get_nvme_status(bdev_io, &sct, &sc);
spdk_bdev_free_io(bdev_io);
task->dnr = !success;
task->sct = sct;
task->sc = sc;
if (spdk_unlikely(!success)) {
SPDK_ERRLOG("I/O error, sector %u\n", cmd->cdw10);
}
spdk_vhost_nvme_task_complete(task);
}
static void static void
blk_unmap_complete_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) blk_unmap_complete_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{ {
struct spdk_vhost_nvme_task *child = cb_arg; struct spdk_vhost_nvme_task *child = cb_arg;
struct spdk_vhost_nvme_task *task = child->parent; struct spdk_vhost_nvme_task *task = child->parent;
struct spdk_vhost_nvme_dev *nvme = task->nvme; struct spdk_vhost_nvme_dev *nvme = task->nvme;
int sct, sc;
if (bdev_io) { assert(bdev_io != NULL);
spdk_bdev_free_io(bdev_io);
}
task->num_children--; task->num_children--;
if (!success) { if (!success) {
task->success = false; task->dnr = 1;
spdk_bdev_io_get_nvme_status(bdev_io, &sct, &sc);
task->sct = sct;
task->sc = sc;
} }
spdk_bdev_free_io(bdev_io);
if (!task->num_children) { if (!task->num_children) {
blk_request_complete_cb(NULL, task->success, task); spdk_vhost_nvme_task_complete(task);
} }
STAILQ_INSERT_TAIL(&nvme->free_tasks, child, stailq); STAILQ_INSERT_TAIL(&nvme->free_tasks, child, stailq);
@ -415,21 +424,29 @@ spdk_nvme_process_sq(struct spdk_vhost_nvme_dev *nvme, struct spdk_vhost_nvme_sq
uint16_t i, num_ranges = 0; uint16_t i, num_ranges = 0;
task->nvme = nvme; task->nvme = nvme;
task->dnr = 0;
task->sct = 0;
task->sc = 0;
ns = spdk_vhost_nvme_get_ns_from_nsid(nvme, cmd->nsid); ns = spdk_vhost_nvme_get_ns_from_nsid(nvme, cmd->nsid);
if (spdk_unlikely(!ns)) { if (spdk_unlikely(!ns)) {
blk_request_complete_cb(NULL, false, task); task->dnr = 1;
task->sct = SPDK_NVME_SCT_GENERIC;
task->sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT;
spdk_vhost_nvme_task_complete(task);
return -1; return -1;
} }
block_size = ns->block_size; block_size = ns->block_size;
task->success = true;
task->num_children = 0; task->num_children = 0;
task->cqid = sq->cqid; task->cqid = sq->cqid;
task->sqid = sq->sqid; task->sqid = sq->sqid;
if (spdk_unlikely(!ns->active_ns)) { if (spdk_unlikely(!ns->active_ns)) {
blk_request_complete_cb(NULL, false, task); task->dnr = 1;
task->sct = SPDK_NVME_SCT_GENERIC;
task->sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT;
spdk_vhost_nvme_task_complete(task);
return -1; return -1;
} }
@ -443,7 +460,10 @@ spdk_nvme_process_sq(struct spdk_vhost_nvme_dev *nvme, struct spdk_vhost_nvme_sq
if (cmd->psdt != SPDK_NVME_PSDT_PRP) { if (cmd->psdt != SPDK_NVME_PSDT_PRP) {
SPDK_DEBUGLOG(SPDK_LOG_VHOST_NVME, "Invalid PSDT %u%ub in command\n", SPDK_DEBUGLOG(SPDK_LOG_VHOST_NVME, "Invalid PSDT %u%ub in command\n",
cmd->psdt >> 1, cmd->psdt & 1u); cmd->psdt >> 1, cmd->psdt & 1u);
blk_request_complete_cb(NULL, false, task); task->dnr = 1;
task->sct = SPDK_NVME_SCT_GENERIC;
task->sc = SPDK_NVME_SC_INVALID_FIELD;
spdk_vhost_nvme_task_complete(task);
return -1; return -1;
} }
@ -457,7 +477,10 @@ spdk_nvme_process_sq(struct spdk_vhost_nvme_dev *nvme, struct spdk_vhost_nvme_sq
ret = spdk_nvme_map_prps(nvme, cmd, task, len); ret = spdk_nvme_map_prps(nvme, cmd, task, len);
if (spdk_unlikely(ret != 0)) { if (spdk_unlikely(ret != 0)) {
SPDK_ERRLOG("nvme command map prps failed\n"); SPDK_ERRLOG("nvme command map prps failed\n");
blk_request_complete_cb(NULL, false, task); task->dnr = 1;
task->sct = SPDK_NVME_SCT_GENERIC;
task->sc = SPDK_NVME_SC_INVALID_FIELD;
spdk_vhost_nvme_task_complete(task);
return -1; return -1;
} }
} }
@ -509,7 +532,10 @@ spdk_nvme_process_sq(struct spdk_vhost_nvme_dev *nvme, struct spdk_vhost_nvme_sq
if (spdk_unlikely(ret)) { if (spdk_unlikely(ret)) {
/* post error status to cqe */ /* post error status to cqe */
SPDK_ERRLOG("Error Submission For Command %u, ret %d\n", cmd->opc, ret); SPDK_ERRLOG("Error Submission For Command %u, ret %d\n", cmd->opc, ret);
blk_request_complete_cb(NULL, false, task); task->dnr = 1;
task->sct = SPDK_NVME_SCT_GENERIC;
task->sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
spdk_vhost_nvme_task_complete(task);
} }
return ret; return ret;
@ -552,7 +578,7 @@ nvme_worker(void *arg)
!nvme_cq_is_full(cq))) { !nvme_cq_is_full(cq))) {
task = STAILQ_FIRST(&cq->cq_full_waited_tasks); task = STAILQ_FIRST(&cq->cq_full_waited_tasks);
STAILQ_REMOVE_HEAD(&cq->cq_full_waited_tasks, stailq); STAILQ_REMOVE_HEAD(&cq->cq_full_waited_tasks, stailq);
blk_request_complete_cb(NULL, task->success, task); spdk_vhost_nvme_task_complete(task);
} }
dbbuf_sq = nvme->dbbuf_dbs[sq_offset(qid, 1)]; dbbuf_sq = nvme->dbbuf_dbs[sq_offset(qid, 1)];