Commit b8d72590 authored by Jin Yu's avatar Jin Yu Committed by Tomasz Zawadzki
Browse files

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: default avatarLi Lin <lilin24@baidu.com>
Signed-off-by: default avatarNi Xun <nixun@baidu.com>
Signed-off-by: default avatarZhang Yu <zhangyu31@baidu.com>
Signed-off-by: default avatarJin Yu <jin.yu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/471235


Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
parent f29d20a2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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;
+64 −1
Original line number Diff line number Diff line
@@ -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",
+4 −0
Original line number Diff line number Diff line
@@ -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;