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