xref: /spdk/test/unit/lib/blob/blob.c/blob_ut.c (revision 19de08066d6259f6358e89ad2fde4f6704010f05)
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 	struct spdk_bs_super_block *super_blob;
853 	uint64_t length;
854 	int rc;
855 	const void *value;
856 	size_t value_len;
857 
858 	dev = init_dev();
859 
860 	/* Initialize a new blob store */
861 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
862 	CU_ASSERT(g_bserrno == 0);
863 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
864 
865 	/* Create a blob */
866 	spdk_bs_md_create_blob(g_bs, blob_op_with_id_complete, NULL);
867 	CU_ASSERT(g_bserrno == 0);
868 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
869 	blobid = g_blobid;
870 
871 	spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
872 	CU_ASSERT(g_bserrno == 0);
873 	CU_ASSERT(g_blob != NULL);
874 	blob = g_blob;
875 
876 	/* Set some xattrs */
877 	rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
878 	CU_ASSERT(rc == 0);
879 
880 	length = 2345;
881 	rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length));
882 	CU_ASSERT(rc == 0);
883 
884 	/* Resize the blob */
885 	rc = spdk_bs_md_resize_blob(blob, 10);
886 	CU_ASSERT(rc == 0);
887 
888 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
889 	CU_ASSERT(g_bserrno == 0);
890 	blob = NULL;
891 	g_blob = NULL;
892 	g_blobid = SPDK_BLOBID_INVALID;
893 
894 	/* Unload the blob store */
895 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
896 	CU_ASSERT(g_bserrno == 0);
897 	g_bs = NULL;
898 	g_blob = NULL;
899 	g_blobid = 0;
900 
901 	super_blob = (struct spdk_bs_super_block *)g_dev_buffer;
902 	CU_ASSERT(super_blob->clean == 1);
903 	dev = init_dev();
904 	/* Load an existing blob store */
905 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
906 	CU_ASSERT(g_bserrno == 0);
907 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
908 
909 	super_blob = (struct spdk_bs_super_block *)g_dev_buffer;
910 	CU_ASSERT(super_blob->clean == 0);
911 
912 	spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
913 	CU_ASSERT(g_bserrno == 0);
914 	CU_ASSERT(g_blob != NULL);
915 	blob = g_blob;
916 
917 	/* Get the xattrs */
918 	value = NULL;
919 	rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len);
920 	CU_ASSERT(rc == 0);
921 	SPDK_CU_ASSERT_FATAL(value != NULL);
922 	CU_ASSERT(*(uint64_t *)value == length);
923 	CU_ASSERT(value_len == 8);
924 
925 	rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len);
926 	CU_ASSERT(rc == -ENOENT);
927 
928 	CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10);
929 
930 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
931 	CU_ASSERT(g_bserrno == 0);
932 	blob = NULL;
933 	g_blob = NULL;
934 	g_blobid = SPDK_BLOBID_INVALID;
935 
936 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
937 	CU_ASSERT(g_bserrno == 0);
938 	g_bs = NULL;
939 }
940 
941 /*
942  * Create a blobstore and then unload it, while delaying all scheduled operations
943  * until after spdk_bs_unload call has finished.  This ensures the memory associated
944  * with the internal blobstore channels is not touched after it is freed.
945  */
946 static void
947 bs_unload_delayed(void)
948 {
949 	struct spdk_bs_dev *dev;
950 
951 	dev = init_dev();
952 
953 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
954 	CU_ASSERT(g_bserrno == 0);
955 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
956 
957 	g_scheduler_delay = true;
958 
959 	g_bserrno = -1;
960 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
961 	CU_ASSERT(g_bserrno == 0);
962 	g_bs = NULL;
963 
964 	_bs_flush_scheduler();
965 	CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops));
966 
967 	g_scheduler_delay = false;
968 }
969 
970 /*
971  * Create a blobstore with a cluster size different than the default, and ensure it is
972  *  persisted.
973  */
974 static void
975 bs_cluster_sz(void)
976 {
977 	struct spdk_bs_dev *dev;
978 	struct spdk_bs_opts opts;
979 	uint32_t cluster_sz;
980 
981 	dev = init_dev();
982 	spdk_bs_opts_init(&opts);
983 	opts.cluster_sz *= 2;
984 	cluster_sz = opts.cluster_sz;
985 
986 	/* Initialize a new blob store */
987 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
988 	CU_ASSERT(g_bserrno == 0);
989 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
990 
991 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
992 
993 	/* Unload the blob store */
994 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
995 	CU_ASSERT(g_bserrno == 0);
996 	g_bs = NULL;
997 	g_blob = NULL;
998 	g_blobid = 0;
999 
1000 	dev = init_dev();
1001 	/* Load an existing blob store */
1002 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1003 	CU_ASSERT(g_bserrno == 0);
1004 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1005 
1006 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1007 
1008 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1009 	CU_ASSERT(g_bserrno == 0);
1010 	g_bs = NULL;
1011 }
1012 
1013 /*
1014  * Test resizing of the metadata blob.  This requires creating enough blobs
1015  *  so that one cluster is not enough to fit the metadata for those blobs.
1016  *  To induce this condition to happen more quickly, we reduce the cluster
1017  *  size to 16KB, which means only 4 4KB blob metadata pages can fit.
1018  */
1019 static void
1020 bs_resize_md(void)
1021 {
1022 	const int CLUSTER_PAGE_COUNT = 4;
1023 	const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4;
1024 	struct spdk_bs_dev *dev;
1025 	struct spdk_bs_opts opts;
1026 	uint32_t cluster_sz;
1027 	spdk_blob_id blobids[NUM_BLOBS];
1028 	int i;
1029 
1030 
1031 	dev = init_dev();
1032 	spdk_bs_opts_init(&opts);
1033 	opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096;
1034 	cluster_sz = opts.cluster_sz;
1035 
1036 	/* Initialize a new blob store */
1037 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
1038 	CU_ASSERT(g_bserrno == 0);
1039 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1040 
1041 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1042 
1043 	for (i = 0; i < NUM_BLOBS; i++) {
1044 		g_bserrno = -1;
1045 		g_blobid = SPDK_BLOBID_INVALID;
1046 		spdk_bs_md_create_blob(g_bs,
1047 				       blob_op_with_id_complete, NULL);
1048 		CU_ASSERT(g_bserrno == 0);
1049 		CU_ASSERT(g_blobid !=  SPDK_BLOBID_INVALID);
1050 		blobids[i] = g_blobid;
1051 	}
1052 
1053 	/* Unload the blob store */
1054 	g_bserrno = -1;
1055 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1056 	CU_ASSERT(g_bserrno == 0);
1057 
1058 	/* Load an existing blob store */
1059 	g_bserrno = -1;
1060 	g_bs = NULL;
1061 	dev = init_dev();
1062 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1063 	CU_ASSERT(g_bserrno == 0);
1064 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1065 
1066 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1067 
1068 	for (i = 0; i < NUM_BLOBS; i++) {
1069 		g_bserrno = -1;
1070 		g_blob = NULL;
1071 		spdk_bs_md_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL);
1072 		CU_ASSERT(g_bserrno == 0);
1073 		CU_ASSERT(g_blob !=  NULL);
1074 		g_bserrno = -1;
1075 		spdk_bs_md_close_blob(&g_blob, blob_op_complete, NULL);
1076 		CU_ASSERT(g_bserrno == 0);
1077 	}
1078 
1079 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1080 	CU_ASSERT(g_bserrno == 0);
1081 	g_bs = NULL;
1082 }
1083 
1084 /* Try to hit all of the corner cases associated with serializing
1085  * a blob to disk
1086  */
1087 static void
1088 blob_serialize(void)
1089 {
1090 	struct spdk_bs_dev *dev;
1091 	struct spdk_bs_opts opts;
1092 	struct spdk_blob_store *bs;
1093 	spdk_blob_id blobid[2];
1094 	struct spdk_blob *blob[2];
1095 	uint64_t i;
1096 	char *value;
1097 	int rc;
1098 
1099 	dev = init_dev();
1100 
1101 	/* Initialize a new blobstore with very small clusters */
1102 	spdk_bs_opts_init(&opts);
1103 	opts.cluster_sz = dev->blocklen * 8;
1104 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
1105 	CU_ASSERT(g_bserrno == 0);
1106 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1107 	bs = g_bs;
1108 
1109 	/* Create and open two blobs */
1110 	for (i = 0; i < 2; i++) {
1111 		spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
1112 		CU_ASSERT(g_bserrno == 0);
1113 		CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1114 		blobid[i] = g_blobid;
1115 
1116 		/* Open a blob */
1117 		spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
1118 		CU_ASSERT(g_bserrno == 0);
1119 		CU_ASSERT(g_blob != NULL);
1120 		blob[i] = g_blob;
1121 
1122 		/* Set a fairly large xattr on both blobs to eat up
1123 		 * metadata space
1124 		 */
1125 		value = calloc(dev->blocklen - 64, sizeof(char));
1126 		SPDK_CU_ASSERT_FATAL(value != NULL);
1127 		memset(value, i, dev->blocklen / 2);
1128 		rc = spdk_blob_md_set_xattr(blob[i], "name", value, dev->blocklen - 64);
1129 		CU_ASSERT(rc == 0);
1130 		free(value);
1131 	}
1132 
1133 	/* Resize the blobs, alternating 1 cluster at a time.
1134 	 * This thwarts run length encoding and will cause spill
1135 	 * over of the extents.
1136 	 */
1137 	for (i = 0; i < 6; i++) {
1138 		rc = spdk_bs_md_resize_blob(blob[i % 2], (i / 2) + 1);
1139 		CU_ASSERT(rc == 0);
1140 	}
1141 
1142 	for (i = 0; i < 2; i++) {
1143 		spdk_bs_md_sync_blob(blob[i], blob_op_complete, NULL);
1144 		CU_ASSERT(g_bserrno == 0);
1145 	}
1146 
1147 	/* Close the blobs */
1148 	for (i = 0; i < 2; i++) {
1149 		spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL);
1150 		CU_ASSERT(g_bserrno == 0);
1151 	}
1152 
1153 	/* Unload the blobstore */
1154 	spdk_bs_unload(bs, bs_op_complete, NULL);
1155 	CU_ASSERT(g_bserrno == 0);
1156 	g_bs = NULL;
1157 	g_blob = NULL;
1158 	g_blobid = 0;
1159 	bs = NULL;
1160 
1161 	dev = init_dev();
1162 	/* Load an existing blob store */
1163 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1164 	CU_ASSERT(g_bserrno == 0);
1165 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1166 	bs = g_bs;
1167 
1168 	for (i = 0; i < 2; i++) {
1169 		blob[i] = NULL;
1170 
1171 		spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
1172 		CU_ASSERT(g_bserrno == 0);
1173 		CU_ASSERT(g_blob != NULL);
1174 		blob[i] = g_blob;
1175 
1176 		CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3);
1177 
1178 		spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL);
1179 		CU_ASSERT(g_bserrno == 0);
1180 	}
1181 
1182 	spdk_bs_unload(bs, bs_op_complete, NULL);
1183 	CU_ASSERT(g_bserrno == 0);
1184 	g_bs = NULL;
1185 }
1186 
1187 static void
1188 blob_crc(void)
1189 {
1190 	struct spdk_blob_store *bs;
1191 	struct spdk_bs_dev *dev;
1192 	struct spdk_blob *blob;
1193 	spdk_blob_id blobid;
1194 	uint32_t page_num;
1195 	int index;
1196 	struct spdk_blob_md_page *page;
1197 
1198 	dev = init_dev();
1199 
1200 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1201 	CU_ASSERT(g_bserrno == 0);
1202 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1203 	bs = g_bs;
1204 
1205 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
1206 	CU_ASSERT(g_bserrno == 0);
1207 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1208 	blobid = g_blobid;
1209 
1210 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1211 	CU_ASSERT(g_bserrno == 0);
1212 	CU_ASSERT(g_blob != NULL);
1213 	blob = g_blob;
1214 
1215 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
1216 	CU_ASSERT(g_bserrno == 0);
1217 	CU_ASSERT(blob == NULL);
1218 
1219 	page_num = _spdk_bs_blobid_to_page(blobid);
1220 	index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num);
1221 	page = (struct spdk_blob_md_page *)&g_dev_buffer[index];
1222 	page->crc = 0;
1223 
1224 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1225 	CU_ASSERT(g_bserrno == -EINVAL);
1226 	CU_ASSERT(g_blob == NULL);
1227 	g_bserrno = 0;
1228 
1229 	spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL);
1230 	CU_ASSERT(g_bserrno == -EINVAL);
1231 
1232 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1233 	CU_ASSERT(g_bserrno == 0);
1234 	g_bs = NULL;
1235 }
1236 
1237 int main(int argc, char **argv)
1238 {
1239 	CU_pSuite	suite = NULL;
1240 	unsigned int	num_failures;
1241 
1242 	if (CU_initialize_registry() != CUE_SUCCESS) {
1243 		return CU_get_error();
1244 	}
1245 
1246 	suite = CU_add_suite("blob", NULL, NULL);
1247 	if (suite == NULL) {
1248 		CU_cleanup_registry();
1249 		return CU_get_error();
1250 	}
1251 
1252 	if (
1253 		CU_add_test(suite, "blob_init", blob_init) == NULL ||
1254 		CU_add_test(suite, "blob_open", blob_open) == NULL ||
1255 		CU_add_test(suite, "blob_delete", blob_delete) == NULL ||
1256 		CU_add_test(suite, "blob_resize", blob_resize) == NULL ||
1257 		CU_add_test(suite, "channel_ops", channel_ops) == NULL ||
1258 		CU_add_test(suite, "blob_super", blob_super) == NULL ||
1259 		CU_add_test(suite, "blob_write", blob_write) == NULL ||
1260 		CU_add_test(suite, "blob_read", blob_read) == NULL ||
1261 		CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL ||
1262 		CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL ||
1263 		CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL ||
1264 		CU_add_test(suite, "blob_iter", blob_iter) == NULL ||
1265 		CU_add_test(suite, "blob_xattr", blob_xattr) == NULL ||
1266 		CU_add_test(suite, "bs_load", bs_load) == NULL ||
1267 		CU_add_test(suite, "bs_unload_delayed", bs_unload_delayed) == NULL ||
1268 		CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL ||
1269 		CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL ||
1270 		CU_add_test(suite, "blob_serialize", blob_serialize) == NULL ||
1271 		CU_add_test(suite, "blob_crc", blob_crc) == NULL
1272 	) {
1273 		CU_cleanup_registry();
1274 		return CU_get_error();
1275 	}
1276 
1277 	g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
1278 	spdk_allocate_thread(_bs_send_msg, NULL, "thread0");
1279 	CU_basic_set_mode(CU_BRM_VERBOSE);
1280 	CU_basic_run_tests();
1281 	num_failures = CU_get_number_of_failures();
1282 	CU_cleanup_registry();
1283 	spdk_free_thread();
1284 	free(g_dev_buffer);
1285 	return num_failures;
1286 }
1287