xref: /spdk/test/unit/lib/blob/blob.c/blob_ut.c (revision 130d278adf62d046ab88392f2fcc9dabf318b484)
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.
943  */
944 static void
945 bs_unload(void)
946 {
947 	struct spdk_bs_dev *dev;
948 
949 	dev = init_dev();
950 
951 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
952 	CU_ASSERT(g_bserrno == 0);
953 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
954 
955 	g_bserrno = -1;
956 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
957 	CU_ASSERT(g_bserrno == 0);
958 	g_bs = NULL;
959 }
960 
961 /*
962  * Create a blobstore with a cluster size different than the default, and ensure it is
963  *  persisted.
964  */
965 static void
966 bs_cluster_sz(void)
967 {
968 	struct spdk_bs_dev *dev;
969 	struct spdk_bs_opts opts;
970 	uint32_t cluster_sz;
971 
972 	dev = init_dev();
973 	spdk_bs_opts_init(&opts);
974 	opts.cluster_sz *= 2;
975 	cluster_sz = opts.cluster_sz;
976 
977 	/* Initialize a new blob store */
978 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
979 	CU_ASSERT(g_bserrno == 0);
980 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
981 
982 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
983 
984 	/* Unload the blob store */
985 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
986 	CU_ASSERT(g_bserrno == 0);
987 	g_bs = NULL;
988 	g_blob = NULL;
989 	g_blobid = 0;
990 
991 	dev = init_dev();
992 	/* Load an existing blob store */
993 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
994 	CU_ASSERT(g_bserrno == 0);
995 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
996 
997 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
998 
999 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1000 	CU_ASSERT(g_bserrno == 0);
1001 	g_bs = NULL;
1002 }
1003 
1004 /*
1005  * Test resizing of the metadata blob.  This requires creating enough blobs
1006  *  so that one cluster is not enough to fit the metadata for those blobs.
1007  *  To induce this condition to happen more quickly, we reduce the cluster
1008  *  size to 16KB, which means only 4 4KB blob metadata pages can fit.
1009  */
1010 static void
1011 bs_resize_md(void)
1012 {
1013 	const int CLUSTER_PAGE_COUNT = 4;
1014 	const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4;
1015 	struct spdk_bs_dev *dev;
1016 	struct spdk_bs_opts opts;
1017 	uint32_t cluster_sz;
1018 	spdk_blob_id blobids[NUM_BLOBS];
1019 	int i;
1020 
1021 
1022 	dev = init_dev();
1023 	spdk_bs_opts_init(&opts);
1024 	opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096;
1025 	cluster_sz = opts.cluster_sz;
1026 
1027 	/* Initialize a new blob store */
1028 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
1029 	CU_ASSERT(g_bserrno == 0);
1030 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1031 
1032 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1033 
1034 	for (i = 0; i < NUM_BLOBS; i++) {
1035 		g_bserrno = -1;
1036 		g_blobid = SPDK_BLOBID_INVALID;
1037 		spdk_bs_md_create_blob(g_bs,
1038 				       blob_op_with_id_complete, NULL);
1039 		CU_ASSERT(g_bserrno == 0);
1040 		CU_ASSERT(g_blobid !=  SPDK_BLOBID_INVALID);
1041 		blobids[i] = g_blobid;
1042 	}
1043 
1044 	/* Unload the blob store */
1045 	g_bserrno = -1;
1046 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1047 	CU_ASSERT(g_bserrno == 0);
1048 
1049 	/* Load an existing blob store */
1050 	g_bserrno = -1;
1051 	g_bs = NULL;
1052 	dev = init_dev();
1053 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1054 	CU_ASSERT(g_bserrno == 0);
1055 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1056 
1057 	CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz);
1058 
1059 	for (i = 0; i < NUM_BLOBS; i++) {
1060 		g_bserrno = -1;
1061 		g_blob = NULL;
1062 		spdk_bs_md_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL);
1063 		CU_ASSERT(g_bserrno == 0);
1064 		CU_ASSERT(g_blob !=  NULL);
1065 		g_bserrno = -1;
1066 		spdk_bs_md_close_blob(&g_blob, blob_op_complete, NULL);
1067 		CU_ASSERT(g_bserrno == 0);
1068 	}
1069 
1070 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1071 	CU_ASSERT(g_bserrno == 0);
1072 	g_bs = NULL;
1073 }
1074 
1075 /* Try to hit all of the corner cases associated with serializing
1076  * a blob to disk
1077  */
1078 static void
1079 blob_serialize(void)
1080 {
1081 	struct spdk_bs_dev *dev;
1082 	struct spdk_bs_opts opts;
1083 	struct spdk_blob_store *bs;
1084 	spdk_blob_id blobid[2];
1085 	struct spdk_blob *blob[2];
1086 	uint64_t i;
1087 	char *value;
1088 	int rc;
1089 
1090 	dev = init_dev();
1091 
1092 	/* Initialize a new blobstore with very small clusters */
1093 	spdk_bs_opts_init(&opts);
1094 	opts.cluster_sz = dev->blocklen * 8;
1095 	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
1096 	CU_ASSERT(g_bserrno == 0);
1097 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1098 	bs = g_bs;
1099 
1100 	/* Create and open two blobs */
1101 	for (i = 0; i < 2; i++) {
1102 		spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
1103 		CU_ASSERT(g_bserrno == 0);
1104 		CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1105 		blobid[i] = g_blobid;
1106 
1107 		/* Open a blob */
1108 		spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
1109 		CU_ASSERT(g_bserrno == 0);
1110 		CU_ASSERT(g_blob != NULL);
1111 		blob[i] = g_blob;
1112 
1113 		/* Set a fairly large xattr on both blobs to eat up
1114 		 * metadata space
1115 		 */
1116 		value = calloc(dev->blocklen - 64, sizeof(char));
1117 		SPDK_CU_ASSERT_FATAL(value != NULL);
1118 		memset(value, i, dev->blocklen / 2);
1119 		rc = spdk_blob_md_set_xattr(blob[i], "name", value, dev->blocklen - 64);
1120 		CU_ASSERT(rc == 0);
1121 		free(value);
1122 	}
1123 
1124 	/* Resize the blobs, alternating 1 cluster at a time.
1125 	 * This thwarts run length encoding and will cause spill
1126 	 * over of the extents.
1127 	 */
1128 	for (i = 0; i < 6; i++) {
1129 		rc = spdk_bs_md_resize_blob(blob[i % 2], (i / 2) + 1);
1130 		CU_ASSERT(rc == 0);
1131 	}
1132 
1133 	for (i = 0; i < 2; i++) {
1134 		spdk_bs_md_sync_blob(blob[i], blob_op_complete, NULL);
1135 		CU_ASSERT(g_bserrno == 0);
1136 	}
1137 
1138 	/* Close the blobs */
1139 	for (i = 0; i < 2; i++) {
1140 		spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL);
1141 		CU_ASSERT(g_bserrno == 0);
1142 	}
1143 
1144 	/* Unload the blobstore */
1145 	spdk_bs_unload(bs, bs_op_complete, NULL);
1146 	CU_ASSERT(g_bserrno == 0);
1147 	g_bs = NULL;
1148 	g_blob = NULL;
1149 	g_blobid = 0;
1150 	bs = NULL;
1151 
1152 	dev = init_dev();
1153 	/* Load an existing blob store */
1154 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1155 	CU_ASSERT(g_bserrno == 0);
1156 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1157 	bs = g_bs;
1158 
1159 	for (i = 0; i < 2; i++) {
1160 		blob[i] = NULL;
1161 
1162 		spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL);
1163 		CU_ASSERT(g_bserrno == 0);
1164 		CU_ASSERT(g_blob != NULL);
1165 		blob[i] = g_blob;
1166 
1167 		CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3);
1168 
1169 		spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL);
1170 		CU_ASSERT(g_bserrno == 0);
1171 	}
1172 
1173 	spdk_bs_unload(bs, bs_op_complete, NULL);
1174 	CU_ASSERT(g_bserrno == 0);
1175 	g_bs = NULL;
1176 }
1177 
1178 static void
1179 blob_crc(void)
1180 {
1181 	struct spdk_blob_store *bs;
1182 	struct spdk_bs_dev *dev;
1183 	struct spdk_blob *blob;
1184 	spdk_blob_id blobid;
1185 	uint32_t page_num;
1186 	int index;
1187 	struct spdk_blob_md_page *page;
1188 
1189 	dev = init_dev();
1190 
1191 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1192 	CU_ASSERT(g_bserrno == 0);
1193 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1194 	bs = g_bs;
1195 
1196 	spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL);
1197 	CU_ASSERT(g_bserrno == 0);
1198 	CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
1199 	blobid = g_blobid;
1200 
1201 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1202 	CU_ASSERT(g_bserrno == 0);
1203 	CU_ASSERT(g_blob != NULL);
1204 	blob = g_blob;
1205 
1206 	spdk_bs_md_close_blob(&blob, blob_op_complete, NULL);
1207 	CU_ASSERT(g_bserrno == 0);
1208 	CU_ASSERT(blob == NULL);
1209 
1210 	page_num = _spdk_bs_blobid_to_page(blobid);
1211 	index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num);
1212 	page = (struct spdk_blob_md_page *)&g_dev_buffer[index];
1213 	page->crc = 0;
1214 
1215 	spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
1216 	CU_ASSERT(g_bserrno == -EINVAL);
1217 	CU_ASSERT(g_blob == NULL);
1218 	g_bserrno = 0;
1219 
1220 	spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL);
1221 	CU_ASSERT(g_bserrno == -EINVAL);
1222 
1223 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1224 	CU_ASSERT(g_bserrno == 0);
1225 	g_bs = NULL;
1226 }
1227 
1228 static void
1229 super_block_crc(void)
1230 {
1231 	struct spdk_bs_dev *dev;
1232 	struct spdk_bs_super_block *super_block;
1233 
1234 	dev = init_dev();
1235 
1236 	spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
1237 	CU_ASSERT(g_bserrno == 0);
1238 	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
1239 
1240 	spdk_bs_unload(g_bs, bs_op_complete, NULL);
1241 	CU_ASSERT(g_bserrno == 0);
1242 	g_bs = NULL;
1243 
1244 	super_block = (struct spdk_bs_super_block *)g_dev_buffer;
1245 	super_block->crc = 0;
1246 	dev = init_dev();
1247 
1248 	g_scheduler_delay = true;
1249 	/* Load an existing blob store */
1250 	spdk_bs_load(dev, bs_op_with_handle_complete, NULL);
1251 
1252 	CU_ASSERT(g_bserrno == -EILSEQ);
1253 	_bs_flush_scheduler();
1254 	CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops));
1255 
1256 	g_scheduler_delay = false;
1257 }
1258 
1259 int main(int argc, char **argv)
1260 {
1261 	CU_pSuite	suite = NULL;
1262 	unsigned int	num_failures;
1263 
1264 	if (CU_initialize_registry() != CUE_SUCCESS) {
1265 		return CU_get_error();
1266 	}
1267 
1268 	suite = CU_add_suite("blob", NULL, NULL);
1269 	if (suite == NULL) {
1270 		CU_cleanup_registry();
1271 		return CU_get_error();
1272 	}
1273 
1274 	if (
1275 		CU_add_test(suite, "blob_init", blob_init) == NULL ||
1276 		CU_add_test(suite, "blob_open", blob_open) == NULL ||
1277 		CU_add_test(suite, "blob_delete", blob_delete) == NULL ||
1278 		CU_add_test(suite, "blob_resize", blob_resize) == NULL ||
1279 		CU_add_test(suite, "channel_ops", channel_ops) == NULL ||
1280 		CU_add_test(suite, "blob_super", blob_super) == NULL ||
1281 		CU_add_test(suite, "blob_write", blob_write) == NULL ||
1282 		CU_add_test(suite, "blob_read", blob_read) == NULL ||
1283 		CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL ||
1284 		CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL ||
1285 		CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL ||
1286 		CU_add_test(suite, "blob_iter", blob_iter) == NULL ||
1287 		CU_add_test(suite, "blob_xattr", blob_xattr) == NULL ||
1288 		CU_add_test(suite, "bs_load", bs_load) == NULL ||
1289 		CU_add_test(suite, "bs_unload", bs_unload) == NULL ||
1290 		CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL ||
1291 		CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL ||
1292 		CU_add_test(suite, "blob_serialize", blob_serialize) == NULL ||
1293 		CU_add_test(suite, "blob_crc", blob_crc) == NULL ||
1294 		CU_add_test(suite, "super_block_crc", super_block_crc) == NULL
1295 	) {
1296 		CU_cleanup_registry();
1297 		return CU_get_error();
1298 	}
1299 
1300 	g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
1301 	spdk_allocate_thread(_bs_send_msg, NULL, "thread0");
1302 	CU_basic_set_mode(CU_BRM_VERBOSE);
1303 	CU_basic_run_tests();
1304 	num_failures = CU_get_number_of_failures();
1305 	CU_cleanup_registry();
1306 	spdk_free_thread();
1307 	free(g_dev_buffer);
1308 	return num_failures;
1309 }
1310