xref: /spdk/test/unit/lib/bdev/bdev.c/bdev_ut.c (revision 8a0a98d35e21f282088edf28b9e8da66ec390e3a)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk_cunit.h"
35 
36 #include "common/lib/test_env.c"
37 #include "unit/lib/json_mock.c"
38 
39 /* HACK: disable VTune integration so the unit test doesn't need VTune headers and libs to build */
40 #undef SPDK_CONFIG_VTUNE
41 
42 #include "bdev/bdev.c"
43 
44 DEFINE_STUB(spdk_conf_find_section, struct spdk_conf_section *, (struct spdk_conf *cp,
45 		const char *name), NULL);
46 DEFINE_STUB(spdk_conf_section_get_nmval, char *,
47 	    (struct spdk_conf_section *sp, const char *key, int idx1, int idx2), NULL);
48 DEFINE_STUB(spdk_conf_section_get_intval, int, (struct spdk_conf_section *sp, const char *key), -1);
49 
50 static void
51 _bdev_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx)
52 {
53 	fn(ctx);
54 }
55 
56 void
57 spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io,
58 			 int *sc, int *sk, int *asc, int *ascq)
59 {
60 }
61 
62 static int
63 null_init(void)
64 {
65 	return 0;
66 }
67 
68 static int
69 null_clean(void)
70 {
71 	return 0;
72 }
73 
74 static int
75 stub_destruct(void *ctx)
76 {
77 	return 0;
78 }
79 
80 struct bdev_ut_channel {
81 	TAILQ_HEAD(, spdk_bdev_io)	outstanding_io;
82 	uint32_t			outstanding_io_count;
83 };
84 
85 static uint32_t g_bdev_ut_io_device;
86 static struct bdev_ut_channel *g_bdev_ut_channel;
87 
88 static void
89 stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
90 {
91 	struct bdev_ut_channel *ch = spdk_io_channel_get_ctx(_ch);
92 
93 	TAILQ_INSERT_TAIL(&ch->outstanding_io, bdev_io, module_link);
94 	ch->outstanding_io_count++;
95 }
96 
97 static uint32_t
98 stub_complete_io(uint32_t num_to_complete)
99 {
100 	struct bdev_ut_channel *ch = g_bdev_ut_channel;
101 	struct spdk_bdev_io *bdev_io;
102 	uint32_t num_completed = 0;
103 
104 	while (num_completed < num_to_complete) {
105 		if (TAILQ_EMPTY(&ch->outstanding_io)) {
106 			break;
107 		}
108 		bdev_io = TAILQ_FIRST(&ch->outstanding_io);
109 		TAILQ_REMOVE(&ch->outstanding_io, bdev_io, module_link);
110 		ch->outstanding_io_count--;
111 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
112 		num_completed++;
113 	}
114 
115 	return num_completed;
116 }
117 
118 static struct spdk_io_channel *
119 bdev_ut_get_io_channel(void *ctx)
120 {
121 	return spdk_get_io_channel(&g_bdev_ut_io_device);
122 }
123 
124 static struct spdk_bdev_fn_table fn_table = {
125 	.destruct = stub_destruct,
126 	.submit_request = stub_submit_request,
127 	.get_io_channel = bdev_ut_get_io_channel,
128 };
129 
130 static int
131 bdev_ut_create_ch(void *io_device, void *ctx_buf)
132 {
133 	struct bdev_ut_channel *ch = ctx_buf;
134 
135 	CU_ASSERT(g_bdev_ut_channel == NULL);
136 	g_bdev_ut_channel = ch;
137 
138 	TAILQ_INIT(&ch->outstanding_io);
139 	ch->outstanding_io_count = 0;
140 	return 0;
141 }
142 
143 static void
144 bdev_ut_destroy_ch(void *io_device, void *ctx_buf)
145 {
146 	CU_ASSERT(g_bdev_ut_channel != NULL);
147 	g_bdev_ut_channel = NULL;
148 }
149 
150 static int
151 bdev_ut_module_init(void)
152 {
153 	spdk_io_device_register(&g_bdev_ut_io_device, bdev_ut_create_ch, bdev_ut_destroy_ch,
154 				sizeof(struct bdev_ut_channel));
155 	return 0;
156 }
157 
158 static void
159 bdev_ut_module_fini(void)
160 {
161 }
162 
163 struct spdk_bdev_module bdev_ut_if = {
164 	.name = "bdev_ut",
165 	.module_init = bdev_ut_module_init,
166 	.module_fini = bdev_ut_module_fini,
167 };
168 
169 static void vbdev_ut_examine(struct spdk_bdev *bdev);
170 
171 static int
172 vbdev_ut_module_init(void)
173 {
174 	return 0;
175 }
176 
177 static void
178 vbdev_ut_module_fini(void)
179 {
180 }
181 
182 struct spdk_bdev_module vbdev_ut_if = {
183 	.name = "vbdev_ut",
184 	.examine = vbdev_ut_examine,
185 	.module_init = vbdev_ut_module_init,
186 	.module_fini = vbdev_ut_module_fini,
187 };
188 
189 SPDK_BDEV_MODULE_REGISTER(&bdev_ut_if)
190 SPDK_BDEV_MODULE_REGISTER(&vbdev_ut_if)
191 
192 static void
193 vbdev_ut_examine(struct spdk_bdev *bdev)
194 {
195 	spdk_bdev_module_examine_done(&vbdev_ut_if);
196 }
197 
198 static bool
199 is_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev)
200 {
201 	size_t i;
202 	int found = 0;
203 
204 	for (i = 0; i < base->vbdevs_cnt; i++) {
205 		found += base->vbdevs[i] == vbdev;
206 	}
207 
208 	CU_ASSERT(found <= 1);
209 	return !!found;
210 }
211 
212 static bool
213 is_base_bdev(struct spdk_bdev *base, struct spdk_bdev *vbdev)
214 {
215 	size_t i;
216 	int found = 0;
217 
218 	for (i = 0; i < vbdev->base_bdevs_cnt; i++) {
219 		found += vbdev->base_bdevs[i] == base;
220 	}
221 
222 	CU_ASSERT(found <= 1);
223 	return !!found;
224 }
225 
226 static bool
227 check_base_and_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev)
228 {
229 	bool _is_vbdev = is_vbdev(base, vbdev);
230 	bool _is_base = is_base_bdev(base, vbdev);
231 
232 	CU_ASSERT(_is_vbdev == _is_base);
233 
234 	return _is_base && _is_vbdev;
235 }
236 
237 static struct spdk_bdev *
238 allocate_bdev(char *name)
239 {
240 	struct spdk_bdev *bdev;
241 	int rc;
242 
243 	bdev = calloc(1, sizeof(*bdev));
244 	SPDK_CU_ASSERT_FATAL(bdev != NULL);
245 
246 	bdev->name = name;
247 	bdev->fn_table = &fn_table;
248 	bdev->module = &bdev_ut_if;
249 	bdev->blockcnt = 1;
250 
251 	rc = spdk_bdev_register(bdev);
252 	CU_ASSERT(rc == 0);
253 	CU_ASSERT(bdev->base_bdevs_cnt == 0);
254 	CU_ASSERT(bdev->vbdevs_cnt == 0);
255 
256 	return bdev;
257 }
258 
259 static struct spdk_bdev *
260 allocate_vbdev(char *name, struct spdk_bdev *base1, struct spdk_bdev *base2)
261 {
262 	struct spdk_bdev *bdev;
263 	struct spdk_bdev *array[2];
264 	int rc;
265 
266 	bdev = calloc(1, sizeof(*bdev));
267 	SPDK_CU_ASSERT_FATAL(bdev != NULL);
268 
269 	bdev->name = name;
270 	bdev->fn_table = &fn_table;
271 	bdev->module = &vbdev_ut_if;
272 
273 	/* vbdev must have at least one base bdev */
274 	CU_ASSERT(base1 != NULL);
275 
276 	array[0] = base1;
277 	array[1] = base2;
278 
279 	rc = spdk_vbdev_register(bdev, array, base2 == NULL ? 1 : 2);
280 	CU_ASSERT(rc == 0);
281 	CU_ASSERT(bdev->base_bdevs_cnt > 0);
282 	CU_ASSERT(bdev->vbdevs_cnt == 0);
283 
284 	CU_ASSERT(check_base_and_vbdev(base1, bdev) == true);
285 
286 	if (base2) {
287 		CU_ASSERT(check_base_and_vbdev(base2, bdev) == true);
288 	}
289 
290 	return bdev;
291 }
292 
293 static void
294 free_bdev(struct spdk_bdev *bdev)
295 {
296 	spdk_bdev_unregister(bdev, NULL, NULL);
297 	memset(bdev, 0xFF, sizeof(*bdev));
298 	free(bdev);
299 }
300 
301 static void
302 free_vbdev(struct spdk_bdev *bdev)
303 {
304 	CU_ASSERT(bdev->base_bdevs_cnt != 0);
305 	spdk_bdev_unregister(bdev, NULL, NULL);
306 	memset(bdev, 0xFF, sizeof(*bdev));
307 	free(bdev);
308 }
309 
310 static void
311 get_device_stat_cb(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, void *cb_arg, int rc)
312 {
313 	const char *bdev_name;
314 
315 	CU_ASSERT(bdev != NULL);
316 	CU_ASSERT(rc == 0);
317 	bdev_name = spdk_bdev_get_name(bdev);
318 	CU_ASSERT_STRING_EQUAL(bdev_name, "bdev0");
319 
320 	free(stat);
321 	free_bdev(bdev);
322 }
323 
324 static void
325 get_device_stat_test(void)
326 {
327 	struct spdk_bdev *bdev;
328 	struct spdk_bdev_io_stat *stat;
329 
330 	bdev = allocate_bdev("bdev0");
331 	stat = calloc(1, sizeof(struct spdk_bdev_io_stat));
332 	if (stat == NULL) {
333 		free_bdev(bdev);
334 		return;
335 	}
336 	spdk_bdev_get_device_stat(bdev, stat, get_device_stat_cb, NULL);
337 }
338 
339 static void
340 open_write_test(void)
341 {
342 	struct spdk_bdev *bdev[9];
343 	struct spdk_bdev_desc *desc[9] = {};
344 	int rc;
345 
346 	/*
347 	 * Create a tree of bdevs to test various open w/ write cases.
348 	 *
349 	 * bdev0 through bdev3 are physical block devices, such as NVMe
350 	 * namespaces or Ceph block devices.
351 	 *
352 	 * bdev4 is a virtual bdev with multiple base bdevs.  This models
353 	 * caching or RAID use cases.
354 	 *
355 	 * bdev5 through bdev7 are all virtual bdevs with the same base
356 	 * bdev (except bdev7). This models partitioning or logical volume
357 	 * use cases.
358 	 *
359 	 * bdev7 is a virtual bdev with multiple base bdevs. One of base bdevs
360 	 * (bdev2) is shared with other virtual bdevs: bdev5 and bdev6. This
361 	 * models caching, RAID, partitioning or logical volumes use cases.
362 	 *
363 	 * bdev8 is a virtual bdev with multiple base bdevs, but these
364 	 * base bdevs are themselves virtual bdevs.
365 	 *
366 	 *                bdev8
367 	 *                  |
368 	 *            +----------+
369 	 *            |          |
370 	 *          bdev4      bdev5   bdev6   bdev7
371 	 *            |          |       |       |
372 	 *        +---+---+      +---+   +   +---+---+
373 	 *        |       |           \  |  /         \
374 	 *      bdev0   bdev1          bdev2         bdev3
375 	 */
376 
377 	bdev[0] = allocate_bdev("bdev0");
378 	rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, &bdev_ut_if);
379 	CU_ASSERT(rc == 0);
380 
381 	bdev[1] = allocate_bdev("bdev1");
382 	rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if);
383 	CU_ASSERT(rc == 0);
384 
385 	bdev[2] = allocate_bdev("bdev2");
386 	rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, &bdev_ut_if);
387 	CU_ASSERT(rc == 0);
388 
389 	bdev[3] = allocate_bdev("bdev3");
390 	rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if);
391 	CU_ASSERT(rc == 0);
392 
393 	bdev[4] = allocate_vbdev("bdev4", bdev[0], bdev[1]);
394 	rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, &bdev_ut_if);
395 	CU_ASSERT(rc == 0);
396 
397 	bdev[5] = allocate_vbdev("bdev5", bdev[2], NULL);
398 	rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if);
399 	CU_ASSERT(rc == 0);
400 
401 	bdev[6] = allocate_vbdev("bdev6", bdev[2], NULL);
402 
403 	bdev[7] = allocate_vbdev("bdev7", bdev[2], bdev[3]);
404 
405 	bdev[8] = allocate_vbdev("bdev8", bdev[4], bdev[5]);
406 
407 	/* Check tree */
408 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[4]) == true);
409 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[5]) == false);
410 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[6]) == false);
411 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[7]) == false);
412 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[8]) == false);
413 
414 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[4]) == true);
415 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[5]) == false);
416 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[6]) == false);
417 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[7]) == false);
418 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[8]) == false);
419 
420 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[4]) == false);
421 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[5]) == true);
422 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[6]) == true);
423 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[7]) == true);
424 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[8]) == false);
425 
426 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[4]) == false);
427 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[5]) == false);
428 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[6]) == false);
429 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[7]) == true);
430 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[8]) == false);
431 
432 	/* Open bdev0 read-only.  This should succeed. */
433 	rc = spdk_bdev_open(bdev[0], false, NULL, NULL, &desc[0]);
434 	CU_ASSERT(rc == 0);
435 	CU_ASSERT(desc[0] != NULL);
436 	spdk_bdev_close(desc[0]);
437 
438 	/*
439 	 * Open bdev1 read/write.  This should fail since bdev1 has been claimed
440 	 * by a vbdev module.
441 	 */
442 	rc = spdk_bdev_open(bdev[1], true, NULL, NULL, &desc[1]);
443 	CU_ASSERT(rc == -EPERM);
444 
445 	/*
446 	 * Open bdev4 read/write.  This should fail since bdev3 has been claimed
447 	 * by a vbdev module.
448 	 */
449 	rc = spdk_bdev_open(bdev[4], true, NULL, NULL, &desc[4]);
450 	CU_ASSERT(rc == -EPERM);
451 
452 	/* Open bdev4 read-only.  This should succeed. */
453 	rc = spdk_bdev_open(bdev[4], false, NULL, NULL, &desc[4]);
454 	CU_ASSERT(rc == 0);
455 	CU_ASSERT(desc[4] != NULL);
456 	spdk_bdev_close(desc[4]);
457 
458 	/*
459 	 * Open bdev8 read/write.  This should succeed since it is a leaf
460 	 * bdev.
461 	 */
462 	rc = spdk_bdev_open(bdev[8], true, NULL, NULL, &desc[8]);
463 	CU_ASSERT(rc == 0);
464 	CU_ASSERT(desc[8] != NULL);
465 	spdk_bdev_close(desc[8]);
466 
467 	/*
468 	 * Open bdev5 read/write.  This should fail since bdev4 has been claimed
469 	 * by a vbdev module.
470 	 */
471 	rc = spdk_bdev_open(bdev[5], true, NULL, NULL, &desc[5]);
472 	CU_ASSERT(rc == -EPERM);
473 
474 	/* Open bdev4 read-only.  This should succeed. */
475 	rc = spdk_bdev_open(bdev[5], false, NULL, NULL, &desc[5]);
476 	CU_ASSERT(rc == 0);
477 	CU_ASSERT(desc[5] != NULL);
478 	spdk_bdev_close(desc[5]);
479 
480 	free_vbdev(bdev[8]);
481 
482 	free_vbdev(bdev[5]);
483 	free_vbdev(bdev[6]);
484 	free_vbdev(bdev[7]);
485 
486 	free_vbdev(bdev[4]);
487 
488 	free_bdev(bdev[0]);
489 	free_bdev(bdev[1]);
490 	free_bdev(bdev[2]);
491 	free_bdev(bdev[3]);
492 }
493 
494 static void
495 bytes_to_blocks_test(void)
496 {
497 	struct spdk_bdev bdev;
498 	uint64_t offset_blocks, num_blocks;
499 
500 	memset(&bdev, 0, sizeof(bdev));
501 
502 	bdev.blocklen = 512;
503 
504 	/* All parameters valid */
505 	offset_blocks = 0;
506 	num_blocks = 0;
507 	CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0);
508 	CU_ASSERT(offset_blocks == 1);
509 	CU_ASSERT(num_blocks == 2);
510 
511 	/* Offset not a block multiple */
512 	CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0);
513 
514 	/* Length not a block multiple */
515 	CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0);
516 }
517 
518 static void
519 num_blocks_test(void)
520 {
521 	struct spdk_bdev bdev;
522 	struct spdk_bdev_desc *desc;
523 
524 	memset(&bdev, 0, sizeof(bdev));
525 	bdev.name = "num_blocks";
526 	bdev.fn_table = &fn_table;
527 	bdev.module = &bdev_ut_if;
528 	spdk_bdev_register(&bdev);
529 	spdk_bdev_notify_blockcnt_change(&bdev, 50);
530 
531 	/* Growing block number */
532 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 70) == 0);
533 	/* Shrinking block number */
534 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 30) == 0);
535 
536 	/* In case bdev opened */
537 	spdk_bdev_open(&bdev, false, NULL, NULL, &desc);
538 
539 	/* Growing block number */
540 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 80) == 0);
541 	/* Shrinking block number */
542 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 20) != 0);
543 
544 	spdk_bdev_close(desc);
545 	spdk_bdev_unregister(&bdev, NULL, NULL);
546 }
547 
548 static void
549 io_valid_test(void)
550 {
551 	struct spdk_bdev bdev;
552 
553 	memset(&bdev, 0, sizeof(bdev));
554 
555 	bdev.blocklen = 512;
556 	spdk_bdev_notify_blockcnt_change(&bdev, 100);
557 
558 	/* All parameters valid */
559 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 1, 2) == true);
560 
561 	/* Last valid block */
562 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 1) == true);
563 
564 	/* Offset past end of bdev */
565 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 100, 1) == false);
566 
567 	/* Offset + length past end of bdev */
568 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 2) == false);
569 
570 	/* Offset near end of uint64_t range (2^64 - 1) */
571 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false);
572 }
573 
574 static void
575 alias_add_del_test(void)
576 {
577 	struct spdk_bdev *bdev[2];
578 	int rc;
579 
580 	/* Creating and registering bdevs */
581 	bdev[0] = allocate_bdev("bdev0");
582 	SPDK_CU_ASSERT_FATAL(bdev[0] != 0);
583 
584 	bdev[1] = allocate_bdev("bdev1");
585 	SPDK_CU_ASSERT_FATAL(bdev[1] != 0);
586 
587 	/*
588 	 * Trying adding an alias identical to name.
589 	 * Alias is identical to name, so it can not be added to aliases list
590 	 */
591 	rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name);
592 	CU_ASSERT(rc == -EEXIST);
593 
594 	/*
595 	 * Trying to add empty alias,
596 	 * this one should fail
597 	 */
598 	rc = spdk_bdev_alias_add(bdev[0], NULL);
599 	CU_ASSERT(rc == -EINVAL);
600 
601 	/* Trying adding same alias to two different registered bdevs */
602 
603 	/* Alias is used first time, so this one should pass */
604 	rc = spdk_bdev_alias_add(bdev[0], "proper alias 0");
605 	CU_ASSERT(rc == 0);
606 
607 	/* Alias was added to another bdev, so this one should fail */
608 	rc = spdk_bdev_alias_add(bdev[1], "proper alias 0");
609 	CU_ASSERT(rc == -EEXIST);
610 
611 	/* Alias is used first time, so this one should pass */
612 	rc = spdk_bdev_alias_add(bdev[1], "proper alias 1");
613 	CU_ASSERT(rc == 0);
614 
615 	/* Trying removing an alias from registered bdevs */
616 
617 	/* Alias is not on a bdev aliases list, so this one should fail */
618 	rc = spdk_bdev_alias_del(bdev[0], "not existing");
619 	CU_ASSERT(rc == -ENOENT);
620 
621 	/* Alias is present on a bdev aliases list, so this one should pass */
622 	rc = spdk_bdev_alias_del(bdev[0], "proper alias 0");
623 	CU_ASSERT(rc == 0);
624 
625 	/* Alias is present on a bdev aliases list, so this one should pass */
626 	rc = spdk_bdev_alias_del(bdev[1], "proper alias 1");
627 	CU_ASSERT(rc == 0);
628 
629 	/* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */
630 	rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name);
631 	CU_ASSERT(rc != 0);
632 
633 	/* Unregister and free bdevs */
634 	spdk_bdev_unregister(bdev[0], NULL, NULL);
635 	spdk_bdev_unregister(bdev[1], NULL, NULL);
636 
637 	free(bdev[0]);
638 	free(bdev[1]);
639 }
640 
641 static void
642 io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
643 {
644 	spdk_bdev_free_io(bdev_io);
645 }
646 
647 static void
648 bdev_init_cb(void *arg, int rc)
649 {
650 	CU_ASSERT(rc == 0);
651 }
652 
653 struct bdev_ut_io_wait_entry {
654 	struct spdk_bdev_io_wait_entry	entry;
655 	struct spdk_io_channel		*io_ch;
656 	struct spdk_bdev_desc		*desc;
657 	bool				submitted;
658 };
659 
660 static void
661 io_wait_cb(void *arg)
662 {
663 	struct bdev_ut_io_wait_entry *entry = arg;
664 	int rc;
665 
666 	rc = spdk_bdev_read_blocks(entry->desc, entry->io_ch, NULL, 0, 1, io_done, NULL);
667 	CU_ASSERT(rc == 0);
668 	entry->submitted = true;
669 }
670 
671 static void
672 bdev_io_wait_test(void)
673 {
674 	struct spdk_bdev *bdev;
675 	struct spdk_bdev_desc *desc;
676 	struct spdk_io_channel *io_ch;
677 	struct spdk_bdev_opts bdev_opts = {
678 		.bdev_io_pool_size = 4,
679 		.bdev_io_cache_size = 2,
680 	};
681 	struct bdev_ut_io_wait_entry io_wait_entry;
682 	struct bdev_ut_io_wait_entry io_wait_entry2;
683 	int rc;
684 
685 	rc = spdk_bdev_set_opts(&bdev_opts);
686 	CU_ASSERT(rc == 0);
687 	spdk_bdev_initialize(bdev_init_cb, NULL);
688 
689 	bdev = allocate_bdev("bdev0");
690 
691 	rc = spdk_bdev_open(bdev, true, NULL, NULL, &desc);
692 	CU_ASSERT(rc == 0);
693 	CU_ASSERT(desc != NULL);
694 	io_ch = spdk_bdev_get_io_channel(desc);
695 	CU_ASSERT(io_ch != NULL);
696 
697 	rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL);
698 	CU_ASSERT(rc == 0);
699 	rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL);
700 	CU_ASSERT(rc == 0);
701 	rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL);
702 	CU_ASSERT(rc == 0);
703 	rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL);
704 	CU_ASSERT(rc == 0);
705 	CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4);
706 
707 	rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL);
708 	CU_ASSERT(rc == -ENOMEM);
709 
710 	io_wait_entry.entry.bdev = bdev;
711 	io_wait_entry.entry.cb_fn = io_wait_cb;
712 	io_wait_entry.entry.cb_arg = &io_wait_entry;
713 	io_wait_entry.io_ch = io_ch;
714 	io_wait_entry.desc = desc;
715 	io_wait_entry.submitted = false;
716 	/* Cannot use the same io_wait_entry for two different calls. */
717 	memcpy(&io_wait_entry2, &io_wait_entry, sizeof(io_wait_entry));
718 	io_wait_entry2.entry.cb_arg = &io_wait_entry2;
719 
720 	/* Queue two I/O waits. */
721 	rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry.entry);
722 	CU_ASSERT(rc == 0);
723 	CU_ASSERT(io_wait_entry.submitted == false);
724 	rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry2.entry);
725 	CU_ASSERT(rc == 0);
726 	CU_ASSERT(io_wait_entry2.submitted == false);
727 
728 	stub_complete_io(1);
729 	CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4);
730 	CU_ASSERT(io_wait_entry.submitted == true);
731 	CU_ASSERT(io_wait_entry2.submitted == false);
732 
733 	stub_complete_io(1);
734 	CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4);
735 	CU_ASSERT(io_wait_entry2.submitted == true);
736 
737 	stub_complete_io(4);
738 	CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0);
739 
740 	spdk_put_io_channel(io_ch);
741 	spdk_bdev_close(desc);
742 	free_bdev(bdev);
743 }
744 
745 int
746 main(int argc, char **argv)
747 {
748 	CU_pSuite	suite = NULL;
749 	unsigned int	num_failures;
750 
751 	if (CU_initialize_registry() != CUE_SUCCESS) {
752 		return CU_get_error();
753 	}
754 
755 	suite = CU_add_suite("bdev", null_init, null_clean);
756 	if (suite == NULL) {
757 		CU_cleanup_registry();
758 		return CU_get_error();
759 	}
760 
761 	if (
762 		CU_add_test(suite, "bytes_to_blocks_test", bytes_to_blocks_test) == NULL ||
763 		CU_add_test(suite, "num_blocks_test", num_blocks_test) == NULL ||
764 		CU_add_test(suite, "io_valid", io_valid_test) == NULL ||
765 		CU_add_test(suite, "open_write", open_write_test) == NULL ||
766 		CU_add_test(suite, "alias_add_del", alias_add_del_test) == NULL ||
767 		CU_add_test(suite, "get_device_stat", get_device_stat_test) == NULL ||
768 		CU_add_test(suite, "bdev_io_wait", bdev_io_wait_test) == NULL
769 	) {
770 		CU_cleanup_registry();
771 		return CU_get_error();
772 	}
773 
774 	spdk_allocate_thread(_bdev_send_msg, NULL, NULL, NULL, "thread0");
775 	CU_basic_set_mode(CU_BRM_VERBOSE);
776 	CU_basic_run_tests();
777 	num_failures = CU_get_number_of_failures();
778 	CU_cleanup_registry();
779 	spdk_free_thread();
780 	return num_failures;
781 }
782