diff --git a/test/unit/lib/bdev/bdev.c/bdev_ut.c b/test/unit/lib/bdev/bdev.c/bdev_ut.c index 68cc18f59c..eb9cfd8607 100644 --- a/test/unit/lib/bdev/bdev.c/bdev_ut.c +++ b/test/unit/lib/bdev/bdev.c/bdev_ut.c @@ -59,6 +59,10 @@ DEFINE_STUB_V(spdk_trace_register_description, (const char *name, const char *sh DEFINE_STUB_V(_spdk_trace_record, (uint64_t tsc, uint16_t tpoint_id, uint16_t poller_id, uint32_t size, uint64_t object_id, uint64_t arg1)); +int g_status; +int g_count; +struct spdk_histogram_data *g_histogram; + void spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io, int *sc, int *sk, int *asc, int *ascq) @@ -1427,6 +1431,114 @@ bdev_io_alignment(void) free(buf); } +static void +histogram_status_cb(void *cb_arg, int status) +{ + g_status = status; +} + +static void +histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) +{ + g_status = status; + g_histogram = histogram; +} + +static void +histogram_io_count(void *ctx, uint64_t start, uint64_t end, uint64_t count, + uint64_t total, uint64_t so_far) +{ + g_count += count; +} + +static void +bdev_histograms(void) +{ + struct spdk_bdev *bdev; + struct spdk_bdev_desc *desc; + struct spdk_io_channel *ch; + struct spdk_histogram_data *histogram; + uint8_t buf[4096]; + int rc; + + spdk_bdev_initialize(bdev_init_cb, NULL); + + bdev = allocate_bdev("bdev"); + + rc = spdk_bdev_open(bdev, true, NULL, NULL, &desc); + CU_ASSERT(rc == 0); + CU_ASSERT(desc != NULL); + + ch = spdk_bdev_get_io_channel(desc); + CU_ASSERT(ch != NULL); + + /* Enable histogram */ + g_status = -1; + spdk_bdev_histogram_enable(bdev, histogram_status_cb, NULL, true); + poll_threads(); + CU_ASSERT(g_status == 0); + CU_ASSERT(bdev->internal.histogram_enabled == true); + + /* Allocate histogram */ + histogram = spdk_histogram_data_alloc(); + SPDK_CU_ASSERT_FATAL(histogram != NULL); + + /* Check if histogram is zeroed */ + spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); + poll_threads(); + CU_ASSERT(g_status == 0); + SPDK_CU_ASSERT_FATAL(g_histogram != NULL); + + g_count = 0; + spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); + + CU_ASSERT(g_count == 0); + + rc = spdk_bdev_write_blocks(desc, ch, &buf, 0, 1, io_done, NULL); + CU_ASSERT(rc == 0); + + spdk_delay_us(10); + stub_complete_io(1); + poll_threads(); + + rc = spdk_bdev_read_blocks(desc, ch, &buf, 0, 1, io_done, NULL); + CU_ASSERT(rc == 0); + + spdk_delay_us(10); + stub_complete_io(1); + poll_threads(); + + /* Check if histogram gathered data from all I/O channels */ + g_histogram = NULL; + spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); + poll_threads(); + CU_ASSERT(g_status == 0); + CU_ASSERT(bdev->internal.histogram_enabled == true); + SPDK_CU_ASSERT_FATAL(g_histogram != NULL); + + g_count = 0; + spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); + CU_ASSERT(g_count == 2); + + /* Disable histogram */ + spdk_bdev_histogram_enable(bdev, histogram_status_cb, NULL, false); + poll_threads(); + CU_ASSERT(g_status == 0); + CU_ASSERT(bdev->internal.histogram_enabled == false); + + /* Try to run histogram commands on disabled bdev */ + spdk_bdev_histogram_get(bdev, histogram, histogram_data_cb, NULL); + poll_threads(); + CU_ASSERT(g_status == -EFAULT); + + spdk_histogram_data_free(g_histogram); + spdk_put_io_channel(ch); + spdk_bdev_close(desc); + free_bdev(bdev); + spdk_bdev_finish(bdev_fini_cb, NULL); + poll_threads(); +} + int main(int argc, char **argv) { @@ -1454,7 +1566,8 @@ main(int argc, char **argv) CU_add_test(suite, "bdev_io_spans_boundary", bdev_io_spans_boundary_test) == NULL || CU_add_test(suite, "bdev_io_split", bdev_io_split) == NULL || CU_add_test(suite, "bdev_io_split_with_io_wait", bdev_io_split_with_io_wait) == NULL || - CU_add_test(suite, "bdev_io_alignment", bdev_io_alignment) == NULL + CU_add_test(suite, "bdev_io_alignment", bdev_io_alignment) == NULL || + CU_add_test(suite, "bdev_histograms", bdev_histograms) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c b/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c index 9ba931bf65..6efb8fb378 100644 --- a/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c +++ b/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c @@ -80,6 +80,9 @@ bool g_get_io_channel = true; bool g_create_ch = true; bool g_init_complete_called = false; bool g_fini_start_called = true; +int g_status = 0; +int g_count = 0; +struct spdk_histogram_data *g_histogram = NULL; static int stub_create_ch(void *io_device, void *ctx_buf) @@ -1314,6 +1317,108 @@ qos_dynamic_enable(void) teardown_test(); } +static void +histogram_status_cb(void *cb_arg, int status) +{ + g_status = status; +} + +static void +histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) +{ + g_status = status; + g_histogram = histogram; +} + +static void +histogram_io_count(void *ctx, uint64_t start, uint64_t end, uint64_t count, + uint64_t total, uint64_t so_far) +{ + g_count += count; +} + +static void +bdev_histograms_mt(void) +{ + struct spdk_io_channel *ch[2]; + struct spdk_histogram_data *histogram; + uint8_t buf[4096]; + int status = false; + int rc; + + + setup_test(); + + set_thread(0); + ch[0] = spdk_bdev_get_io_channel(g_desc); + CU_ASSERT(ch[0] != NULL); + + set_thread(1); + ch[1] = spdk_bdev_get_io_channel(g_desc); + CU_ASSERT(ch[1] != NULL); + + + /* Enable histogram */ + spdk_bdev_histogram_enable(&g_bdev.bdev, histogram_status_cb, NULL, true); + poll_threads(); + CU_ASSERT(g_status == 0); + CU_ASSERT(g_bdev.bdev.internal.histogram_enabled == true); + + /* Allocate histogram */ + histogram = spdk_histogram_data_alloc(); + + /* Check if histogram is zeroed */ + spdk_bdev_histogram_get(&g_bdev.bdev, histogram, histogram_data_cb, NULL); + poll_threads(); + CU_ASSERT(g_status == 0); + SPDK_CU_ASSERT_FATAL(g_histogram != NULL); + + g_count = 0; + spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); + + CU_ASSERT(g_count == 0); + + set_thread(0); + rc = spdk_bdev_write_blocks(g_desc, ch[0], &buf, 0, 1, io_during_io_done, &status); + CU_ASSERT(rc == 0); + + spdk_delay_us(10); + stub_complete_io(g_bdev.io_target, 1); + poll_threads(); + CU_ASSERT(status == true); + + + set_thread(1); + rc = spdk_bdev_read_blocks(g_desc, ch[1], &buf, 0, 1, io_during_io_done, &status); + CU_ASSERT(rc == 0); + + spdk_delay_us(10); + stub_complete_io(g_bdev.io_target, 1); + poll_threads(); + CU_ASSERT(status == true); + + set_thread(0); + + /* Check if histogram gathered data from all I/O channels */ + spdk_bdev_histogram_get(&g_bdev.bdev, histogram, histogram_data_cb, NULL); + poll_threads(); + CU_ASSERT(g_status == 0); + CU_ASSERT(g_bdev.bdev.internal.histogram_enabled == true); + SPDK_CU_ASSERT_FATAL(g_histogram != NULL); + + g_count = 0; + spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL); + CU_ASSERT(g_count == 2); + + /* Disable histogram */ + spdk_bdev_histogram_enable(&g_bdev.bdev, histogram_status_cb, NULL, false); + poll_threads(); + CU_ASSERT(g_status == 0); + CU_ASSERT(g_bdev.bdev.internal.histogram_enabled == false); + + spdk_histogram_data_free(g_histogram); +} + int main(int argc, char **argv) { @@ -1342,7 +1447,8 @@ main(int argc, char **argv) CU_add_test(suite, "enomem", enomem) == NULL || CU_add_test(suite, "enomem_multi_bdev", enomem_multi_bdev) == NULL || CU_add_test(suite, "enomem_multi_io_target", enomem_multi_io_target) == NULL || - CU_add_test(suite, "qos_dynamic_enable", qos_dynamic_enable) == NULL + CU_add_test(suite, "qos_dynamic_enable", qos_dynamic_enable) == NULL || + CU_add_test(suite, "bdev_histograms_mt", bdev_histograms_mt) == NULL ) { CU_cleanup_registry(); return CU_get_error();