xref: /spdk/test/unit/lib/bdev/bdev.c/bdev_ut.c (revision 61e8486c10bd179811225d792add75a8fcc936ce)
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 /* Return NULL to test hardcoded defaults. */
45 struct spdk_conf_section *
46 spdk_conf_find_section(struct spdk_conf *cp, const char *name)
47 {
48 	return NULL;
49 }
50 
51 /* Return NULL to test hardcoded defaults. */
52 char *
53 spdk_conf_section_get_nmval(struct spdk_conf_section *sp, const char *key, int idx1, int idx2)
54 {
55 	return NULL;
56 }
57 
58 void
59 spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io,
60 			 int *sc, int *sk, int *asc, int *ascq)
61 {
62 }
63 
64 static int
65 null_init(void)
66 {
67 	return 0;
68 }
69 
70 static int
71 null_clean(void)
72 {
73 	return 0;
74 }
75 
76 static int
77 stub_destruct(void *ctx)
78 {
79 	return 0;
80 }
81 
82 static struct spdk_bdev_fn_table fn_table = {
83 	.destruct = stub_destruct,
84 };
85 
86 struct spdk_bdev_module bdev_ut_if = {
87 	.name = "bdev_ut",
88 };
89 
90 static void vbdev_ut_examine(struct spdk_bdev *bdev);
91 
92 struct spdk_bdev_module vbdev_ut_if = {
93 	.name = "vbdev_ut",
94 	.examine = vbdev_ut_examine,
95 };
96 
97 SPDK_BDEV_MODULE_REGISTER(&bdev_ut_if)
98 SPDK_BDEV_MODULE_REGISTER(&vbdev_ut_if)
99 
100 static void
101 vbdev_ut_examine(struct spdk_bdev *bdev)
102 {
103 	spdk_bdev_module_examine_done(&vbdev_ut_if);
104 }
105 
106 static bool
107 is_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev)
108 {
109 	size_t i;
110 	int found = 0;
111 
112 	for (i = 0; i < base->vbdevs_cnt; i++) {
113 		found += base->vbdevs[i] == vbdev;
114 	}
115 
116 	CU_ASSERT(found <= 1);
117 	return !!found;
118 }
119 
120 static bool
121 is_base_bdev(struct spdk_bdev *base, struct spdk_bdev *vbdev)
122 {
123 	size_t i;
124 	int found = 0;
125 
126 	for (i = 0; i < vbdev->base_bdevs_cnt; i++) {
127 		found += vbdev->base_bdevs[i] == base;
128 	}
129 
130 	CU_ASSERT(found <= 1);
131 	return !!found;
132 }
133 
134 static bool
135 check_base_and_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev)
136 {
137 	bool _is_vbdev = is_vbdev(base, vbdev);
138 	bool _is_base = is_base_bdev(base, vbdev);
139 
140 	CU_ASSERT(_is_vbdev == _is_base);
141 
142 	return _is_base && _is_vbdev;
143 }
144 
145 static struct spdk_bdev *
146 allocate_bdev(char *name)
147 {
148 	struct spdk_bdev *bdev;
149 	int rc;
150 
151 	bdev = calloc(1, sizeof(*bdev));
152 	SPDK_CU_ASSERT_FATAL(bdev != NULL);
153 
154 	bdev->name = name;
155 	bdev->fn_table = &fn_table;
156 	bdev->module = &bdev_ut_if;
157 
158 	rc = spdk_bdev_register(bdev);
159 	CU_ASSERT(rc == 0);
160 	CU_ASSERT(bdev->base_bdevs_cnt == 0);
161 	CU_ASSERT(bdev->vbdevs_cnt == 0);
162 
163 	return bdev;
164 }
165 
166 static struct spdk_bdev *
167 allocate_vbdev(char *name, struct spdk_bdev *base1, struct spdk_bdev *base2)
168 {
169 	struct spdk_bdev *bdev;
170 	struct spdk_bdev *array[2];
171 	int rc;
172 
173 	bdev = calloc(1, sizeof(*bdev));
174 	SPDK_CU_ASSERT_FATAL(bdev != NULL);
175 
176 	bdev->name = name;
177 	bdev->fn_table = &fn_table;
178 	bdev->module = &vbdev_ut_if;
179 
180 	/* vbdev must have at least one base bdev */
181 	CU_ASSERT(base1 != NULL);
182 
183 	array[0] = base1;
184 	array[1] = base2;
185 
186 	rc = spdk_vbdev_register(bdev, array, base2 == NULL ? 1 : 2);
187 	CU_ASSERT(rc == 0);
188 	CU_ASSERT(bdev->base_bdevs_cnt > 0);
189 	CU_ASSERT(bdev->vbdevs_cnt == 0);
190 
191 	CU_ASSERT(check_base_and_vbdev(base1, bdev) == true);
192 
193 	if (base2) {
194 		CU_ASSERT(check_base_and_vbdev(base2, bdev) == true);
195 	}
196 
197 	return bdev;
198 }
199 
200 static void
201 free_bdev(struct spdk_bdev *bdev)
202 {
203 	spdk_bdev_unregister(bdev, NULL, NULL);
204 	memset(bdev, 0xFF, sizeof(*bdev));
205 	free(bdev);
206 }
207 
208 static void
209 free_vbdev(struct spdk_bdev *bdev)
210 {
211 	CU_ASSERT(bdev->base_bdevs_cnt != 0);
212 	spdk_bdev_unregister(bdev, NULL, NULL);
213 	memset(bdev, 0xFF, sizeof(*bdev));
214 	free(bdev);
215 }
216 
217 static void
218 open_write_test(void)
219 {
220 	struct spdk_bdev *bdev[9];
221 	struct spdk_bdev_desc *desc[9] = {};
222 	int rc;
223 
224 	/*
225 	 * Create a tree of bdevs to test various open w/ write cases.
226 	 *
227 	 * bdev0 through bdev3 are physical block devices, such as NVMe
228 	 * namespaces or Ceph block devices.
229 	 *
230 	 * bdev4 is a virtual bdev with multiple base bdevs.  This models
231 	 * caching or RAID use cases.
232 	 *
233 	 * bdev5 through bdev7 are all virtual bdevs with the same base
234 	 * bdev (except bdev7). This models partitioning or logical volume
235 	 * use cases.
236 	 *
237 	 * bdev7 is a virtual bdev with multiple base bdevs. One of base bdevs
238 	 * (bdev2) is shared with other virtual bdevs: bdev5 and bdev6. This
239 	 * models caching, RAID, partitioning or logical volumes use cases.
240 	 *
241 	 * bdev8 is a virtual bdev with multiple base bdevs, but these
242 	 * base bdevs are themselves virtual bdevs.
243 	 *
244 	 *                bdev8
245 	 *                  |
246 	 *            +----------+
247 	 *            |          |
248 	 *          bdev4      bdev5   bdev6   bdev7
249 	 *            |          |       |       |
250 	 *        +---+---+      +---+   +   +---+---+
251 	 *        |       |           \  |  /         \
252 	 *      bdev0   bdev1          bdev2         bdev3
253 	 */
254 
255 	bdev[0] = allocate_bdev("bdev0");
256 	rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, &bdev_ut_if);
257 	CU_ASSERT(rc == 0);
258 
259 	bdev[1] = allocate_bdev("bdev1");
260 	rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if);
261 	CU_ASSERT(rc == 0);
262 
263 	bdev[2] = allocate_bdev("bdev2");
264 	rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, &bdev_ut_if);
265 	CU_ASSERT(rc == 0);
266 
267 	bdev[3] = allocate_bdev("bdev3");
268 	rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if);
269 	CU_ASSERT(rc == 0);
270 
271 	bdev[4] = allocate_vbdev("bdev4", bdev[0], bdev[1]);
272 	rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, &bdev_ut_if);
273 	CU_ASSERT(rc == 0);
274 
275 	bdev[5] = allocate_vbdev("bdev5", bdev[2], NULL);
276 	rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if);
277 	CU_ASSERT(rc == 0);
278 
279 	bdev[6] = allocate_vbdev("bdev6", bdev[2], NULL);
280 
281 	bdev[7] = allocate_vbdev("bdev7", bdev[2], bdev[3]);
282 
283 	bdev[8] = allocate_vbdev("bdev8", bdev[4], bdev[5]);
284 
285 	/* Check tree */
286 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[4]) == true);
287 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[5]) == false);
288 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[6]) == false);
289 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[7]) == false);
290 	CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[8]) == false);
291 
292 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[4]) == true);
293 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[5]) == false);
294 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[6]) == false);
295 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[7]) == false);
296 	CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[8]) == false);
297 
298 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[4]) == false);
299 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[5]) == true);
300 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[6]) == true);
301 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[7]) == true);
302 	CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[8]) == false);
303 
304 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[4]) == false);
305 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[5]) == false);
306 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[6]) == false);
307 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[7]) == true);
308 	CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[8]) == false);
309 
310 	/* Open bdev0 read-only.  This should succeed. */
311 	rc = spdk_bdev_open(bdev[0], false, NULL, NULL, &desc[0]);
312 	CU_ASSERT(rc == 0);
313 	CU_ASSERT(desc[0] != NULL);
314 	spdk_bdev_close(desc[0]);
315 
316 	/*
317 	 * Open bdev1 read/write.  This should fail since bdev1 has been claimed
318 	 * by a vbdev module.
319 	 */
320 	rc = spdk_bdev_open(bdev[1], true, NULL, NULL, &desc[1]);
321 	CU_ASSERT(rc == -EPERM);
322 
323 	/*
324 	 * Open bdev4 read/write.  This should fail since bdev3 has been claimed
325 	 * by a vbdev module.
326 	 */
327 	rc = spdk_bdev_open(bdev[4], true, NULL, NULL, &desc[4]);
328 	CU_ASSERT(rc == -EPERM);
329 
330 	/* Open bdev4 read-only.  This should succeed. */
331 	rc = spdk_bdev_open(bdev[4], false, NULL, NULL, &desc[4]);
332 	CU_ASSERT(rc == 0);
333 	CU_ASSERT(desc[4] != NULL);
334 	spdk_bdev_close(desc[4]);
335 
336 	/*
337 	 * Open bdev8 read/write.  This should succeed since it is a leaf
338 	 * bdev.
339 	 */
340 	rc = spdk_bdev_open(bdev[8], true, NULL, NULL, &desc[8]);
341 	CU_ASSERT(rc == 0);
342 	CU_ASSERT(desc[8] != NULL);
343 	spdk_bdev_close(desc[8]);
344 
345 	/*
346 	 * Open bdev5 read/write.  This should fail since bdev4 has been claimed
347 	 * by a vbdev module.
348 	 */
349 	rc = spdk_bdev_open(bdev[5], true, NULL, NULL, &desc[5]);
350 	CU_ASSERT(rc == -EPERM);
351 
352 	/* Open bdev4 read-only.  This should succeed. */
353 	rc = spdk_bdev_open(bdev[5], false, NULL, NULL, &desc[5]);
354 	CU_ASSERT(rc == 0);
355 	CU_ASSERT(desc[5] != NULL);
356 	spdk_bdev_close(desc[5]);
357 
358 	free_vbdev(bdev[8]);
359 
360 	free_vbdev(bdev[5]);
361 	free_vbdev(bdev[6]);
362 	free_vbdev(bdev[7]);
363 
364 	free_vbdev(bdev[4]);
365 
366 	free_bdev(bdev[0]);
367 	free_bdev(bdev[1]);
368 	free_bdev(bdev[2]);
369 	free_bdev(bdev[3]);
370 }
371 
372 static void
373 bytes_to_blocks_test(void)
374 {
375 	struct spdk_bdev bdev;
376 	uint64_t offset_blocks, num_blocks;
377 
378 	memset(&bdev, 0, sizeof(bdev));
379 
380 	bdev.blocklen = 512;
381 
382 	/* All parameters valid */
383 	offset_blocks = 0;
384 	num_blocks = 0;
385 	CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0);
386 	CU_ASSERT(offset_blocks == 1);
387 	CU_ASSERT(num_blocks == 2);
388 
389 	/* Offset not a block multiple */
390 	CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0);
391 
392 	/* Length not a block multiple */
393 	CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0);
394 }
395 
396 static void
397 num_blocks_test(void)
398 {
399 	struct spdk_bdev bdev;
400 	struct spdk_bdev_desc *desc;
401 
402 	memset(&bdev, 0, sizeof(bdev));
403 	bdev.name = "num_blocks";
404 	bdev.fn_table = &fn_table;
405 	bdev.module = &bdev_ut_if;
406 	spdk_bdev_register(&bdev);
407 	spdk_bdev_notify_blockcnt_change(&bdev, 50);
408 
409 	/* Growing block number */
410 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 70) == 0);
411 	/* Shrinking block number */
412 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 30) == 0);
413 
414 	/* In case bdev opened */
415 	spdk_bdev_open(&bdev, false, NULL, NULL, &desc);
416 
417 	/* Growing block number */
418 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 80) == 0);
419 	/* Shrinking block number */
420 	CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 20) != 0);
421 
422 	spdk_bdev_close(desc);
423 	spdk_bdev_unregister(&bdev, NULL, NULL);
424 }
425 
426 static void
427 io_valid_test(void)
428 {
429 	struct spdk_bdev bdev;
430 
431 	memset(&bdev, 0, sizeof(bdev));
432 
433 	bdev.blocklen = 512;
434 	spdk_bdev_notify_blockcnt_change(&bdev, 100);
435 
436 	/* All parameters valid */
437 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 1, 2) == true);
438 
439 	/* Last valid block */
440 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 1) == true);
441 
442 	/* Offset past end of bdev */
443 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 100, 1) == false);
444 
445 	/* Offset + length past end of bdev */
446 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 2) == false);
447 
448 	/* Offset near end of uint64_t range (2^64 - 1) */
449 	CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false);
450 }
451 
452 static void
453 alias_add_del_test(void)
454 {
455 	struct spdk_bdev *bdev[2];
456 	int rc;
457 
458 	/* Creating and registering bdevs */
459 	bdev[0] = allocate_bdev("bdev0");
460 	SPDK_CU_ASSERT_FATAL(bdev[0] != 0);
461 
462 	bdev[1] = allocate_bdev("bdev1");
463 	SPDK_CU_ASSERT_FATAL(bdev[1] != 0);
464 
465 	/*
466 	 * Trying adding an alias identical to name.
467 	 * Alias is identical to name, so it can not be added to aliases list
468 	 */
469 	rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name);
470 	CU_ASSERT(rc == -EEXIST);
471 
472 	/*
473 	 * Trying to add empty alias,
474 	 * this one should fail
475 	 */
476 	rc = spdk_bdev_alias_add(bdev[0], NULL);
477 	CU_ASSERT(rc == -EINVAL);
478 
479 	/* Trying adding same alias to two different registered bdevs */
480 
481 	/* Alias is used first time, so this one should pass */
482 	rc = spdk_bdev_alias_add(bdev[0], "proper alias 0");
483 	CU_ASSERT(rc == 0);
484 
485 	/* Alias was added to another bdev, so this one should fail */
486 	rc = spdk_bdev_alias_add(bdev[1], "proper alias 0");
487 	CU_ASSERT(rc == -EEXIST);
488 
489 	/* Alias is used first time, so this one should pass */
490 	rc = spdk_bdev_alias_add(bdev[1], "proper alias 1");
491 	CU_ASSERT(rc == 0);
492 
493 	/* Trying removing an alias from registered bdevs */
494 
495 	/* Alias is not on a bdev aliases list, so this one should fail */
496 	rc = spdk_bdev_alias_del(bdev[0], "not existing");
497 	CU_ASSERT(rc == -ENOENT);
498 
499 	/* Alias is present on a bdev aliases list, so this one should pass */
500 	rc = spdk_bdev_alias_del(bdev[0], "proper alias 0");
501 	CU_ASSERT(rc == 0);
502 
503 	/* Alias is present on a bdev aliases list, so this one should pass */
504 	rc = spdk_bdev_alias_del(bdev[1], "proper alias 1");
505 	CU_ASSERT(rc == 0);
506 
507 	/* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */
508 	rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name);
509 	CU_ASSERT(rc != 0);
510 
511 	/* Unregister and free bdevs */
512 	spdk_bdev_unregister(bdev[0], NULL, NULL);
513 	spdk_bdev_unregister(bdev[1], NULL, NULL);
514 
515 	free(bdev[0]);
516 	free(bdev[1]);
517 }
518 
519 int
520 main(int argc, char **argv)
521 {
522 	CU_pSuite	suite = NULL;
523 	unsigned int	num_failures;
524 
525 	if (CU_initialize_registry() != CUE_SUCCESS) {
526 		return CU_get_error();
527 	}
528 
529 	suite = CU_add_suite("bdev", null_init, null_clean);
530 	if (suite == NULL) {
531 		CU_cleanup_registry();
532 		return CU_get_error();
533 	}
534 
535 	if (
536 		CU_add_test(suite, "bytes_to_blocks_test", bytes_to_blocks_test) == NULL ||
537 		CU_add_test(suite, "num_blocks_test", num_blocks_test) == NULL ||
538 		CU_add_test(suite, "io_valid", io_valid_test) == NULL ||
539 		CU_add_test(suite, "open_write", open_write_test) == NULL ||
540 		CU_add_test(suite, "alias_add_del", alias_add_del_test) == NULL
541 	) {
542 		CU_cleanup_registry();
543 		return CU_get_error();
544 	}
545 
546 	CU_basic_set_mode(CU_BRM_VERBOSE);
547 	CU_basic_run_tests();
548 	num_failures = CU_get_number_of_failures();
549 	CU_cleanup_registry();
550 	return num_failures;
551 }
552