xref: /spdk/test/unit/lib/fsdev/fsdev.c/fsdev_ut.c (revision c164db9ffe3718ad4e4f5bab380ccfa62c2fa672)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  */
4 
5 #include "spdk_internal/cunit.h"
6 
7 #include "common/lib/ut_multithread.c"
8 #include "unit/lib/json_mock.c"
9 
10 #include "spdk/config.h"
11 
12 #include "spdk/log.h"
13 #include "spdk/fsdev.h"
14 #include "spdk/fsdev_module.h"
15 
16 #define UT_UNIQUE 0xBEADBEAD
17 #define UT_FOBJECT ((struct spdk_fsdev_file_object *)0xDEADDEAD)
18 #define UT_FHANDLE ((struct spdk_fsdev_file_handle *)0xBEABBEAB)
19 #define UT_FNAME "ut_test.file"
20 #define UT_LNAME "ut_test.file.link"
21 #define UT_ANAME "xattr1.name"
22 #define UT_AVALUE "xattr1.val"
23 #define UT_NUM_LOOKUPS 11
24 #define UT_DATA_SIZE 22
25 
26 
27 #define UT_CALL_REC_MAX_CALLS 5
28 #define UT_CALL_REC_MAX_PARAMS 15
29 #define UT_CALL_REC_MAX_STR_SIZE 255
30 
31 #define UT_SUBMIT_IO_NUM_COMMON_PARAMS 4
32 
33 static uint64_t
34 ut_hash(const void *buf, size_t size)
35 {
36 	uint64_t hash = 5381;
37 	const char *p = buf;
38 	size_t i;
39 
40 	for (i = 0; i < size; i++) {
41 		hash = ((hash << 5) + hash) + (*p); /* hash * 33 + c */
42 		p++;
43 	}
44 
45 	return hash;
46 }
47 
48 struct ut_call_record {
49 	struct {
50 		void *func;
51 		union {
52 			uint64_t integer;
53 			void *ptr;
54 			char str[UT_CALL_REC_MAX_STR_SIZE + 1];
55 			uint64_t hash;
56 		} params[UT_CALL_REC_MAX_PARAMS];
57 		size_t param_count;
58 	} call[UT_CALL_REC_MAX_CALLS];
59 	size_t count;
60 };
61 
62 static struct ut_call_record g_call_list;
63 
64 static inline void
65 ut_calls_reset(void)
66 {
67 	memset(&g_call_list, 0, sizeof(g_call_list));
68 }
69 
70 static inline void
71 ut_call_record_begin(void *pfunc)
72 {
73 	SPDK_CU_ASSERT_FATAL(g_call_list.count < UT_CALL_REC_MAX_CALLS);
74 	g_call_list.call[g_call_list.count].func = pfunc;
75 	g_call_list.call[g_call_list.count].param_count = 0;
76 }
77 
78 static inline void
79 ut_call_record_param_int(uint64_t val)
80 {
81 	SPDK_CU_ASSERT_FATAL(g_call_list.call[g_call_list.count].param_count < UT_CALL_REC_MAX_PARAMS);
82 	g_call_list.call[g_call_list.count].params[g_call_list.call[g_call_list.count].param_count].integer
83 		= val;
84 	g_call_list.call[g_call_list.count].param_count++;
85 }
86 
87 static inline void
88 ut_call_record_param_ptr(void *ptr)
89 {
90 	SPDK_CU_ASSERT_FATAL(g_call_list.call[g_call_list.count].param_count < UT_CALL_REC_MAX_PARAMS);
91 	g_call_list.call[g_call_list.count].params[g_call_list.call[g_call_list.count].param_count].ptr =
92 		ptr;
93 	g_call_list.call[g_call_list.count].param_count++;
94 }
95 
96 static inline void
97 ut_call_record_param_str(const char *str)
98 {
99 	SPDK_CU_ASSERT_FATAL(g_call_list.call[g_call_list.count].param_count < UT_CALL_REC_MAX_PARAMS);
100 	spdk_strcpy_pad(
101 		g_call_list.call[g_call_list.count].params[g_call_list.call[g_call_list.count].param_count].str,
102 		str, UT_CALL_REC_MAX_STR_SIZE, 0);
103 	g_call_list.call[g_call_list.count].params[g_call_list.call[g_call_list.count].param_count].str[UT_CALL_REC_MAX_STR_SIZE]
104 		= 0;
105 	g_call_list.call[g_call_list.count].param_count++;
106 }
107 
108 static inline void
109 ut_call_record_param_hash(const void *buf, size_t size)
110 {
111 	SPDK_CU_ASSERT_FATAL(g_call_list.call[g_call_list.count].param_count < UT_CALL_REC_MAX_PARAMS);
112 	g_call_list.call[g_call_list.count].params[g_call_list.call[g_call_list.count].param_count].hash =
113 		ut_hash(buf, size);
114 	g_call_list.call[g_call_list.count].param_count++;
115 }
116 
117 static inline size_t
118 ut_call_record_get_current_param_count(void)
119 {
120 	return g_call_list.call[g_call_list.count].param_count;
121 }
122 static inline void
123 ut_call_record_end(void)
124 {
125 	g_call_list.count++;
126 }
127 
128 static inline void
129 ut_call_record_simple_param_ptr(void *pfunc, void *ptr)
130 {
131 	ut_call_record_begin(pfunc);
132 	ut_call_record_param_ptr(ptr);
133 	ut_call_record_end();
134 }
135 
136 static inline size_t
137 ut_calls_get_call_count(void)
138 {
139 	return g_call_list.count;
140 }
141 
142 static inline size_t
143 ut_calls_get_param_count(size_t call_idx)
144 {
145 	SPDK_CU_ASSERT_FATAL(call_idx < g_call_list.count);
146 	return g_call_list.call[call_idx].param_count;
147 }
148 
149 static inline void *
150 ut_calls_get_func(size_t call_idx)
151 {
152 	SPDK_CU_ASSERT_FATAL(call_idx < g_call_list.count);
153 	return g_call_list.call[call_idx].func;
154 }
155 
156 static inline uint64_t
157 ut_calls_param_get_int(size_t call_idx, size_t param_idx)
158 {
159 	SPDK_CU_ASSERT_FATAL(call_idx < g_call_list.count);
160 	SPDK_CU_ASSERT_FATAL(param_idx < g_call_list.call[call_idx].param_count);
161 	return g_call_list.call[call_idx].params[param_idx].integer;
162 }
163 
164 static inline void *
165 ut_calls_param_get_ptr(size_t call_idx, size_t param_idx)
166 {
167 	SPDK_CU_ASSERT_FATAL(call_idx < g_call_list.count);
168 	SPDK_CU_ASSERT_FATAL(param_idx < g_call_list.call[call_idx].param_count);
169 	return g_call_list.call[call_idx].params[param_idx].ptr;
170 }
171 
172 static inline const char *
173 ut_calls_param_get_str(size_t call_idx, size_t param_idx)
174 {
175 	SPDK_CU_ASSERT_FATAL(call_idx < g_call_list.count);
176 	SPDK_CU_ASSERT_FATAL(param_idx < g_call_list.call[call_idx].param_count);
177 	return g_call_list.call[call_idx].params[param_idx].str;
178 }
179 
180 static inline uint64_t
181 ut_calls_param_get_hash(size_t call_idx, size_t param_idx)
182 {
183 	SPDK_CU_ASSERT_FATAL(call_idx < g_call_list.count);
184 	SPDK_CU_ASSERT_FATAL(param_idx < g_call_list.call[call_idx].param_count);
185 	return g_call_list.call[call_idx].params[param_idx].hash;
186 }
187 
188 struct ut_fsdev {
189 	struct spdk_fsdev fsdev;
190 	int desired_io_status;
191 };
192 
193 struct ut_io_channel {
194 	int reserved;
195 };
196 
197 struct spdk_fsdev_file_object {
198 	int reserved;
199 };
200 
201 struct spdk_fsdev_file_handle {
202 	int reserved;
203 };
204 
205 static inline struct ut_fsdev *
206 fsdev_to_ut_fsdev(struct spdk_fsdev *fsdev)
207 {
208 	return SPDK_CONTAINEROF(fsdev, struct ut_fsdev, fsdev);
209 }
210 
211 static struct ut_io_channel *g_ut_io_channel = NULL;
212 
213 static int
214 ut_fsdev_io_channel_create_cb(void *io_device, void *ctx_buf)
215 {
216 	struct ut_io_channel *ch = ctx_buf;
217 
218 	g_ut_io_channel = ch;
219 
220 	ut_call_record_simple_param_ptr(ut_fsdev_io_channel_create_cb, ctx_buf);
221 
222 	return 0;
223 }
224 
225 static void
226 ut_fsdev_io_channel_destroy_cb(void *io_device, void *ctx_buf)
227 {
228 	g_ut_io_channel = NULL;
229 
230 	ut_call_record_simple_param_ptr(ut_fsdev_io_channel_destroy_cb, ctx_buf);
231 }
232 
233 static int
234 ut_fsdev_initialize(void)
235 {
236 	spdk_io_device_register(&g_call_list,
237 				ut_fsdev_io_channel_create_cb, ut_fsdev_io_channel_destroy_cb,
238 				sizeof(struct ut_io_channel), "ut_fsdev");
239 
240 	return 0;
241 }
242 
243 static void
244 ut_fsdev_io_device_unregister_done(void *io_device)
245 {
246 	SPDK_NOTICELOG("ut_fsdev_io_device unregistred\n");
247 }
248 
249 static void
250 ut_fsdev_finish(void)
251 {
252 	spdk_io_device_unregister(&g_call_list, ut_fsdev_io_device_unregister_done);
253 }
254 
255 static int
256 ut_fsdev_get_ctx_size(void)
257 {
258 	return 0;
259 }
260 
261 static struct spdk_fsdev_module ut_fsdev_module = {
262 	.name = "ut_fsdev",
263 	.module_init = ut_fsdev_initialize,
264 	.module_fini = ut_fsdev_finish,
265 	.get_ctx_size = ut_fsdev_get_ctx_size,
266 };
267 
268 SPDK_FSDEV_MODULE_REGISTER(ut_fsdev, &ut_fsdev_module);
269 
270 static int
271 ut_fsdev_destruct(void *ctx)
272 {
273 	ut_call_record_simple_param_ptr(ut_fsdev_destruct, ctx);
274 
275 	return 0;
276 }
277 
278 static struct spdk_fsdev_file_attr ut_fsdev_attr;
279 static struct spdk_fsdev_file_object ut_fsdev_fobject;
280 static struct iovec ut_iov[5];
281 static struct spdk_fsdev_file_statfs ut_statfs;
282 static char ut_buff[1024];
283 static bool ut_listxattr_size_only;
284 static uint64_t ut_readdir_offset;
285 static uint64_t ut_readdir_num_entries;
286 static uint64_t ut_readdir_num_entry_cb_calls;
287 static struct spdk_fsdev_mount_opts ut_mount_opts;
288 
289 static void
290 ut_fsdev_submit_request(struct spdk_io_channel *_ch, struct spdk_fsdev_io *fsdev_io)
291 {
292 	enum spdk_fsdev_io_type type = spdk_fsdev_io_get_type(fsdev_io);
293 	struct ut_fsdev *utfsdev = fsdev_to_ut_fsdev(fsdev_io->fsdev);
294 	struct ut_io_channel *ch = spdk_io_channel_get_ctx(_ch);
295 	uint64_t unique = spdk_fsdev_io_get_unique(fsdev_io);
296 	int res, i = 0;
297 
298 	CU_ASSERT(type >= 0 && type < __SPDK_FSDEV_IO_LAST);
299 
300 	ut_call_record_begin(ut_fsdev_submit_request);
301 
302 	/* Common params */
303 	ut_call_record_param_int(type);
304 	/* There's no unique for abort so we just add UT_UNIQUE to pass the test */
305 	ut_call_record_param_int((type != SPDK_FSDEV_IO_ABORT) ? unique : UT_UNIQUE);
306 	ut_call_record_param_ptr(ch);
307 	ut_call_record_param_ptr(utfsdev);
308 
309 	CU_ASSERT(ut_call_record_get_current_param_count() == UT_SUBMIT_IO_NUM_COMMON_PARAMS);
310 
311 	switch (type) {
312 	case SPDK_FSDEV_IO_MOUNT:
313 		ut_call_record_param_hash(&fsdev_io->u_in.mount.opts, sizeof(fsdev_io->u_in.mount.opts));
314 		fsdev_io->u_out.mount.root_fobject = UT_FOBJECT;
315 		fsdev_io->u_out.mount.opts.opts_size = fsdev_io->u_in.mount.opts.opts_size;
316 		fsdev_io->u_out.mount.opts.max_write = fsdev_io->u_in.mount.opts.max_write / 2;
317 		fsdev_io->u_out.mount.opts.writeback_cache_enabled =
318 			!fsdev_io->u_in.mount.opts.writeback_cache_enabled;
319 		break;
320 	case SPDK_FSDEV_IO_LOOKUP:
321 		ut_call_record_param_str(fsdev_io->u_in.lookup.name);
322 		ut_call_record_param_ptr(fsdev_io->u_in.lookup.parent_fobject);
323 		fsdev_io->u_out.lookup.fobject = &ut_fsdev_fobject;
324 		fsdev_io->u_out.lookup.attr = ut_fsdev_attr;
325 		break;
326 	case SPDK_FSDEV_IO_FORGET:
327 		ut_call_record_param_ptr(fsdev_io->u_in.forget.fobject);
328 		ut_call_record_param_int(fsdev_io->u_in.forget.nlookup);
329 		break;
330 	case SPDK_FSDEV_IO_GETATTR:
331 		ut_call_record_param_ptr(fsdev_io->u_in.getattr.fobject);
332 		ut_call_record_param_ptr(fsdev_io->u_in.getattr.fhandle);
333 		fsdev_io->u_out.getattr.attr = ut_fsdev_attr;
334 		break;
335 	case SPDK_FSDEV_IO_SETATTR:
336 		ut_call_record_param_ptr(fsdev_io->u_in.setattr.fobject);
337 		ut_call_record_param_ptr(fsdev_io->u_in.setattr.fhandle);
338 		ut_call_record_param_hash(&fsdev_io->u_in.setattr.attr, sizeof(fsdev_io->u_in.setattr.attr));
339 		ut_call_record_param_int(fsdev_io->u_in.setattr.to_set);
340 		fsdev_io->u_out.getattr.attr = ut_fsdev_attr;
341 		break;
342 	case SPDK_FSDEV_IO_READLINK:
343 		ut_call_record_param_ptr(fsdev_io->u_in.readlink.fobject);
344 		fsdev_io->u_out.readlink.linkname = strdup(UT_FNAME);
345 		SPDK_CU_ASSERT_FATAL(fsdev_io->u_out.readlink.linkname != NULL);
346 		break;
347 	case SPDK_FSDEV_IO_SYMLINK:
348 		ut_call_record_param_ptr(fsdev_io->u_in.symlink.parent_fobject);
349 		ut_call_record_param_str(fsdev_io->u_in.symlink.target);
350 		ut_call_record_param_str(fsdev_io->u_in.symlink.linkpath);
351 		ut_call_record_param_int(fsdev_io->u_in.symlink.euid);
352 		ut_call_record_param_int(fsdev_io->u_in.symlink.egid);
353 		fsdev_io->u_out.symlink.fobject = UT_FOBJECT + 1;
354 		fsdev_io->u_out.symlink.attr = ut_fsdev_attr;
355 		break;
356 	case SPDK_FSDEV_IO_MKNOD:
357 		ut_call_record_param_ptr(fsdev_io->u_in.mknod.parent_fobject);
358 		ut_call_record_param_str(fsdev_io->u_in.mknod.name);
359 		ut_call_record_param_int(fsdev_io->u_in.mknod.mode);
360 		ut_call_record_param_int(fsdev_io->u_in.mknod.rdev);
361 		ut_call_record_param_int(fsdev_io->u_in.mknod.euid);
362 		ut_call_record_param_int(fsdev_io->u_in.mknod.egid);
363 		fsdev_io->u_out.mknod.fobject = UT_FOBJECT + 1;
364 		fsdev_io->u_out.mknod.attr = ut_fsdev_attr;
365 		break;
366 	case SPDK_FSDEV_IO_MKDIR:
367 		ut_call_record_param_ptr(fsdev_io->u_in.mkdir.parent_fobject);
368 		ut_call_record_param_str(fsdev_io->u_in.mkdir.name);
369 		ut_call_record_param_int(fsdev_io->u_in.mkdir.mode);
370 		ut_call_record_param_int(fsdev_io->u_in.mkdir.euid);
371 		ut_call_record_param_int(fsdev_io->u_in.mkdir.egid);
372 		fsdev_io->u_out.mkdir.fobject = UT_FOBJECT + 1;
373 		fsdev_io->u_out.mkdir.attr = ut_fsdev_attr;
374 		break;
375 	case SPDK_FSDEV_IO_UNLINK:
376 		ut_call_record_param_ptr(fsdev_io->u_in.unlink.parent_fobject);
377 		ut_call_record_param_str(fsdev_io->u_in.unlink.name);
378 		break;
379 	case SPDK_FSDEV_IO_RMDIR:
380 		ut_call_record_param_ptr(fsdev_io->u_in.rmdir.parent_fobject);
381 		ut_call_record_param_str(fsdev_io->u_in.rmdir.name);
382 		break;
383 	case SPDK_FSDEV_IO_RENAME:
384 		ut_call_record_param_ptr(fsdev_io->u_in.rename.parent_fobject);
385 		ut_call_record_param_str(fsdev_io->u_in.rename.name);
386 		ut_call_record_param_ptr(fsdev_io->u_in.rename.new_parent_fobject);
387 		ut_call_record_param_str(fsdev_io->u_in.rename.new_name);
388 		ut_call_record_param_int(fsdev_io->u_in.rename.flags);
389 		break;
390 	case SPDK_FSDEV_IO_LINK:
391 		ut_call_record_param_ptr(fsdev_io->u_in.link.fobject);
392 		ut_call_record_param_ptr(fsdev_io->u_in.link.new_parent_fobject);
393 		ut_call_record_param_str(fsdev_io->u_in.link.name);
394 		fsdev_io->u_out.link.fobject = UT_FOBJECT + 1;
395 		fsdev_io->u_out.link.attr = ut_fsdev_attr;
396 		break;
397 	case SPDK_FSDEV_IO_OPEN:
398 		ut_call_record_param_ptr(fsdev_io->u_in.open.fobject);
399 		ut_call_record_param_int(fsdev_io->u_in.open.flags);
400 		fsdev_io->u_out.open.fhandle = UT_FHANDLE;
401 		break;
402 	case SPDK_FSDEV_IO_READ:
403 		ut_call_record_param_ptr(fsdev_io->u_in.read.fobject);
404 		ut_call_record_param_ptr(fsdev_io->u_in.read.fhandle);
405 		ut_call_record_param_int(fsdev_io->u_in.read.size);
406 		ut_call_record_param_int(fsdev_io->u_in.read.offs);
407 		ut_call_record_param_int(fsdev_io->u_in.read.flags);
408 		ut_call_record_param_hash(fsdev_io->u_in.read.iov,
409 					  fsdev_io->u_in.read.iovcnt * sizeof(fsdev_io->u_in.read.iov[0]));
410 		ut_call_record_param_int(fsdev_io->u_in.read.iovcnt);
411 		ut_call_record_param_ptr(fsdev_io->u_in.read.opts);
412 		fsdev_io->u_out.read.data_size = UT_DATA_SIZE;
413 		break;
414 	case SPDK_FSDEV_IO_WRITE:
415 		ut_call_record_param_ptr(fsdev_io->u_in.write.fobject);
416 		ut_call_record_param_ptr(fsdev_io->u_in.write.fhandle);
417 		ut_call_record_param_int(fsdev_io->u_in.write.size);
418 		ut_call_record_param_int(fsdev_io->u_in.write.offs);
419 		ut_call_record_param_int(fsdev_io->u_in.write.flags);
420 		ut_call_record_param_hash(fsdev_io->u_in.write.iov,
421 					  fsdev_io->u_in.write.iovcnt * sizeof(fsdev_io->u_in.write.iov[0]));
422 		ut_call_record_param_int(fsdev_io->u_in.write.iovcnt);
423 		ut_call_record_param_ptr(fsdev_io->u_in.write.opts);
424 		fsdev_io->u_out.write.data_size = UT_DATA_SIZE;
425 		break;
426 	case SPDK_FSDEV_IO_STATFS:
427 		ut_call_record_param_ptr(fsdev_io->u_in.statfs.fobject);
428 		fsdev_io->u_out.statfs.statfs = ut_statfs;
429 		break;
430 	case SPDK_FSDEV_IO_RELEASE:
431 		ut_call_record_param_ptr(fsdev_io->u_in.release.fobject);
432 		ut_call_record_param_ptr(fsdev_io->u_in.release.fhandle);
433 		break;
434 	case SPDK_FSDEV_IO_FSYNC:
435 		ut_call_record_param_ptr(fsdev_io->u_in.fsync.fobject);
436 		ut_call_record_param_ptr(fsdev_io->u_in.fsync.fhandle);
437 		ut_call_record_param_int(fsdev_io->u_in.fsync.datasync);
438 		break;
439 	case SPDK_FSDEV_IO_SETXATTR:
440 		ut_call_record_param_ptr(fsdev_io->u_in.setxattr.fobject);
441 		ut_call_record_param_str(fsdev_io->u_in.setxattr.name);
442 		ut_call_record_param_str(fsdev_io->u_in.setxattr.value);
443 		ut_call_record_param_int(fsdev_io->u_in.setxattr.size);
444 		ut_call_record_param_int(fsdev_io->u_in.setxattr.flags);
445 		break;
446 	case SPDK_FSDEV_IO_GETXATTR:
447 		ut_call_record_param_ptr(fsdev_io->u_in.getxattr.fobject);
448 		ut_call_record_param_str(fsdev_io->u_in.getxattr.name);
449 		ut_call_record_param_ptr(fsdev_io->u_in.getxattr.buffer);
450 		ut_call_record_param_int(fsdev_io->u_in.getxattr.size);
451 		spdk_strcpy_pad(fsdev_io->u_in.getxattr.buffer, UT_AVALUE,
452 				fsdev_io->u_in.getxattr.size - 1, 0);
453 		fsdev_io->u_out.getxattr.value_size = sizeof(UT_AVALUE);
454 		break;
455 	case SPDK_FSDEV_IO_LISTXATTR:
456 		ut_call_record_param_ptr(fsdev_io->u_in.listxattr.fobject);
457 		ut_call_record_param_ptr(fsdev_io->u_in.listxattr.buffer);
458 		ut_call_record_param_int(fsdev_io->u_in.listxattr.size);
459 
460 		fsdev_io->u_out.listxattr.size_only = fsdev_io->u_in.listxattr.buffer == NULL;
461 		fsdev_io->u_out.listxattr.data_size = (sizeof(ut_buff) / sizeof(UT_ANAME)) * sizeof(UT_ANAME);
462 
463 		if (!fsdev_io->u_out.listxattr.size_only) {
464 			size_t size = fsdev_io->u_in.listxattr.size;
465 			char *p = fsdev_io->u_in.listxattr.buffer;
466 
467 			while (size >= sizeof(UT_ANAME)) {
468 				memcpy(p, UT_ANAME, sizeof(UT_ANAME));
469 				p += sizeof(UT_ANAME);
470 				size -= sizeof(UT_ANAME);
471 			}
472 		}
473 		break;
474 	case SPDK_FSDEV_IO_REMOVEXATTR:
475 		ut_call_record_param_ptr(fsdev_io->u_in.removexattr.fobject);
476 		ut_call_record_param_str(fsdev_io->u_in.removexattr.name);
477 		break;
478 	case SPDK_FSDEV_IO_FLUSH:
479 		ut_call_record_param_ptr(fsdev_io->u_in.flush.fobject);
480 		ut_call_record_param_ptr(fsdev_io->u_in.flush.fhandle);
481 		break;
482 	case SPDK_FSDEV_IO_OPENDIR:
483 		ut_call_record_param_ptr(fsdev_io->u_in.opendir.fobject);
484 		ut_call_record_param_int(fsdev_io->u_in.opendir.flags);
485 		fsdev_io->u_out.opendir.fhandle = UT_FHANDLE;
486 		break;
487 	case SPDK_FSDEV_IO_READDIR:
488 		ut_call_record_param_ptr(fsdev_io->u_in.readdir.fobject);
489 		ut_call_record_param_ptr(fsdev_io->u_in.readdir.fhandle);
490 		ut_call_record_param_int(fsdev_io->u_in.readdir.offset);
491 		ut_call_record_param_ptr(fsdev_io->u_in.readdir.usr_entry_cb_fn);
492 
493 		do {
494 			fsdev_io->u_out.readdir.fobject = UT_FOBJECT + i;
495 			fsdev_io->u_out.readdir.attr = ut_fsdev_attr;
496 			fsdev_io->u_out.readdir.name = UT_FNAME;
497 			fsdev_io->u_out.readdir.offset = ut_readdir_offset + i;
498 			res = fsdev_io->u_in.readdir.entry_cb_fn(fsdev_io, fsdev_io->internal.cb_arg);
499 			i++;
500 		} while (!res);
501 
502 		break;
503 	case SPDK_FSDEV_IO_RELEASEDIR:
504 		ut_call_record_param_ptr(fsdev_io->u_in.releasedir.fobject);
505 		ut_call_record_param_ptr(fsdev_io->u_in.releasedir.fhandle);
506 		break;
507 	case SPDK_FSDEV_IO_FSYNCDIR:
508 		ut_call_record_param_ptr(fsdev_io->u_in.fsyncdir.fobject);
509 		ut_call_record_param_ptr(fsdev_io->u_in.fsyncdir.fhandle);
510 		ut_call_record_param_int(fsdev_io->u_in.fsyncdir.datasync);
511 		break;
512 	case SPDK_FSDEV_IO_FLOCK:
513 		ut_call_record_param_ptr(fsdev_io->u_in.flock.fobject);
514 		ut_call_record_param_ptr(fsdev_io->u_in.flock.fhandle);
515 		ut_call_record_param_int(fsdev_io->u_in.flock.operation);
516 		break;
517 	case SPDK_FSDEV_IO_CREATE:
518 		ut_call_record_param_ptr(fsdev_io->u_in.create.parent_fobject);
519 		ut_call_record_param_str(fsdev_io->u_in.create.name);
520 		ut_call_record_param_int(fsdev_io->u_in.create.mode);
521 		ut_call_record_param_int(fsdev_io->u_in.create.flags);
522 		ut_call_record_param_int(fsdev_io->u_in.create.umask);
523 		ut_call_record_param_int(fsdev_io->u_in.create.euid);
524 		ut_call_record_param_int(fsdev_io->u_in.create.egid);
525 		fsdev_io->u_out.create.fobject = UT_FOBJECT + 1;
526 		fsdev_io->u_out.create.fhandle = UT_FHANDLE;
527 		fsdev_io->u_out.create.attr = ut_fsdev_attr;
528 		break;
529 	case SPDK_FSDEV_IO_ABORT:
530 		ut_call_record_param_int(fsdev_io->u_in.abort.unique_to_abort);
531 		break;
532 	case SPDK_FSDEV_IO_FALLOCATE:
533 		ut_call_record_param_ptr(fsdev_io->u_in.fallocate.fobject);
534 		ut_call_record_param_ptr(fsdev_io->u_in.fallocate.fhandle);
535 		ut_call_record_param_int(fsdev_io->u_in.fallocate.mode);
536 		ut_call_record_param_int(fsdev_io->u_in.fallocate.offset);
537 		ut_call_record_param_int(fsdev_io->u_in.fallocate.length);
538 		break;
539 	case SPDK_FSDEV_IO_COPY_FILE_RANGE:
540 		ut_call_record_param_ptr(fsdev_io->u_in.copy_file_range.fobject_in);
541 		ut_call_record_param_ptr(fsdev_io->u_in.copy_file_range.fhandle_in);
542 		ut_call_record_param_int(fsdev_io->u_in.copy_file_range.off_in);
543 		ut_call_record_param_ptr(fsdev_io->u_in.copy_file_range.fobject_out);
544 		ut_call_record_param_ptr(fsdev_io->u_in.copy_file_range.fhandle_out);
545 		ut_call_record_param_int(fsdev_io->u_in.copy_file_range.off_out);
546 		ut_call_record_param_int(fsdev_io->u_in.copy_file_range.len);
547 		ut_call_record_param_int(fsdev_io->u_in.copy_file_range.flags);
548 		fsdev_io->u_out.copy_file_range.data_size = UT_DATA_SIZE;
549 		break;
550 	case __SPDK_FSDEV_IO_LAST:
551 	default:
552 		break;
553 	}
554 
555 	ut_call_record_end();
556 
557 	spdk_fsdev_io_complete(fsdev_io, utfsdev->desired_io_status);
558 }
559 
560 static struct spdk_io_channel *
561 ut_fsdev_get_io_channel(void *ctx)
562 {
563 	ut_call_record_simple_param_ptr(ut_fsdev_get_io_channel, ctx);
564 
565 	return spdk_get_io_channel(&g_call_list);
566 }
567 
568 static void
569 ut_fsdev_write_config_json(struct spdk_fsdev *fsdev, struct spdk_json_write_ctx *w)
570 {
571 
572 }
573 
574 static int
575 ut_fsdev_get_memory_domains(void *ctx, struct spdk_memory_domain **domains,
576 			    int array_size)
577 {
578 	return 0;
579 }
580 
581 static const struct spdk_fsdev_fn_table ut_fdev_fn_table = {
582 	.destruct		= ut_fsdev_destruct,
583 	.submit_request		= ut_fsdev_submit_request,
584 	.get_io_channel		= ut_fsdev_get_io_channel,
585 	.write_config_json	= ut_fsdev_write_config_json,
586 	.get_memory_domains	= ut_fsdev_get_memory_domains,
587 };
588 
589 static void
590 ut_fsdev_free(struct ut_fsdev *ufsdev)
591 {
592 	free(ufsdev->fsdev.name);
593 	free(ufsdev);
594 }
595 
596 static void
597 ut_fsdev_unregister_done(void *cb_arg, int rc)
598 {
599 	struct ut_fsdev *ufsdev = cb_arg;
600 
601 	ut_call_record_simple_param_ptr(ut_fsdev_unregister_done, cb_arg);
602 
603 	ut_fsdev_free(ufsdev);
604 }
605 
606 static void
607 ut_fsdev_destroy(struct ut_fsdev *utfsdev)
608 {
609 	ut_calls_reset();
610 	spdk_fsdev_unregister(&utfsdev->fsdev, ut_fsdev_unregister_done, utfsdev);
611 	poll_thread(0);
612 
613 	CU_ASSERT(ut_calls_get_call_count() == 2);
614 
615 	CU_ASSERT(ut_calls_get_func(0) == ut_fsdev_destruct);
616 	CU_ASSERT(ut_calls_get_param_count(0) == 1);
617 	CU_ASSERT(ut_calls_param_get_ptr(0, 0) == utfsdev);
618 
619 	CU_ASSERT(ut_calls_get_func(1) == ut_fsdev_unregister_done);
620 	CU_ASSERT(ut_calls_get_param_count(1) == 1);
621 	CU_ASSERT(ut_calls_param_get_ptr(1, 0) == utfsdev);
622 }
623 
624 static struct ut_fsdev *
625 ut_fsdev_create(const char *name)
626 {
627 	struct ut_fsdev *ufsdev;
628 	int rc;
629 
630 	ufsdev = calloc(1, sizeof(*ufsdev));
631 	if (!ufsdev) {
632 		SPDK_ERRLOG("Could not allocate ut_fsdev\n");
633 		return NULL;
634 	}
635 
636 	ufsdev->fsdev.name = strdup(name);
637 	if (!ufsdev->fsdev.name) {
638 		SPDK_ERRLOG("Could not strdup name %s\n", name);
639 		free(ufsdev);
640 		return NULL;
641 	}
642 
643 	ufsdev->fsdev.ctxt = ufsdev;
644 	ufsdev->fsdev.fn_table = &ut_fdev_fn_table;
645 	ufsdev->fsdev.module = &ut_fsdev_module;
646 
647 	rc = spdk_fsdev_register(&ufsdev->fsdev);
648 	if (rc) {
649 		ut_fsdev_free(ufsdev);
650 		return NULL;
651 	}
652 
653 	return ufsdev;
654 }
655 
656 static void
657 ut_fsdev_initialize_complete(void *cb_arg, int rc)
658 {
659 	bool *completed  = cb_arg;
660 
661 	*completed = true;
662 }
663 
664 static int
665 ut_fsdev_setup(void)
666 {
667 	bool completed = false;
668 
669 	spdk_fsdev_initialize(ut_fsdev_initialize_complete, &completed);
670 
671 	poll_thread(0);
672 
673 	if (!completed) {
674 		SPDK_ERRLOG("No spdk_fsdev_initialize callback arrived\n");
675 		return EINVAL;
676 	}
677 
678 	return 0;
679 }
680 
681 static void
682 ut_fsdev_teardown_complete(void *cb_arg)
683 {
684 	bool *completed  = cb_arg;
685 
686 	*completed = true;
687 }
688 
689 static int
690 ut_fsdev_teardown(void)
691 {
692 	bool completed = false;
693 	spdk_fsdev_finish(ut_fsdev_teardown_complete, &completed);
694 
695 	poll_thread(0);
696 
697 	if (!completed) {
698 		SPDK_ERRLOG("No spdk_fsdev_finish callback arrived\n");
699 		return EINVAL;
700 	}
701 
702 	return 0;
703 }
704 
705 static void
706 fsdev_event_cb(enum spdk_fsdev_event_type type, struct spdk_fsdev *fsdev,
707 	       void *event_ctx)
708 {
709 	SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
710 }
711 
712 static void
713 ut_fsdev_test_open_close(void)
714 {
715 	struct ut_fsdev *utfsdev;
716 	struct spdk_fsdev_desc *fsdev_desc;
717 	int rc;
718 
719 	utfsdev = ut_fsdev_create("utfsdev0");
720 	CU_ASSERT(utfsdev != NULL);
721 
722 	CU_ASSERT(!strcmp(spdk_fsdev_get_module_name(&utfsdev->fsdev), ut_fsdev_module.name));
723 	CU_ASSERT(!strcmp(spdk_fsdev_get_name(&utfsdev->fsdev), "utfsdev0"));
724 
725 	ut_calls_reset();
726 	rc = spdk_fsdev_open("utfsdev0", fsdev_event_cb, NULL, &fsdev_desc);
727 	CU_ASSERT(rc == 0);
728 	CU_ASSERT(fsdev_desc != NULL);
729 	CU_ASSERT(spdk_fsdev_desc_get_fsdev(fsdev_desc) == &utfsdev->fsdev);
730 
731 	if (fsdev_desc) {
732 		spdk_fsdev_close(fsdev_desc);
733 	}
734 
735 	ut_fsdev_destroy(utfsdev);
736 }
737 
738 static void
739 ut_fsdev_test_set_opts(void)
740 {
741 	struct spdk_fsdev_opts old_opts;
742 	struct spdk_fsdev_opts new_opts;
743 	int rc;
744 
745 	rc = spdk_fsdev_set_opts(NULL);
746 	CU_ASSERT(rc == -EINVAL);
747 
748 	new_opts.opts_size = 0;
749 	rc = spdk_fsdev_set_opts(&new_opts);
750 	CU_ASSERT(rc == -EINVAL);
751 
752 	old_opts.opts_size = sizeof(old_opts);
753 	rc = spdk_fsdev_get_opts(&old_opts, sizeof(old_opts));
754 	CU_ASSERT(rc == 0);
755 
756 	new_opts.opts_size = sizeof(new_opts);
757 	new_opts.fsdev_io_pool_size = old_opts.fsdev_io_pool_size * 2;
758 	new_opts.fsdev_io_cache_size = old_opts.fsdev_io_cache_size * 2;
759 	rc = spdk_fsdev_set_opts(&new_opts);
760 	CU_ASSERT(rc == 0);
761 
762 	rc = spdk_fsdev_get_opts(&new_opts, sizeof(new_opts));
763 	CU_ASSERT(rc == 0);
764 	CU_ASSERT(old_opts.fsdev_io_pool_size * 2 == new_opts.fsdev_io_pool_size);
765 	CU_ASSERT(old_opts.fsdev_io_cache_size * 2 == new_opts.fsdev_io_cache_size);
766 }
767 
768 static void
769 ut_fsdev_test_get_io_channel(void)
770 {
771 	struct ut_fsdev *utfsdev;
772 	struct spdk_io_channel *ch;
773 	struct spdk_fsdev_desc *fsdev_desc;
774 	struct ut_io_channel *ut_ch;
775 	int rc;
776 
777 	utfsdev = ut_fsdev_create("utfsdev0");
778 	CU_ASSERT(utfsdev != NULL);
779 
780 	rc = spdk_fsdev_open("utfsdev0", fsdev_event_cb, NULL, &fsdev_desc);
781 	CU_ASSERT(rc == 0);
782 	CU_ASSERT(fsdev_desc != NULL);
783 	CU_ASSERT(spdk_fsdev_desc_get_fsdev(fsdev_desc) == &utfsdev->fsdev);
784 
785 	ut_calls_reset();
786 	ch = spdk_fsdev_get_io_channel(fsdev_desc);
787 	CU_ASSERT(ch != NULL);
788 	CU_ASSERT(ut_calls_get_call_count() == 2);
789 
790 	CU_ASSERT(ut_calls_get_func(0) == ut_fsdev_get_io_channel);
791 	CU_ASSERT(ut_calls_get_param_count(0) == 1);
792 	CU_ASSERT(ut_calls_param_get_ptr(0, 0) == utfsdev);
793 
794 	CU_ASSERT(ut_calls_get_func(1) == ut_fsdev_io_channel_create_cb);
795 	CU_ASSERT(ut_calls_get_param_count(1) == 1);
796 	ut_ch = (struct ut_io_channel *)ut_calls_param_get_ptr(1, 0);
797 
798 	ut_calls_reset();
799 	spdk_put_io_channel(ch);
800 	poll_thread(0);
801 	CU_ASSERT(ut_calls_get_call_count() == 1);
802 
803 	CU_ASSERT(ut_calls_get_func(0) == ut_fsdev_io_channel_destroy_cb);
804 	CU_ASSERT(ut_calls_get_param_count(0) == 1);
805 	CU_ASSERT(ut_calls_param_get_ptr(0, 0) == ut_ch);
806 
807 	spdk_fsdev_close(fsdev_desc);
808 
809 	ut_fsdev_destroy(utfsdev);
810 }
811 
812 typedef int (*execute_clb)(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
813 			   struct spdk_fsdev_desc *fsdev_desc, int *status);
814 typedef void (*check_clb)(void);
815 
816 static void
817 ut_fsdev_test_io(enum spdk_fsdev_io_type type, int desired_io_status, size_t num_priv_params,
818 		 execute_clb execute_cb, check_clb check_cb)
819 {
820 	struct ut_fsdev *utfsdev;
821 	struct spdk_io_channel *ch;
822 	struct spdk_fsdev_desc *fsdev_desc;
823 	int rc;
824 	int status = -1;
825 
826 	utfsdev = ut_fsdev_create("utfsdev0");
827 	CU_ASSERT(utfsdev != NULL);
828 
829 	rc = spdk_fsdev_open("utfsdev0", fsdev_event_cb, NULL, &fsdev_desc);
830 	CU_ASSERT(rc == 0);
831 	CU_ASSERT(fsdev_desc != NULL);
832 
833 	ch = spdk_fsdev_get_io_channel(fsdev_desc);
834 	CU_ASSERT(ch != NULL);
835 
836 	ut_calls_reset();
837 	utfsdev->desired_io_status = desired_io_status;
838 	rc = execute_cb(utfsdev, ch, fsdev_desc, &status);
839 	CU_ASSERT(rc == 0);
840 
841 	poll_thread(0);
842 	CU_ASSERT(status == desired_io_status);
843 	CU_ASSERT(ut_calls_get_call_count() == 1);
844 	CU_ASSERT(ut_calls_get_func(0) == ut_fsdev_submit_request);
845 	CU_ASSERT(ut_calls_get_param_count(0) == UT_SUBMIT_IO_NUM_COMMON_PARAMS + num_priv_params);
846 
847 	/* Common params */
848 	CU_ASSERT(ut_calls_param_get_int(0, 0) == type);
849 	CU_ASSERT(ut_calls_param_get_int(0, 1) == UT_UNIQUE);
850 	CU_ASSERT(ut_calls_param_get_ptr(0, 2) == g_ut_io_channel);
851 	CU_ASSERT(ut_calls_param_get_ptr(0, 3) == utfsdev);
852 
853 	SPDK_CU_ASSERT_FATAL(UT_SUBMIT_IO_NUM_COMMON_PARAMS == 4);
854 
855 	/* Op-specific params */
856 	check_cb();
857 
858 	ut_calls_reset();
859 	spdk_put_io_channel(ch);
860 	poll_thread(0);
861 
862 	spdk_fsdev_close(fsdev_desc);
863 
864 	ut_fsdev_destroy(utfsdev);
865 }
866 
867 static void
868 ut_fsdev_mount_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
869 		      const struct spdk_fsdev_mount_opts *opts, struct spdk_fsdev_file_object *root_fobject)
870 
871 {
872 	int *clb_status = cb_arg;
873 	*clb_status = status;
874 	if (!status) {
875 		CU_ASSERT(root_fobject == UT_FOBJECT);
876 		CU_ASSERT(opts != NULL);
877 		CU_ASSERT(opts->opts_size == ut_mount_opts.opts_size);
878 		CU_ASSERT(opts->max_write == ut_mount_opts.max_write / 2);
879 		CU_ASSERT(opts->writeback_cache_enabled == !ut_mount_opts.writeback_cache_enabled);
880 	}
881 }
882 
883 static int
884 ut_fsdev_mount_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
885 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
886 {
887 	memset(&ut_mount_opts, 0, sizeof(ut_mount_opts));
888 	ut_mount_opts.opts_size = sizeof(ut_mount_opts);
889 	ut_mount_opts.max_write = UINT32_MAX;
890 	ut_mount_opts.writeback_cache_enabled = true;
891 
892 	return spdk_fsdev_mount(fsdev_desc, ch, UT_UNIQUE, &ut_mount_opts, ut_fsdev_mount_cpl_cb, status);
893 }
894 
895 static void
896 ut_fsdev_mount_check_clb(void)
897 {
898 	CU_ASSERT(ut_calls_param_get_hash(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) ==
899 		  ut_hash(&ut_mount_opts, sizeof(ut_mount_opts)));
900 }
901 
902 static void
903 ut_fsdev_test_mount_ok(void)
904 {
905 	ut_fsdev_test_io(SPDK_FSDEV_IO_MOUNT, 0, 1, ut_fsdev_mount_execute_clb,
906 			 ut_fsdev_mount_check_clb);
907 }
908 
909 static void
910 ut_fsdev_test_mount_err(void)
911 {
912 	ut_fsdev_test_io(SPDK_FSDEV_IO_MOUNT, -EINVAL, 1, ut_fsdev_mount_execute_clb,
913 			 ut_fsdev_mount_check_clb);
914 }
915 
916 static void
917 ut_fsdev_umount_cpl_cb(void *cb_arg, struct spdk_io_channel *ch)
918 {
919 	int *clb_status = cb_arg;
920 	*clb_status = 0; /* the callback doesn't get status, so we just zero it here */
921 }
922 
923 static int
924 ut_fsdev_umount_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
925 			    struct spdk_fsdev_desc *fsdev_desc, int *status)
926 {
927 	return spdk_fsdev_umount(fsdev_desc, ch, UT_UNIQUE, ut_fsdev_umount_cpl_cb, status);
928 }
929 
930 static void
931 ut_fsdev_umount_check_clb(void)
932 {
933 	/* Nothing to check here */
934 }
935 
936 static void
937 ut_fsdev_test_umount(void)
938 {
939 	ut_fsdev_test_io(SPDK_FSDEV_IO_UMOUNT, 0, 0, ut_fsdev_umount_execute_clb,
940 			 ut_fsdev_umount_check_clb);
941 }
942 
943 static void
944 ut_fsdev_lookup_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
945 		       struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
946 {
947 	int *clb_status = cb_arg;
948 	*clb_status = status;
949 	if (!status) {
950 		CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
951 		CU_ASSERT(&ut_fsdev_fobject == fobject);
952 	}
953 }
954 
955 static int
956 ut_fsdev_lookup_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
957 			    struct spdk_fsdev_desc *fsdev_desc, int *status)
958 {
959 	return spdk_fsdev_lookup(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FNAME,
960 				 ut_fsdev_lookup_cpl_cb,
961 				 status);
962 }
963 
964 static void
965 ut_fsdev_lookup_check_clb(void)
966 {
967 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS), UT_FNAME,
968 			   UT_CALL_REC_MAX_STR_SIZE));
969 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FOBJECT);
970 }
971 
972 static void
973 ut_fsdev_test_lookup_ok(void)
974 {
975 	ut_fsdev_test_io(SPDK_FSDEV_IO_LOOKUP, 0, 2, ut_fsdev_lookup_execute_clb,
976 			 ut_fsdev_lookup_check_clb);
977 }
978 
979 static void
980 ut_fsdev_test_lookup_err(void)
981 {
982 	ut_fsdev_test_io(SPDK_FSDEV_IO_LOOKUP, -EBUSY, 2, ut_fsdev_lookup_execute_clb,
983 			 ut_fsdev_lookup_check_clb);
984 }
985 
986 static void
987 ut_fsdev_forget_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
988 {
989 	int *clb_status = cb_arg;
990 	*clb_status = status;
991 }
992 
993 static int
994 ut_fsdev_forget_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
995 			    struct spdk_fsdev_desc *fsdev_desc, int *status)
996 {
997 	return spdk_fsdev_forget(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_NUM_LOOKUPS,
998 				 ut_fsdev_forget_cpl_cb, status);
999 }
1000 
1001 static void
1002 ut_fsdev_forget_check_clb(void)
1003 {
1004 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1005 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_NUM_LOOKUPS);
1006 }
1007 
1008 static void
1009 ut_fsdev_test_forget(void)
1010 {
1011 	ut_fsdev_test_io(SPDK_FSDEV_IO_FORGET, 0, 2, ut_fsdev_forget_execute_clb,
1012 			 ut_fsdev_forget_check_clb);
1013 }
1014 
1015 static void
1016 ut_fsdev_getattr_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1017 			const struct spdk_fsdev_file_attr *attr)
1018 {
1019 	int *clb_status = cb_arg;
1020 	*clb_status = status;
1021 }
1022 
1023 static int
1024 ut_fsdev_getattr_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1025 			     struct spdk_fsdev_desc *fsdev_desc, int *status)
1026 {
1027 	return spdk_fsdev_getattr(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE,
1028 				  ut_fsdev_getattr_cpl_cb, status);
1029 }
1030 
1031 static void
1032 ut_fsdev_getattr_check_clb(void)
1033 {
1034 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1035 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1036 }
1037 
1038 static void
1039 ut_fsdev_test_getattr(void)
1040 {
1041 	ut_fsdev_test_io(SPDK_FSDEV_IO_GETATTR, 0, 2, ut_fsdev_getattr_execute_clb,
1042 			 ut_fsdev_getattr_check_clb);
1043 }
1044 
1045 static void
1046 ut_fsdev_setattr_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1047 			const struct spdk_fsdev_file_attr *attr)
1048 {
1049 	int *clb_status = cb_arg;
1050 	CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
1051 	*clb_status = status;
1052 }
1053 
1054 static int
1055 ut_fsdev_setattr_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1056 			     struct spdk_fsdev_desc *fsdev_desc, int *status)
1057 {
1058 	memset(&ut_fsdev_attr, rand(), sizeof(ut_fsdev_attr));
1059 	return spdk_fsdev_setattr(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE,
1060 				  &ut_fsdev_attr, 0x11111111, ut_fsdev_setattr_cpl_cb, status);
1061 }
1062 
1063 static void
1064 ut_fsdev_setattr_check_clb(void)
1065 {
1066 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1067 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1068 	CU_ASSERT(ut_calls_param_get_hash(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) ==
1069 		  ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)));
1070 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 0x11111111);
1071 }
1072 
1073 static void
1074 ut_fsdev_test_setattr(void)
1075 {
1076 	ut_fsdev_test_io(SPDK_FSDEV_IO_SETATTR, 0, 4, ut_fsdev_setattr_execute_clb,
1077 			 ut_fsdev_setattr_check_clb);
1078 }
1079 
1080 static void
1081 ut_fsdev_readlink_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1082 			 const char *linkname)
1083 {
1084 	int *clb_status = cb_arg;
1085 	CU_ASSERT(!strcmp(linkname, UT_FNAME));
1086 	*clb_status = status;
1087 }
1088 
1089 static int
1090 ut_fsdev_readlink_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1091 			      struct spdk_fsdev_desc *fsdev_desc, int *status)
1092 {
1093 	return spdk_fsdev_readlink(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, ut_fsdev_readlink_cpl_cb,
1094 				   status);
1095 }
1096 
1097 static void
1098 ut_fsdev_readlink_check_clb(void)
1099 {
1100 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1101 }
1102 
1103 static void
1104 ut_fsdev_test_readlink(void)
1105 {
1106 	ut_fsdev_test_io(SPDK_FSDEV_IO_READLINK, 0, 1, ut_fsdev_readlink_execute_clb,
1107 			 ut_fsdev_readlink_check_clb);
1108 }
1109 
1110 static void
1111 ut_fsdev_symlink_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1112 			struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
1113 {
1114 	int *clb_status = cb_arg;
1115 	CU_ASSERT(fobject == UT_FOBJECT + 1);
1116 	CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
1117 	*clb_status = status;
1118 }
1119 
1120 static int
1121 ut_fsdev_symlink_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1122 			     struct spdk_fsdev_desc *fsdev_desc, int *status)
1123 {
1124 	memset(&ut_fsdev_attr, rand(), sizeof(ut_fsdev_attr));
1125 	return spdk_fsdev_symlink(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FNAME, UT_LNAME, 100, 200,
1126 				  ut_fsdev_symlink_cpl_cb, status);
1127 }
1128 
1129 static void
1130 ut_fsdev_symlink_check_clb(void)
1131 {
1132 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1133 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_FNAME,
1134 			   UT_CALL_REC_MAX_STR_SIZE));
1135 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2), UT_LNAME,
1136 			   UT_CALL_REC_MAX_STR_SIZE));
1137 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 100);
1138 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 200);
1139 }
1140 
1141 static void
1142 ut_fsdev_test_symlink(void)
1143 {
1144 	ut_fsdev_test_io(SPDK_FSDEV_IO_SYMLINK, 0, 5, ut_fsdev_symlink_execute_clb,
1145 			 ut_fsdev_symlink_check_clb);
1146 }
1147 
1148 static void
1149 ut_fsdev_mknod_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1150 		      struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
1151 {
1152 	int *clb_status = cb_arg;
1153 	CU_ASSERT(fobject == UT_FOBJECT + 1);
1154 	CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
1155 	*clb_status = status;
1156 }
1157 
1158 static int
1159 ut_fsdev_mknod_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1160 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1161 {
1162 	memset(&ut_fsdev_attr, rand(), sizeof(ut_fsdev_attr));
1163 	return spdk_fsdev_mknod(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FNAME, 0x1111, 50, 100, 200,
1164 				ut_fsdev_mknod_cpl_cb, status);
1165 }
1166 
1167 static void
1168 ut_fsdev_mknod_check_clb(void)
1169 {
1170 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1171 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_FNAME,
1172 			   UT_CALL_REC_MAX_STR_SIZE));
1173 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 0x1111);
1174 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 50);
1175 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 100);
1176 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 5) == 200);
1177 }
1178 
1179 static void
1180 ut_fsdev_test_mknod(void)
1181 {
1182 	ut_fsdev_test_io(SPDK_FSDEV_IO_MKNOD, 0, 6, ut_fsdev_mknod_execute_clb,
1183 			 ut_fsdev_mknod_check_clb);
1184 }
1185 
1186 static void
1187 ut_fsdev_mkdir_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1188 		      struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
1189 {
1190 	int *clb_status = cb_arg;
1191 	CU_ASSERT(fobject == UT_FOBJECT + 1);
1192 	CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
1193 	*clb_status = status;
1194 }
1195 
1196 static int
1197 ut_fsdev_mkdir_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1198 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1199 {
1200 	memset(&ut_fsdev_attr, rand(), sizeof(ut_fsdev_attr));
1201 	return spdk_fsdev_mkdir(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FNAME, 0x1111, 100, 200,
1202 				ut_fsdev_mkdir_cpl_cb, status);
1203 }
1204 
1205 static void
1206 ut_fsdev_mkdir_check_clb(void)
1207 {
1208 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1209 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_FNAME,
1210 			   UT_CALL_REC_MAX_STR_SIZE));
1211 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 0x1111);
1212 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 100);
1213 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 200);
1214 }
1215 
1216 static void
1217 ut_fsdev_test_mkdir(void)
1218 {
1219 	ut_fsdev_test_io(SPDK_FSDEV_IO_MKDIR, 0, 5, ut_fsdev_mkdir_execute_clb,
1220 			 ut_fsdev_mkdir_check_clb);
1221 }
1222 
1223 static void
1224 ut_fsdev_unlink_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1225 {
1226 	int *clb_status = cb_arg;
1227 	*clb_status = status;
1228 }
1229 
1230 static int
1231 ut_fsdev_unlink_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1232 			    struct spdk_fsdev_desc *fsdev_desc, int *status)
1233 {
1234 	return spdk_fsdev_unlink(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FNAME,
1235 				 ut_fsdev_unlink_cpl_cb, status);
1236 }
1237 
1238 static void
1239 ut_fsdev_unlink_check_clb(void)
1240 {
1241 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1242 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_FNAME,
1243 			   UT_CALL_REC_MAX_STR_SIZE));
1244 }
1245 
1246 static void
1247 ut_fsdev_test_unlink(void)
1248 {
1249 	ut_fsdev_test_io(SPDK_FSDEV_IO_UNLINK, 0, 2, ut_fsdev_unlink_execute_clb,
1250 			 ut_fsdev_unlink_check_clb);
1251 }
1252 
1253 static void
1254 ut_fsdev_rmdir_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1255 {
1256 	int *clb_status = cb_arg;
1257 	*clb_status = status;
1258 }
1259 
1260 static int
1261 ut_fsdev_rmdir_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1262 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1263 {
1264 	return spdk_fsdev_rmdir(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FNAME,
1265 				ut_fsdev_rmdir_cpl_cb, status);
1266 }
1267 
1268 static void
1269 ut_fsdev_rmdir_check_clb(void)
1270 {
1271 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1272 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_FNAME,
1273 			   UT_CALL_REC_MAX_STR_SIZE));
1274 }
1275 
1276 static void
1277 ut_fsdev_test_rmdir(void)
1278 {
1279 	ut_fsdev_test_io(SPDK_FSDEV_IO_RMDIR, 0, 2, ut_fsdev_rmdir_execute_clb,
1280 			 ut_fsdev_rmdir_check_clb);
1281 }
1282 
1283 static void
1284 ut_fsdev_rename_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1285 {
1286 	int *clb_status = cb_arg;
1287 	*clb_status = status;
1288 }
1289 
1290 static int
1291 ut_fsdev_rename_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1292 			    struct spdk_fsdev_desc *fsdev_desc, int *status)
1293 {
1294 	return spdk_fsdev_rename(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FNAME, UT_FOBJECT + 2,
1295 				 UT_LNAME, 0xFFFF, ut_fsdev_rename_cpl_cb, status);
1296 }
1297 
1298 static void
1299 ut_fsdev_rename_check_clb(void)
1300 {
1301 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1302 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_FNAME,
1303 			   UT_CALL_REC_MAX_STR_SIZE));
1304 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == UT_FOBJECT + 2);
1305 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3), UT_LNAME,
1306 			   UT_CALL_REC_MAX_STR_SIZE));
1307 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 0xFFFF);
1308 }
1309 
1310 static void
1311 ut_fsdev_test_rename(void)
1312 {
1313 	ut_fsdev_test_io(SPDK_FSDEV_IO_RENAME, 0, 5, ut_fsdev_rename_execute_clb,
1314 			 ut_fsdev_rename_check_clb);
1315 }
1316 
1317 static void
1318 ut_fsdev_link_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1319 		     struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
1320 {
1321 	int *clb_status = cb_arg;
1322 	CU_ASSERT(fobject == UT_FOBJECT + 1);
1323 	CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
1324 	*clb_status = status;
1325 }
1326 
1327 static int
1328 ut_fsdev_link_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1329 			  struct spdk_fsdev_desc *fsdev_desc, int *status)
1330 {
1331 	return spdk_fsdev_link(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FOBJECT + 2, UT_LNAME,
1332 			       ut_fsdev_link_cpl_cb, status);
1333 }
1334 
1335 static void
1336 ut_fsdev_link_check_clb(void)
1337 {
1338 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1339 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FOBJECT + 2);
1340 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2), UT_LNAME,
1341 			   UT_CALL_REC_MAX_STR_SIZE));
1342 }
1343 
1344 static void
1345 ut_fsdev_test_link(void)
1346 {
1347 	ut_fsdev_test_io(SPDK_FSDEV_IO_LINK, 0, 3, ut_fsdev_link_execute_clb,
1348 			 ut_fsdev_link_check_clb);
1349 }
1350 
1351 static void
1352 ut_fsdev_fopen_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1353 		      struct spdk_fsdev_file_handle *fhandle)
1354 {
1355 	int *clb_status = cb_arg;
1356 	CU_ASSERT(fhandle == UT_FHANDLE);
1357 	*clb_status = status;
1358 }
1359 
1360 static int
1361 ut_fsdev_fopen_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1362 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1363 {
1364 	return spdk_fsdev_fopen(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, 0xFEAD,
1365 				ut_fsdev_fopen_cpl_cb, status);
1366 }
1367 
1368 static void
1369 ut_fsdev_fopen_check_clb(void)
1370 {
1371 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1372 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == 0xFEAD);
1373 }
1374 
1375 static void
1376 ut_fsdev_test_fopen(void)
1377 {
1378 	ut_fsdev_test_io(SPDK_FSDEV_IO_OPEN, 0, 2, ut_fsdev_fopen_execute_clb,
1379 			 ut_fsdev_fopen_check_clb);
1380 }
1381 
1382 static void
1383 ut_fsdev_read_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1384 		     uint32_t data_size)
1385 {
1386 	int *clb_status = cb_arg;
1387 	CU_ASSERT(data_size == UT_DATA_SIZE);
1388 	*clb_status = status;
1389 }
1390 
1391 static int
1392 ut_fsdev_read_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1393 			  struct spdk_fsdev_desc *fsdev_desc, int *status)
1394 {
1395 	memset(&ut_iov, rand(), sizeof(ut_iov));
1396 	return spdk_fsdev_read(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, 100, 200, 0x1111,
1397 			       ut_iov, SPDK_COUNTOF(ut_iov), (struct spdk_fsdev_io_opts *)0xAAAAAAAA,
1398 			       ut_fsdev_read_cpl_cb, status);
1399 }
1400 
1401 static void
1402 ut_fsdev_read_check_clb(void)
1403 {
1404 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1405 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1406 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 100);
1407 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 200);
1408 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 0x1111);
1409 	CU_ASSERT(ut_calls_param_get_hash(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 5) == ut_hash(ut_iov,
1410 			sizeof(ut_iov)));
1411 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 6) == SPDK_COUNTOF(ut_iov));
1412 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 7) == 0xAAAAAAAA);
1413 }
1414 
1415 static void
1416 ut_fsdev_test_read(void)
1417 {
1418 	ut_fsdev_test_io(SPDK_FSDEV_IO_READ, 0, 8, ut_fsdev_read_execute_clb,
1419 			 ut_fsdev_read_check_clb);
1420 }
1421 
1422 static void
1423 ut_fsdev_write_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1424 		      uint32_t data_size)
1425 {
1426 	int *clb_status = cb_arg;
1427 	CU_ASSERT(data_size == UT_DATA_SIZE);
1428 	*clb_status = status;
1429 }
1430 
1431 static int
1432 ut_fsdev_write_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1433 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1434 {
1435 	memset(&ut_iov, rand(), sizeof(ut_iov));
1436 	return spdk_fsdev_write(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, 100, 200, 0x1111,
1437 				ut_iov, SPDK_COUNTOF(ut_iov), (struct spdk_fsdev_io_opts *)0xAAAAAAAA,
1438 				ut_fsdev_write_cpl_cb, status);
1439 }
1440 
1441 static void
1442 ut_fsdev_write_check_clb(void)
1443 {
1444 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1445 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1446 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 100);
1447 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 200);
1448 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 0x1111);
1449 	CU_ASSERT(ut_calls_param_get_hash(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 5) ==
1450 		  ut_hash(ut_iov, sizeof(ut_iov)));
1451 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 6) == SPDK_COUNTOF(ut_iov));
1452 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 7) == 0xAAAAAAAA);
1453 }
1454 
1455 static void
1456 ut_fsdev_test_write(void)
1457 {
1458 	ut_fsdev_test_io(SPDK_FSDEV_IO_WRITE, 0, 8, ut_fsdev_write_execute_clb,
1459 			 ut_fsdev_write_check_clb);
1460 }
1461 
1462 static void
1463 ut_fsdev_statfs_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1464 		       const struct spdk_fsdev_file_statfs *statfs)
1465 {
1466 	int *clb_status = cb_arg;
1467 	CU_ASSERT(ut_hash(&ut_statfs, sizeof(ut_statfs)) == ut_hash(statfs, sizeof(*statfs)));
1468 	*clb_status = status;
1469 }
1470 
1471 static int
1472 ut_fsdev_statfs_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1473 			    struct spdk_fsdev_desc *fsdev_desc, int *status)
1474 {
1475 	memset(&ut_statfs, rand(), sizeof(ut_statfs));
1476 	return spdk_fsdev_statfs(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT,
1477 				 ut_fsdev_statfs_cpl_cb, status);
1478 }
1479 
1480 static void
1481 ut_fsdev_statfs_check_clb(void)
1482 {
1483 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1484 }
1485 
1486 static void
1487 ut_fsdev_test_statfs(void)
1488 {
1489 	ut_fsdev_test_io(SPDK_FSDEV_IO_STATFS, 0, 1, ut_fsdev_statfs_execute_clb,
1490 			 ut_fsdev_statfs_check_clb);
1491 }
1492 
1493 static void
1494 ut_fsdev_release_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1495 {
1496 	int *clb_status = cb_arg;
1497 	*clb_status = status;
1498 }
1499 
1500 static int
1501 ut_fsdev_release_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1502 			     struct spdk_fsdev_desc *fsdev_desc, int *status)
1503 {
1504 	return spdk_fsdev_release(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE,
1505 				  ut_fsdev_release_cpl_cb, status);
1506 }
1507 
1508 static void
1509 ut_fsdev_release_check_clb(void)
1510 {
1511 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1512 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1513 }
1514 
1515 static void
1516 ut_fsdev_test_release(void)
1517 {
1518 	ut_fsdev_test_io(SPDK_FSDEV_IO_RELEASE, 0, 2, ut_fsdev_release_execute_clb,
1519 			 ut_fsdev_release_check_clb);
1520 }
1521 
1522 static void
1523 ut_fsdev_fsync_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1524 {
1525 	int *clb_status = cb_arg;
1526 	*clb_status = status;
1527 }
1528 
1529 static int
1530 ut_fsdev_fsync_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1531 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1532 {
1533 	return spdk_fsdev_fsync(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, false,
1534 				ut_fsdev_fsync_cpl_cb, status);
1535 }
1536 
1537 static void
1538 ut_fsdev_fsync_check_clb(void)
1539 {
1540 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1541 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1542 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == false);
1543 }
1544 
1545 static void
1546 ut_fsdev_test_fsync(void)
1547 {
1548 	ut_fsdev_test_io(SPDK_FSDEV_IO_FSYNC, 0, 3, ut_fsdev_fsync_execute_clb,
1549 			 ut_fsdev_fsync_check_clb);
1550 }
1551 
1552 static void
1553 ut_fsdev_getxattr_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1554 			 size_t value_size)
1555 {
1556 	int *clb_status = cb_arg;
1557 	CU_ASSERT(value_size == sizeof(UT_AVALUE));
1558 	CU_ASSERT(!strcmp(ut_buff, UT_AVALUE));
1559 	*clb_status = status;
1560 }
1561 
1562 static int
1563 ut_fsdev_getxattr_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1564 			      struct spdk_fsdev_desc *fsdev_desc, int *status)
1565 {
1566 	memset(ut_buff, 0, sizeof(ut_buff));
1567 	return spdk_fsdev_getxattr(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_ANAME, ut_buff,
1568 				   sizeof(ut_buff), ut_fsdev_getxattr_cpl_cb, status);
1569 }
1570 
1571 static void
1572 ut_fsdev_getxattr_check_clb(void)
1573 {
1574 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1575 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_ANAME,
1576 			   UT_CALL_REC_MAX_STR_SIZE));
1577 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == ut_buff);
1578 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == sizeof(ut_buff));
1579 }
1580 
1581 static void
1582 ut_fsdev_test_getxattr(void)
1583 {
1584 	ut_fsdev_test_io(SPDK_FSDEV_IO_GETXATTR, 0, 4, ut_fsdev_getxattr_execute_clb,
1585 			 ut_fsdev_getxattr_check_clb);
1586 }
1587 
1588 static void
1589 ut_fsdev_setxattr_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1590 {
1591 	int *clb_status = cb_arg;
1592 	*clb_status = status;
1593 }
1594 
1595 static int
1596 ut_fsdev_setxattr_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1597 			      struct spdk_fsdev_desc *fsdev_desc, int *status)
1598 {
1599 	return spdk_fsdev_setxattr(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_ANAME, UT_AVALUE,
1600 				   sizeof(UT_AVALUE), 0xFF, ut_fsdev_setxattr_cpl_cb, status);
1601 }
1602 
1603 static void
1604 ut_fsdev_setxattr_check_clb(void)
1605 {
1606 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1607 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_ANAME,
1608 			   UT_CALL_REC_MAX_STR_SIZE));
1609 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2), UT_AVALUE,
1610 			   UT_CALL_REC_MAX_STR_SIZE));
1611 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == sizeof(UT_AVALUE));
1612 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 0xFF);
1613 }
1614 
1615 static void
1616 ut_fsdev_test_setxattr(void)
1617 {
1618 	ut_fsdev_test_io(SPDK_FSDEV_IO_SETXATTR, 0, 5, ut_fsdev_setxattr_execute_clb,
1619 			 ut_fsdev_setxattr_check_clb);
1620 }
1621 
1622 static void
1623 ut_fsdev_listxattr_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status, size_t size,
1624 			  bool size_only)
1625 {
1626 	int *clb_status = cb_arg;
1627 	if (ut_listxattr_size_only) {
1628 		CU_ASSERT(size_only);
1629 		CU_ASSERT(size == (sizeof(ut_buff) / sizeof(UT_ANAME)) * sizeof(UT_ANAME));
1630 	} else {
1631 		char *p = ut_buff;
1632 
1633 		CU_ASSERT(!size_only);
1634 		CU_ASSERT(size != 0);
1635 
1636 		for (; p + sizeof(UT_ANAME) <= ut_buff + size; p += sizeof(UT_ANAME)) {
1637 			CU_ASSERT(!strcmp(p, UT_ANAME));
1638 		}
1639 
1640 		CU_ASSERT(size + sizeof(UT_ANAME) > sizeof(ut_buff));
1641 	}
1642 	*clb_status = status;
1643 }
1644 
1645 static int
1646 ut_fsdev_listxattr_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1647 			       struct spdk_fsdev_desc *fsdev_desc, int *status)
1648 {
1649 	return spdk_fsdev_listxattr(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT,
1650 				    ut_listxattr_size_only ? NULL : ut_buff, ut_listxattr_size_only ? 0 : sizeof(ut_buff),
1651 				    ut_fsdev_listxattr_cpl_cb, status);
1652 }
1653 
1654 static void
1655 ut_fsdev_listxattr_check_clb(void)
1656 {
1657 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1658 	if (ut_listxattr_size_only) {
1659 		CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == NULL);
1660 		CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 0);
1661 	} else {
1662 		CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == ut_buff);
1663 		CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == sizeof(ut_buff));
1664 	}
1665 }
1666 
1667 static void
1668 ut_fsdev_test_listxattr(void)
1669 {
1670 	ut_listxattr_size_only = false;
1671 	ut_fsdev_test_io(SPDK_FSDEV_IO_LISTXATTR, 0, 3, ut_fsdev_listxattr_execute_clb,
1672 			 ut_fsdev_listxattr_check_clb);
1673 }
1674 
1675 static void
1676 ut_fsdev_test_listxattr_get_size(void)
1677 {
1678 	ut_listxattr_size_only = true;
1679 	ut_fsdev_test_io(SPDK_FSDEV_IO_LISTXATTR, 0, 3, ut_fsdev_listxattr_execute_clb,
1680 			 ut_fsdev_listxattr_check_clb);
1681 }
1682 
1683 static void
1684 ut_fsdev_removexattr_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1685 {
1686 	int *clb_status = cb_arg;
1687 	*clb_status = status;
1688 }
1689 
1690 static int
1691 ut_fsdev_removexattr_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1692 				 struct spdk_fsdev_desc *fsdev_desc, int *status)
1693 {
1694 	return spdk_fsdev_removexattr(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_ANAME,
1695 				      ut_fsdev_removexattr_cpl_cb, status);
1696 }
1697 
1698 static void
1699 ut_fsdev_removexattr_check_clb(void)
1700 {
1701 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1702 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_ANAME,
1703 			   UT_CALL_REC_MAX_STR_SIZE));
1704 }
1705 
1706 static void
1707 ut_fsdev_test_removexattr(void)
1708 {
1709 	ut_fsdev_test_io(SPDK_FSDEV_IO_REMOVEXATTR, 0, 2, ut_fsdev_removexattr_execute_clb,
1710 			 ut_fsdev_removexattr_check_clb);
1711 }
1712 
1713 static void
1714 ut_fsdev_flush_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1715 {
1716 	int *clb_status = cb_arg;
1717 	*clb_status = status;
1718 }
1719 
1720 static int
1721 ut_fsdev_flush_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1722 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1723 {
1724 	return spdk_fsdev_flush(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE,
1725 				ut_fsdev_flush_cpl_cb, status);
1726 }
1727 
1728 static void
1729 ut_fsdev_flush_check_clb(void)
1730 {
1731 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1732 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1733 }
1734 
1735 static void
1736 ut_fsdev_test_flush(void)
1737 {
1738 	ut_fsdev_test_io(SPDK_FSDEV_IO_FLUSH, 0, 2, ut_fsdev_flush_execute_clb,
1739 			 ut_fsdev_flush_check_clb);
1740 }
1741 
1742 static void
1743 ut_fsdev_opendir_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1744 			struct spdk_fsdev_file_handle *fhandle)
1745 {
1746 	int *clb_status = cb_arg;
1747 	CU_ASSERT(fhandle == UT_FHANDLE);
1748 	*clb_status = status;
1749 }
1750 
1751 static int
1752 ut_fsdev_opendir_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1753 			     struct spdk_fsdev_desc *fsdev_desc, int *status)
1754 {
1755 	return spdk_fsdev_opendir(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, 0x1111,
1756 				  ut_fsdev_opendir_cpl_cb, status);
1757 }
1758 
1759 static void
1760 ut_fsdev_opendir_check_clb(void)
1761 {
1762 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1763 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == 0x1111);
1764 }
1765 
1766 static void
1767 ut_fsdev_test_opendir(void)
1768 {
1769 	ut_fsdev_test_io(SPDK_FSDEV_IO_OPENDIR, 0, 2, ut_fsdev_opendir_execute_clb,
1770 			 ut_fsdev_opendir_check_clb);
1771 }
1772 
1773 static int
1774 ut_fsdev_readdir_entry_cb(void *cb_arg, struct spdk_io_channel *ch, const char *name,
1775 			  struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr,
1776 			  off_t offset)
1777 {
1778 	CU_ASSERT(!strcmp(name, UT_FNAME));
1779 	CU_ASSERT(fobject == UT_FOBJECT + ut_readdir_num_entry_cb_calls);
1780 	CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
1781 	CU_ASSERT(offset == (off_t)(ut_readdir_offset + ut_readdir_num_entry_cb_calls));
1782 
1783 	ut_readdir_num_entry_cb_calls++;
1784 	return (ut_readdir_num_entry_cb_calls == ut_readdir_num_entries) ? -1 : 0;
1785 }
1786 
1787 static void
1788 ut_fsdev_readdir_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1789 {
1790 	int *clb_status = cb_arg;
1791 	*clb_status = status;
1792 }
1793 
1794 static int
1795 ut_fsdev_readdir_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1796 			     struct spdk_fsdev_desc *fsdev_desc, int *status)
1797 {
1798 	ut_readdir_num_entries = 20;
1799 	ut_readdir_num_entry_cb_calls = 0;
1800 	ut_readdir_offset = (uint64_t)rand();
1801 	memset(&ut_fsdev_attr, rand(), sizeof(ut_fsdev_attr));
1802 	return spdk_fsdev_readdir(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, 10000,
1803 				  ut_fsdev_readdir_entry_cb, ut_fsdev_readdir_cpl_cb, status);
1804 }
1805 
1806 static void
1807 ut_fsdev_readdir_check_clb(void)
1808 {
1809 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1810 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1811 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 10000);
1812 	CU_ASSERT(ut_calls_param_get_ptr(0,
1813 					 UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == ut_fsdev_readdir_entry_cb);
1814 	CU_ASSERT(ut_readdir_num_entry_cb_calls == ut_readdir_num_entries);
1815 }
1816 
1817 static void
1818 ut_fsdev_test_readdir(void)
1819 {
1820 	ut_fsdev_test_io(SPDK_FSDEV_IO_READDIR, 0, 4, ut_fsdev_readdir_execute_clb,
1821 			 ut_fsdev_readdir_check_clb);
1822 }
1823 
1824 static void
1825 ut_fsdev_releasedir_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1826 {
1827 	int *clb_status = cb_arg;
1828 	*clb_status = status;
1829 }
1830 
1831 static int
1832 ut_fsdev_releasedir_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1833 				struct spdk_fsdev_desc *fsdev_desc, int *status)
1834 {
1835 	return spdk_fsdev_releasedir(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE,
1836 				     ut_fsdev_releasedir_cpl_cb, status);
1837 }
1838 
1839 static void
1840 ut_fsdev_releasedir_check_clb(void)
1841 {
1842 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1843 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1844 }
1845 
1846 static void
1847 ut_fsdev_test_releasedir(void)
1848 {
1849 	ut_fsdev_test_io(SPDK_FSDEV_IO_RELEASEDIR, 0, 2, ut_fsdev_releasedir_execute_clb,
1850 			 ut_fsdev_releasedir_check_clb);
1851 }
1852 
1853 static void
1854 ut_fsdev_fsyncdir_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1855 {
1856 	int *clb_status = cb_arg;
1857 	*clb_status = status;
1858 }
1859 
1860 static int
1861 ut_fsdev_fsyncdir_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1862 			      struct spdk_fsdev_desc *fsdev_desc, int *status)
1863 {
1864 	return spdk_fsdev_fsyncdir(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, true,
1865 				   ut_fsdev_fsyncdir_cpl_cb, status);
1866 }
1867 
1868 static void
1869 ut_fsdev_fsyncdir_check_clb(void)
1870 {
1871 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1872 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1873 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == true);
1874 }
1875 
1876 static void
1877 ut_fsdev_test_fsyncdir(void)
1878 {
1879 	ut_fsdev_test_io(SPDK_FSDEV_IO_FSYNCDIR, 0, 3, ut_fsdev_fsyncdir_execute_clb,
1880 			 ut_fsdev_fsyncdir_check_clb);
1881 }
1882 
1883 static void
1884 ut_fsdev_flock_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1885 {
1886 	int *clb_status = cb_arg;
1887 	*clb_status = status;
1888 }
1889 
1890 static int
1891 ut_fsdev_flock_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1892 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1893 {
1894 	return spdk_fsdev_flock(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, 111,
1895 				ut_fsdev_flock_cpl_cb, status);
1896 }
1897 
1898 static void
1899 ut_fsdev_flock_check_clb(void)
1900 {
1901 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1902 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
1903 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 111);
1904 }
1905 
1906 static void
1907 ut_fsdev_test_flock(void)
1908 {
1909 	ut_fsdev_test_io(SPDK_FSDEV_IO_FLOCK, 0, 3, ut_fsdev_flock_execute_clb,
1910 			 ut_fsdev_flock_check_clb);
1911 }
1912 
1913 static void
1914 ut_fsdev_create_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
1915 		       struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr,
1916 		       struct spdk_fsdev_file_handle *fhandle)
1917 {
1918 	int *clb_status = cb_arg;
1919 	CU_ASSERT(fobject == UT_FOBJECT + 1);
1920 	CU_ASSERT(fhandle == UT_FHANDLE);
1921 	CU_ASSERT(ut_hash(&ut_fsdev_attr, sizeof(ut_fsdev_attr)) == ut_hash(attr, sizeof(*attr)));
1922 	*clb_status = status;
1923 }
1924 
1925 static int
1926 ut_fsdev_create_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1927 			    struct spdk_fsdev_desc *fsdev_desc, int *status)
1928 {
1929 	memset(&ut_fsdev_attr, rand(), sizeof(ut_fsdev_attr));
1930 	return spdk_fsdev_create(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_LNAME, 100, 0x2222, 0x666,
1931 				 200, 300, ut_fsdev_create_cpl_cb, status);
1932 }
1933 
1934 static void
1935 ut_fsdev_create_check_clb(void)
1936 {
1937 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
1938 	CU_ASSERT(!strncmp(ut_calls_param_get_str(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1), UT_LNAME,
1939 			   UT_CALL_REC_MAX_STR_SIZE));
1940 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 100);
1941 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 0x2222);
1942 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 0x666);
1943 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 5) == 200);
1944 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 6) == 300);
1945 }
1946 
1947 static void
1948 ut_fsdev_test_create(void)
1949 {
1950 	ut_fsdev_test_io(SPDK_FSDEV_IO_CREATE, 0, 7, ut_fsdev_create_execute_clb,
1951 			 ut_fsdev_create_check_clb);
1952 }
1953 
1954 static void
1955 ut_fsdev_abort_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1956 {
1957 	int *clb_status = cb_arg;
1958 	*clb_status = status;
1959 }
1960 
1961 static int
1962 ut_fsdev_abort_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1963 			   struct spdk_fsdev_desc *fsdev_desc, int *status)
1964 {
1965 	return spdk_fsdev_abort(fsdev_desc, ch, UT_UNIQUE,
1966 				ut_fsdev_abort_cpl_cb, status);
1967 }
1968 
1969 static void
1970 ut_fsdev_abort_check_clb(void)
1971 {
1972 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_UNIQUE);
1973 }
1974 
1975 static void
1976 ut_fsdev_test_abort(void)
1977 {
1978 	ut_fsdev_test_io(SPDK_FSDEV_IO_ABORT, 0, 1, ut_fsdev_abort_execute_clb,
1979 			 ut_fsdev_abort_check_clb);
1980 }
1981 
1982 static void
1983 ut_fsdev_fallocate_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status)
1984 {
1985 	int *clb_status = cb_arg;
1986 	*clb_status = status;
1987 }
1988 
1989 static int
1990 ut_fsdev_fallocate_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
1991 			       struct spdk_fsdev_desc *fsdev_desc, int *status)
1992 {
1993 	return spdk_fsdev_fallocate(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, 0x1111, 2000,
1994 				    1002, ut_fsdev_fallocate_cpl_cb, status);
1995 }
1996 
1997 static void
1998 ut_fsdev_fallocate_check_clb(void)
1999 {
2000 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
2001 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
2002 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 0x1111);
2003 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == 2000);
2004 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == 1002);
2005 }
2006 
2007 static void
2008 ut_fsdev_test_fallocate(void)
2009 {
2010 	ut_fsdev_test_io(SPDK_FSDEV_IO_FALLOCATE, 0, 5, ut_fsdev_fallocate_execute_clb,
2011 			 ut_fsdev_fallocate_check_clb);
2012 }
2013 
2014 static void
2015 ut_fsdev_copy_file_range_cpl_cb(void *cb_arg, struct spdk_io_channel *ch, int status,
2016 				uint32_t data_size)
2017 {
2018 	int *clb_status = cb_arg;
2019 	CU_ASSERT(data_size == UT_DATA_SIZE);
2020 	*clb_status = status;
2021 }
2022 
2023 static int
2024 ut_fsdev_copy_file_range_execute_clb(struct ut_fsdev *utfsdev, struct spdk_io_channel *ch,
2025 				     struct spdk_fsdev_desc *fsdev_desc, int *status)
2026 {
2027 	return spdk_fsdev_copy_file_range(fsdev_desc, ch, UT_UNIQUE, UT_FOBJECT, UT_FHANDLE, 1000,
2028 					  UT_FOBJECT + 2, UT_FHANDLE + 2, 3000, 50000, 0x77777777,
2029 					  ut_fsdev_copy_file_range_cpl_cb, status);
2030 }
2031 
2032 static void
2033 ut_fsdev_copy_file_range_check_clb(void)
2034 {
2035 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS) == UT_FOBJECT);
2036 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 1) == UT_FHANDLE);
2037 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 2) == 1000);
2038 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 3) == UT_FOBJECT + 2);
2039 	CU_ASSERT(ut_calls_param_get_ptr(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 4) == UT_FHANDLE + 2);
2040 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 5) == 3000);
2041 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 6) == 50000);
2042 	CU_ASSERT(ut_calls_param_get_int(0, UT_SUBMIT_IO_NUM_COMMON_PARAMS + 7) == 0x77777777);
2043 }
2044 
2045 static void
2046 ut_fsdev_test_copy_file_range(void)
2047 {
2048 	ut_fsdev_test_io(SPDK_FSDEV_IO_COPY_FILE_RANGE, 0, 8, ut_fsdev_copy_file_range_execute_clb,
2049 			 ut_fsdev_copy_file_range_check_clb);
2050 }
2051 
2052 int
2053 main(int argc, char **argv)
2054 {
2055 	CU_pSuite		suite = NULL;
2056 	unsigned int		num_failures;
2057 
2058 	CU_initialize_registry();
2059 
2060 	suite = CU_add_suite("fsdev", ut_fsdev_setup, ut_fsdev_teardown);
2061 
2062 	CU_ADD_TEST(suite, ut_fsdev_test_open_close);
2063 	CU_ADD_TEST(suite, ut_fsdev_test_set_opts);
2064 	CU_ADD_TEST(suite, ut_fsdev_test_get_io_channel);
2065 	CU_ADD_TEST(suite, ut_fsdev_test_mount_ok);
2066 	CU_ADD_TEST(suite, ut_fsdev_test_mount_err);
2067 	CU_ADD_TEST(suite, ut_fsdev_test_umount);
2068 	CU_ADD_TEST(suite, ut_fsdev_test_lookup_ok);
2069 	CU_ADD_TEST(suite, ut_fsdev_test_lookup_err);
2070 	CU_ADD_TEST(suite, ut_fsdev_test_forget);
2071 	CU_ADD_TEST(suite, ut_fsdev_test_getattr);
2072 	CU_ADD_TEST(suite, ut_fsdev_test_setattr);
2073 	CU_ADD_TEST(suite, ut_fsdev_test_readlink);
2074 	CU_ADD_TEST(suite, ut_fsdev_test_symlink);
2075 	CU_ADD_TEST(suite, ut_fsdev_test_mknod);
2076 	CU_ADD_TEST(suite, ut_fsdev_test_mkdir);
2077 	CU_ADD_TEST(suite, ut_fsdev_test_unlink);
2078 	CU_ADD_TEST(suite, ut_fsdev_test_rmdir);
2079 	CU_ADD_TEST(suite, ut_fsdev_test_rename);
2080 	CU_ADD_TEST(suite, ut_fsdev_test_link);
2081 	CU_ADD_TEST(suite, ut_fsdev_test_fopen);
2082 	CU_ADD_TEST(suite, ut_fsdev_test_read);
2083 	CU_ADD_TEST(suite, ut_fsdev_test_write);
2084 	CU_ADD_TEST(suite, ut_fsdev_test_statfs);
2085 	CU_ADD_TEST(suite, ut_fsdev_test_release);
2086 	CU_ADD_TEST(suite, ut_fsdev_test_fsync);
2087 	CU_ADD_TEST(suite, ut_fsdev_test_getxattr);
2088 	CU_ADD_TEST(suite, ut_fsdev_test_setxattr);
2089 	CU_ADD_TEST(suite, ut_fsdev_test_listxattr);
2090 	CU_ADD_TEST(suite, ut_fsdev_test_listxattr_get_size);
2091 	CU_ADD_TEST(suite, ut_fsdev_test_removexattr);
2092 	CU_ADD_TEST(suite, ut_fsdev_test_flush);
2093 	CU_ADD_TEST(suite, ut_fsdev_test_opendir);
2094 	CU_ADD_TEST(suite, ut_fsdev_test_readdir);
2095 	CU_ADD_TEST(suite, ut_fsdev_test_releasedir);
2096 	CU_ADD_TEST(suite, ut_fsdev_test_fsyncdir);
2097 	CU_ADD_TEST(suite, ut_fsdev_test_flock);
2098 	CU_ADD_TEST(suite, ut_fsdev_test_create);
2099 	CU_ADD_TEST(suite, ut_fsdev_test_abort);
2100 	CU_ADD_TEST(suite, ut_fsdev_test_fallocate);
2101 	CU_ADD_TEST(suite, ut_fsdev_test_copy_file_range);
2102 
2103 	allocate_cores(1);
2104 	allocate_threads(1);
2105 	set_thread(0);
2106 
2107 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
2108 	CU_cleanup_registry();
2109 
2110 	poll_thread(0);
2111 
2112 	free_threads();
2113 	free_cores();
2114 
2115 	return num_failures;
2116 }
2117