Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk_internal/cunit.h"
8 : : #include "spdk/blob.h"
9 : : #include "spdk/util.h"
10 : :
11 : : #include "spdk/bdev_module.h"
12 : : #include "thread/thread_internal.h"
13 : :
14 : : #include "common/lib/ut_multithread.c"
15 : : #include "lvol/lvol.c"
16 : :
17 : : #define DEV_BUFFER_SIZE (64 * 1024 * 1024)
18 : : #define DEV_BUFFER_BLOCKLEN (4096)
19 : : #define DEV_BUFFER_BLOCKCNT (DEV_BUFFER_SIZE / DEV_BUFFER_BLOCKLEN)
20 : : #define BS_CLUSTER_SIZE (1024 * 1024)
21 : : #define BS_FREE_CLUSTERS (DEV_BUFFER_SIZE / BS_CLUSTER_SIZE)
22 : : #define BS_PAGE_SIZE (4096)
23 : :
24 : : #define SPDK_BLOB_OPTS_CLUSTER_SZ (1024 * 1024)
25 : : #define SPDK_BLOB_OPTS_NUM_MD_PAGES UINT32_MAX
26 : : #define SPDK_BLOB_OPTS_MAX_MD_OPS 32
27 : : #define SPDK_BLOB_OPTS_MAX_CHANNEL_OPS 512
28 : :
29 : : #define SPDK_BLOB_THIN_PROV (1ULL << 0)
30 : :
31 : :
32 : 0 : DEFINE_STUB(spdk_bdev_get_name, const char *, (const struct spdk_bdev *bdev), NULL);
33 : 0 : DEFINE_STUB(spdk_bdev_get_by_name, struct spdk_bdev *, (const char *name), NULL);
34 : 0 : DEFINE_STUB(spdk_bdev_create_bs_dev_ro, int,
35 : : (const char *bdev_name, spdk_bdev_event_cb_t event_cb, void *event_ctx,
36 : : struct spdk_bs_dev **bs_dev), -ENOTSUP);
37 [ # # ]: 0 : DEFINE_STUB(spdk_blob_is_esnap_clone, bool, (const struct spdk_blob *blob), false);
38 [ # # ]: 0 : DEFINE_STUB(spdk_blob_is_degraded, bool, (const struct spdk_blob *blob), false);
39 : 0 : DEFINE_STUB_V(spdk_bs_grow_live,
40 : : (struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_arg));
41 : :
42 : :
43 : : const char *uuid = "828d9766-ae50-11e7-bd8d-001e67edf350";
44 : :
45 : : struct spdk_blob {
46 : : spdk_blob_id id;
47 : : uint32_t ref;
48 : : struct spdk_blob_store *bs;
49 : : int close_status;
50 : : int open_status;
51 : : int load_status;
52 : : TAILQ_ENTRY(spdk_blob) link;
53 : : char uuid[SPDK_UUID_STRING_LEN];
54 : : char name[SPDK_LVS_NAME_MAX];
55 : : bool thin_provisioned;
56 : : struct spdk_bs_dev *back_bs_dev;
57 : : };
58 : :
59 : : int g_lvserrno;
60 : : int g_close_super_status;
61 : : int g_resize_rc;
62 : : int g_inflate_rc;
63 : : int g_remove_rc;
64 : : bool g_lvs_rename_blob_open_error = false;
65 : : struct spdk_lvol_store *g_lvol_store;
66 : : struct spdk_lvol *g_lvol;
67 : : spdk_blob_id g_blobid = 1;
68 : : struct spdk_io_channel *g_io_channel;
69 : : struct lvol_ut_bs_dev g_esnap_dev;
70 : :
71 : : struct spdk_blob_store {
72 : : struct spdk_bs_opts bs_opts;
73 : : spdk_blob_id super_blobid;
74 : : TAILQ_HEAD(, spdk_blob) blobs;
75 : : int get_super_status;
76 : : spdk_bs_esnap_dev_create esnap_bs_dev_create;
77 : : };
78 : :
79 : : struct lvol_ut_bs_dev {
80 : : struct spdk_bs_dev bs_dev;
81 : : int init_status;
82 : : int load_status;
83 : : struct spdk_blob_store *bs;
84 : : };
85 : :
86 : : struct ut_cb_res {
87 : : void *data;
88 : : int err;
89 : : };
90 : :
91 : : void
92 : 6 : spdk_bs_inflate_blob(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
93 : : spdk_blob_id blobid, spdk_blob_op_complete cb_fn, void *cb_arg)
94 : : {
95 : 6 : cb_fn(cb_arg, g_inflate_rc);
96 : 6 : }
97 : :
98 : : void
99 : 6 : spdk_bs_blob_decouple_parent(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
100 : : spdk_blob_id blobid, spdk_blob_op_complete cb_fn, void *cb_arg)
101 : : {
102 : 6 : cb_fn(cb_arg, g_inflate_rc);
103 : 6 : }
104 : :
105 : : void
106 : 60 : spdk_bs_iter_next(struct spdk_blob_store *bs, struct spdk_blob *b,
107 : : spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
108 : : {
109 : : struct spdk_blob *next;
110 : 60 : int _errno = 0;
111 : :
112 : 60 : next = TAILQ_NEXT(b, link);
113 [ + + ]: 60 : if (next == NULL) {
114 : 24 : _errno = -ENOENT;
115 [ + + ]: 36 : } else if (next->load_status != 0) {
116 : 6 : _errno = next->load_status;
117 : : }
118 : :
119 : 60 : cb_fn(cb_arg, next, _errno);
120 : 60 : }
121 : :
122 : : void
123 : 24 : spdk_bs_iter_first(struct spdk_blob_store *bs,
124 : : spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
125 : : {
126 : : struct spdk_blob *first;
127 : 24 : int _errno = 0;
128 : :
129 : 24 : first = TAILQ_FIRST(&bs->blobs);
130 [ - + ]: 24 : if (first == NULL) {
131 : 0 : _errno = -ENOENT;
132 [ - + ]: 24 : } else if (first->load_status != 0) {
133 : 0 : _errno = first->load_status;
134 : : }
135 : :
136 : 24 : cb_fn(cb_arg, first, _errno);
137 : 24 : }
138 : :
139 : : uint64_t
140 : 0 : spdk_blob_get_num_clusters(struct spdk_blob *blob)
141 : : {
142 : 0 : return 0;
143 : : }
144 : :
145 : : void
146 : 42 : spdk_bs_get_super(struct spdk_blob_store *bs,
147 : : spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
148 : : {
149 [ + + ]: 42 : if (bs->get_super_status != 0) {
150 : 3 : cb_fn(cb_arg, 0, bs->get_super_status);
151 : : } else {
152 : 39 : cb_fn(cb_arg, bs->super_blobid, 0);
153 : : }
154 : 42 : }
155 : :
156 : : void
157 : 138 : spdk_bs_set_super(struct spdk_blob_store *bs, spdk_blob_id blobid,
158 : : spdk_bs_op_complete cb_fn, void *cb_arg)
159 : : {
160 : 138 : bs->super_blobid = blobid;
161 : 138 : cb_fn(cb_arg, 0);
162 : 138 : }
163 : :
164 : : void
165 : 45 : spdk_bs_load(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts,
166 : : spdk_bs_op_with_handle_complete cb_fn, void *cb_arg)
167 : : {
168 : 45 : struct lvol_ut_bs_dev *ut_dev = SPDK_CONTAINEROF(dev, struct lvol_ut_bs_dev, bs_dev);
169 : 45 : struct spdk_blob_store *bs = NULL;
170 : :
171 [ + + ]: 45 : if (ut_dev->load_status == 0) {
172 : 42 : bs = ut_dev->bs;
173 : : }
174 : :
175 : 45 : cb_fn(cb_arg, bs, ut_dev->load_status);
176 : 45 : }
177 : :
178 : : void
179 : 0 : spdk_bs_grow(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
180 : : spdk_bs_op_with_handle_complete cb_fn, void *cb_arg)
181 : : {
182 : 0 : cb_fn(cb_arg, NULL, -EINVAL);
183 : 0 : }
184 : :
185 : 12 : struct spdk_io_channel *spdk_bs_alloc_io_channel(struct spdk_blob_store *bs)
186 : : {
187 [ + - ]: 12 : if (g_io_channel == NULL) {
188 : 12 : g_io_channel = calloc(1, sizeof(struct spdk_io_channel));
189 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(g_io_channel != NULL);
190 : : }
191 : 12 : g_io_channel->ref++;
192 : 12 : return g_io_channel;
193 : : }
194 : :
195 : : void
196 : 12 : spdk_bs_free_io_channel(struct spdk_io_channel *channel)
197 : : {
198 : 12 : g_io_channel->ref--;
199 [ + - ]: 12 : if (g_io_channel->ref == 0) {
200 : 12 : free(g_io_channel);
201 : 12 : g_io_channel = NULL;
202 : : }
203 : 12 : return;
204 : : }
205 : :
206 : : int
207 : 336 : spdk_blob_set_xattr(struct spdk_blob *blob, const char *name, const void *value,
208 : : uint16_t value_len)
209 : : {
210 [ + + + + ]: 336 : if (!strcmp(name, "uuid")) {
211 : 165 : CU_ASSERT(value_len == SPDK_UUID_STRING_LEN);
212 [ - + - + ]: 165 : memcpy(blob->uuid, value, SPDK_UUID_STRING_LEN);
213 [ + + + - ]: 171 : } else if (!strcmp(name, "name")) {
214 : 171 : CU_ASSERT(value_len <= SPDK_LVS_NAME_MAX);
215 [ - + - + ]: 171 : memcpy(blob->name, value, value_len);
216 : : }
217 : :
218 : 336 : return 0;
219 : : }
220 : :
221 : : int
222 : 129 : spdk_blob_get_xattr_value(struct spdk_blob *blob, const char *name,
223 : : const void **value, size_t *value_len)
224 : : {
225 [ + + + + : 129 : if (!strcmp(name, "uuid") && strnlen(blob->uuid, SPDK_UUID_STRING_LEN) != 0) {
- + + + ]
226 [ - + ]: 63 : CU_ASSERT(strnlen(blob->uuid, SPDK_UUID_STRING_LEN) == (SPDK_UUID_STRING_LEN - 1));
227 : 63 : *value = blob->uuid;
228 : 63 : *value_len = SPDK_UUID_STRING_LEN;
229 : 63 : return 0;
230 [ + + + + : 66 : } else if (!strcmp(name, "name") && strnlen(blob->name, SPDK_LVS_NAME_MAX) != 0) {
- + + + ]
231 : 60 : *value = blob->name;
232 [ - + ]: 60 : *value_len = strnlen(blob->name, SPDK_LVS_NAME_MAX) + 1;
233 : 60 : return 0;
234 : : }
235 : :
236 : 6 : return -ENOENT;
237 : : }
238 : :
239 : : void
240 : 75 : spdk_blob_set_esnap_bs_dev(struct spdk_blob *blob, struct spdk_bs_dev *back_bs_dev,
241 : : spdk_blob_op_complete cb_fn, void *cb_arg)
242 : : {
243 : 75 : blob->back_bs_dev = back_bs_dev;
244 : 75 : cb_fn(cb_arg, 0);
245 : 75 : }
246 : :
247 : : bool
248 : 0 : spdk_blob_is_thin_provisioned(struct spdk_blob *blob)
249 : : {
250 [ # # ]: 0 : return blob->thin_provisioned;
251 : : }
252 : :
253 : 0 : DEFINE_STUB(spdk_bs_get_page_size, uint64_t, (struct spdk_blob_store *bs), BS_PAGE_SIZE);
254 : :
255 : : int
256 : 0 : spdk_bdev_notify_blockcnt_change(struct spdk_bdev *bdev, uint64_t size)
257 : : {
258 : 0 : bdev->blockcnt = size;
259 : 0 : return 0;
260 : : }
261 : :
262 : : const struct spdk_uuid *
263 : 0 : spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
264 : : {
265 : 0 : return &bdev->uuid;
266 : : }
267 : :
268 : : uint64_t
269 : 0 : spdk_bdev_get_num_blocks(const struct spdk_bdev *bdev)
270 : : {
271 : 0 : return bdev->blockcnt;
272 : : }
273 : :
274 : : uint32_t
275 : 0 : spdk_bdev_get_block_size(const struct spdk_bdev *bdev)
276 : : {
277 : 0 : return bdev->blocklen;
278 : : }
279 : :
280 : : static void
281 : 144 : init_dev(struct lvol_ut_bs_dev *dev)
282 : : {
283 [ - + ]: 144 : memset(dev, 0, sizeof(*dev));
284 : 144 : dev->bs_dev.blockcnt = DEV_BUFFER_BLOCKCNT;
285 : 144 : dev->bs_dev.blocklen = DEV_BUFFER_BLOCKLEN;
286 : 144 : }
287 : :
288 : : static void
289 : 69 : free_dev(struct lvol_ut_bs_dev *dev)
290 : : {
291 : 69 : struct spdk_blob_store *bs = dev->bs;
292 : : struct spdk_blob *blob, *tmp;
293 : :
294 [ - + ]: 69 : if (bs == NULL) {
295 : 0 : return;
296 : : }
297 : :
298 [ + + ]: 210 : TAILQ_FOREACH_SAFE(blob, &bs->blobs, link, tmp) {
299 [ + + ]: 141 : TAILQ_REMOVE(&bs->blobs, blob, link);
300 : 141 : free(blob);
301 : : }
302 : :
303 : 69 : free(bs);
304 : 69 : dev->bs = NULL;
305 : : }
306 : :
307 : : static void
308 : 9 : init_bdev(struct spdk_bdev *bdev, char *name, size_t size)
309 : : {
310 [ - + ]: 9 : memset(bdev, 0, sizeof(*bdev));
311 : 9 : bdev->name = name;
312 : 9 : spdk_uuid_generate(&bdev->uuid);
313 : 9 : bdev->blocklen = BS_PAGE_SIZE;
314 : 9 : bdev->phys_blocklen = BS_PAGE_SIZE;
315 : 9 : bdev->blockcnt = size / BS_PAGE_SIZE;
316 : 9 : }
317 : :
318 : : void
319 : 147 : spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
320 : : spdk_bs_op_with_handle_complete cb_fn, void *cb_arg)
321 : : {
322 : 147 : struct lvol_ut_bs_dev *ut_dev = SPDK_CONTAINEROF(dev, struct lvol_ut_bs_dev, bs_dev);
323 : : struct spdk_blob_store *bs;
324 : :
325 : 147 : bs = calloc(1, sizeof(*bs));
326 [ - + ]: 147 : SPDK_CU_ASSERT_FATAL(bs != NULL);
327 : :
328 : 147 : TAILQ_INIT(&bs->blobs);
329 : :
330 : 147 : ut_dev->bs = bs;
331 : 147 : bs->esnap_bs_dev_create = o->esnap_bs_dev_create;
332 : :
333 [ - + - + ]: 147 : memcpy(&bs->bs_opts, o, sizeof(struct spdk_bs_opts));
334 : :
335 : 147 : cb_fn(cb_arg, bs, 0);
336 : 147 : }
337 : :
338 : : void
339 : 102 : spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_arg)
340 : : {
341 : 102 : cb_fn(cb_arg, 0);
342 : 102 : }
343 : :
344 : : void
345 : 78 : spdk_bs_destroy(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn,
346 : : void *cb_arg)
347 : : {
348 : 78 : free(bs);
349 : :
350 : 78 : cb_fn(cb_arg, 0);
351 : 78 : }
352 : :
353 : : void
354 : 231 : spdk_bs_delete_blob(struct spdk_blob_store *bs, spdk_blob_id blobid,
355 : : spdk_blob_op_complete cb_fn, void *cb_arg)
356 : : {
357 : : struct spdk_blob *blob;
358 : :
359 [ + + ]: 387 : TAILQ_FOREACH(blob, &bs->blobs, link) {
360 [ + + ]: 381 : if (blob->id == blobid) {
361 [ + + ]: 225 : TAILQ_REMOVE(&bs->blobs, blob, link);
362 : 225 : free(blob);
363 : 225 : break;
364 : : }
365 : : }
366 : :
367 : 231 : cb_fn(cb_arg, g_remove_rc);
368 : 231 : }
369 : :
370 : : spdk_blob_id
371 : 486 : spdk_blob_get_id(struct spdk_blob *blob)
372 : : {
373 : 486 : return blob->id;
374 : : }
375 : :
376 : : void
377 : 201 : spdk_bs_opts_init(struct spdk_bs_opts *opts, size_t opts_size)
378 : : {
379 [ - + ]: 201 : memset(opts, 0, sizeof(*opts));
380 : 201 : opts->opts_size = opts_size;
381 : 201 : opts->cluster_sz = SPDK_BLOB_OPTS_CLUSTER_SZ;
382 : 201 : opts->num_md_pages = SPDK_BLOB_OPTS_NUM_MD_PAGES;
383 : 201 : opts->max_md_ops = SPDK_BLOB_OPTS_MAX_MD_OPS;
384 : 201 : opts->max_channel_ops = SPDK_BLOB_OPTS_MAX_CHANNEL_OPS;
385 : 201 : }
386 : :
387 : 204 : DEFINE_STUB(spdk_bs_get_cluster_size, uint64_t, (struct spdk_blob_store *bs), BS_CLUSTER_SIZE);
388 : :
389 : : void
390 : 402 : spdk_blob_close(struct spdk_blob *b, spdk_blob_op_complete cb_fn, void *cb_arg)
391 : : {
392 : 402 : b->ref--;
393 : :
394 : 402 : cb_fn(cb_arg, b->close_status);
395 : 402 : }
396 : :
397 : : void
398 : 18 : spdk_blob_resize(struct spdk_blob *blob, uint64_t sz, spdk_blob_op_complete cb_fn, void *cb_arg)
399 : : {
400 [ + + ]: 18 : if (g_resize_rc != 0) {
401 : 3 : return cb_fn(cb_arg, g_resize_rc);
402 [ + + ]: 15 : } else if (sz > DEV_BUFFER_SIZE / BS_CLUSTER_SIZE) {
403 : 3 : return cb_fn(cb_arg, -ENOMEM);
404 : : }
405 : 12 : cb_fn(cb_arg, 0);
406 : : }
407 : :
408 : 3 : DEFINE_STUB(spdk_blob_set_read_only, int, (struct spdk_blob *blob), 0);
409 : :
410 : : void
411 : 159 : spdk_blob_sync_md(struct spdk_blob *blob, spdk_blob_op_complete cb_fn, void *cb_arg)
412 : : {
413 : 159 : cb_fn(cb_arg, 0);
414 : 159 : }
415 : :
416 : : void
417 : 228 : spdk_bs_open_blob_ext(struct spdk_blob_store *bs, spdk_blob_id blobid,
418 : : struct spdk_blob_open_opts *opts, spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
419 : : {
420 : 228 : spdk_bs_open_blob(bs, blobid, cb_fn, cb_arg);
421 : 228 : }
422 : :
423 : : void
424 : 411 : spdk_bs_open_blob(struct spdk_blob_store *bs, spdk_blob_id blobid,
425 : : spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
426 : : {
427 : : struct spdk_blob *blob;
428 : :
429 [ + + + + ]: 411 : if (!g_lvs_rename_blob_open_error) {
430 [ + - ]: 756 : TAILQ_FOREACH(blob, &bs->blobs, link) {
431 [ + + ]: 756 : if (blob->id == blobid) {
432 : 408 : blob->ref++;
433 : 408 : cb_fn(cb_arg, blob, blob->open_status);
434 : 408 : return;
435 : : }
436 : : }
437 : : }
438 : :
439 : 3 : cb_fn(cb_arg, NULL, -ENOENT);
440 : : }
441 : :
442 : 0 : DEFINE_STUB(spdk_bs_free_cluster_count, uint64_t, (struct spdk_blob_store *bs), BS_FREE_CLUSTERS);
443 : :
444 : : void
445 : 183 : spdk_blob_opts_init(struct spdk_blob_opts *opts, size_t opts_size)
446 : : {
447 : 183 : opts->opts_size = opts_size;
448 : 183 : opts->num_clusters = 0;
449 : 183 : opts->thin_provision = false;
450 : 183 : opts->xattrs.count = 0;
451 : 183 : opts->xattrs.names = NULL;
452 : 183 : opts->xattrs.ctx = NULL;
453 : 183 : opts->xattrs.get_value = NULL;
454 : 183 : }
455 : :
456 : : void
457 : 228 : spdk_blob_open_opts_init(struct spdk_blob_open_opts *opts, size_t opts_size)
458 : : {
459 : 228 : opts->opts_size = opts_size;
460 : 228 : opts->clear_method = BLOB_CLEAR_WITH_DEFAULT;
461 : 228 : }
462 : :
463 : : void
464 : 138 : spdk_bs_create_blob(struct spdk_blob_store *bs,
465 : : spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
466 : : {
467 : 138 : spdk_bs_create_blob_ext(bs, NULL, cb_fn, cb_arg);
468 : 138 : }
469 : :
470 : : void
471 : 351 : spdk_bs_create_blob_ext(struct spdk_blob_store *bs, const struct spdk_blob_opts *opts,
472 : : spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
473 : : {
474 : : struct spdk_blob *b;
475 : :
476 [ + + + + ]: 351 : if (opts && opts->num_clusters > DEV_BUFFER_SIZE / BS_CLUSTER_SIZE) {
477 : 3 : cb_fn(cb_arg, 0, -1);
478 : 3 : return;
479 : : }
480 : :
481 : 348 : b = calloc(1, sizeof(*b));
482 [ - + ]: 348 : SPDK_CU_ASSERT_FATAL(b != NULL);
483 : :
484 : 348 : b->id = g_blobid++;
485 [ + + + + : 348 : if (opts != NULL && opts->thin_provision) {
+ + ]
486 : 120 : b->thin_provisioned = true;
487 : : }
488 : 348 : b->bs = bs;
489 : :
490 : 348 : TAILQ_INSERT_TAIL(&bs->blobs, b, link);
491 : 348 : cb_fn(cb_arg, b->id, 0);
492 : : }
493 : :
494 : : void
495 : 18 : spdk_bs_create_snapshot(struct spdk_blob_store *bs, spdk_blob_id blobid,
496 : : const struct spdk_blob_xattr_opts *snapshot_xattrs,
497 : : spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
498 : : {
499 : 18 : spdk_bs_create_blob_ext(bs, NULL, cb_fn, cb_arg);
500 : 18 : }
501 : :
502 : : void
503 : 12 : spdk_bs_create_clone(struct spdk_blob_store *bs, spdk_blob_id blobid,
504 : : const struct spdk_blob_xattr_opts *clone_xattrs,
505 : : spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
506 : : {
507 : 12 : spdk_bs_create_blob_ext(bs, NULL, cb_fn, cb_arg);
508 : 12 : }
509 : :
510 : : static int g_spdk_blob_get_esnap_id_errno;
511 : : static bool g_spdk_blob_get_esnap_id_called;
512 : : static void *g_spdk_blob_get_esnap_id;
513 : : static size_t g_spdk_blob_get_esnap_id_len;
514 : : int
515 : 0 : spdk_blob_get_esnap_id(struct spdk_blob *blob, const void **id, size_t *len)
516 : : {
517 : 0 : g_spdk_blob_get_esnap_id_called = true;
518 [ # # ]: 0 : if (g_spdk_blob_get_esnap_id_errno == 0) {
519 : 0 : *id = g_spdk_blob_get_esnap_id;
520 : 0 : *len = g_spdk_blob_get_esnap_id_len;
521 : : }
522 : 0 : return g_spdk_blob_get_esnap_id_errno;
523 : : }
524 : :
525 : : static spdk_blob_id g_spdk_blob_get_clones_snap_id = 0xbad;
526 : : static size_t g_spdk_blob_get_clones_count;
527 : : static spdk_blob_id *g_spdk_blob_get_clones_ids;
528 : : int
529 : 174 : spdk_blob_get_clones(struct spdk_blob_store *bs, spdk_blob_id blob_id, spdk_blob_id *ids,
530 : : size_t *count)
531 : : {
532 [ + + ]: 174 : if (blob_id != g_spdk_blob_get_clones_snap_id) {
533 : 153 : *count = 0;
534 : 153 : return 0;
535 : : }
536 [ + + - + ]: 21 : if (ids == NULL || *count < g_spdk_blob_get_clones_count) {
537 : 9 : *count = g_spdk_blob_get_clones_count;
538 : 9 : return -ENOMEM;
539 : : }
540 [ - + - + ]: 12 : memcpy(ids, g_spdk_blob_get_clones_ids, g_spdk_blob_get_clones_count * sizeof(*ids));
541 : 12 : return 0;
542 : : }
543 : :
544 : : static void
545 : 186 : lvol_store_op_with_handle_complete(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
546 : : {
547 : 186 : g_lvol_store = lvol_store;
548 : 186 : g_lvserrno = lvserrno;
549 [ + + ]: 186 : if (cb_arg != NULL) {
550 : 39 : struct ut_cb_res *res = cb_arg;
551 : :
552 : 39 : res->data = lvol_store;
553 : 39 : res->err = lvserrno;
554 : : }
555 : 186 : }
556 : :
557 : : static void
558 : 342 : lvol_op_with_handle_complete(void *cb_arg, struct spdk_lvol *lvol, int lvserrno)
559 : : {
560 : 342 : g_lvol = lvol;
561 : 342 : g_lvserrno = lvserrno;
562 [ + + ]: 342 : if (cb_arg != NULL) {
563 : 12 : struct ut_cb_res *res = cb_arg;
564 : :
565 : 12 : res->data = lvol;
566 : 12 : res->err = lvserrno;
567 : : }
568 : 342 : }
569 : :
570 : : static void
571 : 609 : op_complete(void *cb_arg, int lvserrno)
572 : : {
573 : 609 : g_lvserrno = lvserrno;
574 [ + + ]: 609 : if (cb_arg != NULL) {
575 : 48 : struct ut_cb_res *res = cb_arg;
576 : :
577 : 48 : res->err = lvserrno;
578 : : }
579 : 609 : }
580 : :
581 : : static struct ut_cb_res *
582 : 78 : ut_cb_res_clear(struct ut_cb_res *res)
583 : : {
584 [ - + ]: 78 : memset(res, 0, sizeof(*res));
585 : 78 : res->data = (void *)(uintptr_t)(-1);
586 : 78 : res->err = 0xbad;
587 : 78 : return res;
588 : : }
589 : :
590 : : static bool
591 : 6 : ut_cb_res_untouched(const struct ut_cb_res *res)
592 : : {
593 : 6 : struct ut_cb_res pristine;
594 : :
595 : 6 : ut_cb_res_clear(&pristine);
596 [ - + ]: 6 : return !memcmp(&pristine, res, sizeof(pristine));
597 : : }
598 : :
599 : : struct count_clones_ctx {
600 : : struct spdk_lvol *stop_on_lvol;
601 : : int stop_errno;
602 : : int count;
603 : : };
604 : :
605 : : static int
606 : 12 : count_clones(void *_ctx, struct spdk_lvol *lvol)
607 : : {
608 : 12 : struct count_clones_ctx *ctx = _ctx;
609 : :
610 [ + + ]: 12 : if (ctx->stop_on_lvol == lvol) {
611 : 3 : return ctx->stop_errno;
612 : : }
613 : 9 : ctx->count++;
614 : 9 : return 0;
615 : : }
616 : :
617 : : static void
618 : 3 : lvs_init_unload_success(void)
619 : : {
620 : 3 : struct lvol_ut_bs_dev dev;
621 : 3 : struct spdk_lvs_opts opts;
622 : 3 : int rc = 0;
623 : :
624 : 3 : init_dev(&dev);
625 : :
626 : 3 : spdk_lvs_opts_init(&opts);
627 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
628 : :
629 : 3 : g_lvserrno = -1;
630 : :
631 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
632 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
633 : 3 : CU_ASSERT(rc == 0);
634 : 3 : CU_ASSERT(g_lvserrno == 0);
635 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
636 : 3 : CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
637 : :
638 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
639 : : lvol_op_with_handle_complete, NULL);
640 : 3 : CU_ASSERT(g_lvserrno == 0);
641 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
642 : :
643 : : /* Lvol store has an open lvol, this unload should fail. */
644 : 3 : g_lvserrno = -1;
645 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
646 : 3 : CU_ASSERT(rc == -EBUSY);
647 : 3 : CU_ASSERT(g_lvserrno == -EBUSY);
648 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
649 : 3 : CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
650 : :
651 : : /* Lvol has to be closed (or destroyed) before unloading lvol store. */
652 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
653 : 3 : CU_ASSERT(g_lvserrno == 0);
654 : :
655 : 3 : g_lvserrno = -1;
656 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
657 : 3 : CU_ASSERT(rc == 0);
658 : 3 : CU_ASSERT(g_lvserrno == 0);
659 : 3 : g_lvol_store = NULL;
660 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
661 : :
662 : 3 : free_dev(&dev);
663 : 3 : }
664 : :
665 : : static void
666 : 3 : lvs_init_destroy_success(void)
667 : : {
668 : 3 : struct lvol_ut_bs_dev dev;
669 : 3 : struct spdk_lvs_opts opts;
670 : 3 : int rc = 0;
671 : :
672 : 3 : init_dev(&dev);
673 : :
674 : 3 : spdk_lvs_opts_init(&opts);
675 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
676 : :
677 : 3 : g_lvserrno = -1;
678 : :
679 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
680 : 3 : CU_ASSERT(rc == 0);
681 : 3 : CU_ASSERT(g_lvserrno == 0);
682 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
683 : :
684 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
685 : : lvol_op_with_handle_complete, NULL);
686 : 3 : CU_ASSERT(g_lvserrno == 0);
687 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
688 : :
689 : : /* Lvol store contains one lvol, this destroy should fail. */
690 : 3 : g_lvserrno = -1;
691 : 3 : rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
692 : 3 : CU_ASSERT(rc == -EBUSY);
693 : 3 : CU_ASSERT(g_lvserrno == -EBUSY);
694 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
695 : :
696 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
697 : 3 : CU_ASSERT(g_lvserrno == 0);
698 : :
699 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
700 : :
701 : 3 : g_lvserrno = -1;
702 : 3 : rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
703 : 3 : CU_ASSERT(rc == 0);
704 : 3 : CU_ASSERT(g_lvserrno == 0);
705 : 3 : g_lvol_store = NULL;
706 : 3 : }
707 : :
708 : : static void
709 : 3 : lvs_init_opts_success(void)
710 : : {
711 : 3 : struct lvol_ut_bs_dev dev;
712 : 3 : struct spdk_lvs_opts opts;
713 : 3 : int rc = 0;
714 : :
715 : 3 : init_dev(&dev);
716 : :
717 : 3 : g_lvserrno = -1;
718 : :
719 : 3 : spdk_lvs_opts_init(&opts);
720 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
721 : 3 : opts.cluster_sz = 8192;
722 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
723 : 3 : CU_ASSERT(rc == 0);
724 : 3 : CU_ASSERT(g_lvserrno == 0);
725 : 3 : CU_ASSERT(dev.bs->bs_opts.cluster_sz == opts.cluster_sz);
726 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
727 : :
728 : 3 : g_lvserrno = -1;
729 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
730 : 3 : CU_ASSERT(rc == 0);
731 : 3 : CU_ASSERT(g_lvserrno == 0);
732 : 3 : g_lvol_store = NULL;
733 : :
734 : 3 : free_dev(&dev);
735 : 3 : }
736 : :
737 : : static void
738 : 3 : lvs_unload_lvs_is_null_fail(void)
739 : : {
740 : 3 : int rc = 0;
741 : :
742 : 3 : g_lvserrno = -1;
743 : 3 : rc = spdk_lvs_unload(NULL, op_complete, NULL);
744 : 3 : CU_ASSERT(rc == -ENODEV);
745 : 3 : CU_ASSERT(g_lvserrno == -1);
746 : 3 : }
747 : :
748 : : static void
749 : 3 : lvs_names(void)
750 : : {
751 : 3 : struct lvol_ut_bs_dev dev_x, dev_y, dev_x2;
752 : 3 : struct spdk_lvs_opts opts_none, opts_x, opts_y, opts_full;
753 : : struct spdk_lvol_store *lvs_x, *lvs_y, *lvs_x2;
754 : 3 : int rc = 0;
755 : :
756 : 3 : init_dev(&dev_x);
757 : 3 : init_dev(&dev_y);
758 : 3 : init_dev(&dev_x2);
759 : :
760 : 3 : spdk_lvs_opts_init(&opts_none);
761 : 3 : spdk_lvs_opts_init(&opts_x);
762 : 3 : opts_x.name[0] = 'x';
763 : 3 : spdk_lvs_opts_init(&opts_y);
764 : 3 : opts_y.name[0] = 'y';
765 : 3 : spdk_lvs_opts_init(&opts_full);
766 : 3 : memset(opts_full.name, 'a', sizeof(opts_full.name));
767 : :
768 : : /* Test that opts with no name fails spdk_lvs_init(). */
769 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
770 : 3 : rc = spdk_lvs_init(&dev_x.bs_dev, &opts_none, lvol_store_op_with_handle_complete, NULL);
771 : 3 : CU_ASSERT(rc != 0);
772 : 3 : CU_ASSERT(g_lvol_store == NULL);
773 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
774 : :
775 : : /* Test that opts with no null terminator for name fails spdk_lvs_init(). */
776 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
777 : 3 : rc = spdk_lvs_init(&dev_x.bs_dev, &opts_full, lvol_store_op_with_handle_complete, NULL);
778 : 3 : CU_ASSERT(rc != 0);
779 : 3 : CU_ASSERT(g_lvol_store == NULL);
780 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
781 : :
782 : : /* Test that we can create an lvolstore with name 'x'. */
783 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
784 : 3 : g_lvol_store = NULL;
785 : 3 : rc = spdk_lvs_init(&dev_x.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
786 : 3 : CU_ASSERT(rc == 0);
787 : 3 : CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
788 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
789 : 3 : lvs_x = g_lvol_store;
790 : :
791 : : /* Test that we can create an lvolstore with name 'y'. */
792 : 3 : g_lvol_store = NULL;
793 : 3 : rc = spdk_lvs_init(&dev_y.bs_dev, &opts_y, lvol_store_op_with_handle_complete, NULL);
794 : 3 : CU_ASSERT(rc == 0);
795 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
796 : 3 : lvs_y = g_lvol_store;
797 : :
798 : : /* Test that we cannot create another lvolstore with name 'x'. */
799 : 3 : rc = spdk_lvs_init(&dev_x2.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
800 : 3 : CU_ASSERT(rc == -EEXIST);
801 : :
802 : : /* Now destroy lvolstore 'x' and then confirm we can create a new lvolstore with name 'x'. */
803 : 3 : g_lvserrno = -1;
804 : 3 : rc = spdk_lvs_destroy(lvs_x, op_complete, NULL);
805 : 3 : CU_ASSERT(rc == 0);
806 : 3 : CU_ASSERT(g_lvserrno == 0);
807 : 3 : g_lvol_store = NULL;
808 : 3 : rc = spdk_lvs_init(&dev_x.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
809 : 3 : CU_ASSERT(rc == 0);
810 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
811 : 3 : lvs_x = g_lvol_store;
812 : :
813 : : /*
814 : : * Unload lvolstore 'x'. Then we should be able to create another lvolstore with name 'x'.
815 : : */
816 : 3 : g_lvserrno = -1;
817 : 3 : rc = spdk_lvs_unload(lvs_x, op_complete, NULL);
818 : 3 : CU_ASSERT(rc == 0);
819 : 3 : CU_ASSERT(g_lvserrno == 0);
820 : 3 : g_lvol_store = NULL;
821 : 3 : rc = spdk_lvs_init(&dev_x2.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
822 : 3 : CU_ASSERT(rc == 0);
823 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
824 : 3 : lvs_x2 = g_lvol_store;
825 : :
826 : : /* Confirm that we cannot load the first lvolstore 'x'. */
827 : 3 : g_lvserrno = 0;
828 : 3 : spdk_lvs_load(&dev_x.bs_dev, lvol_store_op_with_handle_complete, NULL);
829 : 3 : CU_ASSERT(g_lvserrno != 0);
830 : :
831 : : /* Destroy the second lvolstore 'x'. Then we should be able to load the first lvolstore 'x'. */
832 : 3 : g_lvserrno = -1;
833 : 3 : rc = spdk_lvs_destroy(lvs_x2, op_complete, NULL);
834 : 3 : CU_ASSERT(rc == 0);
835 : 3 : CU_ASSERT(g_lvserrno == 0);
836 : 3 : g_lvserrno = -1;
837 : 3 : spdk_lvs_load(&dev_x.bs_dev, lvol_store_op_with_handle_complete, NULL);
838 : 3 : CU_ASSERT(g_lvserrno == 0);
839 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
840 : 3 : lvs_x = g_lvol_store;
841 : :
842 : 3 : g_lvserrno = -1;
843 : 3 : rc = spdk_lvs_destroy(lvs_x, op_complete, NULL);
844 : 3 : CU_ASSERT(rc == 0);
845 : 3 : CU_ASSERT(g_lvserrno == 0);
846 : :
847 : 3 : g_lvserrno = -1;
848 : 3 : rc = spdk_lvs_destroy(lvs_y, op_complete, NULL);
849 : 3 : CU_ASSERT(rc == 0);
850 : 3 : CU_ASSERT(g_lvserrno == 0);
851 : 3 : }
852 : :
853 : : static void
854 : 3 : lvol_create_destroy_success(void)
855 : : {
856 : 3 : struct lvol_ut_bs_dev dev;
857 : 3 : struct spdk_lvs_opts opts;
858 : 3 : int rc = 0;
859 : :
860 : 3 : init_dev(&dev);
861 : :
862 : 3 : spdk_lvs_opts_init(&opts);
863 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
864 : :
865 : 3 : g_lvserrno = -1;
866 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
867 : 3 : CU_ASSERT(rc == 0);
868 : 3 : CU_ASSERT(g_lvserrno == 0);
869 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
870 : :
871 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
872 : : lvol_op_with_handle_complete, NULL);
873 : 3 : CU_ASSERT(g_lvserrno == 0);
874 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
875 : :
876 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
877 : 3 : CU_ASSERT(g_lvserrno == 0);
878 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
879 : 3 : CU_ASSERT(g_lvserrno == 0);
880 : :
881 : 3 : g_lvserrno = -1;
882 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
883 : 3 : CU_ASSERT(rc == 0);
884 : 3 : CU_ASSERT(g_lvserrno == 0);
885 : 3 : g_lvol_store = NULL;
886 : :
887 : 3 : free_dev(&dev);
888 : 3 : }
889 : :
890 : : static void
891 : 3 : lvol_create_fail(void)
892 : : {
893 : 3 : struct lvol_ut_bs_dev dev;
894 : 3 : struct spdk_lvs_opts opts;
895 : 3 : int rc = 0;
896 : :
897 : 3 : init_dev(&dev);
898 : :
899 : 3 : spdk_lvs_opts_init(&opts);
900 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
901 : :
902 : 3 : g_lvol_store = NULL;
903 : 3 : g_lvserrno = 0;
904 : 3 : rc = spdk_lvs_init(NULL, &opts, lvol_store_op_with_handle_complete, NULL);
905 : 3 : CU_ASSERT(rc != 0);
906 : 3 : CU_ASSERT(g_lvol_store == NULL);
907 : :
908 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
909 : 3 : CU_ASSERT(rc == 0);
910 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
911 : :
912 : 3 : g_lvol = NULL;
913 : 3 : rc = spdk_lvol_create(NULL, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
914 : : lvol_op_with_handle_complete, NULL);
915 : 3 : CU_ASSERT(rc != 0);
916 : 3 : CU_ASSERT(g_lvol == NULL);
917 : :
918 : 3 : g_lvol = NULL;
919 : 3 : rc = spdk_lvol_create(g_lvol_store, "lvol", DEV_BUFFER_SIZE + 1, false, LVOL_CLEAR_WITH_DEFAULT,
920 : : lvol_op_with_handle_complete, NULL);
921 : 3 : CU_ASSERT(rc == 0);
922 : 3 : CU_ASSERT(g_lvserrno != 0);
923 : 3 : CU_ASSERT(g_lvol == NULL);
924 : :
925 : 3 : g_lvserrno = -1;
926 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
927 : 3 : CU_ASSERT(rc == 0);
928 : 3 : CU_ASSERT(g_lvserrno == 0);
929 : 3 : g_lvol_store = NULL;
930 : :
931 : 3 : free_dev(&dev);
932 : 3 : }
933 : :
934 : : static void
935 : 3 : lvol_destroy_fail(void)
936 : : {
937 : 3 : struct lvol_ut_bs_dev dev;
938 : 3 : struct spdk_lvs_opts opts;
939 : 3 : int rc = 0;
940 : :
941 : 3 : init_dev(&dev);
942 : :
943 : 3 : spdk_lvs_opts_init(&opts);
944 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
945 : :
946 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
947 : 3 : CU_ASSERT(rc == 0);
948 : 3 : CU_ASSERT(g_lvserrno == 0);
949 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
950 : :
951 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
952 : : lvol_op_with_handle_complete, NULL);
953 : 3 : CU_ASSERT(g_lvserrno == 0);
954 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
955 : :
956 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
957 : 3 : CU_ASSERT(g_lvserrno == 0);
958 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
959 : 3 : CU_ASSERT(g_lvserrno == 0);
960 : :
961 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
962 : : lvol_op_with_handle_complete, NULL);
963 : 3 : CU_ASSERT(g_lvserrno == 0);
964 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
965 : :
966 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
967 : 3 : CU_ASSERT(g_lvserrno == 0);
968 : :
969 : 3 : g_remove_rc = -1;
970 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
971 : 3 : CU_ASSERT(g_lvserrno != 0);
972 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_store->lvols));
973 : 3 : g_remove_rc = 0;
974 : :
975 : 3 : g_lvserrno = -1;
976 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
977 : 3 : CU_ASSERT(rc == 0);
978 : 3 : CU_ASSERT(g_lvserrno == 0);
979 : 3 : g_lvol_store = NULL;
980 : :
981 : 3 : free_dev(&dev);
982 : 3 : }
983 : :
984 : : static void
985 : 3 : lvol_close(void)
986 : : {
987 : 3 : struct lvol_ut_bs_dev dev;
988 : : struct spdk_lvol *lvol;
989 : : struct spdk_lvol_store *lvs;
990 : 3 : struct spdk_lvs_opts opts;
991 : 3 : struct ut_cb_res cb_res;
992 : :
993 : 3 : int rc = 0;
994 : :
995 : 3 : init_dev(&dev);
996 : :
997 : 3 : spdk_lvs_opts_init(&opts);
998 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
999 : :
1000 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete,
1001 : 3 : ut_cb_res_clear(&cb_res));
1002 : 3 : CU_ASSERT(rc == 0);
1003 : 3 : CU_ASSERT(cb_res.err == 0);
1004 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(cb_res.data != NULL);
1005 : 3 : lvs = cb_res.data;
1006 : :
1007 : 3 : spdk_lvol_create(lvs, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
1008 : 3 : lvol_op_with_handle_complete, ut_cb_res_clear(&cb_res));
1009 : 3 : CU_ASSERT(cb_res.err == 0);
1010 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(cb_res.data != NULL);
1011 : 3 : lvol = cb_res.data;
1012 [ - + ]: 3 : CU_ASSERT(lvol->action_in_progress == false);
1013 : :
1014 : : /* Fail - lvol does not exist */
1015 : 3 : spdk_lvol_close(NULL, op_complete, ut_cb_res_clear(&cb_res));
1016 : 3 : CU_ASSERT(cb_res.err == -ENODEV);
1017 [ - + ]: 3 : CU_ASSERT(lvol->action_in_progress == false);
1018 : :
1019 : : /* Fail - lvol not open */
1020 : 3 : lvol->ref_count = 0;
1021 : 3 : spdk_lvol_close(lvol, op_complete, ut_cb_res_clear(&cb_res));
1022 : 3 : CU_ASSERT(cb_res.err == -EINVAL);
1023 [ - + ]: 3 : CU_ASSERT(lvol->action_in_progress == false);
1024 : 3 : lvol->ref_count = 1;
1025 : :
1026 : : /* Fail - blob close fails */
1027 : 3 : lvol->blob->close_status = -1;
1028 : 3 : spdk_lvol_close(lvol, op_complete, ut_cb_res_clear(&cb_res));
1029 : 3 : CU_ASSERT(cb_res.err == -1);
1030 [ - + ]: 3 : CU_ASSERT(lvol->action_in_progress == false);
1031 : 3 : lvol->blob->close_status = 0;
1032 : :
1033 : : /* Success */
1034 : 3 : spdk_lvol_close(lvol, op_complete, ut_cb_res_clear(&cb_res));
1035 : 3 : CU_ASSERT(cb_res.err == 0);
1036 : :
1037 : 3 : rc = spdk_lvs_unload(lvs, op_complete, ut_cb_res_clear(&cb_res));
1038 : 3 : CU_ASSERT(rc == 0);
1039 : 3 : CU_ASSERT(cb_res.err == 0);
1040 : :
1041 : 3 : free_dev(&dev);
1042 : 3 : }
1043 : :
1044 : : static void
1045 : 3 : lvol_resize(void)
1046 : : {
1047 : 3 : struct lvol_ut_bs_dev dev;
1048 : 3 : struct spdk_lvs_opts opts;
1049 : 3 : int rc = 0;
1050 : :
1051 : 3 : init_dev(&dev);
1052 : :
1053 : 3 : spdk_lvs_opts_init(&opts);
1054 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1055 : :
1056 : 3 : g_resize_rc = 0;
1057 : 3 : g_lvserrno = -1;
1058 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1059 : 3 : CU_ASSERT(rc == 0);
1060 : 3 : CU_ASSERT(g_lvserrno == 0);
1061 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1062 : :
1063 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
1064 : : lvol_op_with_handle_complete, NULL);
1065 : 3 : CU_ASSERT(g_lvserrno == 0);
1066 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1067 : :
1068 : : /* Resize to same size */
1069 : 3 : spdk_lvol_resize(g_lvol, 10, op_complete, NULL);
1070 : 3 : CU_ASSERT(g_lvserrno == 0);
1071 : :
1072 : : /* Resize to smaller size */
1073 : 3 : spdk_lvol_resize(g_lvol, 5, op_complete, NULL);
1074 : 3 : CU_ASSERT(g_lvserrno == 0);
1075 : :
1076 : : /* Resize to bigger size */
1077 : 3 : spdk_lvol_resize(g_lvol, 15, op_complete, NULL);
1078 : 3 : CU_ASSERT(g_lvserrno == 0);
1079 : :
1080 : : /* Resize to size = 0 */
1081 : 3 : spdk_lvol_resize(g_lvol, 0, op_complete, NULL);
1082 : 3 : CU_ASSERT(g_lvserrno == 0);
1083 : :
1084 : : /* Resize to bigger size than available */
1085 : 3 : g_lvserrno = 0;
1086 : 3 : spdk_lvol_resize(g_lvol, 0xFFFFFFFF, op_complete, NULL);
1087 : 3 : CU_ASSERT(g_lvserrno != 0);
1088 : :
1089 : : /* Fail resize */
1090 : 3 : g_resize_rc = -1;
1091 : 3 : g_lvserrno = 0;
1092 : 3 : spdk_lvol_resize(g_lvol, 10, op_complete, NULL);
1093 : 3 : CU_ASSERT(g_lvserrno != 0);
1094 : 3 : g_resize_rc = 0;
1095 : :
1096 : 3 : g_resize_rc = 0;
1097 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
1098 : 3 : CU_ASSERT(g_lvserrno == 0);
1099 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
1100 : 3 : CU_ASSERT(g_lvserrno == 0);
1101 : :
1102 : 3 : g_lvserrno = -1;
1103 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1104 : 3 : CU_ASSERT(rc == 0);
1105 : 3 : CU_ASSERT(g_lvserrno == 0);
1106 : 3 : g_lvol_store = NULL;
1107 : :
1108 : 3 : free_dev(&dev);
1109 : 3 : }
1110 : :
1111 : : static void
1112 : 3 : lvol_set_read_only(void)
1113 : : {
1114 : 3 : struct lvol_ut_bs_dev dev;
1115 : 3 : struct spdk_lvs_opts opts;
1116 : 3 : int rc = 0;
1117 : : struct spdk_lvol *lvol, *clone;
1118 : :
1119 : 3 : init_dev(&dev);
1120 : :
1121 : 3 : spdk_lvs_opts_init(&opts);
1122 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1123 : :
1124 : 3 : g_lvserrno = -1;
1125 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1126 : 3 : CU_ASSERT(rc == 0);
1127 : 3 : CU_ASSERT(g_lvserrno == 0);
1128 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1129 : :
1130 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
1131 : : lvol_op_with_handle_complete, NULL);
1132 : 3 : CU_ASSERT(g_lvserrno == 0);
1133 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1134 : 3 : lvol = g_lvol;
1135 : :
1136 : : /* Set lvol as read only */
1137 : 3 : spdk_lvol_set_read_only(lvol, op_complete, NULL);
1138 : 3 : CU_ASSERT(g_lvserrno == 0);
1139 : :
1140 : : /* Create lvol clone from read only lvol */
1141 : 3 : spdk_lvol_create_clone(lvol, "clone", lvol_op_with_handle_complete, NULL);
1142 : 3 : CU_ASSERT(g_lvserrno == 0);
1143 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1144 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
1145 : 3 : clone = g_lvol;
1146 : :
1147 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1148 : 3 : CU_ASSERT(g_lvserrno == 0);
1149 : 3 : spdk_lvol_close(clone, op_complete, NULL);
1150 : 3 : CU_ASSERT(g_lvserrno == 0);
1151 : :
1152 : 3 : g_lvserrno = -1;
1153 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1154 : 3 : CU_ASSERT(rc == 0);
1155 : 3 : CU_ASSERT(g_lvserrno == 0);
1156 : 3 : g_lvol_store = NULL;
1157 : :
1158 : 3 : free_dev(&dev);
1159 : 3 : }
1160 : :
1161 : : static void
1162 : 9 : null_cb(void *ctx, struct spdk_blob_store *bs, int bserrno)
1163 : : {
1164 [ - + ]: 9 : SPDK_CU_ASSERT_FATAL(bs != NULL);
1165 : 9 : }
1166 : :
1167 : : static void
1168 : 3 : test_lvs_load(void)
1169 : : {
1170 : 3 : int rc = -1;
1171 : 3 : struct lvol_ut_bs_dev dev;
1172 : : struct spdk_lvs_with_handle_req *req;
1173 : 3 : struct spdk_bs_opts bs_opts = {};
1174 : : struct spdk_blob *super_blob;
1175 : 3 : struct spdk_lvs_opts opts = {};
1176 : :
1177 : 3 : req = calloc(1, sizeof(*req));
1178 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1179 : :
1180 : 3 : init_dev(&dev);
1181 : 3 : spdk_bs_opts_init(&bs_opts, sizeof(bs_opts));
1182 : 3 : snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
1183 : 3 : spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL);
1184 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(dev.bs != NULL);
1185 : :
1186 : : /* Fail on bs load */
1187 : 3 : dev.load_status = -1;
1188 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1189 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1190 : 3 : CU_ASSERT(g_lvserrno != 0);
1191 : 3 : CU_ASSERT(g_lvol_store == NULL);
1192 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1193 : :
1194 : : /* Fail on getting super blob */
1195 : 3 : dev.load_status = 0;
1196 : 3 : dev.bs->get_super_status = -1;
1197 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1198 : 3 : CU_ASSERT(g_lvserrno == -ENODEV);
1199 : 3 : CU_ASSERT(g_lvol_store == NULL);
1200 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1201 : :
1202 : : /* Fail on opening super blob */
1203 : 3 : g_lvserrno = 0;
1204 : 3 : super_blob = calloc(1, sizeof(*super_blob));
1205 : 3 : super_blob->id = 0x100;
1206 : 3 : super_blob->open_status = -1;
1207 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, super_blob, link);
1208 : 3 : dev.bs->super_blobid = 0x100;
1209 : 3 : dev.bs->get_super_status = 0;
1210 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1211 : 3 : CU_ASSERT(g_lvserrno == -ENODEV);
1212 : 3 : CU_ASSERT(g_lvol_store == NULL);
1213 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1214 : :
1215 : : /* Fail on getting uuid */
1216 : 3 : g_lvserrno = 0;
1217 : 3 : super_blob->open_status = 0;
1218 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1219 : 3 : CU_ASSERT(g_lvserrno == -EINVAL);
1220 : 3 : CU_ASSERT(g_lvol_store == NULL);
1221 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1222 : :
1223 : : /* Fail on getting name */
1224 : 3 : g_lvserrno = 0;
1225 : 3 : spdk_blob_set_xattr(super_blob, "uuid", uuid, SPDK_UUID_STRING_LEN);
1226 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1227 : 3 : CU_ASSERT(g_lvserrno == -EINVAL);
1228 : 3 : CU_ASSERT(g_lvol_store == NULL);
1229 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1230 : :
1231 : : /* Fail on closing super blob */
1232 : 3 : g_lvserrno = 0;
1233 : 3 : spdk_blob_set_xattr(super_blob, "name", "lvs", strlen("lvs") + 1);
1234 : 3 : super_blob->close_status = -1;
1235 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1236 : 3 : CU_ASSERT(g_lvserrno == -ENODEV);
1237 : 3 : CU_ASSERT(g_lvol_store == NULL);
1238 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1239 : :
1240 : : /* Fail on invalid options */
1241 : 3 : g_lvserrno = -1;
1242 : 3 : spdk_lvs_opts_init(&opts);
1243 : 3 : opts.opts_size = 0; /* Invalid length */
1244 : 3 : spdk_lvs_load_ext(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1245 : 3 : CU_ASSERT(g_lvserrno == -EINVAL);
1246 : 3 : CU_ASSERT(g_lvol_store == NULL);
1247 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1248 : :
1249 : : /* Load successfully */
1250 : 3 : g_lvserrno = 0;
1251 : 3 : super_blob->close_status = 0;
1252 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1253 : 3 : CU_ASSERT(g_lvserrno == 0);
1254 : 3 : CU_ASSERT(g_lvol_store != NULL);
1255 : 3 : CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
1256 : :
1257 : 3 : g_lvserrno = -1;
1258 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1259 : 3 : CU_ASSERT(rc == 0);
1260 : 3 : CU_ASSERT(g_lvserrno == 0);
1261 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
1262 : :
1263 : 3 : free(req);
1264 : 3 : free_dev(&dev);
1265 : 3 : }
1266 : :
1267 : : static void
1268 : 3 : lvols_load(void)
1269 : : {
1270 : 3 : int rc = -1;
1271 : 3 : struct lvol_ut_bs_dev dev;
1272 : : struct spdk_lvs_with_handle_req *req;
1273 : 3 : struct spdk_bs_opts bs_opts;
1274 : : struct spdk_blob *super_blob, *blob1, *blob2, *blob3;
1275 : :
1276 : 3 : req = calloc(1, sizeof(*req));
1277 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1278 : :
1279 : 3 : init_dev(&dev);
1280 : 3 : spdk_bs_opts_init(&bs_opts, sizeof(bs_opts));
1281 : 3 : snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
1282 : 3 : spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL);
1283 : 3 : super_blob = calloc(1, sizeof(*super_blob));
1284 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(super_blob != NULL);
1285 : 3 : super_blob->id = 0x100;
1286 : 3 : spdk_blob_set_xattr(super_blob, "uuid", uuid, SPDK_UUID_STRING_LEN);
1287 : 3 : spdk_blob_set_xattr(super_blob, "name", "lvs", strlen("lvs") + 1);
1288 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, super_blob, link);
1289 : 3 : dev.bs->super_blobid = 0x100;
1290 : :
1291 : : /*
1292 : : * Create 3 blobs, write different char values to the last char in the UUID
1293 : : * to make sure they are unique.
1294 : : */
1295 : 3 : blob1 = calloc(1, sizeof(*blob1));
1296 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(blob1 != NULL);
1297 : 3 : blob1->id = 0x1;
1298 : 3 : spdk_blob_set_xattr(blob1, "uuid", uuid, SPDK_UUID_STRING_LEN);
1299 : 3 : spdk_blob_set_xattr(blob1, "name", "lvol1", strlen("lvol1") + 1);
1300 : 3 : blob1->uuid[SPDK_UUID_STRING_LEN - 2] = '1';
1301 : :
1302 : 3 : blob2 = calloc(1, sizeof(*blob2));
1303 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(blob2 != NULL);
1304 : 3 : blob2->id = 0x2;
1305 : 3 : spdk_blob_set_xattr(blob2, "uuid", uuid, SPDK_UUID_STRING_LEN);
1306 : 3 : spdk_blob_set_xattr(blob2, "name", "lvol2", strlen("lvol2") + 1);
1307 : 3 : blob2->uuid[SPDK_UUID_STRING_LEN - 2] = '2';
1308 : :
1309 : 3 : blob3 = calloc(1, sizeof(*blob3));
1310 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(blob3 != NULL);
1311 : 3 : blob3->id = 0x3;
1312 : 3 : spdk_blob_set_xattr(blob3, "uuid", uuid, SPDK_UUID_STRING_LEN);
1313 : 3 : spdk_blob_set_xattr(blob3, "name", "lvol3", strlen("lvol3") + 1);
1314 : 3 : blob3->uuid[SPDK_UUID_STRING_LEN - 2] = '3';
1315 : :
1316 : : /* Load lvs with 0 blobs */
1317 : 3 : g_lvserrno = 0;
1318 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1319 : 3 : CU_ASSERT(g_lvserrno == 0);
1320 : 3 : CU_ASSERT(g_lvol_store != NULL);
1321 : 3 : CU_ASSERT(g_lvserrno == 0);
1322 : :
1323 : 3 : g_lvserrno = -1;
1324 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1325 : 3 : CU_ASSERT(rc == 0);
1326 : 3 : CU_ASSERT(g_lvserrno == 0);
1327 : :
1328 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, blob1, link);
1329 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, blob2, link);
1330 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, blob3, link);
1331 : :
1332 : : /* Load lvs again with 3 blobs, but fail on 1st one */
1333 : 3 : g_lvol_store = NULL;
1334 : 3 : g_lvserrno = 0;
1335 : 3 : blob1->load_status = -1;
1336 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1337 : 3 : CU_ASSERT(g_lvserrno != 0);
1338 : 3 : CU_ASSERT(g_lvol_store == NULL);
1339 : :
1340 : : /* Load lvs again with 3 blobs, but fail on 3rd one */
1341 : 3 : g_lvol_store = NULL;
1342 : 3 : g_lvserrno = 0;
1343 : 3 : blob1->load_status = 0;
1344 : 3 : blob2->load_status = 0;
1345 : 3 : blob3->load_status = -1;
1346 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1347 : 3 : CU_ASSERT(g_lvserrno != 0);
1348 : 3 : CU_ASSERT(g_lvol_store == NULL);
1349 : :
1350 : : /* Load lvs again with 3 blobs, with success */
1351 : 3 : g_lvol_store = NULL;
1352 : 3 : g_lvserrno = 0;
1353 : 3 : blob1->load_status = 0;
1354 : 3 : blob2->load_status = 0;
1355 : 3 : blob3->load_status = 0;
1356 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1357 : 3 : CU_ASSERT(g_lvserrno == 0);
1358 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1359 : 3 : CU_ASSERT(!TAILQ_EMPTY(&g_lvol_store->lvols));
1360 : :
1361 : 3 : g_lvserrno = -1;
1362 : 3 : /* rc = */ spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1363 : : /*
1364 : : * Disable these two asserts for now. lvolstore should allow unload as long
1365 : : * as the lvols were not opened - but this is coming a future patch.
1366 : : */
1367 : : /* CU_ASSERT(rc == 0); */
1368 : : /* CU_ASSERT(g_lvserrno == 0); */
1369 : :
1370 : 3 : free(req);
1371 : 3 : free_dev(&dev);
1372 : 3 : }
1373 : :
1374 : : static void
1375 : 3 : lvol_open(void)
1376 : : {
1377 : 3 : struct lvol_ut_bs_dev dev;
1378 : : struct spdk_lvs_with_handle_req *req;
1379 : 3 : struct spdk_bs_opts bs_opts;
1380 : : struct spdk_blob *super_blob, *blob1, *blob2, *blob3;
1381 : : struct spdk_lvol *lvol, *tmp;
1382 : :
1383 : 3 : req = calloc(1, sizeof(*req));
1384 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1385 : :
1386 : 3 : init_dev(&dev);
1387 : 3 : spdk_bs_opts_init(&bs_opts, sizeof(bs_opts));
1388 : 3 : snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
1389 : 3 : spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL);
1390 : 3 : super_blob = calloc(1, sizeof(*super_blob));
1391 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(super_blob != NULL);
1392 : 3 : super_blob->id = 0x100;
1393 : 3 : spdk_blob_set_xattr(super_blob, "uuid", uuid, SPDK_UUID_STRING_LEN);
1394 : 3 : spdk_blob_set_xattr(super_blob, "name", "lvs", strlen("lvs") + 1);
1395 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, super_blob, link);
1396 : 3 : dev.bs->super_blobid = 0x100;
1397 : :
1398 : : /*
1399 : : * Create 3 blobs, write different char values to the last char in the UUID
1400 : : * to make sure they are unique.
1401 : : */
1402 : 3 : blob1 = calloc(1, sizeof(*blob1));
1403 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(blob1 != NULL);
1404 : 3 : blob1->id = 0x1;
1405 : 3 : spdk_blob_set_xattr(blob1, "uuid", uuid, SPDK_UUID_STRING_LEN);
1406 : 3 : spdk_blob_set_xattr(blob1, "name", "lvol1", strlen("lvol1") + 1);
1407 : 3 : blob1->uuid[SPDK_UUID_STRING_LEN - 2] = '1';
1408 : :
1409 : 3 : blob2 = calloc(1, sizeof(*blob2));
1410 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(blob2 != NULL);
1411 : 3 : blob2->id = 0x2;
1412 : 3 : spdk_blob_set_xattr(blob2, "uuid", uuid, SPDK_UUID_STRING_LEN);
1413 : 3 : spdk_blob_set_xattr(blob2, "name", "lvol2", strlen("lvol2") + 1);
1414 : 3 : blob2->uuid[SPDK_UUID_STRING_LEN - 2] = '2';
1415 : :
1416 : 3 : blob3 = calloc(1, sizeof(*blob3));
1417 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(blob3 != NULL);
1418 : 3 : blob3->id = 0x2;
1419 : 3 : spdk_blob_set_xattr(blob3, "uuid", uuid, SPDK_UUID_STRING_LEN);
1420 : 3 : spdk_blob_set_xattr(blob3, "name", "lvol3", strlen("lvol3") + 1);
1421 : 3 : blob3->uuid[SPDK_UUID_STRING_LEN - 2] = '3';
1422 : :
1423 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, blob1, link);
1424 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, blob2, link);
1425 : 3 : TAILQ_INSERT_TAIL(&dev.bs->blobs, blob3, link);
1426 : :
1427 : : /* Load lvs with 3 blobs */
1428 : 3 : g_lvol_store = NULL;
1429 : 3 : g_lvserrno = 0;
1430 : 3 : spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
1431 : 3 : CU_ASSERT(g_lvserrno == 0);
1432 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1433 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_lvol_stores));
1434 : :
1435 : 3 : blob1->open_status = -1;
1436 : 3 : blob2->open_status = -1;
1437 : 3 : blob3->open_status = -1;
1438 : :
1439 : : /* Fail opening all lvols */
1440 [ + + ]: 12 : TAILQ_FOREACH_SAFE(lvol, &g_lvol_store->lvols, link, tmp) {
1441 : 9 : spdk_lvol_open(lvol, lvol_op_with_handle_complete, NULL);
1442 : 9 : CU_ASSERT(g_lvserrno != 0);
1443 : : }
1444 : :
1445 : 3 : blob1->open_status = 0;
1446 : 3 : blob2->open_status = 0;
1447 : 3 : blob3->open_status = 0;
1448 : :
1449 : : /* Open all lvols */
1450 [ + + ]: 12 : TAILQ_FOREACH_SAFE(lvol, &g_lvol_store->lvols, link, tmp) {
1451 : 9 : spdk_lvol_open(lvol, lvol_op_with_handle_complete, NULL);
1452 : 9 : CU_ASSERT(g_lvserrno == 0);
1453 : : }
1454 : :
1455 : : /* Close all lvols */
1456 [ + + ]: 12 : TAILQ_FOREACH_SAFE(lvol, &g_lvol_store->lvols, link, tmp) {
1457 : 9 : spdk_lvol_close(lvol, op_complete, NULL);
1458 : 9 : CU_ASSERT(g_lvserrno == 0);
1459 : : }
1460 : :
1461 : 3 : g_lvserrno = -1;
1462 : 3 : spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
1463 : :
1464 : 3 : free(req);
1465 : 3 : free(blob1);
1466 : 3 : free(blob2);
1467 : 3 : free(blob3);
1468 : 3 : }
1469 : :
1470 : : static void
1471 : 3 : lvol_snapshot(void)
1472 : : {
1473 : 3 : struct lvol_ut_bs_dev dev;
1474 : : struct spdk_lvol *lvol;
1475 : 3 : struct spdk_lvs_opts opts;
1476 : 3 : int rc = 0;
1477 : :
1478 : 3 : init_dev(&dev);
1479 : :
1480 : 3 : spdk_lvs_opts_init(&opts);
1481 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1482 : :
1483 : 3 : g_lvserrno = -1;
1484 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1485 : 3 : CU_ASSERT(rc == 0);
1486 : 3 : CU_ASSERT(g_lvserrno == 0);
1487 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1488 : :
1489 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
1490 : : lvol_op_with_handle_complete, NULL);
1491 : 3 : CU_ASSERT(g_lvserrno == 0);
1492 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1493 : :
1494 : 3 : lvol = g_lvol;
1495 : :
1496 : 3 : spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
1497 : 3 : CU_ASSERT(g_lvserrno == 0);
1498 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1499 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
1500 : :
1501 : : /* Lvol has to be closed (or destroyed) before unloading lvol store. */
1502 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
1503 : 3 : CU_ASSERT(g_lvserrno == 0);
1504 : 3 : g_lvserrno = -1;
1505 : :
1506 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1507 : 3 : CU_ASSERT(g_lvserrno == 0);
1508 : 3 : g_lvserrno = -1;
1509 : :
1510 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1511 : 3 : CU_ASSERT(rc == 0);
1512 : 3 : CU_ASSERT(g_lvserrno == 0);
1513 : 3 : g_lvol_store = NULL;
1514 : :
1515 : 3 : free_dev(&dev);
1516 : 3 : }
1517 : :
1518 : : static void
1519 : 3 : lvol_snapshot_fail(void)
1520 : : {
1521 : 3 : struct lvol_ut_bs_dev dev;
1522 : : struct spdk_lvol *lvol, *snap;
1523 : 3 : struct spdk_lvs_opts opts;
1524 : 3 : int rc = 0;
1525 : :
1526 : 3 : init_dev(&dev);
1527 : :
1528 : 3 : spdk_lvs_opts_init(&opts);
1529 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1530 : :
1531 : 3 : g_lvserrno = -1;
1532 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1533 : 3 : CU_ASSERT(rc == 0);
1534 : 3 : CU_ASSERT(g_lvserrno == 0);
1535 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1536 : :
1537 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
1538 : : lvol_op_with_handle_complete, NULL);
1539 : 3 : CU_ASSERT(g_lvserrno == 0);
1540 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1541 : :
1542 : 3 : lvol = g_lvol;
1543 : :
1544 : 3 : spdk_lvol_create_snapshot(NULL, "snap", lvol_op_with_handle_complete, NULL);
1545 : 3 : CU_ASSERT(g_lvserrno < 0);
1546 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
1547 : :
1548 : 3 : spdk_lvol_create_snapshot(lvol, "", lvol_op_with_handle_complete, NULL);
1549 : 3 : CU_ASSERT(g_lvserrno < 0);
1550 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
1551 : :
1552 : 3 : spdk_lvol_create_snapshot(lvol, NULL, lvol_op_with_handle_complete, NULL);
1553 : 3 : CU_ASSERT(g_lvserrno < 0);
1554 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
1555 : :
1556 : 3 : spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
1557 : 3 : CU_ASSERT(g_lvserrno == 0);
1558 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1559 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
1560 : :
1561 : 3 : snap = g_lvol;
1562 : :
1563 : 3 : spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
1564 : 3 : CU_ASSERT(g_lvserrno < 0);
1565 : :
1566 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1567 : 3 : CU_ASSERT(g_lvserrno == 0);
1568 : 3 : g_lvserrno = -1;
1569 : :
1570 : 3 : spdk_lvol_close(snap, op_complete, NULL);
1571 : 3 : CU_ASSERT(g_lvserrno == 0);
1572 : 3 : g_lvserrno = -1;
1573 : :
1574 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1575 : 3 : CU_ASSERT(rc == 0);
1576 : 3 : CU_ASSERT(g_lvserrno == 0);
1577 : 3 : g_lvol_store = NULL;
1578 : :
1579 : 3 : free_dev(&dev);
1580 : 3 : }
1581 : :
1582 : : static void
1583 : 3 : lvol_clone(void)
1584 : : {
1585 : 3 : struct lvol_ut_bs_dev dev;
1586 : : struct spdk_lvol *lvol;
1587 : : struct spdk_lvol *snap;
1588 : 3 : struct spdk_lvs_opts opts;
1589 : 3 : int rc = 0;
1590 : :
1591 : 3 : init_dev(&dev);
1592 : :
1593 : 3 : spdk_lvs_opts_init(&opts);
1594 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1595 : :
1596 : 3 : g_lvserrno = -1;
1597 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1598 : 3 : CU_ASSERT(rc == 0);
1599 : 3 : CU_ASSERT(g_lvserrno == 0);
1600 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1601 : :
1602 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
1603 : : lvol_op_with_handle_complete, NULL);
1604 : 3 : CU_ASSERT(g_lvserrno == 0);
1605 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1606 : :
1607 : 3 : lvol = g_lvol;
1608 : :
1609 : 3 : spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
1610 : 3 : CU_ASSERT(g_lvserrno == 0);
1611 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1612 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
1613 : :
1614 : 3 : snap = g_lvol;
1615 : :
1616 : 3 : spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
1617 : 3 : CU_ASSERT(g_lvserrno == 0);
1618 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1619 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
1620 : :
1621 : : /* Lvol has to be closed (or destroyed) before unloading lvol store. */
1622 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
1623 : 3 : CU_ASSERT(g_lvserrno == 0);
1624 : 3 : g_lvserrno = -1;
1625 : :
1626 : 3 : spdk_lvol_close(snap, op_complete, NULL);
1627 : 3 : CU_ASSERT(g_lvserrno == 0);
1628 : 3 : g_lvserrno = -1;
1629 : :
1630 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1631 : 3 : CU_ASSERT(g_lvserrno == 0);
1632 : 3 : g_lvserrno = -1;
1633 : :
1634 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1635 : 3 : CU_ASSERT(rc == 0);
1636 : 3 : CU_ASSERT(g_lvserrno == 0);
1637 : 3 : g_lvol_store = NULL;
1638 : :
1639 : 3 : free_dev(&dev);
1640 : 3 : }
1641 : :
1642 : : static void
1643 : 3 : lvol_clone_fail(void)
1644 : : {
1645 : 3 : struct lvol_ut_bs_dev dev;
1646 : : struct spdk_lvol *lvol;
1647 : : struct spdk_lvol *snap;
1648 : : struct spdk_lvol *clone;
1649 : 3 : struct spdk_lvs_opts opts;
1650 : 3 : int rc = 0;
1651 : :
1652 : 3 : init_dev(&dev);
1653 : :
1654 : 3 : spdk_lvs_opts_init(&opts);
1655 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1656 : :
1657 : 3 : g_lvserrno = -1;
1658 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1659 : 3 : CU_ASSERT(rc == 0);
1660 : 3 : CU_ASSERT(g_lvserrno == 0);
1661 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1662 : :
1663 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
1664 : : lvol_op_with_handle_complete, NULL);
1665 : 3 : CU_ASSERT(g_lvserrno == 0);
1666 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1667 : :
1668 : 3 : lvol = g_lvol;
1669 : :
1670 : 3 : spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
1671 : 3 : CU_ASSERT(g_lvserrno == 0);
1672 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1673 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
1674 : :
1675 : 3 : snap = g_lvol;
1676 : :
1677 : 3 : spdk_lvol_create_clone(NULL, "clone", lvol_op_with_handle_complete, NULL);
1678 : 3 : CU_ASSERT(g_lvserrno < 0);
1679 : :
1680 : 3 : spdk_lvol_create_clone(snap, "", lvol_op_with_handle_complete, NULL);
1681 : 3 : CU_ASSERT(g_lvserrno < 0);
1682 : :
1683 : 3 : spdk_lvol_create_clone(snap, NULL, lvol_op_with_handle_complete, NULL);
1684 : 3 : CU_ASSERT(g_lvserrno < 0);
1685 : :
1686 : 3 : spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
1687 : 3 : CU_ASSERT(g_lvserrno == 0);
1688 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1689 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
1690 : :
1691 : 3 : clone = g_lvol;
1692 : :
1693 : 3 : spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
1694 : 3 : CU_ASSERT(g_lvserrno < 0);
1695 : :
1696 : : /* Lvol has to be closed (or destroyed) before unloading lvol store. */
1697 : 3 : spdk_lvol_close(clone, op_complete, NULL);
1698 : 3 : CU_ASSERT(g_lvserrno == 0);
1699 : 3 : g_lvserrno = -1;
1700 : :
1701 : 3 : spdk_lvol_close(snap, op_complete, NULL);
1702 : 3 : CU_ASSERT(g_lvserrno == 0);
1703 : 3 : g_lvserrno = -1;
1704 : :
1705 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1706 : 3 : CU_ASSERT(g_lvserrno == 0);
1707 : 3 : g_lvserrno = -1;
1708 : :
1709 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1710 : 3 : CU_ASSERT(rc == 0);
1711 : 3 : CU_ASSERT(g_lvserrno == 0);
1712 : 3 : g_lvol_store = NULL;
1713 : :
1714 : 3 : free_dev(&dev);
1715 : 3 : }
1716 : :
1717 : : static void
1718 : 3 : lvol_iter_clones(void)
1719 : : {
1720 : 3 : struct lvol_ut_bs_dev dev;
1721 : : struct spdk_lvol *lvol, *snap, *clone;
1722 : 3 : struct spdk_lvs_opts opts;
1723 : 3 : struct count_clones_ctx ctx = { 0 };
1724 : 3 : spdk_blob_id mock_clones[2];
1725 : 3 : int rc = 0;
1726 : :
1727 : 3 : init_dev(&dev);
1728 : :
1729 : 3 : spdk_lvs_opts_init(&opts);
1730 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1731 : :
1732 : 3 : g_spdk_blob_get_clones_ids = mock_clones;
1733 : :
1734 : 3 : g_lvserrno = -1;
1735 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1736 : 3 : CU_ASSERT(rc == 0);
1737 : 3 : CU_ASSERT(g_lvserrno == 0);
1738 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1739 : :
1740 : : /* Create a volume */
1741 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
1742 : : lvol_op_with_handle_complete, NULL);
1743 : 3 : CU_ASSERT(g_lvserrno == 0);
1744 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1745 : 3 : lvol = g_lvol;
1746 : :
1747 : : /* Create a snapshot of the volume */
1748 : 3 : spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
1749 : 3 : CU_ASSERT(g_lvserrno == 0);
1750 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1751 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
1752 : 3 : snap = g_lvol;
1753 : :
1754 : 3 : g_spdk_blob_get_clones_snap_id = snap->blob_id;
1755 : 3 : g_spdk_blob_get_clones_count = 1;
1756 : 3 : mock_clones[0] = lvol->blob_id;
1757 : :
1758 : : /* The snapshot turned the lvol into a clone, so the snapshot now has one clone. */
1759 : 3 : memset(&ctx, 0, sizeof(ctx));
1760 : 3 : rc = spdk_lvol_iter_immediate_clones(snap, count_clones, &ctx);
1761 : 3 : CU_ASSERT(rc == 0);
1762 : 3 : CU_ASSERT(ctx.count == 1);
1763 : :
1764 : : /* The snapshotted volume still has no clones. */
1765 : 3 : memset(&ctx, 0, sizeof(ctx));
1766 : 3 : rc = spdk_lvol_iter_immediate_clones(lvol, count_clones, &ctx);
1767 : 3 : CU_ASSERT(rc == 0);
1768 : 3 : CU_ASSERT(ctx.count == 0);
1769 : :
1770 : : /* Iteration can be stopped and the return value is propagated. */
1771 : 3 : memset(&ctx, 0, sizeof(ctx));
1772 : 3 : ctx.stop_on_lvol = lvol;
1773 : 3 : ctx.stop_errno = 42;
1774 : 3 : rc = spdk_lvol_iter_immediate_clones(snap, count_clones, &ctx);
1775 : 3 : CU_ASSERT(rc == 42);
1776 : 3 : CU_ASSERT(ctx.count == 0);
1777 : :
1778 : : /* Create a clone of the snapshot */
1779 : 3 : spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
1780 : 3 : CU_ASSERT(g_lvserrno == 0);
1781 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1782 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
1783 : 3 : clone = g_lvol;
1784 : :
1785 : 3 : g_spdk_blob_get_clones_count = 2;
1786 : 3 : mock_clones[1] = clone->blob_id;
1787 : :
1788 : : /* The snapshot now has two clones */
1789 : 3 : memset(&ctx, 0, sizeof(ctx));
1790 : 3 : rc = spdk_lvol_iter_immediate_clones(snap, count_clones, &ctx);
1791 : 3 : CU_ASSERT(rc == 0);
1792 : 3 : CU_ASSERT(ctx.count == 2);
1793 : :
1794 : : /* Cleanup */
1795 : 3 : g_spdk_blob_get_clones_snap_id = 0xbad;
1796 : 3 : g_spdk_blob_get_clones_count = 0;
1797 : 3 : g_spdk_blob_get_clones_ids = NULL;
1798 : :
1799 : 3 : spdk_lvol_close(snap, op_complete, NULL);
1800 : 3 : CU_ASSERT(g_lvserrno == 0);
1801 : :
1802 : 3 : g_lvserrno = -1;
1803 : 3 : spdk_lvol_close(clone, op_complete, NULL);
1804 : 3 : CU_ASSERT(g_lvserrno == 0);
1805 : :
1806 : 3 : g_lvserrno = -1;
1807 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1808 : 3 : CU_ASSERT(g_lvserrno == 0);
1809 : :
1810 : 3 : g_lvserrno = -1;
1811 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
1812 : 3 : CU_ASSERT(rc == 0);
1813 : 3 : CU_ASSERT(g_lvserrno == 0);
1814 : 3 : g_lvol_store = NULL;
1815 : 3 : g_lvol = NULL;
1816 : :
1817 : 3 : free_dev(&dev);
1818 : 3 : }
1819 : :
1820 : : static void
1821 : 3 : lvol_names(void)
1822 : : {
1823 : 3 : struct lvol_ut_bs_dev dev;
1824 : 3 : struct spdk_lvs_opts opts;
1825 : : struct spdk_lvol_store *lvs;
1826 : : struct spdk_lvol *lvol, *lvol2;
1827 : 3 : char fullname[SPDK_LVOL_NAME_MAX];
1828 : 3 : int rc = 0;
1829 : :
1830 : 3 : init_dev(&dev);
1831 : :
1832 : 3 : spdk_lvs_opts_init(&opts);
1833 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1834 : :
1835 : 3 : g_lvserrno = -1;
1836 : 3 : g_lvol_store = NULL;
1837 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1838 : 3 : CU_ASSERT(rc == 0);
1839 : 3 : CU_ASSERT(g_lvserrno == 0);
1840 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1841 : 3 : lvs = g_lvol_store;
1842 : :
1843 : 3 : rc = spdk_lvol_create(lvs, NULL, 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1844 : : NULL);
1845 : 3 : CU_ASSERT(rc == -EINVAL);
1846 : :
1847 : 3 : rc = spdk_lvol_create(lvs, "", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1848 : : NULL);
1849 : 3 : CU_ASSERT(rc == -EINVAL);
1850 : :
1851 : 3 : memset(fullname, 'x', sizeof(fullname));
1852 : 3 : rc = spdk_lvol_create(lvs, fullname, 1, false, LVOL_CLEAR_WITH_DEFAULT,
1853 : : lvol_op_with_handle_complete, NULL);
1854 : 3 : CU_ASSERT(rc == -EINVAL);
1855 : :
1856 : 3 : g_lvserrno = -1;
1857 : 3 : rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1858 : : NULL);
1859 : 3 : CU_ASSERT(rc == 0);
1860 : 3 : CU_ASSERT(g_lvserrno == 0);
1861 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1862 : 3 : lvol = g_lvol;
1863 : :
1864 : 3 : rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1865 : : NULL);
1866 : 3 : CU_ASSERT(rc == -EEXIST);
1867 : :
1868 : 3 : g_lvserrno = -1;
1869 : 3 : rc = spdk_lvol_create(lvs, "lvol2", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1870 : : NULL);
1871 : 3 : CU_ASSERT(rc == 0);
1872 : 3 : CU_ASSERT(g_lvserrno == 0);
1873 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1874 : 3 : lvol2 = g_lvol;
1875 : :
1876 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1877 : 3 : spdk_lvol_destroy(lvol, op_complete, NULL);
1878 : :
1879 : 3 : g_lvserrno = -1;
1880 : 3 : g_lvol = NULL;
1881 : 3 : rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1882 : : NULL);
1883 : 3 : CU_ASSERT(rc == 0);
1884 : 3 : CU_ASSERT(g_lvserrno == 0);
1885 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1886 : 3 : lvol = g_lvol;
1887 : :
1888 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1889 : 3 : spdk_lvol_destroy(lvol, op_complete, NULL);
1890 : :
1891 : 3 : spdk_lvol_close(lvol2, op_complete, NULL);
1892 : 3 : spdk_lvol_destroy(lvol2, op_complete, NULL);
1893 : :
1894 : : /* Simulate creating two lvols with same name simultaneously. */
1895 : 3 : lvol = calloc(1, sizeof(*lvol));
1896 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(lvol != NULL);
1897 : 3 : snprintf(lvol->name, sizeof(lvol->name), "tmp_name");
1898 : 3 : TAILQ_INSERT_TAIL(&lvs->pending_lvols, lvol, link);
1899 : 3 : rc = spdk_lvol_create(lvs, "tmp_name", 1, false, LVOL_CLEAR_WITH_DEFAULT,
1900 : : lvol_op_with_handle_complete, NULL);
1901 : 3 : CU_ASSERT(rc == -EEXIST);
1902 : :
1903 : : /* Remove name from temporary list and try again. */
1904 [ - + ]: 3 : TAILQ_REMOVE(&lvs->pending_lvols, lvol, link);
1905 : 3 : free(lvol);
1906 : :
1907 : 3 : rc = spdk_lvol_create(lvs, "tmp_name", 1, false, LVOL_CLEAR_WITH_DEFAULT,
1908 : : lvol_op_with_handle_complete, NULL);
1909 : 3 : CU_ASSERT(rc == 0);
1910 : 3 : CU_ASSERT(g_lvserrno == 0);
1911 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1912 : 3 : lvol = g_lvol;
1913 : :
1914 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1915 : 3 : spdk_lvol_destroy(lvol, op_complete, NULL);
1916 : :
1917 : 3 : g_lvserrno = -1;
1918 : 3 : rc = spdk_lvs_destroy(lvs, op_complete, NULL);
1919 : 3 : CU_ASSERT(rc == 0);
1920 : 3 : CU_ASSERT(g_lvserrno == 0);
1921 : 3 : g_lvol_store = NULL;
1922 : 3 : }
1923 : :
1924 : : static void
1925 : 3 : lvol_rename(void)
1926 : : {
1927 : 3 : struct lvol_ut_bs_dev dev;
1928 : 3 : struct spdk_lvs_opts opts;
1929 : : struct spdk_lvol_store *lvs;
1930 : : struct spdk_lvol *lvol, *lvol2;
1931 : 3 : int rc = 0;
1932 : :
1933 : 3 : init_dev(&dev);
1934 : :
1935 : 3 : spdk_lvs_opts_init(&opts);
1936 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
1937 : :
1938 : 3 : g_lvserrno = -1;
1939 : 3 : g_lvol_store = NULL;
1940 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
1941 : 3 : CU_ASSERT(rc == 0);
1942 : 3 : CU_ASSERT(g_lvserrno == 0);
1943 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
1944 : 3 : lvs = g_lvol_store;
1945 : :
1946 : : /* Trying to create new lvol */
1947 : 3 : g_lvserrno = -1;
1948 : 3 : rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1949 : : NULL);
1950 : 3 : CU_ASSERT(rc == 0);
1951 : 3 : CU_ASSERT(g_lvserrno == 0);
1952 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1953 : 3 : lvol = g_lvol;
1954 : :
1955 : : /* Trying to create second lvol with existing lvol name */
1956 : 3 : g_lvserrno = -1;
1957 : 3 : g_lvol = NULL;
1958 : 3 : rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1959 : : NULL);
1960 : 3 : CU_ASSERT(rc == -EEXIST);
1961 : 3 : CU_ASSERT(g_lvserrno == -1);
1962 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
1963 : :
1964 : : /* Trying to create second lvol with non existing name */
1965 : 3 : g_lvserrno = -1;
1966 : 3 : rc = spdk_lvol_create(lvs, "lvol2", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
1967 : : NULL);
1968 : 3 : CU_ASSERT(rc == 0);
1969 : 3 : CU_ASSERT(g_lvserrno == 0);
1970 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
1971 : 3 : lvol2 = g_lvol;
1972 : :
1973 : : /* Trying to rename lvol with not existing name */
1974 : 3 : spdk_lvol_rename(lvol, "lvol_new", op_complete, NULL);
1975 : 3 : CU_ASSERT(g_lvserrno == 0);
1976 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvol->name, "lvol_new");
1977 : :
1978 : : /* Trying to rename lvol with other lvol name */
1979 : 3 : spdk_lvol_rename(lvol2, "lvol_new", op_complete, NULL);
1980 : 3 : CU_ASSERT(g_lvserrno == -EEXIST);
1981 [ - + ]: 3 : CU_ASSERT_STRING_NOT_EQUAL(lvol2->name, "lvol_new");
1982 : :
1983 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
1984 : 3 : spdk_lvol_destroy(lvol, op_complete, NULL);
1985 : :
1986 : 3 : spdk_lvol_close(lvol2, op_complete, NULL);
1987 : 3 : spdk_lvol_destroy(lvol2, op_complete, NULL);
1988 : :
1989 : 3 : g_lvserrno = -1;
1990 : 3 : rc = spdk_lvs_destroy(lvs, op_complete, NULL);
1991 : 3 : CU_ASSERT(rc == 0);
1992 : 3 : CU_ASSERT(g_lvserrno == 0);
1993 : 3 : g_lvol_store = NULL;
1994 : 3 : }
1995 : :
1996 : : static void
1997 : 3 : lvs_rename(void)
1998 : : {
1999 : 3 : struct lvol_ut_bs_dev dev;
2000 : 3 : struct spdk_lvs_opts opts;
2001 : : struct spdk_lvol_store *lvs, *lvs2;
2002 : 3 : int rc = 0;
2003 : :
2004 : 3 : init_dev(&dev);
2005 : :
2006 : 3 : spdk_lvs_opts_init(&opts);
2007 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2008 : 3 : g_lvserrno = -1;
2009 : 3 : g_lvol_store = NULL;
2010 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2011 : 3 : CU_ASSERT(rc == 0);
2012 : 3 : CU_ASSERT(g_lvserrno == 0);
2013 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2014 : 3 : lvs = g_lvol_store;
2015 : :
2016 : 3 : spdk_lvs_opts_init(&opts);
2017 : 3 : snprintf(opts.name, sizeof(opts.name), "unimportant_lvs_name");
2018 : 3 : g_lvserrno = -1;
2019 : 3 : g_lvol_store = NULL;
2020 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2021 : 3 : CU_ASSERT(rc == 0);
2022 : 3 : CU_ASSERT(g_lvserrno == 0);
2023 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2024 : 3 : lvs2 = g_lvol_store;
2025 : :
2026 : : /* Trying to rename lvs with new name */
2027 : 3 : spdk_lvs_rename(lvs, "new_lvs_name", op_complete, NULL);
2028 : 3 : CU_ASSERT(g_lvserrno == 0);
2029 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
2030 : :
2031 : : /* Trying to rename lvs with name lvs already has */
2032 : 3 : spdk_lvs_rename(lvs, "new_lvs_name", op_complete, NULL);
2033 : 3 : CU_ASSERT(g_lvserrno == 0);
2034 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
2035 : :
2036 : : /* Trying to rename lvs with name already existing */
2037 : 3 : spdk_lvs_rename(lvs2, "new_lvs_name", op_complete, NULL);
2038 : 3 : CU_ASSERT(g_lvserrno == -EEXIST);
2039 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs2->name, "unimportant_lvs_name");
2040 : :
2041 : : /* Trying to rename lvs with another rename process started with the same name */
2042 : : /* Simulate renaming process in progress */
2043 : 3 : snprintf(lvs2->new_name, sizeof(lvs2->new_name), "another_new_lvs_name");
2044 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs2->new_name, "another_new_lvs_name");
2045 : : /* Start second process */
2046 : 3 : spdk_lvs_rename(lvs, "another_new_lvs_name", op_complete, NULL);
2047 : 3 : CU_ASSERT(g_lvserrno == -EEXIST);
2048 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
2049 : : /* reverting lvs2 new name to proper value */
2050 : 3 : snprintf(lvs2->new_name, sizeof(lvs2->new_name), "unimportant_lvs_name");
2051 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs2->new_name, "unimportant_lvs_name");
2052 : :
2053 : : /* Simulate error while lvs rename */
2054 : 3 : g_lvs_rename_blob_open_error = true;
2055 : 3 : spdk_lvs_rename(lvs, "complete_new_lvs_name", op_complete, NULL);
2056 : 3 : CU_ASSERT(g_lvserrno != 0);
2057 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
2058 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(lvs->new_name, "new_lvs_name");
2059 : 3 : g_lvs_rename_blob_open_error = false;
2060 : :
2061 : 3 : g_lvserrno = -1;
2062 : 3 : rc = spdk_lvs_destroy(lvs, op_complete, NULL);
2063 : 3 : CU_ASSERT(rc == 0);
2064 : 3 : CU_ASSERT(g_lvserrno == 0);
2065 : 3 : g_lvol_store = NULL;
2066 : :
2067 : 3 : g_lvserrno = -1;
2068 : 3 : rc = spdk_lvs_destroy(lvs2, op_complete, NULL);
2069 : 3 : CU_ASSERT(rc == 0);
2070 : 3 : CU_ASSERT(g_lvserrno == 0);
2071 : 3 : g_lvol_store = NULL;
2072 : 3 : }
2073 : : static void
2074 : 3 : lvol_refcnt(void)
2075 : : {
2076 : 3 : struct lvol_ut_bs_dev dev;
2077 : 3 : struct spdk_lvs_opts opts;
2078 : : struct spdk_lvol *lvol;
2079 : 3 : int rc = 0;
2080 : :
2081 : 3 : init_dev(&dev);
2082 : :
2083 : 3 : spdk_lvs_opts_init(&opts);
2084 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2085 : :
2086 : 3 : g_lvserrno = -1;
2087 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2088 : 3 : CU_ASSERT(rc == 0);
2089 : 3 : CU_ASSERT(g_lvserrno == 0);
2090 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2091 : :
2092 : :
2093 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
2094 : : lvol_op_with_handle_complete, NULL);
2095 : :
2096 : 3 : CU_ASSERT(g_lvserrno == 0);
2097 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2098 : 3 : CU_ASSERT(g_lvol->ref_count == 1);
2099 : :
2100 : 3 : lvol = g_lvol;
2101 : 3 : spdk_lvol_open(g_lvol, lvol_op_with_handle_complete, NULL);
2102 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2103 : 3 : CU_ASSERT(lvol->ref_count == 2);
2104 : :
2105 : : /* Trying to destroy lvol while its open should fail */
2106 : 3 : spdk_lvol_destroy(lvol, op_complete, NULL);
2107 : 3 : CU_ASSERT(g_lvserrno != 0);
2108 : :
2109 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
2110 : 3 : CU_ASSERT(lvol->ref_count == 1);
2111 : 3 : CU_ASSERT(g_lvserrno == 0);
2112 : :
2113 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
2114 : 3 : CU_ASSERT(lvol->ref_count == 0);
2115 : 3 : CU_ASSERT(g_lvserrno == 0);
2116 : :
2117 : : /* Try to close already closed lvol */
2118 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
2119 : 3 : CU_ASSERT(lvol->ref_count == 0);
2120 : 3 : CU_ASSERT(g_lvserrno != 0);
2121 : :
2122 : 3 : g_lvserrno = -1;
2123 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
2124 : 3 : CU_ASSERT(rc == 0);
2125 : 3 : CU_ASSERT(g_lvserrno == 0);
2126 : 3 : g_lvol_store = NULL;
2127 : :
2128 : 3 : CU_ASSERT(rc == 0);
2129 : 3 : CU_ASSERT(g_lvserrno == 0);
2130 : 3 : g_lvol_store = NULL;
2131 : :
2132 : 3 : free_dev(&dev);
2133 : 3 : }
2134 : :
2135 : : static void
2136 : 3 : lvol_create_thin_provisioned(void)
2137 : : {
2138 : 3 : struct lvol_ut_bs_dev dev;
2139 : 3 : struct spdk_lvs_opts opts;
2140 : 3 : int rc = 0;
2141 : :
2142 : 3 : init_dev(&dev);
2143 : :
2144 : 3 : spdk_lvs_opts_init(&opts);
2145 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2146 : :
2147 : 3 : g_lvserrno = -1;
2148 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2149 : 3 : CU_ASSERT(rc == 0);
2150 : 3 : CU_ASSERT(g_lvserrno == 0);
2151 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2152 : :
2153 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
2154 : : lvol_op_with_handle_complete, NULL);
2155 : 3 : CU_ASSERT(g_lvserrno == 0);
2156 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2157 : :
2158 [ - + ]: 3 : CU_ASSERT(g_lvol->blob->thin_provisioned == false);
2159 : :
2160 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
2161 : 3 : CU_ASSERT(g_lvserrno == 0);
2162 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
2163 : 3 : CU_ASSERT(g_lvserrno == 0);
2164 : :
2165 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
2166 : : lvol_op_with_handle_complete, NULL);
2167 : 3 : CU_ASSERT(g_lvserrno == 0);
2168 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2169 : :
2170 [ - + ]: 3 : CU_ASSERT(g_lvol->blob->thin_provisioned == true);
2171 : :
2172 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
2173 : 3 : CU_ASSERT(g_lvserrno == 0);
2174 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
2175 : 3 : CU_ASSERT(g_lvserrno == 0);
2176 : :
2177 : 3 : g_lvserrno = -1;
2178 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
2179 : 3 : CU_ASSERT(rc == 0);
2180 : 3 : CU_ASSERT(g_lvserrno == 0);
2181 : 3 : g_lvol_store = NULL;
2182 : :
2183 : 3 : free_dev(&dev);
2184 : 3 : }
2185 : :
2186 : : static void
2187 : 3 : lvol_inflate(void)
2188 : : {
2189 : 3 : struct lvol_ut_bs_dev dev;
2190 : 3 : struct spdk_lvs_opts opts;
2191 : 3 : int rc = 0;
2192 : :
2193 : 3 : init_dev(&dev);
2194 : :
2195 : 3 : spdk_lvs_opts_init(&opts);
2196 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2197 : :
2198 : 3 : g_lvserrno = -1;
2199 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2200 : 3 : CU_ASSERT(rc == 0);
2201 : 3 : CU_ASSERT(g_lvserrno == 0);
2202 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2203 : :
2204 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
2205 : : lvol_op_with_handle_complete, NULL);
2206 : 3 : CU_ASSERT(g_lvserrno == 0);
2207 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2208 : :
2209 : 3 : g_inflate_rc = -1;
2210 : 3 : spdk_lvol_inflate(g_lvol, op_complete, NULL);
2211 : 3 : CU_ASSERT(g_lvserrno != 0);
2212 : :
2213 : 3 : g_inflate_rc = 0;
2214 : 3 : spdk_lvol_inflate(g_lvol, op_complete, NULL);
2215 : 3 : CU_ASSERT(g_lvserrno == 0);
2216 : :
2217 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
2218 : 3 : CU_ASSERT(g_lvserrno == 0);
2219 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
2220 : 3 : CU_ASSERT(g_lvserrno == 0);
2221 : :
2222 : 3 : g_lvserrno = -1;
2223 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
2224 : 3 : CU_ASSERT(rc == 0);
2225 : 3 : CU_ASSERT(g_lvserrno == 0);
2226 : 3 : g_lvol_store = NULL;
2227 : :
2228 : 3 : free_dev(&dev);
2229 : :
2230 : : /* Make sure that all references to the io_channel was closed after
2231 : : * inflate call
2232 : : */
2233 : 3 : CU_ASSERT(g_io_channel == NULL);
2234 : 3 : }
2235 : :
2236 : : static void
2237 : 3 : lvol_decouple_parent(void)
2238 : : {
2239 : 3 : struct lvol_ut_bs_dev dev;
2240 : 3 : struct spdk_lvs_opts opts;
2241 : 3 : int rc = 0;
2242 : :
2243 : 3 : init_dev(&dev);
2244 : :
2245 : 3 : spdk_lvs_opts_init(&opts);
2246 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2247 : :
2248 : 3 : g_lvserrno = -1;
2249 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2250 : 3 : CU_ASSERT(rc == 0);
2251 : 3 : CU_ASSERT(g_lvserrno == 0);
2252 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2253 : :
2254 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
2255 : : lvol_op_with_handle_complete, NULL);
2256 : 3 : CU_ASSERT(g_lvserrno == 0);
2257 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2258 : :
2259 : 3 : g_inflate_rc = -1;
2260 : 3 : spdk_lvol_decouple_parent(g_lvol, op_complete, NULL);
2261 : 3 : CU_ASSERT(g_lvserrno != 0);
2262 : :
2263 : 3 : g_inflate_rc = 0;
2264 : 3 : spdk_lvol_decouple_parent(g_lvol, op_complete, NULL);
2265 : 3 : CU_ASSERT(g_lvserrno == 0);
2266 : :
2267 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
2268 : 3 : CU_ASSERT(g_lvserrno == 0);
2269 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
2270 : 3 : CU_ASSERT(g_lvserrno == 0);
2271 : :
2272 : 3 : g_lvserrno = -1;
2273 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
2274 : 3 : CU_ASSERT(rc == 0);
2275 : 3 : CU_ASSERT(g_lvserrno == 0);
2276 : 3 : g_lvol_store = NULL;
2277 : :
2278 : 3 : free_dev(&dev);
2279 : :
2280 : : /* Make sure that all references to the io_channel was closed after
2281 : : * inflate call
2282 : : */
2283 : 3 : CU_ASSERT(g_io_channel == NULL);
2284 : 3 : }
2285 : :
2286 : : static void
2287 : 3 : lvol_get_xattr(void)
2288 : : {
2289 : 3 : struct lvol_ut_bs_dev dev;
2290 : 3 : struct spdk_lvs_opts opts;
2291 : 3 : int rc = 0;
2292 : : struct spdk_lvol *lvol;
2293 : 3 : const char *value = NULL;
2294 : 3 : size_t value_len = 0;
2295 : :
2296 : 3 : init_dev(&dev);
2297 : :
2298 : 3 : spdk_lvs_opts_init(&opts);
2299 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2300 : :
2301 : 3 : g_lvserrno = -1;
2302 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2303 : 3 : CU_ASSERT(rc == 0);
2304 : 3 : CU_ASSERT(g_lvserrno == 0);
2305 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2306 : :
2307 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
2308 : : lvol_op_with_handle_complete, NULL);
2309 : 3 : CU_ASSERT(g_lvserrno == 0);
2310 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2311 : 3 : lvol = g_lvol;
2312 : :
2313 : : /* Should be able to look up name */
2314 : 3 : lvol_get_xattr_value(lvol, "name", (const void **)&value, &value_len);
2315 [ + - + + : 3 : CU_ASSERT(value != NULL && strcmp(value, "lvol") == 0);
+ - ]
2316 : 3 : CU_ASSERT(value_len != 0);
2317 : :
2318 : : /* Looking up something that doesn't exist should indicate non-existence */
2319 : 3 : lvol_get_xattr_value(lvol, "mumble", (const void **)&value, &value_len);
2320 : 3 : CU_ASSERT(value == NULL);
2321 : 3 : CU_ASSERT(value_len == 0);
2322 : :
2323 : : /* Clean up */
2324 : 3 : spdk_lvol_close(lvol, op_complete, NULL);
2325 : 3 : CU_ASSERT(g_lvserrno == 0);
2326 : 3 : spdk_lvol_destroy(lvol, op_complete, NULL);
2327 : 3 : CU_ASSERT(g_lvserrno == 0);
2328 : :
2329 : 3 : g_lvserrno = -1;
2330 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
2331 : 3 : CU_ASSERT(rc == 0);
2332 : 3 : CU_ASSERT(g_lvserrno == 0);
2333 : 3 : g_lvol_store = NULL;
2334 : :
2335 : 3 : free_dev(&dev);
2336 : 3 : }
2337 : :
2338 : : struct spdk_bs_dev *g_esnap_bs_dev;
2339 : : int g_esnap_bs_dev_errno = -ENOTSUP;
2340 : :
2341 : : static int
2342 : 3 : ut_esnap_bs_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
2343 : : const void *esnap_id, uint32_t id_len,
2344 : : struct spdk_bs_dev **_bs_dev)
2345 : : {
2346 : 3 : *_bs_dev = g_esnap_bs_dev;
2347 : 3 : return g_esnap_bs_dev_errno;
2348 : : }
2349 : :
2350 : : static void
2351 : 3 : lvol_esnap_reload(void)
2352 : : {
2353 : 3 : struct lvol_ut_bs_dev dev;
2354 : : struct spdk_lvs_with_handle_req *req;
2355 : 3 : struct spdk_lvs_opts opts;
2356 : : int rc;
2357 : :
2358 : 3 : g_esnap_bs_dev = NULL;
2359 : 3 : g_esnap_bs_dev_errno = -ENOTSUP;
2360 : :
2361 : 3 : req = calloc(1, sizeof(*req));
2362 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
2363 : :
2364 : 3 : init_dev(&dev);
2365 : :
2366 : : /* Create an lvstore with external snapshot support */
2367 : 3 : spdk_lvs_opts_init(&opts);
2368 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2369 : 3 : opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
2370 : 3 : g_lvserrno = -1;
2371 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2372 : 3 : CU_ASSERT(rc == 0);
2373 : 3 : CU_ASSERT(g_lvserrno == 0);
2374 : 3 : CU_ASSERT(dev.bs->esnap_bs_dev_create == ut_esnap_bs_dev_create);
2375 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2376 : :
2377 : : /* Unload the lvstore */
2378 : 3 : g_lvserrno = -1;
2379 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
2380 : 3 : CU_ASSERT(rc == 0);
2381 : 3 : CU_ASSERT(g_lvserrno == 0);
2382 : 3 : g_lvol_store = NULL;
2383 : :
2384 : : /* Load the lvstore with external snapshot support */
2385 : 3 : g_lvserrno = -1;
2386 : 3 : spdk_lvs_opts_init(&opts);
2387 : 3 : opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
2388 : 3 : spdk_lvs_load_ext(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2389 : 3 : CU_ASSERT(g_lvserrno == 0);
2390 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2391 : 3 : CU_ASSERT(dev.bs->esnap_bs_dev_create == ut_esnap_bs_dev_create);
2392 : :
2393 : 3 : g_lvserrno = -1;
2394 : 3 : rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
2395 : 3 : CU_ASSERT(rc == 0);
2396 : 3 : CU_ASSERT(g_lvserrno == 0);
2397 : 3 : g_lvol_store = NULL;
2398 : :
2399 : 3 : free(req);
2400 : 3 : }
2401 : :
2402 : : static void
2403 : 3 : lvol_esnap_create_bad_args(void)
2404 : : {
2405 : 3 : struct lvol_ut_bs_dev dev;
2406 : 3 : struct spdk_bdev esnap_bdev;
2407 : 3 : struct spdk_lvs_opts opts;
2408 : 3 : char long_name[SPDK_LVOL_NAME_MAX + 1];
2409 : : int rc;
2410 : 3 : struct ut_cb_res lvres1, lvres2;
2411 : : struct spdk_lvol *lvol;
2412 : 3 : char uuid_str[SPDK_UUID_STRING_LEN];
2413 : : uint64_t block_sz, cluster_sz;
2414 : :
2415 : 3 : init_dev(&dev);
2416 : 3 : block_sz = dev.bs_dev.blocklen;
2417 : :
2418 : 3 : spdk_lvs_opts_init(&opts);
2419 : 3 : cluster_sz = opts.cluster_sz;
2420 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2421 : 3 : opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
2422 : 3 : g_lvserrno = -1;
2423 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2424 : 3 : CU_ASSERT(rc == 0);
2425 : 3 : CU_ASSERT(g_lvserrno == 0);
2426 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2427 : :
2428 : 3 : init_bdev(&esnap_bdev, "bdev1", BS_CLUSTER_SIZE);
2429 : 3 : CU_ASSERT(spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &esnap_bdev.uuid) == 0);
2430 : 3 : MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
2431 : :
2432 : : /* error with lvs == NULL */
2433 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, NULL, "clone1",
2434 : : lvol_op_with_handle_complete, NULL);
2435 : 3 : CU_ASSERT(rc == -EINVAL);
2436 : :
2437 : : /* error with clone name that is too short */
2438 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store, "",
2439 : : lvol_op_with_handle_complete, NULL);
2440 : 3 : CU_ASSERT(rc == -EINVAL);
2441 : :
2442 : : /* error with clone name that is too long */
2443 : 3 : memset(long_name, 'a', sizeof(long_name));
2444 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
2445 : : long_name, lvol_op_with_handle_complete, NULL);
2446 : 3 : CU_ASSERT(rc == -EINVAL);
2447 : :
2448 : : /* error with size that is not a multiple of an integer multiple of cluster_sz */
2449 [ - + ]: 3 : CU_ASSERT(((cluster_sz + block_sz) % cluster_sz) != 0);
2450 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz + block_sz,
2451 : : g_lvol_store, "clone1",
2452 : : lvol_op_with_handle_complete, NULL);
2453 : 3 : CU_ASSERT(rc == -EINVAL);
2454 : :
2455 : : /* error when an lvol with that name already exists */
2456 : 3 : spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
2457 : : lvol_op_with_handle_complete, NULL);
2458 : 3 : CU_ASSERT(g_lvserrno == 0);
2459 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2460 : 3 : lvol = g_lvol;
2461 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
2462 : : "lvol", lvol_op_with_handle_complete, NULL);
2463 : 3 : CU_ASSERT(rc == -EEXIST);
2464 : 3 : spdk_lvol_close(lvol, op_complete, ut_cb_res_clear(&lvres1));
2465 : 3 : spdk_lvol_destroy(lvol, op_complete, ut_cb_res_clear(&lvres2));
2466 : 3 : poll_threads();
2467 : 3 : CU_ASSERT(lvres1.err == 0);
2468 : 3 : CU_ASSERT(lvres2.err == 0);
2469 : 3 : g_lvol = NULL;
2470 : :
2471 : : /* error when two clones created at the same time with the same name */
2472 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
2473 : : "clone1", lvol_op_with_handle_complete,
2474 : 3 : ut_cb_res_clear(&lvres1));
2475 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
2476 : : "clone1", lvol_op_with_handle_complete,
2477 : 3 : ut_cb_res_clear(&lvres2));
2478 : 3 : CU_ASSERT(rc == -EEXIST);
2479 : 3 : poll_threads();
2480 : 3 : CU_ASSERT(g_lvol != NULL);
2481 : 3 : CU_ASSERT(lvres1.err == 0);
2482 : 3 : CU_ASSERT(lvres2.err == 0xbad);
2483 : 3 : CU_ASSERT(TAILQ_EMPTY(&g_lvol_store->pending_lvols));
2484 : 3 : spdk_lvol_close(g_lvol, op_complete, ut_cb_res_clear(&lvres1));
2485 : 3 : spdk_lvol_destroy(g_lvol, op_complete, ut_cb_res_clear(&lvres2));
2486 : 3 : poll_threads();
2487 : 3 : CU_ASSERT(lvres1.err == 0);
2488 : 3 : CU_ASSERT(lvres2.err == 0);
2489 : 3 : g_lvol = NULL;
2490 : :
2491 : 3 : g_lvserrno = -1;
2492 : 3 : rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
2493 : 3 : CU_ASSERT(rc == 0);
2494 : 3 : CU_ASSERT(g_lvserrno == 0);
2495 : 3 : g_lvol_store = NULL;
2496 : :
2497 : 3 : free_dev(&dev);
2498 : 3 : }
2499 : :
2500 : : static void
2501 : 3 : lvol_esnap_create_delete(void)
2502 : : {
2503 : 3 : struct lvol_ut_bs_dev dev;
2504 : 3 : struct spdk_bdev esnap_bdev;
2505 : 3 : struct spdk_lvs_opts opts;
2506 : 3 : char uuid_str[SPDK_UUID_STRING_LEN];
2507 : : int rc;
2508 : : uint64_t cluster_sz;
2509 : :
2510 : 3 : init_dev(&dev);
2511 : 3 : init_dev(&g_esnap_dev);
2512 : :
2513 : 3 : spdk_lvs_opts_init(&opts);
2514 : 3 : cluster_sz = opts.cluster_sz;
2515 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2516 : 3 : opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
2517 : 3 : g_lvserrno = -1;
2518 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2519 : 3 : CU_ASSERT(rc == 0);
2520 : 3 : CU_ASSERT(g_lvserrno == 0);
2521 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2522 : :
2523 : 3 : g_lvserrno = 0xbad;
2524 : 3 : init_bdev(&esnap_bdev, "bdev1", BS_CLUSTER_SIZE);
2525 : 3 : CU_ASSERT(spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &esnap_bdev.uuid) == 0);
2526 : 3 : MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
2527 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
2528 : : "clone1", lvol_op_with_handle_complete, NULL);
2529 : 3 : CU_ASSERT(rc == 0);
2530 : 3 : poll_threads();
2531 : 3 : CU_ASSERT(g_lvserrno == 0);
2532 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
2533 : 3 : MOCK_CLEAR(spdk_bdev_get_by_name);
2534 : :
2535 : 3 : g_lvserrno = 0xbad;
2536 : 3 : spdk_lvol_close(g_lvol, op_complete, NULL);
2537 : 3 : CU_ASSERT(g_lvserrno == 0);
2538 : 3 : g_lvserrno = 0xbad;
2539 : 3 : spdk_lvol_destroy(g_lvol, op_complete, NULL);
2540 : 3 : CU_ASSERT(g_lvserrno == 0);
2541 : 3 : g_lvol = NULL;
2542 : :
2543 : 3 : g_lvserrno = -1;
2544 : 3 : rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
2545 : 3 : CU_ASSERT(rc == 0);
2546 : 3 : CU_ASSERT(g_lvserrno == 0);
2547 : 3 : g_lvol_store = NULL;
2548 : 3 : }
2549 : :
2550 : : static void
2551 : 3 : lvol_esnap_load_esnaps(void)
2552 : : {
2553 : 3 : struct spdk_blob blob = { .id = 42 };
2554 : : struct spdk_lvol_store *lvs;
2555 : : struct spdk_lvol *lvol;
2556 : 3 : struct spdk_bs_dev *bs_dev = NULL;
2557 : 3 : struct spdk_bs_dev esnap_bs_dev = { 0 };
2558 : : int rc;
2559 : 3 : uint64_t esnap_id = 42;
2560 : :
2561 : 3 : lvs = lvs_alloc();
2562 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(lvs != NULL);
2563 : 3 : lvs->esnap_bs_dev_create = ut_esnap_bs_dev_create;
2564 : 3 : lvol = lvol_alloc(lvs, __func__, true, LVOL_CLEAR_WITH_DEFAULT);
2565 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(lvol != NULL);
2566 : :
2567 : : /* Handle missing bs_ctx and blob_ctx gracefully */
2568 : 3 : rc = lvs_esnap_bs_dev_create(NULL, NULL, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
2569 : 3 : CU_ASSERT(rc == -EINVAL);
2570 : :
2571 : : /* Do not try to load external snapshot when load_esnaps is false */
2572 : 3 : g_spdk_blob_get_esnap_id_called = false;
2573 : 3 : bs_dev = NULL;
2574 : 3 : rc = lvs_esnap_bs_dev_create(lvs, lvol, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
2575 : 3 : CU_ASSERT(rc == 0);
2576 : 3 : CU_ASSERT(bs_dev == NULL);
2577 [ - + ]: 3 : CU_ASSERT(!g_spdk_blob_get_esnap_id_called);
2578 : :
2579 : : /* Same, with only lvs */
2580 : 3 : bs_dev = NULL;
2581 : 3 : rc = lvs_esnap_bs_dev_create(lvs, NULL, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
2582 : 3 : CU_ASSERT(rc == 0);
2583 : 3 : CU_ASSERT(bs_dev == NULL);
2584 [ - + ]: 3 : CU_ASSERT(!g_spdk_blob_get_esnap_id_called);
2585 : :
2586 : : /* Same, with only lvol */
2587 : 3 : bs_dev = NULL;
2588 : 3 : rc = lvs_esnap_bs_dev_create(NULL, lvol, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
2589 : 3 : CU_ASSERT(rc == 0);
2590 : 3 : CU_ASSERT(bs_dev == NULL);
2591 [ - + ]: 3 : CU_ASSERT(!g_spdk_blob_get_esnap_id_called);
2592 : :
2593 : : /* Happy path */
2594 : 3 : g_esnap_bs_dev = &esnap_bs_dev;
2595 : 3 : g_esnap_bs_dev_errno = 0;
2596 : :
2597 : 3 : lvs->load_esnaps = true;
2598 : 3 : ut_spdk_bdev_create_bs_dev_ro = 0;
2599 : 3 : g_spdk_blob_get_esnap_id_errno = 0;
2600 : 3 : bs_dev = NULL;
2601 : 3 : rc = lvs_esnap_bs_dev_create(lvs, lvol, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
2602 : 3 : CU_ASSERT(rc == 0);
2603 : :
2604 : : /* Clean up */
2605 : 3 : lvol_free(lvol);
2606 : 3 : lvs_free(lvs);
2607 : 3 : g_esnap_bs_dev = NULL;
2608 : 3 : g_esnap_bs_dev_errno = -ENOTSUP;
2609 : 3 : }
2610 : :
2611 : : struct ut_degraded_dev {
2612 : : struct spdk_bs_dev bs_dev;
2613 : : struct spdk_lvol *lvol;
2614 : : };
2615 : :
2616 : : static void
2617 : 6 : ut_destroy_degraded(struct spdk_bs_dev *ddev)
2618 : : {
2619 : 6 : free(ddev);
2620 : 6 : }
2621 : :
2622 : : static int
2623 : 6 : ut_create_degraded(struct spdk_lvol_store *lvs, struct spdk_lvol *lvol,
2624 : : struct spdk_blob *blob, const char *name, struct spdk_bs_dev **bs_dev)
2625 : : {
2626 : : struct ut_degraded_dev *ddev;
2627 : :
2628 : 6 : ddev = calloc(1, sizeof(*ddev));
2629 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(ddev != NULL);
2630 : :
2631 : 6 : ddev->lvol = lvol;
2632 : 6 : ddev->bs_dev.destroy = ut_destroy_degraded;
2633 : 6 : ddev->bs_dev.blockcnt = UINT64_MAX / 512;
2634 : 6 : ddev->bs_dev.blocklen = 512;
2635 : 6 : *bs_dev = &ddev->bs_dev;
2636 : 6 : return 0;
2637 : : }
2638 : :
2639 : : static void
2640 : 3 : lvol_esnap_missing(void)
2641 : : {
2642 : 3 : struct lvol_ut_bs_dev dev;
2643 : 3 : struct spdk_lvs_opts opts;
2644 : 3 : struct spdk_blob blob = { .id = 42 };
2645 : 3 : struct ut_cb_res cb_res;
2646 : : struct spdk_lvol_store *lvs;
2647 : : struct spdk_lvol *lvol1, *lvol2;
2648 : 3 : struct spdk_bs_dev *bs_dev;
2649 : 3 : struct spdk_bdev esnap_bdev;
2650 : : struct spdk_lvs_degraded_lvol_set *degraded_set;
2651 : 3 : const char *name1 = "lvol1";
2652 : 3 : const char *name2 = "lvol2";
2653 : 3 : char uuid_str[SPDK_UUID_STRING_LEN];
2654 : : uint64_t cluster_sz;
2655 : : int rc;
2656 : :
2657 : : /* Create an lvstore */
2658 : 3 : init_dev(&dev);
2659 : 3 : spdk_lvs_opts_init(&opts);
2660 : 3 : cluster_sz = opts.cluster_sz;
2661 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
2662 : 3 : g_lvserrno = -1;
2663 : 3 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2664 : 3 : CU_ASSERT(rc == 0);
2665 : 3 : CU_ASSERT(g_lvserrno == 0);
2666 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2667 : 3 : lvs = g_lvol_store;
2668 : 3 : lvs->load_esnaps = true;
2669 : :
2670 : : /* Pre-populate the lvstore with a degraded device */
2671 : 3 : lvol1 = lvol_alloc(lvs, name1, true, LVOL_CLEAR_WITH_DEFAULT);
2672 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(lvol1 != NULL);
2673 : 3 : lvol1->blob_id = blob.id;
2674 [ - + ]: 3 : TAILQ_REMOVE(&lvs->pending_lvols, lvol1, link);
2675 : 3 : TAILQ_INSERT_TAIL(&lvs->lvols, lvol1, link);
2676 : 3 : rc = ut_create_degraded(lvs, lvol1, &blob, name1, &bs_dev);
2677 : 3 : CU_ASSERT(rc == 0);
2678 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bs_dev != NULL);
2679 : :
2680 : : /* A clone with a missing external snapshot prevents a conflicting clone's creation */
2681 : 3 : init_bdev(&esnap_bdev, "bdev1", BS_CLUSTER_SIZE);
2682 : 3 : CU_ASSERT(spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &esnap_bdev.uuid) == 0);
2683 : 3 : MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
2684 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, sizeof(uuid_str), cluster_sz, g_lvol_store,
2685 : : name1, lvol_op_with_handle_complete,
2686 : 3 : ut_cb_res_clear(&cb_res));
2687 : 3 : CU_ASSERT(rc == -EEXIST);
2688 : 3 : CU_ASSERT(ut_cb_res_untouched(&cb_res));
2689 : 3 : MOCK_CLEAR(spdk_bdev_get_by_name);
2690 : :
2691 : : /* A clone with a missing external snapshot prevents a conflicting lvol's creation */
2692 : 3 : rc = spdk_lvol_create(lvs, name1, 10, false, LVOL_CLEAR_WITH_DEFAULT,
2693 : 3 : lvol_op_with_handle_complete, ut_cb_res_clear(&cb_res));
2694 : 3 : CU_ASSERT(rc == -EEXIST);
2695 : 3 : CU_ASSERT(ut_cb_res_untouched(&cb_res));
2696 : :
2697 : : /* Using a unique lvol name allows the clone to be created. */
2698 : 3 : MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
2699 : 3 : MOCK_SET(spdk_blob_is_esnap_clone, true);
2700 : 3 : rc = spdk_lvol_create_esnap_clone(uuid_str, sizeof(uuid_str), cluster_sz, g_lvol_store,
2701 : : name2, lvol_op_with_handle_complete,
2702 : 3 : ut_cb_res_clear(&cb_res));
2703 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
2704 : 3 : CU_ASSERT(cb_res.err == 0);
2705 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(cb_res.data != NULL);
2706 : 3 : lvol2 = cb_res.data;
2707 : 3 : CU_ASSERT(lvol2->degraded_set == NULL);
2708 : 3 : spdk_lvol_close(lvol2, op_complete, ut_cb_res_clear(&cb_res));
2709 : 3 : CU_ASSERT(cb_res.err == 0);
2710 : 3 : spdk_lvol_destroy(lvol2, op_complete, ut_cb_res_clear(&cb_res));
2711 : 3 : CU_ASSERT(cb_res.err == 0);
2712 : 3 : MOCK_CLEAR(spdk_blob_is_esnap_clone);
2713 : 3 : MOCK_CLEAR(spdk_bdev_get_by_name);
2714 : :
2715 : : /* Destroying the esnap clone removes it from the degraded_set esnaps tree. */
2716 : 3 : spdk_lvol_destroy(lvol1, op_complete, ut_cb_res_clear(&cb_res));
2717 : 3 : CU_ASSERT(cb_res.err == 0);
2718 : 3 : CU_ASSERT(RB_EMPTY(&lvs->degraded_lvol_sets_tree));
2719 : 3 : bs_dev->destroy(bs_dev);
2720 : :
2721 : : /* Create a missing device again */
2722 : 3 : lvol1 = lvol_alloc(lvs, name1, true, LVOL_CLEAR_WITH_DEFAULT);
2723 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(lvol1 != NULL);
2724 : 3 : lvol1->blob_id = blob.id;
2725 [ - + ]: 3 : TAILQ_REMOVE(&lvs->pending_lvols, lvol1, link);
2726 : 3 : TAILQ_INSERT_TAIL(&lvs->lvols, lvol1, link);
2727 : 3 : rc = ut_create_degraded(lvs, lvol1, &blob, name1, &bs_dev);
2728 : 3 : CU_ASSERT(rc == 0);
2729 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bs_dev != NULL);
2730 : 3 : lvol1->blob = &blob;
2731 [ - + ]: 3 : rc = spdk_lvs_esnap_missing_add(lvs, lvol1, esnap_bdev.name, strlen(esnap_bdev.name) + 1);
2732 : 3 : CU_ASSERT(rc == 0);
2733 : 3 : lvol1->ref_count = 1;
2734 : :
2735 : : /*
2736 : : * Creating a snapshot of lvol1 makes lvol1 a clone of the new snapshot. What was a clone of
2737 : : * the external snapshot is now a clone of the snapshot. The snapshot is a clone of the
2738 : : * external snapshot. Now the snapshot is degraded_set its external snapshot.
2739 : : */
2740 : 3 : degraded_set = lvol1->degraded_set;
2741 : 3 : CU_ASSERT(degraded_set != NULL);
2742 : 3 : spdk_lvol_create_snapshot(lvol1, name2, lvol_op_with_handle_complete,
2743 : 3 : ut_cb_res_clear(&cb_res));
2744 : 3 : CU_ASSERT(cb_res.err == 0);
2745 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(cb_res.data != NULL);
2746 : 3 : lvol2 = cb_res.data;
2747 : 3 : CU_ASSERT(lvol1->degraded_set == NULL);
2748 : 3 : CU_ASSERT(lvol2->degraded_set == degraded_set);
2749 : :
2750 : : /*
2751 : : * Removing the snapshot (lvol2) makes the first lvol (lvol1) back into a clone of an
2752 : : * external snapshot.
2753 : : */
2754 : 3 : MOCK_SET(spdk_blob_is_esnap_clone, true);
2755 : 3 : g_spdk_blob_get_clones_snap_id = lvol2->blob_id;
2756 : 3 : g_spdk_blob_get_clones_ids = &lvol1->blob_id;
2757 : 3 : g_spdk_blob_get_clones_count = 1;
2758 : 3 : spdk_lvol_close(lvol2, op_complete, ut_cb_res_clear(&cb_res));
2759 : 3 : CU_ASSERT(cb_res.err == 0);
2760 : 3 : spdk_lvol_destroy(lvol2, op_complete, ut_cb_res_clear(&cb_res));
2761 : 3 : CU_ASSERT(cb_res.err == 0);
2762 : 3 : CU_ASSERT(lvol1->degraded_set == degraded_set);
2763 : 3 : g_spdk_blob_get_clones_snap_id = 0xbad;
2764 : 3 : g_spdk_blob_get_clones_ids = NULL;
2765 : 3 : g_spdk_blob_get_clones_count = 0;
2766 : :
2767 : : /* Clean up */
2768 : 3 : spdk_lvol_close(lvol1, op_complete, ut_cb_res_clear(&cb_res));
2769 : 3 : CU_ASSERT(cb_res.err == 0);
2770 : 3 : spdk_lvol_destroy(lvol1, op_complete, ut_cb_res_clear(&cb_res));
2771 : 3 : CU_ASSERT(cb_res.err == 0);
2772 : 3 : bs_dev->destroy(bs_dev);
2773 : 3 : rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
2774 : 3 : CU_ASSERT(rc == 0);
2775 : 3 : MOCK_CLEAR(spdk_blob_is_esnap_clone);
2776 : 3 : }
2777 : :
2778 : : struct hotplug_lvol {
2779 : : /*
2780 : : * These fields must be set before calling lvol_esnap_hotplug_scenario().
2781 : : */
2782 : : char *lvol_name;
2783 : : char *esnap_id;
2784 : : /* How many times hotplug is expected to be called, likely 1. */
2785 : : int expect_hp_count;
2786 : : /* If not 0, return this during hotplug without registering esnap_dev. */
2787 : : int hotplug_retval;
2788 : : /* If true, call spdk_lvs_esnap_missing_add(), return 0, NULL bs_dev */
2789 : : bool register_missing;
2790 : :
2791 : : /*
2792 : : * These fields set are set by lvol_esnap_hotplug_scenario().
2793 : : */
2794 : : struct spdk_lvol *lvol;
2795 : : int id_len;
2796 : : int hp_count;
2797 : : bool created;
2798 : : };
2799 : :
2800 : : struct missing_esnap {
2801 : : char *esnap_id;
2802 : : struct spdk_bs_dev *esnap_dev;
2803 : : int expect_missing_lvol_count_after_create;
2804 : : int expect_missing_lvol_count_after_hotplug;
2805 : : };
2806 : :
2807 : : /* Arrays. Terminate with a zeroed struct. */
2808 : : struct hotplug_lvol *g_hotplug_lvols;
2809 : : struct missing_esnap *g_missing_esnap;
2810 : :
2811 : : static int
2812 : 162 : missing_get_lvol_count(struct spdk_lvol_store *lvs, char *esnap_id)
2813 : : {
2814 : 162 : struct spdk_lvs_degraded_lvol_set find = { 0 };
2815 : : struct spdk_lvs_degraded_lvol_set *found;
2816 : : struct spdk_lvol *lvol;
2817 : 162 : int count = 0;
2818 : :
2819 : 162 : find.esnap_id = esnap_id;
2820 [ - + ]: 162 : find.id_len = strlen(esnap_id) + 1;
2821 : :
2822 : 162 : found = RB_FIND(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, &find);
2823 [ + + ]: 162 : if (found == NULL) {
2824 : 18 : return 0;
2825 : : }
2826 [ + + ]: 372 : TAILQ_FOREACH(lvol, &found->lvols, degraded_link) {
2827 : 228 : count++;
2828 : : }
2829 : 144 : return count;
2830 : : }
2831 : :
2832 : : static struct missing_esnap *
2833 : 201 : get_missing_esnap(struct missing_esnap *missing_esnap, const char *esnap_id)
2834 : : {
2835 [ + - ]: 219 : for (; missing_esnap->esnap_id != NULL; missing_esnap++) {
2836 [ + + - + : 219 : if (strcmp(missing_esnap->esnap_id, esnap_id) == 0) {
+ + ]
2837 : 201 : return missing_esnap;
2838 : : }
2839 : : }
2840 : 0 : return NULL;
2841 : : }
2842 : :
2843 : : static int
2844 : 168 : ut_esnap_hotplug_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
2845 : : const void *esnap_id, uint32_t id_len, struct spdk_bs_dev **bs_dev)
2846 : : {
2847 : 168 : struct spdk_lvol_store *lvs = bs_ctx;
2848 : 168 : struct spdk_lvol *lvol = blob_ctx;
2849 : : struct hotplug_lvol *hp_lvol;
2850 : : struct missing_esnap *missing_esnap;
2851 : : int rc;
2852 : :
2853 : 168 : CU_ASSERT(lvs != NULL);
2854 : 168 : CU_ASSERT(lvol != NULL);
2855 : :
2856 [ + - ]: 288 : for (hp_lvol = g_hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
2857 [ + + ]: 288 : if (hp_lvol->lvol->blob == lvol->blob) {
2858 : 168 : break;
2859 : : }
2860 : : }
2861 [ - + ]: 168 : if (hp_lvol->lvol == NULL) {
2862 : 0 : return -EINVAL;
2863 : : }
2864 : :
2865 [ + + + + ]: 168 : if (!hp_lvol->created) {
2866 : 84 : hp_lvol->created = true;
2867 : 84 : rc = spdk_lvs_esnap_missing_add(lvs, lvol, hp_lvol->esnap_id, hp_lvol->id_len);
2868 : 84 : CU_ASSERT(rc == 0);
2869 : 84 : *bs_dev = NULL;
2870 : 84 : return 0;
2871 : : }
2872 : :
2873 : 84 : hp_lvol->hp_count++;
2874 : :
2875 [ + + ]: 84 : if (hp_lvol->hotplug_retval != 0) {
2876 : 9 : return hp_lvol->hotplug_retval;
2877 : : }
2878 : :
2879 : 75 : missing_esnap = get_missing_esnap(g_missing_esnap, esnap_id);
2880 [ - + ]: 75 : if (missing_esnap == NULL) {
2881 : 0 : return -ENODEV;
2882 : : }
2883 : :
2884 [ + + + + ]: 75 : if (hp_lvol->register_missing) {
2885 : 21 : rc = spdk_lvs_esnap_missing_add(hp_lvol->lvol->lvol_store, hp_lvol->lvol,
2886 : 21 : hp_lvol->esnap_id, hp_lvol->id_len);
2887 : 21 : CU_ASSERT(rc == 0);
2888 : 21 : *bs_dev = NULL;
2889 : 21 : return 0;
2890 : : }
2891 : :
2892 : 54 : *bs_dev = missing_esnap->esnap_dev;
2893 : 54 : return 0;
2894 : : }
2895 : :
2896 : : /*
2897 : : * Creates an lvolstore with the specified esnap clone lvols. They are all initially missing their
2898 : : * external snapshots, similar to what would happen if an lvolstore's device is examined before the
2899 : : * devices that act as external snapshots. After the lvols are loaded, the blobstore is notified of
2900 : : * each missing esnap (degraded_set).
2901 : : *
2902 : : * @param hotplug_lvols An array of esnap clone lvols to create. The array is terminated by zeroed
2903 : : * element.
2904 : : * @parm degraded_lvol_sets_tree An array of external snapshots that will be hotplugged. The array is
2905 : : * terminated by a zeroed element.
2906 : : * @desc Unused, but is very helpful when displaying stack traces in a debugger.
2907 : : */
2908 : : static bool
2909 : 39 : lvol_esnap_hotplug_scenario(struct hotplug_lvol *hotplug_lvols,
2910 : : struct missing_esnap *degraded_lvol_sets_tree,
2911 : : char *desc)
2912 : : {
2913 : 39 : struct lvol_ut_bs_dev dev;
2914 : 39 : struct spdk_lvs_opts opts;
2915 : : struct spdk_lvol_store *lvs;
2916 : : struct spdk_lvs_degraded_lvol_set *degraded_set;
2917 : : struct hotplug_lvol *hp_lvol;
2918 : : struct missing_esnap *m_esnap;
2919 : : int count;
2920 : : int rc;
2921 : 39 : uint32_t num_failures = CU_get_number_of_failures();
2922 : :
2923 : 39 : g_hotplug_lvols = hotplug_lvols;
2924 : 39 : g_missing_esnap = degraded_lvol_sets_tree;
2925 : :
2926 : : /* Create the lvstore */
2927 : 39 : init_dev(&dev);
2928 : 39 : spdk_lvs_opts_init(&opts);
2929 : 39 : snprintf(opts.name, sizeof(opts.name), "lvs");
2930 : 39 : g_lvserrno = -1;
2931 : 39 : rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
2932 : 39 : CU_ASSERT(rc == 0);
2933 : 39 : CU_ASSERT(g_lvserrno == 0);
2934 [ - + ]: 39 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
2935 : 39 : lvs = g_lvol_store;
2936 : 39 : lvs->esnap_bs_dev_create = ut_esnap_hotplug_dev_create;
2937 : :
2938 : : /* Create the lvols */
2939 [ + + ]: 123 : for (hp_lvol = hotplug_lvols; hp_lvol->lvol_name != NULL; hp_lvol++) {
2940 [ + - ]: 84 : if (hp_lvol->id_len == 0) {
2941 [ - + ]: 84 : hp_lvol->id_len = strlen(hp_lvol->esnap_id) + 1;
2942 : : }
2943 : :
2944 : 84 : g_lvserrno = 0xbad;
2945 : 84 : rc = spdk_lvol_create_esnap_clone(hp_lvol->esnap_id, hp_lvol->id_len,
2946 : 84 : opts.cluster_sz, lvs, hp_lvol->lvol_name,
2947 : : lvol_op_with_handle_complete, NULL);
2948 : 84 : CU_ASSERT(rc == 0);
2949 : 84 : poll_threads();
2950 : 84 : CU_ASSERT(g_lvserrno == 0);
2951 : 84 : CU_ASSERT(g_lvol != NULL);
2952 [ - + ]: 84 : if (g_lvol == NULL) {
2953 : 0 : break;
2954 : : }
2955 : 84 : hp_lvol->lvol = g_lvol;
2956 : : /* This is normally triggered by the blobstore in blob_load_esnap(), but that part
2957 : : * of blobstore is not mocked by lvol_ut. Later commits will further exercise
2958 : : * hotplug with a functional blobstore. See test/lvol/esnap/esnap.c and
2959 : : * test/lvol/external_snapshot.sh in later commits.
2960 : : */
2961 : 140 : rc = ut_esnap_hotplug_dev_create(lvs, hp_lvol->lvol, hp_lvol->lvol->blob,
2962 : 84 : hp_lvol->esnap_id, hp_lvol->id_len,
2963 : 84 : &hp_lvol->lvol->blob->back_bs_dev);
2964 : 84 : CU_ASSERT(rc == 0);
2965 : : }
2966 : :
2967 : : /* Verify lvol count in lvs->degraded_lvol_sets_tree tree. */
2968 [ + + ]: 84 : for (m_esnap = degraded_lvol_sets_tree; m_esnap->esnap_id != NULL; m_esnap++) {
2969 : 45 : count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
2970 : 45 : CU_ASSERT(m_esnap->expect_missing_lvol_count_after_create == count);
2971 : : }
2972 : :
2973 : : /* Verify lvs->degraded_lvol_sets_tree tree has nothing extra */
2974 [ + + ]: 84 : RB_FOREACH(degraded_set, degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree) {
2975 : 45 : m_esnap = get_missing_esnap(degraded_lvol_sets_tree, degraded_set->esnap_id);
2976 : 45 : CU_ASSERT(m_esnap != NULL);
2977 [ + - ]: 45 : if (m_esnap != NULL) {
2978 : 45 : count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
2979 : 45 : CU_ASSERT(m_esnap->expect_missing_lvol_count_after_create == count);
2980 : : }
2981 : : }
2982 : :
2983 : : /* Perform hotplug */
2984 [ + + ]: 84 : for (m_esnap = degraded_lvol_sets_tree; m_esnap->esnap_id != NULL; m_esnap++) {
2985 [ - + ]: 45 : spdk_lvs_notify_hotplug(m_esnap->esnap_id, strlen(m_esnap->esnap_id) + 1,
2986 : : lvol_op_with_handle_complete, NULL);
2987 : : }
2988 : :
2989 : : /* Verify lvol->degraded_set and back_bs_dev */
2990 [ + + ]: 123 : for (hp_lvol = hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
2991 [ + + + + : 84 : if (hp_lvol->register_missing || hp_lvol->hotplug_retval != 0) {
+ + ]
2992 : 30 : CU_ASSERT(hp_lvol->lvol->degraded_set != NULL);
2993 : 30 : CU_ASSERT(hp_lvol->lvol->blob->back_bs_dev == NULL);
2994 : : } else {
2995 : 54 : CU_ASSERT(hp_lvol->lvol->degraded_set == NULL);
2996 : 54 : m_esnap = get_missing_esnap(degraded_lvol_sets_tree, hp_lvol->esnap_id);
2997 : 54 : CU_ASSERT(m_esnap != NULL);
2998 [ + - ]: 54 : if (m_esnap != NULL) {
2999 : 54 : CU_ASSERT(hp_lvol->lvol->blob->back_bs_dev == m_esnap->esnap_dev);
3000 : : }
3001 : : }
3002 : : }
3003 : :
3004 : : /* Verify hotplug count on lvols */
3005 [ + + ]: 123 : for (hp_lvol = hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
3006 : 84 : CU_ASSERT(hp_lvol->hp_count == 1);
3007 : : }
3008 : :
3009 : : /* Verify lvol count in lvs->degraded_lvol_sets_tree tree. */
3010 [ + + ]: 84 : for (m_esnap = degraded_lvol_sets_tree; m_esnap->esnap_id != NULL; m_esnap++) {
3011 : 45 : count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
3012 : 45 : CU_ASSERT(m_esnap->expect_missing_lvol_count_after_hotplug == count);
3013 : : }
3014 : :
3015 : : /* Verify lvs->degraded_lvol_sets_tree tree has nothing extra */
3016 [ + + ]: 66 : RB_FOREACH(degraded_set, degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree) {
3017 : 27 : m_esnap = get_missing_esnap(degraded_lvol_sets_tree, degraded_set->esnap_id);
3018 : 27 : CU_ASSERT(m_esnap != NULL);
3019 [ + - ]: 27 : if (m_esnap != NULL) {
3020 : 27 : count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
3021 : 27 : CU_ASSERT(m_esnap->expect_missing_lvol_count_after_hotplug == count);
3022 : : }
3023 : : }
3024 : :
3025 : : /* Clean up */
3026 [ + + ]: 123 : for (hp_lvol = hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
3027 : 84 : g_lvserrno = 0xbad;
3028 : 84 : spdk_lvol_close(hp_lvol->lvol, op_complete, NULL);
3029 : 84 : CU_ASSERT(g_lvserrno == 0);
3030 : 84 : g_lvserrno = 0xbad;
3031 : 84 : spdk_lvol_destroy(hp_lvol->lvol, op_complete, NULL);
3032 : 84 : CU_ASSERT(g_lvserrno == 0);
3033 : : }
3034 : 39 : g_lvserrno = 0xabad;
3035 : 39 : rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
3036 : 39 : poll_threads();
3037 : 39 : CU_ASSERT(rc == 0);
3038 : 39 : CU_ASSERT(g_lvserrno == 0);
3039 : 39 : g_lvol = NULL;
3040 : 39 : g_lvol_store = NULL;
3041 : :
3042 : 39 : return num_failures == CU_get_number_of_failures();
3043 : : }
3044 : :
3045 : : static void
3046 : 3 : lvol_esnap_hotplug(void)
3047 : : {
3048 : 3 : struct spdk_bs_dev bs_dev = { 0 };
3049 : 3 : struct spdk_bs_dev bs_dev2 = { 0 };
3050 : : uint64_t i;
3051 : : bool ok;
3052 : : #define HOTPLUG_LVOL(_lvol_name, _esnap_id, _hotplug_retval, _register_missing) { \
3053 : : .lvol_name = _lvol_name, \
3054 : : .esnap_id = _esnap_id, \
3055 : : .hotplug_retval = _hotplug_retval, \
3056 : : .register_missing = _register_missing, \
3057 : : }
3058 : : #define MISSING_ESNAP(_esnap_id, _esnap_dev, _after_create, _after_hotplug) { \
3059 : : .esnap_id = _esnap_id, \
3060 : : .esnap_dev = _esnap_dev, \
3061 : : .expect_missing_lvol_count_after_create = _after_create, \
3062 : : .expect_missing_lvol_count_after_hotplug = _after_hotplug, \
3063 : : }
3064 : : struct {
3065 : : char *desc;
3066 : : struct hotplug_lvol h[4];
3067 : : struct missing_esnap m[3];
3068 : 3 : } scenario[] = {
3069 : : {
3070 : : "one missing, happy path",
3071 : : { HOTPLUG_LVOL("lvol1", "esnap1", 0, false) },
3072 : : { MISSING_ESNAP("esnap1", &bs_dev, 1, 0) }
3073 : : },
3074 : : {
3075 : : "one missing, cb registers degraded_set",
3076 : : { HOTPLUG_LVOL("lvol1", "esnap1", 0, true) },
3077 : : { MISSING_ESNAP("esnap1", &bs_dev, 1, 1) }
3078 : : },
3079 : : {
3080 : : "one missing, cb retuns -ENOMEM",
3081 : : { HOTPLUG_LVOL("lvol1", "esnap1", -ENOMEM, true) },
3082 : : { MISSING_ESNAP("esnap1", &bs_dev, 1, 1) }
3083 : : },
3084 : : {
3085 : : "two missing with same esnap, happy path",
3086 : : {
3087 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
3088 : : HOTPLUG_LVOL("lvol2", "esnap1", 0, false)
3089 : : },
3090 : : { MISSING_ESNAP("esnap1", &bs_dev, 2, 0) }
3091 : : },
3092 : : {
3093 : : "two missing with same esnap, first -ENOMEM",
3094 : : {
3095 : : HOTPLUG_LVOL("lvol1", "esnap1", -ENOMEM, false),
3096 : : HOTPLUG_LVOL("lvol2", "esnap1", 0, false)
3097 : : },
3098 : : { MISSING_ESNAP("esnap1", &bs_dev, 2, 1) }
3099 : : },
3100 : : {
3101 : : "two missing with same esnap, second -ENOMEM",
3102 : : {
3103 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
3104 : : HOTPLUG_LVOL("lvol2", "esnap1", -ENOMEM, false)
3105 : : },
3106 : : { MISSING_ESNAP("esnap1", &bs_dev, 2, 1) }
3107 : : },
3108 : : {
3109 : : "two missing with different esnaps, happy path",
3110 : : {
3111 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
3112 : : HOTPLUG_LVOL("lvol2", "esnap2", 0, false)
3113 : : },
3114 : : {
3115 : : MISSING_ESNAP("esnap1", &bs_dev, 1, 0),
3116 : : MISSING_ESNAP("esnap2", &bs_dev2, 1, 0)
3117 : : }
3118 : : },
3119 : : {
3120 : : "two missing with different esnaps, first still missing",
3121 : : {
3122 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, true),
3123 : : HOTPLUG_LVOL("lvol2", "esnap2", 0, false)
3124 : : },
3125 : : {
3126 : : MISSING_ESNAP("esnap1", &bs_dev, 1, 1),
3127 : : MISSING_ESNAP("esnap2", &bs_dev2, 1, 0)
3128 : : }
3129 : : },
3130 : : {
3131 : : "three missing with same esnap, happy path",
3132 : : {
3133 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
3134 : : HOTPLUG_LVOL("lvol2", "esnap1", 0, false),
3135 : : HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
3136 : : },
3137 : : { MISSING_ESNAP("esnap1", &bs_dev, 3, 0) }
3138 : : },
3139 : : {
3140 : : "three missing with same esnap, first still missing",
3141 : : {
3142 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, true),
3143 : : HOTPLUG_LVOL("lvol2", "esnap1", 0, false),
3144 : : HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
3145 : : },
3146 : : { MISSING_ESNAP("esnap1", &bs_dev, 3, 1) }
3147 : : },
3148 : : {
3149 : : "three missing with same esnap, first two still missing",
3150 : : {
3151 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, true),
3152 : : HOTPLUG_LVOL("lvol2", "esnap1", 0, true),
3153 : : HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
3154 : : },
3155 : : { MISSING_ESNAP("esnap1", &bs_dev, 3, 2) }
3156 : : },
3157 : : {
3158 : : "three missing with same esnap, middle still missing",
3159 : : {
3160 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
3161 : : HOTPLUG_LVOL("lvol2", "esnap1", 0, true),
3162 : : HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
3163 : : },
3164 : : { MISSING_ESNAP("esnap1", &bs_dev, 3, 1) }
3165 : : },
3166 : : {
3167 : : "three missing with same esnap, last still missing",
3168 : : {
3169 : : HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
3170 : : HOTPLUG_LVOL("lvol2", "esnap1", 0, false),
3171 : : HOTPLUG_LVOL("lvol3", "esnap1", 0, true)
3172 : : },
3173 : : { MISSING_ESNAP("esnap1", &bs_dev, 3, 1) }
3174 : : },
3175 : : };
3176 : : #undef HOTPLUG_LVOL
3177 : : #undef MISSING_ESNAP
3178 : :
3179 : 3 : printf("\n");
3180 [ + + ]: 42 : for (i = 0; i < SPDK_COUNTOF(scenario); i++) {
3181 : 39 : ok = lvol_esnap_hotplug_scenario(scenario[i].h, scenario[i].m, scenario[i].desc);
3182 : : /* Add markers in the output to help correlate failures to scenarios. */
3183 : 39 : CU_ASSERT(ok);
3184 [ + - - + ]: 39 : printf("\t%s scenario %" PRIu64 ": %s - %s\n", __func__, i,
3185 : 26 : ok ? "PASS" : "FAIL", scenario[i].desc);
3186 : : }
3187 : 3 : }
3188 : :
3189 : : static void
3190 : 3 : lvol_get_by(void)
3191 : : {
3192 : 3 : struct lvol_ut_bs_dev dev1, dev2;
3193 : : struct spdk_lvol_store *lvs1, *lvs2;
3194 : : struct spdk_lvol *lvol1, *lvol2, *lvol3;
3195 : 3 : struct spdk_lvs_opts opts;
3196 : 3 : int rc = 0;
3197 : 3 : struct spdk_uuid uuid;
3198 : :
3199 : 3 : init_dev(&dev1);
3200 : :
3201 : 3 : spdk_lvs_opts_init(&opts);
3202 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs");
3203 : :
3204 : 3 : g_lvserrno = -1;
3205 : 3 : rc = spdk_lvs_init(&dev1.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
3206 : 3 : CU_ASSERT(rc == 0);
3207 : 3 : CU_ASSERT(g_lvserrno == 0);
3208 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
3209 : 3 : lvs1 = g_lvol_store;
3210 : :
3211 : : /* Create lvol name "lvol" */
3212 : 3 : spdk_lvol_create(lvs1, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
3213 : : lvol_op_with_handle_complete, NULL);
3214 : 3 : CU_ASSERT(g_lvserrno == 0);
3215 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
3216 : 3 : lvol1 = g_lvol;
3217 : :
3218 : : /* Should be able to look up lvol1 by its name and UUID */
3219 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
3220 : : /* Be sure a pointer comparison isn't used. */
3221 : 3 : memcpy(&uuid, &lvol1->uuid, sizeof(uuid));
3222 : 3 : CU_ASSERT(spdk_lvol_get_by_uuid(&uuid) == lvol1);
3223 : :
3224 : : /* Shorter and longer values for lvol_name must not match. */
3225 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvoll") == NULL);
3226 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvo") == NULL);
3227 : :
3228 : : /* Shorter and longer values for lvs_name must not match. */
3229 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvss", "lvol") == NULL);
3230 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lv", "lvol") == NULL);
3231 : :
3232 : : /* Create lvol name "lvol2" */
3233 : 3 : spdk_lvol_create(lvs1, "lvol2", 10, true, LVOL_CLEAR_WITH_DEFAULT,
3234 : : lvol_op_with_handle_complete, NULL);
3235 : 3 : CU_ASSERT(g_lvserrno == 0);
3236 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
3237 : 3 : lvol2 = g_lvol;
3238 : :
3239 : : /* When there are multiple lvols, the right one is found */
3240 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
3241 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol2") == lvol2);
3242 : :
3243 : : /* Create a second lvolstore */
3244 : 3 : init_dev(&dev2);
3245 : 3 : snprintf(opts.name, sizeof(opts.name), "lvs2");
3246 : 3 : g_lvserrno = -1;
3247 : 3 : rc = spdk_lvs_init(&dev2.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
3248 : 3 : CU_ASSERT(rc == 0);
3249 : 3 : CU_ASSERT(g_lvserrno == 0);
3250 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
3251 : 3 : lvs2 = g_lvol_store;
3252 : :
3253 : : /* Lookups that worked with one lvstore still work */
3254 : 3 : memcpy(&uuid, &lvol1->uuid, sizeof(uuid));
3255 : 3 : CU_ASSERT(spdk_lvol_get_by_uuid(&uuid) == lvol1);
3256 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
3257 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol2") == lvol2);
3258 : :
3259 : : /* Add an lvol name "lvol" in the second lvstore */
3260 : 3 : spdk_lvol_create(lvs2, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
3261 : : lvol_op_with_handle_complete, NULL);
3262 : 3 : CU_ASSERT(g_lvserrno == 0);
3263 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
3264 : 3 : lvol3 = g_lvol;
3265 : :
3266 : : /* Lookups by name find the lvols in the right lvstores */
3267 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
3268 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol2") == lvol2);
3269 : 3 : CU_ASSERT(spdk_lvol_get_by_names("lvs2", "lvol") == lvol3);
3270 : :
3271 : : /* Clean up */
3272 : 3 : g_lvserrno = -1;
3273 : 3 : spdk_lvol_close(lvol1, op_complete, NULL);
3274 : 3 : CU_ASSERT(g_lvserrno == 0);
3275 : :
3276 : 3 : g_lvserrno = -1;
3277 : 3 : spdk_lvol_close(lvol2, op_complete, NULL);
3278 : 3 : CU_ASSERT(g_lvserrno == 0);
3279 : :
3280 : 3 : g_lvserrno = -1;
3281 : 3 : spdk_lvol_close(lvol3, op_complete, NULL);
3282 : 3 : CU_ASSERT(g_lvserrno == 0);
3283 : :
3284 : 3 : g_lvserrno = -1;
3285 : 3 : rc = spdk_lvs_unload(lvs1, op_complete, NULL);
3286 : 3 : CU_ASSERT(rc == 0);
3287 : 3 : CU_ASSERT(g_lvserrno == 0);
3288 : :
3289 : 3 : g_lvserrno = -1;
3290 : 3 : rc = spdk_lvs_unload(lvs2, op_complete, NULL);
3291 : 3 : CU_ASSERT(rc == 0);
3292 : 3 : CU_ASSERT(g_lvserrno == 0);
3293 : :
3294 : 3 : g_lvol_store = NULL;
3295 : 3 : g_lvol = NULL;
3296 : :
3297 : 3 : free_dev(&dev1);
3298 : 3 : free_dev(&dev2);
3299 : 3 : }
3300 : :
3301 : : int
3302 : 3 : main(int argc, char **argv)
3303 : : {
3304 : 3 : CU_pSuite suite = NULL;
3305 : : unsigned int num_failures;
3306 : :
3307 : 3 : CU_initialize_registry();
3308 : :
3309 : 3 : suite = CU_add_suite("lvol", NULL, NULL);
3310 : :
3311 : 3 : CU_ADD_TEST(suite, lvs_init_unload_success);
3312 : 3 : CU_ADD_TEST(suite, lvs_init_destroy_success);
3313 : 3 : CU_ADD_TEST(suite, lvs_init_opts_success);
3314 : 3 : CU_ADD_TEST(suite, lvs_unload_lvs_is_null_fail);
3315 : 3 : CU_ADD_TEST(suite, lvs_names);
3316 : 3 : CU_ADD_TEST(suite, lvol_create_destroy_success);
3317 : 3 : CU_ADD_TEST(suite, lvol_create_fail);
3318 : 3 : CU_ADD_TEST(suite, lvol_destroy_fail);
3319 : 3 : CU_ADD_TEST(suite, lvol_close);
3320 : 3 : CU_ADD_TEST(suite, lvol_resize);
3321 : 3 : CU_ADD_TEST(suite, lvol_set_read_only);
3322 : 3 : CU_ADD_TEST(suite, test_lvs_load);
3323 : 3 : CU_ADD_TEST(suite, lvols_load);
3324 : 3 : CU_ADD_TEST(suite, lvol_open);
3325 : 3 : CU_ADD_TEST(suite, lvol_snapshot);
3326 : 3 : CU_ADD_TEST(suite, lvol_snapshot_fail);
3327 : 3 : CU_ADD_TEST(suite, lvol_clone);
3328 : 3 : CU_ADD_TEST(suite, lvol_clone_fail);
3329 : 3 : CU_ADD_TEST(suite, lvol_iter_clones);
3330 : 3 : CU_ADD_TEST(suite, lvol_refcnt);
3331 : 3 : CU_ADD_TEST(suite, lvol_names);
3332 : 3 : CU_ADD_TEST(suite, lvol_create_thin_provisioned);
3333 : 3 : CU_ADD_TEST(suite, lvol_rename);
3334 : 3 : CU_ADD_TEST(suite, lvs_rename);
3335 : 3 : CU_ADD_TEST(suite, lvol_inflate);
3336 : 3 : CU_ADD_TEST(suite, lvol_decouple_parent);
3337 : 3 : CU_ADD_TEST(suite, lvol_get_xattr);
3338 : 3 : CU_ADD_TEST(suite, lvol_esnap_reload);
3339 : 3 : CU_ADD_TEST(suite, lvol_esnap_create_bad_args);
3340 : 3 : CU_ADD_TEST(suite, lvol_esnap_create_delete);
3341 : 3 : CU_ADD_TEST(suite, lvol_esnap_load_esnaps);
3342 : 3 : CU_ADD_TEST(suite, lvol_esnap_missing);
3343 : 3 : CU_ADD_TEST(suite, lvol_esnap_hotplug);
3344 : 3 : CU_ADD_TEST(suite, lvol_get_by);
3345 : :
3346 : 3 : allocate_threads(1);
3347 : 3 : set_thread(0);
3348 : :
3349 : 3 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
3350 : 3 : CU_cleanup_registry();
3351 : :
3352 : 3 : free_threads();
3353 : :
3354 : 3 : return num_failures;
3355 : : }
|