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 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, size_t opts_size) 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 struct spdk_iobuf_node_cache *cache; 58 59 cache = &ch->cache[0]; 60 61 STAILQ_INIT(&g_iobuf_entries); 62 cache->small.cache_count = small_cache_size; 63 cache->small.cache_size = small_cache_size; 64 cache->large.cache_count = large_cache_size; 65 cache->large.cache_size = large_cache_size; 66 return 0; 67 } 68 69 DEFINE_RETURN_MOCK(spdk_iobuf_get, void *); 70 void * 71 spdk_iobuf_get(struct spdk_iobuf_channel *ch, uint64_t len, 72 struct spdk_iobuf_entry *entry, spdk_iobuf_get_cb cb_fn) 73 { 74 struct spdk_iobuf_node_cache *cache; 75 struct spdk_iobuf_pool_cache *pool; 76 uint32_t *count; 77 void *buf; 78 79 HANDLE_RETURN_MOCK(spdk_iobuf_get); 80 81 cache = &ch->cache[0]; 82 83 if (len > g_iobuf.opts.small_bufsize) { 84 pool = &cache->large; 85 count = &g_iobuf.large_pool_count; 86 } else { 87 pool = &cache->small; 88 count = &g_iobuf.small_pool_count; 89 } 90 91 if (pool->cache_count > 0) { 92 buf = calloc(1, len); 93 CU_ASSERT(buf != NULL); 94 pool->cache_count--; 95 return buf; 96 } 97 98 if (*count == 0) { 99 if (entry) { 100 entry->cb_fn = cb_fn; 101 STAILQ_INSERT_TAIL(&g_iobuf_entries, entry, stailq); 102 } 103 104 return NULL; 105 } 106 107 buf = calloc(1, len); 108 CU_ASSERT(buf != NULL); 109 (*count)--; 110 return buf; 111 } 112 113 void 114 spdk_iobuf_put(struct spdk_iobuf_channel *ch, void *buf, uint64_t len) 115 { 116 struct spdk_iobuf_entry *entry; 117 struct spdk_iobuf_node_cache *cache; 118 struct spdk_iobuf_pool_cache *pool; 119 uint32_t *count; 120 121 cache = &ch->cache[0]; 122 123 if (len > g_iobuf.opts.small_bufsize) { 124 pool = &cache->large; 125 count = &g_iobuf.large_pool_count; 126 } else { 127 pool = &cache->small; 128 count = &g_iobuf.small_pool_count; 129 } 130 131 if (!STAILQ_EMPTY(&g_iobuf_entries)) { 132 entry = STAILQ_FIRST(&g_iobuf_entries); 133 STAILQ_REMOVE_HEAD(&g_iobuf_entries, stailq); 134 entry->cb_fn(entry, buf); 135 return; 136 } 137 138 if (pool->cache_count < pool->cache_size) { 139 pool->cache_count++; 140 } else { 141 (*count)++; 142 } 143 144 free(buf); 145 } 146