From 9cddfc0bbfb8ff3b75b3b6caa2c137f81d82e72c Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Tue, 22 Jan 2019 16:25:35 +0100 Subject: [PATCH] vhost: move lcore management to the device backend Although Vhost SCSI code is technically capable of polling different sessions on different lcores, the underlying SCSI API won't allow allocating io_channels on more than one lcore. That's why we will now let device backends assign lcores by themselves. The first Vhost SCSI session will now choose one core from the available ones, and any subsequent sessions will stick to the same one. Change-Id: I616cd195a919960dff68508473cea236abf8d6a3 Signed-off-by: Darek Stojaczyk Reviewed-on: https://review.gerrithub.io/c/441581 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Changpeng Liu Reviewed-by: Pawel Wodkowski Reviewed-by: Jim Harris --- lib/vhost/vhost.c | 8 ++--- lib/vhost/vhost_blk.c | 27 ++++++++++++++--- lib/vhost/vhost_internal.h | 3 ++ lib/vhost/vhost_nvme.c | 27 ++++++++++++++--- lib/vhost/vhost_scsi.c | 62 +++++++++++++++++++++++++++++--------- 5 files changed, 98 insertions(+), 29 deletions(-) diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index d52d34fe1..943c2b6b3 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -591,7 +591,7 @@ spdk_vhost_session_mem_unregister(struct spdk_vhost_session *vsession) } -static void +void spdk_vhost_free_reactor(uint32_t lcore) { g_num_ctrlrs[lcore]--; @@ -821,7 +821,7 @@ spdk_vhost_dev_get_cpumask(struct spdk_vhost_dev *vdev) return vdev->cpumask; } -static uint32_t +uint32_t spdk_vhost_allocate_reactor(struct spdk_cpuset *cpumask) { uint32_t i, selected_core; @@ -1025,7 +1025,6 @@ stop_device(int vid) spdk_vhost_session_mem_unregister(vsession); free(vsession->mem); - spdk_vhost_free_reactor(vsession->lcore); vsession->lcore = -1; assert(vdev->active_session_num > 0); vdev->active_session_num--; @@ -1101,14 +1100,11 @@ start_device(int vid) } spdk_vhost_session_set_coalescing(vdev, vsession, NULL); - vsession->lcore = spdk_vhost_allocate_reactor(vdev->cpumask); spdk_vhost_session_mem_register(vsession); rc = vdev->backend->start_session(vsession); if (rc != 0) { spdk_vhost_session_mem_unregister(vsession); free(vsession->mem); - spdk_vhost_free_reactor(vsession->lcore); - vsession->lcore = -1; goto out; } diff --git a/lib/vhost/vhost_blk.c b/lib/vhost/vhost_blk.c index 5507afa71..f615564e2 100644 --- a/lib/vhost/vhost_blk.c +++ b/lib/vhost/vhost_blk.c @@ -719,8 +719,18 @@ out: static int spdk_vhost_blk_start(struct spdk_vhost_session *vsession) { - return spdk_vhost_session_send_event(vsession, spdk_vhost_blk_start_cb, - 3, "start session"); + int rc; + + vsession->lcore = spdk_vhost_allocate_reactor(vsession->vdev->cpumask); + rc = spdk_vhost_session_send_event(vsession, spdk_vhost_blk_start_cb, + 3, "start session"); + + if (rc != 0) { + spdk_vhost_free_reactor(vsession->lcore); + vsession->lcore = -1; + } + + return rc; } static int @@ -779,8 +789,17 @@ err: static int spdk_vhost_blk_stop(struct spdk_vhost_session *vsession) { - return spdk_vhost_session_send_event(vsession, spdk_vhost_blk_stop_cb, - 3, "stop session"); + int rc; + + rc = spdk_vhost_session_send_event(vsession, spdk_vhost_blk_stop_cb, + 3, "stop session"); + if (rc != 0) { + return rc; + } + + spdk_vhost_free_reactor(vsession->lcore); + vsession->lcore = -1; + return 0; } static void diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index 6ef7acbfb..38adf850d 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -343,6 +343,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_free_reactor(uint32_t lcore); +uint32_t spdk_vhost_allocate_reactor(struct spdk_cpuset *cpumask); + void spdk_vhost_lock(void); void spdk_vhost_unlock(void); int spdk_remove_vhost_controller(struct spdk_vhost_dev *vdev); diff --git a/lib/vhost/vhost_nvme.c b/lib/vhost/vhost_nvme.c index 4ee377773..44c407e27 100644 --- a/lib/vhost/vhost_nvme.c +++ b/lib/vhost/vhost_nvme.c @@ -1106,14 +1106,24 @@ spdk_vhost_nvme_start_cb(struct spdk_vhost_dev *vdev, static int spdk_vhost_nvme_start(struct spdk_vhost_session *vsession) { + int rc; + if (vsession->vdev->active_session_num > 0) { /* We're trying to start a second session */ SPDK_ERRLOG("Vhost-NVMe devices can support only one simultaneous connection.\n"); return -1; } - return spdk_vhost_session_send_event(vsession, spdk_vhost_nvme_start_cb, - 3, "start session"); + vsession->lcore = spdk_vhost_allocate_reactor(vsession->vdev->cpumask); + rc = spdk_vhost_session_send_event(vsession, spdk_vhost_nvme_start_cb, + 3, "start session"); + + if (rc != 0) { + spdk_vhost_free_reactor(vsession->lcore); + vsession->lcore = -1; + } + + return rc; } static void @@ -1196,8 +1206,17 @@ spdk_vhost_nvme_stop_cb(struct spdk_vhost_dev *vdev, static int spdk_vhost_nvme_stop(struct spdk_vhost_session *vsession) { - return spdk_vhost_session_send_event(vsession, spdk_vhost_nvme_stop_cb, - 3, "start session"); + int rc; + + rc = spdk_vhost_session_send_event(vsession, spdk_vhost_nvme_stop_cb, + 3, "start session"); + if (rc != 0) { + return rc; + } + + spdk_vhost_free_reactor(vsession->lcore); + vsession->lcore = -1; + return 0; } static void diff --git a/lib/vhost/vhost_scsi.c b/lib/vhost/vhost_scsi.c index e3ca65db5..c4756cf0a 100644 --- a/lib/vhost/vhost_scsi.c +++ b/lib/vhost/vhost_scsi.c @@ -77,6 +77,9 @@ struct spdk_scsi_dev_vhost_state { struct spdk_vhost_scsi_dev { struct spdk_vhost_dev vdev; struct spdk_scsi_dev_vhost_state scsi_dev_state[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS]; + + /* The CPU chosen to poll I/O of all active vhost sessions */ + int32_t lcore; } __rte_cache_aligned; struct spdk_vhost_scsi_session { @@ -1217,14 +1220,7 @@ spdk_vhost_scsi_start_cb(struct spdk_vhost_dev *vdev, int rc; svsession = to_scsi_session(vsession); - if (svsession == NULL) { - SPDK_ERRLOG("Trying to start non-scsi controller as a scsi one.\n"); - rc = -1; - goto out; - } - - svdev = to_scsi_dev(vdev); - svsession->svdev = svdev; + svdev = svsession->svdev; /* validate all I/O queues are in a contiguous index range */ for (i = VIRTIO_SCSI_REQUESTQ; i < vsession->max_queues; i++) { @@ -1266,14 +1262,36 @@ out: static int spdk_vhost_scsi_start(struct spdk_vhost_session *vsession) { - if (vsession->vdev->active_session_num > 0) { - /* We're trying to start a second session */ - SPDK_ERRLOG("Vhost-SCSI devices can support only one simultaneous connection.\n"); + struct spdk_vhost_scsi_session *svsession; + struct spdk_vhost_scsi_dev *svdev; + int rc; + + svsession = to_scsi_session(vsession); + if (svsession == NULL) { + SPDK_ERRLOG("Trying to start non-scsi session as a scsi one.\n"); return -1; } - return spdk_vhost_session_send_event(vsession, spdk_vhost_scsi_start_cb, - 3, "start session"); + svdev = to_scsi_dev(vsession->vdev); + svsession->svdev = svdev; + + if (svdev->vdev.active_session_num == 0) { + svdev->lcore = spdk_vhost_allocate_reactor(svdev->vdev.cpumask); + } + + vsession->lcore = svdev->lcore; + rc = spdk_vhost_session_send_event(vsession, spdk_vhost_scsi_start_cb, + 3, "start session"); + if (rc != 0) { + vsession->lcore = -1; + + if (svdev->vdev.active_session_num == 0) { + spdk_vhost_free_reactor(svdev->lcore); + svdev->lcore = -1; + } + } + + return rc; } static int @@ -1339,8 +1357,22 @@ err: static int spdk_vhost_scsi_stop(struct spdk_vhost_session *vsession) { - return spdk_vhost_session_send_event(vsession, spdk_vhost_scsi_stop_cb, - 3, "stop session"); + struct spdk_vhost_scsi_session *svsession; + int rc; + + svsession = to_scsi_session(vsession); + rc = spdk_vhost_session_send_event(vsession, spdk_vhost_scsi_stop_cb, + 3, "stop session"); + if (rc != 0) { + return rc; + } + + vsession->lcore = -1; + if (vsession->vdev->active_session_num == 1) { + spdk_vhost_free_reactor(svsession->svdev->lcore); + svsession->svdev->lcore = -1; + } + return 0; } static void