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