xref: /spdk/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c (revision 450e2b88c79ca8bb0d0f142a277b35e066fbc042)
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 #include "spdk/string.h"
36 
37 #include "vbdev_lvol.c"
38 
39 #define SPDK_BS_PAGE_SIZE 0x1000
40 
41 int g_lvolerrno;
42 int g_lvserrno;
43 int g_cluster_size;
44 struct spdk_lvol_store *g_lvs = NULL;
45 struct spdk_lvol *g_lvol = NULL;
46 struct lvol_store_bdev *g_lvs_bdev = NULL;
47 struct spdk_bdev *g_base_bdev = NULL;
48 
49 
50 static struct spdk_bdev g_bdev = {};
51 static struct spdk_bs_dev *g_bs_dev = NULL;
52 static struct spdk_lvol_store *g_lvol_store = NULL;
53 bool lvol_store_initialize_fail = false;
54 bool lvol_store_initialize_cb_fail = false;
55 bool lvol_already_opened = false;
56 
57 int
58 spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module_if *module)
59 {
60 	if (lvol_already_opened == true)
61 		return -1;
62 
63 	lvol_already_opened = true;
64 
65 	return 0;
66 }
67 
68 void
69 spdk_vbdev_unregister(struct spdk_bdev *vbdev)
70 {
71 	SPDK_CU_ASSERT_FATAL(vbdev != NULL);
72 	vbdev->fn_table->destruct(vbdev->ctxt);
73 }
74 
75 uint64_t
76 spdk_bs_get_page_size(struct spdk_blob_store *bs)
77 {
78 	return SPDK_BS_PAGE_SIZE;
79 }
80 
81 static void
82 bdev_blob_destroy(struct spdk_bs_dev *bs_dev)
83 {
84 	CU_ASSERT(g_bs_dev != NULL);
85 	CU_ASSERT(bs_dev != NULL);
86 	CU_ASSERT(g_bs_dev == bs_dev);
87 	free(bs_dev);
88 	g_bs_dev = NULL;
89 	lvol_already_opened = false;
90 }
91 
92 struct spdk_bs_dev *
93 spdk_bdev_create_bs_dev(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb, void *remove_ctx)
94 {
95 	struct spdk_bs_dev *bs_dev;
96 
97 	if (lvol_already_opened == true)
98 		return NULL;
99 
100 	bs_dev = calloc(1, sizeof(*bs_dev));
101 	SPDK_CU_ASSERT_FATAL(bs_dev != NULL);
102 	bs_dev->destroy = bdev_blob_destroy;
103 
104 	CU_ASSERT(g_bs_dev == NULL);
105 	g_bs_dev = bs_dev;
106 	return bs_dev;
107 }
108 
109 int
110 spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o,
111 	      spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
112 {
113 	struct spdk_lvol_store *lvs;
114 	int error = 0;
115 
116 	if (lvol_store_initialize_fail)
117 		return -1;
118 
119 	if (lvol_store_initialize_cb_fail) {
120 		bs_dev->destroy(bs_dev);
121 		lvs = NULL;
122 		error = -1;
123 	} else {
124 		lvs = calloc(1, sizeof(*lvs));
125 		SPDK_CU_ASSERT_FATAL(lvs != NULL);
126 		lvs->bs_dev = bs_dev;
127 		error = 0;
128 	}
129 	cb_fn(cb_arg, lvs, error);
130 
131 	return 0;
132 }
133 
134 int
135 spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
136 {
137 	g_lvol_store = NULL;
138 	free(lvs);
139 
140 	g_bs_dev->destroy(g_bs_dev);
141 
142 	if (cb_fn != NULL)
143 		cb_fn(cb_arg, 0);
144 
145 	return 0;
146 }
147 
148 int
149 spdk_lvol_resize(struct spdk_lvol *lvol, size_t sz,
150 		 spdk_lvol_op_complete cb_fn, void *cb_arg)
151 {
152 	cb_fn(cb_arg, 0);
153 
154 	return 0;
155 }
156 
157 uint64_t
158 spdk_bs_get_cluster_size(struct spdk_blob_store *bs)
159 {
160 	return g_cluster_size;
161 }
162 
163 struct spdk_bdev *
164 spdk_bdev_get_by_name(const char *bdev_name)
165 {
166 	if (!strcmp(g_base_bdev->name, bdev_name)) {
167 		return g_base_bdev;
168 	}
169 
170 	return NULL;
171 }
172 
173 void
174 spdk_lvol_close(struct spdk_lvol *lvol)
175 {
176 	struct spdk_lvs_req *destruct_req;
177 
178 	SPDK_CU_ASSERT_FATAL(lvol == g_lvol);
179 
180 	TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
181 
182 	destruct_req = lvol->lvol_store->destruct_req;
183 	if (destruct_req && TAILQ_EMPTY(&lvol->lvol_store->lvols)) {
184 		spdk_lvs_unload(lvol->lvol_store, destruct_req->cb_fn, destruct_req->cb_arg);
185 		free(destruct_req);
186 	}
187 
188 	free(lvol->name);
189 	free(lvol);
190 	g_lvol = NULL;
191 }
192 
193 void
194 spdk_lvol_destroy(struct spdk_lvol *lvol)
195 {
196 	/* Lvol destroy and close are effectively the same from UT perspective */
197 	spdk_lvol_close(lvol);
198 }
199 
200 void
201 spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status)
202 {
203 }
204 
205 struct spdk_io_channel *spdk_lvol_get_io_channel(struct spdk_lvol *lvol)
206 {
207 	return NULL;
208 }
209 
210 void
211 spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, uint64_t len)
212 {
213 }
214 
215 void
216 spdk_bs_io_read_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
217 		     void *payload, uint64_t offset, uint64_t length,
218 		     spdk_blob_op_complete cb_fn, void *cb_arg)
219 {
220 }
221 
222 void
223 spdk_bs_io_write_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
224 		      void *payload, uint64_t offset, uint64_t length,
225 		      spdk_blob_op_complete cb_fn, void *cb_arg)
226 {
227 }
228 
229 void
230 spdk_bs_io_writev_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
231 		       struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length,
232 		       spdk_blob_op_complete cb_fn, void *cb_arg)
233 {
234 }
235 
236 void
237 spdk_bs_io_readv_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
238 		      struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length,
239 		      spdk_blob_op_complete cb_fn, void *cb_arg)
240 {
241 }
242 
243 void
244 spdk_bs_io_flush_channel(struct spdk_io_channel *channel, spdk_blob_op_complete cb_fn, void *cb_arg)
245 {
246 }
247 
248 void
249 spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module)
250 {
251 }
252 
253 int
254 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name)
255 {
256 	return 0;
257 }
258 
259 int
260 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val)
261 {
262 	return 0;
263 }
264 
265 int
266 spdk_json_write_object_begin(struct spdk_json_write_ctx *w)
267 {
268 	return 0;
269 }
270 
271 int
272 spdk_json_write_object_end(struct spdk_json_write_ctx *w)
273 {
274 	return 0;
275 }
276 
277 const char *
278 spdk_bdev_get_name(const struct spdk_bdev *bdev)
279 {
280 	return "test";
281 }
282 
283 void
284 spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, int base_bdev_count)
285 {
286 }
287 
288 void
289 spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module)
290 {
291 }
292 
293 int
294 spdk_lvol_create(struct spdk_lvol_store *lvs, size_t sz, spdk_lvol_op_with_handle_complete cb_fn,
295 		 void *cb_arg)
296 {
297 	struct spdk_lvol *lvol = calloc(1, sizeof(*lvol));
298 
299 	SPDK_CU_ASSERT_FATAL(lvol != NULL);
300 
301 	lvol->lvol_store = lvs;
302 	lvol->name = spdk_sprintf_alloc("%s", "UNIT_TEST_UUID");
303 	SPDK_CU_ASSERT_FATAL(lvol->name != NULL);
304 
305 	TAILQ_INIT(&lvs->lvols);
306 	TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link);
307 
308 	cb_fn(cb_arg, lvol, 0);
309 
310 	return 0;
311 }
312 
313 static void
314 lvol_store_op_complete(void *cb_arg, int lvserrno)
315 {
316 	g_lvserrno = lvserrno;
317 	return;
318 }
319 
320 static void
321 lvol_store_op_with_handle_complete(void *cb_arg, struct spdk_lvol_store *lvs, int lvserrno)
322 {
323 	g_lvserrno = lvserrno;
324 	g_lvol_store = lvs;
325 	return;
326 }
327 
328 static void
329 vbdev_lvol_create_complete(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
330 {
331 	g_lvolerrno = lvolerrno;
332 	g_lvol = lvol;
333 }
334 
335 static void
336 vbdev_lvol_resize_complete(void *cb_arg, int lvolerrno)
337 {
338 	g_lvolerrno = lvolerrno;
339 }
340 
341 static void
342 ut_lvs_destroy(void)
343 {
344 	int rc = 0;
345 	int sz = 10;
346 	struct spdk_lvol_store *lvs;
347 
348 	/* Lvol store is succesfully created */
349 	rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL);
350 	CU_ASSERT(rc == 0);
351 	CU_ASSERT(g_lvserrno == 0);
352 	SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
353 	CU_ASSERT(g_bs_dev != NULL);
354 
355 	lvs = g_lvol_store;
356 	g_lvol_store = NULL;
357 
358 	uuid_generate_time(lvs->uuid);
359 
360 	/* Suuccessfully create lvol, which should be destroyed with lvs later */
361 	g_lvolerrno = -1;
362 	rc = vbdev_lvol_create(lvs->uuid, sz, vbdev_lvol_create_complete, NULL);
363 	CU_ASSERT(rc == 0);
364 	CU_ASSERT(g_lvolerrno == 0);
365 	SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
366 
367 	/* Destroy lvol store */
368 	vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL);
369 	CU_ASSERT(g_lvserrno == 0);
370 	CU_ASSERT(g_lvol_store == NULL);
371 	CU_ASSERT(g_lvol == NULL);
372 }
373 
374 static void
375 ut_lvol_init(void)
376 {
377 	uuid_t wrong_uuid;
378 	int sz = 10;
379 	int rc;
380 
381 	g_lvs = calloc(1, sizeof(*g_lvs));
382 	SPDK_CU_ASSERT_FATAL(g_lvs != NULL);
383 	g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev));
384 	SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL);
385 	g_base_bdev = calloc(1, sizeof(*g_base_bdev));
386 	SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL);
387 
388 	g_lvs_bdev->lvs = g_lvs;
389 	g_lvs_bdev->bdev = g_base_bdev;
390 
391 	uuid_generate_time(g_lvs->uuid);
392 	uuid_generate_time(wrong_uuid);
393 
394 	/* Incorrect uuid set */
395 	g_lvolerrno = 0;
396 	rc = vbdev_lvol_create(wrong_uuid, sz, vbdev_lvol_create_complete, NULL);
397 	CU_ASSERT(rc == -ENODEV);
398 
399 	TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
400 
401 	/* Successful lvol create */
402 	g_lvolerrno = -1;
403 	rc = vbdev_lvol_create(g_lvs->uuid, sz, vbdev_lvol_create_complete, NULL);
404 	SPDK_CU_ASSERT_FATAL(rc == 0);
405 	CU_ASSERT(g_lvol != NULL);
406 	CU_ASSERT(g_lvolerrno == 0);
407 
408 	/* Successful lvol destruct */
409 	vbdev_lvol_destruct(g_lvol);
410 	CU_ASSERT(g_lvol == NULL);
411 
412 	TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
413 
414 	free(g_lvs);
415 	free(g_lvs_bdev);
416 	free(g_base_bdev);
417 
418 
419 }
420 
421 static void
422 ut_lvol_hotremove(void)
423 {
424 	int rc = 0;
425 
426 	lvol_store_initialize_fail = false;
427 	lvol_store_initialize_cb_fail = false;
428 	lvol_already_opened = false;
429 	g_bs_dev = NULL;
430 
431 	/* Lvol store is succesfully created */
432 	rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL);
433 	CU_ASSERT(rc == 0);
434 	CU_ASSERT(g_lvserrno == 0);
435 	CU_ASSERT(g_lvol_store != NULL);
436 	CU_ASSERT(g_bs_dev != NULL);
437 
438 	/* Hot remove callback with NULL - stability check */
439 	vbdev_lvs_hotremove_cb(NULL);
440 
441 	/* Hot remove lvs on bdev removal */
442 	vbdev_lvs_hotremove_cb(&g_bdev);
443 
444 	CU_ASSERT(g_lvol_store == NULL);
445 	CU_ASSERT(TAILQ_EMPTY(&g_spdk_lvol_pairs));
446 
447 }
448 
449 static void
450 ut_lvol_resize(void)
451 {
452 	int sz = 10;
453 	int rc = 0;
454 
455 	g_lvs = calloc(1, sizeof(*g_lvs));
456 	g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev));
457 	g_base_bdev = calloc(1, sizeof(*g_base_bdev));
458 	g_lvs_bdev->lvs = g_lvs;
459 	g_lvs_bdev->bdev = g_base_bdev;
460 
461 
462 	uuid_generate_time(g_lvs->uuid);
463 	g_base_bdev->blocklen = 4096;
464 	TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
465 
466 	/* Successful lvol create */
467 	g_lvolerrno = -1;
468 	rc = vbdev_lvol_create(g_lvs->uuid, sz, vbdev_lvol_create_complete, NULL);
469 	CU_ASSERT(rc == 0);
470 	CU_ASSERT(g_lvolerrno == 0);
471 	SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
472 
473 	g_base_bdev->ctxt = g_lvol;
474 
475 	g_base_bdev->name = spdk_sprintf_alloc("%s", g_lvol->name);
476 
477 	/* Successful lvol resize */
478 	rc = vbdev_lvol_resize(g_lvol->name, 20, vbdev_lvol_resize_complete, NULL);
479 	CU_ASSERT(rc == 0);
480 	CU_ASSERT(g_base_bdev->blockcnt == 20 * g_cluster_size / g_base_bdev->blocklen);
481 
482 	/* Resize with wrong bdev name */
483 	rc = vbdev_lvol_resize("wrong name", 20, vbdev_lvol_resize_complete, NULL);
484 	CU_ASSERT(rc != 0);
485 
486 	/* Resize with correct bdev name, but wrong lvol name */
487 	free(g_lvol->name);
488 	g_lvol->name = strdup("wrong name");
489 	SPDK_CU_ASSERT_FATAL(g_lvol->name != NULL);
490 	rc = vbdev_lvol_resize(g_base_bdev->name, 20, vbdev_lvol_resize_complete, NULL);
491 	CU_ASSERT(rc != 0);
492 
493 	/* Successful lvol destruct */
494 	vbdev_lvol_destruct(g_lvol);
495 	CU_ASSERT(g_lvol == NULL);
496 
497 	TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
498 	free(g_lvs);
499 	free(g_lvs_bdev);
500 	free(g_base_bdev->name);
501 	free(g_base_bdev);
502 }
503 
504 static void
505 ut_lvs_init(void)
506 {
507 	int rc = 0;
508 	struct spdk_lvol_store *lvs;
509 	struct spdk_bs_dev *bs_dev_temp;
510 
511 	/* spdk_lvs_init() fails */
512 	lvol_store_initialize_fail = true;
513 
514 	rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL);
515 	CU_ASSERT(rc != 0);
516 	CU_ASSERT(g_lvserrno == 0);
517 	CU_ASSERT(g_lvol_store == NULL);
518 	CU_ASSERT(g_bs_dev == NULL);
519 
520 	lvol_store_initialize_fail = false;
521 
522 	/* spdk_lvs_init_cb() fails */
523 	lvol_store_initialize_cb_fail = true;
524 
525 	rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL);
526 	CU_ASSERT(rc == 0);
527 	CU_ASSERT(g_lvserrno != 0);
528 	CU_ASSERT(g_lvol_store == NULL);
529 	CU_ASSERT(g_bs_dev == NULL);
530 
531 	lvol_store_initialize_cb_fail = false;
532 
533 	/* Lvol store is succesfully created */
534 	rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL);
535 	CU_ASSERT(rc == 0);
536 	CU_ASSERT(g_lvserrno == 0);
537 	CU_ASSERT(g_lvol_store != NULL);
538 	CU_ASSERT(g_bs_dev != NULL);
539 
540 	lvs = g_lvol_store;
541 	g_lvol_store = NULL;
542 	bs_dev_temp = g_bs_dev;
543 	g_bs_dev = NULL;
544 
545 	/* Bdev with lvol store already claimed */
546 	rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL);
547 	CU_ASSERT(rc != 0);
548 	CU_ASSERT(g_lvserrno == 0);
549 	CU_ASSERT(g_lvol_store == NULL);
550 	CU_ASSERT(g_bs_dev == NULL);
551 
552 	/* Destruct lvol store */
553 	g_bs_dev = bs_dev_temp;
554 
555 	vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL);
556 	CU_ASSERT(g_lvserrno == 0);
557 	CU_ASSERT(g_lvol_store == NULL);
558 	CU_ASSERT(g_bs_dev == NULL);
559 	free(g_bs_dev);
560 
561 }
562 
563 int main(int argc, char **argv)
564 {
565 	CU_pSuite	suite = NULL;
566 	unsigned int	num_failures;
567 
568 	if (CU_initialize_registry() != CUE_SUCCESS) {
569 		return CU_get_error();
570 	}
571 
572 	suite = CU_add_suite("lvol", NULL, NULL);
573 	if (suite == NULL) {
574 		CU_cleanup_registry();
575 		return CU_get_error();
576 	}
577 
578 	if (
579 		CU_add_test(suite, "ut_lvs_init", ut_lvs_init) == NULL ||
580 		CU_add_test(suite, "ut_lvol_init", ut_lvol_init) == NULL ||
581 		CU_add_test(suite, "ut_lvs_destroy", ut_lvs_destroy) == NULL ||
582 		CU_add_test(suite, "ut_lvol_resize", ut_lvol_resize) == NULL ||
583 		CU_add_test(suite, "lvol_hotremove", ut_lvol_hotremove) == NULL
584 	) {
585 		CU_cleanup_registry();
586 		return CU_get_error();
587 	}
588 
589 	CU_basic_set_mode(CU_BRM_VERBOSE);
590 	CU_basic_run_tests();
591 	num_failures = CU_get_number_of_failures();
592 	CU_cleanup_registry();
593 	return num_failures;
594 }
595