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