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