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