Commit 8ef5cfc6 authored by Changpeng Liu's avatar Changpeng Liu Committed by Tomasz Zawadzki
Browse files

vhost: restart device when memory region changed



There are cases for users to add a new memory region during
runtime, in earlier SPDK versions before 23.01, SPDK supported
this feature via restart the device for any new SET_MEM_TABLE
messages.  In the commit 23baa676 we removed this support to
start device only once, since users are still requiring this
feature, so adding it back.

For SEM_MEM_TABLE vhost-user message, DPDK will hold the
access lock of vring, we can't call `rte_vhost_vring_call`
in the DPDK vhost thread context, so use the non-block API
instead.

Fix issue #3132.

Change-Id: I6dcb427eb56b778d9804f89c5998b2179ea3a916
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/19932


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Community-CI: Mellanox Build Bot
parent 91459140
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -358,7 +358,11 @@ vhost_vq_used_signal(struct spdk_vhost_session *vsession,
		      "Queue %td - USED RING: sending IRQ: last used %"PRIu16"\n",
		      virtqueue - vsession->virtqueue, virtqueue->last_used_idx);

#if RTE_VERSION < RTE_VERSION_NUM(22, 11, 0, 0)
	if (rte_vhost_vring_call(vsession->vid, virtqueue->vring_idx) == 0) {
#else
	if (rte_vhost_vring_call_nonblock(vsession->vid, virtqueue->vring_idx) == 0) {
#endif
		/* interrupt signalled */
		virtqueue->req_cnt += virtqueue->used_req_cnt;
		virtqueue->used_req_cnt = 0;
@@ -1468,6 +1472,17 @@ extern_vhost_pre_msg_handler(int vid, void *_msg)
		}
		pthread_mutex_unlock(&user_dev->lock);
		break;
	case VHOST_USER_SET_MEM_TABLE:
		pthread_mutex_lock(&user_dev->lock);
		if (vsession->started) {
			vsession->original_max_queues = vsession->max_queues;
			pthread_mutex_unlock(&user_dev->lock);
			g_spdk_vhost_ops.destroy_device(vid);
			vsession->needs_restart = true;
			break;
		}
		pthread_mutex_unlock(&user_dev->lock);
		break;
	case VHOST_USER_GET_CONFIG: {
		int rc = 0;

@@ -1520,10 +1535,6 @@ extern_vhost_post_msg_handler(int vid, void *_msg)
	}
	user_dev = to_user_dev(vsession->vdev);

	if (msg->request == VHOST_USER_SET_MEM_TABLE) {
		vhost_register_memtable_if_required(vsession, vid);
	}

	switch (msg->request) {
	case VHOST_USER_SET_FEATURES:
		rc = vhost_get_negotiated_features(vid, &vsession->negotiated_features);
@@ -1557,6 +1568,21 @@ extern_vhost_post_msg_handler(int vid, void *_msg)
		}
		pthread_mutex_unlock(&user_dev->lock);
		break;
	case VHOST_USER_SET_MEM_TABLE:
		vhost_register_memtable_if_required(vsession, vid);
		pthread_mutex_lock(&user_dev->lock);
		if (vsession->needs_restart) {
			vsession->needs_restart = false;
			pthread_mutex_unlock(&user_dev->lock);
			for (qid = 0; qid < vsession->original_max_queues; qid++) {
				enable_device_vq(vsession, qid);
			}
			vsession->original_max_queues = 0;
			g_spdk_vhost_ops.new_device(vid);
			break;
		}
		pthread_mutex_unlock(&user_dev->lock);
		break;
	default:
		break;
	}
+3 −0
Original line number Diff line number Diff line
@@ -116,12 +116,15 @@ struct spdk_vhost_session {
	bool started;
	bool starting;
	bool interrupt_mode;
	bool needs_restart;

	struct rte_vhost_memory *mem;

	int task_cnt;

	uint16_t max_queues;
	/* Maximum number of queues before restart, used with 'needs_restart' flag */
	uint16_t original_max_queues;

	uint64_t negotiated_features;

+4 −0
Original line number Diff line number Diff line
@@ -24,7 +24,11 @@ DEFINE_STUB(rte_vhost_get_vring_base, int, (int vid, uint16_t queue_id,
		uint16_t *last_avail_idx, uint16_t *last_used_idx), 0);
DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0);
DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0);
#if RTE_VERSION < RTE_VERSION_NUM(22, 11, 0, 0)
DEFINE_STUB(rte_vhost_vring_call, int, (int vid, uint16_t vring_idx), 0);
#else
DEFINE_STUB(rte_vhost_vring_call_nonblock, int, (int vid, uint16_t vring_idx), 0);
#endif
DEFINE_STUB_V(rte_vhost_log_used_vring, (int vid, uint16_t vring_idx,
		uint64_t offset, uint64_t len));