1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2023 Intel Corporation. 3 * All rights reserved. 4 */ 5 #include "spdk/stdinc.h" 6 7 #include "spdk_internal/mock.h" 8 9 #include "spdk/thread.h" 10 11 DEFINE_STUB(spdk_iobuf_initialize, int, (void), 0); 12 DEFINE_STUB(spdk_iobuf_register_module, int, (const char *name), 0); 13 DEFINE_STUB(spdk_iobuf_unregister_module, int, (const char *name), 0); 14 DEFINE_STUB_V(spdk_iobuf_channel_fini, (struct spdk_iobuf_channel *ch)); 15 DEFINE_STUB(spdk_iobuf_for_each_entry, int, (struct spdk_iobuf_channel *ch, 16 struct spdk_iobuf_pool *pool, spdk_iobuf_for_each_entry_fn cb_fn, void *cb_ctx), 0); 17 DEFINE_STUB_V(spdk_iobuf_entry_abort, (struct spdk_iobuf_channel *ch, 18 struct spdk_iobuf_entry *entry, uint64_t len)); 19 20 struct ut_iobuf { 21 struct spdk_iobuf_opts opts; 22 uint32_t small_pool_count; 23 uint32_t large_pool_count; 24 }; 25 26 static struct ut_iobuf g_iobuf = { 27 .small_pool_count = 32, 28 .large_pool_count = 32 29 }; 30 static spdk_iobuf_entry_stailq_t g_iobuf_entries; 31 32 int 33 spdk_iobuf_set_opts(const struct spdk_iobuf_opts *opts) 34 { 35 g_iobuf.opts = *opts; 36 g_iobuf.small_pool_count = opts->small_pool_count; 37 g_iobuf.large_pool_count = opts->large_pool_count; 38 return 0; 39 } 40 41 void 42 spdk_iobuf_get_opts(struct spdk_iobuf_opts *opts) 43 { 44 *opts = g_iobuf.opts; 45 } 46 47 void 48 spdk_iobuf_finish(spdk_iobuf_finish_cb cb_fn, void *cb_arg) 49 { 50 cb_fn(cb_arg); 51 } 52 53 int 54 spdk_iobuf_channel_init(struct spdk_iobuf_channel *ch, const char *name, 55 uint32_t small_cache_size, uint32_t large_cache_size) 56 { 57 STAILQ_INIT(&g_iobuf_entries); 58 ch->small.cache_count = small_cache_size; 59 ch->small.cache_size = small_cache_size; 60 ch->large.cache_count = large_cache_size; 61 ch->large.cache_size = large_cache_size; 62 return 0; 63 } 64 65 DEFINE_RETURN_MOCK(spdk_iobuf_get, void *); 66 void * 67 spdk_iobuf_get(struct spdk_iobuf_channel *ch, uint64_t len, 68 struct spdk_iobuf_entry *entry, spdk_iobuf_get_cb cb_fn) 69 { 70 struct spdk_iobuf_pool *pool; 71 uint32_t *count; 72 void *buf; 73 74 HANDLE_RETURN_MOCK(spdk_iobuf_get); 75 76 if (len > g_iobuf.opts.small_bufsize) { 77 pool = &ch->large; 78 count = &g_iobuf.large_pool_count; 79 } else { 80 pool = &ch->small; 81 count = &g_iobuf.small_pool_count; 82 } 83 84 if (pool->cache_count > 0) { 85 buf = calloc(1, len); 86 CU_ASSERT(buf != NULL); 87 pool->cache_count--; 88 return buf; 89 } 90 91 if (*count == 0) { 92 if (entry) { 93 entry->cb_fn = cb_fn; 94 STAILQ_INSERT_TAIL(&g_iobuf_entries, entry, stailq); 95 } 96 97 return NULL; 98 } 99 100 buf = calloc(1, len); 101 CU_ASSERT(buf != NULL); 102 (*count)--; 103 return buf; 104 } 105 106 void 107 spdk_iobuf_put(struct spdk_iobuf_channel *ch, void *buf, uint64_t len) 108 { 109 struct spdk_iobuf_entry *entry; 110 struct spdk_iobuf_pool *pool; 111 uint32_t *count; 112 113 if (len > g_iobuf.opts.small_bufsize) { 114 pool = &ch->large; 115 count = &g_iobuf.large_pool_count; 116 } else { 117 pool = &ch->small; 118 count = &g_iobuf.small_pool_count; 119 } 120 121 if (!STAILQ_EMPTY(&g_iobuf_entries)) { 122 entry = STAILQ_FIRST(&g_iobuf_entries); 123 STAILQ_REMOVE_HEAD(&g_iobuf_entries, stailq); 124 entry->cb_fn(entry, buf); 125 return; 126 } 127 128 if (pool->cache_count < pool->cache_size) { 129 pool->cache_count++; 130 } else { 131 (*count)++; 132 } 133 134 free(buf); 135 } 136