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