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