xref: /spdk/test/common/lib/test_iobuf.c (revision 83ba9086796471697a4975a58f60e2392bccd08c)
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