Commit 29a33dab authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Jim Harris
Browse files

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: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Signed-off-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/373703


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 024e0e90
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -114,15 +114,30 @@ spdk_vhost_vq_avail_ring_get(struct rte_vhost_vring *vq, uint16_t *reqs, uint16_
	return count;
}

static bool
spdk_vhost_vring_desc_is_indirect(struct vring_desc *cur_desc)
{
	return !!(cur_desc->flags & VRING_DESC_F_INDIRECT);
}

int
spdk_vhost_vq_get_desc(struct rte_vhost_vring *vq, uint16_t req_idx, struct vring_desc **desc,
		       struct vring_desc **desc_table, uint32_t *desc_table_size)
spdk_vhost_vq_get_desc(struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq, uint16_t req_idx,
		       struct vring_desc **desc, struct vring_desc **desc_table, uint32_t *desc_table_size)
{
	if (spdk_unlikely(req_idx >= vq->size)) {
		return -1;
	}

	*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_size = vq->size;

+1 −1
Original line number Diff line number Diff line
@@ -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;
	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) {
		SPDK_ERRLOG("%s: Invalid descriptor at index %"PRIu16".\n", vdev->name, req_idx);
		return -1;
+5 −4
Original line number Diff line number Diff line
@@ -74,8 +74,7 @@
	(1ULL << VIRTIO_RING_F_INDIRECT_DESC))

#define SPDK_VHOST_DISABLED_FEATURES ((1ULL << VHOST_F_LOG_ALL) | \
	(1ULL << VIRTIO_RING_F_EVENT_IDX) | \
	(1ULL << VIRTIO_RING_F_INDIRECT_DESC))
	(1ULL << VIRTIO_RING_F_EVENT_IDX))

enum spdk_vhost_dev_type {
	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
 * chain. The subsequent descriptors are accesible via
 * \c spdk_vhost_vring_desc_get_next.
 * \param vdev vhost device
 * \param vq virtqueue
 * \param req_idx descriptor index
 * \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.
 * 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,
			   struct vring_desc **desc_table, uint32_t *desc_table_size);
int spdk_vhost_vq_get_desc(struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq,
			   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,
				     uint16_t id, uint32_t len);

+10 −9
Original line number Diff line number Diff line
@@ -190,7 +190,7 @@ eventq_enqueue(struct spdk_vhost_scsi_dev *svdev, unsigned scsi_dev_num, uint32_
		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)) {
		SPDK_ERRLOG("Controller %s: Invalid eventq descriptor at index %"PRIu16".\n",
			    svdev->vdev.name, req);
@@ -314,6 +314,7 @@ spdk_vhost_scsi_task_init_target(struct spdk_vhost_scsi_task *task, const __u8 *
static void
process_ctrl_request(struct spdk_vhost_scsi_task *task)
{
	struct spdk_vhost_dev *vdev = &task->svdev->vdev;
	struct vring_desc *desc, *desc_table;
	struct virtio_scsi_ctrl_tmf_req *ctrl_req;
	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,
				 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)) {
		SPDK_ERRLOG("%s: Invalid controlq descriptor at index %d.\n",
			    task->svdev->vdev.name, task->req_idx);
			    vdev->name, task->req_idx);
		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,
		      "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);
	if (spdk_unlikely(desc == NULL)) {
		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;
	}

	/* Process the TMF request */
	switch (ctrl_req->type) {
	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 */
		if (task->scsi_dev == NULL) {
@@ -374,7 +375,7 @@ process_ctrl_request(struct spdk_vhost_scsi_task *task)
		break;
	case VIRTIO_SCSI_T_AN_QUERY:
	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;
		break;
	}
@@ -384,7 +385,7 @@ process_ctrl_request(struct spdk_vhost_scsi_task *task)
	}

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);
}

@@ -405,7 +406,7 @@ task_data_setup(struct spdk_vhost_scsi_task *task,
	uint32_t desc_table_len, len = 0;
	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 */
	if (rc != 0 || spdk_unlikely(spdk_vhost_vring_desc_is_wr(desc))) {
		SPDK_WARNLOG("Invalid first (request) descriptor.\n");
+3 −2
Original line number Diff line number Diff line
@@ -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_V(spdk_vhost_vq_used_ring_enqueue, (struct spdk_vhost_dev *vdev,
		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,
		struct vring_desc **desc, struct vring_desc **desc_table, uint32_t *desc_table_size), 0);
DEFINE_STUB(spdk_vhost_vq_get_desc, int, (struct spdk_vhost_dev *vdev, struct rte_vhost_vring *vq,
		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_to_iov, int, (struct spdk_vhost_dev *vdev, struct iovec *iov,
		uint16_t *iov_index, const struct vring_desc *desc), 0);
Loading