lib/vhost: use user_dev's lock to protect vhost sessions
`spdk_vhost_dev` is created|deleted via RPC or APIs, and we use a global `spdk_vhost_lock` to protect it, but for some other places such as: vhost-user message processing, we also use the global lock for now, actually we don't need to use this lock, because these vhost-user messages processing will not delete nor add vhost devices. While here, we add a `spdk_vhost_user_dev` access lock to protect vhost-user message processing as an optimization. Change-Id: Ia9c45b056cebb7b65f458d56ed775a15e386f905 Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15184 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Feng Li <lifeng1519@gmail.com>
This commit is contained in:
parent
d37a07f7c0
commit
376c25ed0c
@ -53,13 +53,6 @@ struct vhost_session_fn_ctx {
|
||||
void *user_ctx;
|
||||
};
|
||||
|
||||
static struct spdk_vhost_user_dev *
|
||||
to_user_dev(struct spdk_vhost_dev *vdev)
|
||||
{
|
||||
assert(vdev != NULL);
|
||||
return vdev->ctxt;
|
||||
}
|
||||
|
||||
static void
|
||||
__attribute__((constructor))
|
||||
_vhost_user_sem_init(void)
|
||||
@ -919,21 +912,23 @@ new_connection(int vid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
spdk_vhost_lock();
|
||||
|
||||
ctrlr_name = &ifname[0];
|
||||
dev_dirname_len = strlen(g_vhost_user_dev_dirname);
|
||||
if (strncmp(ctrlr_name, g_vhost_user_dev_dirname, dev_dirname_len) == 0) {
|
||||
ctrlr_name += dev_dirname_len;
|
||||
}
|
||||
|
||||
spdk_vhost_lock();
|
||||
vdev = spdk_vhost_dev_find(ctrlr_name);
|
||||
if (vdev == NULL) {
|
||||
SPDK_ERRLOG("Couldn't find device with vid %d to create connection for.\n", vid);
|
||||
spdk_vhost_unlock();
|
||||
return -1;
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
|
||||
user_dev = to_user_dev(vdev);
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
|
||||
/* We expect sessions inside user_dev->vsessions to be sorted in ascending
|
||||
* order in regard of vsession->id. For now we always set id = vsessions_cnt++
|
||||
@ -941,6 +936,7 @@ new_connection(int vid)
|
||||
* This is required for vhost_user_dev_foreach_session() to work.
|
||||
*/
|
||||
if (user_dev->vsessions_num == UINT_MAX) {
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
assert(false);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -948,7 +944,7 @@ new_connection(int vid)
|
||||
if (posix_memalign((void **)&vsession, SPDK_CACHE_LINE_SIZE, sizeof(*vsession) +
|
||||
user_dev->user_backend->session_ctx_size)) {
|
||||
SPDK_ERRLOG("vsession alloc failed\n");
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return -1;
|
||||
}
|
||||
memset(vsession, 0, sizeof(*vsession) + user_dev->user_backend->session_ctx_size);
|
||||
@ -959,8 +955,8 @@ new_connection(int vid)
|
||||
vsession->name = spdk_sprintf_alloc("%ss%u", vdev->name, vsession->vid);
|
||||
if (vsession->name == NULL) {
|
||||
SPDK_ERRLOG("vsession alloc failed\n");
|
||||
spdk_vhost_unlock();
|
||||
free(vsession);
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return -1;
|
||||
}
|
||||
vsession->started = false;
|
||||
@ -968,9 +964,9 @@ new_connection(int vid)
|
||||
vsession->stats_check_interval = SPDK_VHOST_STATS_CHECK_INTERVAL_MS *
|
||||
spdk_get_ticks_hz() / 1000UL;
|
||||
TAILQ_INSERT_TAIL(&user_dev->vsessions, vsession, tailq);
|
||||
|
||||
vhost_session_install_rte_compat_hooks(vsession);
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -983,6 +979,7 @@ vhost_user_session_start(void *arg1)
|
||||
const struct spdk_vhost_user_dev_backend *backend;
|
||||
int rc;
|
||||
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
backend = user_dev->user_backend;
|
||||
rc = backend->start_session(vdev, vsession, NULL);
|
||||
if (rc == 0) {
|
||||
@ -991,6 +988,7 @@ vhost_user_session_start(void *arg1)
|
||||
assert(user_dev->active_session_num < UINT32_MAX);
|
||||
user_dev->active_session_num++;
|
||||
}
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1119,17 +1117,18 @@ start_device(int vid)
|
||||
{
|
||||
struct spdk_vhost_dev *vdev;
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_user_dev *user_dev;
|
||||
int rc = 0;
|
||||
|
||||
spdk_vhost_lock();
|
||||
|
||||
vsession = vhost_session_find_by_vid(vid);
|
||||
if (vsession == NULL) {
|
||||
rc = -1;
|
||||
SPDK_ERRLOG("Couldn't find session with vid %d.\n", vid);
|
||||
goto out;
|
||||
return -1;
|
||||
}
|
||||
vdev = vsession->vdev;
|
||||
user_dev = to_user_dev(vdev);
|
||||
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (vsession->started) {
|
||||
/* already started, nothing to do */
|
||||
goto out;
|
||||
@ -1141,12 +1140,11 @@ start_device(int vid)
|
||||
goto out;
|
||||
}
|
||||
|
||||
vdev = vsession->vdev;
|
||||
vhost_user_session_set_coalescing(vdev, vsession, NULL);
|
||||
spdk_thread_send_msg(vdev->thread, vhost_user_session_start, vsession);
|
||||
|
||||
out:
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1154,43 +1152,43 @@ static void
|
||||
stop_device(int vid)
|
||||
{
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_user_dev *user_dev;
|
||||
|
||||
spdk_vhost_lock();
|
||||
vsession = vhost_session_find_by_vid(vid);
|
||||
if (vsession == NULL) {
|
||||
SPDK_ERRLOG("Couldn't find session with vid %d.\n", vid);
|
||||
spdk_vhost_unlock();
|
||||
return;
|
||||
}
|
||||
user_dev = to_user_dev(vsession->vdev);
|
||||
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (!vsession->started) {
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
/* already stopped, nothing to do */
|
||||
spdk_vhost_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
_stop_session(vsession);
|
||||
spdk_vhost_unlock();
|
||||
|
||||
return;
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_connection(int vid)
|
||||
{
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_user_dev *user_dev;
|
||||
|
||||
spdk_vhost_lock();
|
||||
vsession = vhost_session_find_by_vid(vid);
|
||||
if (vsession == NULL) {
|
||||
SPDK_ERRLOG("Couldn't find session with vid %d.\n", vid);
|
||||
spdk_vhost_unlock();
|
||||
return;
|
||||
}
|
||||
user_dev = to_user_dev(vsession->vdev);
|
||||
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (vsession->started) {
|
||||
if (_stop_session(vsession) != 0) {
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1203,7 +1201,7 @@ destroy_connection(int vid)
|
||||
TAILQ_REMOVE(&to_user_dev(vsession->vdev)->vsessions, vsession, tailq);
|
||||
free(vsession->name);
|
||||
free(vsession);
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
}
|
||||
|
||||
#if RTE_VERSION >= RTE_VERSION_NUM(21, 11, 0, 0)
|
||||
@ -1236,15 +1234,24 @@ vhost_session_find_by_vid(int vid)
|
||||
{
|
||||
struct spdk_vhost_dev *vdev;
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_user_dev *user_dev;
|
||||
|
||||
spdk_vhost_lock();
|
||||
for (vdev = spdk_vhost_dev_next(NULL); vdev != NULL;
|
||||
vdev = spdk_vhost_dev_next(vdev)) {
|
||||
TAILQ_FOREACH(vsession, &to_user_dev(vdev)->vsessions, tailq) {
|
||||
user_dev = to_user_dev(vdev);
|
||||
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
TAILQ_FOREACH(vsession, &user_dev->vsessions, tailq) {
|
||||
if (vsession->vid == vid) {
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
spdk_vhost_unlock();
|
||||
return vsession;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -1290,16 +1297,18 @@ static void
|
||||
vhost_event_cb(void *arg1)
|
||||
{
|
||||
struct vhost_session_fn_ctx *ctx = arg1;
|
||||
struct spdk_vhost_dev *vdev = ctx->vdev;
|
||||
struct spdk_vhost_user_dev *user_dev = to_user_dev(vdev);
|
||||
struct spdk_vhost_session *vsession;
|
||||
|
||||
if (spdk_vhost_trylock() != 0) {
|
||||
if (pthread_mutex_trylock(&user_dev->lock) != 0) {
|
||||
spdk_thread_send_msg(spdk_get_thread(), vhost_event_cb, arg1);
|
||||
return;
|
||||
}
|
||||
|
||||
vsession = vhost_session_find_by_id(ctx->vdev, ctx->vsession_id);
|
||||
ctx->cb_fn(ctx->vdev, vsession, NULL);
|
||||
spdk_vhost_unlock();
|
||||
vsession = vhost_session_find_by_id(vdev, ctx->vsession_id);
|
||||
ctx->cb_fn(vdev, vsession, NULL);
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
}
|
||||
|
||||
int
|
||||
@ -1309,6 +1318,7 @@ vhost_user_session_send_event(struct spdk_vhost_session *vsession,
|
||||
{
|
||||
struct vhost_session_fn_ctx ev_ctx = {0};
|
||||
struct spdk_vhost_dev *vdev = vsession->vdev;
|
||||
struct spdk_vhost_user_dev *user_dev = to_user_dev(vdev);
|
||||
|
||||
ev_ctx.vdev = vdev;
|
||||
ev_ctx.vsession_id = vsession->id;
|
||||
@ -1316,9 +1326,9 @@ vhost_user_session_send_event(struct spdk_vhost_session *vsession,
|
||||
|
||||
spdk_thread_send_msg(vdev->thread, vhost_event_cb, &ev_ctx);
|
||||
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
wait_for_semaphore(timeout_sec, errmsg);
|
||||
spdk_vhost_lock();
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
|
||||
return g_dpdk_response;
|
||||
}
|
||||
@ -1330,7 +1340,7 @@ foreach_session_finish_cb(void *arg1)
|
||||
struct spdk_vhost_dev *vdev = ev_ctx->vdev;
|
||||
struct spdk_vhost_user_dev *user_dev = to_user_dev(vdev);
|
||||
|
||||
if (spdk_vhost_trylock() != 0) {
|
||||
if (pthread_mutex_trylock(&user_dev->lock) != 0) {
|
||||
spdk_thread_send_msg(spdk_get_thread(),
|
||||
foreach_session_finish_cb, arg1);
|
||||
return;
|
||||
@ -1342,7 +1352,7 @@ foreach_session_finish_cb(void *arg1)
|
||||
ev_ctx->cpl_fn(vdev, ev_ctx->user_ctx);
|
||||
}
|
||||
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
free(ev_ctx);
|
||||
}
|
||||
|
||||
@ -1350,16 +1360,17 @@ static void
|
||||
foreach_session(void *arg1)
|
||||
{
|
||||
struct vhost_session_fn_ctx *ev_ctx = arg1;
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_dev *vdev = ev_ctx->vdev;
|
||||
struct spdk_vhost_user_dev *user_dev = to_user_dev(vdev);
|
||||
struct spdk_vhost_session *vsession;
|
||||
int rc;
|
||||
|
||||
if (spdk_vhost_trylock() != 0) {
|
||||
if (pthread_mutex_trylock(&user_dev->lock) != 0) {
|
||||
spdk_thread_send_msg(spdk_get_thread(), foreach_session, arg1);
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(vsession, &to_user_dev(vdev)->vsessions, tailq) {
|
||||
TAILQ_FOREACH(vsession, &user_dev->vsessions, tailq) {
|
||||
rc = ev_ctx->cb_fn(vdev, vsession, ev_ctx->user_ctx);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
@ -1367,8 +1378,7 @@ foreach_session(void *arg1)
|
||||
}
|
||||
|
||||
out:
|
||||
spdk_vhost_unlock();
|
||||
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
spdk_thread_send_msg(g_vhost_user_init_thread, foreach_session_finish_cb, arg1);
|
||||
}
|
||||
|
||||
@ -1393,8 +1403,10 @@ vhost_user_dev_foreach_session(struct spdk_vhost_dev *vdev,
|
||||
ev_ctx->cpl_fn = cpl_fn;
|
||||
ev_ctx->user_ctx = arg;
|
||||
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
assert(user_dev->pending_async_op_num < UINT32_MAX);
|
||||
user_dev->pending_async_op_num++;
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
|
||||
spdk_thread_send_msg(vdev->thread, foreach_session, ev_ctx);
|
||||
}
|
||||
@ -1453,6 +1465,7 @@ extern_vhost_pre_msg_handler(int vid, void *_msg)
|
||||
{
|
||||
struct vhost_user_msg *msg = _msg;
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_user_dev *user_dev;
|
||||
|
||||
vsession = vhost_session_find_by_vid(vid);
|
||||
if (vsession == NULL) {
|
||||
@ -1460,17 +1473,24 @@ extern_vhost_pre_msg_handler(int vid, void *_msg)
|
||||
assert(false);
|
||||
return RTE_VHOST_MSG_RESULT_ERR;
|
||||
}
|
||||
user_dev = to_user_dev(vsession->vdev);
|
||||
|
||||
switch (msg->request) {
|
||||
case VHOST_USER_GET_VRING_BASE:
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (vsession->started) {
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
/* `stop_device` is running in synchronous, it
|
||||
* will hold this lock again before exiting.
|
||||
*/
|
||||
g_spdk_vhost_ops.destroy_device(vid);
|
||||
}
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
break;
|
||||
case VHOST_USER_GET_CONFIG: {
|
||||
int rc = 0;
|
||||
|
||||
spdk_vhost_lock();
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (vsession->vdev->backend->vhost_get_config) {
|
||||
rc = vsession->vdev->backend->vhost_get_config(vsession->vdev,
|
||||
msg->payload.cfg.region, msg->payload.cfg.size);
|
||||
@ -1478,20 +1498,20 @@ extern_vhost_pre_msg_handler(int vid, void *_msg)
|
||||
msg->size = 0;
|
||||
}
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
|
||||
return RTE_VHOST_MSG_RESULT_REPLY;
|
||||
}
|
||||
case VHOST_USER_SET_CONFIG: {
|
||||
int rc = 0;
|
||||
|
||||
spdk_vhost_lock();
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (vsession->vdev->backend->vhost_set_config) {
|
||||
rc = vsession->vdev->backend->vhost_set_config(vsession->vdev,
|
||||
msg->payload.cfg.region, msg->payload.cfg.offset,
|
||||
msg->payload.cfg.size, msg->payload.cfg.flags);
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
|
||||
return rc == 0 ? RTE_VHOST_MSG_RESULT_OK : RTE_VHOST_MSG_RESULT_ERR;
|
||||
}
|
||||
@ -1507,6 +1527,7 @@ extern_vhost_post_msg_handler(int vid, void *_msg)
|
||||
{
|
||||
struct vhost_user_msg *msg = _msg;
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_user_dev *user_dev;
|
||||
uint16_t qid;
|
||||
int rc;
|
||||
|
||||
@ -1516,6 +1537,7 @@ extern_vhost_post_msg_handler(int vid, void *_msg)
|
||||
assert(false);
|
||||
return RTE_VHOST_MSG_RESULT_ERR;
|
||||
}
|
||||
user_dev = to_user_dev(vsession->vdev);
|
||||
|
||||
if (msg->request == VHOST_USER_SET_MEM_TABLE) {
|
||||
vhost_register_memtable_if_required(vsession, vid);
|
||||
@ -1546,9 +1568,13 @@ extern_vhost_post_msg_handler(int vid, void *_msg)
|
||||
/* vhost-user spec tells us to start polling a queue after receiving
|
||||
* its SET_VRING_KICK message. Let's do it!
|
||||
*/
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (!vsession->started) {
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
g_spdk_vhost_ops.new_device(vid);
|
||||
return RTE_VHOST_MSG_RESULT_NOT_HANDLED;
|
||||
}
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1782,6 +1808,7 @@ vhost_user_dev_register(struct spdk_vhost_dev *vdev, const char *name, struct sp
|
||||
user_dev->vdev = vdev;
|
||||
user_dev->registered = true;
|
||||
TAILQ_INIT(&user_dev->vsessions);
|
||||
pthread_mutex_init(&user_dev->lock, NULL);
|
||||
|
||||
vhost_user_dev_set_coalescing(user_dev, SPDK_VHOST_COALESCING_DELAY_BASE_US,
|
||||
SPDK_VHOST_VQ_IOPS_COALESCING_THRESHOLD);
|
||||
@ -1789,6 +1816,7 @@ vhost_user_dev_register(struct spdk_vhost_dev *vdev, const char *name, struct sp
|
||||
if (vhost_register_unix_socket(path, name, vdev->virtio_features, vdev->disabled_features,
|
||||
vdev->protocol_features)) {
|
||||
spdk_thread_send_msg(vdev->thread, vhost_dev_thread_exit, NULL);
|
||||
pthread_mutex_destroy(&user_dev->lock);
|
||||
free(user_dev);
|
||||
free(vdev->path);
|
||||
return -EIO;
|
||||
@ -1802,14 +1830,18 @@ vhost_user_dev_unregister(struct spdk_vhost_dev *vdev)
|
||||
{
|
||||
struct spdk_vhost_user_dev *user_dev = to_user_dev(vdev);
|
||||
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
if (user_dev->pending_async_op_num) {
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!TAILQ_EMPTY(&user_dev->vsessions)) {
|
||||
SPDK_ERRLOG("Controller %s has still valid connection.\n", vdev->name);
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
|
||||
/* There are no valid connections now, and it's not an error if the domain
|
||||
* socket was already removed by shutdown thread.
|
||||
@ -1817,6 +1849,8 @@ vhost_user_dev_unregister(struct spdk_vhost_dev *vdev)
|
||||
vhost_driver_unregister(vdev->path);
|
||||
|
||||
spdk_thread_send_msg(vdev->thread, vhost_dev_thread_exit, NULL);
|
||||
pthread_mutex_destroy(&user_dev->lock);
|
||||
|
||||
free(user_dev);
|
||||
free(vdev->path);
|
||||
|
||||
@ -1868,16 +1902,18 @@ vhost_user_session_shutdown(void *vhost_cb)
|
||||
{
|
||||
struct spdk_vhost_dev *vdev = NULL;
|
||||
struct spdk_vhost_session *vsession;
|
||||
struct spdk_vhost_user_dev *user_dev;
|
||||
|
||||
for (vdev = spdk_vhost_dev_next(NULL); vdev != NULL;
|
||||
vdev = spdk_vhost_dev_next(vdev)) {
|
||||
spdk_vhost_lock();
|
||||
TAILQ_FOREACH(vsession, &to_user_dev(vdev)->vsessions, tailq) {
|
||||
user_dev = to_user_dev(vdev);
|
||||
pthread_mutex_lock(&user_dev->lock);
|
||||
TAILQ_FOREACH(vsession, &user_dev->vsessions, tailq) {
|
||||
if (vsession->started) {
|
||||
_stop_session(vsession);
|
||||
}
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
vhost_driver_unregister(vdev->path);
|
||||
}
|
||||
|
||||
|
@ -127,13 +127,16 @@ vhost_dev_register(struct spdk_vhost_dev *vdev, const char *name, const char *ma
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spdk_vhost_lock();
|
||||
if (spdk_vhost_dev_find(name)) {
|
||||
SPDK_ERRLOG("vhost controller %s already exists.\n", name);
|
||||
spdk_vhost_unlock();
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
vdev->name = strdup(name);
|
||||
if (vdev->name == NULL) {
|
||||
spdk_vhost_unlock();
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -145,10 +148,12 @@ vhost_dev_register(struct spdk_vhost_dev *vdev, const char *name, const char *ma
|
||||
}
|
||||
if (rc != 0) {
|
||||
free(vdev->name);
|
||||
spdk_vhost_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_vhost_devices, vdev, tailq);
|
||||
spdk_vhost_unlock();
|
||||
|
||||
SPDK_INFOLOG(vhost, "Controller %s: new controller added\n", vdev->name);
|
||||
return 0;
|
||||
@ -171,11 +176,13 @@ vhost_dev_unregister(struct spdk_vhost_dev *vdev)
|
||||
SPDK_INFOLOG(vhost, "Controller %s: removed\n", vdev->name);
|
||||
|
||||
free(vdev->name);
|
||||
TAILQ_REMOVE(&g_vhost_devices, vdev, tailq);
|
||||
|
||||
spdk_vhost_lock();
|
||||
TAILQ_REMOVE(&g_vhost_devices, vdev, tailq);
|
||||
if (TAILQ_EMPTY(&g_vhost_devices) && g_fini_cb != NULL) {
|
||||
g_fini_cb();
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -265,9 +272,7 @@ vhost_fini(void)
|
||||
{
|
||||
struct spdk_vhost_dev *vdev, *tmp;
|
||||
|
||||
spdk_vhost_lock();
|
||||
if (spdk_vhost_dev_next(NULL) == NULL) {
|
||||
spdk_vhost_unlock();
|
||||
g_fini_cb();
|
||||
return;
|
||||
}
|
||||
@ -279,7 +284,6 @@ vhost_fini(void)
|
||||
/* don't care if it fails, there's nothing we can do for now */
|
||||
vdev = tmp;
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
|
||||
/* g_fini_cb will get called when last device is unregistered. */
|
||||
}
|
||||
|
@ -1141,10 +1141,8 @@ vhost_session_bdev_resize_cb(struct spdk_vhost_dev *vdev,
|
||||
static void
|
||||
vhost_user_blk_resize_cb(struct spdk_vhost_dev *vdev, bdev_event_cb_complete cb, void *cb_arg)
|
||||
{
|
||||
spdk_vhost_lock();
|
||||
vhost_user_dev_foreach_session(vdev, vhost_session_bdev_resize_cb,
|
||||
cb, cb_arg);
|
||||
spdk_vhost_unlock();
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1182,10 +1180,8 @@ vhost_user_bdev_remove_cb(struct spdk_vhost_dev *vdev, bdev_event_cb_complete cb
|
||||
SPDK_WARNLOG("%s: hot-removing bdev - all further requests will fail.\n",
|
||||
vdev->name);
|
||||
|
||||
spdk_vhost_lock();
|
||||
vhost_user_dev_foreach_session(vdev, vhost_user_session_bdev_remove_cb,
|
||||
cb, cb_arg);
|
||||
spdk_vhost_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1363,9 +1359,10 @@ destroy_session_poller_cb(void *arg)
|
||||
{
|
||||
struct spdk_vhost_blk_session *bvsession = arg;
|
||||
struct spdk_vhost_session *vsession = &bvsession->vsession;
|
||||
struct spdk_vhost_user_dev *user_dev = to_user_dev(vsession->vdev);
|
||||
int i;
|
||||
|
||||
if (vsession->task_cnt > 0 || spdk_vhost_trylock() != 0) {
|
||||
if (vsession->task_cnt > 0 || (pthread_mutex_trylock(&user_dev->lock) != 0)) {
|
||||
assert(vsession->stop_retry_count > 0);
|
||||
vsession->stop_retry_count--;
|
||||
if (vsession->stop_retry_count == 0) {
|
||||
@ -1395,7 +1392,7 @@ destroy_session_poller_cb(void *arg)
|
||||
spdk_poller_unregister(&bvsession->stop_poller);
|
||||
vhost_user_session_stop_done(vsession, 0);
|
||||
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return SPDK_POLLER_BUSY;
|
||||
}
|
||||
|
||||
@ -1599,8 +1596,6 @@ spdk_vhost_blk_construct(const char *name, const char *cpumask, const char *dev_
|
||||
const char *transport_name = VIRTIO_BLK_DEFAULT_TRANSPORT;
|
||||
int ret = 0;
|
||||
|
||||
spdk_vhost_lock();
|
||||
|
||||
bvdev = calloc(1, sizeof(*bvdev));
|
||||
if (bvdev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
@ -1669,7 +1664,6 @@ out:
|
||||
if (ret != 0 && bvdev) {
|
||||
free(bvdev);
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -156,6 +156,9 @@ struct spdk_vhost_user_dev {
|
||||
|
||||
bool registered;
|
||||
|
||||
/* Use this lock to protect multiple sessions. */
|
||||
pthread_mutex_t lock;
|
||||
|
||||
/* Current connections to the device */
|
||||
TAILQ_HEAD(, spdk_vhost_session) vsessions;
|
||||
|
||||
@ -188,6 +191,13 @@ struct spdk_vhost_dev {
|
||||
TAILQ_ENTRY(spdk_vhost_dev) tailq;
|
||||
};
|
||||
|
||||
static inline struct spdk_vhost_user_dev *
|
||||
to_user_dev(struct spdk_vhost_dev *vdev)
|
||||
{
|
||||
assert(vdev != NULL);
|
||||
return vdev->ctxt;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param vdev vhost device.
|
||||
* \param vsession vhost session.
|
||||
|
@ -293,9 +293,9 @@ rpc_vhost_delete_controller(struct spdk_jsonrpc_request *request,
|
||||
rc = -ENODEV;
|
||||
goto invalid;
|
||||
}
|
||||
spdk_vhost_unlock();
|
||||
|
||||
rc = spdk_vhost_dev_remove(vdev);
|
||||
spdk_vhost_unlock();
|
||||
if (rc < 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
@ -169,6 +169,15 @@ vhost_scsi_task_free_cb(struct spdk_scsi_task *scsi_task)
|
||||
task->used = false;
|
||||
}
|
||||
|
||||
static void
|
||||
vhost_scsi_dev_unregister(void *arg1)
|
||||
{
|
||||
struct spdk_vhost_scsi_dev *svdev = arg1;
|
||||
|
||||
vhost_dev_unregister(&svdev->vdev);
|
||||
free(svdev);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_scsi_tgt(struct spdk_vhost_scsi_dev *svdev,
|
||||
unsigned scsi_tgt_num)
|
||||
@ -189,8 +198,10 @@ remove_scsi_tgt(struct spdk_vhost_scsi_dev *svdev,
|
||||
SPDK_INFOLOG(vhost, "removed target 'Target %u'\n", scsi_tgt_num);
|
||||
|
||||
if (--svdev->ref == 0 && svdev->registered == false) {
|
||||
vhost_dev_unregister(&svdev->vdev);
|
||||
free(svdev);
|
||||
/* `remove_scsi_tgt` is running under vhost-user lock, so we
|
||||
* unregister the device in next poll.
|
||||
*/
|
||||
spdk_thread_send_msg(spdk_get_thread(), vhost_scsi_dev_unregister, svdev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,12 +259,10 @@ process_removed_devs(struct spdk_vhost_scsi_session *svsession)
|
||||
state->dev = NULL;
|
||||
state->status = VHOST_SCSI_DEV_REMOVED;
|
||||
/* try to detach it globally */
|
||||
spdk_vhost_lock();
|
||||
vhost_user_dev_foreach_session(&svsession->svdev->vdev,
|
||||
vhost_scsi_session_process_removed,
|
||||
vhost_scsi_dev_process_removed_cpl_cb,
|
||||
(void *)(uintptr_t)i);
|
||||
spdk_vhost_unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -860,19 +869,16 @@ spdk_vhost_scsi_dev_construct(const char *name, const char *cpumask)
|
||||
svdev->vdev.disabled_features = SPDK_VHOST_SCSI_DISABLED_FEATURES;
|
||||
svdev->vdev.protocol_features = SPDK_VHOST_SCSI_PROTOCOL_FEATURES;
|
||||
|
||||
spdk_vhost_lock();
|
||||
rc = vhost_dev_register(&svdev->vdev, name, cpumask, NULL,
|
||||
&spdk_vhost_scsi_device_backend,
|
||||
&spdk_vhost_scsi_user_device_backend);
|
||||
if (rc) {
|
||||
free(svdev);
|
||||
spdk_vhost_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
svdev->registered = true;
|
||||
|
||||
spdk_vhost_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1409,10 +1415,11 @@ destroy_session_poller_cb(void *arg)
|
||||
{
|
||||
struct spdk_vhost_scsi_session *svsession = arg;
|
||||
struct spdk_vhost_session *vsession = &svsession->vsession;
|
||||
struct spdk_vhost_user_dev *user_dev = to_user_dev(vsession->vdev);
|
||||
struct spdk_scsi_dev_session_state *state;
|
||||
uint32_t i;
|
||||
|
||||
if (vsession->task_cnt > 0 || spdk_vhost_trylock() != 0) {
|
||||
if (vsession->task_cnt > 0 || (pthread_mutex_trylock(&user_dev->lock) != 0)) {
|
||||
assert(vsession->stop_retry_count > 0);
|
||||
vsession->stop_retry_count--;
|
||||
if (vsession->stop_retry_count == 0) {
|
||||
@ -1461,7 +1468,7 @@ destroy_session_poller_cb(void *arg)
|
||||
spdk_poller_unregister(&svsession->stop_poller);
|
||||
vhost_user_session_stop_done(vsession, 0);
|
||||
|
||||
spdk_vhost_unlock();
|
||||
pthread_mutex_unlock(&user_dev->lock);
|
||||
return SPDK_POLLER_BUSY;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user