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