vhost-blk: record inflight descs of packed ring

This patch is for packed ring live recovery.
First step is to track the packed ring descs.

This feature base on this QEMU patch:
https://patchwork.kernel.org/patch/11766697/

Change-Id: Id0ccb6fd12b3623cc367424f496b4ffc5323f390
Signed-off-by: Jin Yu <jin.yu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4126
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Jin Yu 2020-08-18 00:31:32 +08:00 committed by Tomasz Zawadzki
parent c73dc155c2
commit e28ac3bc6b
4 changed files with 28 additions and 12 deletions

View File

@ -546,7 +546,7 @@ void
vhost_vq_packed_ring_enqueue(struct spdk_vhost_session *vsession,
struct spdk_vhost_virtqueue *virtqueue,
uint16_t num_descs, uint16_t buffer_id,
uint32_t length)
uint32_t length, uint16_t inflight_head)
{
struct vring_packed_desc *desc = &virtqueue->vring.desc_packed[virtqueue->last_used_idx];
bool used, avail;
@ -587,6 +587,8 @@ vhost_vq_packed_ring_enqueue(struct spdk_vhost_session *vsession,
* written to the descriptor.
*/
spdk_smp_wmb();
rte_vhost_set_last_inflight_io_packed(vsession->vid, virtqueue->vring_idx, inflight_head);
/* To mark a desc as used, the device sets the F_USED bit in flags to match
* the internal Device ring wrap counter. It also sets the F_AVAIL bit to
* match the same value.
@ -596,6 +598,7 @@ vhost_vq_packed_ring_enqueue(struct spdk_vhost_session *vsession,
} else {
desc->flags &= ~VRING_DESC_F_AVAIL_USED;
}
rte_vhost_clr_inflight_desc_packed(vsession->vid, virtqueue->vring_idx, inflight_head);
vhost_log_used_vring_elem(vsession, virtqueue, virtqueue->last_used_idx);
virtqueue->last_used_idx += num_descs;

View File

@ -72,6 +72,7 @@ struct spdk_vhost_blk_task {
uint16_t req_idx;
uint16_t num_descs;
uint16_t buffer_id;
uint16_t inflight_head;
/* for io wait */
struct spdk_bdev_io_wait_entry bdev_io_wait;
@ -141,7 +142,8 @@ blk_task_enqueue(struct spdk_vhost_blk_task *task)
if (task->vq->packed.packed_ring) {
vhost_vq_packed_ring_enqueue(&task->bvsession->vsession, task->vq,
task->num_descs,
task->buffer_id, task->used_len);
task->buffer_id, task->used_len,
task->inflight_head);
} else {
vhost_vq_used_ring_enqueue(&task->bvsession->vsession, task->vq,
task->req_idx, task->used_len);
@ -578,6 +580,10 @@ process_blk_task(struct spdk_vhost_virtqueue *vq, uint16_t req_idx)
task->req_idx = req_idx;
task->num_descs = num_descs;
task->buffer_id = task_idx;
rte_vhost_set_inflight_desc_packed(task->bvsession->vsession.vid, vq->vring_idx,
req_idx, (req_idx + num_descs - 1) % vq->vring.size,
&task->inflight_head);
}
task->bvsession->vsession.task_cnt++;
@ -752,7 +758,8 @@ no_bdev_process_packed_vq(struct spdk_vhost_blk_session *bvsession, struct spdk_
SPDK_ERRLOG("%s: request with idx '%"PRIu16"' is already pending.\n",
vsession->name, req_idx);
vhost_vq_packed_ring_enqueue(vsession, vq, num_descs,
task->buffer_id, task->used_len);
task->buffer_id, task->used_len,
task->inflight_head);
return;
}
@ -769,7 +776,8 @@ no_bdev_process_packed_vq(struct spdk_vhost_blk_session *bvsession, struct spdk_
task->used = false;
vhost_vq_packed_ring_enqueue(vsession, vq, num_descs,
task->buffer_id, task->used_len);
task->buffer_id, task->used_len,
task->inflight_head);
}
static int

View File

@ -324,11 +324,12 @@ void vhost_vq_used_ring_enqueue(struct spdk_vhost_session *vsession,
* \buffer_id descriptor buffer ID.
* \length device write length. Specify the length of the buffer that has been initialized
* (written to) by the device
* \inflight_head the head idx of this IO inflight desc chain.
*/
void vhost_vq_packed_ring_enqueue(struct spdk_vhost_session *vsession,
struct spdk_vhost_virtqueue *virtqueue,
uint16_t num_descs, uint16_t buffer_id,
uint32_t length);
uint32_t length, uint16_t inflight_head);
/**
* Get subsequent descriptor from given table.

View File

@ -75,6 +75,10 @@ DEFINE_STUB(rte_vhost_set_last_inflight_io_split, int,
(int vid, uint16_t vring_idx, uint16_t idx), 0);
DEFINE_STUB(rte_vhost_clr_inflight_desc_split, int,
(int vid, uint16_t vring_idx, uint16_t last_used_idx, uint16_t idx), 0);
DEFINE_STUB(rte_vhost_set_last_inflight_io_packed, int,
(int vid, uint16_t vring_idx, uint16_t head), 0);
DEFINE_STUB(rte_vhost_clr_inflight_desc_packed, int,
(int vid, uint16_t vring_idx, uint16_t head), 0);
DEFINE_STUB_V(rte_vhost_log_write, (int vid, uint64_t addr, uint64_t len));
DEFINE_STUB_V(vhost_session_mem_register, (struct rte_vhost_memory *mem));
DEFINE_STUB_V(vhost_session_mem_unregister, (struct rte_vhost_memory *mem));
@ -473,9 +477,9 @@ vq_packed_ring_test(void)
}
/* Host complete them out of order: 1, 0, 2. */
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 1, 1);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 0, 1);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 2, 1);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 1, 1, 0);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 0, 1, 0);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 2, 1, 0);
/* Host has got all the available request but only complete three requests */
CU_ASSERT(vq.last_avail_idx == 0);
@ -511,10 +515,10 @@ vq_packed_ring_test(void)
CU_ASSERT(vq.packed.avail_phase == 0);
/* Host complete all the requests */
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 1, 1);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 0, 1);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 3, 1);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 2, 1);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 1, 1, 0);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 0, 1, 0);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 3, 1, 0);
vhost_vq_packed_ring_enqueue(&vs, &vq, 1, 2, 1, 0);
CU_ASSERT(vq.last_used_idx == vq.last_avail_idx);
CU_ASSERT(vq.packed.used_phase == vq.packed.avail_phase);