vhost: spdk live recovery from crash or killing

This patch is for the vhost-blk live recovery feature
which can make spdk recover from crash or killing.
The relate rte_xx functions are in the the shared memory
protocol patches which have been merged in DPDK 19.11.

Change-Id: Ia0ac99f8ba0bd66dc9f525f2c72bd1de141ec596
Signed-off-by: Li Lin <lilin24@baidu.com>
Signed-off-by: Ni Xun <nixun@baidu.com>
Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
Signed-off-by: Jin Yu <jin.yu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/471235
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Jin Yu 2019-10-15 00:43:37 +08:00 committed by Tomasz Zawadzki
parent f29d20a21e
commit b8d72590b3
3 changed files with 74 additions and 1 deletions

View File

@ -414,6 +414,7 @@ vhost_vq_used_ring_enqueue(struct spdk_vhost_session *vsession,
struct rte_vhost_vring *vring = &virtqueue->vring;
struct vring_used *used = vring->used;
uint16_t last_idx = virtqueue->last_used_idx & (vring->size - 1);
uint16_t vq_idx = virtqueue->vring_idx;
SPDK_DEBUGLOG(SPDK_LOG_VHOST_RING,
"Queue %td - USED RING: last_idx=%"PRIu16" req id=%"PRIu16" len=%"PRIu32"\n",
@ -428,10 +429,14 @@ vhost_vq_used_ring_enqueue(struct spdk_vhost_session *vsession,
/* Ensure the used ring is updated before we log it or increment used->idx. */
spdk_smp_wmb();
rte_vhost_set_last_inflight_io_split(vsession->vid, vq_idx, id);
vhost_log_used_vring_elem(vsession, virtqueue, last_idx);
* (volatile uint16_t *) &used->idx = virtqueue->last_used_idx;
vhost_log_used_vring_idx(vsession, virtqueue);
rte_vhost_clr_inflight_desc_split(vsession->vid, vq_idx, virtqueue->last_used_idx, id);
virtqueue->used_req_cnt++;
}
@ -1060,6 +1065,7 @@ vhost_start_device_cb(int vid)
continue;
}
q->vring_idx = i;
rte_vhost_get_vhost_ring_inflight(vid, i, &q->vring_inflight);
if (q->vring.desc == NULL || q->vring.size == 0) {
continue;

View File

@ -59,7 +59,8 @@
(1ULL << VIRTIO_BLK_F_BARRIER) | (1ULL << VIRTIO_BLK_F_SCSI))
/* Vhost-blk support protocol features */
#define SPDK_VHOST_BLK_PROTOCOL_FEATURES ((1ULL << VHOST_USER_PROTOCOL_F_CONFIG))
#define SPDK_VHOST_BLK_PROTOCOL_FEATURES ((1ULL << VHOST_USER_PROTOCOL_F_CONFIG) | \
(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))
struct spdk_vhost_blk_task {
struct spdk_bdev_io *bdev_io;
@ -432,6 +433,64 @@ process_blk_request(struct spdk_vhost_blk_task *task,
return 0;
}
static void
submit_inflight_desc(struct spdk_vhost_blk_session *bvsession,
struct spdk_vhost_virtqueue *vq)
{
struct spdk_vhost_blk_dev *bvdev = bvsession->bvdev;
struct spdk_vhost_blk_task *task;
struct spdk_vhost_session *vsession = &bvsession->vsession;
spdk_vhost_resubmit_info *resubmit = vq->vring_inflight.resubmit_inflight;
spdk_vhost_resubmit_desc *resubmit_list;
int rc;
uint16_t req_idx;
if (spdk_likely(resubmit == NULL || resubmit->resubmit_list == NULL)) {
return;
}
resubmit_list = resubmit->resubmit_list;
while (resubmit->resubmit_num-- > 0) {
req_idx = resubmit_list[resubmit->resubmit_num].index;
SPDK_DEBUGLOG(SPDK_LOG_VHOST_BLK, "====== Start processing request idx %"PRIu16"======\n",
req_idx);
if (spdk_unlikely(req_idx >= vq->vring.size)) {
SPDK_ERRLOG("%s: request idx '%"PRIu16"' exceeds virtqueue size (%"PRIu16").\n",
bvdev->vdev.name, req_idx, vq->vring.size);
vhost_vq_used_ring_enqueue(vsession, vq, req_idx, 0);
continue;
}
task = &((struct spdk_vhost_blk_task *)vq->tasks)[req_idx];
if (spdk_unlikely(task->used)) {
SPDK_ERRLOG("%s: request with idx '%"PRIu16"' is already pending.\n",
bvdev->vdev.name, req_idx);
vhost_vq_used_ring_enqueue(vsession, vq, req_idx, 0);
continue;
}
vsession->task_cnt++;
task->used = true;
task->iovcnt = SPDK_COUNTOF(task->iovs);
task->status = NULL;
task->used_len = 0;
rc = process_blk_request(task, bvsession, vq);
if (rc == 0) {
SPDK_DEBUGLOG(SPDK_LOG_VHOST_BLK, "====== Task %p req_idx %d submitted ======\n", task,
req_idx);
} else {
SPDK_DEBUGLOG(SPDK_LOG_VHOST_BLK, "====== Task %p req_idx %d failed ======\n", task,
req_idx);
}
}
free(resubmit_list);
resubmit->resubmit_list = NULL;
}
static void
process_vq(struct spdk_vhost_blk_session *bvsession, struct spdk_vhost_virtqueue *vq)
{
@ -440,6 +499,9 @@ process_vq(struct spdk_vhost_blk_session *bvsession, struct spdk_vhost_virtqueue
int rc;
uint16_t reqs[32];
uint16_t reqs_cnt, i;
uint16_t vq_idx = vq->vring_idx;
submit_inflight_desc(bvsession, vq);
reqs_cnt = vhost_vq_avail_ring_get(vq, reqs, SPDK_COUNTOF(reqs));
if (!reqs_cnt) {
@ -457,6 +519,7 @@ process_vq(struct spdk_vhost_blk_session *bvsession, struct spdk_vhost_virtqueue
continue;
}
rte_vhost_set_inflight_desc_split(vsession->vid, vq_idx, reqs[i]);
task = &((struct spdk_vhost_blk_task *)vq->tasks)[reqs[i]];
if (spdk_unlikely(task->used)) {
SPDK_ERRLOG("%s: request with idx '%"PRIu16"' is already pending.\n",

View File

@ -85,8 +85,12 @@ struct vhost_poll_group {
TAILQ_ENTRY(vhost_poll_group) tailq;
};
typedef struct rte_vhost_resubmit_desc spdk_vhost_resubmit_desc;
typedef struct rte_vhost_resubmit_info spdk_vhost_resubmit_info;
struct spdk_vhost_virtqueue {
struct rte_vhost_vring vring;
struct rte_vhost_ring_inflight vring_inflight;
uint16_t last_avail_idx;
uint16_t last_used_idx;