xref: /spdk/test/unit/lib/blob/blob.c/blob_ut.c (revision d92f0f75caf311608f5f0e19d4b3db349609b4e8)
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 
39 #include "lib/test_env.c"
40 #include "../bs_dev_common.c"
41 #include "blobstore.c"
42 #include "request.c"
43 
44 struct spdk_blob_store *g_bs;
45 spdk_blob_id g_blobid;
46 struct spdk_blob *g_blob;
47 int g_bserrno;
48 struct spdk_xattr_names *g_names;
49 int g_done;
50 
51 bool g_scheduler_delay = false;
52 
53 struct scheduled_ops {
54 	spdk_thread_fn	fn;
55 	void		*ctx;
56 
57 	TAILQ_ENTRY(scheduled_ops)	ops_queue;
58 };
59 
60 static TAILQ_HEAD(, scheduled_ops) g_scheduled_ops = TAILQ_HEAD_INITIALIZER(g_scheduled_ops);
61 
62 static void
63 _bs_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx)
64 {
65 	if (g_scheduler_delay) {
66 		struct scheduled_ops *ops = calloc(1, sizeof(*ops));
67 
68 		SPDK_CU_ASSERT_FATAL(ops != NULL);
69 		ops->fn = fn;
70 		ops->ctx = ctx;
71 		TAILQ_INSERT_TAIL(&g_scheduled_ops, ops, ops_queue);
72 	} else {
73 		fn(ctx);
74 	}
75 }
76 
77 static void
78 _bs_flush_scheduler(void)
79 {
80 	struct scheduled_ops *ops, *tmp;
81 
82 	TAILQ_FOREACH_SAFE(ops, &g_scheduled_ops, ops_queue, tmp) {
83 		ops->fn(ops->ctx);
84 		TAILQ_REMOVE(&g_scheduled_ops, ops, ops_queue);
85 		free(ops);
86 	}
87 }
88 
89 static void
90 bs_op_complete(void *cb_arg, int bserrno)
91 {
92 	g_bserrno = bserrno;
93 }
94 
95 static void
96 bs_op_with_handle_complete(void *cb_arg, struct spdk_blob_store *bs,
97 			   int bserrno)
98 {
99 	g_bs = bs;
100 	g_bserrno = bserrno;
101 }
102 
103 static void
104 blob_op_complete(void *cb_arg, int bserrno)
105 {
106 	g_bserrno = bserrno;
107 }
108 
109 static void
110 blob_op_with_id_complete(void *cb_arg, spdk_blob_id blobid, int bserrno)
111 {
112 	g_blobid = blobid;
113 	g_bserrno = bserrno;
114 }
115 
116 static void
117 blob_op_with_handle_complete(void *cb_arg, struct spdk_blob *blb, int bserrno)
118 {
119 	g_blob = blb;
120 	g_bserrno = bserrno;
121 }
122 
123 static void
124 blob_init(void)
125 {
126 	struct spdk_bs_dev *dev;
127 
128 	dev = init_dev();
129 
130 	/* should fail for an unsupported blocklen */
131 	dev->blocklen = 500;
132 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
133 	CU_ASSERT(g_bserrno == -EINVAL);
134 	/*
135 	 * Normally dev gets deleted as part of the dev->destroy callback.  But
136 	 *  that doesn't get invoked when init() fails.  So manually free it here
137 	 *  instead.  Probably blobstore should still destroy the dev when init
138 	 *  fails, but we'll do that in a separate patch.
139 	 */
140 	free(dev);
141 
142 	dev = init_dev();
143 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
144 	CU_ASSERT(g_bserrno == 0);
145 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
146 
147 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
148 	CU_ASSERT(g_bserrno == 0);
149 	g_bs = NULL;
150 }
151 
152 static void
153 blob_super(void)
154 {
155 	struct spdk_blob_store *bs;
156 	struct spdk_bs_dev *dev;
157 	spdk_blob_id blobid;
158 
159 	dev = init_dev();
160 
161 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
162 	CU_ASSERT(g_bserrno == 0);
163 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
164 	bs = g_bs;
165 
166 	/* Get the super blob without having set one */
167 	spdk_bs_get_super(bs, blob_op_with_id_complete, NULL);
168 	CU_ASSERT(g_bserrno == -ENOENT);
169 	CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID);
170 
171 	/* Create a blob */
172 	spdk_bs_md_create_blob(bs,
173 			       blob_op_with_id_complete, NULL);
174 	CU_ASSERT(g_bserrno == 0);
175 	CU_ASSERT(g_blobid !=  SPDK_BLOBID_INVALID);
176 	blobid = g_blobid;
177 
178 	/* Set the blob as the super blob */
179 	spdk_bs_set_super(bs, blobid, blob_op_complete, NULL);
180 	CU_ASSERT(g_bserrno == 0);
181 
182 	/* Get the super blob */
183 	spdk_bs_get_super(bs, blob_op_with_id_complete, NULL);
184 	CU_ASSERT(g_bserrno == 0);
185 	CU_ASSERT(blobid == g_blobid);
186 
187 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
188 	CU_ASSERT(g_bserrno == 0);
189 	g_bs = NULL;
190 }
191 
192 static void
193 blob_open(void)
194 {
195 	struct spdk_blob_store *bs;
196 	struct spdk_bs_dev *dev;
197 	struct spdk_blob *blob;
198 	spdk_blob_id blobid, blobid2;
199 
200 	dev = init_dev();
201 
202 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
203 	CU_ASSERT(g_bserrno == 0);
204 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
205 	bs = g_bs;
206 
207 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
208 	CU_ASSERT(g_bserrno == 0);
209 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
210 	blobid = g_blobid;
211 
212 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
213 	CU_ASSERT(g_bserrno == 0);
214 	CU_ASSERT(g_blob != NULL);
215 	blob = g_blob;
216 
217 	blobid2 = spdk_blob_get_id(blob);
218 	CU_ASSERT(blobid == blobid2);
219 
220 	/* Try to open file again.  It should return success. */
221 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
222 	CU_ASSERT(g_bserrno == 0);
223 	CU_ASSERT(blob == g_blob);
224 
225 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
226 	CU_ASSERT(g_bserrno == 0);
227 	CU_ASSERT(blob == NULL);
228 
229 	/*
230 	 * Close the file a second time, releasing the second reference.  This
231 	 *  should succeed.
232 	 */
233 	blob = g_blob;
234 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
235 	CU_ASSERT(g_bserrno == 0);
236 
237 	/*
238 	 * Try to open file again.  It should succeed.  This tests the case
239 	 *  where the file is opened, closed, then re-opened again.
240 	 */
241 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
242 	CU_ASSERT(g_bserrno == 0);
243 	CU_ASSERT(g_blob != NULL);
244 	blob = g_blob;
245 
246 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
247 	CU_ASSERT(g_bserrno == 0);
248 
249 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
250 	CU_ASSERT(g_bserrno == 0);
251 	g_bs = NULL;
252 }
253 
254 static void
255 blob_delete(void)
256 {
257 	struct spdk_blob_store *bs;
258 	struct spdk_bs_dev *dev;
259 	spdk_blob_id blobid;
260 
261 	dev = init_dev();
262 
263 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
264 	CU_ASSERT(g_bserrno == 0);
265 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
266 	bs = g_bs;
267 
268 	/* Create a blob and then delete it. */
269 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
270 	CU_ASSERT(g_bserrno == 0);
271 	CU_ASSERT(g_blobid > 0);
272 	blobid = g_blobid;
273 
274 	spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL);
275 	CU_ASSERT(g_bserrno == 0);
276 
277 	/* Try to open the blob */
278 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
279 	CU_ASSERT(g_bserrno == -ENOENT);
280 
281 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
282 	CU_ASSERT(g_bserrno == 0);
283 	g_bs = NULL;
284 }
285 
286 static void
287 blob_resize(void)
288 {
289 	struct spdk_blob_store *bs;
290 	struct spdk_bs_dev *dev;
291 	struct spdk_blob *blob;
292 	spdk_blob_id blobid;
293 	uint64_t free_clusters;
294 	int rc;
295 
296 	dev = init_dev();
297 
298 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
299 	CU_ASSERT(g_bserrno == 0);
300 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
301 	bs = g_bs;
302 	free_clusters = spdk_bs_free_cluster_count(bs);
303 
304 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
305 	CU_ASSERT(g_bserrno == 0);
306 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
307 	CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
308 	blobid = g_blobid;
309 
310 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
311 	CU_ASSERT(g_bserrno == 0);
312 	CU_ASSERT(g_blob != NULL);
313 	blob = g_blob;
314 
315 	/* The blob started at 0 clusters. Resize it to be 5. */
316 	rc = spdk_bs_md_resize_blob(blob, 5);
317 	CU_ASSERT(rc == 0);
318 	CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs));
319 
320 	/* Shrink the blob to 3 clusters. This will not actually release
321 	 * the old clusters until the blob is synced.
322 	 */
323 	rc = spdk_bs_md_resize_blob(blob, 3);
324 	CU_ASSERT(rc == 0);
325 	/* Verify there are still 5 clusters in use */
326 	CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs));
327 
328 	spdk_bs_md_sync_blob(blob, blob_op_complete, NULL);
329 	CU_ASSERT(g_bserrno == 0);
330 	/* Now there are only 3 clusters in use */
331 	CU_ASSERT((free_clusters - 3) == spdk_bs_free_cluster_count(bs));
332 
333 	/* Resize the blob to be 10 clusters. Growth takes effect immediately. */
334 	rc = spdk_bs_md_resize_blob(blob, 10);
335 	CU_ASSERT(rc == 0);
336 	CU_ASSERT((free_clusters - 10) == spdk_bs_free_cluster_count(bs));
337 
338 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
339 	CU_ASSERT(g_bserrno == 0);
340 
341 	spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL);
342 	CU_ASSERT(g_bserrno == 0);
343 
344 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
345 	CU_ASSERT(g_bserrno == 0);
346 	g_bs = NULL;
347 }
348 
349 static void
350 channel_ops(void)
351 {
352 	struct spdk_blob_store *bs;
353 	struct spdk_bs_dev *dev;
354 	struct spdk_io_channel *channel;
355 
356 	dev = init_dev();
357 
358 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
359 	CU_ASSERT(g_bserrno == 0);
360 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
361 	bs = g_bs;
362 
363 	channel = spdk_bs_alloc_io_channel(bs);
364 	CU_ASSERT(channel != NULL);
365 
366 	spdk_bs_free_io_channel(channel);
367 
368 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
369 	CU_ASSERT(g_bserrno == 0);
370 	g_bs = NULL;
371 }
372 
373 static void
374 blob_write(void)
375 {
376 	struct spdk_blob_store *bs;
377 	struct spdk_bs_dev *dev;
378 	struct spdk_blob *blob;
379 	struct spdk_io_channel *channel;
380 	spdk_blob_id blobid;
381 	uint64_t pages_per_cluster;
382 	uint8_t payload[10 * 4096];
383 	int rc;
384 
385 	dev = init_dev();
386 
387 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
388 	CU_ASSERT(g_bserrno == 0);
389 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
390 	bs = g_bs;
391 
392 	pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs);
393 
394 	channel = spdk_bs_alloc_io_channel(bs);
395 	CU_ASSERT(channel != NULL);
396 
397 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
398 	CU_ASSERT(g_bserrno == 0);
399 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
400 	blobid = g_blobid;
401 
402 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
403 	CU_ASSERT(g_bserrno == 0);
404 	CU_ASSERT(g_blob != NULL);
405 	blob = g_blob;
406 
407 	/* Write to a blob with 0 size */
408 	spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL);
409 	CU_ASSERT(g_bserrno == -EINVAL);
410 
411 	/* Resize the blob */
412 	rc = spdk_bs_md_resize_blob(blob, 5);
413 	CU_ASSERT(rc == 0);
414 
415 	/* Write to the blob */
416 	spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL);
417 	CU_ASSERT(g_bserrno == 0);
418 
419 	/* Write starting beyond the end */
420 	spdk_bs_io_write_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete,
421 			      NULL);
422 	CU_ASSERT(g_bserrno == -EINVAL);
423 
424 	/* Write starting at a valid location but going off the end */
425 	spdk_bs_io_write_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1,
426 			      blob_op_complete, NULL);
427 	CU_ASSERT(g_bserrno == -EINVAL);
428 
429 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
430 	CU_ASSERT(g_bserrno == 0);
431 
432 	spdk_bs_free_io_channel(channel);
433 
434 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
435 	CU_ASSERT(g_bserrno == 0);
436 	g_bs = NULL;
437 }
438 
439 static void
440 blob_read(void)
441 {
442 	struct spdk_blob_store *bs;
443 	struct spdk_bs_dev *dev;
444 	struct spdk_blob *blob;
445 	struct spdk_io_channel *channel;
446 	spdk_blob_id blobid;
447 	uint64_t pages_per_cluster;
448 	uint8_t payload[10 * 4096];
449 	int rc;
450 
451 	dev = init_dev();
452 
453 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
454 	CU_ASSERT(g_bserrno == 0);
455 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
456 	bs = g_bs;
457 
458 	pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs);
459 
460 	channel = spdk_bs_alloc_io_channel(bs);
461 	CU_ASSERT(channel != NULL);
462 
463 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
464 	CU_ASSERT(g_bserrno == 0);
465 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
466 	blobid = g_blobid;
467 
468 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
469 	CU_ASSERT(g_bserrno == 0);
470 	CU_ASSERT(g_blob != NULL);
471 	blob = g_blob;
472 
473 	/* Read from a blob with 0 size */
474 	spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL);
475 	CU_ASSERT(g_bserrno == -EINVAL);
476 
477 	/* Resize the blob */
478 	rc = spdk_bs_md_resize_blob(blob, 5);
479 	CU_ASSERT(rc == 0);
480 
481 	/* Read from the blob */
482 	spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL);
483 	CU_ASSERT(g_bserrno == 0);
484 
485 	/* Read starting beyond the end */
486 	spdk_bs_io_read_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete,
487 			     NULL);
488 	CU_ASSERT(g_bserrno == -EINVAL);
489 
490 	/* Read starting at a valid location but going off the end */
491 	spdk_bs_io_read_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1,
492 			     blob_op_complete, NULL);
493 	CU_ASSERT(g_bserrno == -EINVAL);
494 
495 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
496 	CU_ASSERT(g_bserrno == 0);
497 
498 	spdk_bs_free_io_channel(channel);
499 
500 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
501 	CU_ASSERT(g_bserrno == 0);
502 	g_bs = NULL;
503 }
504 
505 static void
506 blob_rw_verify(void)
507 {
508 	struct spdk_blob_store *bs;
509 	struct spdk_bs_dev *dev;
510 	struct spdk_blob *blob;
511 	struct spdk_io_channel *channel;
512 	spdk_blob_id blobid;
513 	uint8_t payload_read[10 * 4096];
514 	uint8_t payload_write[10 * 4096];
515 	int rc;
516 
517 	dev = init_dev();
518 
519 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
520 	CU_ASSERT(g_bserrno == 0);
521 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
522 	bs = g_bs;
523 
524 	channel = spdk_bs_alloc_io_channel(bs);
525 	CU_ASSERT(channel != NULL);
526 
527 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
528 	CU_ASSERT(g_bserrno == 0);
529 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
530 	blobid = g_blobid;
531 
532 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
533 	CU_ASSERT(g_bserrno == 0);
534 	CU_ASSERT(g_blob != NULL);
535 	blob = g_blob;
536 
537 	rc = spdk_bs_md_resize_blob(blob, 32);
538 	CU_ASSERT(rc == 0);
539 
540 	memset(payload_write, 0xE5, sizeof(payload_write));
541 	spdk_bs_io_write_blob(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
542 	CU_ASSERT(g_bserrno == 0);
543 
544 	memset(payload_read, 0x00, sizeof(payload_read));
545 	spdk_bs_io_read_blob(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
546 	CU_ASSERT(g_bserrno == 0);
547 	CU_ASSERT(memcmp(payload_write, payload_read, 4 * 4096) == 0);
548 
549 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
550 	CU_ASSERT(g_bserrno == 0);
551 
552 	spdk_bs_free_io_channel(channel);
553 
554 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
555 	CU_ASSERT(g_bserrno == 0);
556 	g_bs = NULL;
557 }
558 
559 static void
560 blob_rw_verify_iov(void)
561 {
562 	struct spdk_blob_store *bs;
563 	struct spdk_bs_dev *dev;
564 	struct spdk_blob *blob;
565 	struct spdk_io_channel *channel;
566 	spdk_blob_id blobid;
567 	uint8_t payload_read[10 * 4096];
568 	uint8_t payload_write[10 * 4096];
569 	struct iovec iov_read[3];
570 	struct iovec iov_write[3];
571 	void *buf;
572 	int rc;
573 
574 	dev = init_dev();
575 	memset(g_dev_buffer, 0, DEV_BUFFER_SIZE);
576 
577 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
578 	CU_ASSERT(g_bserrno == 0);
579 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
580 	bs = g_bs;
581 
582 	channel = spdk_bs_alloc_io_channel(bs);
583 	CU_ASSERT(channel != NULL);
584 
585 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
586 	CU_ASSERT(g_bserrno == 0);
587 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
588 	blobid = g_blobid;
589 
590 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
591 	CU_ASSERT(g_bserrno == 0);
592 	SPDK_CU_ASSERT_FATAL(g_blob != NULL);
593 	blob = g_blob;
594 
595 	rc = spdk_bs_md_resize_blob(blob, 2);
596 	CU_ASSERT(rc == 0);
597 
598 	/*
599 	 * Manually adjust the offset of the blob's second cluster.  This allows
600 	 *  us to make sure that the readv/write code correctly accounts for I/O
601 	 *  that cross cluster boundaries.  Start by asserting that the allocated
602 	 *  clusters are where we expect before modifying the second cluster.
603 	 */
604 	CU_ASSERT(blob->active.clusters[0] == 1 * 256);
605 	CU_ASSERT(blob->active.clusters[1] == 2 * 256);
606 	blob->active.clusters[1] = 3 * 256;
607 
608 	memset(payload_write, 0xE5, sizeof(payload_write));
609 	iov_write[0].iov_base = payload_write;
610 	iov_write[0].iov_len = 1 * 4096;
611 	iov_write[1].iov_base = payload_write + 1 * 4096;
612 	iov_write[1].iov_len = 5 * 4096;
613 	iov_write[2].iov_base = payload_write + 6 * 4096;
614 	iov_write[2].iov_len = 4 * 4096;
615 	/*
616 	 * Choose a page offset just before the cluster boundary.  The first 6 pages of payload
617 	 *  will get written to the first cluster, the last 4 to the second cluster.
618 	 */
619 	spdk_bs_io_writev_blob(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL);
620 	CU_ASSERT(g_bserrno == 0);
621 
622 	memset(payload_read, 0xAA, sizeof(payload_read));
623 	iov_read[0].iov_base = payload_read;
624 	iov_read[0].iov_len = 3 * 4096;
625 	iov_read[1].iov_base = payload_read + 3 * 4096;
626 	iov_read[1].iov_len = 4 * 4096;
627 	iov_read[2].iov_base = payload_read + 7 * 4096;
628 	iov_read[2].iov_len = 3 * 4096;
629 	spdk_bs_io_readv_blob(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL);
630 	CU_ASSERT(g_bserrno == 0);
631 	CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
632 
633 	buf = calloc(1, 256 * 4096);
634 	SPDK_CU_ASSERT_FATAL(buf != NULL);
635 	/* Check that cluster 2 on "disk" was not modified. */
636 	CU_ASSERT(memcmp(buf, &g_dev_buffer[512 * 4096], 256 * 4096) == 0);
637 	free(buf);
638 
639 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
640 	CU_ASSERT(g_bserrno == 0);
641 
642 	spdk_bs_free_io_channel(channel);
643 
644 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
645 	CU_ASSERT(g_bserrno == 0);
646 	g_bs = NULL;
647 }
648 
649 static uint32_t
650 bs_channel_get_req_count(struct spdk_io_channel *_channel)
651 {
652 	struct spdk_bs_channel *channel = spdk_io_channel_get_ctx(_channel);
653 	struct spdk_bs_request_set *set;
654 	uint32_t count = 0;
655 
656 	TAILQ_FOREACH(set, &channel->reqs, link) {
657 		count++;
658 	}
659 
660 	return count;
661 }
662 
663 static void
664 blob_rw_verify_iov_nomem(void)
665 {
666 	struct spdk_blob_store *bs;
667 	struct spdk_bs_dev *dev;
668 	struct spdk_blob *blob;
669 	struct spdk_io_channel *channel;
670 	spdk_blob_id blobid;
671 	uint8_t payload_write[10 * 4096];
672 	struct iovec iov_write[3];
673 	uint32_t req_count;
674 	int rc;
675 
676 	dev = init_dev();
677 	memset(g_dev_buffer, 0, DEV_BUFFER_SIZE);
678 
679 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
680 	CU_ASSERT(g_bserrno == 0);
681 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
682 	bs = g_bs;
683 
684 	channel = spdk_bs_alloc_io_channel(bs);
685 	CU_ASSERT(channel != NULL);
686 
687 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
688 	CU_ASSERT(g_bserrno == 0);
689 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
690 	blobid = g_blobid;
691 
692 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
693 	CU_ASSERT(g_bserrno == 0);
694 	CU_ASSERT(g_blob != NULL);
695 	blob = g_blob;
696 
697 	rc = spdk_bs_md_resize_blob(blob, 2);
698 	CU_ASSERT(rc == 0);
699 
700 	/*
701 	 * Choose a page offset just before the cluster boundary.  The first 6 pages of payload
702 	 *  will get written to the first cluster, the last 4 to the second cluster.
703 	 */
704 	iov_write[0].iov_base = payload_write;
705 	iov_write[0].iov_len = 1 * 4096;
706 	iov_write[1].iov_base = payload_write + 1 * 4096;
707 	iov_write[1].iov_len = 5 * 4096;
708 	iov_write[2].iov_base = payload_write + 6 * 4096;
709 	iov_write[2].iov_len = 4 * 4096;
710 	MOCK_SET(calloc, void *, NULL);
711 	req_count = bs_channel_get_req_count(channel);
712 	spdk_bs_io_writev_blob(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL);
713 	CU_ASSERT(g_bserrno = -ENOMEM);
714 	CU_ASSERT(req_count == bs_channel_get_req_count(channel));
715 	MOCK_SET(calloc, void *, (void *)MOCK_PASS_THRU);
716 
717 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
718 	CU_ASSERT(g_bserrno == 0);
719 
720 	spdk_bs_free_io_channel(channel);
721 
722 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
723 	CU_ASSERT(g_bserrno == 0);
724 	g_bs = NULL;
725 }
726 
727 static void
728 blob_iter(void)
729 {
730 	struct spdk_blob_store *bs;
731 	struct spdk_bs_dev *dev;
732 	struct spdk_blob *blob;
733 	spdk_blob_id blobid;
734 
735 	dev = init_dev();
736 
737 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
738 	CU_ASSERT(g_bserrno == 0);
739 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
740 	bs = g_bs;
741 
742 	spdk_bs_md_iter_first(bs, blob_op_with_handle_complete, NULL);
743 	CU_ASSERT(g_blob == NULL);
744 	CU_ASSERT(g_bserrno == -ENOENT);
745 
746 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
747 	CU_ASSERT(g_bserrno == 0);
748 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
749 	blobid = g_blobid;
750 
751 	spdk_bs_md_iter_first(bs, blob_op_with_handle_complete, NULL);
752 	CU_ASSERT(g_blob != NULL);
753 	CU_ASSERT(g_bserrno == 0);
754 	blob = g_blob;
755 	CU_ASSERT(spdk_blob_get_id(blob) == blobid);
756 
757 	spdk_bs_md_iter_next(bs, &blob, blob_op_with_handle_complete, NULL);
758 	CU_ASSERT(g_blob == NULL);
759 	CU_ASSERT(g_bserrno == -ENOENT);
760 
761 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
762 	CU_ASSERT(g_bserrno == 0);
763 	g_bs = NULL;
764 }
765 
766 static void
767 blob_xattr(void)
768 {
769 	struct spdk_blob_store *bs;
770 	struct spdk_bs_dev *dev;
771 	struct spdk_blob *blob;
772 	spdk_blob_id blobid;
773 	uint64_t length;
774 	int rc;
775 	const char *name1, *name2;
776 	const void *value;
777 	size_t value_len;
778 	struct spdk_xattr_names *names;
779 
780 	dev = init_dev();
781 
782 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
783 	CU_ASSERT(g_bserrno == 0);
784 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
785 	bs = g_bs;
786 
787 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
788 	CU_ASSERT(g_bserrno == 0);
789 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
790 	blobid = g_blobid;
791 
792 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
793 	CU_ASSERT(g_bserrno == 0);
794 	CU_ASSERT(g_blob != NULL);
795 	blob = g_blob;
796 
797 	rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
798 	CU_ASSERT(rc == 0);
799 
800 	length = 2345;
801 	rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length));
802 	CU_ASSERT(rc == 0);
803 
804 	/* Overwrite "length" xattr. */
805 	length = 3456;
806 	rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length));
807 	CU_ASSERT(rc == 0);
808 
809 	value = NULL;
810 	rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len);
811 	CU_ASSERT(rc == 0);
812 	SPDK_CU_ASSERT_FATAL(value != NULL);
813 	CU_ASSERT(*(uint64_t *)value == length);
814 	CU_ASSERT(value_len == 8);
815 
816 	rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len);
817 	CU_ASSERT(rc == -ENOENT);
818 
819 	names = NULL;
820 	rc = spdk_bs_md_get_xattr_names(blob, &names);
821 	CU_ASSERT(rc == 0);
822 	SPDK_CU_ASSERT_FATAL(names != NULL);
823 	CU_ASSERT(spdk_xattr_names_get_count(names) == 2);
824 	name1 = spdk_xattr_names_get_name(names, 0);
825 	SPDK_CU_ASSERT_FATAL(name1 != NULL);
826 	CU_ASSERT(!strcmp(name1, "name") || !strcmp(name1, "length"));
827 	name2 = spdk_xattr_names_get_name(names, 1);
828 	SPDK_CU_ASSERT_FATAL(name2 != NULL);
829 	CU_ASSERT(!strcmp(name2, "name") || !strcmp(name2, "length"));
830 	CU_ASSERT(strcmp(name1, name2));
831 	spdk_xattr_names_free(names);
832 
833 	rc = spdk_blob_md_remove_xattr(blob, "name");
834 	CU_ASSERT(rc == 0);
835 
836 	rc = spdk_blob_md_remove_xattr(blob, "foobar");
837 	CU_ASSERT(rc == -ENOENT);
838 
839 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
840 
841 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
842 	CU_ASSERT(g_bserrno == 0);
843 	g_bs = NULL;
844 }
845 
846 static void
847 bs_load(void)
848 {
849 	struct spdk_bs_dev *dev;
850 	spdk_blob_id blobid;
851 	struct spdk_blob *blob;
852 	uint64_t length;
853 	int rc;
854 	const void *value;
855 	size_t value_len;
856 
857 	dev = init_dev();
858 
859 	/* Initialize a new blob store */
860 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
861 	CU_ASSERT(g_bserrno == 0);
862 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
863 
864 	/* Create a blob */
865 	spdk_bs_md_create_blob(g_bs, blob_op_with_id_complete, NULL);
866 	CU_ASSERT(g_bserrno == 0);
867 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
868 	blobid = g_blobid;
869 
870 	spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
871 	CU_ASSERT(g_bserrno == 0);
872 	CU_ASSERT(g_blob != NULL);
873 	blob = g_blob;
874 
875 	/* Set some xattrs */
876 	rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
877 	CU_ASSERT(rc == 0);
878 
879 	length = 2345;
880 	rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length));
881 	CU_ASSERT(rc == 0);
882 
883 	/* Resize the blob */
884 	rc = spdk_bs_md_resize_blob(blob, 10);
885 	CU_ASSERT(rc == 0);
886 
887 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
888 	CU_ASSERT(g_bserrno == 0);
889 	blob = NULL;
890 	g_blob = NULL;
891 	g_blobid = SPDK_BLOBID_INVALID;
892 
893 	/* Unload the blob store */
894 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
895 	CU_ASSERT(g_bserrno == 0);
896 	g_bs = NULL;
897 	g_blob = NULL;
898 	g_blobid = 0;
899 
900 	dev = init_dev();
901 	/* Load an existing blob store */
902 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
903 	CU_ASSERT(g_bserrno == 0);
904 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
905 
906 	spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
907 	CU_ASSERT(g_bserrno == 0);
908 	CU_ASSERT(g_blob != NULL);
909 	blob = g_blob;
910 
911 	/* Get the xattrs */
912 	value = NULL;
913 	rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len);
914 	CU_ASSERT(rc == 0);
915 	SPDK_CU_ASSERT_FATAL(value != NULL);
916 	CU_ASSERT(*(uint64_t *)value == length);
917 	CU_ASSERT(value_len == 8);
918 
919 	rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len);
920 	CU_ASSERT(rc == -ENOENT);
921 
922 	CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10);
923 
924 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
925 	CU_ASSERT(g_bserrno == 0);
926 	blob = NULL;
927 	g_blob = NULL;
928 	g_blobid = SPDK_BLOBID_INVALID;
929 
930 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
931 	CU_ASSERT(g_bserrno == 0);
932 	g_bs = NULL;
933 }
934 
935 /*
936  * Create a blobstore and then unload it, while delaying all scheduled operations
937  * until after spdk_bs_unload call has finished.  This ensures the memory associated
938  * with the internal blobstore channels is not touched after it is freed.
939  */
940 static void
941 bs_unload_delayed(void)
942 {
943 	struct spdk_bs_dev *dev;
944 
945 	dev = init_dev();
946 
947 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
948 	CU_ASSERT(g_bserrno == 0);
949 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
950 
951 	g_scheduler_delay = true;
952 
953 	g_bserrno = -1;
954 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
955 	CU_ASSERT(g_bserrno == 0);
956 	g_bs = NULL;
957 
958 	_bs_flush_scheduler();
959 	CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops));
960 
961 	g_scheduler_delay = false;
962 }
963 
964 /*
965  * Create a blobstore with a cluster size different than the default, and ensure it is
966  *  persisted.
967  */
968 static void
969 bs_cluster_sz(void)
970 {
971 	struct spdk_bs_dev *dev;
972 	struct spdk_bs_opts opts;
973 	uint32_t cluster_sz;
974 
975 	dev = init_dev();
976 	spdk_bs_opts_init(&opts);
977 	opts.cluster_sz *= 2;
978 	cluster_sz = opts.cluster_sz;
979 
980 	/* Initialize a new blob store */
981 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
982 	CU_ASSERT(g_bserrno == 0);
983 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
984 
985 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
986 
987 	/* Unload the blob store */
988 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
989 	CU_ASSERT(g_bserrno == 0);
990 	g_bs = NULL;
991 	g_blob = NULL;
992 	g_blobid = 0;
993 
994 	dev = init_dev();
995 	/* Load an existing blob store */
996 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
997 	CU_ASSERT(g_bserrno == 0);
998 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
999 
1000 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1001 
1002 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1003 	CU_ASSERT(g_bserrno == 0);
1004 	g_bs = NULL;
1005 }
1006 
1007 /*
1008  * Test resizing of the metadata blob.  This requires creating enough blobs
1009  *  so that one cluster is not enough to fit the metadata for those blobs.
1010  *  To induce this condition to happen more quickly, we reduce the cluster
1011  *  size to 16KB, which means only 4 4KB blob metadata pages can fit.
1012  */
1013 static void
1014 bs_resize_md(void)
1015 {
1016 	const int CLUSTER_PAGE_COUNT = 4;
1017 	const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4;
1018 	struct spdk_bs_dev *dev;
1019 	struct spdk_bs_opts opts;
1020 	uint32_t cluster_sz;
1021 	spdk_blob_id blobids[NUM_BLOBS];
1022 	int i;
1023 
1024 
1025 	dev = init_dev();
1026 	spdk_bs_opts_init(&opts);
1027 	opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096;
1028 	cluster_sz = opts.cluster_sz;
1029 
1030 	/* Initialize a new blob store */
1031 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
1032 	CU_ASSERT(g_bserrno == 0);
1033 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1034 
1035 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1036 
1037 	for (i = 0; i < NUM_BLOBS; i++) {
1038 		g_bserrno = -1;
1039 		g_blobid = SPDK_BLOBID_INVALID;
1040 		spdk_bs_md_create_blob(g_bs,
1041 				       blob_op_with_id_complete, NULL);
1042 		CU_ASSERT(g_bserrno == 0);
1043 		CU_ASSERT(g_blobid !=  SPDK_BLOBID_INVALID);
1044 		blobids[i] = g_blobid;
1045 	}
1046 
1047 	/* Unload the blob store */
1048 	g_bserrno = -1;
1049 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1050 	CU_ASSERT(g_bserrno == 0);
1051 
1052 	/* Load an existing blob store */
1053 	g_bserrno = -1;
1054 	g_bs = NULL;
1055 	dev = init_dev();
1056 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1057 	CU_ASSERT(g_bserrno == 0);
1058 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1059 
1060 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1061 
1062 	for (i = 0; i < NUM_BLOBS; i++) {
1063 		g_bserrno = -1;
1064 		g_blob = NULL;
1065 		spdk_bs_md_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL);
1066 		CU_ASSERT(g_bserrno == 0);
1067 		CU_ASSERT(g_blob !=  NULL);
1068 		g_bserrno = -1;
1069 		spdk_bs_md_close_blob(&g_blob, blob_op_complete, NULL);
1070 		CU_ASSERT(g_bserrno == 0);
1071 	}
1072 
1073 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1074 	CU_ASSERT(g_bserrno == 0);
1075 	g_bs = NULL;
1076 }
1077 
1078 /* Try to hit all of the corner cases associated with serializing
1079  * a blob to disk
1080  */
1081 static void
1082 blob_serialize(void)
1083 {
1084 	struct spdk_bs_dev *dev;
1085 	struct spdk_bs_opts opts;
1086 	struct spdk_blob_store *bs;
1087 	spdk_blob_id blobid[2];
1088 	struct spdk_blob *blob[2];
1089 	uint64_t i;
1090 	char *value;
1091 	int rc;
1092 
1093 	dev = init_dev();
1094 
1095 	/* Initialize a new blobstore with very small clusters */
1096 	spdk_bs_opts_init(&opts);
1097 	opts.cluster_sz = dev->blocklen * 8;
1098 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
1099 	CU_ASSERT(g_bserrno == 0);
1100 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1101 	bs = g_bs;
1102 
1103 	/* Create and open two blobs */
1104 	for (i = 0; i < 2; i++) {
1105 		spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
1106 		CU_ASSERT(g_bserrno == 0);
1107 		CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1108 		blobid[i] = g_blobid;
1109 
1110 		/* Open a blob */
1111 		spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
1112 		CU_ASSERT(g_bserrno == 0);
1113 		CU_ASSERT(g_blob != NULL);
1114 		blob[i] = g_blob;
1115 
1116 		/* Set a fairly large xattr on both blobs to eat up
1117 		 * metadata space
1118 		 */
1119 		value = calloc(dev->blocklen - 64, sizeof(char));
1120 		SPDK_CU_ASSERT_FATAL(value != NULL);
1121 		memset(value, i, dev->blocklen / 2);
1122 		rc = spdk_blob_md_set_xattr(blob[i], "name", value, dev->blocklen - 64);
1123 		CU_ASSERT(rc == 0);
1124 		free(value);
1125 	}
1126 
1127 	/* Resize the blobs, alternating 1 cluster at a time.
1128 	 * This thwarts run length encoding and will cause spill
1129 	 * over of the extents.
1130 	 */
1131 	for (i = 0; i < 6; i++) {
1132 		rc = spdk_bs_md_resize_blob(blob[i % 2], (i / 2) + 1);
1133 		CU_ASSERT(rc == 0);
1134 	}
1135 
1136 	for (i = 0; i < 2; i++) {
1137 		spdk_bs_md_sync_blob(blob[i], blob_op_complete, NULL);
1138 		CU_ASSERT(g_bserrno == 0);
1139 	}
1140 
1141 	/* Close the blobs */
1142 	for (i = 0; i < 2; i++) {
1143 		spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL);
1144 		CU_ASSERT(g_bserrno == 0);
1145 	}
1146 
1147 	/* Unload the blobstore */
1148 	spdk_bs_unload(bs, bs_op_complete, NULL);
1149 	CU_ASSERT(g_bserrno == 0);
1150 	g_bs = NULL;
1151 	g_blob = NULL;
1152 	g_blobid = 0;
1153 	bs = NULL;
1154 
1155 	dev = init_dev();
1156 	/* Load an existing blob store */
1157 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1158 	CU_ASSERT(g_bserrno == 0);
1159 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1160 	bs = g_bs;
1161 
1162 	for (i = 0; i < 2; i++) {
1163 		blob[i] = NULL;
1164 
1165 		spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
1166 		CU_ASSERT(g_bserrno == 0);
1167 		CU_ASSERT(g_blob != NULL);
1168 		blob[i] = g_blob;
1169 
1170 		CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3);
1171 
1172 		spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL);
1173 		CU_ASSERT(g_bserrno == 0);
1174 	}
1175 
1176 	spdk_bs_unload(bs, bs_op_complete, NULL);
1177 	CU_ASSERT(g_bserrno == 0);
1178 	g_bs = NULL;
1179 }
1180 
1181 int main(int argc, char **argv)
1182 {
1183 	CU_pSuite	suite = NULL;
1184 	unsigned int	num_failures;
1185 
1186 	if (CU_initialize_registry() != CUE_SUCCESS) {
1187 		return CU_get_error();
1188 	}
1189 
1190 	suite = CU_add_suite("blob", NULL, NULL);
1191 	if (suite == NULL) {
1192 		CU_cleanup_registry();
1193 		return CU_get_error();
1194 	}
1195 
1196 	if (
1197 		CU_add_test(suite, "blob_init", blob_init) == NULL ||
1198 		CU_add_test(suite, "blob_open", blob_open) == NULL ||
1199 		CU_add_test(suite, "blob_delete", blob_delete) == NULL ||
1200 		CU_add_test(suite, "blob_resize", blob_resize) == NULL ||
1201 		CU_add_test(suite, "channel_ops", channel_ops) == NULL ||
1202 		CU_add_test(suite, "blob_super", blob_super) == NULL ||
1203 		CU_add_test(suite, "blob_write", blob_write) == NULL ||
1204 		CU_add_test(suite, "blob_read", blob_read) == NULL ||
1205 		CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL ||
1206 		CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL ||
1207 		CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL ||
1208 		CU_add_test(suite, "blob_iter", blob_iter) == NULL ||
1209 		CU_add_test(suite, "blob_xattr", blob_xattr) == NULL ||
1210 		CU_add_test(suite, "bs_load", bs_load) == NULL ||
1211 		CU_add_test(suite, "bs_unload_delayed", bs_unload_delayed) == NULL ||
1212 		CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL ||
1213 		CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL ||
1214 		CU_add_test(suite, "blob_serialize", blob_serialize) == NULL
1215 	) {
1216 		CU_cleanup_registry();
1217 		return CU_get_error();
1218 	}
1219 
1220 	g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
1221 	spdk_allocate_thread(_bs_send_msg, NULL, "thread0");
1222 	CU_basic_set_mode(CU_BRM_VERBOSE);
1223 	CU_basic_run_tests();
1224 	num_failures = CU_get_number_of_failures();
1225 	CU_cleanup_registry();
1226 	spdk_free_thread();
1227 	free(g_dev_buffer);
1228 	return num_failures;
1229 }
1230