vhost_scsi: fix bug with tasks enqueue/dequeue

We need MP MC ring for tasks. So instead implementing this add per
controller ring to avoid this issue.

Change-Id: I5926ad7866ab28251aeebd163917de2df2b44a22
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/368547
Reviewed-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Pawel Wodkowski 2017-07-07 16:10:41 +02:00 committed by Jim Harris
parent 5586209634
commit 05fd28399a

View File

@ -72,13 +72,12 @@
/* Allocated iovec buffer len */
#define SPDK_VHOST_SCSI_IOVS_LEN 128
#define SPDK_VHOST_SCSI_TASK_POOL_SIZE 16384
struct spdk_vhost_scsi_dev {
struct spdk_vhost_dev vdev;
struct spdk_scsi_dev *scsi_dev[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];
bool removed_dev[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];
struct spdk_ring *task_pool;
struct spdk_poller *requestq_poller;
struct spdk_poller *mgmt_poller;
@ -114,8 +113,6 @@ const struct spdk_vhost_dev_backend spdk_vhost_scsi_device_backend = {
}
};
static struct spdk_ring *g_task_pool;
static void
spdk_vhost_task_put(struct spdk_vhost_task *task)
{
@ -129,7 +126,7 @@ spdk_vhost_task_free_cb(struct spdk_scsi_task *scsi_task)
assert(task->svdev->vdev.task_cnt > 0);
task->svdev->vdev.task_cnt--;
spdk_ring_enqueue(g_task_pool, (void **) &task, 1);
spdk_ring_enqueue(task->svdev->task_pool, (void **) &task, 1);
}
static void
@ -138,7 +135,7 @@ spdk_vhost_get_tasks(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_task *
{
size_t res_count;
res_count = spdk_ring_dequeue(g_task_pool, (void **)tasks, count);
res_count = spdk_ring_dequeue(svdev->task_pool, (void **)tasks, count);
if (res_count != count) {
SPDK_ERRLOG("%s: couldn't get %zu tasks from task_pool\n", svdev->vdev.name, count);
/* FIXME: we should never run out of tasks, but what if we do? */
@ -955,6 +952,66 @@ spdk_vhost_scsi_controller_construct(void)
return 0;
}
static void
free_task_pool(struct spdk_vhost_scsi_dev *svdev)
{
struct spdk_vhost_task *task;
if (!svdev->task_pool) {
return;
}
while (spdk_ring_dequeue(svdev->task_pool, (void **)&task, 1) == 1) {
spdk_dma_free(task);
}
spdk_ring_free(svdev->task_pool);
svdev->task_pool = NULL;
}
static int
alloc_task_pool(struct spdk_vhost_scsi_dev *svdev)
{
struct spdk_vhost_task *task;
uint32_t task_cnt = 0;
uint32_t ring_size;
uint16_t i;
int rc;
for (i = 0; i < svdev->vdev.num_queues; i++) {
/*
* FIXME:
* this is too big because we need only size/2 from each queue but for now
* lets leave it as is to be sure we are not mistaken.
*
* Limit the pool size to 1024 * num_queues. This should be enough as QEMU have the
* same hard limit for queue size.
*/
task_cnt += spdk_min(svdev->vdev.virtqueue[i].size, 1024);
}
ring_size = spdk_align32pow2(task_cnt + 1);
svdev->task_pool = spdk_ring_create(SPDK_RING_TYPE_SP_SC, ring_size,
spdk_env_get_socket_id(svdev->vdev.lcore));
if (svdev->task_pool == NULL) {
SPDK_ERRLOG("Controller %s: Failed to init vhost scsi task pool\n", svdev->vdev.name);
return -1;
}
for (i = 0; i < task_cnt; ++i) {
task = spdk_dma_zmalloc(sizeof(*task), SPDK_CACHE_LINE_SIZE, NULL);
rc = spdk_ring_enqueue(svdev->task_pool, (void **)&task, 1);
if (rc != 1) {
SPDK_ERRLOG("Controller %s: Failed to alloc %"PRIu32" vhost scsi tasks\n", svdev->vdev.name,
task_cnt);
free_task_pool(svdev);
return -1;
}
}
return 0;
}
/*
* A new device is added to a data core. First the device is added to the main linked list
* and then allocated to a specific data core.
@ -969,6 +1026,11 @@ new_device(int vid)
return -1;
}
if (alloc_task_pool(svdev)) {
spdk_vhost_dev_unload(&svdev->vdev);
return -1;
}
spdk_vhost_timed_event_send(svdev->vdev.lcore, add_vdev_cb, svdev, 1, "add scsi vdev");
return 0;
}
@ -1007,44 +1069,19 @@ destroy_device(int vid)
spdk_vhost_timed_event_send(vdev->lcore, remove_vdev_cb, svdev, 1, "remove scsi vdev");
free_task_pool(svdev);
spdk_vhost_dev_unload(vdev);
}
int
spdk_vhost_init(void)
{
struct spdk_vhost_dev *task;
int rc, i;
g_task_pool = spdk_ring_create(SPDK_RING_TYPE_MP_SC, SPDK_VHOST_SCSI_TASK_POOL_SIZE, SOCKET_ID_ANY);
if (g_task_pool == NULL) {
SPDK_ERRLOG("Failed to init vhost scsi task pool\n");
return -1;
}
for (i = 0; i < SPDK_VHOST_SCSI_TASK_POOL_SIZE - 1; ++i) {
task = spdk_dma_zmalloc(sizeof(*task), SPDK_CACHE_LINE_SIZE, NULL);
rc = spdk_ring_enqueue(g_task_pool, (void **)&task, 1);
if (rc != 1) {
SPDK_ERRLOG("Failed to alloc vhost scsi tasks\n");
return -1;
}
}
return 0;
}
int
spdk_vhost_fini(void)
{
struct spdk_vhost_dev *task;
while (spdk_ring_dequeue(g_task_pool, (void **)&task, 1) == 1) {
spdk_dma_free(task);
}
spdk_ring_free(g_task_pool);
return 0;
}