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