]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/test/unit/lib/blob/blob.c/blob_ut.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / test / unit / lib / blob / blob.c / blob_ut.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "spdk/stdinc.h"
35
36 #include "spdk_cunit.h"
37 #include "spdk/blob.h"
38 #include "spdk/string.h"
39 #include "spdk_internal/thread.h"
40
41 #include "common/lib/ut_multithread.c"
42 #include "../bs_dev_common.c"
43 #include "blob/blobstore.c"
44 #include "blob/request.c"
45 #include "blob/zeroes.c"
46 #include "blob/blob_bs_dev.c"
47
48 struct spdk_blob_store *g_bs;
49 spdk_blob_id g_blobid;
50 struct spdk_blob *g_blob;
51 int g_bserrno;
52 struct spdk_xattr_names *g_names;
53 int g_done;
54 char *g_xattr_names[] = {"first", "second", "third"};
55 char *g_xattr_values[] = {"one", "two", "three"};
56 uint64_t g_ctx = 1729;
57
58 struct spdk_bs_super_block_ver1 {
59 uint8_t signature[8];
60 uint32_t version;
61 uint32_t length;
62 uint32_t clean; /* If there was a clean shutdown, this is 1. */
63 spdk_blob_id super_blob;
64
65 uint32_t cluster_size; /* In bytes */
66
67 uint32_t used_page_mask_start; /* Offset from beginning of disk, in pages */
68 uint32_t used_page_mask_len; /* Count, in pages */
69
70 uint32_t used_cluster_mask_start; /* Offset from beginning of disk, in pages */
71 uint32_t used_cluster_mask_len; /* Count, in pages */
72
73 uint32_t md_start; /* Offset from beginning of disk, in pages */
74 uint32_t md_len; /* Count, in pages */
75
76 uint8_t reserved[4036];
77 uint32_t crc;
78 } __attribute__((packed));
79 SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block_ver1) == 0x1000, "Invalid super block size");
80
81 static void
82 _get_xattr_value(void *arg, const char *name,
83 const void **value, size_t *value_len)
84 {
85 uint64_t i;
86
87 SPDK_CU_ASSERT_FATAL(value_len != NULL);
88 SPDK_CU_ASSERT_FATAL(value != NULL);
89 CU_ASSERT(arg == &g_ctx)
90
91 for (i = 0; i < sizeof(g_xattr_names); i++) {
92 if (!strcmp(name, g_xattr_names[i])) {
93 *value_len = strlen(g_xattr_values[i]);
94 *value = g_xattr_values[i];
95 break;
96 }
97 }
98 }
99
100 static void
101 _get_xattr_value_null(void *arg, const char *name,
102 const void **value, size_t *value_len)
103 {
104 SPDK_CU_ASSERT_FATAL(value_len != NULL);
105 SPDK_CU_ASSERT_FATAL(value != NULL);
106 CU_ASSERT(arg == NULL)
107
108 *value_len = 0;
109 *value = NULL;
110 }
111
112 static int
113 _get_snapshots_count(struct spdk_blob_store *bs)
114 {
115 struct spdk_blob_list *snapshot = NULL;
116 int count = 0;
117
118 TAILQ_FOREACH(snapshot, &bs->snapshots, link) {
119 count += 1;
120 }
121
122 return count;
123 }
124
125 static void
126 bs_op_complete(void *cb_arg, int bserrno)
127 {
128 g_bserrno = bserrno;
129 }
130
131 static void
132 bs_op_with_handle_complete(void *cb_arg, struct spdk_blob_store *bs,
133 int bserrno)
134 {
135 g_bs = bs;
136 g_bserrno = bserrno;
137 }
138
139 static void
140 blob_op_complete(void *cb_arg, int bserrno)
141 {
142 g_bserrno = bserrno;
143 }
144
145 static void
146 blob_op_with_id_complete(void *cb_arg, spdk_blob_id blobid, int bserrno)
147 {
148 g_blobid = blobid;
149 g_bserrno = bserrno;
150 }
151
152 static void
153 blob_op_with_handle_complete(void *cb_arg, struct spdk_blob *blb, int bserrno)
154 {
155 g_blob = blb;
156 g_bserrno = bserrno;
157 }
158
159 static void
160 blob_init(void)
161 {
162 struct spdk_bs_dev *dev;
163
164 dev = init_dev();
165
166 /* should fail for an unsupported blocklen */
167 dev->blocklen = 500;
168 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
169 poll_threads();
170 CU_ASSERT(g_bserrno == -EINVAL);
171
172 dev = init_dev();
173 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
174 poll_threads();
175 CU_ASSERT(g_bserrno == 0);
176 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
177
178 spdk_bs_unload(g_bs, bs_op_complete, NULL);
179 poll_threads();
180 CU_ASSERT(g_bserrno == 0);
181 g_bs = NULL;
182 }
183
184 static void
185 blob_super(void)
186 {
187 struct spdk_blob_store *bs;
188 struct spdk_bs_dev *dev;
189 spdk_blob_id blobid;
190
191 dev = init_dev();
192
193 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
194 poll_threads();
195 CU_ASSERT(g_bserrno == 0);
196 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
197 bs = g_bs;
198
199 /* Get the super blob without having set one */
200 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL);
201 poll_threads();
202 CU_ASSERT(g_bserrno == -ENOENT);
203 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID);
204
205 /* Create a blob */
206 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
207 poll_threads();
208 CU_ASSERT(g_bserrno == 0);
209 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
210 blobid = g_blobid;
211
212 /* Set the blob as the super blob */
213 spdk_bs_set_super(bs, blobid, blob_op_complete, NULL);
214 poll_threads();
215 CU_ASSERT(g_bserrno == 0);
216
217 /* Get the super blob */
218 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL);
219 poll_threads();
220 CU_ASSERT(g_bserrno == 0);
221 CU_ASSERT(blobid == g_blobid);
222
223 spdk_bs_unload(g_bs, bs_op_complete, NULL);
224 poll_threads();
225 CU_ASSERT(g_bserrno == 0);
226 g_bs = NULL;
227 }
228
229 static void
230 blob_open(void)
231 {
232 struct spdk_blob_store *bs;
233 struct spdk_bs_dev *dev;
234 struct spdk_blob *blob;
235 spdk_blob_id blobid, blobid2;
236
237 dev = init_dev();
238
239 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
240 poll_threads();
241 CU_ASSERT(g_bserrno == 0);
242 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
243 bs = g_bs;
244
245 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
246 poll_threads();
247 CU_ASSERT(g_bserrno == 0);
248 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
249 blobid = g_blobid;
250
251 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
252 poll_threads();
253 CU_ASSERT(g_bserrno == 0);
254 CU_ASSERT(g_blob != NULL);
255 blob = g_blob;
256
257 blobid2 = spdk_blob_get_id(blob);
258 CU_ASSERT(blobid == blobid2);
259
260 /* Try to open file again. It should return success. */
261 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
262 poll_threads();
263 CU_ASSERT(g_bserrno == 0);
264 CU_ASSERT(blob == g_blob);
265
266 spdk_blob_close(blob, blob_op_complete, NULL);
267 poll_threads();
268 CU_ASSERT(g_bserrno == 0);
269
270 /*
271 * Close the file a second time, releasing the second reference. This
272 * should succeed.
273 */
274 blob = g_blob;
275 spdk_blob_close(blob, blob_op_complete, NULL);
276 poll_threads();
277 CU_ASSERT(g_bserrno == 0);
278
279 /*
280 * Try to open file again. It should succeed. This tests the case
281 * where the file is opened, closed, then re-opened again.
282 */
283 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
284 poll_threads();
285 CU_ASSERT(g_bserrno == 0);
286 CU_ASSERT(g_blob != NULL);
287 blob = g_blob;
288
289 spdk_blob_close(blob, blob_op_complete, NULL);
290 poll_threads();
291 CU_ASSERT(g_bserrno == 0);
292
293 spdk_bs_unload(g_bs, bs_op_complete, NULL);
294 poll_threads();
295 CU_ASSERT(g_bserrno == 0);
296 g_bs = NULL;
297 }
298
299 static void
300 blob_create(void)
301 {
302 struct spdk_blob_store *bs;
303 struct spdk_bs_dev *dev;
304 struct spdk_blob *blob;
305 struct spdk_blob_opts opts;
306 spdk_blob_id blobid;
307
308 dev = init_dev();
309
310 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
311 poll_threads();
312 CU_ASSERT(g_bserrno == 0);
313 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
314 bs = g_bs;
315
316 /* Create blob with 10 clusters */
317
318 spdk_blob_opts_init(&opts);
319 opts.num_clusters = 10;
320
321 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
322 poll_threads();
323 CU_ASSERT(g_bserrno == 0);
324 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
325 blobid = g_blobid;
326
327 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
328 poll_threads();
329 CU_ASSERT(g_bserrno == 0);
330 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
331 blob = g_blob;
332 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
333
334 spdk_blob_close(blob, blob_op_complete, NULL);
335 poll_threads();
336 CU_ASSERT(g_bserrno == 0);
337
338 /* Create blob with 0 clusters */
339
340 spdk_blob_opts_init(&opts);
341 opts.num_clusters = 0;
342
343 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
344 poll_threads();
345 CU_ASSERT(g_bserrno == 0);
346 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
347 blobid = g_blobid;
348
349 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
350 poll_threads();
351 CU_ASSERT(g_bserrno == 0);
352 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
353 blob = g_blob;
354 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0)
355
356 spdk_blob_close(blob, blob_op_complete, NULL);
357 poll_threads();
358 CU_ASSERT(g_bserrno == 0);
359
360 /* Create blob with default options (opts == NULL) */
361
362 spdk_bs_create_blob_ext(bs, NULL, blob_op_with_id_complete, NULL);
363 poll_threads();
364 CU_ASSERT(g_bserrno == 0);
365 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
366 blobid = g_blobid;
367
368 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
369 poll_threads();
370 CU_ASSERT(g_bserrno == 0);
371 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
372 blob = g_blob;
373 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0)
374
375 spdk_blob_close(blob, blob_op_complete, NULL);
376 poll_threads();
377 CU_ASSERT(g_bserrno == 0);
378
379 /* Try to create blob with size larger than blobstore */
380
381 spdk_blob_opts_init(&opts);
382 opts.num_clusters = bs->total_clusters + 1;
383
384 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
385 poll_threads();
386 CU_ASSERT(g_bserrno == -ENOSPC);
387
388 spdk_bs_unload(g_bs, bs_op_complete, NULL);
389 poll_threads();
390 CU_ASSERT(g_bserrno == 0);
391 g_bs = NULL;
392
393 }
394
395 static void
396 blob_create_internal(void)
397 {
398 struct spdk_blob_store *bs;
399 struct spdk_bs_dev *dev;
400 struct spdk_blob *blob;
401 struct spdk_blob_opts opts;
402 struct spdk_blob_xattr_opts internal_xattrs;
403 const void *value;
404 size_t value_len;
405 spdk_blob_id blobid;
406 int rc;
407
408 dev = init_dev();
409
410 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
411 poll_threads();
412 CU_ASSERT(g_bserrno == 0);
413 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
414 bs = g_bs;
415
416 /* Create blob with custom xattrs */
417
418 spdk_blob_opts_init(&opts);
419 _spdk_blob_xattrs_init(&internal_xattrs);
420 internal_xattrs.count = 3;
421 internal_xattrs.names = g_xattr_names;
422 internal_xattrs.get_value = _get_xattr_value;
423 internal_xattrs.ctx = &g_ctx;
424
425 _spdk_bs_create_blob(bs, &opts, &internal_xattrs, blob_op_with_id_complete, NULL);
426 poll_threads();
427 CU_ASSERT(g_bserrno == 0);
428 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
429 blobid = g_blobid;
430
431 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
432 poll_threads();
433 CU_ASSERT(g_bserrno == 0);
434 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
435 blob = g_blob;
436
437 rc = _spdk_blob_get_xattr_value(blob, g_xattr_names[0], &value, &value_len, true);
438 CU_ASSERT(rc == 0);
439 SPDK_CU_ASSERT_FATAL(value != NULL);
440 CU_ASSERT(value_len == strlen(g_xattr_values[0]));
441 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len);
442
443 rc = _spdk_blob_get_xattr_value(blob, g_xattr_names[1], &value, &value_len, true);
444 CU_ASSERT(rc == 0);
445 SPDK_CU_ASSERT_FATAL(value != NULL);
446 CU_ASSERT(value_len == strlen(g_xattr_values[1]));
447 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len);
448
449 rc = _spdk_blob_get_xattr_value(blob, g_xattr_names[2], &value, &value_len, true);
450 CU_ASSERT(rc == 0);
451 SPDK_CU_ASSERT_FATAL(value != NULL);
452 CU_ASSERT(value_len == strlen(g_xattr_values[2]));
453 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len);
454
455 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[0], &value, &value_len);
456 CU_ASSERT(rc != 0);
457
458 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[1], &value, &value_len);
459 CU_ASSERT(rc != 0);
460
461 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[2], &value, &value_len);
462 CU_ASSERT(rc != 0);
463
464 spdk_blob_close(blob, blob_op_complete, NULL);
465 poll_threads();
466 CU_ASSERT(g_bserrno == 0);
467
468 /* Create blob with NULL internal options */
469
470 _spdk_bs_create_blob(bs, NULL, NULL, blob_op_with_id_complete, NULL);
471 poll_threads();
472 CU_ASSERT(g_bserrno == 0);
473 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
474 blobid = g_blobid;
475
476 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
477 poll_threads();
478 CU_ASSERT(g_bserrno == 0);
479 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
480 CU_ASSERT(TAILQ_FIRST(&g_blob->xattrs_internal) == NULL);
481
482 blob = g_blob;
483
484 spdk_blob_close(blob, blob_op_complete, NULL);
485 poll_threads();
486 CU_ASSERT(g_bserrno == 0);
487
488 spdk_bs_unload(g_bs, bs_op_complete, NULL);
489 poll_threads();
490 CU_ASSERT(g_bserrno == 0);
491 g_bs = NULL;
492
493 }
494
495 static void
496 blob_thin_provision(void)
497 {
498 struct spdk_blob_store *bs;
499 struct spdk_bs_dev *dev;
500 struct spdk_blob *blob;
501 struct spdk_blob_opts opts;
502 struct spdk_bs_opts bs_opts;
503 spdk_blob_id blobid;
504
505 dev = init_dev();
506 spdk_bs_opts_init(&bs_opts);
507 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE");
508
509 /* Initialize a new blob store */
510 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL);
511 poll_threads();
512 CU_ASSERT(g_bserrno == 0);
513 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
514
515 bs = g_bs;
516
517 /* Create blob with thin provisioning enabled */
518
519 spdk_blob_opts_init(&opts);
520 opts.thin_provision = true;
521 opts.num_clusters = 10;
522
523 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
524 poll_threads();
525 CU_ASSERT(g_bserrno == 0);
526 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
527 blobid = g_blobid;
528
529 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
530 poll_threads();
531 CU_ASSERT(g_bserrno == 0);
532 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
533 blob = g_blob;
534 CU_ASSERT(blob->invalid_flags & SPDK_BLOB_THIN_PROV);
535
536 spdk_blob_close(blob, blob_op_complete, NULL);
537 CU_ASSERT(g_bserrno == 0);
538
539 /* Do not shut down cleanly. This makes sure that when we load again
540 * and try to recover a valid used_cluster map, that blobstore will
541 * ignore clusters with index 0 since these are unallocated clusters.
542 */
543
544 /* Load an existing blob store and check if invalid_flags is set */
545 dev = init_dev();
546 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE");
547 spdk_bs_load(dev, &bs_opts, bs_op_with_handle_complete, NULL);
548 poll_threads();
549 CU_ASSERT(g_bserrno == 0);
550 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
551
552 bs = g_bs;
553
554 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
555 poll_threads();
556 CU_ASSERT(g_bserrno == 0);
557 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
558 blob = g_blob;
559 CU_ASSERT(blob->invalid_flags & SPDK_BLOB_THIN_PROV);
560
561 spdk_blob_close(blob, blob_op_complete, NULL);
562 poll_threads();
563 CU_ASSERT(g_bserrno == 0);
564
565 spdk_bs_unload(g_bs, bs_op_complete, NULL);
566 poll_threads();
567 CU_ASSERT(g_bserrno == 0);
568 g_bs = NULL;
569 }
570
571 static void
572 blob_snapshot(void)
573 {
574 struct spdk_blob_store *bs;
575 struct spdk_bs_dev *dev;
576 struct spdk_blob *blob;
577 struct spdk_blob *snapshot, *snapshot2;
578 struct spdk_blob_bs_dev *blob_bs_dev;
579 struct spdk_blob_opts opts;
580 struct spdk_blob_xattr_opts xattrs;
581 spdk_blob_id blobid;
582 spdk_blob_id snapshotid;
583 spdk_blob_id snapshotid2;
584 const void *value;
585 size_t value_len;
586 int rc;
587
588 dev = init_dev();
589
590 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
591 poll_threads();
592 CU_ASSERT(g_bserrno == 0);
593 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
594 bs = g_bs;
595
596 /* Create blob with 10 clusters */
597 spdk_blob_opts_init(&opts);
598 opts.num_clusters = 10;
599
600 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
601 poll_threads();
602 CU_ASSERT(g_bserrno == 0);
603 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
604 blobid = g_blobid;
605
606 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
607 poll_threads();
608 CU_ASSERT(g_bserrno == 0);
609 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
610 blob = g_blob;
611 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
612
613 /* Create snapshot from blob */
614 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 0);
615 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
616 poll_threads();
617 CU_ASSERT(g_bserrno == 0);
618 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
619 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 1);
620 snapshotid = g_blobid;
621
622 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
623 poll_threads();
624 CU_ASSERT(g_bserrno == 0);
625 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
626 snapshot = g_blob;
627 CU_ASSERT(snapshot->data_ro == true)
628 CU_ASSERT(snapshot->md_ro == true)
629 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 10)
630
631 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
632 CU_ASSERT(blob->invalid_flags & SPDK_BLOB_THIN_PROV);
633 CU_ASSERT(spdk_mem_all_zero(blob->active.clusters,
634 blob->active.num_clusters * sizeof(blob->active.clusters[0])));
635
636 /* Try to create snapshot from clone with xattrs */
637 xattrs.names = g_xattr_names;
638 xattrs.get_value = _get_xattr_value;
639 xattrs.count = 3;
640 xattrs.ctx = &g_ctx;
641 spdk_bs_create_snapshot(bs, blobid, &xattrs, blob_op_with_id_complete, NULL);
642 poll_threads();
643 CU_ASSERT(g_bserrno == 0);
644 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
645 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 2);
646 snapshotid2 = g_blobid;
647
648 spdk_bs_open_blob(bs, snapshotid2, blob_op_with_handle_complete, NULL);
649 CU_ASSERT(g_bserrno == 0);
650 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
651 snapshot2 = g_blob;
652 CU_ASSERT(snapshot2->data_ro == true)
653 CU_ASSERT(snapshot2->md_ro == true)
654 CU_ASSERT(spdk_blob_get_num_clusters(snapshot2) == 10)
655
656 /* Confirm that blob is backed by snapshot2 and snapshot2 is backed by snapshot */
657 CU_ASSERT(snapshot->back_bs_dev == NULL);
658 SPDK_CU_ASSERT_FATAL(blob->back_bs_dev != NULL);
659 SPDK_CU_ASSERT_FATAL(snapshot2->back_bs_dev != NULL);
660
661 blob_bs_dev = (struct spdk_blob_bs_dev *)blob->back_bs_dev;
662 CU_ASSERT(blob_bs_dev->blob == snapshot2);
663
664 blob_bs_dev = (struct spdk_blob_bs_dev *)snapshot2->back_bs_dev;
665 CU_ASSERT(blob_bs_dev->blob == snapshot);
666
667 rc = spdk_blob_get_xattr_value(snapshot2, g_xattr_names[0], &value, &value_len);
668 CU_ASSERT(rc == 0);
669 SPDK_CU_ASSERT_FATAL(value != NULL);
670 CU_ASSERT(value_len == strlen(g_xattr_values[0]));
671 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len);
672
673 rc = spdk_blob_get_xattr_value(snapshot2, g_xattr_names[1], &value, &value_len);
674 CU_ASSERT(rc == 0);
675 SPDK_CU_ASSERT_FATAL(value != NULL);
676 CU_ASSERT(value_len == strlen(g_xattr_values[1]));
677 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len);
678
679 rc = spdk_blob_get_xattr_value(snapshot2, g_xattr_names[2], &value, &value_len);
680 CU_ASSERT(rc == 0);
681 SPDK_CU_ASSERT_FATAL(value != NULL);
682 CU_ASSERT(value_len == strlen(g_xattr_values[2]));
683 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len);
684
685 /* Try to create snapshot from snapshot */
686 spdk_bs_create_snapshot(bs, snapshotid, NULL, blob_op_with_id_complete, NULL);
687 poll_threads();
688 CU_ASSERT(g_bserrno == -EINVAL);
689 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID);
690 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 2);
691
692 spdk_blob_close(blob, blob_op_complete, NULL);
693 poll_threads();
694 CU_ASSERT(g_bserrno == 0);
695
696 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
697 CU_ASSERT(g_bserrno == 0);
698 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 2);
699
700 spdk_blob_close(snapshot2, blob_op_complete, NULL);
701 poll_threads();
702 CU_ASSERT(g_bserrno == 0);
703
704 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
705 poll_threads();
706 CU_ASSERT(g_bserrno == 0);
707 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 1);
708
709 spdk_blob_close(snapshot, blob_op_complete, NULL);
710 poll_threads();
711 CU_ASSERT(g_bserrno == 0);
712
713 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
714 poll_threads();
715 CU_ASSERT(g_bserrno == 0);
716 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 0);
717
718 spdk_bs_unload(g_bs, bs_op_complete, NULL);
719 poll_threads();
720 CU_ASSERT(g_bserrno == 0);
721 g_bs = NULL;
722 }
723
724 static void
725 blob_snapshot_freeze_io(void)
726 {
727 struct spdk_thread *thread;
728 struct spdk_io_channel *channel;
729 struct spdk_bs_channel *bs_channel;
730 struct spdk_blob_store *bs;
731 struct spdk_bs_dev *dev;
732 struct spdk_blob *blob;
733 struct spdk_blob_opts opts;
734 spdk_blob_id blobid;
735 uint32_t num_of_pages = 10;
736 uint8_t payload_read[num_of_pages * SPDK_BS_PAGE_SIZE];
737 uint8_t payload_write[num_of_pages * SPDK_BS_PAGE_SIZE];
738 uint8_t payload_zero[num_of_pages * SPDK_BS_PAGE_SIZE];
739
740 memset(payload_write, 0xE5, sizeof(payload_write));
741 memset(payload_read, 0x00, sizeof(payload_read));
742 memset(payload_zero, 0x00, sizeof(payload_zero));
743
744 dev = init_dev();
745 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE);
746
747 /* Test freeze I/O during snapshot */
748
749 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
750 poll_threads();
751 CU_ASSERT(g_bserrno == 0);
752 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
753 bs = g_bs;
754
755 channel = spdk_bs_alloc_io_channel(bs);
756 bs_channel = spdk_io_channel_get_ctx(channel);
757
758 /* Create blob with 10 clusters */
759 spdk_blob_opts_init(&opts);
760 opts.num_clusters = 10;
761 opts.thin_provision = false;
762
763 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
764 poll_threads();
765 CU_ASSERT(g_bserrno == 0);
766 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
767 blobid = g_blobid;
768
769 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
770 poll_threads();
771 CU_ASSERT(g_bserrno == 0);
772 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
773 blob = g_blob;
774 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10);
775
776 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
777
778 /* This is implementation specific.
779 * Flag 'frozen_io' is set in _spdk_bs_snapshot_freeze_cpl callback.
780 * Four async I/O operations happen before that. */
781 thread = spdk_get_thread();
782 spdk_thread_poll(thread, 1, 0);
783 spdk_thread_poll(thread, 1, 0);
784 spdk_thread_poll(thread, 1, 0);
785
786 CU_ASSERT(TAILQ_EMPTY(&bs_channel->queued_io));
787
788 /* Blob I/O should be frozen here */
789 CU_ASSERT(blob->frozen_refcnt == 1);
790
791 /* Write to the blob */
792 spdk_blob_io_write(blob, channel, payload_write, 0, num_of_pages, blob_op_complete, NULL);
793
794 /* Verify that I/O is queued */
795 CU_ASSERT(!TAILQ_EMPTY(&bs_channel->queued_io));
796 /* Verify that payload is not written to disk */
797 CU_ASSERT(memcmp(payload_zero, &g_dev_buffer[blob->active.clusters[0]*SPDK_BS_PAGE_SIZE],
798 SPDK_BS_PAGE_SIZE) == 0);
799
800 /* Finish all operations including spdk_bs_create_snapshot */
801 poll_threads();
802
803 /* Verify snapshot */
804 CU_ASSERT(g_bserrno == 0);
805 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
806
807 /* Verify that blob has unset frozen_io */
808 CU_ASSERT(blob->frozen_refcnt == 0);
809
810 /* Verify that postponed I/O completed successfully by comparing payload */
811 spdk_blob_io_read(blob, channel, payload_read, 0, num_of_pages, blob_op_complete, NULL);
812 poll_threads();
813 CU_ASSERT(g_bserrno == 0);
814 CU_ASSERT(memcmp(payload_write, payload_read, num_of_pages * SPDK_BS_PAGE_SIZE) == 0);
815
816 spdk_blob_close(blob, blob_op_complete, NULL);
817 poll_threads();
818 CU_ASSERT(g_bserrno == 0);
819
820 spdk_bs_free_io_channel(channel);
821 poll_threads();
822
823 spdk_bs_unload(g_bs, bs_op_complete, NULL);
824 poll_threads();
825 CU_ASSERT(g_bserrno == 0);
826 g_bs = NULL;
827 }
828
829 static void
830 blob_clone(void)
831 {
832 struct spdk_blob_store *bs;
833 struct spdk_bs_dev *dev;
834 struct spdk_blob_opts opts;
835 struct spdk_blob *blob, *snapshot, *clone;
836 spdk_blob_id blobid, cloneid, snapshotid;
837 struct spdk_blob_xattr_opts xattrs;
838 const void *value;
839 size_t value_len;
840 int rc;
841
842 dev = init_dev();
843
844 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
845 poll_threads();
846 CU_ASSERT(g_bserrno == 0);
847 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
848 bs = g_bs;
849
850 /* Create blob with 10 clusters */
851
852 spdk_blob_opts_init(&opts);
853 opts.num_clusters = 10;
854
855 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
856 poll_threads();
857 CU_ASSERT(g_bserrno == 0);
858 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
859 blobid = g_blobid;
860
861 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
862 poll_threads();
863 CU_ASSERT(g_bserrno == 0);
864 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
865 blob = g_blob;
866 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
867
868 /* Create snapshot */
869 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
870 poll_threads();
871 CU_ASSERT(g_bserrno == 0);
872 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
873 snapshotid = g_blobid;
874
875 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
876 poll_threads();
877 CU_ASSERT(g_bserrno == 0);
878 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
879 snapshot = g_blob;
880 CU_ASSERT(snapshot->data_ro == true)
881 CU_ASSERT(snapshot->md_ro == true)
882 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 10);
883
884 spdk_blob_close(snapshot, blob_op_complete, NULL);
885 poll_threads();
886 CU_ASSERT(g_bserrno == 0);
887
888 /* Create clone from snapshot with xattrs */
889 xattrs.names = g_xattr_names;
890 xattrs.get_value = _get_xattr_value;
891 xattrs.count = 3;
892 xattrs.ctx = &g_ctx;
893
894 spdk_bs_create_clone(bs, snapshotid, &xattrs, blob_op_with_id_complete, NULL);
895 poll_threads();
896 CU_ASSERT(g_bserrno == 0);
897 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
898 cloneid = g_blobid;
899
900 spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL);
901 poll_threads();
902 CU_ASSERT(g_bserrno == 0);
903 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
904 clone = g_blob;
905 CU_ASSERT(clone->data_ro == false)
906 CU_ASSERT(clone->md_ro == false)
907 CU_ASSERT(spdk_blob_get_num_clusters(clone) == 10);
908
909 rc = spdk_blob_get_xattr_value(clone, g_xattr_names[0], &value, &value_len);
910 CU_ASSERT(rc == 0);
911 SPDK_CU_ASSERT_FATAL(value != NULL);
912 CU_ASSERT(value_len == strlen(g_xattr_values[0]));
913 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len);
914
915 rc = spdk_blob_get_xattr_value(clone, g_xattr_names[1], &value, &value_len);
916 CU_ASSERT(rc == 0);
917 SPDK_CU_ASSERT_FATAL(value != NULL);
918 CU_ASSERT(value_len == strlen(g_xattr_values[1]));
919 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len);
920
921 rc = spdk_blob_get_xattr_value(clone, g_xattr_names[2], &value, &value_len);
922 CU_ASSERT(rc == 0);
923 SPDK_CU_ASSERT_FATAL(value != NULL);
924 CU_ASSERT(value_len == strlen(g_xattr_values[2]));
925 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len);
926
927
928 spdk_blob_close(clone, blob_op_complete, NULL);
929 poll_threads();
930 CU_ASSERT(g_bserrno == 0);
931
932 /* Try to create clone from not read only blob */
933 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL);
934 poll_threads();
935 CU_ASSERT(g_bserrno == -EINVAL);
936 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID);
937
938 /* Mark blob as read only */
939 spdk_blob_set_read_only(blob);
940 spdk_blob_sync_md(blob, blob_op_complete, NULL);
941 poll_threads();
942 CU_ASSERT(g_bserrno == 0);
943
944 /* Create clone from read only blob */
945 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL);
946 poll_threads();
947 CU_ASSERT(g_bserrno == 0);
948 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
949 cloneid = g_blobid;
950
951 spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL);
952 poll_threads();
953 CU_ASSERT(g_bserrno == 0);
954 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
955 clone = g_blob;
956 CU_ASSERT(clone->data_ro == false)
957 CU_ASSERT(clone->md_ro == false)
958 CU_ASSERT(spdk_blob_get_num_clusters(clone) == 10);
959
960 spdk_blob_close(clone, blob_op_complete, NULL);
961 poll_threads();
962 CU_ASSERT(g_bserrno == 0);
963
964 spdk_blob_close(blob, blob_op_complete, NULL);
965 poll_threads();
966 CU_ASSERT(g_bserrno == 0);
967
968 spdk_bs_unload(g_bs, bs_op_complete, NULL);
969 poll_threads();
970 CU_ASSERT(g_bserrno == 0);
971 g_bs = NULL;
972
973 }
974
975 static void
976 _blob_inflate(bool decouple_parent)
977 {
978 struct spdk_blob_store *bs;
979 struct spdk_bs_dev *dev;
980 struct spdk_blob_opts opts;
981 struct spdk_blob *blob, *snapshot;
982 spdk_blob_id blobid, snapshotid;
983 struct spdk_io_channel *channel;
984 uint64_t free_clusters;
985
986 dev = init_dev();
987
988 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
989 poll_threads();
990 CU_ASSERT(g_bserrno == 0);
991 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
992 bs = g_bs;
993
994 channel = spdk_bs_alloc_io_channel(bs);
995 SPDK_CU_ASSERT_FATAL(channel != NULL);
996
997 /* Create blob with 10 clusters */
998
999 spdk_blob_opts_init(&opts);
1000 opts.num_clusters = 10;
1001 opts.thin_provision = true;
1002
1003 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
1004 poll_threads();
1005 CU_ASSERT(g_bserrno == 0);
1006 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1007 blobid = g_blobid;
1008
1009 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1010 poll_threads();
1011 CU_ASSERT(g_bserrno == 0);
1012 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1013 blob = g_blob;
1014
1015 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
1016 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == true);
1017
1018 /* 1) Blob with no parent */
1019 if (decouple_parent) {
1020 /* Decouple parent of blob with no parent (should fail) */
1021 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL);
1022 poll_threads();
1023 CU_ASSERT(g_bserrno != 0);
1024 } else {
1025 /* Inflate of thin blob with no parent should made it thick */
1026 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL);
1027 poll_threads();
1028 CU_ASSERT(g_bserrno == 0);
1029 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == false);
1030 }
1031
1032 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
1033 poll_threads();
1034 CU_ASSERT(g_bserrno == 0);
1035 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1036 snapshotid = g_blobid;
1037
1038 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == true);
1039 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
1040
1041 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
1042 poll_threads();
1043 CU_ASSERT(g_bserrno == 0);
1044 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1045 snapshot = g_blob;
1046 CU_ASSERT(snapshot->data_ro == true)
1047 CU_ASSERT(snapshot->md_ro == true)
1048 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 10);
1049
1050 spdk_blob_close(snapshot, blob_op_complete, NULL);
1051 poll_threads();
1052 CU_ASSERT(g_bserrno == 0);
1053
1054 free_clusters = spdk_bs_free_cluster_count(bs);
1055
1056 /* 2) Blob with parent */
1057 if (!decouple_parent) {
1058 /* Do full blob inflation */
1059 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL);
1060 poll_threads();
1061 CU_ASSERT(g_bserrno == 0);
1062 /* all 10 clusters should be allocated */
1063 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters - 10);
1064 } else {
1065 /* Decouple parent of blob */
1066 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL);
1067 poll_threads();
1068 CU_ASSERT(g_bserrno == 0);
1069 /* when only parent is removed, none of the clusters should be allocated */
1070 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters);
1071 }
1072
1073 /* Now, it should be possible to delete snapshot */
1074 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
1075 poll_threads();
1076 CU_ASSERT(g_bserrno == 0);
1077
1078 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
1079 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == decouple_parent);
1080
1081 spdk_blob_close(blob, blob_op_complete, NULL);
1082 poll_threads();
1083 CU_ASSERT(g_bserrno == 0);
1084
1085 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1086 poll_threads();
1087 CU_ASSERT(g_bserrno == 0);
1088 g_bs = NULL;
1089
1090 spdk_bs_free_io_channel(channel);
1091 poll_threads();
1092 }
1093
1094 static void
1095 blob_inflate(void)
1096 {
1097 _blob_inflate(false);
1098 _blob_inflate(true);
1099 }
1100
1101 static void
1102 blob_delete(void)
1103 {
1104 struct spdk_blob_store *bs;
1105 struct spdk_bs_dev *dev;
1106 spdk_blob_id blobid;
1107
1108 dev = init_dev();
1109
1110 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1111 poll_threads();
1112 CU_ASSERT(g_bserrno == 0);
1113 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1114 bs = g_bs;
1115
1116 /* Create a blob and then delete it. */
1117 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1118 poll_threads();
1119 CU_ASSERT(g_bserrno == 0);
1120 CU_ASSERT(g_blobid > 0);
1121 blobid = g_blobid;
1122
1123 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
1124 poll_threads();
1125 CU_ASSERT(g_bserrno == 0);
1126
1127 /* Try to open the blob */
1128 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1129 poll_threads();
1130 CU_ASSERT(g_bserrno == -ENOENT);
1131
1132 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1133 poll_threads();
1134 CU_ASSERT(g_bserrno == 0);
1135 g_bs = NULL;
1136 }
1137
1138 static void
1139 blob_resize(void)
1140 {
1141 struct spdk_blob_store *bs;
1142 struct spdk_bs_dev *dev;
1143 struct spdk_blob *blob;
1144 spdk_blob_id blobid;
1145 uint64_t free_clusters;
1146
1147 dev = init_dev();
1148
1149 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1150 poll_threads();
1151 CU_ASSERT(g_bserrno == 0);
1152 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1153 bs = g_bs;
1154 free_clusters = spdk_bs_free_cluster_count(bs);
1155
1156 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1157 poll_threads();
1158 CU_ASSERT(g_bserrno == 0);
1159 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1160 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
1161 blobid = g_blobid;
1162
1163 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1164 poll_threads();
1165 CU_ASSERT(g_bserrno == 0);
1166 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1167 blob = g_blob;
1168
1169 /* Confirm that resize fails if blob is marked read-only. */
1170 blob->md_ro = true;
1171 spdk_blob_resize(blob, 5, blob_op_complete, NULL);
1172 poll_threads();
1173 CU_ASSERT(g_bserrno == -EPERM);
1174 blob->md_ro = false;
1175
1176 /* The blob started at 0 clusters. Resize it to be 5. */
1177 spdk_blob_resize(blob, 5, blob_op_complete, NULL);
1178 poll_threads();
1179 CU_ASSERT(g_bserrno == 0);
1180 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs));
1181
1182 /* Shrink the blob to 3 clusters. This will not actually release
1183 * the old clusters until the blob is synced.
1184 */
1185 spdk_blob_resize(blob, 3, blob_op_complete, NULL);
1186 poll_threads();
1187 CU_ASSERT(g_bserrno == 0);
1188 /* Verify there are still 5 clusters in use */
1189 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs));
1190
1191 spdk_blob_sync_md(blob, blob_op_complete, NULL);
1192 poll_threads();
1193 CU_ASSERT(g_bserrno == 0);
1194 /* Now there are only 3 clusters in use */
1195 CU_ASSERT((free_clusters - 3) == spdk_bs_free_cluster_count(bs));
1196
1197 /* Resize the blob to be 10 clusters. Growth takes effect immediately. */
1198 spdk_blob_resize(blob, 10, blob_op_complete, NULL);
1199 poll_threads();
1200 CU_ASSERT(g_bserrno == 0);
1201 CU_ASSERT((free_clusters - 10) == spdk_bs_free_cluster_count(bs));
1202
1203 /* Try to resize the blob to size larger than blobstore. */
1204 spdk_blob_resize(blob, bs->total_clusters + 1, blob_op_complete, NULL);
1205 poll_threads();
1206 CU_ASSERT(g_bserrno == -ENOSPC);
1207
1208 spdk_blob_close(blob, blob_op_complete, NULL);
1209 poll_threads();
1210 CU_ASSERT(g_bserrno == 0);
1211
1212 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
1213 poll_threads();
1214 CU_ASSERT(g_bserrno == 0);
1215
1216 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1217 poll_threads();
1218 CU_ASSERT(g_bserrno == 0);
1219 g_bs = NULL;
1220 }
1221
1222 static void
1223 blob_read_only(void)
1224 {
1225 struct spdk_blob_store *bs;
1226 struct spdk_bs_dev *dev;
1227 struct spdk_blob *blob;
1228 struct spdk_bs_opts opts;
1229 spdk_blob_id blobid;
1230 int rc;
1231
1232 dev = init_dev();
1233 spdk_bs_opts_init(&opts);
1234 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
1235
1236 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
1237 poll_threads();
1238 CU_ASSERT(g_bserrno == 0);
1239 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1240 bs = g_bs;
1241
1242 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1243 poll_threads();
1244 CU_ASSERT(g_bserrno == 0);
1245 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1246 blobid = g_blobid;
1247
1248 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1249 poll_threads();
1250 CU_ASSERT(g_bserrno == 0);
1251 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1252 blob = g_blob;
1253
1254 rc = spdk_blob_set_read_only(blob);
1255 CU_ASSERT(rc == 0);
1256
1257 CU_ASSERT(blob->data_ro == false);
1258 CU_ASSERT(blob->md_ro == false);
1259
1260 spdk_blob_sync_md(blob, bs_op_complete, NULL);
1261 poll_threads();
1262
1263 CU_ASSERT(blob->data_ro == true);
1264 CU_ASSERT(blob->md_ro == true);
1265 CU_ASSERT(blob->data_ro_flags & SPDK_BLOB_READ_ONLY);
1266
1267 spdk_blob_close(blob, blob_op_complete, NULL);
1268 poll_threads();
1269 CU_ASSERT(g_bserrno == 0);
1270
1271 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1272 poll_threads();
1273 CU_ASSERT(g_bserrno == 0);
1274 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1275 blob = g_blob;
1276
1277 CU_ASSERT(blob->data_ro == true);
1278 CU_ASSERT(blob->md_ro == true);
1279 CU_ASSERT(blob->data_ro_flags & SPDK_BLOB_READ_ONLY);
1280
1281 spdk_blob_close(blob, blob_op_complete, NULL);
1282 poll_threads();
1283 CU_ASSERT(g_bserrno == 0);
1284
1285 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1286 poll_threads();
1287 CU_ASSERT(g_bserrno == 0);
1288 g_bs = NULL;
1289 g_blob = NULL;
1290 g_blobid = 0;
1291
1292 /* Load an existing blob store */
1293 dev = init_dev();
1294 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
1295 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
1296 poll_threads();
1297 CU_ASSERT(g_bserrno == 0);
1298 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1299
1300 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
1301 poll_threads();
1302 CU_ASSERT(g_bserrno == 0);
1303 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1304 blob = g_blob;
1305
1306 CU_ASSERT(blob->data_ro == true);
1307 CU_ASSERT(blob->md_ro == true);
1308 CU_ASSERT(blob->data_ro_flags & SPDK_BLOB_READ_ONLY);
1309
1310 spdk_blob_close(blob, blob_op_complete, NULL);
1311 poll_threads();
1312 CU_ASSERT(g_bserrno == 0);
1313
1314 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1315 poll_threads();
1316 CU_ASSERT(g_bserrno == 0);
1317
1318 }
1319
1320 static void
1321 channel_ops(void)
1322 {
1323 struct spdk_blob_store *bs;
1324 struct spdk_bs_dev *dev;
1325 struct spdk_io_channel *channel;
1326
1327 dev = init_dev();
1328
1329 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1330 poll_threads();
1331 CU_ASSERT(g_bserrno == 0);
1332 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1333 bs = g_bs;
1334
1335 channel = spdk_bs_alloc_io_channel(bs);
1336 CU_ASSERT(channel != NULL);
1337
1338 spdk_bs_free_io_channel(channel);
1339 poll_threads();
1340
1341 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1342 poll_threads();
1343 CU_ASSERT(g_bserrno == 0);
1344 g_bs = NULL;
1345 }
1346
1347 static void
1348 blob_write(void)
1349 {
1350 struct spdk_blob_store *bs;
1351 struct spdk_bs_dev *dev;
1352 struct spdk_blob *blob;
1353 struct spdk_io_channel *channel;
1354 spdk_blob_id blobid;
1355 uint64_t pages_per_cluster;
1356 uint8_t payload[10 * 4096];
1357
1358 dev = init_dev();
1359
1360 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1361 poll_threads();
1362 CU_ASSERT(g_bserrno == 0);
1363 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1364 bs = g_bs;
1365
1366 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs);
1367
1368 channel = spdk_bs_alloc_io_channel(bs);
1369 CU_ASSERT(channel != NULL);
1370
1371 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1372 poll_threads();
1373 CU_ASSERT(g_bserrno == 0);
1374 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1375 blobid = g_blobid;
1376
1377 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1378 poll_threads();
1379 CU_ASSERT(g_bserrno == 0);
1380 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1381 blob = g_blob;
1382
1383 /* Write to a blob with 0 size */
1384 spdk_blob_io_write(blob, channel, payload, 0, 1, blob_op_complete, NULL);
1385 poll_threads();
1386 CU_ASSERT(g_bserrno == -EINVAL);
1387
1388 /* Resize the blob */
1389 spdk_blob_resize(blob, 5, blob_op_complete, NULL);
1390 poll_threads();
1391 CU_ASSERT(g_bserrno == 0);
1392
1393 /* Confirm that write fails if blob is marked read-only. */
1394 blob->data_ro = true;
1395 spdk_blob_io_write(blob, channel, payload, 0, 1, blob_op_complete, NULL);
1396 poll_threads();
1397 CU_ASSERT(g_bserrno == -EPERM);
1398 blob->data_ro = false;
1399
1400 /* Write to the blob */
1401 spdk_blob_io_write(blob, channel, payload, 0, 1, blob_op_complete, NULL);
1402 poll_threads();
1403 CU_ASSERT(g_bserrno == 0);
1404
1405 /* Write starting beyond the end */
1406 spdk_blob_io_write(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete,
1407 NULL);
1408 poll_threads();
1409 CU_ASSERT(g_bserrno == -EINVAL);
1410
1411 /* Write starting at a valid location but going off the end */
1412 spdk_blob_io_write(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1,
1413 blob_op_complete, NULL);
1414 poll_threads();
1415 CU_ASSERT(g_bserrno == -EINVAL);
1416
1417 spdk_blob_close(blob, blob_op_complete, NULL);
1418 poll_threads();
1419 CU_ASSERT(g_bserrno == 0);
1420
1421 spdk_bs_free_io_channel(channel);
1422 poll_threads();
1423
1424 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1425 poll_threads();
1426 CU_ASSERT(g_bserrno == 0);
1427 g_bs = NULL;
1428 }
1429
1430 static void
1431 blob_read(void)
1432 {
1433 struct spdk_blob_store *bs;
1434 struct spdk_bs_dev *dev;
1435 struct spdk_blob *blob;
1436 struct spdk_io_channel *channel;
1437 spdk_blob_id blobid;
1438 uint64_t pages_per_cluster;
1439 uint8_t payload[10 * 4096];
1440
1441 dev = init_dev();
1442
1443 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1444 poll_threads();
1445 CU_ASSERT(g_bserrno == 0);
1446 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1447 bs = g_bs;
1448
1449 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs);
1450
1451 channel = spdk_bs_alloc_io_channel(bs);
1452 CU_ASSERT(channel != NULL);
1453
1454 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1455 poll_threads();
1456 CU_ASSERT(g_bserrno == 0);
1457 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1458 blobid = g_blobid;
1459
1460 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1461 poll_threads();
1462 CU_ASSERT(g_bserrno == 0);
1463 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1464 blob = g_blob;
1465
1466 /* Read from a blob with 0 size */
1467 spdk_blob_io_read(blob, channel, payload, 0, 1, blob_op_complete, NULL);
1468 poll_threads();
1469 CU_ASSERT(g_bserrno == -EINVAL);
1470
1471 /* Resize the blob */
1472 spdk_blob_resize(blob, 5, blob_op_complete, NULL);
1473 poll_threads();
1474 CU_ASSERT(g_bserrno == 0);
1475
1476 /* Confirm that read passes if blob is marked read-only. */
1477 blob->data_ro = true;
1478 spdk_blob_io_read(blob, channel, payload, 0, 1, blob_op_complete, NULL);
1479 poll_threads();
1480 CU_ASSERT(g_bserrno == 0);
1481 blob->data_ro = false;
1482
1483 /* Read from the blob */
1484 spdk_blob_io_read(blob, channel, payload, 0, 1, blob_op_complete, NULL);
1485 poll_threads();
1486 CU_ASSERT(g_bserrno == 0);
1487
1488 /* Read starting beyond the end */
1489 spdk_blob_io_read(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete,
1490 NULL);
1491 poll_threads();
1492 CU_ASSERT(g_bserrno == -EINVAL);
1493
1494 /* Read starting at a valid location but going off the end */
1495 spdk_blob_io_read(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1,
1496 blob_op_complete, NULL);
1497 poll_threads();
1498 CU_ASSERT(g_bserrno == -EINVAL);
1499
1500 spdk_blob_close(blob, blob_op_complete, NULL);
1501 poll_threads();
1502 CU_ASSERT(g_bserrno == 0);
1503
1504 spdk_bs_free_io_channel(channel);
1505 poll_threads();
1506
1507 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1508 poll_threads();
1509 CU_ASSERT(g_bserrno == 0);
1510 g_bs = NULL;
1511 }
1512
1513 static void
1514 blob_rw_verify(void)
1515 {
1516 struct spdk_blob_store *bs;
1517 struct spdk_bs_dev *dev;
1518 struct spdk_blob *blob;
1519 struct spdk_io_channel *channel;
1520 spdk_blob_id blobid;
1521 uint8_t payload_read[10 * 4096];
1522 uint8_t payload_write[10 * 4096];
1523
1524 dev = init_dev();
1525
1526 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1527 poll_threads();
1528 CU_ASSERT(g_bserrno == 0);
1529 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1530 bs = g_bs;
1531
1532 channel = spdk_bs_alloc_io_channel(bs);
1533 CU_ASSERT(channel != NULL);
1534
1535 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1536 poll_threads();
1537 CU_ASSERT(g_bserrno == 0);
1538 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1539 blobid = g_blobid;
1540
1541 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1542 poll_threads();
1543 CU_ASSERT(g_bserrno == 0);
1544 CU_ASSERT(g_blob != NULL);
1545 blob = g_blob;
1546
1547 spdk_blob_resize(blob, 32, blob_op_complete, NULL);
1548 poll_threads();
1549 CU_ASSERT(g_bserrno == 0);
1550
1551 memset(payload_write, 0xE5, sizeof(payload_write));
1552 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
1553 poll_threads();
1554 CU_ASSERT(g_bserrno == 0);
1555
1556 memset(payload_read, 0x00, sizeof(payload_read));
1557 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
1558 poll_threads();
1559 CU_ASSERT(g_bserrno == 0);
1560 CU_ASSERT(memcmp(payload_write, payload_read, 4 * 4096) == 0);
1561
1562 spdk_blob_close(blob, blob_op_complete, NULL);
1563 poll_threads();
1564 CU_ASSERT(g_bserrno == 0);
1565
1566 spdk_bs_free_io_channel(channel);
1567 poll_threads();
1568
1569 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1570 poll_threads();
1571 CU_ASSERT(g_bserrno == 0);
1572 g_bs = NULL;
1573 }
1574
1575 static void
1576 blob_rw_verify_iov(void)
1577 {
1578 struct spdk_blob_store *bs;
1579 struct spdk_bs_dev *dev;
1580 struct spdk_blob *blob;
1581 struct spdk_io_channel *channel;
1582 spdk_blob_id blobid;
1583 uint8_t payload_read[10 * 4096];
1584 uint8_t payload_write[10 * 4096];
1585 struct iovec iov_read[3];
1586 struct iovec iov_write[3];
1587 void *buf;
1588
1589 dev = init_dev();
1590 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE);
1591
1592 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1593 poll_threads();
1594 CU_ASSERT(g_bserrno == 0);
1595 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1596 bs = g_bs;
1597
1598 channel = spdk_bs_alloc_io_channel(bs);
1599 CU_ASSERT(channel != NULL);
1600
1601 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1602 poll_threads();
1603 CU_ASSERT(g_bserrno == 0);
1604 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1605 blobid = g_blobid;
1606
1607 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1608 poll_threads();
1609 CU_ASSERT(g_bserrno == 0);
1610 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1611 blob = g_blob;
1612
1613 spdk_blob_resize(blob, 2, blob_op_complete, NULL);
1614 poll_threads();
1615 CU_ASSERT(g_bserrno == 0);
1616
1617 /*
1618 * Manually adjust the offset of the blob's second cluster. This allows
1619 * us to make sure that the readv/write code correctly accounts for I/O
1620 * that cross cluster boundaries. Start by asserting that the allocated
1621 * clusters are where we expect before modifying the second cluster.
1622 */
1623 CU_ASSERT(blob->active.clusters[0] == 1 * 256);
1624 CU_ASSERT(blob->active.clusters[1] == 2 * 256);
1625 blob->active.clusters[1] = 3 * 256;
1626
1627 memset(payload_write, 0xE5, sizeof(payload_write));
1628 iov_write[0].iov_base = payload_write;
1629 iov_write[0].iov_len = 1 * 4096;
1630 iov_write[1].iov_base = payload_write + 1 * 4096;
1631 iov_write[1].iov_len = 5 * 4096;
1632 iov_write[2].iov_base = payload_write + 6 * 4096;
1633 iov_write[2].iov_len = 4 * 4096;
1634 /*
1635 * Choose a page offset just before the cluster boundary. The first 6 pages of payload
1636 * will get written to the first cluster, the last 4 to the second cluster.
1637 */
1638 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL);
1639 poll_threads();
1640 CU_ASSERT(g_bserrno == 0);
1641
1642 memset(payload_read, 0xAA, sizeof(payload_read));
1643 iov_read[0].iov_base = payload_read;
1644 iov_read[0].iov_len = 3 * 4096;
1645 iov_read[1].iov_base = payload_read + 3 * 4096;
1646 iov_read[1].iov_len = 4 * 4096;
1647 iov_read[2].iov_base = payload_read + 7 * 4096;
1648 iov_read[2].iov_len = 3 * 4096;
1649 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL);
1650 poll_threads();
1651 CU_ASSERT(g_bserrno == 0);
1652 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
1653
1654 buf = calloc(1, 256 * 4096);
1655 SPDK_CU_ASSERT_FATAL(buf != NULL);
1656 /* Check that cluster 2 on "disk" was not modified. */
1657 CU_ASSERT(memcmp(buf, &g_dev_buffer[512 * 4096], 256 * 4096) == 0);
1658 free(buf);
1659
1660 spdk_blob_close(blob, blob_op_complete, NULL);
1661 poll_threads();
1662 CU_ASSERT(g_bserrno == 0);
1663
1664 spdk_bs_free_io_channel(channel);
1665 poll_threads();
1666
1667 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1668 poll_threads();
1669 CU_ASSERT(g_bserrno == 0);
1670 g_bs = NULL;
1671 }
1672
1673 static uint32_t
1674 bs_channel_get_req_count(struct spdk_io_channel *_channel)
1675 {
1676 struct spdk_bs_channel *channel = spdk_io_channel_get_ctx(_channel);
1677 struct spdk_bs_request_set *set;
1678 uint32_t count = 0;
1679
1680 TAILQ_FOREACH(set, &channel->reqs, link) {
1681 count++;
1682 }
1683
1684 return count;
1685 }
1686
1687 static void
1688 blob_rw_verify_iov_nomem(void)
1689 {
1690 struct spdk_blob_store *bs;
1691 struct spdk_bs_dev *dev;
1692 struct spdk_blob *blob;
1693 struct spdk_io_channel *channel;
1694 spdk_blob_id blobid;
1695 uint8_t payload_write[10 * 4096];
1696 struct iovec iov_write[3];
1697 uint32_t req_count;
1698
1699 dev = init_dev();
1700 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE);
1701
1702 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1703 poll_threads();
1704 CU_ASSERT(g_bserrno == 0);
1705 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1706 bs = g_bs;
1707
1708 channel = spdk_bs_alloc_io_channel(bs);
1709 CU_ASSERT(channel != NULL);
1710
1711 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1712 poll_threads();
1713 CU_ASSERT(g_bserrno == 0);
1714 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1715 blobid = g_blobid;
1716
1717 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1718 poll_threads();
1719 CU_ASSERT(g_bserrno == 0);
1720 CU_ASSERT(g_blob != NULL);
1721 blob = g_blob;
1722
1723 spdk_blob_resize(blob, 2, blob_op_complete, NULL);
1724 poll_threads();
1725 CU_ASSERT(g_bserrno == 0);
1726
1727 /*
1728 * Choose a page offset just before the cluster boundary. The first 6 pages of payload
1729 * will get written to the first cluster, the last 4 to the second cluster.
1730 */
1731 iov_write[0].iov_base = payload_write;
1732 iov_write[0].iov_len = 1 * 4096;
1733 iov_write[1].iov_base = payload_write + 1 * 4096;
1734 iov_write[1].iov_len = 5 * 4096;
1735 iov_write[2].iov_base = payload_write + 6 * 4096;
1736 iov_write[2].iov_len = 4 * 4096;
1737 MOCK_SET(calloc, NULL);
1738 req_count = bs_channel_get_req_count(channel);
1739 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL);
1740 poll_threads();
1741 CU_ASSERT(g_bserrno = -ENOMEM);
1742 CU_ASSERT(req_count == bs_channel_get_req_count(channel));
1743 MOCK_CLEAR(calloc);
1744
1745 spdk_blob_close(blob, blob_op_complete, NULL);
1746 poll_threads();
1747 CU_ASSERT(g_bserrno == 0);
1748
1749 spdk_bs_free_io_channel(channel);
1750 poll_threads();
1751
1752 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1753 poll_threads();
1754 CU_ASSERT(g_bserrno == 0);
1755 g_bs = NULL;
1756 }
1757
1758 static void
1759 blob_rw_iov_read_only(void)
1760 {
1761 struct spdk_blob_store *bs;
1762 struct spdk_bs_dev *dev;
1763 struct spdk_blob *blob;
1764 struct spdk_io_channel *channel;
1765 spdk_blob_id blobid;
1766 uint8_t payload_read[4096];
1767 uint8_t payload_write[4096];
1768 struct iovec iov_read;
1769 struct iovec iov_write;
1770
1771 dev = init_dev();
1772 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE);
1773
1774 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1775 poll_threads();
1776 CU_ASSERT(g_bserrno == 0);
1777 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1778 bs = g_bs;
1779
1780 channel = spdk_bs_alloc_io_channel(bs);
1781 CU_ASSERT(channel != NULL);
1782
1783 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
1784 poll_threads();
1785 CU_ASSERT(g_bserrno == 0);
1786 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1787 blobid = g_blobid;
1788
1789 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1790 poll_threads();
1791 CU_ASSERT(g_bserrno == 0);
1792 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1793 blob = g_blob;
1794
1795 spdk_blob_resize(blob, 2, blob_op_complete, NULL);
1796 poll_threads();
1797 CU_ASSERT(g_bserrno == 0);
1798
1799 /* Verify that writev failed if read_only flag is set. */
1800 blob->data_ro = true;
1801 iov_write.iov_base = payload_write;
1802 iov_write.iov_len = sizeof(payload_write);
1803 spdk_blob_io_writev(blob, channel, &iov_write, 1, 0, 1, blob_op_complete, NULL);
1804 poll_threads();
1805 CU_ASSERT(g_bserrno == -EPERM);
1806
1807 /* Verify that reads pass if data_ro flag is set. */
1808 iov_read.iov_base = payload_read;
1809 iov_read.iov_len = sizeof(payload_read);
1810 spdk_blob_io_readv(blob, channel, &iov_read, 1, 0, 1, blob_op_complete, NULL);
1811 poll_threads();
1812 CU_ASSERT(g_bserrno == 0);
1813
1814 spdk_blob_close(blob, blob_op_complete, NULL);
1815 poll_threads();
1816 CU_ASSERT(g_bserrno == 0);
1817
1818 spdk_bs_free_io_channel(channel);
1819 poll_threads();
1820
1821 spdk_bs_unload(g_bs, bs_op_complete, NULL);
1822 poll_threads();
1823 CU_ASSERT(g_bserrno == 0);
1824 g_bs = NULL;
1825 }
1826
1827 static void
1828 _blob_io_read_no_split(struct spdk_blob *blob, struct spdk_io_channel *channel,
1829 uint8_t *payload, uint64_t offset, uint64_t length,
1830 spdk_blob_op_complete cb_fn, void *cb_arg)
1831 {
1832 uint64_t i;
1833 uint8_t *buf;
1834 uint64_t page_size = spdk_bs_get_page_size(blob->bs);
1835
1836 /* To be sure that operation is NOT splitted, read one page at the time */
1837 buf = payload;
1838 for (i = 0; i < length; i++) {
1839 spdk_blob_io_read(blob, channel, buf, i + offset, 1, blob_op_complete, NULL);
1840 poll_threads();
1841 if (g_bserrno != 0) {
1842 /* Pass the error code up */
1843 break;
1844 }
1845 buf += page_size;
1846 }
1847
1848 cb_fn(cb_arg, g_bserrno);
1849 }
1850
1851 static void
1852 _blob_io_write_no_split(struct spdk_blob *blob, struct spdk_io_channel *channel,
1853 uint8_t *payload, uint64_t offset, uint64_t length,
1854 spdk_blob_op_complete cb_fn, void *cb_arg)
1855 {
1856 uint64_t i;
1857 uint8_t *buf;
1858 uint64_t page_size = spdk_bs_get_page_size(blob->bs);
1859
1860 /* To be sure that operation is NOT splitted, write one page at the time */
1861 buf = payload;
1862 for (i = 0; i < length; i++) {
1863 spdk_blob_io_write(blob, channel, buf, i + offset, 1, blob_op_complete, NULL);
1864 poll_threads();
1865 if (g_bserrno != 0) {
1866 /* Pass the error code up */
1867 break;
1868 }
1869 buf += page_size;
1870 }
1871
1872 cb_fn(cb_arg, g_bserrno);
1873 }
1874
1875 static void
1876 blob_operation_split_rw(void)
1877 {
1878 struct spdk_blob_store *bs;
1879 struct spdk_bs_dev *dev;
1880 struct spdk_blob *blob;
1881 struct spdk_io_channel *channel;
1882 struct spdk_blob_opts opts;
1883 spdk_blob_id blobid;
1884 uint64_t cluster_size;
1885
1886 uint64_t payload_size;
1887 uint8_t *payload_read;
1888 uint8_t *payload_write;
1889 uint8_t *payload_pattern;
1890
1891 uint64_t page_size;
1892 uint64_t pages_per_cluster;
1893 uint64_t pages_per_payload;
1894
1895 uint64_t i;
1896
1897 dev = init_dev();
1898
1899 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1900 poll_threads();
1901 CU_ASSERT(g_bserrno == 0);
1902 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1903 bs = g_bs;
1904
1905 cluster_size = spdk_bs_get_cluster_size(bs);
1906 page_size = spdk_bs_get_page_size(bs);
1907 pages_per_cluster = cluster_size / page_size;
1908 pages_per_payload = pages_per_cluster * 5;
1909 payload_size = cluster_size * 5;
1910
1911 payload_read = malloc(payload_size);
1912 SPDK_CU_ASSERT_FATAL(payload_read != NULL);
1913
1914 payload_write = malloc(payload_size);
1915 SPDK_CU_ASSERT_FATAL(payload_write != NULL);
1916
1917 payload_pattern = malloc(payload_size);
1918 SPDK_CU_ASSERT_FATAL(payload_pattern != NULL);
1919
1920 /* Prepare random pattern to write */
1921 memset(payload_pattern, 0xFF, payload_size);
1922 for (i = 0; i < pages_per_payload; i++) {
1923 *((uint64_t *)(payload_pattern + page_size * i)) = (i + 1);
1924 }
1925
1926 channel = spdk_bs_alloc_io_channel(bs);
1927 SPDK_CU_ASSERT_FATAL(channel != NULL);
1928
1929 /* Create blob */
1930 spdk_blob_opts_init(&opts);
1931 opts.thin_provision = false;
1932 opts.num_clusters = 5;
1933
1934 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
1935 poll_threads();
1936 CU_ASSERT(g_bserrno == 0);
1937 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1938 blobid = g_blobid;
1939
1940 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1941 poll_threads();
1942 CU_ASSERT(g_bserrno == 0);
1943 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
1944 blob = g_blob;
1945
1946 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5);
1947
1948 /* Initial read should return zeroed payload */
1949 memset(payload_read, 0xFF, payload_size);
1950 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL);
1951 poll_threads();
1952 CU_ASSERT(g_bserrno == 0);
1953 CU_ASSERT(spdk_mem_all_zero(payload_read, payload_size));
1954
1955 /* Fill whole blob except last page */
1956 spdk_blob_io_write(blob, channel, payload_pattern, 0, pages_per_payload - 1,
1957 blob_op_complete, NULL);
1958 poll_threads();
1959 CU_ASSERT(g_bserrno == 0);
1960
1961 /* Write last page with a pattern */
1962 spdk_blob_io_write(blob, channel, payload_pattern, pages_per_payload - 1, 1,
1963 blob_op_complete, NULL);
1964 poll_threads();
1965 CU_ASSERT(g_bserrno == 0);
1966
1967 /* Read whole blob and check consistency */
1968 memset(payload_read, 0xFF, payload_size);
1969 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL);
1970 poll_threads();
1971 CU_ASSERT(g_bserrno == 0);
1972 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size - page_size) == 0);
1973 CU_ASSERT(memcmp(payload_pattern, payload_read + payload_size - page_size, page_size) == 0);
1974
1975 /* Fill whole blob except first page */
1976 spdk_blob_io_write(blob, channel, payload_pattern, 1, pages_per_payload - 1,
1977 blob_op_complete, NULL);
1978 poll_threads();
1979 CU_ASSERT(g_bserrno == 0);
1980
1981 /* Write first page with a pattern */
1982 spdk_blob_io_write(blob, channel, payload_pattern, 0, 1,
1983 blob_op_complete, NULL);
1984 poll_threads();
1985 CU_ASSERT(g_bserrno == 0);
1986
1987 /* Read whole blob and check consistency */
1988 memset(payload_read, 0xFF, payload_size);
1989 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL);
1990 poll_threads();
1991 CU_ASSERT(g_bserrno == 0);
1992 CU_ASSERT(memcmp(payload_pattern, payload_read + page_size, payload_size - page_size) == 0);
1993 CU_ASSERT(memcmp(payload_pattern, payload_read, page_size) == 0);
1994
1995
1996 /* Fill whole blob with a pattern (5 clusters) */
1997
1998 /* 1. Read test. */
1999 _blob_io_write_no_split(blob, channel, payload_pattern, 0, pages_per_payload,
2000 blob_op_complete, NULL);
2001 poll_threads();
2002 CU_ASSERT(g_bserrno == 0);
2003
2004 memset(payload_read, 0xFF, payload_size);
2005 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL);
2006 poll_threads();
2007 poll_threads();
2008 CU_ASSERT(g_bserrno == 0);
2009 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0);
2010
2011 /* 2. Write test. */
2012 spdk_blob_io_write(blob, channel, payload_pattern, 0, pages_per_payload,
2013 blob_op_complete, NULL);
2014 poll_threads();
2015 CU_ASSERT(g_bserrno == 0);
2016
2017 memset(payload_read, 0xFF, payload_size);
2018 _blob_io_read_no_split(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL);
2019 poll_threads();
2020 CU_ASSERT(g_bserrno == 0);
2021 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0);
2022
2023 spdk_blob_close(blob, blob_op_complete, NULL);
2024 poll_threads();
2025 CU_ASSERT(g_bserrno == 0);
2026
2027 spdk_bs_free_io_channel(channel);
2028 poll_threads();
2029
2030 /* Unload the blob store */
2031 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2032 poll_threads();
2033 CU_ASSERT(g_bserrno == 0);
2034 g_bs = NULL;
2035 g_blob = NULL;
2036 g_blobid = 0;
2037
2038 free(payload_read);
2039 free(payload_write);
2040 free(payload_pattern);
2041 }
2042
2043 static void
2044 blob_operation_split_rw_iov(void)
2045 {
2046 struct spdk_blob_store *bs;
2047 struct spdk_bs_dev *dev;
2048 struct spdk_blob *blob;
2049 struct spdk_io_channel *channel;
2050 struct spdk_blob_opts opts;
2051 spdk_blob_id blobid;
2052 uint64_t cluster_size;
2053
2054 uint64_t payload_size;
2055 uint8_t *payload_read;
2056 uint8_t *payload_write;
2057 uint8_t *payload_pattern;
2058
2059 uint64_t page_size;
2060 uint64_t pages_per_cluster;
2061 uint64_t pages_per_payload;
2062
2063 struct iovec iov_read[2];
2064 struct iovec iov_write[2];
2065
2066 uint64_t i, j;
2067
2068 dev = init_dev();
2069
2070 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
2071 poll_threads();
2072 CU_ASSERT(g_bserrno == 0);
2073 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2074 bs = g_bs;
2075
2076 cluster_size = spdk_bs_get_cluster_size(bs);
2077 page_size = spdk_bs_get_page_size(bs);
2078 pages_per_cluster = cluster_size / page_size;
2079 pages_per_payload = pages_per_cluster * 5;
2080 payload_size = cluster_size * 5;
2081
2082 payload_read = malloc(payload_size);
2083 SPDK_CU_ASSERT_FATAL(payload_read != NULL);
2084
2085 payload_write = malloc(payload_size);
2086 SPDK_CU_ASSERT_FATAL(payload_write != NULL);
2087
2088 payload_pattern = malloc(payload_size);
2089 SPDK_CU_ASSERT_FATAL(payload_pattern != NULL);
2090
2091 /* Prepare random pattern to write */
2092 for (i = 0; i < pages_per_payload; i++) {
2093 for (j = 0; j < page_size / sizeof(uint64_t); j++) {
2094 uint64_t *tmp;
2095
2096 tmp = (uint64_t *)payload_pattern;
2097 tmp += ((page_size * i) / sizeof(uint64_t)) + j;
2098 *tmp = i + 1;
2099 }
2100 }
2101
2102 channel = spdk_bs_alloc_io_channel(bs);
2103 SPDK_CU_ASSERT_FATAL(channel != NULL);
2104
2105 /* Create blob */
2106 spdk_blob_opts_init(&opts);
2107 opts.thin_provision = false;
2108 opts.num_clusters = 5;
2109
2110 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
2111 poll_threads();
2112 CU_ASSERT(g_bserrno == 0);
2113 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2114 blobid = g_blobid;
2115
2116 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
2117 poll_threads();
2118 CU_ASSERT(g_bserrno == 0);
2119 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2120 blob = g_blob;
2121
2122 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5);
2123
2124 /* Initial read should return zeroes payload */
2125 memset(payload_read, 0xFF, payload_size);
2126 iov_read[0].iov_base = payload_read;
2127 iov_read[0].iov_len = cluster_size * 3;
2128 iov_read[1].iov_base = payload_read + cluster_size * 3;
2129 iov_read[1].iov_len = cluster_size * 2;
2130 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL);
2131 poll_threads();
2132 CU_ASSERT(g_bserrno == 0);
2133 CU_ASSERT(spdk_mem_all_zero(payload_read, payload_size));
2134
2135 /* First of iovs fills whole blob except last page and second of iovs writes last page
2136 * with a pattern. */
2137 iov_write[0].iov_base = payload_pattern;
2138 iov_write[0].iov_len = payload_size - page_size;
2139 iov_write[1].iov_base = payload_pattern;
2140 iov_write[1].iov_len = page_size;
2141 spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL);
2142 poll_threads();
2143 CU_ASSERT(g_bserrno == 0);
2144
2145 /* Read whole blob and check consistency */
2146 memset(payload_read, 0xFF, payload_size);
2147 iov_read[0].iov_base = payload_read;
2148 iov_read[0].iov_len = cluster_size * 2;
2149 iov_read[1].iov_base = payload_read + cluster_size * 2;
2150 iov_read[1].iov_len = cluster_size * 3;
2151 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL);
2152 poll_threads();
2153 CU_ASSERT(g_bserrno == 0);
2154 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size - page_size) == 0);
2155 CU_ASSERT(memcmp(payload_pattern, payload_read + payload_size - page_size, page_size) == 0);
2156
2157 /* First of iovs fills only first page and second of iovs writes whole blob except
2158 * first page with a pattern. */
2159 iov_write[0].iov_base = payload_pattern;
2160 iov_write[0].iov_len = page_size;
2161 iov_write[1].iov_base = payload_pattern;
2162 iov_write[1].iov_len = payload_size - page_size;
2163 spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL);
2164 poll_threads();
2165 CU_ASSERT(g_bserrno == 0);
2166
2167 /* Read whole blob and check consistency */
2168 memset(payload_read, 0xFF, payload_size);
2169 iov_read[0].iov_base = payload_read;
2170 iov_read[0].iov_len = cluster_size * 4;
2171 iov_read[1].iov_base = payload_read + cluster_size * 4;
2172 iov_read[1].iov_len = cluster_size;
2173 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL);
2174 poll_threads();
2175 CU_ASSERT(g_bserrno == 0);
2176 CU_ASSERT(memcmp(payload_pattern, payload_read + page_size, payload_size - page_size) == 0);
2177 CU_ASSERT(memcmp(payload_pattern, payload_read, page_size) == 0);
2178
2179
2180 /* Fill whole blob with a pattern (5 clusters) */
2181
2182 /* 1. Read test. */
2183 _blob_io_write_no_split(blob, channel, payload_pattern, 0, pages_per_payload,
2184 blob_op_complete, NULL);
2185 poll_threads();
2186 CU_ASSERT(g_bserrno == 0);
2187
2188 memset(payload_read, 0xFF, payload_size);
2189 iov_read[0].iov_base = payload_read;
2190 iov_read[0].iov_len = cluster_size;
2191 iov_read[1].iov_base = payload_read + cluster_size;
2192 iov_read[1].iov_len = cluster_size * 4;
2193 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL);
2194 poll_threads();
2195 CU_ASSERT(g_bserrno == 0);
2196 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0);
2197
2198 /* 2. Write test. */
2199 iov_write[0].iov_base = payload_read;
2200 iov_write[0].iov_len = cluster_size * 2;
2201 iov_write[1].iov_base = payload_read + cluster_size * 2;
2202 iov_write[1].iov_len = cluster_size * 3;
2203 spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL);
2204 poll_threads();
2205 CU_ASSERT(g_bserrno == 0);
2206
2207 memset(payload_read, 0xFF, payload_size);
2208 _blob_io_read_no_split(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL);
2209 poll_threads();
2210 CU_ASSERT(g_bserrno == 0);
2211 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0);
2212
2213 spdk_blob_close(blob, blob_op_complete, NULL);
2214 CU_ASSERT(g_bserrno == 0);
2215
2216 spdk_bs_free_io_channel(channel);
2217 poll_threads();
2218
2219 /* Unload the blob store */
2220 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2221 poll_threads();
2222 CU_ASSERT(g_bserrno == 0);
2223 g_bs = NULL;
2224 g_blob = NULL;
2225 g_blobid = 0;
2226
2227 free(payload_read);
2228 free(payload_write);
2229 free(payload_pattern);
2230 }
2231
2232 static void
2233 blob_unmap(void)
2234 {
2235 struct spdk_blob_store *bs;
2236 struct spdk_bs_dev *dev;
2237 struct spdk_blob *blob;
2238 struct spdk_io_channel *channel;
2239 spdk_blob_id blobid;
2240 struct spdk_blob_opts opts;
2241 uint8_t payload[4096];
2242 int i;
2243
2244 dev = init_dev();
2245
2246 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
2247 poll_threads();
2248 CU_ASSERT(g_bserrno == 0);
2249 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2250 bs = g_bs;
2251
2252 channel = spdk_bs_alloc_io_channel(bs);
2253 CU_ASSERT(channel != NULL);
2254
2255 spdk_blob_opts_init(&opts);
2256 opts.num_clusters = 10;
2257
2258 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
2259 poll_threads();
2260 CU_ASSERT(g_bserrno == 0);
2261 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2262 blobid = g_blobid;
2263
2264 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
2265 poll_threads();
2266 CU_ASSERT(g_bserrno == 0);
2267 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2268 blob = g_blob;
2269
2270 spdk_blob_resize(blob, 10, blob_op_complete, NULL);
2271 poll_threads();
2272 CU_ASSERT(g_bserrno == 0);
2273
2274 memset(payload, 0, sizeof(payload));
2275 payload[0] = 0xFF;
2276
2277 /*
2278 * Set first byte of every cluster to 0xFF.
2279 * First cluster on device is reserved so let's start from cluster number 1
2280 */
2281 for (i = 1; i < 11; i++) {
2282 g_dev_buffer[i * SPDK_BLOB_OPTS_CLUSTER_SZ] = 0xFF;
2283 }
2284
2285 /* Confirm writes */
2286 for (i = 0; i < 10; i++) {
2287 payload[0] = 0;
2288 spdk_blob_io_read(blob, channel, &payload, i * SPDK_BLOB_OPTS_CLUSTER_SZ / 4096, 1,
2289 blob_op_complete, NULL);
2290 poll_threads();
2291 CU_ASSERT(g_bserrno == 0);
2292 CU_ASSERT(payload[0] == 0xFF);
2293 }
2294
2295 /* Mark some clusters as unallocated */
2296 blob->active.clusters[1] = 0;
2297 blob->active.clusters[2] = 0;
2298 blob->active.clusters[3] = 0;
2299 blob->active.clusters[6] = 0;
2300 blob->active.clusters[8] = 0;
2301
2302 /* Unmap clusters by resizing to 0 */
2303 spdk_blob_resize(blob, 0, blob_op_complete, NULL);
2304 poll_threads();
2305 CU_ASSERT(g_bserrno == 0);
2306
2307 spdk_blob_sync_md(blob, blob_op_complete, NULL);
2308 poll_threads();
2309 CU_ASSERT(g_bserrno == 0);
2310
2311 /* Confirm that only 'allocated' clusters were unmapped */
2312 for (i = 1; i < 11; i++) {
2313 switch (i) {
2314 case 2:
2315 case 3:
2316 case 4:
2317 case 7:
2318 case 9:
2319 CU_ASSERT(g_dev_buffer[i * SPDK_BLOB_OPTS_CLUSTER_SZ] == 0xFF);
2320 break;
2321 default:
2322 CU_ASSERT(g_dev_buffer[i * SPDK_BLOB_OPTS_CLUSTER_SZ] == 0);
2323 break;
2324 }
2325 }
2326
2327 spdk_blob_close(blob, blob_op_complete, NULL);
2328 poll_threads();
2329 CU_ASSERT(g_bserrno == 0);
2330
2331 spdk_bs_free_io_channel(channel);
2332 poll_threads();
2333
2334 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2335 poll_threads();
2336 CU_ASSERT(g_bserrno == 0);
2337 g_bs = NULL;
2338 }
2339
2340
2341 static void
2342 blob_iter(void)
2343 {
2344 struct spdk_blob_store *bs;
2345 struct spdk_bs_dev *dev;
2346 struct spdk_blob *blob;
2347 spdk_blob_id blobid;
2348
2349 dev = init_dev();
2350
2351 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
2352 poll_threads();
2353 CU_ASSERT(g_bserrno == 0);
2354 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2355 bs = g_bs;
2356
2357 spdk_bs_iter_first(bs, blob_op_with_handle_complete, NULL);
2358 poll_threads();
2359 CU_ASSERT(g_blob == NULL);
2360 CU_ASSERT(g_bserrno == -ENOENT);
2361
2362 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
2363 poll_threads();
2364 CU_ASSERT(g_bserrno == 0);
2365 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2366 blobid = g_blobid;
2367
2368 spdk_bs_iter_first(bs, blob_op_with_handle_complete, NULL);
2369 poll_threads();
2370 CU_ASSERT(g_blob != NULL);
2371 CU_ASSERT(g_bserrno == 0);
2372 blob = g_blob;
2373 CU_ASSERT(spdk_blob_get_id(blob) == blobid);
2374
2375 spdk_bs_iter_next(bs, blob, blob_op_with_handle_complete, NULL);
2376 poll_threads();
2377 CU_ASSERT(g_blob == NULL);
2378 CU_ASSERT(g_bserrno == -ENOENT);
2379
2380 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2381 poll_threads();
2382 CU_ASSERT(g_bserrno == 0);
2383 g_bs = NULL;
2384 }
2385
2386 static void
2387 blob_xattr(void)
2388 {
2389 struct spdk_blob_store *bs;
2390 struct spdk_bs_dev *dev;
2391 struct spdk_blob *blob;
2392 spdk_blob_id blobid;
2393 uint64_t length;
2394 int rc;
2395 const char *name1, *name2;
2396 const void *value;
2397 size_t value_len;
2398 struct spdk_xattr_names *names;
2399
2400 dev = init_dev();
2401
2402 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
2403 poll_threads();
2404 CU_ASSERT(g_bserrno == 0);
2405 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2406 bs = g_bs;
2407
2408 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
2409 poll_threads();
2410 CU_ASSERT(g_bserrno == 0);
2411 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2412 blobid = g_blobid;
2413
2414 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
2415 poll_threads();
2416 CU_ASSERT(g_bserrno == 0);
2417 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2418 blob = g_blob;
2419
2420 /* Test that set_xattr fails if md_ro flag is set. */
2421 blob->md_ro = true;
2422 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
2423 CU_ASSERT(rc == -EPERM);
2424
2425 blob->md_ro = false;
2426 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
2427 CU_ASSERT(rc == 0);
2428
2429 length = 2345;
2430 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length));
2431 CU_ASSERT(rc == 0);
2432
2433 /* Overwrite "length" xattr. */
2434 length = 3456;
2435 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length));
2436 CU_ASSERT(rc == 0);
2437
2438 /* get_xattr should still work even if md_ro flag is set. */
2439 value = NULL;
2440 blob->md_ro = true;
2441 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len);
2442 CU_ASSERT(rc == 0);
2443 SPDK_CU_ASSERT_FATAL(value != NULL);
2444 CU_ASSERT(*(uint64_t *)value == length);
2445 CU_ASSERT(value_len == 8);
2446 blob->md_ro = false;
2447
2448 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len);
2449 CU_ASSERT(rc == -ENOENT);
2450
2451 names = NULL;
2452 rc = spdk_blob_get_xattr_names(blob, &names);
2453 CU_ASSERT(rc == 0);
2454 SPDK_CU_ASSERT_FATAL(names != NULL);
2455 CU_ASSERT(spdk_xattr_names_get_count(names) == 2);
2456 name1 = spdk_xattr_names_get_name(names, 0);
2457 SPDK_CU_ASSERT_FATAL(name1 != NULL);
2458 CU_ASSERT(!strcmp(name1, "name") || !strcmp(name1, "length"));
2459 name2 = spdk_xattr_names_get_name(names, 1);
2460 SPDK_CU_ASSERT_FATAL(name2 != NULL);
2461 CU_ASSERT(!strcmp(name2, "name") || !strcmp(name2, "length"));
2462 CU_ASSERT(strcmp(name1, name2));
2463 spdk_xattr_names_free(names);
2464
2465 /* Confirm that remove_xattr fails if md_ro is set to true. */
2466 blob->md_ro = true;
2467 rc = spdk_blob_remove_xattr(blob, "name");
2468 CU_ASSERT(rc == -EPERM);
2469
2470 blob->md_ro = false;
2471 rc = spdk_blob_remove_xattr(blob, "name");
2472 CU_ASSERT(rc == 0);
2473
2474 rc = spdk_blob_remove_xattr(blob, "foobar");
2475 CU_ASSERT(rc == -ENOENT);
2476
2477 /* Set internal xattr */
2478 length = 7898;
2479 rc = _spdk_blob_set_xattr(blob, "internal", &length, sizeof(length), true);
2480 CU_ASSERT(rc == 0);
2481 rc = _spdk_blob_get_xattr_value(blob, "internal", &value, &value_len, true);
2482 CU_ASSERT(rc == 0);
2483 CU_ASSERT(*(uint64_t *)value == length);
2484 /* try to get public xattr with same name */
2485 rc = spdk_blob_get_xattr_value(blob, "internal", &value, &value_len);
2486 CU_ASSERT(rc != 0);
2487 rc = _spdk_blob_get_xattr_value(blob, "internal", &value, &value_len, false);
2488 CU_ASSERT(rc != 0);
2489 /* Check if SPDK_BLOB_INTERNAL_XATTR is set */
2490 CU_ASSERT((blob->invalid_flags & SPDK_BLOB_INTERNAL_XATTR) ==
2491 SPDK_BLOB_INTERNAL_XATTR)
2492
2493 spdk_blob_close(blob, blob_op_complete, NULL);
2494 poll_threads();
2495
2496 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2497 poll_threads();
2498
2499 /* Check if xattrs are persisted */
2500 dev = init_dev();
2501
2502 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
2503 poll_threads();
2504 CU_ASSERT(g_bserrno == 0);
2505 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2506
2507 bs = g_bs;
2508
2509 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
2510 poll_threads();
2511 CU_ASSERT(g_bserrno == 0);
2512 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2513 blob = g_blob;
2514
2515 rc = _spdk_blob_get_xattr_value(blob, "internal", &value, &value_len, true);
2516 CU_ASSERT(rc == 0);
2517 CU_ASSERT(*(uint64_t *)value == length);
2518
2519 /* try to get internal xattr trough public call */
2520 rc = spdk_blob_get_xattr_value(blob, "internal", &value, &value_len);
2521 CU_ASSERT(rc != 0);
2522
2523 rc = _spdk_blob_remove_xattr(blob, "internal", true);
2524 CU_ASSERT(rc == 0);
2525
2526 CU_ASSERT((blob->invalid_flags & SPDK_BLOB_INTERNAL_XATTR) == 0);
2527
2528 CU_ASSERT(g_bserrno == 0);
2529 g_bs = NULL;
2530 }
2531
2532 static void
2533 bs_load(void)
2534 {
2535 struct spdk_bs_dev *dev;
2536 spdk_blob_id blobid;
2537 struct spdk_blob *blob;
2538 struct spdk_bs_super_block *super_block;
2539 uint64_t length;
2540 int rc;
2541 const void *value;
2542 size_t value_len;
2543 struct spdk_bs_opts opts;
2544
2545 dev = init_dev();
2546 spdk_bs_opts_init(&opts);
2547 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2548
2549 /* Initialize a new blob store */
2550 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
2551 poll_threads();
2552 CU_ASSERT(g_bserrno == 0);
2553 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2554
2555 /* Try to open a blobid that does not exist */
2556 spdk_bs_open_blob(g_bs, 0, blob_op_with_handle_complete, NULL);
2557 poll_threads();
2558 CU_ASSERT(g_bserrno == -ENOENT);
2559 CU_ASSERT(g_blob == NULL);
2560
2561 /* Create a blob */
2562 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
2563 poll_threads();
2564 CU_ASSERT(g_bserrno == 0);
2565 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2566 blobid = g_blobid;
2567
2568 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
2569 poll_threads();
2570 CU_ASSERT(g_bserrno == 0);
2571 CU_ASSERT(g_blob != NULL);
2572 blob = g_blob;
2573
2574 /* Try again to open valid blob but without the upper bit set */
2575 spdk_bs_open_blob(g_bs, blobid & 0xFFFFFFFF, blob_op_with_handle_complete, NULL);
2576 poll_threads();
2577 CU_ASSERT(g_bserrno == -ENOENT);
2578 CU_ASSERT(g_blob == NULL);
2579
2580 /* Set some xattrs */
2581 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
2582 CU_ASSERT(rc == 0);
2583
2584 length = 2345;
2585 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length));
2586 CU_ASSERT(rc == 0);
2587
2588 /* Resize the blob */
2589 spdk_blob_resize(blob, 10, blob_op_complete, NULL);
2590 poll_threads();
2591 CU_ASSERT(g_bserrno == 0);
2592
2593 spdk_blob_close(blob, blob_op_complete, NULL);
2594 poll_threads();
2595 CU_ASSERT(g_bserrno == 0);
2596 blob = NULL;
2597 g_blob = NULL;
2598 g_blobid = SPDK_BLOBID_INVALID;
2599
2600 /* Unload the blob store */
2601 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2602 poll_threads();
2603 CU_ASSERT(g_bserrno == 0);
2604 g_bs = NULL;
2605 g_blob = NULL;
2606 g_blobid = 0;
2607
2608 super_block = (struct spdk_bs_super_block *)g_dev_buffer;
2609 CU_ASSERT(super_block->clean == 1);
2610
2611 /* Load should fail for device with an unsupported blocklen */
2612 dev = init_dev();
2613 dev->blocklen = SPDK_BS_PAGE_SIZE * 2;
2614 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
2615 poll_threads();
2616 CU_ASSERT(g_bserrno == -EINVAL);
2617
2618 /* Load should when max_md_ops is set to zero */
2619 dev = init_dev();
2620 spdk_bs_opts_init(&opts);
2621 opts.max_md_ops = 0;
2622 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2623 poll_threads();
2624 CU_ASSERT(g_bserrno == -EINVAL);
2625
2626 /* Load should when max_channel_ops is set to zero */
2627 dev = init_dev();
2628 spdk_bs_opts_init(&opts);
2629 opts.max_channel_ops = 0;
2630 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2631 poll_threads();
2632 CU_ASSERT(g_bserrno == -EINVAL);
2633
2634 /* Load an existing blob store */
2635 dev = init_dev();
2636 spdk_bs_opts_init(&opts);
2637 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2638 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2639 poll_threads();
2640 CU_ASSERT(g_bserrno == 0);
2641 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2642
2643 super_block = (struct spdk_bs_super_block *)g_dev_buffer;
2644 CU_ASSERT(super_block->clean == 1);
2645 CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen);
2646
2647 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
2648 poll_threads();
2649 CU_ASSERT(g_bserrno == 0);
2650 CU_ASSERT(g_blob != NULL);
2651 blob = g_blob;
2652
2653 /* Verify that blobstore is marked dirty after first metadata sync */
2654 spdk_blob_sync_md(blob, blob_op_complete, NULL);
2655 CU_ASSERT(super_block->clean == 1);
2656
2657 /* Get the xattrs */
2658 value = NULL;
2659 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len);
2660 CU_ASSERT(rc == 0);
2661 SPDK_CU_ASSERT_FATAL(value != NULL);
2662 CU_ASSERT(*(uint64_t *)value == length);
2663 CU_ASSERT(value_len == 8);
2664
2665 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len);
2666 CU_ASSERT(rc == -ENOENT);
2667
2668 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10);
2669
2670 spdk_blob_close(blob, blob_op_complete, NULL);
2671 poll_threads();
2672 CU_ASSERT(g_bserrno == 0);
2673 blob = NULL;
2674 g_blob = NULL;
2675
2676 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2677 poll_threads();
2678 CU_ASSERT(g_bserrno == 0);
2679 g_bs = NULL;
2680
2681 /* Load should fail: bdev size < saved size */
2682 dev = init_dev();
2683 dev->blockcnt /= 2;
2684
2685 spdk_bs_opts_init(&opts);
2686 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2687 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2688 poll_threads();
2689
2690 CU_ASSERT(g_bserrno == -EILSEQ);
2691
2692 /* Load should succeed: bdev size > saved size */
2693 dev = init_dev();
2694 dev->blockcnt *= 4;
2695
2696 spdk_bs_opts_init(&opts);
2697 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2698 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2699 poll_threads();
2700
2701 CU_ASSERT(g_bserrno == 0);
2702 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2703 poll_threads();
2704
2705
2706 /* Test compatibility mode */
2707
2708 dev = init_dev();
2709 super_block->size = 0;
2710 super_block->crc = _spdk_blob_md_page_calc_crc(super_block);
2711
2712 spdk_bs_opts_init(&opts);
2713 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2714 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2715 poll_threads();
2716 CU_ASSERT(g_bserrno == 0);
2717 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2718
2719 /* Create a blob */
2720 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
2721 poll_threads();
2722 CU_ASSERT(g_bserrno == 0);
2723 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2724
2725 /* Blobstore should update number of blocks in super_block */
2726 CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen);
2727 CU_ASSERT(super_block->clean == 0);
2728
2729 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2730 poll_threads();
2731 CU_ASSERT(g_bserrno == 0);
2732 CU_ASSERT(super_block->clean == 1);
2733 g_bs = NULL;
2734
2735 }
2736
2737 static void
2738 bs_load_pending_removal(void)
2739 {
2740 struct spdk_blob_store *bs;
2741 struct spdk_bs_dev *dev;
2742 struct spdk_blob_opts opts;
2743 struct spdk_blob *blob, *snapshot;
2744 spdk_blob_id blobid, snapshotid;
2745 const void *value;
2746 size_t value_len;
2747 int rc;
2748
2749 dev = init_dev();
2750
2751 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
2752 poll_threads();
2753 CU_ASSERT(g_bserrno == 0);
2754 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2755 bs = g_bs;
2756
2757 /* Create blob */
2758 spdk_blob_opts_init(&opts);
2759 opts.num_clusters = 10;
2760
2761 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
2762 poll_threads();
2763 CU_ASSERT(g_bserrno == 0);
2764 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2765 blobid = g_blobid;
2766
2767 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
2768 poll_threads();
2769 CU_ASSERT(g_bserrno == 0);
2770 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2771 blob = g_blob;
2772
2773 /* Create snapshot */
2774 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
2775 poll_threads();
2776 CU_ASSERT(g_bserrno == 0);
2777 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
2778 snapshotid = g_blobid;
2779
2780 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
2781 poll_threads();
2782 CU_ASSERT(g_bserrno == 0);
2783 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2784 snapshot = g_blob;
2785
2786 /* Set SNAPSHOT_PENDING_REMOVAL xattr */
2787 snapshot->md_ro = false;
2788 rc = _spdk_blob_set_xattr(snapshot, SNAPSHOT_PENDING_REMOVAL, &blobid, sizeof(spdk_blob_id), true);
2789 CU_ASSERT(rc == 0);
2790 snapshot->md_ro = true;
2791
2792 spdk_blob_close(snapshot, blob_op_complete, NULL);
2793 poll_threads();
2794 CU_ASSERT(g_bserrno == 0);
2795
2796 spdk_blob_close(blob, blob_op_complete, NULL);
2797 poll_threads();
2798 CU_ASSERT(g_bserrno == 0);
2799
2800 /* Reload blobstore */
2801 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2802 poll_threads();
2803 CU_ASSERT(g_bserrno == 0);
2804 g_bs = NULL;
2805
2806 dev = init_dev();
2807 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
2808 poll_threads();
2809 CU_ASSERT(g_bserrno == 0);
2810 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2811 bs = g_bs;
2812
2813 /* Snapshot should not be removed as blob is still pointing to it */
2814 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
2815 poll_threads();
2816 CU_ASSERT(g_bserrno == 0);
2817 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2818 snapshot = g_blob;
2819
2820 /* SNAPSHOT_PENDING_REMOVAL xattr should be removed during load */
2821 rc = spdk_blob_get_xattr_value(snapshot, SNAPSHOT_PENDING_REMOVAL, &value, &value_len);
2822 CU_ASSERT(rc != 0);
2823
2824 /* Set SNAPSHOT_PENDING_REMOVAL xattr again */
2825 snapshot->md_ro = false;
2826 rc = _spdk_blob_set_xattr(snapshot, SNAPSHOT_PENDING_REMOVAL, &blobid, sizeof(spdk_blob_id), true);
2827 CU_ASSERT(rc == 0);
2828 snapshot->md_ro = true;
2829
2830 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
2831 poll_threads();
2832 CU_ASSERT(g_bserrno == 0);
2833 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
2834 blob = g_blob;
2835
2836 /* Remove parent_id from blob by removing BLOB_SNAPSHOT xattr */
2837 _spdk_blob_remove_xattr(blob, BLOB_SNAPSHOT, true);
2838
2839 spdk_blob_sync_md(blob, blob_op_complete, NULL);
2840 poll_threads();
2841 CU_ASSERT(g_bserrno == 0);
2842
2843 spdk_blob_close(snapshot, blob_op_complete, NULL);
2844 poll_threads();
2845 CU_ASSERT(g_bserrno == 0);
2846
2847 spdk_blob_close(blob, blob_op_complete, NULL);
2848 poll_threads();
2849 CU_ASSERT(g_bserrno == 0);
2850
2851 /* Reload blobstore */
2852 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2853 poll_threads();
2854 CU_ASSERT(g_bserrno == 0);
2855 g_bs = NULL;
2856
2857 dev = init_dev();
2858 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
2859 poll_threads();
2860 CU_ASSERT(g_bserrno == 0);
2861 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2862 bs = g_bs;
2863
2864 /* Snapshot should be removed as blob is not pointing to it anymore */
2865 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
2866 poll_threads();
2867 CU_ASSERT(g_bserrno != 0);
2868
2869 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2870 poll_threads();
2871 CU_ASSERT(g_bserrno == 0);
2872 g_bs = NULL;
2873 }
2874
2875 static void
2876 bs_load_custom_cluster_size(void)
2877 {
2878 struct spdk_bs_dev *dev;
2879 struct spdk_bs_super_block *super_block;
2880 struct spdk_bs_opts opts;
2881 uint32_t custom_cluster_size = 4194304; /* 4MiB */
2882 uint32_t cluster_sz;
2883 uint64_t total_clusters;
2884
2885 dev = init_dev();
2886 spdk_bs_opts_init(&opts);
2887 opts.cluster_sz = custom_cluster_size;
2888 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2889
2890 /* Initialize a new blob store */
2891 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
2892 poll_threads();
2893 CU_ASSERT(g_bserrno == 0);
2894 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2895 cluster_sz = g_bs->cluster_sz;
2896 total_clusters = g_bs->total_clusters;
2897
2898 /* Unload the blob store */
2899 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2900 poll_threads();
2901 CU_ASSERT(g_bserrno == 0);
2902 g_bs = NULL;
2903 g_blob = NULL;
2904 g_blobid = 0;
2905
2906 super_block = (struct spdk_bs_super_block *)g_dev_buffer;
2907 CU_ASSERT(super_block->clean == 1);
2908
2909 /* Load an existing blob store */
2910 dev = init_dev();
2911 spdk_bs_opts_init(&opts);
2912 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2913 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2914 poll_threads();
2915 CU_ASSERT(g_bserrno == 0);
2916 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2917 /* Compare cluster size and number to one after initialization */
2918 CU_ASSERT(cluster_sz == g_bs->cluster_sz);
2919 CU_ASSERT(total_clusters == g_bs->total_clusters);
2920
2921 super_block = (struct spdk_bs_super_block *)g_dev_buffer;
2922 CU_ASSERT(super_block->clean == 1);
2923 CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen);
2924
2925 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2926 poll_threads();
2927 CU_ASSERT(g_bserrno == 0);
2928 CU_ASSERT(super_block->clean == 1);
2929 g_bs = NULL;
2930 }
2931
2932 static void
2933 bs_type(void)
2934 {
2935 struct spdk_bs_dev *dev;
2936 struct spdk_bs_opts opts;
2937
2938 dev = init_dev();
2939 spdk_bs_opts_init(&opts);
2940 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
2941
2942 /* Initialize a new blob store */
2943 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
2944 poll_threads();
2945 CU_ASSERT(g_bserrno == 0);
2946 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2947
2948 /* Unload the blob store */
2949 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2950 poll_threads();
2951 CU_ASSERT(g_bserrno == 0);
2952 g_bs = NULL;
2953 g_blob = NULL;
2954 g_blobid = 0;
2955
2956 /* Load non existing blobstore type */
2957 dev = init_dev();
2958 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "NONEXISTING");
2959 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2960 poll_threads();
2961 CU_ASSERT(g_bserrno != 0);
2962
2963 /* Load with empty blobstore type */
2964 dev = init_dev();
2965 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype));
2966 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2967 poll_threads();
2968 CU_ASSERT(g_bserrno == 0);
2969
2970 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2971 poll_threads();
2972 CU_ASSERT(g_bserrno == 0);
2973 g_bs = NULL;
2974
2975 /* Initialize a new blob store with empty bstype */
2976 dev = init_dev();
2977 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype));
2978 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
2979 poll_threads();
2980 CU_ASSERT(g_bserrno == 0);
2981 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
2982
2983 spdk_bs_unload(g_bs, bs_op_complete, NULL);
2984 poll_threads();
2985 CU_ASSERT(g_bserrno == 0);
2986 g_bs = NULL;
2987
2988 /* Load non existing blobstore type */
2989 dev = init_dev();
2990 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "NONEXISTING");
2991 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2992 poll_threads();
2993 CU_ASSERT(g_bserrno != 0);
2994
2995 /* Load with empty blobstore type */
2996 dev = init_dev();
2997 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype));
2998 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
2999 poll_threads();
3000 CU_ASSERT(g_bserrno == 0);
3001
3002 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3003 poll_threads();
3004 CU_ASSERT(g_bserrno == 0);
3005 g_bs = NULL;
3006 }
3007
3008 static void
3009 bs_super_block(void)
3010 {
3011 struct spdk_bs_dev *dev;
3012 struct spdk_bs_super_block *super_block;
3013 struct spdk_bs_opts opts;
3014 struct spdk_bs_super_block_ver1 super_block_v1;
3015
3016 dev = init_dev();
3017 spdk_bs_opts_init(&opts);
3018 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
3019
3020 /* Initialize a new blob store */
3021 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3022 poll_threads();
3023 CU_ASSERT(g_bserrno == 0);
3024 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3025
3026 /* Unload the blob store */
3027 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3028 poll_threads();
3029 CU_ASSERT(g_bserrno == 0);
3030 g_bs = NULL;
3031 g_blob = NULL;
3032 g_blobid = 0;
3033
3034 /* Load an existing blob store with version newer than supported */
3035 super_block = (struct spdk_bs_super_block *)g_dev_buffer;
3036 super_block->version++;
3037
3038 dev = init_dev();
3039 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype));
3040 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3041 poll_threads();
3042 CU_ASSERT(g_bserrno != 0);
3043
3044 /* Create a new blob store with super block version 1 */
3045 dev = init_dev();
3046 super_block_v1.version = 1;
3047 memcpy(super_block_v1.signature, "SPDKBLOB", sizeof(super_block_v1.signature));
3048 super_block_v1.length = 0x1000;
3049 super_block_v1.clean = 1;
3050 super_block_v1.super_blob = 0xFFFFFFFFFFFFFFFF;
3051 super_block_v1.cluster_size = 0x100000;
3052 super_block_v1.used_page_mask_start = 0x01;
3053 super_block_v1.used_page_mask_len = 0x01;
3054 super_block_v1.used_cluster_mask_start = 0x02;
3055 super_block_v1.used_cluster_mask_len = 0x01;
3056 super_block_v1.md_start = 0x03;
3057 super_block_v1.md_len = 0x40;
3058 memset(super_block_v1.reserved, 0, 4036);
3059 super_block_v1.crc = _spdk_blob_md_page_calc_crc(&super_block_v1);
3060 memcpy(g_dev_buffer, &super_block_v1, sizeof(struct spdk_bs_super_block_ver1));
3061
3062 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype));
3063 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3064 poll_threads();
3065 CU_ASSERT(g_bserrno == 0);
3066
3067 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3068 poll_threads();
3069 CU_ASSERT(g_bserrno == 0);
3070 g_bs = NULL;
3071 }
3072
3073 /*
3074 * Create a blobstore and then unload it.
3075 */
3076 static void
3077 bs_unload(void)
3078 {
3079 struct spdk_bs_dev *dev;
3080 struct spdk_blob_store *bs;
3081 spdk_blob_id blobid;
3082 struct spdk_blob *blob;
3083
3084 dev = init_dev();
3085
3086 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
3087 poll_threads();
3088 CU_ASSERT(g_bserrno == 0);
3089 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3090 bs = g_bs;
3091
3092 /* Create a blob and open it. */
3093 g_bserrno = -1;
3094 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
3095 poll_threads();
3096 CU_ASSERT(g_bserrno == 0);
3097 CU_ASSERT(g_blobid > 0);
3098 blobid = g_blobid;
3099
3100 g_bserrno = -1;
3101 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
3102 poll_threads();
3103 CU_ASSERT(g_bserrno == 0);
3104 CU_ASSERT(g_blob != NULL);
3105 blob = g_blob;
3106
3107 /* Try to unload blobstore, should fail with open blob */
3108 g_bserrno = -1;
3109 spdk_bs_unload(bs, bs_op_complete, NULL);
3110 poll_threads();
3111 CU_ASSERT(g_bserrno == -EBUSY);
3112 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3113
3114 /* Close the blob, then successfully unload blobstore */
3115 g_bserrno = -1;
3116 spdk_blob_close(blob, blob_op_complete, NULL);
3117 poll_threads();
3118 CU_ASSERT(g_bserrno == 0);
3119
3120 g_bserrno = -1;
3121 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3122 poll_threads();
3123 CU_ASSERT(g_bserrno == 0);
3124 g_bs = NULL;
3125 }
3126
3127 /*
3128 * Create a blobstore with a cluster size different than the default, and ensure it is
3129 * persisted.
3130 */
3131 static void
3132 bs_cluster_sz(void)
3133 {
3134 struct spdk_bs_dev *dev;
3135 struct spdk_bs_opts opts;
3136 uint32_t cluster_sz;
3137
3138 /* Set cluster size to zero */
3139 dev = init_dev();
3140 spdk_bs_opts_init(&opts);
3141 opts.cluster_sz = 0;
3142
3143 /* Initialize a new blob store */
3144 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3145 poll_threads();
3146 CU_ASSERT(g_bserrno == -EINVAL);
3147 SPDK_CU_ASSERT_FATAL(g_bs == NULL);
3148
3149 /*
3150 * Set cluster size to blobstore page size,
3151 * to work it is required to be at least twice the blobstore page size.
3152 */
3153 dev = init_dev();
3154 spdk_bs_opts_init(&opts);
3155 opts.cluster_sz = SPDK_BS_PAGE_SIZE;
3156
3157 /* Initialize a new blob store */
3158 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3159 poll_threads();
3160 CU_ASSERT(g_bserrno == -ENOMEM);
3161 SPDK_CU_ASSERT_FATAL(g_bs == NULL);
3162
3163 /*
3164 * Set cluster size to lower than page size,
3165 * to work it is required to be at least twice the blobstore page size.
3166 */
3167 dev = init_dev();
3168 spdk_bs_opts_init(&opts);
3169 opts.cluster_sz = SPDK_BS_PAGE_SIZE - 1;
3170
3171 /* Initialize a new blob store */
3172 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3173 poll_threads();
3174 CU_ASSERT(g_bserrno == -EINVAL);
3175 SPDK_CU_ASSERT_FATAL(g_bs == NULL);
3176
3177 /* Set cluster size to twice the default */
3178 dev = init_dev();
3179 spdk_bs_opts_init(&opts);
3180 opts.cluster_sz *= 2;
3181 cluster_sz = opts.cluster_sz;
3182
3183 /* Initialize a new blob store */
3184 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3185 poll_threads();
3186 CU_ASSERT(g_bserrno == 0);
3187 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3188
3189 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
3190
3191 /* Unload the blob store */
3192 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3193 poll_threads();
3194 CU_ASSERT(g_bserrno == 0);
3195 g_bs = NULL;
3196 g_blob = NULL;
3197 g_blobid = 0;
3198
3199 dev = init_dev();
3200 /* Load an existing blob store */
3201 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3202 poll_threads();
3203 CU_ASSERT(g_bserrno == 0);
3204 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3205
3206 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
3207
3208 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3209 poll_threads();
3210 CU_ASSERT(g_bserrno == 0);
3211 g_bs = NULL;
3212 }
3213
3214 /*
3215 * Create a blobstore, reload it and ensure total usable cluster count
3216 * stays the same.
3217 */
3218 static void
3219 bs_usable_clusters(void)
3220 {
3221 struct spdk_bs_dev *dev;
3222 struct spdk_bs_opts opts;
3223 uint32_t clusters;
3224 int i;
3225
3226 /* Init blobstore */
3227 dev = init_dev();
3228 spdk_bs_opts_init(&opts);
3229
3230 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3231 poll_threads();
3232 CU_ASSERT(g_bserrno == 0);
3233 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3234
3235 clusters = spdk_bs_total_data_cluster_count(g_bs);
3236
3237 /* Unload the blob store */
3238 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3239 poll_threads();
3240 CU_ASSERT(g_bserrno == 0);
3241 g_bs = NULL;
3242
3243 dev = init_dev();
3244 /* Load an existing blob store */
3245 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3246 poll_threads();
3247 CU_ASSERT(g_bserrno == 0);
3248 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3249
3250 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs) == clusters);
3251
3252 /* Create and resize blobs to make sure that useable cluster count won't change */
3253 for (i = 0; i < 4; i++) {
3254 g_bserrno = -1;
3255 g_blobid = SPDK_BLOBID_INVALID;
3256 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3257 poll_threads();
3258 CU_ASSERT(g_bserrno == 0);
3259 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3260
3261 g_bserrno = -1;
3262 g_blob = NULL;
3263 spdk_bs_open_blob(g_bs, g_blobid, blob_op_with_handle_complete, NULL);
3264 poll_threads();
3265 CU_ASSERT(g_bserrno == 0);
3266 CU_ASSERT(g_blob != NULL);
3267
3268 spdk_blob_resize(g_blob, 10, blob_op_complete, NULL);
3269 poll_threads();
3270 CU_ASSERT(g_bserrno == 0);
3271
3272 g_bserrno = -1;
3273 spdk_blob_close(g_blob, blob_op_complete, NULL);
3274 poll_threads();
3275 CU_ASSERT(g_bserrno == 0);
3276
3277 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs) == clusters);
3278 }
3279
3280 /* Reload the blob store to make sure that nothing changed */
3281 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3282 poll_threads();
3283 CU_ASSERT(g_bserrno == 0);
3284 g_bs = NULL;
3285
3286 dev = init_dev();
3287 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3288 poll_threads();
3289 CU_ASSERT(g_bserrno == 0);
3290 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3291
3292 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs) == clusters);
3293
3294 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3295 poll_threads();
3296 CU_ASSERT(g_bserrno == 0);
3297 g_bs = NULL;
3298 }
3299
3300 /*
3301 * Test resizing of the metadata blob. This requires creating enough blobs
3302 * so that one cluster is not enough to fit the metadata for those blobs.
3303 * To induce this condition to happen more quickly, we reduce the cluster
3304 * size to 16KB, which means only 4 4KB blob metadata pages can fit.
3305 */
3306 static void
3307 bs_resize_md(void)
3308 {
3309 const int CLUSTER_PAGE_COUNT = 4;
3310 const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4;
3311 struct spdk_bs_dev *dev;
3312 struct spdk_bs_opts opts;
3313 uint32_t cluster_sz;
3314 spdk_blob_id blobids[NUM_BLOBS];
3315 int i;
3316
3317
3318 dev = init_dev();
3319 spdk_bs_opts_init(&opts);
3320 opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096;
3321 cluster_sz = opts.cluster_sz;
3322
3323 /* Initialize a new blob store */
3324 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3325 poll_threads();
3326 CU_ASSERT(g_bserrno == 0);
3327 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3328
3329 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
3330
3331 for (i = 0; i < NUM_BLOBS; i++) {
3332 g_bserrno = -1;
3333 g_blobid = SPDK_BLOBID_INVALID;
3334 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3335 poll_threads();
3336 CU_ASSERT(g_bserrno == 0);
3337 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3338 blobids[i] = g_blobid;
3339 }
3340
3341 /* Unload the blob store */
3342 g_bserrno = -1;
3343 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3344 poll_threads();
3345 CU_ASSERT(g_bserrno == 0);
3346
3347 /* Load an existing blob store */
3348 g_bserrno = -1;
3349 g_bs = NULL;
3350 dev = init_dev();
3351 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3352 poll_threads();
3353 CU_ASSERT(g_bserrno == 0);
3354 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3355
3356 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
3357
3358 for (i = 0; i < NUM_BLOBS; i++) {
3359 g_bserrno = -1;
3360 g_blob = NULL;
3361 spdk_bs_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL);
3362 poll_threads();
3363 CU_ASSERT(g_bserrno == 0);
3364 CU_ASSERT(g_blob != NULL);
3365 g_bserrno = -1;
3366 spdk_blob_close(g_blob, blob_op_complete, NULL);
3367 poll_threads();
3368 CU_ASSERT(g_bserrno == 0);
3369 }
3370
3371 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3372 poll_threads();
3373 CU_ASSERT(g_bserrno == 0);
3374 g_bs = NULL;
3375 }
3376
3377 static void
3378 bs_destroy(void)
3379 {
3380 struct spdk_bs_dev *dev;
3381 struct spdk_bs_opts opts;
3382
3383 /* Initialize a new blob store */
3384 dev = init_dev();
3385 spdk_bs_opts_init(&opts);
3386 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3387 poll_threads();
3388 CU_ASSERT(g_bserrno == 0);
3389 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3390
3391 /* Destroy the blob store */
3392 g_bserrno = -1;
3393 spdk_bs_destroy(g_bs, bs_op_complete, NULL);
3394 poll_threads();
3395 CU_ASSERT(g_bserrno == 0);
3396
3397 /* Loading an non-existent blob store should fail. */
3398 g_bs = NULL;
3399 dev = init_dev();
3400
3401 g_bserrno = 0;
3402 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3403 poll_threads();
3404 CU_ASSERT(g_bserrno != 0);
3405 }
3406
3407 /* Try to hit all of the corner cases associated with serializing
3408 * a blob to disk
3409 */
3410 static void
3411 blob_serialize(void)
3412 {
3413 struct spdk_bs_dev *dev;
3414 struct spdk_bs_opts opts;
3415 struct spdk_blob_store *bs;
3416 spdk_blob_id blobid[2];
3417 struct spdk_blob *blob[2];
3418 uint64_t i;
3419 char *value;
3420 int rc;
3421
3422 dev = init_dev();
3423
3424 /* Initialize a new blobstore with very small clusters */
3425 spdk_bs_opts_init(&opts);
3426 opts.cluster_sz = dev->blocklen * 8;
3427 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3428 poll_threads();
3429 CU_ASSERT(g_bserrno == 0);
3430 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3431 bs = g_bs;
3432
3433 /* Create and open two blobs */
3434 for (i = 0; i < 2; i++) {
3435 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
3436 poll_threads();
3437 CU_ASSERT(g_bserrno == 0);
3438 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3439 blobid[i] = g_blobid;
3440
3441 /* Open a blob */
3442 spdk_bs_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
3443 poll_threads();
3444 CU_ASSERT(g_bserrno == 0);
3445 CU_ASSERT(g_blob != NULL);
3446 blob[i] = g_blob;
3447
3448 /* Set a fairly large xattr on both blobs to eat up
3449 * metadata space
3450 */
3451 value = calloc(dev->blocklen - 64, sizeof(char));
3452 SPDK_CU_ASSERT_FATAL(value != NULL);
3453 memset(value, i, dev->blocklen / 2);
3454 rc = spdk_blob_set_xattr(blob[i], "name", value, dev->blocklen - 64);
3455 CU_ASSERT(rc == 0);
3456 free(value);
3457 }
3458
3459 /* Resize the blobs, alternating 1 cluster at a time.
3460 * This thwarts run length encoding and will cause spill
3461 * over of the extents.
3462 */
3463 for (i = 0; i < 6; i++) {
3464 spdk_blob_resize(blob[i % 2], (i / 2) + 1, blob_op_complete, NULL);
3465 poll_threads();
3466 CU_ASSERT(g_bserrno == 0);
3467 }
3468
3469 for (i = 0; i < 2; i++) {
3470 spdk_blob_sync_md(blob[i], blob_op_complete, NULL);
3471 poll_threads();
3472 CU_ASSERT(g_bserrno == 0);
3473 }
3474
3475 /* Close the blobs */
3476 for (i = 0; i < 2; i++) {
3477 spdk_blob_close(blob[i], blob_op_complete, NULL);
3478 poll_threads();
3479 CU_ASSERT(g_bserrno == 0);
3480 }
3481
3482 /* Unload the blobstore */
3483 spdk_bs_unload(bs, bs_op_complete, NULL);
3484 poll_threads();
3485 CU_ASSERT(g_bserrno == 0);
3486 g_bs = NULL;
3487 g_blob = NULL;
3488 g_blobid = 0;
3489 bs = NULL;
3490
3491 dev = init_dev();
3492 /* Load an existing blob store */
3493 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3494 poll_threads();
3495 CU_ASSERT(g_bserrno == 0);
3496 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3497 bs = g_bs;
3498
3499 for (i = 0; i < 2; i++) {
3500 blob[i] = NULL;
3501
3502 spdk_bs_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
3503 poll_threads();
3504 CU_ASSERT(g_bserrno == 0);
3505 CU_ASSERT(g_blob != NULL);
3506 blob[i] = g_blob;
3507
3508 CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3);
3509
3510 spdk_blob_close(blob[i], blob_op_complete, NULL);
3511 poll_threads();
3512 CU_ASSERT(g_bserrno == 0);
3513 }
3514
3515 spdk_bs_unload(bs, bs_op_complete, NULL);
3516 poll_threads();
3517 CU_ASSERT(g_bserrno == 0);
3518 g_bs = NULL;
3519 }
3520
3521 static void
3522 blob_crc(void)
3523 {
3524 struct spdk_blob_store *bs;
3525 struct spdk_bs_dev *dev;
3526 struct spdk_blob *blob;
3527 spdk_blob_id blobid;
3528 uint32_t page_num;
3529 int index;
3530 struct spdk_blob_md_page *page;
3531
3532 dev = init_dev();
3533
3534 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
3535 poll_threads();
3536 CU_ASSERT(g_bserrno == 0);
3537 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3538 bs = g_bs;
3539
3540 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL);
3541 poll_threads();
3542 CU_ASSERT(g_bserrno == 0);
3543 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3544 blobid = g_blobid;
3545
3546 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
3547 poll_threads();
3548 CU_ASSERT(g_bserrno == 0);
3549 CU_ASSERT(g_blob != NULL);
3550 blob = g_blob;
3551
3552 spdk_blob_close(blob, blob_op_complete, NULL);
3553 poll_threads();
3554 CU_ASSERT(g_bserrno == 0);
3555
3556 page_num = _spdk_bs_blobid_to_page(blobid);
3557 index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num);
3558 page = (struct spdk_blob_md_page *)&g_dev_buffer[index];
3559 page->crc = 0;
3560
3561 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
3562 poll_threads();
3563 CU_ASSERT(g_bserrno == -EINVAL);
3564 CU_ASSERT(g_blob == NULL);
3565 g_bserrno = 0;
3566
3567 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
3568 poll_threads();
3569 CU_ASSERT(g_bserrno == -EINVAL);
3570
3571 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3572 poll_threads();
3573 CU_ASSERT(g_bserrno == 0);
3574 g_bs = NULL;
3575 }
3576
3577 static void
3578 super_block_crc(void)
3579 {
3580 struct spdk_bs_dev *dev;
3581 struct spdk_bs_super_block *super_block;
3582 struct spdk_bs_opts opts;
3583
3584 dev = init_dev();
3585 spdk_bs_opts_init(&opts);
3586
3587 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
3588 poll_threads();
3589 CU_ASSERT(g_bserrno == 0);
3590 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3591
3592 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3593 poll_threads();
3594 CU_ASSERT(g_bserrno == 0);
3595 g_bs = NULL;
3596
3597 super_block = (struct spdk_bs_super_block *)g_dev_buffer;
3598 super_block->crc = 0;
3599 dev = init_dev();
3600
3601 /* Load an existing blob store */
3602 g_bserrno = 0;
3603 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3604 poll_threads();
3605 CU_ASSERT(g_bserrno == -EILSEQ);
3606 }
3607
3608 /* For blob dirty shutdown test case we do the following sub-test cases:
3609 * 1 Initialize new blob store and create 1 super blob with some xattrs, then we
3610 * dirty shutdown and reload the blob store and verify the xattrs.
3611 * 2 Resize the blob from 10 clusters to 20 clusters and then dirty shutdown,
3612 * reload the blob store and verify the clusters number.
3613 * 3 Create the second blob and then dirty shutdown, reload the blob store
3614 * and verify the second blob.
3615 * 4 Delete the second blob and then dirty shutdown, reload the blob store
3616 * and verify the second blob is invalid.
3617 * 5 Create the second blob again and also create the third blob, modify the
3618 * md of second blob which makes the md invalid, and then dirty shutdown,
3619 * reload the blob store verify the second blob, it should invalid and also
3620 * verify the third blob, it should correct.
3621 */
3622 static void
3623 blob_dirty_shutdown(void)
3624 {
3625 int rc;
3626 int index;
3627 struct spdk_bs_dev *dev;
3628 spdk_blob_id blobid1, blobid2, blobid3;
3629 struct spdk_blob *blob;
3630 uint64_t length;
3631 uint64_t free_clusters;
3632 const void *value;
3633 size_t value_len;
3634 uint32_t page_num;
3635 struct spdk_blob_md_page *page;
3636 struct spdk_bs_opts opts;
3637
3638 dev = init_dev();
3639 spdk_bs_opts_init(&opts);
3640 /* Initialize a new blob store */
3641 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
3642 poll_threads();
3643 CU_ASSERT(g_bserrno == 0);
3644 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3645
3646 /* Create first blob */
3647 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3648 poll_threads();
3649 CU_ASSERT(g_bserrno == 0);
3650 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3651 blobid1 = g_blobid;
3652
3653 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL);
3654 poll_threads();
3655 CU_ASSERT(g_bserrno == 0);
3656 CU_ASSERT(g_blob != NULL);
3657 blob = g_blob;
3658
3659 /* Set some xattrs */
3660 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
3661 CU_ASSERT(rc == 0);
3662
3663 length = 2345;
3664 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length));
3665 CU_ASSERT(rc == 0);
3666
3667 /* Resize the blob */
3668 spdk_blob_resize(blob, 10, blob_op_complete, NULL);
3669 poll_threads();
3670 CU_ASSERT(g_bserrno == 0);
3671
3672 /* Set the blob as the super blob */
3673 spdk_bs_set_super(g_bs, blobid1, blob_op_complete, NULL);
3674 poll_threads();
3675 CU_ASSERT(g_bserrno == 0);
3676
3677 free_clusters = spdk_bs_free_cluster_count(g_bs);
3678
3679 spdk_blob_close(blob, blob_op_complete, NULL);
3680 poll_threads();
3681 CU_ASSERT(g_bserrno == 0);
3682 blob = NULL;
3683 g_blob = NULL;
3684 g_blobid = SPDK_BLOBID_INVALID;
3685
3686 /* Dirty shutdown */
3687 _spdk_bs_free(g_bs);
3688
3689 /* reload blobstore */
3690 dev = init_dev();
3691 spdk_bs_opts_init(&opts);
3692 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3693 poll_threads();
3694 CU_ASSERT(g_bserrno == 0);
3695
3696 /* Get the super blob */
3697 spdk_bs_get_super(g_bs, blob_op_with_id_complete, NULL);
3698 poll_threads();
3699 CU_ASSERT(g_bserrno == 0);
3700 CU_ASSERT(blobid1 == g_blobid);
3701
3702 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL);
3703 poll_threads();
3704 CU_ASSERT(g_bserrno == 0);
3705 CU_ASSERT(g_blob != NULL);
3706 blob = g_blob;
3707
3708 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs));
3709
3710 /* Get the xattrs */
3711 value = NULL;
3712 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len);
3713 CU_ASSERT(rc == 0);
3714 SPDK_CU_ASSERT_FATAL(value != NULL);
3715 CU_ASSERT(*(uint64_t *)value == length);
3716 CU_ASSERT(value_len == 8);
3717 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10);
3718
3719 /* Resize the blob */
3720 spdk_blob_resize(blob, 20, blob_op_complete, NULL);
3721 poll_threads();
3722 CU_ASSERT(g_bserrno == 0);
3723
3724 free_clusters = spdk_bs_free_cluster_count(g_bs);
3725
3726 spdk_blob_close(blob, blob_op_complete, NULL);
3727 poll_threads();
3728 CU_ASSERT(g_bserrno == 0);
3729 blob = NULL;
3730 g_blob = NULL;
3731 g_blobid = SPDK_BLOBID_INVALID;
3732
3733 /* Dirty shutdown */
3734 _spdk_bs_free(g_bs);
3735
3736 /* reload the blobstore */
3737 dev = init_dev();
3738 spdk_bs_opts_init(&opts);
3739 /* Load an existing blob store */
3740 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3741 poll_threads();
3742 CU_ASSERT(g_bserrno == 0);
3743 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3744 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL);
3745 poll_threads();
3746 CU_ASSERT(g_bserrno == 0);
3747 CU_ASSERT(g_blob != NULL);
3748 blob = g_blob;
3749 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 20);
3750 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs));
3751
3752 spdk_blob_close(blob, blob_op_complete, NULL);
3753 poll_threads();
3754 CU_ASSERT(g_bserrno == 0);
3755 blob = NULL;
3756 g_blob = NULL;
3757 g_blobid = SPDK_BLOBID_INVALID;
3758
3759 /* Create second blob */
3760 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3761 poll_threads();
3762 CU_ASSERT(g_bserrno == 0);
3763 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3764 blobid2 = g_blobid;
3765
3766 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL);
3767 poll_threads();
3768 CU_ASSERT(g_bserrno == 0);
3769 CU_ASSERT(g_blob != NULL);
3770 blob = g_blob;
3771
3772 /* Set some xattrs */
3773 rc = spdk_blob_set_xattr(blob, "name", "log1.txt", strlen("log1.txt") + 1);
3774 CU_ASSERT(rc == 0);
3775
3776 length = 5432;
3777 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length));
3778 CU_ASSERT(rc == 0);
3779
3780 /* Resize the blob */
3781 spdk_blob_resize(blob, 10, blob_op_complete, NULL);
3782 poll_threads();
3783 CU_ASSERT(g_bserrno == 0);
3784
3785 free_clusters = spdk_bs_free_cluster_count(g_bs);
3786
3787 spdk_blob_close(blob, blob_op_complete, NULL);
3788 poll_threads();
3789 CU_ASSERT(g_bserrno == 0);
3790 blob = NULL;
3791 g_blob = NULL;
3792 g_blobid = SPDK_BLOBID_INVALID;
3793
3794 /* Dirty shutdown */
3795 _spdk_bs_free(g_bs);
3796
3797 /* reload the blobstore */
3798 dev = init_dev();
3799 spdk_bs_opts_init(&opts);
3800 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3801 poll_threads();
3802 CU_ASSERT(g_bserrno == 0);
3803
3804 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL);
3805 poll_threads();
3806 CU_ASSERT(g_bserrno == 0);
3807 CU_ASSERT(g_blob != NULL);
3808 blob = g_blob;
3809
3810 /* Get the xattrs */
3811 value = NULL;
3812 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len);
3813 CU_ASSERT(rc == 0);
3814 SPDK_CU_ASSERT_FATAL(value != NULL);
3815 CU_ASSERT(*(uint64_t *)value == length);
3816 CU_ASSERT(value_len == 8);
3817 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10);
3818 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs));
3819
3820 spdk_blob_close(blob, blob_op_complete, NULL);
3821 poll_threads();
3822 CU_ASSERT(g_bserrno == 0);
3823 spdk_bs_delete_blob(g_bs, blobid2, blob_op_complete, NULL);
3824 poll_threads();
3825 CU_ASSERT(g_bserrno == 0);
3826
3827 free_clusters = spdk_bs_free_cluster_count(g_bs);
3828
3829 /* Dirty shutdown */
3830 _spdk_bs_free(g_bs);
3831 /* reload the blobstore */
3832 dev = init_dev();
3833 spdk_bs_opts_init(&opts);
3834 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3835 poll_threads();
3836 CU_ASSERT(g_bserrno == 0);
3837
3838 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL);
3839 poll_threads();
3840 CU_ASSERT(g_bserrno != 0);
3841 CU_ASSERT(g_blob == NULL);
3842
3843 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL);
3844 poll_threads();
3845 CU_ASSERT(g_bserrno == 0);
3846 CU_ASSERT(g_blob != NULL);
3847 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs));
3848 spdk_blob_close(g_blob, blob_op_complete, NULL);
3849 poll_threads();
3850 CU_ASSERT(g_bserrno == 0);
3851
3852 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3853 poll_threads();
3854 CU_ASSERT(g_bserrno == 0);
3855 g_bs = NULL;
3856
3857 /* reload the blobstore */
3858 dev = init_dev();
3859 spdk_bs_opts_init(&opts);
3860 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3861 poll_threads();
3862 CU_ASSERT(g_bserrno == 0);
3863
3864 /* Create second blob */
3865 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3866 poll_threads();
3867 CU_ASSERT(g_bserrno == 0);
3868 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3869 blobid2 = g_blobid;
3870
3871 /* Create third blob */
3872 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3873 poll_threads();
3874 CU_ASSERT(g_bserrno == 0);
3875 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3876 blobid3 = g_blobid;
3877
3878 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL);
3879 poll_threads();
3880 CU_ASSERT(g_bserrno == 0);
3881 CU_ASSERT(g_blob != NULL);
3882 blob = g_blob;
3883
3884 /* Set some xattrs for second blob */
3885 rc = spdk_blob_set_xattr(blob, "name", "log1.txt", strlen("log1.txt") + 1);
3886 CU_ASSERT(rc == 0);
3887
3888 length = 5432;
3889 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length));
3890 CU_ASSERT(rc == 0);
3891
3892 spdk_blob_close(blob, blob_op_complete, NULL);
3893 poll_threads();
3894 CU_ASSERT(g_bserrno == 0);
3895 blob = NULL;
3896 g_blob = NULL;
3897 g_blobid = SPDK_BLOBID_INVALID;
3898
3899 spdk_bs_open_blob(g_bs, blobid3, blob_op_with_handle_complete, NULL);
3900 poll_threads();
3901 CU_ASSERT(g_bserrno == 0);
3902 CU_ASSERT(g_blob != NULL);
3903 blob = g_blob;
3904
3905 /* Set some xattrs for third blob */
3906 rc = spdk_blob_set_xattr(blob, "name", "log2.txt", strlen("log2.txt") + 1);
3907 CU_ASSERT(rc == 0);
3908
3909 length = 5432;
3910 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length));
3911 CU_ASSERT(rc == 0);
3912
3913 spdk_blob_close(blob, blob_op_complete, NULL);
3914 poll_threads();
3915 CU_ASSERT(g_bserrno == 0);
3916 blob = NULL;
3917 g_blob = NULL;
3918 g_blobid = SPDK_BLOBID_INVALID;
3919
3920 /* Mark second blob as invalid */
3921 page_num = _spdk_bs_blobid_to_page(blobid2);
3922
3923 index = DEV_BUFFER_BLOCKLEN * (g_bs->md_start + page_num);
3924 page = (struct spdk_blob_md_page *)&g_dev_buffer[index];
3925 page->sequence_num = 1;
3926 page->crc = _spdk_blob_md_page_calc_crc(page);
3927
3928 free_clusters = spdk_bs_free_cluster_count(g_bs);
3929
3930 /* Dirty shutdown */
3931 _spdk_bs_free(g_bs);
3932 /* reload the blobstore */
3933 dev = init_dev();
3934 spdk_bs_opts_init(&opts);
3935 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
3936 poll_threads();
3937 CU_ASSERT(g_bserrno == 0);
3938
3939 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL);
3940 poll_threads();
3941 CU_ASSERT(g_bserrno != 0);
3942 CU_ASSERT(g_blob == NULL);
3943
3944 spdk_bs_open_blob(g_bs, blobid3, blob_op_with_handle_complete, NULL);
3945 poll_threads();
3946 CU_ASSERT(g_bserrno == 0);
3947 CU_ASSERT(g_blob != NULL);
3948 blob = g_blob;
3949
3950 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs));
3951
3952 spdk_blob_close(blob, blob_op_complete, NULL);
3953 poll_threads();
3954 CU_ASSERT(g_bserrno == 0);
3955 blob = NULL;
3956 g_blob = NULL;
3957 g_blobid = SPDK_BLOBID_INVALID;
3958
3959 spdk_bs_unload(g_bs, bs_op_complete, NULL);
3960 poll_threads();
3961 CU_ASSERT(g_bserrno == 0);
3962 g_bs = NULL;
3963 }
3964
3965 static void
3966 blob_flags(void)
3967 {
3968 struct spdk_bs_dev *dev;
3969 spdk_blob_id blobid_invalid, blobid_data_ro, blobid_md_ro;
3970 struct spdk_blob *blob_invalid, *blob_data_ro, *blob_md_ro;
3971 struct spdk_bs_opts opts;
3972 int rc;
3973
3974 dev = init_dev();
3975 spdk_bs_opts_init(&opts);
3976
3977 /* Initialize a new blob store */
3978 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
3979 poll_threads();
3980 CU_ASSERT(g_bserrno == 0);
3981 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
3982
3983 /* Create three blobs - one each for testing invalid, data_ro and md_ro flags. */
3984 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3985 poll_threads();
3986 CU_ASSERT(g_bserrno == 0);
3987 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3988 blobid_invalid = g_blobid;
3989
3990 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3991 poll_threads();
3992 CU_ASSERT(g_bserrno == 0);
3993 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
3994 blobid_data_ro = g_blobid;
3995
3996 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
3997 poll_threads();
3998 CU_ASSERT(g_bserrno == 0);
3999 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4000 blobid_md_ro = g_blobid;
4001
4002 spdk_bs_open_blob(g_bs, blobid_invalid, blob_op_with_handle_complete, NULL);
4003 poll_threads();
4004 CU_ASSERT(g_bserrno == 0);
4005 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4006 blob_invalid = g_blob;
4007
4008 spdk_bs_open_blob(g_bs, blobid_data_ro, blob_op_with_handle_complete, NULL);
4009 poll_threads();
4010 CU_ASSERT(g_bserrno == 0);
4011 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4012 blob_data_ro = g_blob;
4013
4014 spdk_bs_open_blob(g_bs, blobid_md_ro, blob_op_with_handle_complete, NULL);
4015 poll_threads();
4016 CU_ASSERT(g_bserrno == 0);
4017 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4018 blob_md_ro = g_blob;
4019
4020 /* Change the size of blob_data_ro to check if flags are serialized
4021 * when blob has non zero number of extents */
4022 spdk_blob_resize(blob_data_ro, 10, blob_op_complete, NULL);
4023 poll_threads();
4024 CU_ASSERT(g_bserrno == 0);
4025
4026 /* Set the xattr to check if flags are serialized
4027 * when blob has non zero number of xattrs */
4028 rc = spdk_blob_set_xattr(blob_md_ro, "name", "log.txt", strlen("log.txt") + 1);
4029 CU_ASSERT(rc == 0);
4030
4031 blob_invalid->invalid_flags = (1ULL << 63);
4032 blob_invalid->state = SPDK_BLOB_STATE_DIRTY;
4033 blob_data_ro->data_ro_flags = (1ULL << 62);
4034 blob_data_ro->state = SPDK_BLOB_STATE_DIRTY;
4035 blob_md_ro->md_ro_flags = (1ULL << 61);
4036 blob_md_ro->state = SPDK_BLOB_STATE_DIRTY;
4037
4038 g_bserrno = -1;
4039 spdk_blob_sync_md(blob_invalid, blob_op_complete, NULL);
4040 poll_threads();
4041 CU_ASSERT(g_bserrno == 0);
4042 g_bserrno = -1;
4043 spdk_blob_sync_md(blob_data_ro, blob_op_complete, NULL);
4044 poll_threads();
4045 CU_ASSERT(g_bserrno == 0);
4046 g_bserrno = -1;
4047 spdk_blob_sync_md(blob_md_ro, blob_op_complete, NULL);
4048 poll_threads();
4049 CU_ASSERT(g_bserrno == 0);
4050
4051 g_bserrno = -1;
4052 spdk_blob_close(blob_invalid, blob_op_complete, NULL);
4053 poll_threads();
4054 CU_ASSERT(g_bserrno == 0);
4055 blob_invalid = NULL;
4056 g_bserrno = -1;
4057 spdk_blob_close(blob_data_ro, blob_op_complete, NULL);
4058 poll_threads();
4059 CU_ASSERT(g_bserrno == 0);
4060 blob_data_ro = NULL;
4061 g_bserrno = -1;
4062 spdk_blob_close(blob_md_ro, blob_op_complete, NULL);
4063 poll_threads();
4064 CU_ASSERT(g_bserrno == 0);
4065 blob_md_ro = NULL;
4066
4067 g_blob = NULL;
4068 g_blobid = SPDK_BLOBID_INVALID;
4069
4070 /* Unload the blob store */
4071 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4072 poll_threads();
4073 CU_ASSERT(g_bserrno == 0);
4074 g_bs = NULL;
4075
4076 /* Load an existing blob store */
4077 dev = init_dev();
4078 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
4079 poll_threads();
4080 CU_ASSERT(g_bserrno == 0);
4081 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4082
4083 g_blob = NULL;
4084 g_bserrno = 0;
4085 spdk_bs_open_blob(g_bs, blobid_invalid, blob_op_with_handle_complete, NULL);
4086 poll_threads();
4087 CU_ASSERT(g_bserrno != 0);
4088 CU_ASSERT(g_blob == NULL);
4089
4090 g_blob = NULL;
4091 g_bserrno = -1;
4092 spdk_bs_open_blob(g_bs, blobid_data_ro, blob_op_with_handle_complete, NULL);
4093 poll_threads();
4094 CU_ASSERT(g_bserrno == 0);
4095 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4096 blob_data_ro = g_blob;
4097 /* If an unknown data_ro flag was found, the blob should be marked both data and md read-only. */
4098 CU_ASSERT(blob_data_ro->data_ro == true);
4099 CU_ASSERT(blob_data_ro->md_ro == true);
4100 CU_ASSERT(spdk_blob_get_num_clusters(blob_data_ro) == 10);
4101
4102 g_blob = NULL;
4103 g_bserrno = -1;
4104 spdk_bs_open_blob(g_bs, blobid_md_ro, blob_op_with_handle_complete, NULL);
4105 poll_threads();
4106 CU_ASSERT(g_bserrno == 0);
4107 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4108 blob_md_ro = g_blob;
4109 CU_ASSERT(blob_md_ro->data_ro == false);
4110 CU_ASSERT(blob_md_ro->md_ro == true);
4111
4112 g_bserrno = -1;
4113 spdk_blob_sync_md(blob_md_ro, blob_op_complete, NULL);
4114 poll_threads();
4115 CU_ASSERT(g_bserrno == 0);
4116
4117 spdk_blob_close(blob_data_ro, blob_op_complete, NULL);
4118 poll_threads();
4119 CU_ASSERT(g_bserrno == 0);
4120 spdk_blob_close(blob_md_ro, blob_op_complete, NULL);
4121 poll_threads();
4122 CU_ASSERT(g_bserrno == 0);
4123
4124 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4125 poll_threads();
4126 CU_ASSERT(g_bserrno == 0);
4127 }
4128
4129 static void
4130 bs_version(void)
4131 {
4132 struct spdk_bs_super_block *super;
4133 struct spdk_bs_dev *dev;
4134 struct spdk_bs_opts opts;
4135 spdk_blob_id blobid;
4136
4137 dev = init_dev();
4138 spdk_bs_opts_init(&opts);
4139
4140 /* Initialize a new blob store */
4141 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
4142 poll_threads();
4143 CU_ASSERT(g_bserrno == 0);
4144 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4145
4146 /* Unload the blob store */
4147 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4148 poll_threads();
4149 CU_ASSERT(g_bserrno == 0);
4150 g_bs = NULL;
4151
4152 /*
4153 * Change the bs version on disk. This will allow us to
4154 * test that the version does not get modified automatically
4155 * when loading and unloading the blobstore.
4156 */
4157 super = (struct spdk_bs_super_block *)&g_dev_buffer[0];
4158 CU_ASSERT(super->version == SPDK_BS_VERSION);
4159 CU_ASSERT(super->clean == 1);
4160 super->version = 2;
4161 /*
4162 * Version 2 metadata does not have a used blobid mask, so clear
4163 * those fields in the super block and zero the corresponding
4164 * region on "disk". We will use this to ensure blob IDs are
4165 * correctly reconstructed.
4166 */
4167 memset(&g_dev_buffer[super->used_blobid_mask_start * SPDK_BS_PAGE_SIZE], 0,
4168 super->used_blobid_mask_len * SPDK_BS_PAGE_SIZE);
4169 super->used_blobid_mask_start = 0;
4170 super->used_blobid_mask_len = 0;
4171 super->crc = _spdk_blob_md_page_calc_crc(super);
4172
4173 /* Load an existing blob store */
4174 dev = init_dev();
4175 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
4176 poll_threads();
4177 CU_ASSERT(g_bserrno == 0);
4178 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4179 CU_ASSERT(super->clean == 1);
4180
4181 /*
4182 * Create a blob - just to make sure that when we unload it
4183 * results in writing the super block (since metadata pages
4184 * were allocated.
4185 */
4186 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
4187 poll_threads();
4188 CU_ASSERT(g_bserrno == 0);
4189 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4190 blobid = g_blobid;
4191
4192 /* Unload the blob store */
4193 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4194 poll_threads();
4195 CU_ASSERT(g_bserrno == 0);
4196 g_bs = NULL;
4197 CU_ASSERT(super->version == 2);
4198 CU_ASSERT(super->used_blobid_mask_start == 0);
4199 CU_ASSERT(super->used_blobid_mask_len == 0);
4200
4201 dev = init_dev();
4202 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
4203 poll_threads();
4204 CU_ASSERT(g_bserrno == 0);
4205 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4206
4207 g_blob = NULL;
4208 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
4209 poll_threads();
4210 CU_ASSERT(g_bserrno == 0);
4211 CU_ASSERT(g_blob != NULL);
4212
4213 spdk_blob_close(g_blob, blob_op_complete, NULL);
4214 poll_threads();
4215 CU_ASSERT(g_bserrno == 0);
4216
4217 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4218 poll_threads();
4219 CU_ASSERT(g_bserrno == 0);
4220 g_bs = NULL;
4221 CU_ASSERT(super->version == 2);
4222 CU_ASSERT(super->used_blobid_mask_start == 0);
4223 CU_ASSERT(super->used_blobid_mask_len == 0);
4224 }
4225
4226 static void
4227 blob_set_xattrs(void)
4228 {
4229 struct spdk_blob_store *bs;
4230 struct spdk_bs_dev *dev;
4231 struct spdk_blob *blob;
4232 struct spdk_blob_opts opts;
4233 spdk_blob_id blobid;
4234 const void *value;
4235 size_t value_len;
4236 int rc;
4237
4238 dev = init_dev();
4239
4240 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
4241 poll_threads();
4242 CU_ASSERT(g_bserrno == 0);
4243 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4244 bs = g_bs;
4245
4246 /* Create blob with extra attributes */
4247 spdk_blob_opts_init(&opts);
4248
4249 opts.xattrs.names = g_xattr_names;
4250 opts.xattrs.get_value = _get_xattr_value;
4251 opts.xattrs.count = 3;
4252 opts.xattrs.ctx = &g_ctx;
4253
4254 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4255 poll_threads();
4256 CU_ASSERT(g_bserrno == 0);
4257 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4258 blobid = g_blobid;
4259
4260 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
4261 poll_threads();
4262 CU_ASSERT(g_bserrno == 0);
4263 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4264 blob = g_blob;
4265
4266 /* Get the xattrs */
4267 value = NULL;
4268
4269 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[0], &value, &value_len);
4270 CU_ASSERT(rc == 0);
4271 SPDK_CU_ASSERT_FATAL(value != NULL);
4272 CU_ASSERT(value_len == strlen(g_xattr_values[0]));
4273 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len);
4274
4275 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[1], &value, &value_len);
4276 CU_ASSERT(rc == 0);
4277 SPDK_CU_ASSERT_FATAL(value != NULL);
4278 CU_ASSERT(value_len == strlen(g_xattr_values[1]));
4279 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len);
4280
4281 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[2], &value, &value_len);
4282 CU_ASSERT(rc == 0);
4283 SPDK_CU_ASSERT_FATAL(value != NULL);
4284 CU_ASSERT(value_len == strlen(g_xattr_values[2]));
4285 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len);
4286
4287 /* Try to get non existing attribute */
4288
4289 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len);
4290 CU_ASSERT(rc == -ENOENT);
4291
4292 spdk_blob_close(blob, blob_op_complete, NULL);
4293 poll_threads();
4294 CU_ASSERT(g_bserrno == 0);
4295 blob = NULL;
4296 g_blob = NULL;
4297 g_blobid = SPDK_BLOBID_INVALID;
4298
4299 /* NULL callback */
4300 spdk_blob_opts_init(&opts);
4301 opts.xattrs.names = g_xattr_names;
4302 opts.xattrs.get_value = NULL;
4303 opts.xattrs.count = 1;
4304 opts.xattrs.ctx = &g_ctx;
4305
4306 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4307 poll_threads();
4308 CU_ASSERT(g_bserrno == -EINVAL);
4309 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4310
4311 /* NULL values */
4312 spdk_blob_opts_init(&opts);
4313 opts.xattrs.names = g_xattr_names;
4314 opts.xattrs.get_value = _get_xattr_value_null;
4315 opts.xattrs.count = 1;
4316 opts.xattrs.ctx = NULL;
4317
4318 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4319 poll_threads();
4320 CU_ASSERT(g_bserrno == -EINVAL);
4321
4322 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4323 poll_threads();
4324 CU_ASSERT(g_bserrno == 0);
4325 g_bs = NULL;
4326
4327 }
4328
4329 static void
4330 blob_thin_prov_alloc(void)
4331 {
4332 struct spdk_blob_store *bs;
4333 struct spdk_bs_dev *dev;
4334 struct spdk_blob *blob;
4335 struct spdk_blob_opts opts;
4336 spdk_blob_id blobid;
4337 uint64_t free_clusters;
4338
4339 dev = init_dev();
4340
4341 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
4342 poll_threads();
4343 CU_ASSERT(g_bserrno == 0);
4344 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4345 bs = g_bs;
4346 free_clusters = spdk_bs_free_cluster_count(bs);
4347
4348 /* Set blob as thin provisioned */
4349 spdk_blob_opts_init(&opts);
4350 opts.thin_provision = true;
4351
4352 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4353 poll_threads();
4354 CU_ASSERT(g_bserrno == 0);
4355 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4356 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4357 blobid = g_blobid;
4358
4359 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
4360 poll_threads();
4361 CU_ASSERT(g_bserrno == 0);
4362 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4363 blob = g_blob;
4364
4365 CU_ASSERT(blob->active.num_clusters == 0);
4366 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0);
4367
4368 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */
4369 spdk_blob_resize(blob, 5, blob_op_complete, NULL);
4370 poll_threads();
4371 CU_ASSERT(g_bserrno == 0);
4372 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4373 CU_ASSERT(blob->active.num_clusters == 5);
4374 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5);
4375
4376 /* Grow it to 1TB - still unallocated */
4377 spdk_blob_resize(blob, 262144, blob_op_complete, NULL);
4378 poll_threads();
4379 CU_ASSERT(g_bserrno == 0);
4380 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4381 CU_ASSERT(blob->active.num_clusters == 262144);
4382 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 262144);
4383
4384 spdk_blob_sync_md(blob, blob_op_complete, NULL);
4385 poll_threads();
4386 CU_ASSERT(g_bserrno == 0);
4387 /* Sync must not change anything */
4388 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4389 CU_ASSERT(blob->active.num_clusters == 262144);
4390 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 262144);
4391 /* Since clusters are not allocated,
4392 * number of metadata pages is expected to be minimal.
4393 */
4394 CU_ASSERT(blob->active.num_pages == 1);
4395
4396 /* Shrink the blob to 3 clusters - still unallocated */
4397 spdk_blob_resize(blob, 3, blob_op_complete, NULL);
4398 poll_threads();
4399 CU_ASSERT(g_bserrno == 0);
4400 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4401 CU_ASSERT(blob->active.num_clusters == 3);
4402 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 3);
4403
4404 spdk_blob_sync_md(blob, blob_op_complete, NULL);
4405 poll_threads();
4406 CU_ASSERT(g_bserrno == 0);
4407 /* Sync must not change anything */
4408 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4409 CU_ASSERT(blob->active.num_clusters == 3);
4410 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 3);
4411
4412 spdk_blob_close(blob, blob_op_complete, NULL);
4413 poll_threads();
4414 CU_ASSERT(g_bserrno == 0);
4415
4416 /* Unload the blob store */
4417 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4418 poll_threads();
4419 CU_ASSERT(g_bserrno == 0);
4420 g_bs = NULL;
4421 g_blob = NULL;
4422 g_blobid = 0;
4423
4424 /* Load an existing blob store */
4425 dev = init_dev();
4426 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
4427 poll_threads();
4428 CU_ASSERT(g_bserrno == 0);
4429 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4430
4431 bs = g_bs;
4432
4433 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
4434 poll_threads();
4435 CU_ASSERT(g_bserrno == 0);
4436 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4437 blob = g_blob;
4438
4439 /* Check that clusters allocation and size is still the same */
4440 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4441 CU_ASSERT(blob->active.num_clusters == 3);
4442
4443 spdk_blob_close(blob, blob_op_complete, NULL);
4444 poll_threads();
4445 CU_ASSERT(g_bserrno == 0);
4446
4447 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
4448 poll_threads();
4449 CU_ASSERT(g_bserrno == 0);
4450
4451 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4452 poll_threads();
4453 CU_ASSERT(g_bserrno == 0);
4454 g_bs = NULL;
4455 }
4456
4457 static void
4458 blob_insert_cluster_msg(void)
4459 {
4460 struct spdk_blob_store *bs;
4461 struct spdk_bs_dev *dev;
4462 struct spdk_blob *blob;
4463 struct spdk_blob_opts opts;
4464 spdk_blob_id blobid;
4465 uint64_t free_clusters;
4466
4467 dev = init_dev();
4468
4469 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
4470 poll_threads();
4471 CU_ASSERT(g_bserrno == 0);
4472 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4473 bs = g_bs;
4474 free_clusters = spdk_bs_free_cluster_count(bs);
4475
4476 /* Set blob as thin provisioned */
4477 spdk_blob_opts_init(&opts);
4478 opts.thin_provision = true;
4479 opts.num_clusters = 4;
4480
4481 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4482 poll_threads();
4483 CU_ASSERT(g_bserrno == 0);
4484 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4485 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4486 blobid = g_blobid;
4487
4488 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
4489 poll_threads();
4490 CU_ASSERT(g_bserrno == 0);
4491 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4492 blob = g_blob;
4493
4494 CU_ASSERT(blob->active.num_clusters == 4);
4495 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 4);
4496 CU_ASSERT(blob->active.clusters[1] == 0);
4497
4498 _spdk_bs_claim_cluster(bs, 0xF);
4499 _spdk_blob_insert_cluster_on_md_thread(blob, 1, 0xF, blob_op_complete, NULL);
4500 poll_threads();
4501
4502 CU_ASSERT(blob->active.clusters[1] != 0);
4503
4504 spdk_blob_close(blob, blob_op_complete, NULL);
4505 poll_threads();
4506 CU_ASSERT(g_bserrno == 0);
4507
4508 /* Unload the blob store */
4509 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4510 poll_threads();
4511 CU_ASSERT(g_bserrno == 0);
4512 g_bs = NULL;
4513 g_blob = NULL;
4514 g_blobid = 0;
4515
4516 /* Load an existing blob store */
4517 dev = init_dev();
4518 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
4519 poll_threads();
4520 CU_ASSERT(g_bserrno == 0);
4521 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4522
4523 bs = g_bs;
4524
4525 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
4526 poll_threads();
4527 CU_ASSERT(g_bserrno == 0);
4528 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4529 blob = g_blob;
4530
4531 CU_ASSERT(blob->active.clusters[1] != 0);
4532
4533 spdk_blob_close(blob, blob_op_complete, NULL);
4534 poll_threads();
4535 CU_ASSERT(g_bserrno == 0);
4536
4537 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
4538 poll_threads();
4539 CU_ASSERT(g_bserrno == 0);
4540
4541 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4542 poll_threads();
4543 CU_ASSERT(g_bserrno == 0);
4544 g_bs = NULL;
4545 }
4546
4547 static void
4548 blob_thin_prov_rw(void)
4549 {
4550 static const uint8_t zero[10 * 4096] = { 0 };
4551 struct spdk_blob_store *bs;
4552 struct spdk_bs_dev *dev;
4553 struct spdk_blob *blob;
4554 struct spdk_io_channel *channel, *channel_thread1;
4555 struct spdk_blob_opts opts;
4556 spdk_blob_id blobid;
4557 uint64_t free_clusters;
4558 uint64_t page_size;
4559 uint8_t payload_read[10 * 4096];
4560 uint8_t payload_write[10 * 4096];
4561 uint64_t write_bytes;
4562 uint64_t read_bytes;
4563
4564 dev = init_dev();
4565
4566 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
4567 poll_threads();
4568 CU_ASSERT(g_bserrno == 0);
4569 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4570 bs = g_bs;
4571 free_clusters = spdk_bs_free_cluster_count(bs);
4572 page_size = spdk_bs_get_page_size(bs);
4573
4574 channel = spdk_bs_alloc_io_channel(bs);
4575 CU_ASSERT(channel != NULL);
4576
4577 spdk_blob_opts_init(&opts);
4578 opts.thin_provision = true;
4579
4580 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4581 poll_threads();
4582 CU_ASSERT(g_bserrno == 0);
4583 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4584 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4585 blobid = g_blobid;
4586
4587 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
4588 poll_threads();
4589 CU_ASSERT(g_bserrno == 0);
4590 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4591 blob = g_blob;
4592
4593 CU_ASSERT(blob->active.num_clusters == 0);
4594
4595 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */
4596 spdk_blob_resize(blob, 5, blob_op_complete, NULL);
4597 poll_threads();
4598 CU_ASSERT(g_bserrno == 0);
4599 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4600 CU_ASSERT(blob->active.num_clusters == 5);
4601
4602 spdk_blob_sync_md(blob, blob_op_complete, NULL);
4603 poll_threads();
4604 CU_ASSERT(g_bserrno == 0);
4605 /* Sync must not change anything */
4606 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4607 CU_ASSERT(blob->active.num_clusters == 5);
4608
4609 /* Payload should be all zeros from unallocated clusters */
4610 memset(payload_read, 0xFF, sizeof(payload_read));
4611 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
4612 poll_threads();
4613 CU_ASSERT(g_bserrno == 0);
4614 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0);
4615
4616 write_bytes = g_dev_write_bytes;
4617 read_bytes = g_dev_read_bytes;
4618
4619 /* Perform write on thread 1. That will allocate cluster on thread 0 via send_msg */
4620 set_thread(1);
4621 channel_thread1 = spdk_bs_alloc_io_channel(bs);
4622 CU_ASSERT(channel_thread1 != NULL);
4623 memset(payload_write, 0xE5, sizeof(payload_write));
4624 spdk_blob_io_write(blob, channel_thread1, payload_write, 4, 10, blob_op_complete, NULL);
4625 CU_ASSERT(free_clusters - 1 == spdk_bs_free_cluster_count(bs));
4626 /* Perform write on thread 0. That will try to allocate cluster,
4627 * but fail due to another thread issuing the cluster allocation first. */
4628 set_thread(0);
4629 memset(payload_write, 0xE5, sizeof(payload_write));
4630 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
4631 CU_ASSERT(free_clusters - 2 == spdk_bs_free_cluster_count(bs));
4632 poll_threads();
4633 CU_ASSERT(g_bserrno == 0);
4634 CU_ASSERT(free_clusters - 1 == spdk_bs_free_cluster_count(bs));
4635 /* For thin-provisioned blob we need to write 20 pages plus one page metadata and
4636 * read 0 bytes */
4637 CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 21);
4638 CU_ASSERT(g_dev_read_bytes - read_bytes == 0);
4639
4640 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
4641 poll_threads();
4642 CU_ASSERT(g_bserrno == 0);
4643 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
4644
4645 spdk_blob_close(blob, blob_op_complete, NULL);
4646 poll_threads();
4647 CU_ASSERT(g_bserrno == 0);
4648
4649 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
4650 poll_threads();
4651 CU_ASSERT(g_bserrno == 0);
4652 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4653
4654 spdk_bs_free_io_channel(channel_thread1);
4655 spdk_bs_free_io_channel(channel);
4656 poll_threads();
4657
4658 /* Unload the blob store */
4659 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4660 poll_threads();
4661 CU_ASSERT(g_bserrno == 0);
4662 g_bs = NULL;
4663 g_blob = NULL;
4664 g_blobid = 0;
4665 }
4666
4667 static void
4668 blob_thin_prov_rw_iov(void)
4669 {
4670 static const uint8_t zero[10 * 4096] = { 0 };
4671 struct spdk_blob_store *bs;
4672 struct spdk_bs_dev *dev;
4673 struct spdk_blob *blob;
4674 struct spdk_io_channel *channel;
4675 struct spdk_blob_opts opts;
4676 spdk_blob_id blobid;
4677 uint64_t free_clusters;
4678 uint8_t payload_read[10 * 4096];
4679 uint8_t payload_write[10 * 4096];
4680 struct iovec iov_read[3];
4681 struct iovec iov_write[3];
4682
4683 dev = init_dev();
4684
4685 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
4686 poll_threads();
4687 CU_ASSERT(g_bserrno == 0);
4688 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4689 bs = g_bs;
4690 free_clusters = spdk_bs_free_cluster_count(bs);
4691
4692 channel = spdk_bs_alloc_io_channel(bs);
4693 CU_ASSERT(channel != NULL);
4694
4695 spdk_blob_opts_init(&opts);
4696 opts.thin_provision = true;
4697
4698 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4699 poll_threads();
4700 CU_ASSERT(g_bserrno == 0);
4701 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4702 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4703 blobid = g_blobid;
4704
4705 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
4706 poll_threads();
4707 CU_ASSERT(g_bserrno == 0);
4708 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4709 blob = g_blob;
4710
4711 CU_ASSERT(blob->active.num_clusters == 0);
4712
4713 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */
4714 spdk_blob_resize(blob, 5, blob_op_complete, NULL);
4715 poll_threads();
4716 CU_ASSERT(g_bserrno == 0);
4717 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4718 CU_ASSERT(blob->active.num_clusters == 5);
4719
4720 spdk_blob_sync_md(blob, blob_op_complete, NULL);
4721 poll_threads();
4722 CU_ASSERT(g_bserrno == 0);
4723 /* Sync must not change anything */
4724 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4725 CU_ASSERT(blob->active.num_clusters == 5);
4726
4727 /* Payload should be all zeros from unallocated clusters */
4728 memset(payload_read, 0xAA, sizeof(payload_read));
4729 iov_read[0].iov_base = payload_read;
4730 iov_read[0].iov_len = 3 * 4096;
4731 iov_read[1].iov_base = payload_read + 3 * 4096;
4732 iov_read[1].iov_len = 4 * 4096;
4733 iov_read[2].iov_base = payload_read + 7 * 4096;
4734 iov_read[2].iov_len = 3 * 4096;
4735 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL);
4736 poll_threads();
4737 CU_ASSERT(g_bserrno == 0);
4738 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0);
4739
4740 memset(payload_write, 0xE5, sizeof(payload_write));
4741 iov_write[0].iov_base = payload_write;
4742 iov_write[0].iov_len = 1 * 4096;
4743 iov_write[1].iov_base = payload_write + 1 * 4096;
4744 iov_write[1].iov_len = 5 * 4096;
4745 iov_write[2].iov_base = payload_write + 6 * 4096;
4746 iov_write[2].iov_len = 4 * 4096;
4747
4748 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL);
4749 poll_threads();
4750 CU_ASSERT(g_bserrno == 0);
4751
4752 memset(payload_read, 0xAA, sizeof(payload_read));
4753 iov_read[0].iov_base = payload_read;
4754 iov_read[0].iov_len = 3 * 4096;
4755 iov_read[1].iov_base = payload_read + 3 * 4096;
4756 iov_read[1].iov_len = 4 * 4096;
4757 iov_read[2].iov_base = payload_read + 7 * 4096;
4758 iov_read[2].iov_len = 3 * 4096;
4759 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL);
4760 poll_threads();
4761 CU_ASSERT(g_bserrno == 0);
4762 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
4763
4764 spdk_blob_close(blob, blob_op_complete, NULL);
4765 poll_threads();
4766 CU_ASSERT(g_bserrno == 0);
4767
4768 spdk_bs_free_io_channel(channel);
4769 poll_threads();
4770
4771 /* Unload the blob store */
4772 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4773 poll_threads();
4774 CU_ASSERT(g_bserrno == 0);
4775 g_bs = NULL;
4776 g_blob = NULL;
4777 g_blobid = 0;
4778 }
4779
4780 struct iter_ctx {
4781 int current_iter;
4782 spdk_blob_id blobid[4];
4783 };
4784
4785 static void
4786 test_iter(void *arg, struct spdk_blob *blob, int bserrno)
4787 {
4788 struct iter_ctx *iter_ctx = arg;
4789 spdk_blob_id blobid;
4790
4791 CU_ASSERT(bserrno == 0);
4792 blobid = spdk_blob_get_id(blob);
4793 CU_ASSERT(blobid == iter_ctx->blobid[iter_ctx->current_iter++]);
4794 }
4795
4796 static void
4797 bs_load_iter(void)
4798 {
4799 struct spdk_bs_dev *dev;
4800 struct iter_ctx iter_ctx = { 0 };
4801 struct spdk_blob *blob;
4802 int i, rc;
4803 struct spdk_bs_opts opts;
4804
4805 dev = init_dev();
4806 spdk_bs_opts_init(&opts);
4807 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
4808
4809 /* Initialize a new blob store */
4810 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
4811 poll_threads();
4812 CU_ASSERT(g_bserrno == 0);
4813 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4814
4815 for (i = 0; i < 4; i++) {
4816 g_bserrno = -1;
4817 g_blobid = SPDK_BLOBID_INVALID;
4818 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL);
4819 poll_threads();
4820 CU_ASSERT(g_bserrno == 0);
4821 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4822 iter_ctx.blobid[i] = g_blobid;
4823
4824 g_bserrno = -1;
4825 g_blob = NULL;
4826 spdk_bs_open_blob(g_bs, g_blobid, blob_op_with_handle_complete, NULL);
4827 poll_threads();
4828 CU_ASSERT(g_bserrno == 0);
4829 CU_ASSERT(g_blob != NULL);
4830 blob = g_blob;
4831
4832 /* Just save the blobid as an xattr for testing purposes. */
4833 rc = spdk_blob_set_xattr(blob, "blobid", &g_blobid, sizeof(g_blobid));
4834 CU_ASSERT(rc == 0);
4835
4836 /* Resize the blob */
4837 spdk_blob_resize(blob, i, blob_op_complete, NULL);
4838 poll_threads();
4839 CU_ASSERT(g_bserrno == 0);
4840
4841 spdk_blob_close(blob, blob_op_complete, NULL);
4842 poll_threads();
4843 CU_ASSERT(g_bserrno == 0);
4844 }
4845
4846 g_bserrno = -1;
4847 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4848 poll_threads();
4849 CU_ASSERT(g_bserrno == 0);
4850
4851 dev = init_dev();
4852 spdk_bs_opts_init(&opts);
4853 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
4854 opts.iter_cb_fn = test_iter;
4855 opts.iter_cb_arg = &iter_ctx;
4856
4857 /* Test blob iteration during load after a clean shutdown. */
4858 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
4859 poll_threads();
4860 CU_ASSERT(g_bserrno == 0);
4861 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4862
4863 /* Dirty shutdown */
4864 _spdk_bs_free(g_bs);
4865
4866 dev = init_dev();
4867 spdk_bs_opts_init(&opts);
4868 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");
4869 opts.iter_cb_fn = test_iter;
4870 iter_ctx.current_iter = 0;
4871 opts.iter_cb_arg = &iter_ctx;
4872
4873 /* Test blob iteration during load after a dirty shutdown. */
4874 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
4875 poll_threads();
4876 CU_ASSERT(g_bserrno == 0);
4877 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4878
4879 spdk_bs_unload(g_bs, bs_op_complete, NULL);
4880 poll_threads();
4881 CU_ASSERT(g_bserrno == 0);
4882 g_bs = NULL;
4883 }
4884
4885 static void
4886 blob_snapshot_rw(void)
4887 {
4888 static const uint8_t zero[10 * 4096] = { 0 };
4889 struct spdk_blob_store *bs;
4890 struct spdk_bs_dev *dev;
4891 struct spdk_blob *blob, *snapshot;
4892 struct spdk_io_channel *channel;
4893 struct spdk_blob_opts opts;
4894 spdk_blob_id blobid, snapshotid;
4895 uint64_t free_clusters;
4896 uint64_t cluster_size;
4897 uint64_t page_size;
4898 uint8_t payload_read[10 * 4096];
4899 uint8_t payload_write[10 * 4096];
4900 uint64_t write_bytes;
4901 uint64_t read_bytes;
4902
4903 dev = init_dev();
4904
4905 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
4906 poll_threads();
4907 CU_ASSERT(g_bserrno == 0);
4908 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
4909 bs = g_bs;
4910 free_clusters = spdk_bs_free_cluster_count(bs);
4911 cluster_size = spdk_bs_get_cluster_size(bs);
4912 page_size = spdk_bs_get_page_size(bs);
4913
4914 channel = spdk_bs_alloc_io_channel(bs);
4915 CU_ASSERT(channel != NULL);
4916
4917 spdk_blob_opts_init(&opts);
4918 opts.thin_provision = true;
4919 opts.num_clusters = 5;
4920
4921 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
4922 poll_threads();
4923 CU_ASSERT(g_bserrno == 0);
4924 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4925 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
4926 blobid = g_blobid;
4927
4928 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
4929 poll_threads();
4930 CU_ASSERT(g_bserrno == 0);
4931 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4932 blob = g_blob;
4933
4934 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5);
4935
4936 memset(payload_read, 0xFF, sizeof(payload_read));
4937 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
4938 poll_threads();
4939 CU_ASSERT(g_bserrno == 0);
4940 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0);
4941
4942 memset(payload_write, 0xE5, sizeof(payload_write));
4943 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
4944 poll_threads();
4945 CU_ASSERT(g_bserrno == 0);
4946 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));
4947
4948 /* Create snapshot from blob */
4949 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
4950 poll_threads();
4951 CU_ASSERT(g_bserrno == 0);
4952 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
4953 snapshotid = g_blobid;
4954
4955 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
4956 poll_threads();
4957 CU_ASSERT(g_bserrno == 0);
4958 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
4959 snapshot = g_blob;
4960 CU_ASSERT(snapshot->data_ro == true)
4961 CU_ASSERT(snapshot->md_ro == true)
4962
4963 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5)
4964
4965 write_bytes = g_dev_write_bytes;
4966 read_bytes = g_dev_read_bytes;
4967
4968 memset(payload_write, 0xAA, sizeof(payload_write));
4969 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
4970 poll_threads();
4971 CU_ASSERT(g_bserrno == 0);
4972 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));
4973
4974 /* For a clone we need to allocate and copy one cluster, update one page of metadata
4975 * and then write 10 pages of payload.
4976 */
4977 CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 11 + cluster_size);
4978 CU_ASSERT(g_dev_read_bytes - read_bytes == cluster_size);
4979
4980 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
4981 poll_threads();
4982 CU_ASSERT(g_bserrno == 0);
4983 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
4984
4985 /* Data on snapshot should not change after write to clone */
4986 memset(payload_write, 0xE5, sizeof(payload_write));
4987 spdk_blob_io_read(snapshot, channel, payload_read, 4, 10, blob_op_complete, NULL);
4988 poll_threads();
4989 CU_ASSERT(g_bserrno == 0);
4990 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
4991
4992 spdk_blob_close(blob, blob_op_complete, NULL);
4993 poll_threads();
4994 CU_ASSERT(g_bserrno == 0);
4995
4996 spdk_blob_close(snapshot, blob_op_complete, NULL);
4997 poll_threads();
4998 CU_ASSERT(g_bserrno == 0);
4999
5000 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
5001 poll_threads();
5002 CU_ASSERT(g_bserrno == 0);
5003
5004 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
5005 poll_threads();
5006 CU_ASSERT(g_bserrno == 0);
5007
5008 spdk_bs_free_io_channel(channel);
5009 poll_threads();
5010
5011 /* Unload the blob store */
5012 spdk_bs_unload(g_bs, bs_op_complete, NULL);
5013 poll_threads();
5014 CU_ASSERT(g_bserrno == 0);
5015 g_bs = NULL;
5016 g_blob = NULL;
5017 g_blobid = 0;
5018 }
5019
5020 static void
5021 blob_snapshot_rw_iov(void)
5022 {
5023 static const uint8_t zero[10 * 4096] = { 0 };
5024 struct spdk_blob_store *bs;
5025 struct spdk_bs_dev *dev;
5026 struct spdk_blob *blob, *snapshot;
5027 struct spdk_io_channel *channel;
5028 struct spdk_blob_opts opts;
5029 spdk_blob_id blobid, snapshotid;
5030 uint64_t free_clusters;
5031 uint8_t payload_read[10 * 4096];
5032 uint8_t payload_write[10 * 4096];
5033 struct iovec iov_read[3];
5034 struct iovec iov_write[3];
5035
5036 dev = init_dev();
5037
5038 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
5039 poll_threads();
5040 CU_ASSERT(g_bserrno == 0);
5041 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
5042 bs = g_bs;
5043 free_clusters = spdk_bs_free_cluster_count(bs);
5044
5045 channel = spdk_bs_alloc_io_channel(bs);
5046 CU_ASSERT(channel != NULL);
5047
5048 spdk_blob_opts_init(&opts);
5049 opts.thin_provision = true;
5050 opts.num_clusters = 5;
5051
5052 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
5053 poll_threads();
5054 CU_ASSERT(g_bserrno == 0);
5055 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5056 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
5057 blobid = g_blobid;
5058
5059 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
5060 poll_threads();
5061 CU_ASSERT(g_bserrno == 0);
5062 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5063 blob = g_blob;
5064
5065 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5);
5066
5067 /* Create snapshot from blob */
5068 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
5069 poll_threads();
5070 CU_ASSERT(g_bserrno == 0);
5071 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5072 snapshotid = g_blobid;
5073
5074 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
5075 poll_threads();
5076 CU_ASSERT(g_bserrno == 0);
5077 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5078 snapshot = g_blob;
5079 CU_ASSERT(snapshot->data_ro == true)
5080 CU_ASSERT(snapshot->md_ro == true)
5081 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5);
5082
5083 /* Payload should be all zeros from unallocated clusters */
5084 memset(payload_read, 0xAA, sizeof(payload_read));
5085 iov_read[0].iov_base = payload_read;
5086 iov_read[0].iov_len = 3 * 4096;
5087 iov_read[1].iov_base = payload_read + 3 * 4096;
5088 iov_read[1].iov_len = 4 * 4096;
5089 iov_read[2].iov_base = payload_read + 7 * 4096;
5090 iov_read[2].iov_len = 3 * 4096;
5091 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL);
5092 poll_threads();
5093 CU_ASSERT(g_bserrno == 0);
5094 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0);
5095
5096 memset(payload_write, 0xE5, sizeof(payload_write));
5097 iov_write[0].iov_base = payload_write;
5098 iov_write[0].iov_len = 1 * 4096;
5099 iov_write[1].iov_base = payload_write + 1 * 4096;
5100 iov_write[1].iov_len = 5 * 4096;
5101 iov_write[2].iov_base = payload_write + 6 * 4096;
5102 iov_write[2].iov_len = 4 * 4096;
5103
5104 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL);
5105 poll_threads();
5106 CU_ASSERT(g_bserrno == 0);
5107
5108 memset(payload_read, 0xAA, sizeof(payload_read));
5109 iov_read[0].iov_base = payload_read;
5110 iov_read[0].iov_len = 3 * 4096;
5111 iov_read[1].iov_base = payload_read + 3 * 4096;
5112 iov_read[1].iov_len = 4 * 4096;
5113 iov_read[2].iov_base = payload_read + 7 * 4096;
5114 iov_read[2].iov_len = 3 * 4096;
5115 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL);
5116 poll_threads();
5117 CU_ASSERT(g_bserrno == 0);
5118 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
5119
5120 spdk_blob_close(blob, blob_op_complete, NULL);
5121 poll_threads();
5122 CU_ASSERT(g_bserrno == 0);
5123
5124 spdk_blob_close(snapshot, blob_op_complete, NULL);
5125 poll_threads();
5126 CU_ASSERT(g_bserrno == 0);
5127
5128 spdk_bs_free_io_channel(channel);
5129 poll_threads();
5130
5131 /* Unload the blob store */
5132 spdk_bs_unload(g_bs, bs_op_complete, NULL);
5133 poll_threads();
5134 CU_ASSERT(g_bserrno == 0);
5135 g_bs = NULL;
5136 g_blob = NULL;
5137 g_blobid = 0;
5138 }
5139
5140 /**
5141 * Inflate / decouple parent rw unit tests.
5142 *
5143 * --------------
5144 * original blob: 0 1 2 3 4
5145 * ,---------+---------+---------+---------+---------.
5146 * snapshot |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| - |
5147 * +---------+---------+---------+---------+---------+
5148 * snapshot2 | - |yyyyyyyyy| - |yyyyyyyyy| - |
5149 * +---------+---------+---------+---------+---------+
5150 * blob | - |zzzzzzzzz| - | - | - |
5151 * '---------+---------+---------+---------+---------'
5152 * . . . . . .
5153 * -------- . . . . . .
5154 * inflate: . . . . . .
5155 * ,---------+---------+---------+---------+---------.
5156 * blob |xxxxxxxxx|zzzzzzzzz|xxxxxxxxx|yyyyyyyyy|000000000|
5157 * '---------+---------+---------+---------+---------'
5158 *
5159 * NOTE: needs to allocate 4 clusters, thin provisioning removed, dependency
5160 * on snapshot2 and snapshot removed . . .
5161 * . . . . . .
5162 * ---------------- . . . . . .
5163 * decouple parent: . . . . . .
5164 * ,---------+---------+---------+---------+---------.
5165 * snapshot |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| - |
5166 * +---------+---------+---------+---------+---------+
5167 * blob | - |zzzzzzzzz| - |yyyyyyyyy| - |
5168 * '---------+---------+---------+---------+---------'
5169 *
5170 * NOTE: needs to allocate 1 cluster, 3 clusters unallocated, dependency
5171 * on snapshot2 removed and on snapshot still exists. Snapshot2
5172 * should remain a clone of snapshot.
5173 */
5174 static void
5175 _blob_inflate_rw(bool decouple_parent)
5176 {
5177 struct spdk_blob_store *bs;
5178 struct spdk_bs_dev *dev;
5179 struct spdk_blob *blob, *snapshot, *snapshot2;
5180 struct spdk_io_channel *channel;
5181 struct spdk_blob_opts opts;
5182 spdk_blob_id blobid, snapshotid, snapshot2id;
5183 uint64_t free_clusters;
5184 uint64_t cluster_size;
5185
5186 uint64_t payload_size;
5187 uint8_t *payload_read;
5188 uint8_t *payload_write;
5189 uint8_t *payload_clone;
5190
5191 uint64_t pages_per_cluster;
5192 uint64_t pages_per_payload;
5193
5194 int i;
5195 spdk_blob_id ids[2];
5196 size_t count;
5197
5198 dev = init_dev();
5199
5200 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
5201 poll_threads();
5202 CU_ASSERT(g_bserrno == 0);
5203 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
5204 bs = g_bs;
5205
5206 free_clusters = spdk_bs_free_cluster_count(bs);
5207 cluster_size = spdk_bs_get_cluster_size(bs);
5208 pages_per_cluster = cluster_size / spdk_bs_get_page_size(bs);
5209 pages_per_payload = pages_per_cluster * 5;
5210
5211 payload_size = cluster_size * 5;
5212
5213 payload_read = malloc(payload_size);
5214 SPDK_CU_ASSERT_FATAL(payload_read != NULL);
5215
5216 payload_write = malloc(payload_size);
5217 SPDK_CU_ASSERT_FATAL(payload_write != NULL);
5218
5219 payload_clone = malloc(payload_size);
5220 SPDK_CU_ASSERT_FATAL(payload_clone != NULL);
5221
5222 channel = spdk_bs_alloc_io_channel(bs);
5223 SPDK_CU_ASSERT_FATAL(channel != NULL);
5224
5225 /* Create blob */
5226 spdk_blob_opts_init(&opts);
5227 opts.thin_provision = true;
5228 opts.num_clusters = 5;
5229
5230 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
5231 poll_threads();
5232 CU_ASSERT(g_bserrno == 0);
5233 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5234 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
5235 blobid = g_blobid;
5236
5237 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
5238 poll_threads();
5239 CU_ASSERT(g_bserrno == 0);
5240 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5241 blob = g_blob;
5242
5243 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5);
5244
5245 /* 1) Initial read should return zeroed payload */
5246 memset(payload_read, 0xFF, payload_size);
5247 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload,
5248 blob_op_complete, NULL);
5249 poll_threads();
5250 CU_ASSERT(g_bserrno == 0);
5251 CU_ASSERT(spdk_mem_all_zero(payload_read, payload_size));
5252
5253 /* Fill whole blob with a pattern, except last cluster (to be sure it
5254 * isn't allocated) */
5255 memset(payload_write, 0xE5, payload_size - cluster_size);
5256 spdk_blob_io_write(blob, channel, payload_write, 0, pages_per_payload -
5257 pages_per_cluster, blob_op_complete, NULL);
5258 poll_threads();
5259 CU_ASSERT(g_bserrno == 0);
5260 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));
5261
5262 /* 2) Create snapshot from blob (first level) */
5263 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
5264 poll_threads();
5265 CU_ASSERT(g_bserrno == 0);
5266 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5267 snapshotid = g_blobid;
5268
5269 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
5270 poll_threads();
5271 CU_ASSERT(g_bserrno == 0);
5272 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5273 snapshot = g_blob;
5274 CU_ASSERT(snapshot->data_ro == true)
5275 CU_ASSERT(snapshot->md_ro == true)
5276
5277 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5)
5278
5279 /* Write every second cluster with a pattern.
5280 *
5281 * Last cluster shouldn't be written, to be sure that snapshot nor clone
5282 * doesn't allocate it.
5283 *
5284 * payload_clone stores expected result on "blob" read at the time and
5285 * is used only to check data consistency on clone before and after
5286 * inflation. Initially we fill it with a backing snapshots pattern
5287 * used before.
5288 */
5289 memset(payload_clone, 0xE5, payload_size - cluster_size);
5290 memset(payload_clone + payload_size - cluster_size, 0x00, cluster_size);
5291 memset(payload_write, 0xAA, payload_size);
5292 for (i = 1; i < 5; i += 2) {
5293 spdk_blob_io_write(blob, channel, payload_write, i * pages_per_cluster,
5294 pages_per_cluster, blob_op_complete, NULL);
5295 poll_threads();
5296 CU_ASSERT(g_bserrno == 0);
5297
5298 /* Update expected result */
5299 memcpy(payload_clone + (cluster_size * i), payload_write,
5300 cluster_size);
5301 }
5302 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));
5303
5304 /* Check data consistency on clone */
5305 memset(payload_read, 0xFF, payload_size);
5306 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload,
5307 blob_op_complete, NULL);
5308 poll_threads();
5309 CU_ASSERT(g_bserrno == 0);
5310 CU_ASSERT(memcmp(payload_clone, payload_read, payload_size) == 0);
5311
5312 /* 3) Create second levels snapshot from blob */
5313 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
5314 poll_threads();
5315 CU_ASSERT(g_bserrno == 0);
5316 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5317 snapshot2id = g_blobid;
5318
5319 spdk_bs_open_blob(bs, snapshot2id, blob_op_with_handle_complete, NULL);
5320 poll_threads();
5321 CU_ASSERT(g_bserrno == 0);
5322 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5323 snapshot2 = g_blob;
5324 CU_ASSERT(snapshot2->data_ro == true)
5325 CU_ASSERT(snapshot2->md_ro == true)
5326
5327 CU_ASSERT(spdk_blob_get_num_clusters(snapshot2) == 5)
5328
5329 CU_ASSERT(snapshot2->parent_id == snapshotid);
5330
5331 /* Write one cluster on the top level blob. This cluster (1) covers
5332 * already allocated cluster in the snapshot2, so shouldn't be inflated
5333 * at all */
5334 spdk_blob_io_write(blob, channel, payload_write, pages_per_cluster,
5335 pages_per_cluster, blob_op_complete, NULL);
5336 poll_threads();
5337 CU_ASSERT(g_bserrno == 0);
5338
5339 /* Update expected result */
5340 memcpy(payload_clone + cluster_size, payload_write, cluster_size);
5341
5342 /* Check data consistency on clone */
5343 memset(payload_read, 0xFF, payload_size);
5344 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload,
5345 blob_op_complete, NULL);
5346 poll_threads();
5347 CU_ASSERT(g_bserrno == 0);
5348 CU_ASSERT(memcmp(payload_clone, payload_read, payload_size) == 0);
5349
5350
5351 /* Close all blobs */
5352 spdk_blob_close(blob, blob_op_complete, NULL);
5353 poll_threads();
5354 CU_ASSERT(g_bserrno == 0);
5355
5356 spdk_blob_close(snapshot2, blob_op_complete, NULL);
5357 poll_threads();
5358 CU_ASSERT(g_bserrno == 0);
5359
5360 spdk_blob_close(snapshot, blob_op_complete, NULL);
5361 poll_threads();
5362 CU_ASSERT(g_bserrno == 0);
5363
5364 /* Check snapshot-clone relations */
5365 count = 2;
5366 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid, ids, &count) == 0);
5367 CU_ASSERT(count == 1);
5368 CU_ASSERT(ids[0] == snapshot2id);
5369
5370 count = 2;
5371 CU_ASSERT(spdk_blob_get_clones(bs, snapshot2id, ids, &count) == 0);
5372 CU_ASSERT(count == 1);
5373 CU_ASSERT(ids[0] == blobid);
5374
5375 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshot2id);
5376
5377 free_clusters = spdk_bs_free_cluster_count(bs);
5378 if (!decouple_parent) {
5379 /* Do full blob inflation */
5380 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL);
5381 poll_threads();
5382 CU_ASSERT(g_bserrno == 0);
5383
5384 /* All clusters should be inflated (except one already allocated
5385 * in a top level blob) */
5386 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters - 4);
5387
5388 /* Check if relation tree updated correctly */
5389 count = 2;
5390 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid, ids, &count) == 0);
5391
5392 /* snapshotid have one clone */
5393 CU_ASSERT(count == 1);
5394 CU_ASSERT(ids[0] == snapshot2id);
5395
5396 /* snapshot2id have no clones */
5397 count = 2;
5398 CU_ASSERT(spdk_blob_get_clones(bs, snapshot2id, ids, &count) == 0);
5399 CU_ASSERT(count == 0);
5400
5401 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID);
5402 } else {
5403 /* Decouple parent of blob */
5404 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL);
5405 poll_threads();
5406 CU_ASSERT(g_bserrno == 0);
5407
5408 /* Only one cluster from a parent should be inflated (second one
5409 * is covered by a cluster written on a top level blob, and
5410 * already allocated) */
5411 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters - 1);
5412
5413 /* Check if relation tree updated correctly */
5414 count = 2;
5415 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid, ids, &count) == 0);
5416
5417 /* snapshotid have two clones now */
5418 CU_ASSERT(count == 2);
5419 CU_ASSERT(ids[0] == blobid || ids[1] == blobid);
5420 CU_ASSERT(ids[0] == snapshot2id || ids[1] == snapshot2id);
5421
5422 /* snapshot2id have no clones */
5423 count = 2;
5424 CU_ASSERT(spdk_blob_get_clones(bs, snapshot2id, ids, &count) == 0);
5425 CU_ASSERT(count == 0);
5426
5427 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid);
5428 }
5429
5430 /* Try to delete snapshot2 (should pass) */
5431 spdk_bs_delete_blob(bs, snapshot2id, blob_op_complete, NULL);
5432 poll_threads();
5433 CU_ASSERT(g_bserrno == 0);
5434
5435 /* Try to delete base snapshot (for decouple_parent should fail while
5436 * dependency still exists) */
5437 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
5438 poll_threads();
5439 CU_ASSERT(decouple_parent || g_bserrno == 0);
5440 CU_ASSERT(!decouple_parent || g_bserrno != 0);
5441
5442 /* Reopen blob after snapshot deletion */
5443 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
5444 poll_threads();
5445 CU_ASSERT(g_bserrno == 0);
5446 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5447 blob = g_blob;
5448
5449 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5);
5450
5451 /* Check data consistency on inflated blob */
5452 memset(payload_read, 0xFF, payload_size);
5453 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload,
5454 blob_op_complete, NULL);
5455 poll_threads();
5456 CU_ASSERT(g_bserrno == 0);
5457 CU_ASSERT(memcmp(payload_clone, payload_read, payload_size) == 0);
5458
5459 spdk_blob_close(blob, blob_op_complete, NULL);
5460 poll_threads();
5461 CU_ASSERT(g_bserrno == 0);
5462
5463 spdk_bs_free_io_channel(channel);
5464 poll_threads();
5465
5466 /* Unload the blob store */
5467 spdk_bs_unload(g_bs, bs_op_complete, NULL);
5468 poll_threads();
5469 CU_ASSERT(g_bserrno == 0);
5470 g_bs = NULL;
5471 g_blob = NULL;
5472 g_blobid = 0;
5473
5474 free(payload_read);
5475 free(payload_write);
5476 free(payload_clone);
5477 }
5478
5479 static void
5480 blob_inflate_rw(void)
5481 {
5482 _blob_inflate_rw(false);
5483 _blob_inflate_rw(true);
5484 }
5485
5486 /**
5487 * Snapshot-clones relation test
5488 *
5489 * snapshot
5490 * |
5491 * +-----+-----+
5492 * | |
5493 * blob(ro) snapshot2
5494 * | |
5495 * clone2 clone
5496 */
5497 static void
5498 blob_relations(void)
5499 {
5500 struct spdk_blob_store *bs;
5501 struct spdk_bs_dev *dev;
5502 struct spdk_bs_opts bs_opts;
5503 struct spdk_blob_opts opts;
5504 struct spdk_blob *blob, *snapshot, *snapshot2, *clone, *clone2;
5505 spdk_blob_id blobid, cloneid, snapshotid, cloneid2, snapshotid2;
5506 int rc;
5507 size_t count;
5508 spdk_blob_id ids[10] = {};
5509
5510 dev = init_dev();
5511 spdk_bs_opts_init(&bs_opts);
5512 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE");
5513
5514 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL);
5515 poll_threads();
5516 CU_ASSERT(g_bserrno == 0);
5517 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
5518 bs = g_bs;
5519
5520 /* 1. Create blob with 10 clusters */
5521
5522 spdk_blob_opts_init(&opts);
5523 opts.num_clusters = 10;
5524
5525 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
5526 poll_threads();
5527 CU_ASSERT(g_bserrno == 0);
5528 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5529 blobid = g_blobid;
5530
5531 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
5532 poll_threads();
5533 CU_ASSERT(g_bserrno == 0);
5534 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5535 blob = g_blob;
5536
5537 CU_ASSERT(!spdk_blob_is_read_only(blob));
5538 CU_ASSERT(!spdk_blob_is_snapshot(blob));
5539 CU_ASSERT(!spdk_blob_is_clone(blob));
5540 CU_ASSERT(!spdk_blob_is_thin_provisioned(blob));
5541
5542 /* blob should not have underlying snapshot nor clones */
5543 CU_ASSERT(blob->parent_id == SPDK_BLOBID_INVALID);
5544 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID);
5545 count = SPDK_COUNTOF(ids);
5546 rc = spdk_blob_get_clones(bs, blobid, ids, &count);
5547 CU_ASSERT(rc == 0);
5548 CU_ASSERT(count == 0);
5549
5550
5551 /* 2. Create snapshot */
5552
5553 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
5554 poll_threads();
5555 CU_ASSERT(g_bserrno == 0);
5556 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5557 snapshotid = g_blobid;
5558
5559 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
5560 poll_threads();
5561 CU_ASSERT(g_bserrno == 0);
5562 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5563 snapshot = g_blob;
5564
5565 CU_ASSERT(spdk_blob_is_read_only(snapshot));
5566 CU_ASSERT(spdk_blob_is_snapshot(snapshot));
5567 CU_ASSERT(!spdk_blob_is_clone(snapshot));
5568 CU_ASSERT(snapshot->parent_id == SPDK_BLOBID_INVALID);
5569 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid) == SPDK_BLOBID_INVALID);
5570
5571 /* Check if original blob is converted to the clone of snapshot */
5572 CU_ASSERT(!spdk_blob_is_read_only(blob));
5573 CU_ASSERT(!spdk_blob_is_snapshot(blob));
5574 CU_ASSERT(spdk_blob_is_clone(blob));
5575 CU_ASSERT(spdk_blob_is_thin_provisioned(blob));
5576 CU_ASSERT(blob->parent_id == snapshotid);
5577 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid);
5578
5579 count = SPDK_COUNTOF(ids);
5580 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count);
5581 CU_ASSERT(rc == 0);
5582 CU_ASSERT(count == 1);
5583 CU_ASSERT(ids[0] == blobid);
5584
5585
5586 /* 3. Create clone from snapshot */
5587
5588 spdk_bs_create_clone(bs, snapshotid, NULL, blob_op_with_id_complete, NULL);
5589 poll_threads();
5590 CU_ASSERT(g_bserrno == 0);
5591 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5592 cloneid = g_blobid;
5593
5594 spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL);
5595 poll_threads();
5596 CU_ASSERT(g_bserrno == 0);
5597 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5598 clone = g_blob;
5599
5600 CU_ASSERT(!spdk_blob_is_read_only(clone));
5601 CU_ASSERT(!spdk_blob_is_snapshot(clone));
5602 CU_ASSERT(spdk_blob_is_clone(clone));
5603 CU_ASSERT(spdk_blob_is_thin_provisioned(clone));
5604 CU_ASSERT(clone->parent_id == snapshotid);
5605 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid);
5606
5607 count = SPDK_COUNTOF(ids);
5608 rc = spdk_blob_get_clones(bs, cloneid, ids, &count);
5609 CU_ASSERT(rc == 0);
5610 CU_ASSERT(count == 0);
5611
5612 /* Check if clone is on the snapshot's list */
5613 count = SPDK_COUNTOF(ids);
5614 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count);
5615 CU_ASSERT(rc == 0);
5616 CU_ASSERT(ids[0] == blobid || ids[1] == blobid);
5617 CU_ASSERT(ids[0] == cloneid || ids[1] == cloneid);
5618
5619
5620 /* 4. Create snapshot of the clone */
5621
5622 spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL);
5623 poll_threads();
5624 CU_ASSERT(g_bserrno == 0);
5625 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5626 snapshotid2 = g_blobid;
5627
5628 spdk_bs_open_blob(bs, snapshotid2, blob_op_with_handle_complete, NULL);
5629 poll_threads();
5630 CU_ASSERT(g_bserrno == 0);
5631 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5632 snapshot2 = g_blob;
5633
5634 CU_ASSERT(spdk_blob_is_read_only(snapshot2));
5635 CU_ASSERT(spdk_blob_is_snapshot(snapshot2));
5636 CU_ASSERT(spdk_blob_is_clone(snapshot2));
5637 CU_ASSERT(snapshot2->parent_id == snapshotid);
5638 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid);
5639
5640 /* Check if clone is converted to the clone of snapshot2 and snapshot2
5641 * is a child of snapshot */
5642 CU_ASSERT(!spdk_blob_is_read_only(clone));
5643 CU_ASSERT(!spdk_blob_is_snapshot(clone));
5644 CU_ASSERT(spdk_blob_is_clone(clone));
5645 CU_ASSERT(spdk_blob_is_thin_provisioned(clone));
5646 CU_ASSERT(clone->parent_id == snapshotid2);
5647 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2);
5648
5649 count = SPDK_COUNTOF(ids);
5650 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
5651 CU_ASSERT(rc == 0);
5652 CU_ASSERT(count == 1);
5653 CU_ASSERT(ids[0] == cloneid);
5654
5655
5656 /* 5. Try to create clone from read only blob */
5657
5658 /* Mark blob as read only */
5659 spdk_blob_set_read_only(blob);
5660 spdk_blob_sync_md(blob, blob_op_complete, NULL);
5661 poll_threads();
5662 CU_ASSERT(g_bserrno == 0);
5663
5664 /* Check if previously created blob is read only clone */
5665 CU_ASSERT(spdk_blob_is_read_only(blob));
5666 CU_ASSERT(!spdk_blob_is_snapshot(blob));
5667 CU_ASSERT(spdk_blob_is_clone(blob));
5668 CU_ASSERT(spdk_blob_is_thin_provisioned(blob));
5669
5670 /* Create clone from read only blob */
5671 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL);
5672 poll_threads();
5673 CU_ASSERT(g_bserrno == 0);
5674 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
5675 cloneid2 = g_blobid;
5676
5677 spdk_bs_open_blob(bs, cloneid2, blob_op_with_handle_complete, NULL);
5678 poll_threads();
5679 CU_ASSERT(g_bserrno == 0);
5680 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
5681 clone2 = g_blob;
5682
5683 CU_ASSERT(!spdk_blob_is_read_only(clone2));
5684 CU_ASSERT(!spdk_blob_is_snapshot(clone2));
5685 CU_ASSERT(spdk_blob_is_clone(clone2));
5686 CU_ASSERT(spdk_blob_is_thin_provisioned(clone2));
5687
5688 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid);
5689
5690 count = SPDK_COUNTOF(ids);
5691 rc = spdk_blob_get_clones(bs, blobid, ids, &count);
5692 CU_ASSERT(rc == 0);
5693
5694 CU_ASSERT(count == 1);
5695 CU_ASSERT(ids[0] == cloneid2);
5696
5697 /* Close blobs */
5698
5699 spdk_blob_close(clone2, blob_op_complete, NULL);
5700 poll_threads();
5701 CU_ASSERT(g_bserrno == 0);
5702
5703 spdk_blob_close(blob, blob_op_complete, NULL);
5704 poll_threads();
5705 CU_ASSERT(g_bserrno == 0);
5706
5707 spdk_blob_close(clone, blob_op_complete, NULL);
5708 poll_threads();
5709 CU_ASSERT(g_bserrno == 0);
5710
5711 spdk_blob_close(snapshot, blob_op_complete, NULL);
5712 poll_threads();
5713 CU_ASSERT(g_bserrno == 0);
5714
5715 spdk_blob_close(snapshot2, blob_op_complete, NULL);
5716 poll_threads();
5717 CU_ASSERT(g_bserrno == 0);
5718
5719 /* Try to delete snapshot with created clones */
5720 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
5721 poll_threads();
5722 CU_ASSERT(g_bserrno != 0);
5723
5724 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
5725 poll_threads();
5726 CU_ASSERT(g_bserrno != 0);
5727
5728 spdk_bs_unload(bs, bs_op_complete, NULL);
5729 poll_threads();
5730 CU_ASSERT(g_bserrno == 0);
5731 g_bs = NULL;
5732
5733 /* Load an existing blob store */
5734 dev = init_dev();
5735 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE");
5736
5737 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
5738 poll_threads();
5739 CU_ASSERT(g_bserrno == 0);
5740 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
5741 bs = g_bs;
5742
5743
5744 /* NULL ids array should return number of clones in count */
5745 count = SPDK_COUNTOF(ids);
5746 rc = spdk_blob_get_clones(bs, snapshotid, NULL, &count);
5747 CU_ASSERT(rc == -ENOMEM);
5748 CU_ASSERT(count == 2);
5749
5750 /* incorrect array size */
5751 count = 1;
5752 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count);
5753 CU_ASSERT(rc == -ENOMEM);
5754 CU_ASSERT(count == 2);
5755
5756
5757 /* Verify structure of loaded blob store */
5758
5759 /* snapshot */
5760 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid) == SPDK_BLOBID_INVALID);
5761
5762 count = SPDK_COUNTOF(ids);
5763 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count);
5764 CU_ASSERT(rc == 0);
5765 CU_ASSERT(count == 2);
5766 CU_ASSERT(ids[0] == blobid || ids[1] == blobid);
5767 CU_ASSERT(ids[0] == snapshotid2 || ids[1] == snapshotid2);
5768
5769 /* blob */
5770 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid);
5771 count = SPDK_COUNTOF(ids);
5772 rc = spdk_blob_get_clones(bs, blobid, ids, &count);
5773 CU_ASSERT(rc == 0);
5774 CU_ASSERT(count == 1);
5775 CU_ASSERT(ids[0] == cloneid2);
5776
5777 /* clone */
5778 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2);
5779 count = SPDK_COUNTOF(ids);
5780 rc = spdk_blob_get_clones(bs, cloneid, ids, &count);
5781 CU_ASSERT(rc == 0);
5782 CU_ASSERT(count == 0);
5783
5784 /* snapshot2 */
5785 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid);
5786 count = SPDK_COUNTOF(ids);
5787 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
5788 CU_ASSERT(rc == 0);
5789 CU_ASSERT(count == 1);
5790 CU_ASSERT(ids[0] == cloneid);
5791
5792 /* clone2 */
5793 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid);
5794 count = SPDK_COUNTOF(ids);
5795 rc = spdk_blob_get_clones(bs, cloneid2, ids, &count);
5796 CU_ASSERT(rc == 0);
5797 CU_ASSERT(count == 0);
5798
5799 /* Try to delete all blobs in the worse possible order */
5800
5801 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
5802 poll_threads();
5803 CU_ASSERT(g_bserrno != 0);
5804
5805 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
5806 poll_threads();
5807 CU_ASSERT(g_bserrno != 0);
5808
5809 spdk_bs_delete_blob(bs, cloneid, blob_op_complete, NULL);
5810 poll_threads();
5811 CU_ASSERT(g_bserrno == 0);
5812
5813 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
5814 poll_threads();
5815 CU_ASSERT(g_bserrno == 0);
5816
5817 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
5818 poll_threads();
5819 CU_ASSERT(g_bserrno != 0);
5820
5821 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
5822 poll_threads();
5823 CU_ASSERT(g_bserrno != 0);
5824
5825 spdk_bs_delete_blob(bs, cloneid2, blob_op_complete, NULL);
5826 poll_threads();
5827 CU_ASSERT(g_bserrno == 0);
5828
5829 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
5830 poll_threads();
5831 CU_ASSERT(g_bserrno == 0);
5832
5833 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
5834 poll_threads();
5835 CU_ASSERT(g_bserrno == 0);
5836
5837 spdk_bs_unload(bs, bs_op_complete, NULL);
5838 poll_threads();
5839 CU_ASSERT(g_bserrno == 0);
5840
5841 g_bs = NULL;
5842 }
5843
5844 static void
5845 test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
5846 {
5847 uint8_t payload_ff[64 * 512];
5848 uint8_t payload_aa[64 * 512];
5849 uint8_t payload_00[64 * 512];
5850 uint8_t *cluster0, *cluster1;
5851
5852 memset(payload_ff, 0xFF, sizeof(payload_ff));
5853 memset(payload_aa, 0xAA, sizeof(payload_aa));
5854 memset(payload_00, 0x00, sizeof(payload_00));
5855
5856 /* Try to perform I/O with io unit = 512 */
5857 spdk_blob_io_write(blob, channel, payload_ff, 0, 1, blob_op_complete, NULL);
5858 poll_threads();
5859 CU_ASSERT(g_bserrno == 0);
5860
5861 /* If thin provisioned is set cluster should be allocated now */
5862 SPDK_CU_ASSERT_FATAL(blob->active.clusters[0] != 0);
5863 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen];
5864
5865 /* Each character 0-F symbolizes single io_unit containing 512 bytes block filled with that character.
5866 * Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */
5867 /* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
5868 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
5869 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 31 * 512) == 0);
5870
5871 /* Verify write with offset on first page */
5872 spdk_blob_io_write(blob, channel, payload_ff, 2, 1, blob_op_complete, NULL);
5873 poll_threads();
5874 CU_ASSERT(g_bserrno == 0);
5875
5876 /* cluster0: [ F0F0 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
5877 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
5878 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
5879 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
5880 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
5881 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, 28 * 512) == 0);
5882
5883 /* Verify write with offset on first page */
5884 spdk_blob_io_write(blob, channel, payload_ff, 4, 4, blob_op_complete, NULL);
5885 poll_threads();
5886
5887 /* cluster0: [ F0F0 FFFF | 0000 0000 | 0000 0000 | 0000 0000 ] */
5888 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
5889 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
5890 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
5891 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
5892 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 4 * 512) == 0);
5893 CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, 24 * 512) == 0);
5894
5895 /* Verify write with offset on second page */
5896 spdk_blob_io_write(blob, channel, payload_ff, 8, 4, blob_op_complete, NULL);
5897 poll_threads();
5898
5899 /* cluster0: [ F0F0 FFFF | FFFF 0000 | 0000 0000 | 0000 0000 ] */
5900 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
5901 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
5902 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
5903 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
5904 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 8 * 512) == 0);
5905 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
5906
5907 /* Verify write across multiple pages */
5908 spdk_blob_io_write(blob, channel, payload_aa, 4, 8, blob_op_complete, NULL);
5909 poll_threads();
5910
5911 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 0000 ] */
5912 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
5913 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
5914 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
5915 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
5916 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
5917 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
5918
5919 /* Verify write across multiple clusters */
5920 spdk_blob_io_write(blob, channel, payload_ff, 28, 8, blob_op_complete, NULL);
5921 poll_threads();
5922
5923 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
5924 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];
5925
5926 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5927 * cluster1: [ FFFF 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
5928 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
5929 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
5930 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
5931 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
5932 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
5933 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
5934
5935 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
5936 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 28 * 512) == 0);
5937
5938 /* Verify write to second cluster */
5939 spdk_blob_io_write(blob, channel, payload_ff, 32 + 12, 2, blob_op_complete, NULL);
5940 poll_threads();
5941
5942 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
5943 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];
5944
5945 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5946 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] */
5947 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
5948 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
5949 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
5950 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
5951 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
5952 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
5953
5954 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
5955 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 8 * 512) == 0);
5956 CU_ASSERT(memcmp(cluster1 + 12 * 512, payload_ff, 2 * 512) == 0);
5957 CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, 18 * 512) == 0);
5958 }
5959
5960 static void
5961 test_io_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
5962 {
5963 uint8_t payload_read[64 * 512];
5964 uint8_t payload_ff[64 * 512];
5965 uint8_t payload_aa[64 * 512];
5966 uint8_t payload_00[64 * 512];
5967
5968 memset(payload_ff, 0xFF, sizeof(payload_ff));
5969 memset(payload_aa, 0xAA, sizeof(payload_aa));
5970 memset(payload_00, 0x00, sizeof(payload_00));
5971
5972 /* Read only first io unit */
5973 /* cluster0: [ (F)0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5974 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
5975 * payload_read: F000 0000 | 0000 0000 ... */
5976 memset(payload_read, 0x00, sizeof(payload_read));
5977 spdk_blob_io_read(blob, channel, payload_read, 0, 1, blob_op_complete, NULL);
5978 poll_threads();
5979 CU_ASSERT(g_bserrno == 0);
5980 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
5981 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 31 * 512) == 0);
5982
5983 /* Read four io_units starting from offset = 2
5984 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5985 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
5986 * payload_read: F0AA 0000 | 0000 0000 ... */
5987
5988 memset(payload_read, 0x00, sizeof(payload_read));
5989 spdk_blob_io_read(blob, channel, payload_read, 2, 4, blob_op_complete, NULL);
5990 poll_threads();
5991 CU_ASSERT(g_bserrno == 0);
5992
5993 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
5994 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0);
5995 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_aa, 512) == 0);
5996 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_aa, 512) == 0);
5997 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
5998
5999 /* Read eight io_units across multiple pages
6000 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6001 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6002 * payload_read: AAAA AAAA | 0000 0000 ... */
6003 memset(payload_read, 0x00, sizeof(payload_read));
6004 spdk_blob_io_read(blob, channel, payload_read, 4, 8, blob_op_complete, NULL);
6005 poll_threads();
6006 CU_ASSERT(g_bserrno == 0);
6007
6008 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_aa, 8 * 512) == 0);
6009 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
6010
6011 /* Read eight io_units across multiple clusters
6012 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ]
6013 * cluster1: [ FFFF) 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6014 * payload_read: FFFF FFFF | 0000 0000 ... */
6015 memset(payload_read, 0x00, sizeof(payload_read));
6016 spdk_blob_io_read(blob, channel, payload_read, 28, 8, blob_op_complete, NULL);
6017 poll_threads();
6018 CU_ASSERT(g_bserrno == 0);
6019
6020 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 8 * 512) == 0);
6021 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
6022
6023 /* Read four io_units from second cluster
6024 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6025 * cluster1: [ FFFF 0000 | 00(00 FF)00 | 0000 0000 | 0000 0000 ]
6026 * payload_read: 00FF 0000 | 0000 0000 ... */
6027 memset(payload_read, 0x00, sizeof(payload_read));
6028 spdk_blob_io_read(blob, channel, payload_read, 32 + 10, 4, blob_op_complete, NULL);
6029 poll_threads();
6030 CU_ASSERT(g_bserrno == 0);
6031
6032 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_00, 2 * 512) == 0);
6033 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 2 * 512) == 0);
6034 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
6035
6036 /* Read second cluster
6037 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6038 * cluster1: [ (FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ]
6039 * payload_read: FFFF 0000 | 0000 FF00 ... */
6040 memset(payload_read, 0x00, sizeof(payload_read));
6041 spdk_blob_io_read(blob, channel, payload_read, 32, 32, blob_op_complete, NULL);
6042 poll_threads();
6043 CU_ASSERT(g_bserrno == 0);
6044 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 4 * 512) == 0);
6045 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 8 * 512) == 0);
6046 CU_ASSERT(memcmp(payload_read + 12 * 512, payload_ff, 2 * 512) == 0);
6047 CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, 18 * 512) == 0);
6048
6049 /* Read whole two clusters
6050 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6051 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] */
6052 memset(payload_read, 0x00, sizeof(payload_read));
6053 spdk_blob_io_read(blob, channel, payload_read, 0, 64, blob_op_complete, NULL);
6054 poll_threads();
6055 CU_ASSERT(g_bserrno == 0);
6056
6057 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
6058 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0);
6059 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 512) == 0);
6060 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_00, 512) == 0);
6061 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_aa, 8 * 512) == 0);
6062 CU_ASSERT(memcmp(payload_read + 28 * 512, payload_ff, 4 * 512) == 0);
6063
6064 CU_ASSERT(memcmp(payload_read + (32 + 0) * 512, payload_ff, 4 * 512) == 0);
6065 CU_ASSERT(memcmp(payload_read + (32 + 4) * 512, payload_00, 8 * 512) == 0);
6066 CU_ASSERT(memcmp(payload_read + (32 + 12) * 512, payload_ff, 2 * 512) == 0);
6067 CU_ASSERT(memcmp(payload_read + (32 + 14) * 512, payload_00, 18 * 512) == 0);
6068 }
6069
6070
6071 static void
6072 test_io_unmap(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
6073 {
6074 uint8_t payload_ff[64 * 512];
6075 uint8_t payload_aa[64 * 512];
6076 uint8_t payload_00[64 * 512];
6077 uint8_t *cluster0, *cluster1;
6078
6079 memset(payload_ff, 0xFF, sizeof(payload_ff));
6080 memset(payload_aa, 0xAA, sizeof(payload_aa));
6081 memset(payload_00, 0x00, sizeof(payload_00));
6082
6083 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen];
6084 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];
6085
6086 /* Unmap */
6087 spdk_blob_io_unmap(blob, channel, 0, 64, blob_op_complete, NULL);
6088 poll_threads();
6089
6090 CU_ASSERT(g_bserrno == 0);
6091
6092 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, 32 * 512) == 0);
6093 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, 32 * 512) == 0);
6094 }
6095
6096 static void
6097 test_io_zeroes(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
6098 {
6099 uint8_t payload_ff[64 * 512];
6100 uint8_t payload_aa[64 * 512];
6101 uint8_t payload_00[64 * 512];
6102 uint8_t *cluster0, *cluster1;
6103
6104 memset(payload_ff, 0xFF, sizeof(payload_ff));
6105 memset(payload_aa, 0xAA, sizeof(payload_aa));
6106 memset(payload_00, 0x00, sizeof(payload_00));
6107
6108 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen];
6109 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];
6110
6111 /* Write zeroes */
6112 spdk_blob_io_write_zeroes(blob, channel, 0, 64, blob_op_complete, NULL);
6113 poll_threads();
6114
6115 CU_ASSERT(g_bserrno == 0);
6116
6117 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, 32 * 512) == 0);
6118 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, 32 * 512) == 0);
6119 }
6120
6121
6122 static void
6123 test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
6124 {
6125 uint8_t payload_ff[64 * 512];
6126 uint8_t payload_aa[64 * 512];
6127 uint8_t payload_00[64 * 512];
6128 uint8_t *cluster0, *cluster1;
6129 struct iovec iov[4];
6130
6131 memset(payload_ff, 0xFF, sizeof(payload_ff));
6132 memset(payload_aa, 0xAA, sizeof(payload_aa));
6133 memset(payload_00, 0x00, sizeof(payload_00));
6134
6135 /* Try to perform I/O with io unit = 512 */
6136 iov[0].iov_base = payload_ff;
6137 iov[0].iov_len = 1 * 512;
6138 spdk_blob_io_writev(blob, channel, iov, 1, 0, 1, blob_op_complete, NULL);
6139 poll_threads();
6140 CU_ASSERT(g_bserrno == 0);
6141
6142 /* If thin provisioned is set cluster should be allocated now */
6143 SPDK_CU_ASSERT_FATAL(blob->active.clusters[0] != 0);
6144 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen];
6145
6146 /* Each character 0-F symbolizes single io_unit containing 512 bytes block filled with that character.
6147 * Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */
6148 /* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
6149 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
6150 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 31 * 512) == 0);
6151
6152 /* Verify write with offset on first page */
6153 iov[0].iov_base = payload_ff;
6154 iov[0].iov_len = 1 * 512;
6155 spdk_blob_io_writev(blob, channel, iov, 1, 2, 1, blob_op_complete, NULL);
6156 poll_threads();
6157 CU_ASSERT(g_bserrno == 0);
6158
6159 /* cluster0: [ F0F0 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
6160 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
6161 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
6162 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
6163 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
6164 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, 28 * 512) == 0);
6165
6166 /* Verify write with offset on first page */
6167 iov[0].iov_base = payload_ff;
6168 iov[0].iov_len = 4 * 512;
6169 spdk_blob_io_writev(blob, channel, iov, 1, 4, 4, blob_op_complete, NULL);
6170 poll_threads();
6171
6172 /* cluster0: [ F0F0 FFFF | 0000 0000 | 0000 0000 | 0000 0000 ] */
6173 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
6174 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
6175 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
6176 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
6177 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 4 * 512) == 0);
6178 CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, 24 * 512) == 0);
6179
6180 /* Verify write with offset on second page */
6181 iov[0].iov_base = payload_ff;
6182 iov[0].iov_len = 4 * 512;
6183 spdk_blob_io_writev(blob, channel, iov, 1, 8, 4, blob_op_complete, NULL);
6184 poll_threads();
6185
6186 /* cluster0: [ F0F0 FFFF | FFFF 0000 | 0000 0000 | 0000 0000 ] */
6187 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
6188 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
6189 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
6190 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
6191 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 8 * 512) == 0);
6192 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
6193
6194 /* Verify write across multiple pages */
6195 iov[0].iov_base = payload_aa;
6196 iov[0].iov_len = 8 * 512;
6197 spdk_blob_io_writev(blob, channel, iov, 1, 4, 8, blob_op_complete, NULL);
6198 poll_threads();
6199
6200 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 0000 ] */
6201 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
6202 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
6203 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
6204 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
6205 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
6206 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0);
6207
6208 /* Verify write across multiple clusters */
6209
6210 iov[0].iov_base = payload_ff;
6211 iov[0].iov_len = 8 * 512;
6212 spdk_blob_io_writev(blob, channel, iov, 1, 28, 8, blob_op_complete, NULL);
6213 poll_threads();
6214
6215 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
6216 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];
6217
6218 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6219 * cluster1: [ FFFF 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
6220 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
6221 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
6222 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
6223 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
6224 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
6225 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 16 * 512) == 0);
6226 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
6227
6228 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
6229 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 28 * 512) == 0);
6230
6231 /* Verify write to second cluster */
6232
6233 iov[0].iov_base = payload_ff;
6234 iov[0].iov_len = 2 * 512;
6235 spdk_blob_io_writev(blob, channel, iov, 1, 32 + 12, 2, blob_op_complete, NULL);
6236 poll_threads();
6237
6238 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0);
6239 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen];
6240
6241 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6242 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] */
6243 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0);
6244 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0);
6245 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0);
6246 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0);
6247 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0);
6248 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0);
6249
6250 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0);
6251 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 8 * 512) == 0);
6252 CU_ASSERT(memcmp(cluster1 + 12 * 512, payload_ff, 2 * 512) == 0);
6253 CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, 18 * 512) == 0);
6254 }
6255
6256 static void
6257 test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel)
6258 {
6259 uint8_t payload_read[64 * 512];
6260 uint8_t payload_ff[64 * 512];
6261 uint8_t payload_aa[64 * 512];
6262 uint8_t payload_00[64 * 512];
6263 struct iovec iov[4];
6264
6265 memset(payload_ff, 0xFF, sizeof(payload_ff));
6266 memset(payload_aa, 0xAA, sizeof(payload_aa));
6267 memset(payload_00, 0x00, sizeof(payload_00));
6268
6269 /* Read only first io unit */
6270 /* cluster0: [ (F)0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6271 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6272 * payload_read: F000 0000 | 0000 0000 ... */
6273 memset(payload_read, 0x00, sizeof(payload_read));
6274 iov[0].iov_base = payload_read;
6275 iov[0].iov_len = 1 * 512;
6276 spdk_blob_io_readv(blob, channel, iov, 1, 0, 1, blob_op_complete, NULL);
6277 poll_threads();
6278
6279 CU_ASSERT(g_bserrno == 0);
6280 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
6281 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 31 * 512) == 0);
6282
6283 /* Read four io_units starting from offset = 2
6284 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6285 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6286 * payload_read: F0AA 0000 | 0000 0000 ... */
6287
6288 memset(payload_read, 0x00, sizeof(payload_read));
6289 iov[0].iov_base = payload_read;
6290 iov[0].iov_len = 4 * 512;
6291 spdk_blob_io_readv(blob, channel, iov, 1, 2, 4, blob_op_complete, NULL);
6292 poll_threads();
6293 CU_ASSERT(g_bserrno == 0);
6294
6295 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
6296 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0);
6297 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_aa, 512) == 0);
6298 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_aa, 512) == 0);
6299 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
6300
6301 /* Read eight io_units across multiple pages
6302 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6303 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6304 * payload_read: AAAA AAAA | 0000 0000 ... */
6305 memset(payload_read, 0x00, sizeof(payload_read));
6306 iov[0].iov_base = payload_read;
6307 iov[0].iov_len = 4 * 512;
6308 iov[1].iov_base = payload_read + 4 * 512;
6309 iov[1].iov_len = 4 * 512;
6310 spdk_blob_io_readv(blob, channel, iov, 2, 4, 8, blob_op_complete, NULL);
6311 poll_threads();
6312 CU_ASSERT(g_bserrno == 0);
6313
6314 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_aa, 8 * 512) == 0);
6315 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
6316
6317 /* Read eight io_units across multiple clusters
6318 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ]
6319 * cluster1: [ FFFF) 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6320 * payload_read: FFFF FFFF | 0000 0000 ... */
6321 memset(payload_read, 0x00, sizeof(payload_read));
6322 iov[0].iov_base = payload_read;
6323 iov[0].iov_len = 2 * 512;
6324 iov[1].iov_base = payload_read + 2 * 512;
6325 iov[1].iov_len = 2 * 512;
6326 iov[2].iov_base = payload_read + 4 * 512;
6327 iov[2].iov_len = 2 * 512;
6328 iov[3].iov_base = payload_read + 6 * 512;
6329 iov[3].iov_len = 2 * 512;
6330 spdk_blob_io_readv(blob, channel, iov, 4, 28, 8, blob_op_complete, NULL);
6331 poll_threads();
6332 CU_ASSERT(g_bserrno == 0);
6333
6334 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 8 * 512) == 0);
6335 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0);
6336
6337 /* Read four io_units from second cluster
6338 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6339 * cluster1: [ FFFF 0000 | 00(00 FF)00 | 0000 0000 | 0000 0000 ]
6340 * payload_read: 00FF 0000 | 0000 0000 ... */
6341 memset(payload_read, 0x00, sizeof(payload_read));
6342 iov[0].iov_base = payload_read;
6343 iov[0].iov_len = 1 * 512;
6344 iov[1].iov_base = payload_read + 1 * 512;
6345 iov[1].iov_len = 3 * 512;
6346 spdk_blob_io_readv(blob, channel, iov, 2, 32 + 10, 4, blob_op_complete, NULL);
6347 poll_threads();
6348 CU_ASSERT(g_bserrno == 0);
6349
6350 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_00, 2 * 512) == 0);
6351 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 2 * 512) == 0);
6352 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0);
6353
6354 /* Read second cluster
6355 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6356 * cluster1: [ (FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ]
6357 * payload_read: FFFF 0000 | 0000 FF00 ... */
6358 memset(payload_read, 0x00, sizeof(payload_read));
6359 iov[0].iov_base = payload_read;
6360 iov[0].iov_len = 1 * 512;
6361 iov[1].iov_base = payload_read + 1 * 512;
6362 iov[1].iov_len = 2 * 512;
6363 iov[2].iov_base = payload_read + 3 * 512;
6364 iov[2].iov_len = 4 * 512;
6365 iov[3].iov_base = payload_read + 7 * 512;
6366 iov[3].iov_len = 25 * 512;
6367 spdk_blob_io_readv(blob, channel, iov, 4, 32, 32, blob_op_complete, NULL);
6368 poll_threads();
6369 CU_ASSERT(g_bserrno == 0);
6370 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 4 * 512) == 0);
6371 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 8 * 512) == 0);
6372 CU_ASSERT(memcmp(payload_read + 12 * 512, payload_ff, 2 * 512) == 0);
6373 CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, 18 * 512) == 0);
6374
6375 /* Read whole two clusters
6376 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6377 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] */
6378 memset(payload_read, 0x00, sizeof(payload_read));
6379 iov[0].iov_base = payload_read;
6380 iov[0].iov_len = 1 * 512;
6381 iov[1].iov_base = payload_read + 1 * 512;
6382 iov[1].iov_len = 8 * 512;
6383 iov[2].iov_base = payload_read + 9 * 512;
6384 iov[2].iov_len = 16 * 512;
6385 iov[3].iov_base = payload_read + 25 * 512;
6386 iov[3].iov_len = 39 * 512;
6387 spdk_blob_io_readv(blob, channel, iov, 4, 0, 64, blob_op_complete, NULL);
6388 poll_threads();
6389 CU_ASSERT(g_bserrno == 0);
6390
6391 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0);
6392 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0);
6393 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 512) == 0);
6394 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_00, 512) == 0);
6395 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_aa, 8 * 512) == 0);
6396 CU_ASSERT(memcmp(payload_read + 28 * 512, payload_ff, 4 * 512) == 0);
6397
6398 CU_ASSERT(memcmp(payload_read + (32 + 0) * 512, payload_ff, 4 * 512) == 0);
6399 CU_ASSERT(memcmp(payload_read + (32 + 4) * 512, payload_00, 8 * 512) == 0);
6400 CU_ASSERT(memcmp(payload_read + (32 + 12) * 512, payload_ff, 2 * 512) == 0);
6401 CU_ASSERT(memcmp(payload_read + (32 + 14) * 512, payload_00, 18 * 512) == 0);
6402 }
6403
6404 static void
6405 blob_io_unit(void)
6406 {
6407 struct spdk_bs_opts bsopts;
6408 struct spdk_blob_opts opts;
6409 struct spdk_bs_dev *dev;
6410 struct spdk_blob *blob, *snapshot, *clone;
6411 spdk_blob_id blobid;
6412 struct spdk_io_channel *channel;
6413
6414 /* Create dev with 512 bytes io unit size */
6415
6416 spdk_bs_opts_init(&bsopts);
6417 bsopts.cluster_sz = SPDK_BS_PAGE_SIZE * 4; /* 8 * 4 = 32 io_unit */
6418 snprintf(bsopts.bstype.bstype, sizeof(bsopts.bstype.bstype), "TESTTYPE");
6419
6420 /* Try to initialize a new blob store with unsupported io_unit */
6421 dev = init_dev();
6422 dev->blocklen = 512;
6423 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen;
6424
6425 /* Initialize a new blob store */
6426 spdk_bs_init(dev, &bsopts, bs_op_with_handle_complete, NULL);
6427 poll_threads();
6428 CU_ASSERT(g_bserrno == 0);
6429 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
6430
6431 CU_ASSERT(spdk_bs_get_io_unit_size(g_bs) == 512);
6432 channel = spdk_bs_alloc_io_channel(g_bs);
6433
6434 /* Create thick provisioned blob */
6435 spdk_blob_opts_init(&opts);
6436 opts.thin_provision = false;
6437 opts.num_clusters = 32;
6438
6439 spdk_bs_create_blob_ext(g_bs, &opts, blob_op_with_id_complete, NULL);
6440 poll_threads();
6441
6442 CU_ASSERT(g_bserrno == 0);
6443 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
6444 blobid = g_blobid;
6445
6446 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
6447 poll_threads();
6448 CU_ASSERT(g_bserrno == 0);
6449 CU_ASSERT(g_blob != NULL);
6450 blob = g_blob;
6451
6452 test_io_write(dev, blob, channel);
6453 test_io_read(dev, blob, channel);
6454 test_io_zeroes(dev, blob, channel);
6455
6456 test_iov_write(dev, blob, channel);
6457 test_iov_read(dev, blob, channel);
6458
6459 test_io_unmap(dev, blob, channel);
6460
6461 spdk_blob_close(blob, blob_op_complete, NULL);
6462 poll_threads();
6463 CU_ASSERT(g_bserrno == 0);
6464 blob = NULL;
6465 g_blob = NULL;
6466
6467 /* Create thin provisioned blob */
6468
6469 spdk_blob_opts_init(&opts);
6470 opts.thin_provision = true;
6471 opts.num_clusters = 32;
6472
6473 spdk_bs_create_blob_ext(g_bs, &opts, blob_op_with_id_complete, NULL);
6474 poll_threads();
6475 CU_ASSERT(g_bserrno == 0);
6476 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
6477 blobid = g_blobid;
6478
6479 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
6480 poll_threads();
6481 CU_ASSERT(g_bserrno == 0);
6482 CU_ASSERT(g_blob != NULL);
6483 blob = g_blob;
6484
6485 test_io_write(dev, blob, channel);
6486 test_io_read(dev, blob, channel);
6487
6488 test_io_zeroes(dev, blob, channel);
6489
6490 test_iov_write(dev, blob, channel);
6491 test_iov_read(dev, blob, channel);
6492
6493 /* Create snapshot */
6494
6495 spdk_bs_create_snapshot(g_bs, blobid, NULL, blob_op_with_id_complete, NULL);
6496 poll_threads();
6497 CU_ASSERT(g_bserrno == 0);
6498 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
6499 blobid = g_blobid;
6500
6501 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
6502 poll_threads();
6503 CU_ASSERT(g_bserrno == 0);
6504 CU_ASSERT(g_blob != NULL);
6505 snapshot = g_blob;
6506
6507 spdk_bs_create_clone(g_bs, blobid, NULL, blob_op_with_id_complete, NULL);
6508 poll_threads();
6509 CU_ASSERT(g_bserrno == 0);
6510 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
6511 blobid = g_blobid;
6512
6513 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
6514 poll_threads();
6515 CU_ASSERT(g_bserrno == 0);
6516 CU_ASSERT(g_blob != NULL);
6517 clone = g_blob;
6518
6519 test_io_read(dev, blob, channel);
6520 test_io_read(dev, snapshot, channel);
6521 test_io_read(dev, clone, channel);
6522
6523 test_iov_read(dev, blob, channel);
6524 test_iov_read(dev, snapshot, channel);
6525 test_iov_read(dev, clone, channel);
6526
6527 /* Inflate clone */
6528
6529 spdk_bs_inflate_blob(g_bs, channel, blobid, blob_op_complete, NULL);
6530 poll_threads();
6531
6532 CU_ASSERT(g_bserrno == 0);
6533
6534 test_io_read(dev, clone, channel);
6535
6536 test_io_unmap(dev, clone, channel);
6537
6538 test_iov_write(dev, clone, channel);
6539 test_iov_read(dev, clone, channel);
6540
6541 spdk_blob_close(blob, blob_op_complete, NULL);
6542 spdk_blob_close(snapshot, blob_op_complete, NULL);
6543 spdk_blob_close(clone, blob_op_complete, NULL);
6544 poll_threads();
6545 CU_ASSERT(g_bserrno == 0);
6546 blob = NULL;
6547 g_blob = NULL;
6548
6549 /* Unload the blob store */
6550 spdk_bs_unload(g_bs, bs_op_complete, NULL);
6551 poll_threads();
6552 CU_ASSERT(g_bserrno == 0);
6553 g_bs = NULL;
6554 g_blob = NULL;
6555 g_blobid = 0;
6556 }
6557
6558 static void
6559 blob_io_unit_compatiblity(void)
6560 {
6561 struct spdk_bs_opts bsopts;
6562 struct spdk_bs_dev *dev;
6563 struct spdk_bs_super_block *super;
6564
6565 /* Create dev with 512 bytes io unit size */
6566
6567 spdk_bs_opts_init(&bsopts);
6568 bsopts.cluster_sz = SPDK_BS_PAGE_SIZE * 4; /* 8 * 4 = 32 io_unit */
6569 snprintf(bsopts.bstype.bstype, sizeof(bsopts.bstype.bstype), "TESTTYPE");
6570
6571 /* Try to initialize a new blob store with unsupported io_unit */
6572 dev = init_dev();
6573 dev->blocklen = 512;
6574 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen;
6575
6576 /* Initialize a new blob store */
6577 spdk_bs_init(dev, &bsopts, bs_op_with_handle_complete, NULL);
6578 poll_threads();
6579 CU_ASSERT(g_bserrno == 0);
6580 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
6581
6582 CU_ASSERT(spdk_bs_get_io_unit_size(g_bs) == 512);
6583
6584 /* Unload the blob store */
6585 spdk_bs_unload(g_bs, bs_op_complete, NULL);
6586 poll_threads();
6587 CU_ASSERT(g_bserrno == 0);
6588
6589 /* Modify super block to behave like older version.
6590 * Check if loaded io unit size equals SPDK_BS_PAGE_SIZE */
6591 super = (struct spdk_bs_super_block *)&g_dev_buffer[0];
6592 super->io_unit_size = 0;
6593 super->crc = _spdk_blob_md_page_calc_crc(super);
6594
6595 dev = init_dev();
6596 dev->blocklen = 512;
6597 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen;
6598
6599 spdk_bs_load(dev, &bsopts, bs_op_with_handle_complete, NULL);
6600 poll_threads();
6601 CU_ASSERT(g_bserrno == 0);
6602 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
6603
6604 CU_ASSERT(spdk_bs_get_io_unit_size(g_bs) == SPDK_BS_PAGE_SIZE);
6605
6606 /* Unload the blob store */
6607 spdk_bs_unload(g_bs, bs_op_complete, NULL);
6608 poll_threads();
6609 CU_ASSERT(g_bserrno == 0);
6610
6611 g_bs = NULL;
6612 g_blob = NULL;
6613 g_blobid = 0;
6614 }
6615
6616 static void
6617 blob_simultaneous_operations(void)
6618 {
6619 struct spdk_blob_store *bs;
6620 struct spdk_bs_dev *dev;
6621 struct spdk_blob_opts opts;
6622 struct spdk_blob *blob, *snapshot;
6623 spdk_blob_id blobid, snapshotid;
6624 struct spdk_io_channel *channel;
6625
6626 dev = init_dev();
6627
6628 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
6629 poll_threads();
6630 CU_ASSERT(g_bserrno == 0);
6631 SPDK_CU_ASSERT_FATAL(g_bs != NULL);
6632 bs = g_bs;
6633
6634 channel = spdk_bs_alloc_io_channel(bs);
6635 SPDK_CU_ASSERT_FATAL(channel != NULL);
6636
6637 spdk_blob_opts_init(&opts);
6638 opts.num_clusters = 10;
6639
6640 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
6641 poll_threads();
6642 CU_ASSERT(g_bserrno == 0);
6643 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
6644 blobid = g_blobid;
6645
6646 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
6647 poll_threads();
6648 CU_ASSERT(g_bserrno == 0);
6649 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
6650 blob = g_blob;
6651
6652 /* Create snapshot and try to remove blob in the same time:
6653 * - snapshot should be created successfully
6654 * - delete operation should fail w -EBUSY */
6655 CU_ASSERT(blob->locked_operation_in_progress == false);
6656 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
6657 CU_ASSERT(blob->locked_operation_in_progress == true);
6658 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
6659 CU_ASSERT(blob->locked_operation_in_progress == true);
6660 /* Deletion failure */
6661 CU_ASSERT(g_bserrno == -EBUSY);
6662 poll_threads();
6663 CU_ASSERT(blob->locked_operation_in_progress == false);
6664 /* Snapshot creation success */
6665 CU_ASSERT(g_bserrno == 0);
6666 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
6667
6668 snapshotid = g_blobid;
6669
6670 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
6671 poll_threads();
6672 CU_ASSERT(g_bserrno == 0);
6673 SPDK_CU_ASSERT_FATAL(g_blob != NULL);
6674 snapshot = g_blob;
6675
6676 /* Inflate blob and try to remove blob in the same time:
6677 * - blob should be inflated successfully
6678 * - delete operation should fail w -EBUSY */
6679 CU_ASSERT(blob->locked_operation_in_progress == false);
6680 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL);
6681 CU_ASSERT(blob->locked_operation_in_progress == true);
6682 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
6683 CU_ASSERT(blob->locked_operation_in_progress == true);
6684 /* Deletion failure */
6685 CU_ASSERT(g_bserrno == -EBUSY);
6686 poll_threads();
6687 CU_ASSERT(blob->locked_operation_in_progress == false);
6688 /* Inflation success */
6689 CU_ASSERT(g_bserrno == 0);
6690
6691 /* Clone snapshot and try to remove snapshot in the same time:
6692 * - snapshot should be cloned successfully
6693 * - delete operation should fail w -EBUSY */
6694 CU_ASSERT(blob->locked_operation_in_progress == false);
6695 spdk_bs_create_clone(bs, snapshotid, NULL, blob_op_with_id_complete, NULL);
6696 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
6697 /* Deletion failure */
6698 CU_ASSERT(g_bserrno == -EBUSY);
6699 poll_threads();
6700 CU_ASSERT(blob->locked_operation_in_progress == false);
6701 /* Clone created */
6702 CU_ASSERT(g_bserrno == 0);
6703
6704 /* Resize blob and try to remove blob in the same time:
6705 * - blob should be resized successfully
6706 * - delete operation should fail w -EBUSY */
6707 CU_ASSERT(blob->locked_operation_in_progress == false);
6708 spdk_blob_resize(blob, 50, blob_op_complete, NULL);
6709 CU_ASSERT(blob->locked_operation_in_progress == true);
6710 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
6711 CU_ASSERT(blob->locked_operation_in_progress == true);
6712 /* Deletion failure */
6713 CU_ASSERT(g_bserrno == -EBUSY);
6714 poll_threads();
6715 CU_ASSERT(blob->locked_operation_in_progress == false);
6716 /* Blob resized successfully */
6717 CU_ASSERT(g_bserrno == 0);
6718
6719 spdk_blob_close(blob, blob_op_complete, NULL);
6720 poll_threads();
6721 CU_ASSERT(g_bserrno == 0);
6722
6723 spdk_blob_close(snapshot, blob_op_complete, NULL);
6724 poll_threads();
6725 CU_ASSERT(g_bserrno == 0);
6726
6727 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
6728 poll_threads();
6729 CU_ASSERT(g_bserrno == 0);
6730
6731 spdk_bs_unload(g_bs, bs_op_complete, NULL);
6732 poll_threads();
6733 CU_ASSERT(g_bserrno == 0);
6734 g_bs = NULL;
6735
6736 spdk_bs_free_io_channel(channel);
6737 poll_threads();
6738 }
6739
6740 int main(int argc, char **argv)
6741 {
6742 CU_pSuite suite = NULL;
6743 unsigned int num_failures;
6744
6745 if (CU_initialize_registry() != CUE_SUCCESS) {
6746 return CU_get_error();
6747 }
6748
6749 suite = CU_add_suite("blob", NULL, NULL);
6750 if (suite == NULL) {
6751 CU_cleanup_registry();
6752 return CU_get_error();
6753 }
6754
6755 if (
6756 CU_add_test(suite, "blob_init", blob_init) == NULL ||
6757 CU_add_test(suite, "blob_open", blob_open) == NULL ||
6758 CU_add_test(suite, "blob_create", blob_create) == NULL ||
6759 CU_add_test(suite, "blob_create_internal", blob_create_internal) == NULL ||
6760 CU_add_test(suite, "blob_thin_provision", blob_thin_provision) == NULL ||
6761 CU_add_test(suite, "blob_snapshot", blob_snapshot) == NULL ||
6762 CU_add_test(suite, "blob_clone", blob_clone) == NULL ||
6763 CU_add_test(suite, "blob_inflate", blob_inflate) == NULL ||
6764 CU_add_test(suite, "blob_delete", blob_delete) == NULL ||
6765 CU_add_test(suite, "blob_resize", blob_resize) == NULL ||
6766 CU_add_test(suite, "blob_read_only", blob_read_only) == NULL ||
6767 CU_add_test(suite, "channel_ops", channel_ops) == NULL ||
6768 CU_add_test(suite, "blob_super", blob_super) == NULL ||
6769 CU_add_test(suite, "blob_write", blob_write) == NULL ||
6770 CU_add_test(suite, "blob_read", blob_read) == NULL ||
6771 CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL ||
6772 CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL ||
6773 CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL ||
6774 CU_add_test(suite, "blob_rw_iov_read_only", blob_rw_iov_read_only) == NULL ||
6775 CU_add_test(suite, "blob_unmap", blob_unmap) == NULL ||
6776 CU_add_test(suite, "blob_iter", blob_iter) == NULL ||
6777 CU_add_test(suite, "blob_xattr", blob_xattr) == NULL ||
6778 CU_add_test(suite, "bs_load", bs_load) == NULL ||
6779 CU_add_test(suite, "bs_load_pending_removal", bs_load_pending_removal) == NULL ||
6780 CU_add_test(suite, "bs_load_custom_cluster_size", bs_load_custom_cluster_size) == NULL ||
6781 CU_add_test(suite, "bs_unload", bs_unload) == NULL ||
6782 CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL ||
6783 CU_add_test(suite, "bs_usable_clusters", bs_usable_clusters) == NULL ||
6784 CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL ||
6785 CU_add_test(suite, "bs_destroy", bs_destroy) == NULL ||
6786 CU_add_test(suite, "bs_type", bs_type) == NULL ||
6787 CU_add_test(suite, "bs_super_block", bs_super_block) == NULL ||
6788 CU_add_test(suite, "blob_serialize", blob_serialize) == NULL ||
6789 CU_add_test(suite, "blob_crc", blob_crc) == NULL ||
6790 CU_add_test(suite, "super_block_crc", super_block_crc) == NULL ||
6791 CU_add_test(suite, "blob_dirty_shutdown", blob_dirty_shutdown) == NULL ||
6792 CU_add_test(suite, "blob_flags", blob_flags) == NULL ||
6793 CU_add_test(suite, "bs_version", bs_version) == NULL ||
6794 CU_add_test(suite, "blob_set_xattrs", blob_set_xattrs) == NULL ||
6795 CU_add_test(suite, "blob_thin_prov_alloc", blob_thin_prov_alloc) == NULL ||
6796 CU_add_test(suite, "blob_insert_cluster_msg", blob_insert_cluster_msg) == NULL ||
6797 CU_add_test(suite, "blob_thin_prov_rw", blob_thin_prov_rw) == NULL ||
6798 CU_add_test(suite, "blob_thin_prov_rw_iov", blob_thin_prov_rw_iov) == NULL ||
6799 CU_add_test(suite, "bs_load_iter", bs_load_iter) == NULL ||
6800 CU_add_test(suite, "blob_snapshot_rw", blob_snapshot_rw) == NULL ||
6801 CU_add_test(suite, "blob_snapshot_rw_iov", blob_snapshot_rw_iov) == NULL ||
6802 CU_add_test(suite, "blob_relations", blob_relations) == NULL ||
6803 CU_add_test(suite, "blob_inflate_rw", blob_inflate_rw) == NULL ||
6804 CU_add_test(suite, "blob_snapshot_freeze_io", blob_snapshot_freeze_io) == NULL ||
6805 CU_add_test(suite, "blob_operation_split_rw", blob_operation_split_rw) == NULL ||
6806 CU_add_test(suite, "blob_operation_split_rw_iov", blob_operation_split_rw_iov) == NULL ||
6807 CU_add_test(suite, "blob_io_unit", blob_io_unit) == NULL ||
6808 CU_add_test(suite, "blob_io_unit_compatiblity", blob_io_unit_compatiblity) == NULL ||
6809 CU_add_test(suite, "blob_simultaneous_operations", blob_simultaneous_operations) == NULL
6810 ) {
6811 CU_cleanup_registry();
6812 return CU_get_error();
6813 }
6814
6815 allocate_threads(2);
6816 set_thread(0);
6817
6818 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
6819
6820 CU_basic_set_mode(CU_BRM_VERBOSE);
6821 CU_basic_run_tests();
6822 num_failures = CU_get_number_of_failures();
6823 CU_cleanup_registry();
6824
6825 free(g_dev_buffer);
6826
6827 free_threads();
6828
6829 return num_failures;
6830 }