Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk/blobfs.h"
9 : : #include "spdk/env.h"
10 : : #include "spdk/log.h"
11 : : #include "spdk/barrier.h"
12 : : #include "thread/thread_internal.h"
13 : :
14 : : #include "spdk_internal/cunit.h"
15 : : #include "unit/lib/blob/bs_dev_common.c"
16 : : #include "common/lib/test_env.c"
17 : : #include "blobfs/blobfs.c"
18 : : #include "blobfs/tree.c"
19 : :
20 : : struct spdk_filesystem *g_fs;
21 : : struct spdk_file *g_file;
22 : : int g_fserrno;
23 : : struct spdk_thread *g_dispatch_thread = NULL;
24 : :
25 : : struct ut_request {
26 : : fs_request_fn fn;
27 : : void *arg;
28 : : volatile int done;
29 : : };
30 : :
31 [ # # ]: 0 : DEFINE_STUB(spdk_memory_domain_memzero, int, (struct spdk_memory_domain *src_domain,
32 : : void *src_domain_ctx, struct iovec *iov, uint32_t iovcnt, void (*cpl_cb)(void *, int),
33 : : void *cpl_cb_arg), 0);
34 [ # # ]: 0 : DEFINE_STUB(spdk_mempool_lookup, struct spdk_mempool *, (const char *name), NULL);
35 : :
36 : : static void
37 : 318 : send_request(fs_request_fn fn, void *arg)
38 : : {
39 : 318 : spdk_thread_send_msg(g_dispatch_thread, (spdk_msg_fn)fn, arg);
40 : 318 : }
41 : :
42 : : static void
43 : 174 : ut_call_fn(void *arg)
44 : : {
45 : 174 : struct ut_request *req = arg;
46 : :
47 : 174 : req->fn(req->arg);
48 : 174 : req->done = 1;
49 : 174 : }
50 : :
51 : : static void
52 : 174 : ut_send_request(fs_request_fn fn, void *arg)
53 : : {
54 : 145 : struct ut_request req;
55 : :
56 : 174 : req.fn = fn;
57 : 174 : req.arg = arg;
58 : 174 : req.done = 0;
59 : :
60 : 174 : spdk_thread_send_msg(g_dispatch_thread, ut_call_fn, &req);
61 : :
62 : : /* Wait for this to finish */
63 [ + + ]: 127196721 : while (req.done == 0) { }
64 : 174 : }
65 : :
66 : : static void
67 : 66 : fs_op_complete(void *ctx, int fserrno)
68 : : {
69 : 66 : g_fserrno = fserrno;
70 : 66 : }
71 : :
72 : : static void
73 : 66 : fs_op_with_handle_complete(void *ctx, struct spdk_filesystem *fs, int fserrno)
74 : : {
75 : 66 : g_fs = fs;
76 : 66 : g_fserrno = fserrno;
77 : 66 : }
78 : :
79 : : static void
80 : 210 : fs_thread_poll(void)
81 : : {
82 : : struct spdk_thread *thread;
83 : :
84 : 210 : thread = spdk_get_thread();
85 [ + + ]: 852 : while (spdk_thread_poll(thread, 0, 0) > 0) {}
86 [ + + ]: 372 : while (spdk_thread_poll(g_cache_pool_thread, 0, 0) > 0) {}
87 : 210 : }
88 : :
89 : : static void
90 : 54 : _fs_init(void *arg)
91 : : {
92 : : struct spdk_bs_dev *dev;
93 : :
94 : 54 : g_fs = NULL;
95 : 54 : g_fserrno = -1;
96 : 54 : dev = init_dev();
97 : 54 : spdk_fs_init(dev, NULL, send_request, fs_op_with_handle_complete, NULL);
98 : :
99 : 54 : fs_thread_poll();
100 : :
101 [ - + ]: 54 : SPDK_CU_ASSERT_FATAL(g_fs != NULL);
102 [ - + ]: 54 : SPDK_CU_ASSERT_FATAL(g_fs->bdev == dev);
103 : 54 : CU_ASSERT(g_fserrno == 0);
104 : 54 : }
105 : :
106 : : static void
107 : 12 : _fs_load(void *arg)
108 : : {
109 : : struct spdk_bs_dev *dev;
110 : :
111 : 12 : g_fs = NULL;
112 : 12 : g_fserrno = -1;
113 : 12 : dev = init_dev();
114 : 12 : spdk_fs_load(dev, send_request, fs_op_with_handle_complete, NULL);
115 : :
116 : 12 : fs_thread_poll();
117 : :
118 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(g_fs != NULL);
119 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(g_fs->bdev == dev);
120 : 12 : CU_ASSERT(g_fserrno == 0);
121 : 12 : }
122 : :
123 : : static void
124 : 66 : _fs_unload(void *arg)
125 : : {
126 : 66 : g_fserrno = -1;
127 : 66 : spdk_fs_unload(g_fs, fs_op_complete, NULL);
128 : :
129 : 66 : fs_thread_poll();
130 : :
131 : 66 : CU_ASSERT(g_fserrno == 0);
132 : 66 : g_fs = NULL;
133 : 66 : }
134 : :
135 : : static void
136 : 36 : _nop(void *arg)
137 : : {
138 : 36 : }
139 : :
140 : : static void
141 : 6 : cache_read_after_write(void)
142 : : {
143 : : uint64_t length;
144 : : int rc;
145 : 5 : char w_buf[100], r_buf[100];
146 : : struct spdk_fs_thread_ctx *channel;
147 : 6 : struct spdk_file_stat stat = {0};
148 : :
149 : 6 : ut_send_request(_fs_init, NULL);
150 : :
151 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
152 : :
153 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
154 : 6 : CU_ASSERT(rc == 0);
155 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
156 : :
157 : 6 : length = (4 * 1024 * 1024);
158 : 6 : rc = spdk_file_truncate(g_file, channel, length);
159 : 6 : CU_ASSERT(rc == 0);
160 : :
161 : 6 : memset(w_buf, 0x5a, sizeof(w_buf));
162 : 6 : spdk_file_write(g_file, channel, w_buf, 0, sizeof(w_buf));
163 : :
164 : 6 : CU_ASSERT(spdk_file_get_length(g_file) == length);
165 : :
166 : 6 : rc = spdk_file_truncate(g_file, channel, sizeof(w_buf));
167 : 6 : CU_ASSERT(rc == 0);
168 : :
169 : 6 : spdk_file_close(g_file, channel);
170 : :
171 : 6 : fs_thread_poll();
172 : :
173 : 6 : rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
174 : 6 : CU_ASSERT(rc == 0);
175 : 6 : CU_ASSERT(sizeof(w_buf) == stat.size);
176 : :
177 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &g_file);
178 : 6 : CU_ASSERT(rc == 0);
179 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
180 : :
181 : 6 : memset(r_buf, 0, sizeof(r_buf));
182 : 6 : spdk_file_read(g_file, channel, r_buf, 0, sizeof(r_buf));
183 : 6 : CU_ASSERT(memcmp(w_buf, r_buf, sizeof(r_buf)) == 0);
184 : :
185 : 6 : spdk_file_close(g_file, channel);
186 : :
187 : 6 : fs_thread_poll();
188 : :
189 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
190 : 6 : CU_ASSERT(rc == 0);
191 : :
192 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
193 : 6 : CU_ASSERT(rc == -ENOENT);
194 : :
195 : 6 : spdk_fs_free_thread_ctx(channel);
196 : :
197 : 6 : ut_send_request(_fs_unload, NULL);
198 : 6 : }
199 : :
200 : : static void
201 : 6 : file_length(void)
202 : : {
203 : : int rc;
204 : : char *buf;
205 : : uint64_t buf_length;
206 : : volatile uint64_t *length_flushed;
207 : : struct spdk_fs_thread_ctx *channel;
208 : 6 : struct spdk_file_stat stat = {0};
209 : :
210 : 6 : ut_send_request(_fs_init, NULL);
211 : :
212 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
213 : :
214 : 6 : g_file = NULL;
215 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
216 : 6 : CU_ASSERT(rc == 0);
217 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
218 : :
219 : : /* Write one CACHE_BUFFER. Filling at least one cache buffer triggers
220 : : * a flush to disk.
221 : : */
222 : 6 : buf_length = CACHE_BUFFER_SIZE;
223 : 6 : buf = calloc(1, buf_length);
224 : 6 : spdk_file_write(g_file, channel, buf, 0, buf_length);
225 : 6 : free(buf);
226 : :
227 : : /* Spin until all of the data has been flushed to the SSD. There's been no
228 : : * sync operation yet, so the xattr on the file is still 0.
229 : : *
230 : : * length_flushed: This variable is modified by a different thread in this unit
231 : : * test. So we need to dereference it as a volatile to ensure the value is always
232 : : * re-read.
233 : : */
234 : 6 : length_flushed = &g_file->length_flushed;
235 [ + + ]: 50762 : while (*length_flushed != buf_length) {}
236 : :
237 : : /* Close the file. This causes an implicit sync which should write the
238 : : * length_flushed value as the "length" xattr on the file.
239 : : */
240 : 6 : spdk_file_close(g_file, channel);
241 : :
242 : 6 : fs_thread_poll();
243 : :
244 : 6 : rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
245 : 6 : CU_ASSERT(rc == 0);
246 : 6 : CU_ASSERT(buf_length == stat.size);
247 : :
248 : 6 : spdk_fs_free_thread_ctx(channel);
249 : :
250 : : /* Unload and reload the filesystem. The file length will be
251 : : * read during load from the length xattr. We want to make sure
252 : : * it matches what was written when the file was originally
253 : : * written and closed.
254 : : */
255 : 6 : ut_send_request(_fs_unload, NULL);
256 : :
257 : 6 : ut_send_request(_fs_load, NULL);
258 : :
259 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
260 : :
261 : 6 : rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
262 : 6 : CU_ASSERT(rc == 0);
263 : 6 : CU_ASSERT(buf_length == stat.size);
264 : :
265 : 6 : g_file = NULL;
266 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &g_file);
267 : 6 : CU_ASSERT(rc == 0);
268 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
269 : :
270 : 6 : spdk_file_close(g_file, channel);
271 : :
272 : 6 : fs_thread_poll();
273 : :
274 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
275 : 6 : CU_ASSERT(rc == 0);
276 : :
277 : 6 : spdk_fs_free_thread_ctx(channel);
278 : :
279 : 6 : ut_send_request(_fs_unload, NULL);
280 : 6 : }
281 : :
282 : : static void
283 : 6 : append_write_to_extend_blob(void)
284 : : {
285 : : uint64_t blob_size, buf_length;
286 : 5 : char *buf, append_buf[64];
287 : : int rc;
288 : : struct spdk_fs_thread_ctx *channel;
289 : :
290 : 6 : ut_send_request(_fs_init, NULL);
291 : :
292 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
293 : :
294 : : /* create a file and write the file with blob_size - 1 data length */
295 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
296 : 6 : CU_ASSERT(rc == 0);
297 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
298 : :
299 : 6 : blob_size = __file_get_blob_size(g_file);
300 : :
301 : 6 : buf_length = blob_size - 1;
302 : 6 : buf = calloc(1, buf_length);
303 : 6 : rc = spdk_file_write(g_file, channel, buf, 0, buf_length);
304 : 6 : CU_ASSERT(rc == 0);
305 : 6 : free(buf);
306 : :
307 : 6 : spdk_file_close(g_file, channel);
308 : 6 : fs_thread_poll();
309 : 6 : spdk_fs_free_thread_ctx(channel);
310 : 6 : ut_send_request(_fs_unload, NULL);
311 : :
312 : : /* load existing file and write extra 2 bytes to cross blob boundary */
313 : 6 : ut_send_request(_fs_load, NULL);
314 : :
315 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
316 : 6 : g_file = NULL;
317 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &g_file);
318 : 6 : CU_ASSERT(rc == 0);
319 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
320 : :
321 : 6 : CU_ASSERT(g_file->length == buf_length);
322 : 6 : CU_ASSERT(g_file->last == NULL);
323 : 6 : CU_ASSERT(g_file->append_pos == buf_length);
324 : :
325 : 6 : rc = spdk_file_write(g_file, channel, append_buf, buf_length, 2);
326 : 6 : CU_ASSERT(rc == 0);
327 : 6 : CU_ASSERT(2 * blob_size == __file_get_blob_size(g_file));
328 : 6 : spdk_file_close(g_file, channel);
329 : 6 : fs_thread_poll();
330 : 6 : CU_ASSERT(g_file->length == buf_length + 2);
331 : :
332 : 6 : spdk_fs_free_thread_ctx(channel);
333 : 6 : ut_send_request(_fs_unload, NULL);
334 : 6 : }
335 : :
336 : : static void
337 : 6 : partial_buffer(void)
338 : : {
339 : : int rc;
340 : : char *buf;
341 : : uint64_t buf_length;
342 : : struct spdk_fs_thread_ctx *channel;
343 : 6 : struct spdk_file_stat stat = {0};
344 : :
345 : 6 : ut_send_request(_fs_init, NULL);
346 : :
347 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
348 : :
349 : 6 : g_file = NULL;
350 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
351 : 6 : CU_ASSERT(rc == 0);
352 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
353 : :
354 : : /* Write one CACHE_BUFFER plus one byte. Filling at least one cache buffer triggers
355 : : * a flush to disk. We want to make sure the extra byte is not implicitly flushed.
356 : : * It should only get flushed once we sync or close the file.
357 : : */
358 : 6 : buf_length = CACHE_BUFFER_SIZE + 1;
359 : 6 : buf = calloc(1, buf_length);
360 : 6 : spdk_file_write(g_file, channel, buf, 0, buf_length);
361 : 6 : free(buf);
362 : :
363 : : /* Send some nop messages to the dispatch thread. This will ensure any of the
364 : : * pending write operations are completed. A well-functioning blobfs should only
365 : : * issue one write for the filled CACHE_BUFFER - a buggy one might try to write
366 : : * the extra byte. So do a bunch of _nops to make sure all of them (even the buggy
367 : : * ones) get a chance to run. Note that we can't just send a message to the
368 : : * dispatch thread to call spdk_thread_poll() because the messages are themselves
369 : : * run in the context of spdk_thread_poll().
370 : : */
371 : 6 : ut_send_request(_nop, NULL);
372 : 6 : ut_send_request(_nop, NULL);
373 : 6 : ut_send_request(_nop, NULL);
374 : 6 : ut_send_request(_nop, NULL);
375 : 6 : ut_send_request(_nop, NULL);
376 : 6 : ut_send_request(_nop, NULL);
377 : :
378 : 6 : CU_ASSERT(g_file->length_flushed == CACHE_BUFFER_SIZE);
379 : :
380 : : /* Close the file. This causes an implicit sync which should write the
381 : : * length_flushed value as the "length" xattr on the file.
382 : : */
383 : 6 : spdk_file_close(g_file, channel);
384 : :
385 : 6 : fs_thread_poll();
386 : :
387 : 6 : rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
388 : 6 : CU_ASSERT(rc == 0);
389 : 6 : CU_ASSERT(buf_length == stat.size);
390 : :
391 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
392 : 6 : CU_ASSERT(rc == 0);
393 : :
394 : 6 : spdk_fs_free_thread_ctx(channel);
395 : :
396 : 6 : ut_send_request(_fs_unload, NULL);
397 : 6 : }
398 : :
399 : : static void
400 : 6 : cache_write_null_buffer(void)
401 : : {
402 : : uint64_t length;
403 : : int rc;
404 : : struct spdk_fs_thread_ctx *channel;
405 : : struct spdk_thread *thread;
406 : :
407 : 6 : ut_send_request(_fs_init, NULL);
408 : :
409 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
410 : :
411 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
412 : 6 : CU_ASSERT(rc == 0);
413 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
414 : :
415 : 6 : length = 0;
416 : 6 : rc = spdk_file_truncate(g_file, channel, length);
417 : 6 : CU_ASSERT(rc == 0);
418 : :
419 : 6 : rc = spdk_file_write(g_file, channel, NULL, 0, 0);
420 : 6 : CU_ASSERT(rc == 0);
421 : :
422 : 6 : spdk_file_close(g_file, channel);
423 : :
424 : 6 : fs_thread_poll();
425 : :
426 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
427 : 6 : CU_ASSERT(rc == 0);
428 : :
429 : 6 : spdk_fs_free_thread_ctx(channel);
430 : :
431 : 6 : thread = spdk_get_thread();
432 [ - + ]: 6 : while (spdk_thread_poll(thread, 0, 0) > 0) {}
433 : :
434 : 6 : ut_send_request(_fs_unload, NULL);
435 : 6 : }
436 : :
437 : : static void
438 : 6 : fs_create_sync(void)
439 : : {
440 : : int rc;
441 : : struct spdk_fs_thread_ctx *channel;
442 : :
443 : 6 : ut_send_request(_fs_init, NULL);
444 : :
445 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
446 : 6 : CU_ASSERT(channel != NULL);
447 : :
448 : 6 : rc = spdk_fs_create_file(g_fs, channel, "testfile");
449 : 6 : CU_ASSERT(rc == 0);
450 : :
451 : : /* Create should fail, because the file already exists. */
452 : 6 : rc = spdk_fs_create_file(g_fs, channel, "testfile");
453 : 6 : CU_ASSERT(rc != 0);
454 : :
455 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
456 : 6 : CU_ASSERT(rc == 0);
457 : :
458 : 6 : spdk_fs_free_thread_ctx(channel);
459 : :
460 : 6 : fs_thread_poll();
461 : :
462 : 6 : ut_send_request(_fs_unload, NULL);
463 : 6 : }
464 : :
465 : : static void
466 : 6 : fs_rename_sync(void)
467 : : {
468 : : int rc;
469 : : struct spdk_fs_thread_ctx *channel;
470 : :
471 : 6 : ut_send_request(_fs_init, NULL);
472 : :
473 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
474 : 6 : CU_ASSERT(channel != NULL);
475 : :
476 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
477 : 6 : CU_ASSERT(rc == 0);
478 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
479 : :
480 [ - + ]: 6 : CU_ASSERT(strcmp(spdk_file_get_name(g_file), "testfile") == 0);
481 : :
482 : 6 : rc = spdk_fs_rename_file(g_fs, channel, "testfile", "newtestfile");
483 : 6 : CU_ASSERT(rc == 0);
484 [ - + ]: 6 : CU_ASSERT(strcmp(spdk_file_get_name(g_file), "newtestfile") == 0);
485 : :
486 : 6 : spdk_file_close(g_file, channel);
487 : :
488 : 6 : fs_thread_poll();
489 : :
490 : 6 : spdk_fs_free_thread_ctx(channel);
491 : :
492 : 6 : ut_send_request(_fs_unload, NULL);
493 : 6 : }
494 : :
495 : : static void
496 : 6 : cache_append_no_cache(void)
497 : : {
498 : : int rc;
499 : 5 : char buf[100];
500 : : struct spdk_fs_thread_ctx *channel;
501 : :
502 : 6 : ut_send_request(_fs_init, NULL);
503 : :
504 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
505 : :
506 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
507 : 6 : CU_ASSERT(rc == 0);
508 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
509 : :
510 : 6 : spdk_file_write(g_file, channel, buf, 0 * sizeof(buf), sizeof(buf));
511 : 6 : CU_ASSERT(spdk_file_get_length(g_file) == 1 * sizeof(buf));
512 : 6 : spdk_file_write(g_file, channel, buf, 1 * sizeof(buf), sizeof(buf));
513 : 6 : CU_ASSERT(spdk_file_get_length(g_file) == 2 * sizeof(buf));
514 : 6 : spdk_file_sync(g_file, channel);
515 : :
516 : 6 : fs_thread_poll();
517 : :
518 : 6 : spdk_file_write(g_file, channel, buf, 2 * sizeof(buf), sizeof(buf));
519 : 6 : CU_ASSERT(spdk_file_get_length(g_file) == 3 * sizeof(buf));
520 : 6 : spdk_file_write(g_file, channel, buf, 3 * sizeof(buf), sizeof(buf));
521 : 6 : CU_ASSERT(spdk_file_get_length(g_file) == 4 * sizeof(buf));
522 : 6 : spdk_file_write(g_file, channel, buf, 4 * sizeof(buf), sizeof(buf));
523 : 6 : CU_ASSERT(spdk_file_get_length(g_file) == 5 * sizeof(buf));
524 : :
525 : 6 : spdk_file_close(g_file, channel);
526 : :
527 : 6 : fs_thread_poll();
528 : :
529 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
530 : 6 : CU_ASSERT(rc == 0);
531 : :
532 : 6 : spdk_fs_free_thread_ctx(channel);
533 : :
534 : 6 : ut_send_request(_fs_unload, NULL);
535 : 6 : }
536 : :
537 : : static void
538 : 6 : fs_delete_file_without_close(void)
539 : : {
540 : : int rc;
541 : : struct spdk_fs_thread_ctx *channel;
542 : 5 : struct spdk_file *file;
543 : :
544 : 6 : ut_send_request(_fs_init, NULL);
545 : 6 : channel = spdk_fs_alloc_thread_ctx(g_fs);
546 : 6 : CU_ASSERT(channel != NULL);
547 : :
548 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
549 : 6 : CU_ASSERT(rc == 0);
550 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(g_file != NULL);
551 : :
552 : 6 : rc = spdk_fs_delete_file(g_fs, channel, "testfile");
553 : 6 : CU_ASSERT(rc == 0);
554 : 6 : CU_ASSERT(g_file->ref_count != 0);
555 [ - + ]: 6 : CU_ASSERT(g_file->is_deleted == true);
556 : :
557 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &file);
558 : 6 : CU_ASSERT(rc != 0);
559 : :
560 : 6 : spdk_file_close(g_file, channel);
561 : :
562 : 6 : fs_thread_poll();
563 : :
564 : 6 : rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &file);
565 : 6 : CU_ASSERT(rc != 0);
566 : :
567 : 6 : spdk_fs_free_thread_ctx(channel);
568 : :
569 : 6 : ut_send_request(_fs_unload, NULL);
570 : :
571 : 6 : }
572 : :
573 : : static bool g_thread_exit = false;
574 : :
575 : : static void
576 : 6 : terminate_spdk_thread(void *arg)
577 : : {
578 : 6 : g_thread_exit = true;
579 : 6 : }
580 : :
581 : : static void *
582 : 6 : spdk_thread(void *arg)
583 : : {
584 : 6 : struct spdk_thread *thread = arg;
585 : :
586 : 6 : spdk_set_thread(thread);
587 : :
588 [ + + + + ]: 300377 : while (!g_thread_exit) {
589 : 300371 : spdk_thread_poll(thread, 0, 0);
590 : : }
591 : :
592 : 6 : return NULL;
593 : : }
594 : :
595 : : int
596 : 6 : main(int argc, char **argv)
597 : : {
598 : : struct spdk_thread *thread;
599 : 6 : CU_pSuite suite = NULL;
600 : 5 : pthread_t spdk_tid;
601 : : unsigned int num_failures;
602 : :
603 : 6 : CU_initialize_registry();
604 : :
605 : 6 : suite = CU_add_suite("blobfs_sync_ut", NULL, NULL);
606 : :
607 : 6 : CU_ADD_TEST(suite, cache_read_after_write);
608 : 6 : CU_ADD_TEST(suite, file_length);
609 : 6 : CU_ADD_TEST(suite, append_write_to_extend_blob);
610 : 6 : CU_ADD_TEST(suite, partial_buffer);
611 : 6 : CU_ADD_TEST(suite, cache_write_null_buffer);
612 : 6 : CU_ADD_TEST(suite, fs_create_sync);
613 : 6 : CU_ADD_TEST(suite, fs_rename_sync);
614 : 6 : CU_ADD_TEST(suite, cache_append_no_cache);
615 : 6 : CU_ADD_TEST(suite, fs_delete_file_without_close);
616 : :
617 : 6 : spdk_thread_lib_init(NULL, 0);
618 : :
619 : 6 : thread = spdk_thread_create("test_thread", NULL);
620 : 6 : spdk_set_thread(thread);
621 : :
622 : 6 : g_dispatch_thread = spdk_thread_create("dispatch_thread", NULL);
623 [ - + - + ]: 6 : pthread_create(&spdk_tid, NULL, spdk_thread, g_dispatch_thread);
624 : :
625 : 6 : g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
626 : :
627 : 6 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
628 : 6 : CU_cleanup_registry();
629 : :
630 : 6 : free(g_dev_buffer);
631 : :
632 : 6 : ut_send_request(terminate_spdk_thread, NULL);
633 : 6 : pthread_join(spdk_tid, NULL);
634 : :
635 [ - + ]: 6 : while (spdk_thread_poll(g_dispatch_thread, 0, 0) > 0) {}
636 [ - + ]: 6 : while (spdk_thread_poll(thread, 0, 0) > 0) {}
637 : :
638 : 6 : spdk_set_thread(thread);
639 : 6 : spdk_thread_exit(thread);
640 [ + + ]: 12 : while (!spdk_thread_is_exited(thread)) {
641 : 6 : spdk_thread_poll(thread, 0, 0);
642 : : }
643 : 6 : spdk_thread_destroy(thread);
644 : :
645 : 6 : spdk_set_thread(g_dispatch_thread);
646 : 6 : spdk_thread_exit(g_dispatch_thread);
647 [ + + ]: 12 : while (!spdk_thread_is_exited(g_dispatch_thread)) {
648 : 6 : spdk_thread_poll(g_dispatch_thread, 0, 0);
649 : : }
650 : 6 : spdk_thread_destroy(g_dispatch_thread);
651 : :
652 : 6 : spdk_thread_lib_fini();
653 : :
654 : 6 : return num_failures;
655 : : }
|