diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index e5b1d85188..e801f6dca3 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -268,19 +268,18 @@ spdk_vhost_vq_used_signal(struct spdk_vhost_session *vsession, static void check_session_io_stats(struct spdk_vhost_session *vsession, uint64_t now) { - struct spdk_vhost_dev *vdev = vsession->vdev; struct spdk_vhost_virtqueue *virtqueue; - uint32_t irq_delay_base = vdev->coalescing_delay_time_base; - uint32_t io_threshold = vdev->coalescing_io_rate_threshold; + uint32_t irq_delay_base = vsession->coalescing_delay_time_base; + uint32_t io_threshold = vsession->coalescing_io_rate_threshold; int32_t irq_delay; uint32_t req_cnt; uint16_t q_idx; - if (now < vdev->next_stats_check_time) { + if (now < vsession->next_stats_check_time) { return; } - vdev->next_stats_check_time = now + vdev->stats_check_interval; + vsession->next_stats_check_time = now + vsession->stats_check_interval; for (q_idx = 0; q_idx < vsession->max_queues; q_idx++) { virtqueue = &vsession->virtqueue[q_idx]; @@ -300,12 +299,11 @@ check_session_io_stats(struct spdk_vhost_session *vsession, uint64_t now) void spdk_vhost_session_used_signal(struct spdk_vhost_session *vsession) { - struct spdk_vhost_dev *vdev = vsession->vdev; struct spdk_vhost_virtqueue *virtqueue; uint64_t now; uint16_t q_idx; - if (vdev->coalescing_delay_time_base == 0) { + if (vsession->coalescing_delay_time_base == 0) { for (q_idx = 0; q_idx < vsession->max_queues; q_idx++) { virtqueue = &vsession->virtqueue[q_idx]; @@ -340,19 +338,33 @@ spdk_vhost_session_used_signal(struct spdk_vhost_session *vsession) } } +static int +spdk_vhost_session_set_coalescing(struct spdk_vhost_dev *vdev, + struct spdk_vhost_session *vsession, void *ctx) +{ + if (vdev == NULL || vsession == NULL) { + /* nothing to do */ + return 0; + } + + vsession->coalescing_delay_time_base = vdev->coalescing_delay_time_base; + vsession->coalescing_io_rate_threshold = vdev->coalescing_io_rate_threshold; + return 0; +} + int spdk_vhost_set_coalescing(struct spdk_vhost_dev *vdev, uint32_t delay_base_us, uint32_t iops_threshold) { uint64_t delay_time_base = delay_base_us * spdk_get_ticks_hz() / 1000000ULL; - uint32_t io_rate = iops_threshold * SPDK_VHOST_DEV_STATS_CHECK_INTERVAL_MS / 1000U; + uint32_t io_rate = iops_threshold * SPDK_VHOST_STATS_CHECK_INTERVAL_MS / 1000U; if (delay_time_base >= UINT32_MAX) { SPDK_ERRLOG("Delay time of %"PRIu32" is to big\n", delay_base_us); return -EINVAL; } else if (io_rate == 0) { SPDK_ERRLOG("IOPS rate of %"PRIu32" is too low. Min is %u\n", io_rate, - 1000U / SPDK_VHOST_DEV_STATS_CHECK_INTERVAL_MS); + 1000U / SPDK_VHOST_STATS_CHECK_INTERVAL_MS); return -EINVAL; } @@ -361,6 +373,8 @@ spdk_vhost_set_coalescing(struct spdk_vhost_dev *vdev, uint32_t delay_base_us, vdev->coalescing_delay_us = delay_base_us; vdev->coalescing_iops_threshold = iops_threshold; + + spdk_vhost_dev_foreach_session(vdev, spdk_vhost_session_set_coalescing, NULL); return 0; } @@ -757,9 +771,6 @@ spdk_vhost_dev_register(struct spdk_vhost_dev *vdev, const char *name, const cha spdk_vhost_set_coalescing(vdev, SPDK_VHOST_COALESCING_DELAY_BASE_US, SPDK_VHOST_VQ_IOPS_COALESCING_THRESHOLD); - vdev->next_stats_check_time = 0; - vdev->stats_check_interval = SPDK_VHOST_DEV_STATS_CHECK_INTERVAL_MS * spdk_get_ticks_hz() / - 1000UL; TAILQ_INSERT_TAIL(&g_spdk_vhost_devices, vdev, tailq); @@ -1130,6 +1141,7 @@ start_device(int vid) } } + spdk_vhost_session_set_coalescing(vdev, vsession, NULL); vdev->lcore = spdk_vhost_allocate_reactor(vdev->cpumask); spdk_vhost_session_mem_register(vsession); rc = _spdk_vhost_event_send(vdev, vdev->backend->start_device, 3, "start device"); @@ -1282,6 +1294,9 @@ new_connection(int vid) vsession->vdev = vdev; vsession->vid = vid; + vsession->next_stats_check_time = 0; + vsession->stats_check_interval = SPDK_VHOST_STATS_CHECK_INTERVAL_MS * + spdk_get_ticks_hz() / 1000UL; vdev->session = vsession; pthread_mutex_unlock(&g_spdk_vhost_mutex); return 0; diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index 97f0e707dc..a3db7d9211 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -70,7 +70,7 @@ /* * Rate at which stats are checked for interrupt coalescing. */ -#define SPDK_VHOST_DEV_STATS_CHECK_INTERVAL_MS 10 +#define SPDK_VHOST_STATS_CHECK_INTERVAL_MS 10 /* * Default threshold at which interrupts start to be coalesced. */ @@ -147,6 +147,16 @@ struct spdk_vhost_session { uint64_t negotiated_features; + /* Local copy of device coalescing settings. */ + uint32_t coalescing_delay_time_base; + uint32_t coalescing_io_rate_threshold; + + /* Next time when stats for event coalescing will be checked. */ + uint64_t next_stats_check_time; + + /* Interval used for event coalescing checking. */ + uint64_t stats_check_interval; + struct spdk_vhost_virtqueue virtqueue[SPDK_VHOST_MAX_VQUEUES]; }; @@ -174,12 +184,6 @@ struct spdk_vhost_dev { /* Threshold when event coalescing for virtqueue will be turned on. */ uint32_t coalescing_io_rate_threshold; - /* Next time when stats for event coalescing will be checked. */ - uint64_t next_stats_check_time; - - /* Interval used for event coalescing checking. */ - uint64_t stats_check_interval; - /* Active connection to the device */ struct spdk_vhost_session *session;