vhost: install external msg handling hooks to rte_vhost
DPDK 19.05+ gives us an ability to pre or post-process any single vhost-user message. The user can either perform additional actions upon some generic events, or can implement handling for brand new message types that rte_vhost doesn't even know about. In order to smoothly switch to the upstream rte_vhost and drop our internal copy, we introduce an SPDK wrapper function to register SPDK-specific message handlers. For DPDK 19.05+ this will use the new rte_vhost API to register those message handlers, and for older DPDKs this function simply won't do anything - as w assume the internal rte_copy already contains all the necessary changes and does not need any "external" hooks. For now we use the message handlers to stop the vhost device and wait for any pending DMA ops before letting rte_vhost to process the SET_MEM_TABLE message and unmap the current shared memory. Change-Id: Ic0fefa9174254627cb3fc0ed30ab1e54be4dd654 Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446085 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
parent
2725b5191e
commit
0a6ad9b02e
@ -37,7 +37,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
|||||||
CFLAGS += -I.
|
CFLAGS += -I.
|
||||||
CFLAGS += $(ENV_CFLAGS)
|
CFLAGS += $(ENV_CFLAGS)
|
||||||
|
|
||||||
C_SRCS = vhost.c vhost_rpc.c vhost_scsi.c vhost_blk.c
|
C_SRCS = vhost.c vhost_rpc.c vhost_scsi.c vhost_blk.c rte_vhost_compat.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_VHOST_INTERNAL_LIB),y)
|
ifeq ($(CONFIG_VHOST_INTERNAL_LIB),y)
|
||||||
C_SRCS += vhost_nvme.c
|
C_SRCS += vhost_nvme.c
|
||||||
|
132
lib/vhost/rte_vhost_compat.c
Normal file
132
lib/vhost/rte_vhost_compat.c
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* Set of workarounds for rte_vhost to make it work with device types
|
||||||
|
* other than vhost-net.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "spdk/stdinc.h"
|
||||||
|
|
||||||
|
#include "spdk/env.h"
|
||||||
|
#include "spdk/likely.h"
|
||||||
|
#include "spdk/string.h"
|
||||||
|
#include "spdk/util.h"
|
||||||
|
#include "spdk/barrier.h"
|
||||||
|
#include "spdk/vhost.h"
|
||||||
|
#include "vhost_internal.h"
|
||||||
|
|
||||||
|
#include "spdk_internal/vhost_user.h"
|
||||||
|
|
||||||
|
#ifndef SPDK_CONFIG_VHOST_INTERNAL_LIB
|
||||||
|
extern const struct vhost_device_ops g_spdk_vhost_ops;
|
||||||
|
|
||||||
|
static enum rte_vhost_msg_result
|
||||||
|
spdk_extern_vhost_pre_msg_handler(int vid, void *_msg)
|
||||||
|
{
|
||||||
|
struct vhost_user_msg *msg = _msg;
|
||||||
|
struct spdk_vhost_session *vsession;
|
||||||
|
|
||||||
|
vsession = spdk_vhost_session_find_by_vid(vid);
|
||||||
|
if (vsession == NULL) {
|
||||||
|
SPDK_ERRLOG("Received a message to unitialized session (vid %d).\n", vid);
|
||||||
|
assert(false);
|
||||||
|
return RTE_VHOST_MSG_RESULT_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (msg->request) {
|
||||||
|
case VHOST_USER_SET_MEM_TABLE:
|
||||||
|
/* rte_vhost will unmap previous memory that SPDK may still
|
||||||
|
* have pending DMA operations on. We can't let that happen,
|
||||||
|
* so stop the device before letting rte_vhost unmap anything.
|
||||||
|
* This will block until all pending I/Os are finished.
|
||||||
|
* We will start the device again from the post-processing
|
||||||
|
* message handler.
|
||||||
|
*/
|
||||||
|
if (vsession->lcore != -1) {
|
||||||
|
g_spdk_vhost_ops.destroy_device(vid);
|
||||||
|
vsession->needs_restart = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RTE_VHOST_MSG_RESULT_NOT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum rte_vhost_msg_result
|
||||||
|
spdk_extern_vhost_post_msg_handler(int vid, void *_msg)
|
||||||
|
{
|
||||||
|
struct spdk_vhost_session *vsession;
|
||||||
|
|
||||||
|
vsession = spdk_vhost_session_find_by_vid(vid);
|
||||||
|
if (vsession == NULL) {
|
||||||
|
SPDK_ERRLOG("Received a message to unitialized session (vid %d).\n", vid);
|
||||||
|
assert(false);
|
||||||
|
return RTE_VHOST_MSG_RESULT_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vsession->needs_restart) {
|
||||||
|
g_spdk_vhost_ops.new_device(vid);
|
||||||
|
vsession->needs_restart = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RTE_VHOST_MSG_RESULT_NOT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rte_vhost_user_extern_ops g_spdk_extern_vhost_ops = {
|
||||||
|
.pre_msg_handle = spdk_extern_vhost_pre_msg_handler,
|
||||||
|
.post_msg_handle = spdk_extern_vhost_post_msg_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_vhost_session_install_rte_compat_hooks(struct spdk_vhost_session *vsession)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = rte_vhost_extern_callback_register(vsession->vid, &g_spdk_extern_vhost_ops, NULL);
|
||||||
|
if (rc != 0) {
|
||||||
|
SPDK_ERRLOG("rte_vhost_extern_callback_register() failed for vid = %d\n",
|
||||||
|
vsession->vid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* SPDK_CONFIG_VHOST_INTERNAL_LIB */
|
||||||
|
void
|
||||||
|
spdk_vhost_session_install_rte_compat_hooks(struct spdk_vhost_session *vsession)
|
||||||
|
{
|
||||||
|
/* nothing to do. all the changes are already incorporated into rte_vhost */
|
||||||
|
}
|
||||||
|
#endif
|
@ -527,7 +527,7 @@ spdk_vhost_session_find_by_id(struct spdk_vhost_dev *vdev, unsigned id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct spdk_vhost_session *
|
struct spdk_vhost_session *
|
||||||
spdk_vhost_session_find_by_vid(int vid)
|
spdk_vhost_session_find_by_vid(int vid)
|
||||||
{
|
{
|
||||||
struct spdk_vhost_dev *vdev;
|
struct spdk_vhost_dev *vdev;
|
||||||
@ -1018,7 +1018,7 @@ stop_device(int vid)
|
|||||||
|
|
||||||
vdev = vsession->vdev;
|
vdev = vsession->vdev;
|
||||||
if (vsession->lcore == -1) {
|
if (vsession->lcore == -1) {
|
||||||
SPDK_ERRLOG("Controller %s is not loaded.\n", vdev->name);
|
/* already stopped, nothing to do */
|
||||||
pthread_mutex_unlock(&g_spdk_vhost_mutex);
|
pthread_mutex_unlock(&g_spdk_vhost_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1064,7 +1064,8 @@ start_device(int vid)
|
|||||||
|
|
||||||
vdev = vsession->vdev;
|
vdev = vsession->vdev;
|
||||||
if (vsession->lcore != -1) {
|
if (vsession->lcore != -1) {
|
||||||
SPDK_ERRLOG("Controller %s already loaded.\n", vdev->name);
|
/* already started, nothing to do */
|
||||||
|
rc = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1302,6 +1303,8 @@ new_connection(int vid)
|
|||||||
vsession->stats_check_interval = SPDK_VHOST_STATS_CHECK_INTERVAL_MS *
|
vsession->stats_check_interval = SPDK_VHOST_STATS_CHECK_INTERVAL_MS *
|
||||||
spdk_get_ticks_hz() / 1000UL;
|
spdk_get_ticks_hz() / 1000UL;
|
||||||
TAILQ_INSERT_TAIL(&vdev->vsessions, vsession, tailq);
|
TAILQ_INSERT_TAIL(&vdev->vsessions, vsession, tailq);
|
||||||
|
|
||||||
|
spdk_vhost_session_install_rte_compat_hooks(vsession);
|
||||||
pthread_mutex_unlock(&g_spdk_vhost_mutex);
|
pthread_mutex_unlock(&g_spdk_vhost_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,8 @@ struct spdk_vhost_session {
|
|||||||
|
|
||||||
int32_t lcore;
|
int32_t lcore;
|
||||||
|
|
||||||
|
bool needs_restart;
|
||||||
|
|
||||||
struct rte_vhost_memory *mem;
|
struct rte_vhost_memory *mem;
|
||||||
|
|
||||||
int task_cnt;
|
int task_cnt;
|
||||||
@ -345,6 +347,9 @@ int spdk_vhost_session_send_event(struct spdk_vhost_session *vsession,
|
|||||||
*/
|
*/
|
||||||
void spdk_vhost_session_event_done(void *event_ctx, int response);
|
void spdk_vhost_session_event_done(void *event_ctx, int response);
|
||||||
|
|
||||||
|
struct spdk_vhost_session *spdk_vhost_session_find_by_vid(int vid);
|
||||||
|
void spdk_vhost_session_install_rte_compat_hooks(struct spdk_vhost_session *vsession);
|
||||||
|
|
||||||
void spdk_vhost_free_reactor(uint32_t lcore);
|
void spdk_vhost_free_reactor(uint32_t lcore);
|
||||||
uint32_t spdk_vhost_allocate_reactor(struct spdk_cpuset *cpumask);
|
uint32_t spdk_vhost_allocate_reactor(struct spdk_cpuset *cpumask);
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ DEFINE_STUB(rte_vhost_set_vring_base, int, (int vid, uint16_t queue_id,
|
|||||||
uint16_t last_avail_idx, uint16_t last_used_idx), 0);
|
uint16_t last_avail_idx, uint16_t last_used_idx), 0);
|
||||||
DEFINE_STUB(rte_vhost_get_vring_base, int, (int vid, uint16_t queue_id,
|
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);
|
uint16_t *last_avail_idx, uint16_t *last_used_idx), 0);
|
||||||
|
DEFINE_STUB_V(spdk_vhost_session_install_rte_compat_hooks,
|
||||||
|
(struct spdk_vhost_session *vsession));
|
||||||
DEFINE_STUB(rte_vhost_driver_unregister, int, (const char *path), 0);
|
DEFINE_STUB(rte_vhost_driver_unregister, int, (const char *path), 0);
|
||||||
DEFINE_STUB(spdk_event_allocate, struct spdk_event *,
|
DEFINE_STUB(spdk_event_allocate, struct spdk_event *,
|
||||||
(uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL);
|
(uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user