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