xref: /spdk/test/unit/lib/blobfs/blobfs_async_ut/blobfs_async_ut.c (revision 03e3fc4f5835983a4e6602b4e770922e798ce263)
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 "spdk/stdinc.h"
35 
36 #include "CUnit/Basic.h"
37 
38 #include "common/lib/ut_multithread.c"
39 
40 #include "spdk_cunit.h"
41 #include "blobfs/blobfs.c"
42 #include "blobfs/tree.c"
43 #include "blob/blobstore.h"
44 
45 #include "spdk_internal/thread.h"
46 
47 #include "unit/lib/blob/bs_dev_common.c"
48 
49 struct spdk_filesystem *g_fs;
50 struct spdk_file *g_file;
51 int g_fserrno;
52 struct spdk_trace_histories *g_trace_histories;
53 DEFINE_STUB_V(spdk_trace_add_register_fn, (struct spdk_trace_register_fn *reg_fn));
54 DEFINE_STUB_V(spdk_trace_register_description, (const char *name,
55 		uint16_t tpoint_id, uint8_t owner_type,
56 		uint8_t object_type, uint8_t new_object,
57 		uint8_t arg1_is_ptr, const char *arg1_name));
58 DEFINE_STUB_V(_spdk_trace_record, (uint64_t tsc, uint16_t tpoint_id, uint16_t poller_id,
59 				   uint32_t size, uint64_t object_id, uint64_t arg1));
60 
61 /* Return NULL to test hardcoded defaults. */
62 struct spdk_conf_section *
63 spdk_conf_find_section(struct spdk_conf *cp, const char *name)
64 {
65 	return NULL;
66 }
67 
68 /* Return -1 to test hardcoded defaults. */
69 int
70 spdk_conf_section_get_intval(struct spdk_conf_section *sp, const char *key)
71 {
72 	return -1;
73 }
74 
75 static void
76 fs_op_complete(void *ctx, int fserrno)
77 {
78 	g_fserrno = fserrno;
79 }
80 
81 static void
82 fs_op_with_handle_complete(void *ctx, struct spdk_filesystem *fs, int fserrno)
83 {
84 	g_fs = fs;
85 	g_fserrno = fserrno;
86 }
87 
88 static void
89 fs_poll_threads(void)
90 {
91 	poll_threads();
92 	while (spdk_thread_poll(g_cache_pool_thread, 0, 0) > 0) {}
93 }
94 
95 static void
96 fs_init(void)
97 {
98 	struct spdk_filesystem *fs;
99 	struct spdk_bs_dev *dev;
100 
101 	dev = init_dev();
102 
103 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
104 	fs_poll_threads();
105 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
106 	CU_ASSERT(g_fserrno == 0);
107 	fs = g_fs;
108 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
109 
110 	g_fserrno = 1;
111 	spdk_fs_unload(fs, fs_op_complete, NULL);
112 	fs_poll_threads();
113 	CU_ASSERT(g_fserrno == 0);
114 }
115 
116 static void
117 create_cb(void *ctx, int fserrno)
118 {
119 	g_fserrno = fserrno;
120 }
121 
122 static void
123 open_cb(void *ctx, struct spdk_file *f, int fserrno)
124 {
125 	g_fserrno = fserrno;
126 	g_file = f;
127 }
128 
129 static void
130 delete_cb(void *ctx, int fserrno)
131 {
132 	g_fserrno = fserrno;
133 }
134 
135 static void
136 fs_open(void)
137 {
138 	struct spdk_filesystem *fs;
139 	spdk_fs_iter iter;
140 	struct spdk_bs_dev *dev;
141 	struct spdk_file *file;
142 	char name[257] = {'\0'};
143 
144 	dev = init_dev();
145 	memset(name, 'a', sizeof(name) - 1);
146 
147 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
148 	fs_poll_threads();
149 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
150 	CU_ASSERT(g_fserrno == 0);
151 	fs = g_fs;
152 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
153 
154 	g_fserrno = 0;
155 	/* Open should fail, because the file name is too long. */
156 	spdk_fs_open_file_async(fs, name, SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL);
157 	fs_poll_threads();
158 	CU_ASSERT(g_fserrno == -ENAMETOOLONG);
159 
160 	g_fserrno = 0;
161 	spdk_fs_open_file_async(fs, "file1", 0, open_cb, NULL);
162 	fs_poll_threads();
163 	CU_ASSERT(g_fserrno == -ENOENT);
164 
165 	g_file = NULL;
166 	g_fserrno = 1;
167 	spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL);
168 	fs_poll_threads();
169 	CU_ASSERT(g_fserrno == 0);
170 	SPDK_CU_ASSERT_FATAL(g_file != NULL);
171 	CU_ASSERT(!strcmp("file1", g_file->name));
172 	CU_ASSERT(g_file->ref_count == 1);
173 
174 	iter = spdk_fs_iter_first(fs);
175 	CU_ASSERT(iter != NULL);
176 	file = spdk_fs_iter_get_file(iter);
177 	SPDK_CU_ASSERT_FATAL(file != NULL);
178 	CU_ASSERT(!strcmp("file1", file->name));
179 	iter = spdk_fs_iter_next(iter);
180 	CU_ASSERT(iter == NULL);
181 
182 	g_fserrno = 0;
183 	/* Delete should successful, we will mark the file as deleted. */
184 	spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL);
185 	fs_poll_threads();
186 	CU_ASSERT(g_fserrno == 0);
187 	CU_ASSERT(!TAILQ_EMPTY(&fs->files));
188 
189 	g_fserrno = 1;
190 	spdk_file_close_async(g_file, fs_op_complete, NULL);
191 	fs_poll_threads();
192 	CU_ASSERT(g_fserrno == 0);
193 	CU_ASSERT(TAILQ_EMPTY(&fs->files));
194 
195 	g_fserrno = 1;
196 	spdk_fs_unload(fs, fs_op_complete, NULL);
197 	fs_poll_threads();
198 	CU_ASSERT(g_fserrno == 0);
199 }
200 
201 static void
202 fs_create(void)
203 {
204 	struct spdk_filesystem *fs;
205 	struct spdk_bs_dev *dev;
206 	char name[257] = {'\0'};
207 
208 	dev = init_dev();
209 	memset(name, 'a', sizeof(name) - 1);
210 
211 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
212 	fs_poll_threads();
213 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
214 	CU_ASSERT(g_fserrno == 0);
215 	fs = g_fs;
216 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
217 
218 	g_fserrno = 0;
219 	/* Create should fail, because the file name is too long. */
220 	spdk_fs_create_file_async(fs, name, create_cb, NULL);
221 	fs_poll_threads();
222 	CU_ASSERT(g_fserrno == -ENAMETOOLONG);
223 
224 	g_fserrno = 1;
225 	spdk_fs_create_file_async(fs, "file1", create_cb, NULL);
226 	fs_poll_threads();
227 	CU_ASSERT(g_fserrno == 0);
228 
229 	g_fserrno = 1;
230 	spdk_fs_create_file_async(fs, "file1", create_cb, NULL);
231 	fs_poll_threads();
232 	CU_ASSERT(g_fserrno == -EEXIST);
233 
234 	g_fserrno = 1;
235 	spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL);
236 	fs_poll_threads();
237 	CU_ASSERT(g_fserrno == 0);
238 	CU_ASSERT(TAILQ_EMPTY(&fs->files));
239 
240 	g_fserrno = 1;
241 	spdk_fs_unload(fs, fs_op_complete, NULL);
242 	fs_poll_threads();
243 	CU_ASSERT(g_fserrno == 0);
244 }
245 
246 static void
247 fs_truncate(void)
248 {
249 	struct spdk_filesystem *fs;
250 	struct spdk_bs_dev *dev;
251 
252 	dev = init_dev();
253 
254 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
255 	fs_poll_threads();
256 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
257 	CU_ASSERT(g_fserrno == 0);
258 	fs = g_fs;
259 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
260 
261 	g_file = NULL;
262 	g_fserrno = 1;
263 	spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL);
264 	fs_poll_threads();
265 	CU_ASSERT(g_fserrno == 0);
266 	SPDK_CU_ASSERT_FATAL(g_file != NULL);
267 
268 	g_fserrno = 1;
269 	spdk_file_truncate_async(g_file, 18 * 1024 * 1024 + 1, fs_op_complete, NULL);
270 	fs_poll_threads();
271 	CU_ASSERT(g_fserrno == 0);
272 	CU_ASSERT(g_file->length == 18 * 1024 * 1024 + 1);
273 
274 	g_fserrno = 1;
275 	spdk_file_truncate_async(g_file, 1, fs_op_complete, NULL);
276 	fs_poll_threads();
277 	CU_ASSERT(g_fserrno == 0);
278 	CU_ASSERT(g_file->length == 1);
279 
280 	g_fserrno = 1;
281 	spdk_file_truncate_async(g_file, 18 * 1024 * 1024 + 1, fs_op_complete, NULL);
282 	fs_poll_threads();
283 	CU_ASSERT(g_fserrno == 0);
284 	CU_ASSERT(g_file->length == 18 * 1024 * 1024 + 1);
285 
286 	g_fserrno = 1;
287 	spdk_file_close_async(g_file, fs_op_complete, NULL);
288 	fs_poll_threads();
289 	CU_ASSERT(g_fserrno == 0);
290 	CU_ASSERT(g_file->ref_count == 0);
291 
292 	g_fserrno = 1;
293 	spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL);
294 	fs_poll_threads();
295 	CU_ASSERT(g_fserrno == 0);
296 	CU_ASSERT(TAILQ_EMPTY(&fs->files));
297 
298 	g_fserrno = 1;
299 	spdk_fs_unload(fs, fs_op_complete, NULL);
300 	fs_poll_threads();
301 	CU_ASSERT(g_fserrno == 0);
302 }
303 
304 static void
305 fs_rename(void)
306 {
307 	struct spdk_filesystem *fs;
308 	struct spdk_file *file, *file2, *file_iter;
309 	struct spdk_bs_dev *dev;
310 
311 	dev = init_dev();
312 
313 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
314 	fs_poll_threads();
315 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
316 	CU_ASSERT(g_fserrno == 0);
317 	fs = g_fs;
318 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
319 
320 	g_fserrno = 1;
321 	spdk_fs_create_file_async(fs, "file1", create_cb, NULL);
322 	fs_poll_threads();
323 	CU_ASSERT(g_fserrno == 0);
324 
325 	g_file = NULL;
326 	g_fserrno = 1;
327 	spdk_fs_open_file_async(fs, "file1", 0, open_cb, NULL);
328 	fs_poll_threads();
329 	CU_ASSERT(g_fserrno == 0);
330 	SPDK_CU_ASSERT_FATAL(g_file != NULL);
331 	CU_ASSERT(g_file->ref_count == 1);
332 
333 	file = g_file;
334 	g_file = NULL;
335 	g_fserrno = 1;
336 	spdk_file_close_async(file, fs_op_complete, NULL);
337 	fs_poll_threads();
338 	CU_ASSERT(g_fserrno == 0);
339 	SPDK_CU_ASSERT_FATAL(file->ref_count == 0);
340 
341 	g_file = NULL;
342 	g_fserrno = 1;
343 	spdk_fs_open_file_async(fs, "file2", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL);
344 	fs_poll_threads();
345 	CU_ASSERT(g_fserrno == 0);
346 	SPDK_CU_ASSERT_FATAL(g_file != NULL);
347 	CU_ASSERT(g_file->ref_count == 1);
348 
349 	file2 = g_file;
350 	g_file = NULL;
351 	g_fserrno = 1;
352 	spdk_file_close_async(file2, fs_op_complete, NULL);
353 	fs_poll_threads();
354 	CU_ASSERT(g_fserrno == 0);
355 	SPDK_CU_ASSERT_FATAL(file2->ref_count == 0);
356 
357 	/*
358 	 * Do a 3-way rename.  This should delete the old "file2", then rename
359 	 *  "file1" to "file2".
360 	 */
361 	g_fserrno = 1;
362 	spdk_fs_rename_file_async(fs, "file1", "file2", fs_op_complete, NULL);
363 	fs_poll_threads();
364 	CU_ASSERT(g_fserrno == 0);
365 	CU_ASSERT(file->ref_count == 0);
366 	CU_ASSERT(!strcmp(file->name, "file2"));
367 	CU_ASSERT(TAILQ_FIRST(&fs->files) == file);
368 	CU_ASSERT(TAILQ_NEXT(file, tailq) == NULL);
369 
370 	g_fserrno = 0;
371 	spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL);
372 	fs_poll_threads();
373 	CU_ASSERT(g_fserrno == -ENOENT);
374 	CU_ASSERT(!TAILQ_EMPTY(&fs->files));
375 	TAILQ_FOREACH(file_iter, &fs->files, tailq) {
376 		if (file_iter == NULL) {
377 			SPDK_CU_ASSERT_FATAL(false);
378 		}
379 	}
380 
381 	g_fserrno = 1;
382 	spdk_fs_delete_file_async(fs, "file2", delete_cb, NULL);
383 	fs_poll_threads();
384 	CU_ASSERT(g_fserrno == 0);
385 	CU_ASSERT(TAILQ_EMPTY(&fs->files));
386 
387 	g_fserrno = 1;
388 	spdk_fs_unload(fs, fs_op_complete, NULL);
389 	fs_poll_threads();
390 	CU_ASSERT(g_fserrno == 0);
391 }
392 
393 static void
394 fs_rw_async(void)
395 {
396 	struct spdk_filesystem *fs;
397 	struct spdk_bs_dev *dev;
398 	uint8_t w_buf[4096];
399 	uint8_t r_buf[4096];
400 
401 	dev = init_dev();
402 
403 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
404 	fs_poll_threads();
405 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
406 	CU_ASSERT(g_fserrno == 0);
407 	fs = g_fs;
408 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
409 
410 	g_file = NULL;
411 	g_fserrno = 1;
412 	spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL);
413 	fs_poll_threads();
414 	CU_ASSERT(g_fserrno == 0);
415 	SPDK_CU_ASSERT_FATAL(g_file != NULL);
416 
417 	/* Write file */
418 	CU_ASSERT(g_file->length == 0);
419 	g_fserrno = 1;
420 	memset(w_buf, 0x5a, sizeof(w_buf));
421 	spdk_file_write_async(g_file, fs->sync_target.sync_io_channel, w_buf, 0, 4096,
422 			      fs_op_complete, NULL);
423 	fs_poll_threads();
424 	CU_ASSERT(g_fserrno == 0);
425 	CU_ASSERT(g_file->length == 4096);
426 
427 	/* Read file */
428 	g_fserrno = 1;
429 	memset(r_buf, 0x0, sizeof(r_buf));
430 	spdk_file_read_async(g_file, fs->sync_target.sync_io_channel, r_buf, 0, 4096,
431 			     fs_op_complete, NULL);
432 	fs_poll_threads();
433 	CU_ASSERT(g_fserrno == 0);
434 	CU_ASSERT(memcmp(r_buf, w_buf, sizeof(r_buf)) == 0);
435 
436 	g_fserrno = 1;
437 	spdk_file_close_async(g_file, fs_op_complete, NULL);
438 	fs_poll_threads();
439 	CU_ASSERT(g_fserrno == 0);
440 
441 	g_fserrno = 1;
442 	spdk_fs_unload(fs, fs_op_complete, NULL);
443 	fs_poll_threads();
444 	CU_ASSERT(g_fserrno == 0);
445 }
446 
447 static void
448 fs_writev_readv_async(void)
449 {
450 	struct spdk_filesystem *fs;
451 	struct spdk_bs_dev *dev;
452 	struct iovec w_iov[2];
453 	struct iovec r_iov[2];
454 	uint8_t w_buf[4096];
455 	uint8_t r_buf[4096];
456 
457 	dev = init_dev();
458 
459 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
460 	fs_poll_threads();
461 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
462 	CU_ASSERT(g_fserrno == 0);
463 	fs = g_fs;
464 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
465 
466 	g_file = NULL;
467 	g_fserrno = 1;
468 	spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL);
469 	fs_poll_threads();
470 	CU_ASSERT(g_fserrno == 0);
471 	SPDK_CU_ASSERT_FATAL(g_file != NULL);
472 
473 	/* Write file */
474 	CU_ASSERT(g_file->length == 0);
475 	g_fserrno = 1;
476 	memset(w_buf, 0x5a, sizeof(w_buf));
477 	w_iov[0].iov_base = w_buf;
478 	w_iov[0].iov_len = 2048;
479 	w_iov[1].iov_base = w_buf + 2048;
480 	w_iov[1].iov_len = 2048;
481 	spdk_file_writev_async(g_file, fs->sync_target.sync_io_channel,
482 			       w_iov, 2, 0, 4096, fs_op_complete, NULL);
483 	fs_poll_threads();
484 	CU_ASSERT(g_fserrno == 0);
485 	CU_ASSERT(g_file->length == 4096);
486 
487 	/* Read file */
488 	g_fserrno = 1;
489 	memset(r_buf, 0x0, sizeof(r_buf));
490 	r_iov[0].iov_base = r_buf;
491 	r_iov[0].iov_len = 2048;
492 	r_iov[1].iov_base = r_buf + 2048;
493 	r_iov[1].iov_len = 2048;
494 	spdk_file_readv_async(g_file, fs->sync_target.sync_io_channel,
495 			      r_iov, 2, 0, 4096, fs_op_complete, NULL);
496 	fs_poll_threads();
497 	CU_ASSERT(g_fserrno == 0);
498 	CU_ASSERT(memcmp(r_buf, w_buf, sizeof(r_buf)) == 0);
499 
500 	/* Overwrite file with block aligned */
501 	g_fserrno = 1;
502 	memset(w_buf, 0x6a, sizeof(w_buf));
503 	w_iov[0].iov_base = w_buf;
504 	w_iov[0].iov_len = 2048;
505 	w_iov[1].iov_base = w_buf + 2048;
506 	w_iov[1].iov_len = 2048;
507 	spdk_file_writev_async(g_file, fs->sync_target.sync_io_channel,
508 			       w_iov, 2, 0, 4096, fs_op_complete, NULL);
509 	fs_poll_threads();
510 	CU_ASSERT(g_fserrno == 0);
511 	CU_ASSERT(g_file->length == 4096);
512 
513 	/* Read file to verify the overwritten data */
514 	g_fserrno = 1;
515 	memset(r_buf, 0x0, sizeof(r_buf));
516 	r_iov[0].iov_base = r_buf;
517 	r_iov[0].iov_len = 2048;
518 	r_iov[1].iov_base = r_buf + 2048;
519 	r_iov[1].iov_len = 2048;
520 	spdk_file_readv_async(g_file, fs->sync_target.sync_io_channel,
521 			      r_iov, 2, 0, 4096, fs_op_complete, NULL);
522 	fs_poll_threads();
523 	CU_ASSERT(g_fserrno == 0);
524 	CU_ASSERT(memcmp(r_buf, w_buf, sizeof(r_buf)) == 0);
525 
526 	g_fserrno = 1;
527 	spdk_file_close_async(g_file, fs_op_complete, NULL);
528 	fs_poll_threads();
529 	CU_ASSERT(g_fserrno == 0);
530 
531 	g_fserrno = 1;
532 	spdk_fs_unload(fs, fs_op_complete, NULL);
533 	fs_poll_threads();
534 	CU_ASSERT(g_fserrno == 0);
535 }
536 
537 static void
538 tree_find_buffer_ut(void)
539 {
540 	struct cache_tree *root;
541 	struct cache_tree *level1_0;
542 	struct cache_tree *level0_0_0;
543 	struct cache_tree *level0_0_12;
544 	struct cache_buffer *leaf_0_0_4;
545 	struct cache_buffer *leaf_0_12_8;
546 	struct cache_buffer *leaf_9_23_15;
547 	struct cache_buffer *buffer;
548 
549 	level1_0 = calloc(1, sizeof(struct cache_tree));
550 	SPDK_CU_ASSERT_FATAL(level1_0 != NULL);
551 	level0_0_0 = calloc(1, sizeof(struct cache_tree));
552 	SPDK_CU_ASSERT_FATAL(level0_0_0 != NULL);
553 	level0_0_12 = calloc(1, sizeof(struct cache_tree));
554 	SPDK_CU_ASSERT_FATAL(level0_0_12 != NULL);
555 	leaf_0_0_4 = calloc(1, sizeof(struct cache_buffer));
556 	SPDK_CU_ASSERT_FATAL(leaf_0_0_4 != NULL);
557 	leaf_0_12_8 = calloc(1, sizeof(struct cache_buffer));
558 	SPDK_CU_ASSERT_FATAL(leaf_0_12_8 != NULL);
559 	leaf_9_23_15 = calloc(1, sizeof(struct cache_buffer));
560 	SPDK_CU_ASSERT_FATAL(leaf_9_23_15 != NULL);
561 
562 	level1_0->level = 1;
563 	level0_0_0->level = 0;
564 	level0_0_12->level = 0;
565 
566 	leaf_0_0_4->offset = CACHE_BUFFER_SIZE * 4;
567 	level0_0_0->u.buffer[4] = leaf_0_0_4;
568 	level0_0_0->present_mask |= (1ULL << 4);
569 
570 	leaf_0_12_8->offset = CACHE_TREE_LEVEL_SIZE(1) * 12 + CACHE_BUFFER_SIZE * 8;
571 	level0_0_12->u.buffer[8] = leaf_0_12_8;
572 	level0_0_12->present_mask |= (1ULL << 8);
573 
574 	level1_0->u.tree[0] = level0_0_0;
575 	level1_0->present_mask |= (1ULL << 0);
576 	level1_0->u.tree[12] = level0_0_12;
577 	level1_0->present_mask |= (1ULL << 12);
578 
579 	buffer = tree_find_buffer(NULL, 0);
580 	CU_ASSERT(buffer == NULL);
581 
582 	buffer = tree_find_buffer(level0_0_0, 0);
583 	CU_ASSERT(buffer == NULL);
584 
585 	buffer = tree_find_buffer(level0_0_0, CACHE_TREE_LEVEL_SIZE(0) + 1);
586 	CU_ASSERT(buffer == NULL);
587 
588 	buffer = tree_find_buffer(level0_0_0, leaf_0_0_4->offset);
589 	CU_ASSERT(buffer == leaf_0_0_4);
590 
591 	buffer = tree_find_buffer(level1_0, leaf_0_0_4->offset);
592 	CU_ASSERT(buffer == leaf_0_0_4);
593 
594 	buffer = tree_find_buffer(level1_0, leaf_0_12_8->offset);
595 	CU_ASSERT(buffer == leaf_0_12_8);
596 
597 	buffer = tree_find_buffer(level1_0, leaf_0_12_8->offset + CACHE_BUFFER_SIZE - 1);
598 	CU_ASSERT(buffer == leaf_0_12_8);
599 
600 	buffer = tree_find_buffer(level1_0, leaf_0_12_8->offset - 1);
601 	CU_ASSERT(buffer == NULL);
602 
603 	leaf_9_23_15->offset = CACHE_TREE_LEVEL_SIZE(2) * 9 +
604 			       CACHE_TREE_LEVEL_SIZE(1) * 23 +
605 			       CACHE_BUFFER_SIZE * 15;
606 	root = tree_insert_buffer(level1_0, leaf_9_23_15);
607 	CU_ASSERT(root != level1_0);
608 	buffer = tree_find_buffer(root, leaf_9_23_15->offset);
609 	CU_ASSERT(buffer == leaf_9_23_15);
610 	tree_free_buffers(root);
611 	free(root);
612 }
613 
614 static void
615 channel_ops(void)
616 {
617 	struct spdk_filesystem *fs;
618 	struct spdk_bs_dev *dev;
619 	struct spdk_io_channel *channel;
620 
621 	dev = init_dev();
622 
623 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
624 	fs_poll_threads();
625 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
626 	CU_ASSERT(g_fserrno == 0);
627 	fs = g_fs;
628 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
629 
630 	channel =  spdk_fs_alloc_io_channel(fs);
631 	CU_ASSERT(channel != NULL);
632 
633 	spdk_fs_free_io_channel(channel);
634 
635 	g_fserrno = 1;
636 	spdk_fs_unload(fs, fs_op_complete, NULL);
637 	fs_poll_threads();
638 	CU_ASSERT(g_fserrno == 0);
639 	g_fs = NULL;
640 }
641 
642 static void
643 channel_ops_sync(void)
644 {
645 	struct spdk_filesystem *fs;
646 	struct spdk_bs_dev *dev;
647 	struct spdk_fs_thread_ctx *channel;
648 
649 	dev = init_dev();
650 
651 	spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL);
652 	fs_poll_threads();
653 	SPDK_CU_ASSERT_FATAL(g_fs != NULL);
654 	CU_ASSERT(g_fserrno == 0);
655 	fs = g_fs;
656 	SPDK_CU_ASSERT_FATAL(fs->bs->dev == dev);
657 
658 	channel =  spdk_fs_alloc_thread_ctx(fs);
659 	CU_ASSERT(channel != NULL);
660 
661 	spdk_fs_free_thread_ctx(channel);
662 
663 	g_fserrno = 1;
664 	spdk_fs_unload(fs, fs_op_complete, NULL);
665 	fs_poll_threads();
666 	CU_ASSERT(g_fserrno == 0);
667 	g_fs = NULL;
668 }
669 
670 int main(int argc, char **argv)
671 {
672 	CU_pSuite	suite = NULL;
673 	unsigned int	num_failures;
674 
675 	CU_set_error_action(CUEA_ABORT);
676 	CU_initialize_registry();
677 
678 	suite = CU_add_suite("blobfs_async_ut", NULL, NULL);
679 
680 	CU_ADD_TEST(suite, fs_init);
681 	CU_ADD_TEST(suite, fs_open);
682 	CU_ADD_TEST(suite, fs_create);
683 	CU_ADD_TEST(suite, fs_truncate);
684 	CU_ADD_TEST(suite, fs_rename);
685 	CU_ADD_TEST(suite, fs_rw_async);
686 	CU_ADD_TEST(suite, fs_writev_readv_async);
687 	CU_ADD_TEST(suite, tree_find_buffer_ut);
688 	CU_ADD_TEST(suite, channel_ops);
689 	CU_ADD_TEST(suite, channel_ops_sync);
690 
691 	allocate_threads(1);
692 	set_thread(0);
693 
694 	g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
695 	CU_basic_set_mode(CU_BRM_VERBOSE);
696 	CU_basic_run_tests();
697 	num_failures = CU_get_number_of_failures();
698 	CU_cleanup_registry();
699 	free(g_dev_buffer);
700 
701 	free_threads();
702 
703 	return num_failures;
704 }
705