]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/test/lib/blobfs/cache_ut/cache_ut.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / spdk / test / lib / blobfs / cache_ut / cache_ut.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdint.h>
39 #include <string.h>
40 #include <stdbool.h>
41
42 #include "spdk/blobfs.h"
43 #include "spdk/env.h"
44 #include "spdk/log.h"
45 #include "spdk/io_channel.h"
46 #include "spdk/barrier.h"
47
48 #include "spdk_cunit.h"
49 #include "lib/blob/bs_dev_common.c"
50 #include "lib/test_env.c"
51 #include "blobfs.c"
52 #include "tree.c"
53
54 struct spdk_filesystem *g_fs;
55 struct spdk_file *g_file;
56 int g_fserrno;
57
58 struct spdk_bs_dev g_dev;
59
60 struct ut_request {
61 fs_request_fn fn;
62 void *arg;
63 volatile int done;
64 int from_ut;
65 };
66
67 volatile struct ut_request *g_req = NULL;
68 volatile int g_phase = 0;
69
70 static void
71 send_request(fs_request_fn fn, void *arg)
72 {
73 struct ut_request *req;
74
75 req = calloc(1, sizeof(*req));
76 assert(req != NULL);
77 req->fn = fn;
78 req->arg = arg;
79 req->done = 0;
80 req->from_ut = 0;
81 g_req = req;
82 spdk_mb();
83 g_phase = !g_phase;
84 spdk_mb();
85 }
86
87 static void
88 ut_send_request(fs_request_fn fn, void *arg)
89 {
90 struct ut_request req;
91
92 req.fn = fn;
93 req.arg = arg;
94 req.done = 0;
95 req.from_ut = 1;
96 g_req = &req;
97 spdk_mb();
98 g_phase = !g_phase;
99 spdk_mb();
100 while (req.done == 0)
101 ;
102 }
103
104 static void
105 fs_op_complete(void *ctx, int fserrno)
106 {
107 g_fserrno = fserrno;
108 }
109
110 static void
111 fs_op_with_handle_complete(void *ctx, struct spdk_filesystem *fs, int fserrno)
112 {
113 g_fs = fs;
114 g_fserrno = fserrno;
115 }
116
117 static void
118 _fs_init(void *arg)
119 {
120 g_fs = NULL;
121 g_fserrno = -1;
122 spdk_fs_init(&g_dev, send_request, fs_op_with_handle_complete, NULL);
123 SPDK_CU_ASSERT_FATAL(g_fs != NULL);
124 CU_ASSERT(g_fserrno == 0);
125 }
126
127 static void
128 _fs_unload(void *arg)
129 {
130 g_fserrno = -1;
131 spdk_fs_unload(g_fs, fs_op_complete, NULL);
132 CU_ASSERT(g_fserrno == 0);
133 g_fs = NULL;
134 }
135
136 static void
137 cache_write(void)
138 {
139 uint64_t length;
140 int rc;
141 char buf[100];
142 struct spdk_io_channel *channel;
143
144 ut_send_request(_fs_init, NULL);
145
146 spdk_allocate_thread();
147 channel = spdk_fs_alloc_io_channel_sync(g_fs, SPDK_IO_PRIORITY_DEFAULT);
148
149 rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
150 CU_ASSERT(rc == 0);
151 SPDK_CU_ASSERT_FATAL(g_file != NULL);
152
153 length = (4 * 1024 * 1024);
154 spdk_file_truncate(g_file, channel, length);
155
156 spdk_file_write(g_file, channel, buf, 0, sizeof(buf));
157
158 CU_ASSERT(spdk_file_get_length(g_file) == length);
159
160 spdk_file_truncate(g_file, channel, sizeof(buf));
161
162 spdk_file_close(g_file, channel);
163 rc = spdk_fs_delete_file(g_fs, channel, "testfile");
164 CU_ASSERT(rc == 0);
165
166 rc = spdk_fs_delete_file(g_fs, channel, "testfile");
167 CU_ASSERT(rc == -ENOENT);
168
169 spdk_fs_free_io_channel(channel);
170 spdk_free_thread();
171
172 ut_send_request(_fs_unload, NULL);
173 }
174
175 static void
176 cache_append_no_cache(void)
177 {
178 int rc;
179 char buf[100];
180 struct spdk_io_channel *channel;
181
182 ut_send_request(_fs_init, NULL);
183
184 spdk_allocate_thread();
185 channel = spdk_fs_alloc_io_channel_sync(g_fs, SPDK_IO_PRIORITY_DEFAULT);
186
187 rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
188 CU_ASSERT(rc == 0);
189 SPDK_CU_ASSERT_FATAL(g_file != NULL);
190
191 spdk_file_write(g_file, channel, buf, 0 * sizeof(buf), sizeof(buf));
192 CU_ASSERT(spdk_file_get_length(g_file) == 1 * sizeof(buf));
193 spdk_file_write(g_file, channel, buf, 1 * sizeof(buf), sizeof(buf));
194 CU_ASSERT(spdk_file_get_length(g_file) == 2 * sizeof(buf));
195 spdk_file_sync(g_file, channel);
196 cache_free_buffers(g_file);
197 spdk_file_write(g_file, channel, buf, 2 * sizeof(buf), sizeof(buf));
198 CU_ASSERT(spdk_file_get_length(g_file) == 3 * sizeof(buf));
199 spdk_file_write(g_file, channel, buf, 3 * sizeof(buf), sizeof(buf));
200 CU_ASSERT(spdk_file_get_length(g_file) == 4 * sizeof(buf));
201 spdk_file_write(g_file, channel, buf, 4 * sizeof(buf), sizeof(buf));
202 CU_ASSERT(spdk_file_get_length(g_file) == 5 * sizeof(buf));
203
204 spdk_file_close(g_file, channel);
205 rc = spdk_fs_delete_file(g_fs, channel, "testfile");
206 CU_ASSERT(rc == 0);
207
208 spdk_fs_free_io_channel(channel);
209 spdk_free_thread();
210
211 ut_send_request(_fs_unload, NULL);
212 }
213
214 static void
215 terminate_spdk_thread(void *arg)
216 {
217 spdk_free_thread();
218 pthread_exit(NULL);
219 }
220
221 static void *
222 spdk_thread(void *arg)
223 {
224 struct ut_request *req;
225 int phase = 0;
226 spdk_allocate_thread();
227
228 while (1) {
229 spdk_mb();
230 if (phase != g_phase) {
231 req = (void *)g_req;
232 req->fn(req->arg);
233 req->done = 1;
234 spdk_mb();
235 if (!req->from_ut) {
236 free(req);
237 }
238 phase = !phase;
239 }
240 }
241
242 return NULL;
243 }
244
245 int main(int argc, char **argv)
246 {
247 CU_pSuite suite = NULL;
248 pthread_t spdk_tid;
249 unsigned int num_failures;
250
251 if (CU_initialize_registry() != CUE_SUCCESS) {
252 return CU_get_error();
253 }
254
255 suite = CU_add_suite("cache_ut", NULL, NULL);
256 if (suite == NULL) {
257 CU_cleanup_registry();
258 return CU_get_error();
259 }
260
261 if (
262 CU_add_test(suite, "write", cache_write) == NULL ||
263 CU_add_test(suite, "append_no_cache", cache_append_no_cache) == NULL
264 ) {
265 CU_cleanup_registry();
266 return CU_get_error();
267 }
268
269 init_dev(&g_dev);
270 pthread_create(&spdk_tid, NULL, spdk_thread, NULL);
271 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
272 CU_basic_set_mode(CU_BRM_VERBOSE);
273 CU_basic_run_tests();
274 num_failures = CU_get_number_of_failures();
275 CU_cleanup_registry();
276 free(g_dev_buffer);
277 send_request(terminate_spdk_thread, NULL);
278 pthread_join(spdk_tid, NULL);
279 return num_failures;
280 }