diff --git a/test/common/lib/test_iobuf.c b/test/common/lib/test_iobuf.c new file mode 100644 index 000000000..2bf5983cb --- /dev/null +++ b/test/common/lib/test_iobuf.c @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2023 Intel Corporation. + * All rights reserved. + */ +#include "spdk/stdinc.h" + +#include "spdk_internal/mock.h" + +#include "spdk/thread.h" + +DEFINE_STUB(spdk_iobuf_initialize, int, (void), 0); +DEFINE_STUB(spdk_iobuf_register_module, int, (const char *name), 0); +DEFINE_STUB(spdk_iobuf_unregister_module, int, (const char *name), 0); +DEFINE_STUB_V(spdk_iobuf_channel_fini, (struct spdk_iobuf_channel *ch)); +DEFINE_STUB(spdk_iobuf_for_each_entry, int, (struct spdk_iobuf_channel *ch, + struct spdk_iobuf_pool *pool, spdk_iobuf_for_each_entry_fn cb_fn, void *cb_ctx), 0); +DEFINE_STUB_V(spdk_iobuf_entry_abort, (struct spdk_iobuf_channel *ch, + struct spdk_iobuf_entry *entry, uint64_t len)); + +struct ut_iobuf { + struct spdk_iobuf_opts opts; + uint32_t small_pool_count; + uint32_t large_pool_count; +}; + +static struct ut_iobuf g_iobuf = { + .small_pool_count = 32, + .large_pool_count = 32 +}; +static spdk_iobuf_entry_stailq_t g_iobuf_entries; + +int +spdk_iobuf_set_opts(const struct spdk_iobuf_opts *opts) +{ + g_iobuf.opts = *opts; + g_iobuf.small_pool_count = opts->small_pool_count; + g_iobuf.large_pool_count = opts->large_pool_count; + return 0; +} + +void +spdk_iobuf_get_opts(struct spdk_iobuf_opts *opts) +{ + *opts = g_iobuf.opts; +} + +void +spdk_iobuf_finish(spdk_iobuf_finish_cb cb_fn, void *cb_arg) +{ + cb_fn(cb_arg); +} + +int +spdk_iobuf_channel_init(struct spdk_iobuf_channel *ch, const char *name, + uint32_t small_cache_size, uint32_t large_cache_size) +{ + STAILQ_INIT(&g_iobuf_entries); + ch->small.cache_count = small_cache_size; + ch->small.cache_size = small_cache_size; + ch->large.cache_count = large_cache_size; + ch->large.cache_size = large_cache_size; + return 0; +} + +DEFINE_RETURN_MOCK(spdk_iobuf_get, void *); +void * +spdk_iobuf_get(struct spdk_iobuf_channel *ch, uint64_t len, + struct spdk_iobuf_entry *entry, spdk_iobuf_get_cb cb_fn) +{ + struct spdk_iobuf_pool *pool; + uint32_t *count; + void *buf; + + HANDLE_RETURN_MOCK(spdk_iobuf_get); + + if (len > g_iobuf.opts.small_bufsize) { + pool = &ch->large; + count = &g_iobuf.large_pool_count; + } else { + pool = &ch->small; + count = &g_iobuf.small_pool_count; + } + + if (pool->cache_count > 0) { + buf = calloc(1, len); + CU_ASSERT(buf != NULL); + pool->cache_count--; + return buf; + } + + if (*count == 0) { + if (entry) { + entry->cb_fn = cb_fn; + STAILQ_INSERT_TAIL(&g_iobuf_entries, entry, stailq); + } + + return NULL; + } + + buf = calloc(1, len); + CU_ASSERT(buf != NULL); + (*count)--; + return buf; +} + +void +spdk_iobuf_put(struct spdk_iobuf_channel *ch, void *buf, uint64_t len) +{ + struct spdk_iobuf_entry *entry; + struct spdk_iobuf_pool *pool; + uint32_t *count; + + if (len > g_iobuf.opts.small_bufsize) { + pool = &ch->large; + count = &g_iobuf.large_pool_count; + } else { + pool = &ch->small; + count = &g_iobuf.small_pool_count; + } + + if (!STAILQ_EMPTY(&g_iobuf_entries)) { + entry = STAILQ_FIRST(&g_iobuf_entries); + STAILQ_REMOVE_HEAD(&g_iobuf_entries, stailq); + entry->cb_fn(entry, buf); + return; + } + + if (pool->cache_count < pool->cache_size) { + pool->cache_count++; + } else { + (*count)++; + } + + free(buf); +} diff --git a/test/common/skipped_build_files.txt b/test/common/skipped_build_files.txt index c43f1e397..c4852d054 100644 --- a/test/common/skipped_build_files.txt +++ b/test/common/skipped_build_files.txt @@ -24,6 +24,7 @@ lib/idxd/idxd_kernel # These files all represent c files that are only compiled by direct inclusion in other files. test/common/lib/test_env +test/common/lib/test_iobuf test/common/lib/test_sock test/common/lib/ut_multithread test/common/lib/test_rdma diff --git a/test/unit/lib/accel/accel.c/accel_ut.c b/test/unit/lib/accel/accel.c/accel_ut.c index d56901bdd..c77d8e2ec 100644 --- a/test/unit/lib/accel/accel.c/accel_ut.c +++ b/test/unit/lib/accel/accel.c/accel_ut.c @@ -9,6 +9,7 @@ #include "spdk_internal/accel_module.h" #include "thread/thread_internal.h" #include "common/lib/ut_multithread.c" +#include "common/lib/test_iobuf.c" #include "accel/accel.c" #include "accel/accel_sw.c" #include "unit/lib/json_mock.c" @@ -1929,6 +1930,16 @@ test_sequence_accel_buffers(void) spdk_iobuf_buffer_stailq_t small_cache; uint32_t small_cache_count; int i, rc, completed; + struct spdk_iobuf_opts opts_iobuf = {}; + + /* Set up the iobuf to always use the "small" pool */ + opts_iobuf.large_bufsize = 0x20000; + opts_iobuf.large_pool_count = 0; + opts_iobuf.small_bufsize = 0x10000; + opts_iobuf.small_pool_count = 32; + + rc = spdk_iobuf_set_opts(&opts_iobuf); + CU_ASSERT(rc == 0); ioch = spdk_accel_get_io_channel(); SPDK_CU_ASSERT_FATAL(ioch != NULL); @@ -2223,7 +2234,8 @@ test_sequence_accel_buffers(void) STAILQ_INIT(&small_cache); STAILQ_SWAP(&accel_ch->iobuf.small.cache, &small_cache, spdk_iobuf_buffer); accel_ch->iobuf.small.cache_count = 0; - MOCK_SET(spdk_mempool_get, NULL); + accel_ch->iobuf.small.cache_size = 0; + g_iobuf.small_pool_count = 0; /* First allocate a single buffer used by two operations */ memset(srcbuf, 0x0, 4096); @@ -2258,10 +2270,10 @@ test_sequence_accel_buffers(void) CU_ASSERT(!ut_seq.complete); /* Get a buffer and return it to the pool to trigger the sequence to finish */ - MOCK_CLEAR(spdk_mempool_get); + g_iobuf.small_pool_count = 1; iobuf_buf = spdk_iobuf_get(&accel_ch->iobuf, 4096, NULL, NULL); CU_ASSERT_PTR_NOT_NULL(iobuf_buf); - MOCK_SET(spdk_mempool_get, NULL); + CU_ASSERT(g_iobuf.small_pool_count == 0); spdk_iobuf_put(&accel_ch->iobuf, iobuf_buf, 4096); poll_threads(); @@ -2280,6 +2292,7 @@ test_sequence_accel_buffers(void) small_cache_count++; } accel_ch->iobuf.small.cache_count = 0; + g_iobuf.small_pool_count = 0; /* Check a bit more complex scenario, with two buffers in the sequence */ memset(srcbuf, 0x0, 4096); @@ -2327,20 +2340,20 @@ test_sequence_accel_buffers(void) CU_ASSERT_EQUAL(completed, 0); CU_ASSERT(!ut_seq.complete); - MOCK_CLEAR(spdk_mempool_get); + g_iobuf.small_pool_count = 1; iobuf_buf = spdk_iobuf_get(&accel_ch->iobuf, 4096, NULL, NULL); CU_ASSERT_PTR_NOT_NULL(iobuf_buf); - MOCK_SET(spdk_mempool_get, NULL); + g_iobuf.small_pool_count = 0; spdk_iobuf_put(&accel_ch->iobuf, iobuf_buf, 4096); /* One buffer is not enough to finish the whole sequence */ poll_threads(); CU_ASSERT(!ut_seq.complete); - MOCK_CLEAR(spdk_mempool_get); + g_iobuf.small_pool_count = 1; iobuf_buf = spdk_iobuf_get(&accel_ch->iobuf, 4096, NULL, NULL); CU_ASSERT_PTR_NOT_NULL(iobuf_buf); - MOCK_SET(spdk_mempool_get, NULL); + g_iobuf.small_pool_count = 0; spdk_iobuf_put(&accel_ch->iobuf, iobuf_buf, 4096); poll_threads(); @@ -2361,7 +2374,7 @@ test_sequence_accel_buffers(void) } accel_ch->iobuf.small.cache_count = 0; - MOCK_CLEAR(spdk_mempool_get); + g_iobuf.small_pool_count = 32; STAILQ_SWAP(&accel_ch->iobuf.small.cache, &small_cache, spdk_iobuf_buffer); accel_ch->iobuf.small.cache_count = small_cache_count; @@ -2574,7 +2587,7 @@ test_sequence_memory_domain(void) STAILQ_INIT(&small_cache); STAILQ_SWAP(&accel_ch->iobuf.small.cache, &small_cache, spdk_iobuf_buffer); accel_ch->iobuf.small.cache_count = 0; - MOCK_SET(spdk_mempool_get, NULL); + g_iobuf.small_pool_count = 0; src_iovs[0].iov_base = (void *)0xdeadbeef; src_iovs[0].iov_len = sizeof(srcbuf); @@ -2598,20 +2611,20 @@ test_sequence_memory_domain(void) /* Get a buffer and return it to the pool to trigger the sequence to resume. It shouldn't * be able to complete, as it needs two buffers */ - MOCK_CLEAR(spdk_mempool_get); + g_iobuf.small_pool_count = 1; iobuf_buf = spdk_iobuf_get(&accel_ch->iobuf, sizeof(dstbuf), NULL, NULL); CU_ASSERT_PTR_NOT_NULL(iobuf_buf); - MOCK_SET(spdk_mempool_get, NULL); + g_iobuf.small_pool_count = 0; spdk_iobuf_put(&accel_ch->iobuf, iobuf_buf, sizeof(dstbuf)); CU_ASSERT_EQUAL(completed, 0); CU_ASSERT(!ut_seq.complete); /* Return another buffer, this time the sequence should finish */ - MOCK_CLEAR(spdk_mempool_get); + g_iobuf.small_pool_count = 1; iobuf_buf = spdk_iobuf_get(&accel_ch->iobuf, sizeof(dstbuf), NULL, NULL); CU_ASSERT_PTR_NOT_NULL(iobuf_buf); - MOCK_SET(spdk_mempool_get, NULL); + g_iobuf.small_pool_count = 0; spdk_iobuf_put(&accel_ch->iobuf, iobuf_buf, sizeof(dstbuf)); poll_threads(); @@ -2629,7 +2642,7 @@ test_sequence_memory_domain(void) } accel_ch->iobuf.small.cache_count = 0; - MOCK_CLEAR(spdk_mempool_get); + g_iobuf.small_pool_count = 32; STAILQ_SWAP(&accel_ch->iobuf.small.cache, &small_cache, spdk_iobuf_buffer); accel_ch->iobuf.small.cache_count = small_cache_count;