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 "env_dpdk/memory.c" 35 36 #define UNIT_TEST_NO_VTOPHYS 37 #define UNIT_TEST_NO_PCI_ADDR 38 #include "common/lib/test_env.c" 39 #include "spdk_cunit.h" 40 41 #include "spdk/bit_array.h" 42 43 #define PAGE_ARRAY_SIZE (100) 44 static struct spdk_bit_array *g_page_array; 45 static void *g_vaddr_to_fail = (void *)UINT64_MAX; 46 47 DEFINE_STUB(rte_memseg_contig_walk, int, (rte_memseg_contig_walk_t func, void *arg), 0); 48 DEFINE_STUB(rte_mem_virt2memseg, struct rte_memseg *, 49 (const void *virt, const struct rte_memseg_list *msl), NULL); 50 DEFINE_STUB(spdk_env_dpdk_external_init, bool, (void), true); 51 DEFINE_STUB(rte_mem_event_callback_register, int, 52 (const char *name, rte_mem_event_callback_t clb, void *arg), 0); 53 DEFINE_STUB(rte_mem_virt2iova, rte_iova_t, (const void *virtaddr), 0); 54 DEFINE_STUB(rte_eal_iova_mode, enum rte_iova_mode, (void), RTE_IOVA_VA); 55 DEFINE_STUB(rte_vfio_is_enabled, int, (const char *modname), 0); 56 DEFINE_STUB(rte_vfio_noiommu_is_enabled, int, (void), 0); 57 DEFINE_STUB(rte_memseg_get_fd_thread_unsafe, int, (const struct rte_memseg *ms), 0); 58 DEFINE_STUB(rte_memseg_get_fd_offset_thread_unsafe, int, 59 (const struct rte_memseg *ms, size_t *offset), 0); 60 DEFINE_STUB(rte_dev_iterator_init, int, (struct rte_dev_iterator *it, const char *dev_str), 0); 61 DEFINE_STUB(rte_dev_iterator_next, struct rte_device *, (struct rte_dev_iterator *it), NULL); 62 DEFINE_STUB(rte_dev_event_callback_register, int, (const char *device_name, 63 rte_dev_event_cb_fn cb_fn, void *cb_arg), 0); 64 DEFINE_STUB(rte_dev_event_callback_unregister, int, (const char *device_name, 65 rte_dev_event_cb_fn cb_fn, void *cb_arg), 0); 66 DEFINE_STUB(rte_dev_event_monitor_start, int, (void), 0); 67 DEFINE_STUB(rte_dev_event_monitor_stop, int, (void), 0); 68 DEFINE_STUB(rte_extmem_register, int, (void *va_addr, size_t len, rte_iova_t iova_addrs[], 69 unsigned int n_pages, size_t page_sz), 0); 70 DEFINE_STUB(rte_extmem_unregister, int, (void *va_addr, size_t len), 0); 71 DEFINE_STUB(rte_dev_dma_map, int, (struct rte_device *dev, void *addr, uint64_t iova, 72 size_t len), 0); 73 DEFINE_STUB(rte_dev_dma_unmap, int, (struct rte_device *dev, void *addr, uint64_t iova, 74 size_t len), 0); 75 76 static int 77 test_mem_map_notify(void *cb_ctx, struct spdk_mem_map *map, 78 enum spdk_mem_map_notify_action action, 79 void *vaddr, size_t len) 80 { 81 uint32_t i, end; 82 83 SPDK_CU_ASSERT_FATAL(((uintptr_t)vaddr & MASK_2MB) == 0); 84 SPDK_CU_ASSERT_FATAL((len & MASK_2MB) == 0); 85 86 /* 87 * This is a test requirement - the bit array we use to verify 88 * pages are valid is only so large. 89 */ 90 SPDK_CU_ASSERT_FATAL((uintptr_t)vaddr < (VALUE_2MB * PAGE_ARRAY_SIZE)); 91 92 i = (uintptr_t)vaddr >> SHIFT_2MB; 93 end = i + (len >> SHIFT_2MB); 94 for (; i < end; i++) { 95 switch (action) { 96 case SPDK_MEM_MAP_NOTIFY_REGISTER: 97 /* This page should not already be registered */ 98 SPDK_CU_ASSERT_FATAL(spdk_bit_array_get(g_page_array, i) == false); 99 SPDK_CU_ASSERT_FATAL(spdk_bit_array_set(g_page_array, i) == 0); 100 break; 101 case SPDK_MEM_MAP_NOTIFY_UNREGISTER: 102 SPDK_CU_ASSERT_FATAL(spdk_bit_array_get(g_page_array, i) == true); 103 spdk_bit_array_clear(g_page_array, i); 104 break; 105 default: 106 SPDK_UNREACHABLE(); 107 } 108 } 109 110 return 0; 111 } 112 113 static int 114 test_mem_map_notify_fail(void *cb_ctx, struct spdk_mem_map *map, 115 enum spdk_mem_map_notify_action action, void *vaddr, size_t size) 116 { 117 struct spdk_mem_map *reg_map = cb_ctx; 118 119 switch (action) { 120 case SPDK_MEM_MAP_NOTIFY_REGISTER: 121 if (vaddr == g_vaddr_to_fail) { 122 /* Test the error handling. */ 123 return -1; 124 } 125 break; 126 case SPDK_MEM_MAP_NOTIFY_UNREGISTER: 127 /* Clear the same region in the other mem_map to be able to 128 * verify that there was no memory left still registered after 129 * the mem_map creation failure. 130 */ 131 spdk_mem_map_clear_translation(reg_map, (uint64_t)vaddr, size); 132 break; 133 } 134 135 return 0; 136 } 137 138 static int 139 test_mem_map_notify_checklen(void *cb_ctx, struct spdk_mem_map *map, 140 enum spdk_mem_map_notify_action action, void *vaddr, size_t size) 141 { 142 size_t *len_arr = cb_ctx; 143 144 /* 145 * This is a test requirement - the len array we use to verify 146 * pages are valid is only so large. 147 */ 148 SPDK_CU_ASSERT_FATAL((uintptr_t)vaddr < (VALUE_2MB * PAGE_ARRAY_SIZE)); 149 150 switch (action) { 151 case SPDK_MEM_MAP_NOTIFY_REGISTER: 152 assert(size == len_arr[(uintptr_t)vaddr / VALUE_2MB]); 153 break; 154 case SPDK_MEM_MAP_NOTIFY_UNREGISTER: 155 CU_ASSERT(size == len_arr[(uintptr_t)vaddr / VALUE_2MB]); 156 break; 157 } 158 159 return 0; 160 } 161 162 static int 163 test_check_regions_contiguous(uint64_t addr1, uint64_t addr2) 164 { 165 return addr1 == addr2; 166 } 167 168 const struct spdk_mem_map_ops test_mem_map_ops = { 169 .notify_cb = test_mem_map_notify, 170 .are_contiguous = test_check_regions_contiguous 171 }; 172 173 const struct spdk_mem_map_ops test_mem_map_ops_no_contig = { 174 .notify_cb = test_mem_map_notify, 175 .are_contiguous = NULL 176 }; 177 178 struct spdk_mem_map_ops test_map_ops_notify_fail = { 179 .notify_cb = test_mem_map_notify_fail, 180 .are_contiguous = NULL 181 }; 182 183 struct spdk_mem_map_ops test_map_ops_notify_checklen = { 184 .notify_cb = test_mem_map_notify_checklen, 185 .are_contiguous = NULL 186 }; 187 188 static void 189 test_mem_map_alloc_free(void) 190 { 191 struct spdk_mem_map *map, *failed_map; 192 uint64_t default_translation = 0xDEADBEEF0BADF00D; 193 int i; 194 195 map = spdk_mem_map_alloc(default_translation, &test_mem_map_ops, NULL); 196 SPDK_CU_ASSERT_FATAL(map != NULL); 197 spdk_mem_map_free(&map); 198 CU_ASSERT(map == NULL); 199 200 map = spdk_mem_map_alloc(default_translation, NULL, NULL); 201 SPDK_CU_ASSERT_FATAL(map != NULL); 202 203 /* Register some memory for the initial memory walk in 204 * spdk_mem_map_alloc(). We'll fail registering the last region 205 * and will check if the mem_map cleaned up all its previously 206 * initialized translations. 207 */ 208 for (i = 0; i < 5; i++) { 209 spdk_mem_register((void *)(uintptr_t)(2 * i * VALUE_2MB), VALUE_2MB); 210 } 211 212 /* The last region */ 213 g_vaddr_to_fail = (void *)(8 * VALUE_2MB); 214 failed_map = spdk_mem_map_alloc(default_translation, &test_map_ops_notify_fail, map); 215 CU_ASSERT(failed_map == NULL); 216 217 for (i = 0; i < 4; i++) { 218 uint64_t reg, size = VALUE_2MB; 219 220 reg = spdk_mem_map_translate(map, 2 * i * VALUE_2MB, &size); 221 /* check if `failed_map` didn't leave any translations behind */ 222 CU_ASSERT(reg == default_translation); 223 } 224 225 for (i = 0; i < 5; i++) { 226 spdk_mem_unregister((void *)(uintptr_t)(2 * i * VALUE_2MB), VALUE_2MB); 227 } 228 229 spdk_mem_map_free(&map); 230 CU_ASSERT(map == NULL); 231 } 232 233 static void 234 test_mem_map_translation(void) 235 { 236 struct spdk_mem_map *map; 237 uint64_t default_translation = 0xDEADBEEF0BADF00D; 238 uint64_t addr; 239 uint64_t mapping_length; 240 int rc; 241 242 map = spdk_mem_map_alloc(default_translation, &test_mem_map_ops, NULL); 243 SPDK_CU_ASSERT_FATAL(map != NULL); 244 245 /* Try to get translation for address with no translation */ 246 addr = spdk_mem_map_translate(map, 10, NULL); 247 CU_ASSERT(addr == default_translation); 248 249 /* Set translation for region of non-2MB multiple size */ 250 rc = spdk_mem_map_set_translation(map, VALUE_2MB, 1234, VALUE_2MB); 251 CU_ASSERT(rc == -EINVAL); 252 253 /* Set translation for vaddr that isn't 2MB aligned */ 254 rc = spdk_mem_map_set_translation(map, 1234, VALUE_2MB, VALUE_2MB); 255 CU_ASSERT(rc == -EINVAL); 256 257 /* Set translation for one 2MB page */ 258 rc = spdk_mem_map_set_translation(map, VALUE_2MB, VALUE_2MB, VALUE_2MB); 259 CU_ASSERT(rc == 0); 260 261 /* Set translation for region that overlaps the previous translation */ 262 rc = spdk_mem_map_set_translation(map, 0, 3 * VALUE_2MB, 0); 263 CU_ASSERT(rc == 0); 264 265 /* Make sure we indicate that the three regions are contiguous */ 266 mapping_length = VALUE_2MB * 3; 267 addr = spdk_mem_map_translate(map, 0, &mapping_length); 268 CU_ASSERT(addr == 0); 269 CU_ASSERT(mapping_length == VALUE_2MB * 3); 270 271 /* Translate an unaligned address */ 272 mapping_length = VALUE_2MB * 3; 273 addr = spdk_mem_map_translate(map, VALUE_4KB, &mapping_length); 274 CU_ASSERT(addr == 0); 275 CU_ASSERT(mapping_length == VALUE_2MB * 3 - VALUE_4KB); 276 277 /* Clear translation for the middle page of the larger region. */ 278 rc = spdk_mem_map_clear_translation(map, VALUE_2MB, VALUE_2MB); 279 CU_ASSERT(rc == 0); 280 281 /* Get translation for first page */ 282 addr = spdk_mem_map_translate(map, 0, NULL); 283 CU_ASSERT(addr == 0); 284 285 /* Make sure we indicate that the three regions are no longer contiguous */ 286 mapping_length = VALUE_2MB * 3; 287 addr = spdk_mem_map_translate(map, 0, &mapping_length); 288 CU_ASSERT(addr == 0); 289 CU_ASSERT(mapping_length == VALUE_2MB); 290 291 /* Get translation for an unallocated block. Make sure size is 0 */ 292 mapping_length = VALUE_2MB * 3; 293 addr = spdk_mem_map_translate(map, VALUE_2MB, &mapping_length); 294 CU_ASSERT(addr == default_translation); 295 CU_ASSERT(mapping_length == VALUE_2MB); 296 297 /* Verify translation for 2nd page is the default */ 298 addr = spdk_mem_map_translate(map, VALUE_2MB, NULL); 299 CU_ASSERT(addr == default_translation); 300 301 /* Get translation for third page */ 302 addr = spdk_mem_map_translate(map, 2 * VALUE_2MB, NULL); 303 /* 304 * Note that addr should be 0, not 4MB. When we set the 305 * translation above, we said the whole 6MB region 306 * should translate to 0. 307 */ 308 CU_ASSERT(addr == 0); 309 310 /* Translate only a subset of a 2MB page */ 311 mapping_length = 543; 312 addr = spdk_mem_map_translate(map, 0, &mapping_length); 313 CU_ASSERT(addr == 0); 314 CU_ASSERT(mapping_length == 543); 315 316 /* Translate another subset of a 2MB page */ 317 mapping_length = 543; 318 addr = spdk_mem_map_translate(map, VALUE_4KB, &mapping_length); 319 CU_ASSERT(addr == 0); 320 CU_ASSERT(mapping_length == 543); 321 322 /* Try to translate an unaligned region that is only partially registered */ 323 mapping_length = 543; 324 addr = spdk_mem_map_translate(map, 3 * VALUE_2MB - 196, &mapping_length); 325 CU_ASSERT(addr == 0); 326 CU_ASSERT(mapping_length == 196); 327 328 /* Clear translation for the first page */ 329 rc = spdk_mem_map_clear_translation(map, 0, VALUE_2MB); 330 CU_ASSERT(rc == 0); 331 332 /* Get translation for the first page */ 333 addr = spdk_mem_map_translate(map, 0, NULL); 334 CU_ASSERT(addr == default_translation); 335 336 /* Clear translation for the third page */ 337 rc = spdk_mem_map_clear_translation(map, 2 * VALUE_2MB, VALUE_2MB); 338 CU_ASSERT(rc == 0); 339 340 /* Get translation for the third page */ 341 addr = spdk_mem_map_translate(map, 2 * VALUE_2MB, NULL); 342 CU_ASSERT(addr == default_translation); 343 344 /* Set translation for the last valid 2MB region */ 345 rc = spdk_mem_map_set_translation(map, 0xffffffe00000ULL, VALUE_2MB, 0x1234); 346 CU_ASSERT(rc == 0); 347 348 /* Verify translation for last valid 2MB region */ 349 addr = spdk_mem_map_translate(map, 0xffffffe00000ULL, NULL); 350 CU_ASSERT(addr == 0x1234); 351 352 /* Attempt to set translation for the first invalid address */ 353 rc = spdk_mem_map_set_translation(map, 0x1000000000000ULL, VALUE_2MB, 0x5678); 354 CU_ASSERT(rc == -EINVAL); 355 356 /* Attempt to set translation starting at a valid address but exceeding the valid range */ 357 rc = spdk_mem_map_set_translation(map, 0xffffffe00000ULL, VALUE_2MB * 2, 0x123123); 358 CU_ASSERT(rc != 0); 359 360 spdk_mem_map_free(&map); 361 CU_ASSERT(map == NULL); 362 363 /* Allocate a map without a contiguous region checker */ 364 map = spdk_mem_map_alloc(default_translation, &test_mem_map_ops_no_contig, NULL); 365 SPDK_CU_ASSERT_FATAL(map != NULL); 366 367 /* map three contiguous regions */ 368 rc = spdk_mem_map_set_translation(map, 0, 3 * VALUE_2MB, 0); 369 CU_ASSERT(rc == 0); 370 371 /* Since we can't check their contiguity, make sure we only return the size of one page */ 372 mapping_length = VALUE_2MB * 3; 373 addr = spdk_mem_map_translate(map, 0, &mapping_length); 374 CU_ASSERT(addr == 0); 375 CU_ASSERT(mapping_length == VALUE_2MB); 376 377 /* Translate only a subset of a 2MB page */ 378 mapping_length = 543; 379 addr = spdk_mem_map_translate(map, 0, &mapping_length); 380 CU_ASSERT(addr == 0); 381 CU_ASSERT(mapping_length == 543); 382 383 /* Clear the translation */ 384 rc = spdk_mem_map_clear_translation(map, 0, VALUE_2MB * 3); 385 CU_ASSERT(rc == 0); 386 387 spdk_mem_map_free(&map); 388 CU_ASSERT(map == NULL); 389 } 390 391 static void 392 test_mem_map_registration(void) 393 { 394 int rc; 395 struct spdk_mem_map *map; 396 uint64_t default_translation = 0xDEADBEEF0BADF00D; 397 398 map = spdk_mem_map_alloc(default_translation, &test_mem_map_ops, NULL); 399 SPDK_CU_ASSERT_FATAL(map != NULL); 400 401 /* Unregister memory region that wasn't previously registered */ 402 rc = spdk_mem_unregister((void *)VALUE_2MB, VALUE_2MB); 403 CU_ASSERT(rc == -EINVAL); 404 405 /* Register non-2MB multiple size */ 406 rc = spdk_mem_register((void *)VALUE_2MB, 1234); 407 CU_ASSERT(rc == -EINVAL); 408 409 /* Register region that isn't 2MB aligned */ 410 rc = spdk_mem_register((void *)1234, VALUE_2MB); 411 CU_ASSERT(rc == -EINVAL); 412 413 /* Register one 2MB page */ 414 rc = spdk_mem_register((void *)VALUE_2MB, VALUE_2MB); 415 CU_ASSERT(rc == 0); 416 417 /* Register an overlapping address range */ 418 rc = spdk_mem_register((void *)0, 3 * VALUE_2MB); 419 CU_ASSERT(rc == -EBUSY); 420 421 /* Unregister a 2MB page */ 422 rc = spdk_mem_unregister((void *)VALUE_2MB, VALUE_2MB); 423 CU_ASSERT(rc == 0); 424 425 /* Register non overlapping address range */ 426 rc = spdk_mem_register((void *)0, 3 * VALUE_2MB); 427 CU_ASSERT(rc == 0); 428 429 /* Unregister the middle page of the larger region. */ 430 rc = spdk_mem_unregister((void *)VALUE_2MB, VALUE_2MB); 431 CU_ASSERT(rc == -ERANGE); 432 433 /* Unregister the first page */ 434 rc = spdk_mem_unregister((void *)0, VALUE_2MB); 435 CU_ASSERT(rc == -ERANGE); 436 437 /* Unregister the third page */ 438 rc = spdk_mem_unregister((void *)(2 * VALUE_2MB), VALUE_2MB); 439 CU_ASSERT(rc == -ERANGE); 440 441 /* Unregister the entire address range */ 442 rc = spdk_mem_unregister((void *)0, 3 * VALUE_2MB); 443 CU_ASSERT(rc == 0); 444 445 spdk_mem_map_free(&map); 446 CU_ASSERT(map == NULL); 447 } 448 449 static void 450 test_mem_map_registration_adjacent(void) 451 { 452 struct spdk_mem_map *map, *newmap; 453 uint64_t default_translation = 0xDEADBEEF0BADF00D; 454 uintptr_t vaddr; 455 unsigned i; 456 size_t notify_len[PAGE_ARRAY_SIZE] = {0}; 457 size_t chunk_len[] = { 2, 1, 3, 2, 1, 1 }; 458 459 map = spdk_mem_map_alloc(default_translation, 460 &test_map_ops_notify_checklen, notify_len); 461 SPDK_CU_ASSERT_FATAL(map != NULL); 462 463 vaddr = 0; 464 for (i = 0; i < SPDK_COUNTOF(chunk_len); i++) { 465 notify_len[vaddr / VALUE_2MB] = chunk_len[i] * VALUE_2MB; 466 spdk_mem_register((void *)vaddr, notify_len[vaddr / VALUE_2MB]); 467 vaddr += notify_len[vaddr / VALUE_2MB]; 468 } 469 470 /* Verify the memory is translated in the same chunks it was registered */ 471 newmap = spdk_mem_map_alloc(default_translation, 472 &test_map_ops_notify_checklen, notify_len); 473 SPDK_CU_ASSERT_FATAL(newmap != NULL); 474 spdk_mem_map_free(&newmap); 475 CU_ASSERT(newmap == NULL); 476 477 vaddr = 0; 478 for (i = 0; i < SPDK_COUNTOF(chunk_len); i++) { 479 notify_len[vaddr / VALUE_2MB] = chunk_len[i] * VALUE_2MB; 480 spdk_mem_unregister((void *)vaddr, notify_len[vaddr / VALUE_2MB]); 481 vaddr += notify_len[vaddr / VALUE_2MB]; 482 } 483 484 /* Register all chunks again just to unregister them again, but this 485 * time with only a single unregister() call. 486 */ 487 vaddr = 0; 488 for (i = 0; i < SPDK_COUNTOF(chunk_len); i++) { 489 notify_len[vaddr / VALUE_2MB] = chunk_len[i] * VALUE_2MB; 490 spdk_mem_register((void *)vaddr, notify_len[vaddr / VALUE_2MB]); 491 vaddr += notify_len[vaddr / VALUE_2MB]; 492 } 493 spdk_mem_unregister(0, vaddr); 494 495 spdk_mem_map_free(&map); 496 CU_ASSERT(map == NULL); 497 } 498 499 int 500 main(int argc, char **argv) 501 { 502 CU_pSuite suite = NULL; 503 unsigned int num_failures; 504 505 /* 506 * These tests can use PAGE_ARRAY_SIZE 2MB pages of memory. 507 * Note that the tests just verify addresses - this memory 508 * is not actually allocated. 509 */ 510 g_page_array = spdk_bit_array_create(PAGE_ARRAY_SIZE); 511 512 /* Initialize the memory map */ 513 if (mem_map_init(false) < 0) { 514 return CUE_NOMEMORY; 515 } 516 517 if (CU_initialize_registry() != CUE_SUCCESS) { 518 return CU_get_error(); 519 } 520 521 suite = CU_add_suite("memory", NULL, NULL); 522 if (suite == NULL) { 523 CU_cleanup_registry(); 524 return CU_get_error(); 525 } 526 527 if ( 528 CU_add_test(suite, "alloc and free memory map", test_mem_map_alloc_free) == NULL || 529 CU_add_test(suite, "mem map translation", test_mem_map_translation) == NULL || 530 CU_add_test(suite, "mem map registration", test_mem_map_registration) == NULL || 531 CU_add_test(suite, "mem map adjacent registrations", test_mem_map_registration_adjacent) == NULL 532 ) { 533 CU_cleanup_registry(); 534 return CU_get_error(); 535 } 536 537 CU_basic_set_mode(CU_BRM_VERBOSE); 538 CU_basic_run_tests(); 539 num_failures = CU_get_number_of_failures(); 540 CU_cleanup_registry(); 541 542 spdk_bit_array_free(&g_page_array); 543 544 return num_failures; 545 } 546