vhost: implemented indirect descriptors

Every descriptor may now contain
a separate descriptor table.

This increases the maximum number
of concurrent IO in a virtqueue
from about (vq->size / 3) to
(vq->size * SPDK_VHOST_IOVS_MAX).

Knowing that SPDK_VHOST_IOVS_MAX
is 128, and assuming that vq->size
is 128 (current hardcoded limit
for QEMU), this gives us over 16k
concurrent possible iovectors
on the fly

Change-Id: I0853d80f6f90d53f8774231972b430a5bf05460e
Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/373703
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-10-09 18:55:00 +02:00 committed by Jim Harris
parent 024e0e9095
commit 29a33dab93
6 changed files with 39 additions and 20 deletions

View File

@ -114,15 +114,30 @@ spdk_vhost_vq_avail_ring_get(struct rte_vhost_vring *vq, uint16_t *reqs, uint16_
return count; return count;
} }
static bool
spdk_vhost_vring_desc_is_indirect(struct vring_desc *cur_desc)
{
return !!(cur_desc->flags & VRING_DESC_F_INDIRECT);
}
int int
spdk_vhost_vq_get_desc(struct rte_vhost_vring *vq, uint16_t req_idx, struct vring_desc **desc, spdk_vhost_vq_get_desc(struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq, uint16_t req_idx,
struct vring_desc **desc_table, uint32_t *desc_table_size) struct vring_desc **desc, struct vring_desc **desc_table, uint32_t *desc_table_size)
{ {
if (spdk_unlikely(req_idx >= vq->size)) { if (spdk_unlikely(req_idx >= vq->size)) {
return -1; return -1;
} }
*desc = &vq->desc[req_idx]; *desc = &vq->desc[req_idx];
if (spdk_vhost_vring_desc_is_indirect(*desc)) {
assert(spdk_vhost_dev_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC));
*desc_table = spdk_vhost_gpa_to_vva(vdev, (*desc)->addr);
*desc_table_size = (*desc)->len / sizeof(**desc);
*desc = *desc_table;
return 0;
}
*desc_table = vq->desc; *desc_table = vq->desc;
*desc_table_size = vq->size; *desc_table_size = vq->size;

View File

@ -130,7 +130,7 @@ blk_iovs_setup(struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq, uint16_t
uint32_t desc_table_size, len = 0; uint32_t desc_table_size, len = 0;
int rc; int rc;
rc = spdk_vhost_vq_get_desc(vq, req_idx, &desc, &desc_table, &desc_table_size); rc = spdk_vhost_vq_get_desc(vdev, vq, req_idx, &desc, &desc_table, &desc_table_size);
if (rc != 0) { if (rc != 0) {
SPDK_ERRLOG("%s: Invalid descriptor at index %"PRIu16".\n", vdev->name, req_idx); SPDK_ERRLOG("%s: Invalid descriptor at index %"PRIu16".\n", vdev->name, req_idx);
return -1; return -1;

View File

@ -74,8 +74,7 @@
(1ULL << VIRTIO_RING_F_INDIRECT_DESC)) (1ULL << VIRTIO_RING_F_INDIRECT_DESC))
#define SPDK_VHOST_DISABLED_FEATURES ((1ULL << VHOST_F_LOG_ALL) | \ #define SPDK_VHOST_DISABLED_FEATURES ((1ULL << VHOST_F_LOG_ALL) | \
(1ULL << VIRTIO_RING_F_EVENT_IDX) | \ (1ULL << VIRTIO_RING_F_EVENT_IDX))
(1ULL << VIRTIO_RING_F_INDIRECT_DESC))
enum spdk_vhost_dev_type { enum spdk_vhost_dev_type {
SPDK_VHOST_DEV_T_SCSI, SPDK_VHOST_DEV_T_SCSI,
@ -133,6 +132,7 @@ bool spdk_vhost_vq_should_notify(struct spdk_vhost_dev *vdev, struct rte_vhost_v
* The descriptor will provide access to the entire descriptor * The descriptor will provide access to the entire descriptor
* chain. The subsequent descriptors are accesible via * chain. The subsequent descriptors are accesible via
* \c spdk_vhost_vring_desc_get_next. * \c spdk_vhost_vring_desc_get_next.
* \param vdev vhost device
* \param vq virtqueue * \param vq virtqueue
* \param req_idx descriptor index * \param req_idx descriptor index
* \param desc pointer to be set to the descriptor * \param desc pointer to be set to the descriptor
@ -144,8 +144,9 @@ bool spdk_vhost_vq_should_notify(struct spdk_vhost_dev *vdev, struct rte_vhost_v
* \return 0 on success, -1 if given index is invalid. * \return 0 on success, -1 if given index is invalid.
* If -1 is returned, the params won't be changed. * If -1 is returned, the params won't be changed.
*/ */
int spdk_vhost_vq_get_desc(struct rte_vhost_vring *vq, uint16_t req_idx, struct vring_desc **desc, int spdk_vhost_vq_get_desc(struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq,
struct vring_desc **desc_table, uint32_t *desc_table_size); uint16_t req_idx,
struct vring_desc **desc, struct vring_desc **desc_table, uint32_t *desc_table_size);
void spdk_vhost_vq_used_ring_enqueue(struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq, void spdk_vhost_vq_used_ring_enqueue(struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq,
uint16_t id, uint32_t len); uint16_t id, uint32_t len);

View File

@ -190,7 +190,7 @@ eventq_enqueue(struct spdk_vhost_scsi_dev *svdev, unsigned scsi_dev_num, uint32_
return; return;
} }
rc = spdk_vhost_vq_get_desc(vq, req, &desc, &desc_table, &desc_table_size); rc = spdk_vhost_vq_get_desc(&svdev->vdev, vq, req, &desc, &desc_table, &desc_table_size);
if (rc != 0 || desc->len < sizeof(*desc_ev)) { if (rc != 0 || desc->len < sizeof(*desc_ev)) {
SPDK_ERRLOG("Controller %s: Invalid eventq descriptor at index %"PRIu16".\n", SPDK_ERRLOG("Controller %s: Invalid eventq descriptor at index %"PRIu16".\n",
svdev->vdev.name, req); svdev->vdev.name, req);
@ -314,6 +314,7 @@ spdk_vhost_scsi_task_init_target(struct spdk_vhost_scsi_task *task, const __u8 *
static void static void
process_ctrl_request(struct spdk_vhost_scsi_task *task) process_ctrl_request(struct spdk_vhost_scsi_task *task)
{ {
struct spdk_vhost_dev *vdev = &task->svdev->vdev;
struct vring_desc *desc, *desc_table; struct vring_desc *desc, *desc_table;
struct virtio_scsi_ctrl_tmf_req *ctrl_req; struct virtio_scsi_ctrl_tmf_req *ctrl_req;
struct virtio_scsi_ctrl_an_resp *an_resp; struct virtio_scsi_ctrl_an_resp *an_resp;
@ -322,14 +323,14 @@ process_ctrl_request(struct spdk_vhost_scsi_task *task)
spdk_scsi_task_construct(&task->scsi, spdk_vhost_scsi_task_mgmt_cpl, spdk_vhost_scsi_task_free_cb, spdk_scsi_task_construct(&task->scsi, spdk_vhost_scsi_task_mgmt_cpl, spdk_vhost_scsi_task_free_cb,
NULL); NULL);
rc = spdk_vhost_vq_get_desc(task->vq, task->req_idx, &desc, &desc_table, &desc_table_size); rc = spdk_vhost_vq_get_desc(vdev, task->vq, task->req_idx, &desc, &desc_table, &desc_table_size);
if (spdk_unlikely(rc != 0)) { if (spdk_unlikely(rc != 0)) {
SPDK_ERRLOG("%s: Invalid controlq descriptor at index %d.\n", SPDK_ERRLOG("%s: Invalid controlq descriptor at index %d.\n",
task->svdev->vdev.name, task->req_idx); vdev->name, task->req_idx);
goto out; goto out;
} }
ctrl_req = spdk_vhost_gpa_to_vva(&task->svdev->vdev, desc->addr); ctrl_req = spdk_vhost_gpa_to_vva(vdev, desc->addr);
SPDK_DEBUGLOG(SPDK_TRACE_VHOST_SCSI_QUEUE, SPDK_DEBUGLOG(SPDK_TRACE_VHOST_SCSI_QUEUE,
"Processing controlq descriptor: desc %d/%p, desc_addr %p, len %d, flags %d, last_used_idx %d; kickfd %d; size %d\n", "Processing controlq descriptor: desc %d/%p, desc_addr %p, len %d, flags %d, last_used_idx %d; kickfd %d; size %d\n",
@ -343,14 +344,14 @@ process_ctrl_request(struct spdk_vhost_scsi_task *task)
spdk_vhost_vring_desc_get_next(&desc, desc_table, desc_table_size); spdk_vhost_vring_desc_get_next(&desc, desc_table, desc_table_size);
if (spdk_unlikely(desc == NULL)) { if (spdk_unlikely(desc == NULL)) {
SPDK_ERRLOG("%s: No response descriptor for controlq request %d.\n", SPDK_ERRLOG("%s: No response descriptor for controlq request %d.\n",
task->svdev->vdev.name, task->req_idx); vdev->name, task->req_idx);
goto out; goto out;
} }
/* Process the TMF request */ /* Process the TMF request */
switch (ctrl_req->type) { switch (ctrl_req->type) {
case VIRTIO_SCSI_T_TMF: case VIRTIO_SCSI_T_TMF:
task->tmf_resp = spdk_vhost_gpa_to_vva(&task->svdev->vdev, desc->addr); task->tmf_resp = spdk_vhost_gpa_to_vva(vdev, desc->addr);
/* Check if we are processing a valid request */ /* Check if we are processing a valid request */
if (task->scsi_dev == NULL) { if (task->scsi_dev == NULL) {
@ -374,7 +375,7 @@ process_ctrl_request(struct spdk_vhost_scsi_task *task)
break; break;
case VIRTIO_SCSI_T_AN_QUERY: case VIRTIO_SCSI_T_AN_QUERY:
case VIRTIO_SCSI_T_AN_SUBSCRIBE: { case VIRTIO_SCSI_T_AN_SUBSCRIBE: {
an_resp = spdk_vhost_gpa_to_vva(&task->svdev->vdev, desc->addr); an_resp = spdk_vhost_gpa_to_vva(vdev, desc->addr);
an_resp->response = VIRTIO_SCSI_S_ABORTED; an_resp->response = VIRTIO_SCSI_S_ABORTED;
break; break;
} }
@ -384,7 +385,7 @@ process_ctrl_request(struct spdk_vhost_scsi_task *task)
} }
out: out:
spdk_vhost_vq_used_ring_enqueue(&task->svdev->vdev, task->vq, task->req_idx, 0); spdk_vhost_vq_used_ring_enqueue(vdev, task->vq, task->req_idx, 0);
spdk_vhost_scsi_task_put(task); spdk_vhost_scsi_task_put(task);
} }
@ -405,7 +406,7 @@ task_data_setup(struct spdk_vhost_scsi_task *task,
uint32_t desc_table_len, len = 0; uint32_t desc_table_len, len = 0;
int rc; int rc;
rc = spdk_vhost_vq_get_desc(task->vq, task->req_idx, &desc, &desc_table, &desc_table_len); rc = spdk_vhost_vq_get_desc(vdev, task->vq, task->req_idx, &desc, &desc_table, &desc_table_len);
/* First descriptor must be readable */ /* First descriptor must be readable */
if (rc != 0 || spdk_unlikely(spdk_vhost_vring_desc_is_wr(desc))) { if (rc != 0 || spdk_unlikely(spdk_vhost_vring_desc_is_wr(desc))) {
SPDK_WARNLOG("Invalid first (request) descriptor.\n"); SPDK_WARNLOG("Invalid first (request) descriptor.\n");

View File

@ -63,8 +63,9 @@ DEFINE_STUB(spdk_ring_enqueue, size_t, (struct spdk_ring *ring, void **objs, siz
DEFINE_STUB(spdk_ring_dequeue, size_t, (struct spdk_ring *ring, void **objs, size_t count), 0); DEFINE_STUB(spdk_ring_dequeue, size_t, (struct spdk_ring *ring, void **objs, size_t count), 0);
DEFINE_STUB_V(spdk_vhost_vq_used_ring_enqueue, (struct spdk_vhost_dev *vdev, DEFINE_STUB_V(spdk_vhost_vq_used_ring_enqueue, (struct spdk_vhost_dev *vdev,
struct rte_vhost_vring *vq, uint16_t id, uint32_t len)); struct rte_vhost_vring *vq, uint16_t id, uint32_t len));
DEFINE_STUB(spdk_vhost_vq_get_desc, int, (struct rte_vhost_vring *vq, uint16_t req_idx, DEFINE_STUB(spdk_vhost_vq_get_desc, int, (struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq,
struct vring_desc **desc, struct vring_desc **desc_table, uint32_t *desc_table_size), 0); uint16_t req_idx, struct vring_desc **desc, struct vring_desc **desc_table,
uint32_t *desc_table_size), 0);
DEFINE_STUB(spdk_vhost_vring_desc_is_wr, bool, (struct vring_desc *cur_desc), false); DEFINE_STUB(spdk_vhost_vring_desc_is_wr, bool, (struct vring_desc *cur_desc), false);
DEFINE_STUB(spdk_vhost_vring_desc_to_iov, int, (struct spdk_vhost_dev *vdev, struct iovec *iov, DEFINE_STUB(spdk_vhost_vring_desc_to_iov, int, (struct spdk_vhost_dev *vdev, struct iovec *iov,
uint16_t *iov_index, const struct vring_desc *desc), 0); uint16_t *iov_index, const struct vring_desc *desc), 0);

View File

@ -59,8 +59,9 @@ DEFINE_STUB_P(spdk_scsi_lun_get_name, const char, (const struct spdk_scsi_lun *l
DEFINE_STUB(spdk_scsi_lun_get_id, int, (const struct spdk_scsi_lun *lun), 0); DEFINE_STUB(spdk_scsi_lun_get_id, int, (const struct spdk_scsi_lun *lun), 0);
DEFINE_STUB(spdk_vhost_vq_avail_ring_get, uint16_t, (struct rte_vhost_vring *vq, uint16_t *reqs, DEFINE_STUB(spdk_vhost_vq_avail_ring_get, uint16_t, (struct rte_vhost_vring *vq, uint16_t *reqs,
uint16_t reqs_len), 0); uint16_t reqs_len), 0);
DEFINE_STUB(spdk_vhost_vq_get_desc, int, (struct rte_vhost_vring *vq, uint16_t req_idx, DEFINE_STUB(spdk_vhost_vq_get_desc, int, (struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq,
struct vring_desc **desc, struct vring_desc **desc_table, uint32_t *desc_table_size), 0); uint16_t req_idx, struct vring_desc **desc, struct vring_desc **desc_table,
uint32_t *desc_table_size), 0);
DEFINE_STUB_VP(spdk_vhost_gpa_to_vva, (struct spdk_vhost_dev *vdev, uint64_t addr), {0}); DEFINE_STUB_VP(spdk_vhost_gpa_to_vva, (struct spdk_vhost_dev *vdev, uint64_t addr), {0});
DEFINE_STUB_V(spdk_vhost_vq_used_ring_enqueue, (struct spdk_vhost_dev *vdev, DEFINE_STUB_V(spdk_vhost_vq_used_ring_enqueue, (struct spdk_vhost_dev *vdev,
struct rte_vhost_vring *vq, uint16_t id, uint32_t len)); struct rte_vhost_vring *vq, uint16_t id, uint32_t len));