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