diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index bcd4db2cd..ec0af5528 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -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; diff --git a/lib/vhost/vhost_blk.c b/lib/vhost/vhost_blk.c index a33709b85..87daa59cd 100644 --- a/lib/vhost/vhost_blk.c +++ b/lib/vhost/vhost_blk.c @@ -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; diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index cd4d220bb..74e64e90a 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -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); diff --git a/lib/vhost/vhost_scsi.c b/lib/vhost/vhost_scsi.c index 1139677a8..3122a1166 100644 --- a/lib/vhost/vhost_scsi.c +++ b/lib/vhost/vhost_scsi.c @@ -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"); diff --git a/test/unit/lib/vhost/vhost_blk.c/vhost_blk_ut.c b/test/unit/lib/vhost/vhost_blk.c/vhost_blk_ut.c index fbbb1de34..3cc6caf51 100644 --- a/test/unit/lib/vhost/vhost_blk.c/vhost_blk_ut.c +++ b/test/unit/lib/vhost/vhost_blk.c/vhost_blk_ut.c @@ -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); diff --git a/test/unit/lib/vhost/vhost_scsi.c/vhost_scsi_ut.c b/test/unit/lib/vhost/vhost_scsi.c/vhost_scsi_ut.c index 0c51687b2..3f417cd31 100644 --- a/test/unit/lib/vhost/vhost_scsi.c/vhost_scsi_ut.c +++ b/test/unit/lib/vhost/vhost_scsi.c/vhost_scsi_ut.c @@ -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_vhost_vq_avail_ring_get, uint16_t, (struct rte_vhost_vring *vq, uint16_t *reqs, uint16_t reqs_len), 0); -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_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, struct rte_vhost_vring *vq, uint16_t id, uint32_t len));