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:
Changpeng Liu 2022-10-28 16:57:47 +08:00 committed by Jim Harris
parent d37a07f7c0
commit 376c25ed0c
6 changed files with 124 additions and 73 deletions

View File

@ -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);
}

View File

@ -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. */
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}