bdev/qos: Add unit tests for spdk_bdev_set_qos_limit_iops

These won't cover race conditions across threads, but
at least we have something to test the behavior.

Change-Id: I8e620d2076fe7a3d95df668fda4bee49b6d0afa7
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/409343
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Ben Walker 2018-04-27 10:04:58 -07:00
parent 8e17d9f21f
commit e18d2b7687
2 changed files with 107 additions and 4 deletions

View File

@ -3017,10 +3017,8 @@ spdk_bdev_set_qos_limit_iops(struct spdk_bdev *bdev, uint64_t ios_per_sec,
/* QoS not enabled on this bdev */
if (!thread && ios_per_sec == 0) {
pthread_mutex_unlock(&bdev->mutex);
SPDK_ERRLOG("Requested ios_per_sec limit %" PRIu64 " is not a multiple of %u\n",
ios_per_sec, SPDK_BDEV_QOS_MIN_IOS_PER_SEC);
free(ctx);
cb_fn(cb_arg, -EINVAL);
cb_fn(cb_arg, 0);
return;
}
bdev->qos.enabled = true;

View File

@ -1043,6 +1043,110 @@ enomem_multi_bdev(void)
teardown_test();
}
static void
qos_dynamic_enable_done(void *cb_arg, int status)
{
int *rc = cb_arg;
*rc = status;
}
static void
qos_dynamic_enable(void)
{
struct spdk_io_channel *io_ch[2];
struct spdk_bdev_channel *bdev_ch[2];
struct spdk_bdev *bdev;
int status, second_status;
setup_test();
reset_time();
bdev = &g_bdev.bdev;
g_get_io_channel = true;
/* Create channels */
set_thread(0);
io_ch[0] = spdk_bdev_get_io_channel(g_desc);
bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
CU_ASSERT(bdev_ch[0]->flags == 0);
set_thread(1);
io_ch[1] = spdk_bdev_get_io_channel(g_desc);
bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
CU_ASSERT(bdev_ch[1]->flags == 0);
set_thread(0);
/* Enable QoS */
status = -1;
spdk_bdev_set_qos_limit_iops(bdev, 10000, qos_dynamic_enable_done, &status);
poll_threads();
CU_ASSERT(status == 0);
CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
/* Disable QoS */
status = -1;
spdk_bdev_set_qos_limit_iops(bdev, 0, qos_dynamic_enable_done, &status);
poll_threads();
CU_ASSERT(status == 0);
CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) == 0);
CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) == 0);
/* Disable QoS again */
status = -1;
spdk_bdev_set_qos_limit_iops(bdev, 0, qos_dynamic_enable_done, &status);
poll_threads();
CU_ASSERT(status == 0); /* This should succeed */
CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) == 0);
CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) == 0);
/* Enable QoS on thread 0 */
status = -1;
spdk_bdev_set_qos_limit_iops(bdev, 10000, qos_dynamic_enable_done, &status);
poll_threads();
CU_ASSERT(status == 0);
CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
/* Disable QoS on thread 1 */
set_thread(1);
status = -1;
spdk_bdev_set_qos_limit_iops(bdev, 0, qos_dynamic_enable_done, &status);
/* Don't poll yet. This should leave the channels with QoS enabled */
CU_ASSERT(status == -1);
CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
/* Enable QoS. This should immediately fail because the previous disable QoS hasn't completed. */
second_status = 0;
spdk_bdev_set_qos_limit_iops(bdev, 10000, qos_dynamic_enable_done, &second_status);
poll_threads();
CU_ASSERT(status == 0); /* The disable should succeed */
CU_ASSERT(second_status < 0); /* The enable should fail */
CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) == 0);
CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) == 0);
/* Enable QoS on thread 1. This should succeed now that the disable has completed. */
status = -1;
spdk_bdev_set_qos_limit_iops(bdev, 10000, qos_dynamic_enable_done, &status);
poll_threads();
CU_ASSERT(status == 0);
CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
/* Tear down the channels */
set_thread(0);
spdk_put_io_channel(io_ch[0]);
set_thread(1);
spdk_put_io_channel(io_ch[1]);
poll_threads();
set_thread(0);
teardown_test();
}
int
main(int argc, char **argv)
{
@ -1069,7 +1173,8 @@ main(int argc, char **argv)
CU_add_test(suite, "io_during_qos_queue", io_during_qos_queue) == NULL ||
CU_add_test(suite, "io_during_qos_reset", io_during_qos_reset) == NULL ||
CU_add_test(suite, "enomem", enomem) == NULL ||
CU_add_test(suite, "enomem_multi_bdev", enomem_multi_bdev) == NULL
CU_add_test(suite, "enomem_multi_bdev", enomem_multi_bdev) == NULL ||
CU_add_test(suite, "qos_dynamic_enable", qos_dynamic_enable) == NULL
) {
CU_cleanup_registry();
return CU_get_error();