1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2015 Intel Corporation. All rights reserved. 3 * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved. 4 */ 5 6 #include "spdk_internal/cunit.h" 7 8 #include "spdk/env.h" 9 10 #include "nvme/nvme.c" 11 12 #include "spdk_internal/mock.h" 13 14 #include "common/lib/test_env.c" 15 16 DEFINE_STUB_V(nvme_ctrlr_proc_get_ref, (struct spdk_nvme_ctrlr *ctrlr)); 17 DEFINE_STUB_V(nvme_ctrlr_proc_put_ref, (struct spdk_nvme_ctrlr *ctrlr)); 18 DEFINE_STUB_V(nvme_ctrlr_fail, (struct spdk_nvme_ctrlr *ctrlr, bool hotremove)); 19 DEFINE_STUB(spdk_nvme_transport_available_by_name, bool, 20 (const char *transport_name), true); 21 /* return anything non-NULL, this won't be dereferenced anywhere in this test */ 22 DEFINE_STUB(nvme_ctrlr_get_current_process, struct spdk_nvme_ctrlr_process *, 23 (struct spdk_nvme_ctrlr *ctrlr), (struct spdk_nvme_ctrlr_process *)(uintptr_t)0x1); 24 DEFINE_STUB(nvme_ctrlr_process_init, int, 25 (struct spdk_nvme_ctrlr *ctrlr), 0); 26 DEFINE_STUB(nvme_ctrlr_get_ref_count, int, 27 (struct spdk_nvme_ctrlr *ctrlr), 0); 28 DEFINE_STUB(dummy_probe_cb, bool, 29 (void *cb_ctx, const struct spdk_nvme_transport_id *trid, 30 struct spdk_nvme_ctrlr_opts *opts), false); 31 DEFINE_STUB(nvme_transport_ctrlr_construct, struct spdk_nvme_ctrlr *, 32 (const struct spdk_nvme_transport_id *trid, 33 const struct spdk_nvme_ctrlr_opts *opts, 34 void *devhandle), NULL); 35 DEFINE_STUB_V(nvme_io_msg_ctrlr_detach, (struct spdk_nvme_ctrlr *ctrlr)); 36 DEFINE_STUB(spdk_nvme_transport_available, bool, 37 (enum spdk_nvme_transport_type trtype), true); 38 DEFINE_STUB(spdk_pci_event_listen, int, (void), 0); 39 DEFINE_STUB(spdk_nvme_poll_group_process_completions, int64_t, (struct spdk_nvme_poll_group *group, 40 uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb), 0); 41 42 static bool ut_destruct_called = false; 43 void 44 nvme_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr) 45 { 46 ut_destruct_called = true; 47 } 48 49 void 50 nvme_ctrlr_destruct_async(struct spdk_nvme_ctrlr *ctrlr, struct nvme_ctrlr_detach_ctx *ctx) 51 { 52 ut_destruct_called = true; 53 ctrlr->is_destructed = true; 54 55 ctx->shutdown_complete = true; 56 } 57 58 int 59 nvme_ctrlr_destruct_poll_async(struct spdk_nvme_ctrlr *ctrlr, 60 struct nvme_ctrlr_detach_ctx *ctx) 61 { 62 if (!ctx->shutdown_complete) { 63 return -EAGAIN; 64 } 65 66 if (ctx->cb_fn) { 67 ctx->cb_fn(ctrlr); 68 } 69 70 return 0; 71 } 72 73 union spdk_nvme_csts_register 74 spdk_nvme_ctrlr_get_regs_csts(struct spdk_nvme_ctrlr *ctrlr) 75 { 76 union spdk_nvme_csts_register csts = {}; 77 return csts; 78 } 79 80 void 81 spdk_nvme_ctrlr_get_default_ctrlr_opts(struct spdk_nvme_ctrlr_opts *opts, size_t opts_size) 82 { 83 memset(opts, 0, opts_size); 84 opts->opts_size = opts_size; 85 } 86 87 static void 88 memset_trid(struct spdk_nvme_transport_id *trid1, struct spdk_nvme_transport_id *trid2) 89 { 90 memset(trid1, 0, sizeof(struct spdk_nvme_transport_id)); 91 memset(trid2, 0, sizeof(struct spdk_nvme_transport_id)); 92 } 93 94 static bool ut_check_trtype = false; 95 static bool ut_test_probe_internal = false; 96 97 static int 98 ut_nvme_pcie_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx, 99 bool direct_connect) 100 { 101 struct spdk_nvme_ctrlr *ctrlr; 102 struct spdk_nvme_qpair qpair = {}; 103 int rc; 104 105 if (probe_ctx->trid.trtype != SPDK_NVME_TRANSPORT_PCIE) { 106 return -1; 107 } 108 109 ctrlr = calloc(1, sizeof(*ctrlr)); 110 CU_ASSERT(ctrlr != NULL); 111 ctrlr->adminq = &qpair; 112 113 /* happy path with first controller */ 114 MOCK_SET(nvme_transport_ctrlr_construct, ctrlr); 115 rc = nvme_ctrlr_probe(&probe_ctx->trid, probe_ctx, NULL); 116 CU_ASSERT(rc == 0); 117 118 /* failed with the second controller */ 119 MOCK_SET(nvme_transport_ctrlr_construct, NULL); 120 rc = nvme_ctrlr_probe(&probe_ctx->trid, probe_ctx, NULL); 121 CU_ASSERT(rc != 0); 122 MOCK_CLEAR_P(nvme_transport_ctrlr_construct); 123 124 return -1; 125 } 126 127 int 128 nvme_transport_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr) 129 { 130 free(ctrlr); 131 return 0; 132 } 133 134 int 135 nvme_transport_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx, 136 bool direct_connect) 137 { 138 struct spdk_nvme_ctrlr *ctrlr = NULL; 139 140 if (ut_check_trtype == true) { 141 CU_ASSERT(probe_ctx->trid.trtype == SPDK_NVME_TRANSPORT_PCIE); 142 } 143 144 if (ut_test_probe_internal) { 145 return ut_nvme_pcie_ctrlr_scan(probe_ctx, direct_connect); 146 } 147 148 if (direct_connect == true && probe_ctx->probe_cb) { 149 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock); 150 ctrlr = nvme_get_ctrlr_by_trid(&probe_ctx->trid); 151 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock); 152 probe_ctx->probe_cb(probe_ctx->cb_ctx, &probe_ctx->trid, &ctrlr->opts); 153 } 154 return 0; 155 } 156 157 static bool ut_attach_cb_called = false; 158 static void 159 dummy_attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, 160 struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts) 161 { 162 ut_attach_cb_called = true; 163 } 164 165 static void 166 test_spdk_nvme_probe(void) 167 { 168 int rc = 0; 169 const struct spdk_nvme_transport_id *trid = NULL; 170 void *cb_ctx = NULL; 171 spdk_nvme_probe_cb probe_cb = NULL; 172 spdk_nvme_attach_cb attach_cb = dummy_attach_cb; 173 spdk_nvme_remove_cb remove_cb = NULL; 174 struct spdk_nvme_ctrlr ctrlr; 175 pthread_mutexattr_t attr; 176 struct nvme_driver dummy; 177 g_spdk_nvme_driver = &dummy; 178 179 /* driver init fails */ 180 MOCK_SET(spdk_process_is_primary, false); 181 MOCK_SET(spdk_memzone_lookup, NULL); 182 rc = spdk_nvme_probe(trid, cb_ctx, probe_cb, attach_cb, remove_cb); 183 CU_ASSERT(rc == -1); 184 185 /* 186 * For secondary processes, the attach_cb should automatically get 187 * called for any controllers already initialized by the primary 188 * process. 189 */ 190 MOCK_SET(spdk_nvme_transport_available_by_name, false); 191 MOCK_SET(spdk_process_is_primary, true); 192 dummy.initialized = true; 193 g_spdk_nvme_driver = &dummy; 194 rc = spdk_nvme_probe(trid, cb_ctx, probe_cb, attach_cb, remove_cb); 195 CU_ASSERT(rc == -1); 196 197 /* driver init passes, transport available, secondary call attach_cb */ 198 MOCK_SET(spdk_nvme_transport_available_by_name, true); 199 MOCK_SET(spdk_process_is_primary, false); 200 MOCK_SET(spdk_memzone_lookup, g_spdk_nvme_driver); 201 dummy.initialized = true; 202 memset(&ctrlr, 0, sizeof(struct spdk_nvme_ctrlr)); 203 CU_ASSERT(pthread_mutexattr_init(&attr) == 0); 204 CU_ASSERT(pthread_mutex_init(&dummy.lock, &attr) == 0); 205 TAILQ_INIT(&dummy.shared_attached_ctrlrs); 206 TAILQ_INSERT_TAIL(&dummy.shared_attached_ctrlrs, &ctrlr, tailq); 207 ut_attach_cb_called = false; 208 /* setup nvme_transport_ctrlr_scan() stub to also check the trype */ 209 ut_check_trtype = true; 210 rc = spdk_nvme_probe(trid, cb_ctx, probe_cb, attach_cb, remove_cb); 211 CU_ASSERT(rc == 0); 212 CU_ASSERT(ut_attach_cb_called == true); 213 214 /* driver init passes, transport available, we are primary */ 215 MOCK_SET(spdk_process_is_primary, true); 216 rc = spdk_nvme_probe(trid, cb_ctx, probe_cb, attach_cb, remove_cb); 217 CU_ASSERT(rc == 0); 218 219 g_spdk_nvme_driver = NULL; 220 /* reset to pre-test values */ 221 MOCK_CLEAR(spdk_memzone_lookup); 222 ut_check_trtype = false; 223 224 pthread_mutex_destroy(&dummy.lock); 225 pthread_mutexattr_destroy(&attr); 226 } 227 228 static void 229 test_spdk_nvme_connect(void) 230 { 231 struct spdk_nvme_ctrlr *ret_ctrlr = NULL; 232 struct spdk_nvme_transport_id trid = {}; 233 struct spdk_nvme_ctrlr_opts opts = {}; 234 struct spdk_nvme_ctrlr ctrlr; 235 pthread_mutexattr_t attr; 236 struct nvme_driver dummy; 237 238 /* initialize the variable to prepare the test */ 239 dummy.initialized = true; 240 TAILQ_INIT(&dummy.shared_attached_ctrlrs); 241 g_spdk_nvme_driver = &dummy; 242 CU_ASSERT(pthread_mutexattr_init(&attr) == 0); 243 CU_ASSERT(pthread_mutex_init(&g_spdk_nvme_driver->lock, &attr) == 0); 244 245 /* set NULL trid pointer to test immediate return */ 246 ret_ctrlr = spdk_nvme_connect(NULL, NULL, 0); 247 CU_ASSERT(ret_ctrlr == NULL); 248 249 /* driver init passes, transport available, secondary process connects ctrlr */ 250 MOCK_SET(spdk_process_is_primary, false); 251 MOCK_SET(spdk_memzone_lookup, g_spdk_nvme_driver); 252 MOCK_SET(spdk_nvme_transport_available_by_name, true); 253 memset(&trid, 0, sizeof(trid)); 254 trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 255 ret_ctrlr = spdk_nvme_connect(&trid, NULL, 0); 256 CU_ASSERT(ret_ctrlr == NULL); 257 258 /* driver init passes, setup one ctrlr on the attached_list */ 259 memset(&ctrlr, 0, sizeof(struct spdk_nvme_ctrlr)); 260 snprintf(ctrlr.trid.traddr, sizeof(ctrlr.trid.traddr), "0000:01:00.0"); 261 ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 262 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver->shared_attached_ctrlrs, &ctrlr, tailq); 263 /* get the ctrlr from the attached list */ 264 snprintf(trid.traddr, sizeof(trid.traddr), "0000:01:00.0"); 265 ret_ctrlr = spdk_nvme_connect(&trid, NULL, 0); 266 CU_ASSERT(ret_ctrlr == &ctrlr); 267 /* get the ctrlr from the attached list with default ctrlr opts */ 268 ctrlr.opts.num_io_queues = DEFAULT_MAX_IO_QUEUES; 269 ret_ctrlr = spdk_nvme_connect(&trid, NULL, 0); 270 CU_ASSERT(ret_ctrlr == &ctrlr); 271 CU_ASSERT_EQUAL(ret_ctrlr->opts.num_io_queues, DEFAULT_MAX_IO_QUEUES); 272 /* get the ctrlr from the attached list with default ctrlr opts and consistent opts_size */ 273 opts.num_io_queues = 1; 274 ret_ctrlr = spdk_nvme_connect(&trid, &opts, sizeof(opts)); 275 CU_ASSERT(ret_ctrlr == &ctrlr); 276 CU_ASSERT_EQUAL(ret_ctrlr->opts.num_io_queues, 1); 277 CU_ASSERT_EQUAL(ret_ctrlr->opts.opts_size, sizeof(opts)); 278 279 /* opts_size is 0 */ 280 ret_ctrlr = spdk_nvme_connect(&trid, &opts, 0); 281 CU_ASSERT(ret_ctrlr == &ctrlr); 282 CU_ASSERT_EQUAL(ret_ctrlr->opts.opts_size, 0); 283 284 /* opts_size is less than sizeof(*opts) if opts != NULL */ 285 ret_ctrlr = spdk_nvme_connect(&trid, &opts, 4); 286 CU_ASSERT(ret_ctrlr == &ctrlr); 287 CU_ASSERT_EQUAL(ret_ctrlr->opts.num_io_queues, 1); 288 CU_ASSERT_EQUAL(ret_ctrlr->opts.opts_size, 4); 289 /* remove the attached ctrlr on the attached_list */ 290 MOCK_SET(nvme_ctrlr_get_ref_count, 1); 291 CU_ASSERT(spdk_nvme_detach(&ctrlr) == 0); 292 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver->shared_attached_ctrlrs)); 293 294 /* driver init passes, transport available, primary process connects ctrlr */ 295 MOCK_SET(spdk_process_is_primary, true); 296 /* setup one ctrlr on the attached_list */ 297 memset(&ctrlr, 0, sizeof(struct spdk_nvme_ctrlr)); 298 snprintf(ctrlr.trid.traddr, sizeof(ctrlr.trid.traddr), "0000:02:00.0"); 299 ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 300 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver->shared_attached_ctrlrs, &ctrlr, tailq); 301 /* get the ctrlr from the attached list */ 302 snprintf(trid.traddr, sizeof(trid.traddr), "0000:02:00.0"); 303 ret_ctrlr = spdk_nvme_connect(&trid, NULL, 0); 304 CU_ASSERT(ret_ctrlr == &ctrlr); 305 /* get the ctrlr from the attached list with default ctrlr opts */ 306 ctrlr.opts.num_io_queues = DEFAULT_MAX_IO_QUEUES; 307 ret_ctrlr = spdk_nvme_connect(&trid, NULL, 0); 308 CU_ASSERT(ret_ctrlr == &ctrlr); 309 CU_ASSERT_EQUAL(ret_ctrlr->opts.num_io_queues, DEFAULT_MAX_IO_QUEUES); 310 /* get the ctrlr from the attached list with default ctrlr opts and consistent opts_size */ 311 opts.num_io_queues = 2; 312 ret_ctrlr = spdk_nvme_connect(&trid, &opts, sizeof(opts)); 313 CU_ASSERT(ret_ctrlr == &ctrlr); 314 CU_ASSERT_EQUAL(ret_ctrlr->opts.num_io_queues, 2); 315 /* remove the attached ctrlr on the attached_list */ 316 CU_ASSERT(spdk_nvme_detach(ret_ctrlr) == 0); 317 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver->shared_attached_ctrlrs)); 318 319 /* test driver init failure return */ 320 MOCK_SET(spdk_process_is_primary, false); 321 MOCK_SET(spdk_memzone_lookup, NULL); 322 ret_ctrlr = spdk_nvme_connect(&trid, NULL, 0); 323 CU_ASSERT(ret_ctrlr == NULL); 324 } 325 326 static struct spdk_nvme_probe_ctx * 327 test_nvme_init_get_probe_ctx(void) 328 { 329 struct spdk_nvme_probe_ctx *probe_ctx; 330 331 probe_ctx = calloc(1, sizeof(*probe_ctx)); 332 SPDK_CU_ASSERT_FATAL(probe_ctx != NULL); 333 TAILQ_INIT(&probe_ctx->init_ctrlrs); 334 335 return probe_ctx; 336 } 337 338 static void 339 test_nvme_init_controllers(void) 340 { 341 int rc = 0; 342 struct nvme_driver test_driver; 343 void *cb_ctx = NULL; 344 spdk_nvme_attach_cb attach_cb = dummy_attach_cb; 345 struct spdk_nvme_probe_ctx *probe_ctx; 346 struct spdk_nvme_ctrlr *ctrlr; 347 pthread_mutexattr_t attr; 348 349 g_spdk_nvme_driver = &test_driver; 350 ctrlr = calloc(1, sizeof(*ctrlr)); 351 SPDK_CU_ASSERT_FATAL(ctrlr != NULL); 352 ctrlr->trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 353 CU_ASSERT(pthread_mutexattr_init(&attr) == 0); 354 CU_ASSERT(pthread_mutex_init(&ctrlr->ctrlr_lock, &attr) == 0); 355 CU_ASSERT(pthread_mutex_init(&test_driver.lock, &attr) == 0); 356 TAILQ_INIT(&test_driver.shared_attached_ctrlrs); 357 358 /* 359 * Try to initialize, but nvme_ctrlr_process_init will fail. 360 * Verify correct behavior when it does. 361 */ 362 MOCK_SET(nvme_ctrlr_process_init, 1); 363 MOCK_SET(spdk_process_is_primary, 1); 364 g_spdk_nvme_driver->initialized = false; 365 ut_destruct_called = false; 366 probe_ctx = test_nvme_init_get_probe_ctx(); 367 TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq); 368 probe_ctx->cb_ctx = cb_ctx; 369 probe_ctx->attach_cb = attach_cb; 370 probe_ctx->trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 371 rc = nvme_init_controllers(probe_ctx); 372 CU_ASSERT(rc == 0); 373 CU_ASSERT(g_spdk_nvme_driver->initialized == true); 374 CU_ASSERT(ut_destruct_called == true); 375 376 /* 377 * Controller init OK, need to move the controller state machine 378 * forward by setting the ctrl state so that it can be moved 379 * the shared_attached_ctrlrs list. 380 */ 381 probe_ctx = test_nvme_init_get_probe_ctx(); 382 TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq); 383 ctrlr->state = NVME_CTRLR_STATE_READY; 384 MOCK_SET(nvme_ctrlr_process_init, 0); 385 rc = nvme_init_controllers(probe_ctx); 386 CU_ASSERT(rc == 0); 387 CU_ASSERT(ut_attach_cb_called == true); 388 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs)); 389 CU_ASSERT(TAILQ_FIRST(&g_spdk_nvme_driver->shared_attached_ctrlrs) == ctrlr); 390 TAILQ_REMOVE(&g_spdk_nvme_driver->shared_attached_ctrlrs, ctrlr, tailq); 391 392 /* 393 * Reset to initial state 394 */ 395 CU_ASSERT(pthread_mutex_destroy(&ctrlr->ctrlr_lock) == 0); 396 memset(ctrlr, 0, sizeof(struct spdk_nvme_ctrlr)); 397 CU_ASSERT(pthread_mutex_init(&ctrlr->ctrlr_lock, &attr) == 0); 398 399 /* 400 * Non-PCIe controllers should be added to the per-process list, not the shared list. 401 */ 402 ctrlr->trid.trtype = SPDK_NVME_TRANSPORT_RDMA; 403 probe_ctx = test_nvme_init_get_probe_ctx(); 404 TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq); 405 ctrlr->state = NVME_CTRLR_STATE_READY; 406 MOCK_SET(nvme_ctrlr_process_init, 0); 407 rc = nvme_init_controllers(probe_ctx); 408 CU_ASSERT(rc == 0); 409 CU_ASSERT(ut_attach_cb_called == true); 410 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver->shared_attached_ctrlrs)); 411 CU_ASSERT(TAILQ_FIRST(&g_nvme_attached_ctrlrs) == ctrlr); 412 TAILQ_REMOVE(&g_nvme_attached_ctrlrs, ctrlr, tailq); 413 CU_ASSERT(pthread_mutex_destroy(&ctrlr->ctrlr_lock) == 0); 414 free(ctrlr); 415 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs)); 416 417 g_spdk_nvme_driver = NULL; 418 pthread_mutexattr_destroy(&attr); 419 pthread_mutex_destroy(&test_driver.lock); 420 } 421 422 static void 423 test_nvme_driver_init(void) 424 { 425 int rc; 426 struct nvme_driver dummy; 427 g_spdk_nvme_driver = &dummy; 428 429 /* adjust this so testing doesn't take so long */ 430 g_nvme_driver_timeout_ms = 100; 431 432 /* process is primary and mem already reserved */ 433 MOCK_SET(spdk_process_is_primary, true); 434 dummy.initialized = true; 435 rc = nvme_driver_init(); 436 CU_ASSERT(rc == 0); 437 438 /* 439 * Process is primary and mem not yet reserved but the call 440 * to spdk_memzone_reserve() returns NULL. 441 */ 442 g_spdk_nvme_driver = NULL; 443 MOCK_SET(spdk_process_is_primary, true); 444 MOCK_SET(spdk_memzone_reserve, NULL); 445 rc = nvme_driver_init(); 446 CU_ASSERT(rc == -1); 447 448 /* process is not primary, no mem already reserved */ 449 MOCK_SET(spdk_process_is_primary, false); 450 MOCK_SET(spdk_memzone_lookup, NULL); 451 g_spdk_nvme_driver = NULL; 452 rc = nvme_driver_init(); 453 CU_ASSERT(rc == -1); 454 455 /* process is not primary, mem is already reserved & init'd */ 456 MOCK_SET(spdk_process_is_primary, false); 457 MOCK_SET(spdk_memzone_lookup, (void *)&dummy); 458 dummy.initialized = true; 459 rc = nvme_driver_init(); 460 CU_ASSERT(rc == 0); 461 462 /* process is not primary, mem is reserved but not initialized */ 463 /* and times out */ 464 MOCK_SET(spdk_process_is_primary, false); 465 MOCK_SET(spdk_memzone_reserve, (void *)&dummy); 466 dummy.initialized = false; 467 rc = nvme_driver_init(); 468 CU_ASSERT(rc == -1); 469 470 /* process is primary, got mem but mutex won't init */ 471 MOCK_SET(spdk_process_is_primary, true); 472 MOCK_SET(spdk_memzone_reserve, (void *)&dummy); 473 MOCK_SET(pthread_mutexattr_init, -1); 474 g_spdk_nvme_driver = NULL; 475 dummy.initialized = true; 476 rc = nvme_driver_init(); 477 /* for FreeBSD we can't can't effectively mock this path */ 478 #ifndef __FreeBSD__ 479 CU_ASSERT(rc != 0); 480 #else 481 CU_ASSERT(rc == 0); 482 #endif 483 484 /* process is primary, got mem, mutex OK */ 485 MOCK_SET(spdk_process_is_primary, true); 486 MOCK_CLEAR(pthread_mutexattr_init); 487 g_spdk_nvme_driver = NULL; 488 rc = nvme_driver_init(); 489 CU_ASSERT(g_spdk_nvme_driver->initialized == false); 490 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver->shared_attached_ctrlrs)); 491 CU_ASSERT(rc == 0); 492 493 g_spdk_nvme_driver = NULL; 494 MOCK_CLEAR(spdk_memzone_reserve); 495 MOCK_CLEAR(spdk_memzone_lookup); 496 } 497 498 static void 499 test_spdk_nvme_detach(void) 500 { 501 int rc = 1; 502 struct spdk_nvme_ctrlr ctrlr; 503 struct spdk_nvme_ctrlr *ret_ctrlr; 504 struct nvme_driver test_driver; 505 506 memset(&ctrlr, 0, sizeof(ctrlr)); 507 ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 508 509 g_spdk_nvme_driver = &test_driver; 510 TAILQ_INIT(&test_driver.shared_attached_ctrlrs); 511 TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr, tailq); 512 CU_ASSERT(pthread_mutex_init(&test_driver.lock, NULL) == 0); 513 514 /* 515 * Controllers are ref counted so mock the function that returns 516 * the ref count so that detach will actually call the destruct 517 * function which we've mocked simply to verify that it gets 518 * called (we aren't testing what the real destruct function does 519 * here.) 520 */ 521 MOCK_SET(nvme_ctrlr_get_ref_count, 1); 522 rc = spdk_nvme_detach(&ctrlr); 523 ret_ctrlr = TAILQ_FIRST(&test_driver.shared_attached_ctrlrs); 524 CU_ASSERT(ret_ctrlr == NULL); 525 CU_ASSERT(ut_destruct_called == true); 526 CU_ASSERT(rc == 0); 527 528 /* 529 * Mock the ref count to 1 so we confirm that the destruct 530 * function is not called and that attached ctrl list is 531 * not empty. 532 */ 533 MOCK_SET(nvme_ctrlr_get_ref_count, 2); 534 TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr, tailq); 535 ut_destruct_called = false; 536 rc = spdk_nvme_detach(&ctrlr); 537 ret_ctrlr = TAILQ_FIRST(&test_driver.shared_attached_ctrlrs); 538 CU_ASSERT(ret_ctrlr != NULL); 539 CU_ASSERT(ut_destruct_called == false); 540 CU_ASSERT(rc == 0); 541 542 /* 543 * Non-PCIe controllers should be on the per-process attached_ctrlrs list, not the 544 * shared_attached_ctrlrs list. Test an RDMA controller and ensure it is removed 545 * from the correct list. 546 */ 547 memset(&ctrlr, 0, sizeof(ctrlr)); 548 ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_RDMA; 549 TAILQ_INIT(&g_nvme_attached_ctrlrs); 550 TAILQ_INSERT_TAIL(&g_nvme_attached_ctrlrs, &ctrlr, tailq); 551 MOCK_SET(nvme_ctrlr_get_ref_count, 1); 552 rc = spdk_nvme_detach(&ctrlr); 553 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs)); 554 CU_ASSERT(ut_destruct_called == true); 555 CU_ASSERT(rc == 0); 556 557 g_spdk_nvme_driver = NULL; 558 pthread_mutex_destroy(&test_driver.lock); 559 } 560 561 static void 562 test_nvme_completion_poll_cb(void) 563 { 564 struct nvme_completion_poll_status *status; 565 struct spdk_nvme_cpl cpl; 566 567 status = calloc(1, sizeof(*status)); 568 SPDK_CU_ASSERT_FATAL(status != NULL); 569 570 memset(&cpl, 0xff, sizeof(cpl)); 571 572 nvme_completion_poll_cb(status, &cpl); 573 CU_ASSERT(status->done == true); 574 CU_ASSERT(memcmp(&cpl, &status->cpl, 575 sizeof(struct spdk_nvme_cpl)) == 0); 576 577 free(status); 578 } 579 580 /* stub callback used by test_nvme_user_copy_cmd_complete() */ 581 static struct spdk_nvme_cpl ut_spdk_nvme_cpl = {0}; 582 static void 583 dummy_cb(void *user_cb_arg, struct spdk_nvme_cpl *cpl) 584 { 585 ut_spdk_nvme_cpl = *cpl; 586 } 587 588 static void 589 test_nvme_user_copy_cmd_complete(void) 590 { 591 struct nvme_request req; 592 int test_data = 0xdeadbeef; 593 int buff_size = sizeof(int); 594 void *user_buffer, *buff; 595 int user_cb_arg = 0x123; 596 static struct spdk_nvme_cpl cpl; 597 598 memset(&req, 0, sizeof(req)); 599 memset(&cpl, 0x5a, sizeof(cpl)); 600 601 /* test without a user buffer provided */ 602 req.user_cb_fn = (void *)dummy_cb; 603 req.user_cb_arg = (void *)&user_cb_arg; 604 nvme_user_copy_cmd_complete(&req, &cpl); 605 CU_ASSERT(memcmp(&ut_spdk_nvme_cpl, &cpl, sizeof(cpl)) == 0); 606 CU_ASSERT(req.user_cb_fn == NULL); 607 CU_ASSERT(req.user_cb_arg == NULL); 608 CU_ASSERT(req.user_buffer == NULL); 609 610 /* test with a user buffer provided */ 611 user_buffer = malloc(buff_size); 612 req.user_cb_fn = (void *)dummy_cb; 613 req.user_cb_arg = (void *)&user_cb_arg; 614 req.user_buffer = user_buffer; 615 SPDK_CU_ASSERT_FATAL(req.user_buffer != NULL); 616 memset(req.user_buffer, 0, buff_size); 617 req.payload_size = buff_size; 618 buff = spdk_zmalloc(buff_size, 0x100, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 619 SPDK_CU_ASSERT_FATAL(buff != NULL); 620 req.payload = NVME_PAYLOAD_CONTIG(buff, NULL); 621 memcpy(buff, &test_data, buff_size); 622 req.cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 623 req.pid = getpid(); 624 625 /* zero out the test value set in the callback */ 626 memset(&ut_spdk_nvme_cpl, 0, sizeof(ut_spdk_nvme_cpl)); 627 628 nvme_user_copy_cmd_complete(&req, &cpl); 629 CU_ASSERT(memcmp(user_buffer, &test_data, buff_size) == 0); 630 CU_ASSERT(memcmp(&ut_spdk_nvme_cpl, &cpl, sizeof(cpl)) == 0); 631 CU_ASSERT(req.user_cb_fn == NULL); 632 CU_ASSERT(req.user_cb_arg == NULL); 633 CU_ASSERT(req.user_buffer == NULL); 634 635 /* 636 * Now test the same path as above but this time choose an opc 637 * that results in a different data transfer type. 638 */ 639 memset(&ut_spdk_nvme_cpl, 0, sizeof(ut_spdk_nvme_cpl)); 640 req.user_cb_fn = (void *)dummy_cb; 641 req.user_cb_arg = (void *)&user_cb_arg; 642 req.user_buffer = user_buffer; 643 memset(req.user_buffer, 0, buff_size); 644 buff = spdk_zmalloc(buff_size, 0x100, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 645 SPDK_CU_ASSERT_FATAL(buff != NULL); 646 req.payload = NVME_PAYLOAD_CONTIG(buff, NULL); 647 memcpy(buff, &test_data, buff_size); 648 req.cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 649 nvme_user_copy_cmd_complete(&req, &cpl); 650 CU_ASSERT(memcmp(user_buffer, &test_data, buff_size) != 0); 651 CU_ASSERT(memcmp(&ut_spdk_nvme_cpl, &cpl, sizeof(cpl)) == 0); 652 CU_ASSERT(req.user_cb_fn == NULL); 653 CU_ASSERT(req.user_cb_arg == NULL); 654 CU_ASSERT(req.user_buffer == NULL); 655 656 /* clean up */ 657 free(user_buffer); 658 } 659 660 static void 661 test_nvme_allocate_request_null(void) 662 { 663 struct spdk_nvme_qpair qpair = {}; 664 spdk_nvme_cmd_cb cb_fn = (spdk_nvme_cmd_cb)0x1234; 665 void *cb_arg = (void *)0x5678; 666 struct nvme_request *req = NULL; 667 struct nvme_request dummy_req; 668 669 STAILQ_INIT(&qpair.free_req); 670 STAILQ_INIT(&qpair.queued_req); 671 672 /* 673 * Put a dummy on the queue so we can make a request 674 * and confirm that what comes back is what we expect. 675 */ 676 STAILQ_INSERT_HEAD(&qpair.free_req, &dummy_req, stailq); 677 678 req = nvme_allocate_request_null(&qpair, cb_fn, cb_arg); 679 680 /* 681 * Compare the req with the parameters that we passed in 682 * as well as what the function is supposed to update. 683 */ 684 SPDK_CU_ASSERT_FATAL(req != NULL); 685 CU_ASSERT(req->cb_fn == cb_fn); 686 CU_ASSERT(req->cb_arg == cb_arg); 687 CU_ASSERT(req->pid == getpid()); 688 CU_ASSERT(nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_CONTIG); 689 CU_ASSERT(req->payload.md == NULL); 690 CU_ASSERT(req->payload.contig_or_cb_arg == NULL); 691 } 692 693 static void 694 test_nvme_allocate_request(void) 695 { 696 struct spdk_nvme_qpair qpair; 697 struct nvme_payload payload; 698 uint32_t payload_struct_size = sizeof(payload); 699 spdk_nvme_cmd_cb cb_fn = (spdk_nvme_cmd_cb)0x1234; 700 void *cb_arg = (void *)0x6789; 701 struct nvme_request *req = NULL; 702 struct nvme_request dummy_req; 703 704 /* Fill the whole payload struct with a known pattern */ 705 memset(&payload, 0x5a, payload_struct_size); 706 STAILQ_INIT(&qpair.free_req); 707 STAILQ_INIT(&qpair.queued_req); 708 qpair.num_outstanding_reqs = 0; 709 710 /* Test trying to allocate a request when no requests are available */ 711 req = nvme_allocate_request(&qpair, &payload, payload_struct_size, 0, 712 cb_fn, cb_arg); 713 CU_ASSERT(req == NULL); 714 CU_ASSERT(qpair.num_outstanding_reqs == 0); 715 716 /* put a dummy on the queue, and then allocate one */ 717 STAILQ_INSERT_HEAD(&qpair.free_req, &dummy_req, stailq); 718 req = nvme_allocate_request(&qpair, &payload, payload_struct_size, 0, 719 cb_fn, cb_arg); 720 721 /* all the req elements should now match the passed in parameters */ 722 SPDK_CU_ASSERT_FATAL(req != NULL); 723 CU_ASSERT(qpair.num_outstanding_reqs == 1); 724 CU_ASSERT(req->cb_fn == cb_fn); 725 CU_ASSERT(req->cb_arg == cb_arg); 726 CU_ASSERT(memcmp(&req->payload, &payload, payload_struct_size) == 0); 727 CU_ASSERT(req->payload_size == payload_struct_size); 728 CU_ASSERT(req->pid == getpid()); 729 } 730 731 static void 732 test_nvme_free_request(void) 733 { 734 struct nvme_request match_req; 735 struct spdk_nvme_qpair qpair = {0}; 736 struct nvme_request *req; 737 738 /* put a req on the Q, take it off and compare */ 739 memset(&match_req.cmd, 0x5a, sizeof(struct spdk_nvme_cmd)); 740 match_req.qpair = &qpair; 741 qpair.num_outstanding_reqs = 1; 742 /* the code under tests asserts this condition */ 743 match_req.num_children = 0; 744 STAILQ_INIT(&qpair.free_req); 745 match_req.qpair->reserved_req = NULL; 746 747 nvme_free_request(&match_req); 748 req = STAILQ_FIRST(&match_req.qpair->free_req); 749 CU_ASSERT(req == &match_req); 750 CU_ASSERT(qpair.num_outstanding_reqs == 0); 751 } 752 753 static void 754 test_nvme_allocate_request_user_copy(void) 755 { 756 struct spdk_nvme_qpair qpair; 757 spdk_nvme_cmd_cb cb_fn = (spdk_nvme_cmd_cb)0x12345; 758 void *cb_arg = (void *)0x12345; 759 bool host_to_controller = true; 760 struct nvme_request *req; 761 struct nvme_request dummy_req; 762 int test_data = 0xdeadbeef; 763 void *buffer = NULL; 764 uint32_t payload_size = sizeof(int); 765 766 STAILQ_INIT(&qpair.free_req); 767 STAILQ_INIT(&qpair.queued_req); 768 769 /* no buffer or valid payload size, early NULL return */ 770 req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, 771 cb_arg, host_to_controller); 772 CU_ASSERT(req == NULL); 773 774 /* good buffer and valid payload size */ 775 buffer = malloc(payload_size); 776 SPDK_CU_ASSERT_FATAL(buffer != NULL); 777 memcpy(buffer, &test_data, payload_size); 778 779 /* put a dummy on the queue */ 780 STAILQ_INSERT_HEAD(&qpair.free_req, &dummy_req, stailq); 781 782 MOCK_CLEAR(spdk_malloc); 783 MOCK_CLEAR(spdk_zmalloc); 784 req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, 785 cb_arg, host_to_controller); 786 SPDK_CU_ASSERT_FATAL(req != NULL); 787 CU_ASSERT(req->user_cb_fn == cb_fn); 788 CU_ASSERT(req->user_cb_arg == cb_arg); 789 CU_ASSERT(req->user_buffer == buffer); 790 CU_ASSERT(req->cb_arg == req); 791 CU_ASSERT(memcmp(req->payload.contig_or_cb_arg, buffer, payload_size) == 0); 792 spdk_free(req->payload.contig_or_cb_arg); 793 794 /* same thing but additional path coverage, no copy */ 795 host_to_controller = false; 796 STAILQ_INSERT_HEAD(&qpair.free_req, &dummy_req, stailq); 797 798 req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, 799 cb_arg, host_to_controller); 800 SPDK_CU_ASSERT_FATAL(req != NULL); 801 CU_ASSERT(req->user_cb_fn == cb_fn); 802 CU_ASSERT(req->user_cb_arg == cb_arg); 803 CU_ASSERT(req->user_buffer == buffer); 804 CU_ASSERT(req->cb_arg == req); 805 CU_ASSERT(memcmp(req->payload.contig_or_cb_arg, buffer, payload_size) != 0); 806 spdk_free(req->payload.contig_or_cb_arg); 807 808 /* good buffer and valid payload size but make spdk_zmalloc fail */ 809 /* set the mock pointer to NULL for spdk_zmalloc */ 810 MOCK_SET(spdk_zmalloc, NULL); 811 req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, 812 cb_arg, host_to_controller); 813 CU_ASSERT(req == NULL); 814 free(buffer); 815 MOCK_CLEAR(spdk_zmalloc); 816 } 817 818 static void 819 test_nvme_ctrlr_probe(void) 820 { 821 int rc = 0; 822 struct spdk_nvme_ctrlr ctrlr = {}; 823 struct spdk_nvme_qpair qpair = {}; 824 const struct spdk_nvme_transport_id trid = {}; 825 struct spdk_nvme_probe_ctx probe_ctx = {}; 826 void *devhandle = NULL; 827 void *cb_ctx = NULL; 828 struct spdk_nvme_ctrlr *dummy = NULL; 829 830 ctrlr.adminq = &qpair; 831 832 TAILQ_INIT(&probe_ctx.init_ctrlrs); 833 nvme_driver_init(); 834 835 /* test when probe_cb returns false */ 836 837 MOCK_SET(dummy_probe_cb, false); 838 nvme_probe_ctx_init(&probe_ctx, &trid, cb_ctx, dummy_probe_cb, NULL, NULL); 839 rc = nvme_ctrlr_probe(&trid, &probe_ctx, devhandle); 840 CU_ASSERT(rc == 1); 841 842 /* probe_cb returns true but we can't construct a ctrl */ 843 MOCK_SET(dummy_probe_cb, true); 844 MOCK_SET(nvme_transport_ctrlr_construct, NULL); 845 nvme_probe_ctx_init(&probe_ctx, &trid, cb_ctx, dummy_probe_cb, NULL, NULL); 846 rc = nvme_ctrlr_probe(&trid, &probe_ctx, devhandle); 847 CU_ASSERT(rc == -1); 848 849 /* happy path */ 850 MOCK_SET(dummy_probe_cb, true); 851 MOCK_SET(nvme_transport_ctrlr_construct, &ctrlr); 852 nvme_probe_ctx_init(&probe_ctx, &trid, cb_ctx, dummy_probe_cb, NULL, NULL); 853 rc = nvme_ctrlr_probe(&trid, &probe_ctx, devhandle); 854 CU_ASSERT(rc == 0); 855 dummy = TAILQ_FIRST(&probe_ctx.init_ctrlrs); 856 SPDK_CU_ASSERT_FATAL(dummy != NULL); 857 CU_ASSERT(dummy == ut_nvme_transport_ctrlr_construct); 858 TAILQ_REMOVE(&probe_ctx.init_ctrlrs, dummy, tailq); 859 MOCK_CLEAR_P(nvme_transport_ctrlr_construct); 860 861 free(g_spdk_nvme_driver); 862 } 863 864 static void 865 test_nvme_robust_mutex_init_shared(void) 866 { 867 pthread_mutex_t mtx; 868 int rc = 0; 869 870 /* test where both pthread calls succeed */ 871 MOCK_SET(pthread_mutexattr_init, 0); 872 MOCK_SET(pthread_mutex_init, 0); 873 rc = nvme_robust_mutex_init_shared(&mtx); 874 CU_ASSERT(rc == 0); 875 876 /* test where we can't init attr's but init mutex works */ 877 MOCK_SET(pthread_mutexattr_init, -1); 878 MOCK_SET(pthread_mutex_init, 0); 879 rc = nvme_robust_mutex_init_shared(&mtx); 880 /* for FreeBSD the only possible return value is 0 */ 881 #ifndef __FreeBSD__ 882 CU_ASSERT(rc != 0); 883 #else 884 CU_ASSERT(rc == 0); 885 #endif 886 887 /* test where we can init attr's but the mutex init fails */ 888 MOCK_SET(pthread_mutexattr_init, 0); 889 MOCK_SET(pthread_mutex_init, -1); 890 rc = nvme_robust_mutex_init_shared(&mtx); 891 /* for FreeBSD the only possible return value is 0 */ 892 #ifndef __FreeBSD__ 893 CU_ASSERT(rc != 0); 894 #else 895 CU_ASSERT(rc == 0); 896 #endif 897 MOCK_CLEAR(pthread_mutex_init); 898 } 899 900 static void 901 test_opc_data_transfer(void) 902 { 903 enum spdk_nvme_data_transfer xfer; 904 905 xfer = spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_FLUSH); 906 CU_ASSERT(xfer == SPDK_NVME_DATA_NONE); 907 908 xfer = spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_WRITE); 909 CU_ASSERT(xfer == SPDK_NVME_DATA_HOST_TO_CONTROLLER); 910 911 xfer = spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_READ); 912 CU_ASSERT(xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST); 913 914 xfer = spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_GET_LOG_PAGE); 915 CU_ASSERT(xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST); 916 } 917 918 static void 919 test_trid_parse_and_compare(void) 920 { 921 struct spdk_nvme_transport_id trid1, trid2; 922 int ret; 923 924 /* set trid1 trid2 value to id parse */ 925 ret = spdk_nvme_transport_id_parse(NULL, "trtype:PCIe traddr:0000:04:00.0"); 926 CU_ASSERT(ret == -EINVAL); 927 memset(&trid1, 0, sizeof(trid1)); 928 ret = spdk_nvme_transport_id_parse(&trid1, NULL); 929 CU_ASSERT(ret == -EINVAL); 930 ret = spdk_nvme_transport_id_parse(NULL, NULL); 931 CU_ASSERT(ret == -EINVAL); 932 memset(&trid1, 0, sizeof(trid1)); 933 ret = spdk_nvme_transport_id_parse(&trid1, "trtype-PCIe traddr-0000-04-00.0"); 934 CU_ASSERT(ret == -EINVAL); 935 memset(&trid1, 0, sizeof(trid1)); 936 ret = spdk_nvme_transport_id_parse(&trid1, "trtype-PCIe traddr-0000-04-00.0-:"); 937 CU_ASSERT(ret == -EINVAL); 938 memset(&trid1, 0, sizeof(trid1)); 939 ret = spdk_nvme_transport_id_parse(&trid1, " \t\n:"); 940 CU_ASSERT(ret == -EINVAL); 941 memset(&trid1, 0, sizeof(trid1)); 942 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1, 943 "trtype:rdma\n" 944 "adrfam:ipv4\n" 945 "traddr:192.168.100.8\n" 946 "trsvcid:4420\n" 947 "subnqn:nqn.2014-08.org.nvmexpress.discovery") == 0); 948 CU_ASSERT(trid1.trtype == SPDK_NVME_TRANSPORT_RDMA); 949 CU_ASSERT(trid1.adrfam == SPDK_NVMF_ADRFAM_IPV4); 950 CU_ASSERT(strcmp(trid1.traddr, "192.168.100.8") == 0); 951 CU_ASSERT(strcmp(trid1.trsvcid, "4420") == 0); 952 CU_ASSERT(strcmp(trid1.subnqn, "nqn.2014-08.org.nvmexpress.discovery") == 0); 953 954 memset(&trid2, 0, sizeof(trid2)); 955 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2, "trtype:PCIe traddr:0000:04:00.0") == 0); 956 CU_ASSERT(trid2.trtype == SPDK_NVME_TRANSPORT_PCIE); 957 CU_ASSERT(strcmp(trid2.traddr, "0000:04:00.0") == 0); 958 959 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1, &trid2) != 0); 960 961 /* set trid1 trid2 and test id_compare */ 962 memset_trid(&trid1, &trid2); 963 trid1.adrfam = SPDK_NVMF_ADRFAM_IPV6; 964 trid2.adrfam = SPDK_NVMF_ADRFAM_IPV4; 965 ret = spdk_nvme_transport_id_compare(&trid1, &trid2); 966 CU_ASSERT(ret > 0); 967 968 memset_trid(&trid1, &trid2); 969 snprintf(trid1.traddr, sizeof(trid1.traddr), "192.168.100.8"); 970 snprintf(trid2.traddr, sizeof(trid2.traddr), "192.168.100.9"); 971 ret = spdk_nvme_transport_id_compare(&trid1, &trid2); 972 CU_ASSERT(ret < 0); 973 974 memset_trid(&trid1, &trid2); 975 snprintf(trid1.trsvcid, sizeof(trid1.trsvcid), "4420"); 976 snprintf(trid2.trsvcid, sizeof(trid2.trsvcid), "4421"); 977 ret = spdk_nvme_transport_id_compare(&trid1, &trid2); 978 CU_ASSERT(ret < 0); 979 980 memset_trid(&trid1, &trid2); 981 snprintf(trid1.subnqn, sizeof(trid1.subnqn), "subnqn:nqn.2016-08.org.nvmexpress.discovery"); 982 snprintf(trid2.subnqn, sizeof(trid2.subnqn), "subnqn:nqn.2017-08.org.nvmexpress.discovery"); 983 ret = spdk_nvme_transport_id_compare(&trid1, &trid2); 984 CU_ASSERT(ret < 0); 985 986 memset_trid(&trid1, &trid2); 987 snprintf(trid1.subnqn, sizeof(trid1.subnqn), "subnqn:nqn.2016-08.org.nvmexpress.discovery"); 988 snprintf(trid2.subnqn, sizeof(trid2.subnqn), "subnqn:nqn.2016-08.org.nvmexpress.discovery"); 989 ret = spdk_nvme_transport_id_compare(&trid1, &trid2); 990 CU_ASSERT(ret == 0); 991 992 memset_trid(&trid1, &trid2); 993 snprintf(trid1.subnqn, sizeof(trid1.subnqn), "subnqn:nqn.2016-08.org.nvmexpress.discovery"); 994 snprintf(trid2.subnqn, sizeof(trid2.subnqn), "subnqn:nqn.2016-08.org.Nvmexpress.discovery"); 995 ret = spdk_nvme_transport_id_compare(&trid1, &trid2); 996 CU_ASSERT(ret > 0); 997 998 memset_trid(&trid1, &trid2); 999 ret = spdk_nvme_transport_id_compare(&trid1, &trid2); 1000 CU_ASSERT(ret == 0); 1001 1002 /* Compare PCI addresses via spdk_pci_addr_compare (rather than as strings) */ 1003 memset_trid(&trid1, &trid2); 1004 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1, "trtype:PCIe traddr:0000:04:00.0") == 0); 1005 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2, "trtype:PCIe traddr:04:00.0") == 0); 1006 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1, &trid2) == 0); 1007 1008 memset_trid(&trid1, &trid2); 1009 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1, "trtype:PCIe traddr:0000:05:00.0") == 0); 1010 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2, "trtype:PCIe traddr:04:00.0") == 0); 1011 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1, &trid2) > 0); 1012 1013 memset_trid(&trid1, &trid2); 1014 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1, "trtype:PCIe traddr:0000:04:00.0") == 0); 1015 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2, "trtype:PCIe traddr:05:00.0") == 0); 1016 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1, &trid2) < 0); 1017 1018 memset_trid(&trid1, &trid2); 1019 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1, "trtype=PCIe traddr=0000:04:00.0") == 0); 1020 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2, "trtype=PCIe traddr=05:00.0") == 0); 1021 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1, &trid2) < 0); 1022 1023 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1, 1024 "trtype:tcp\n" 1025 "adrfam:ipv4\n" 1026 "traddr:192.168.100.8\n" 1027 "trsvcid:4420\n" 1028 "priority:2\n" 1029 "subnqn:nqn.2014-08.org.nvmexpress.discovery") == 0); 1030 CU_ASSERT(trid1.priority == 2); 1031 } 1032 1033 static void 1034 test_spdk_nvme_transport_id_parse_trtype(void) 1035 { 1036 1037 enum spdk_nvme_transport_type *trtype; 1038 enum spdk_nvme_transport_type sct; 1039 char *str; 1040 1041 trtype = NULL; 1042 str = "unit_test"; 1043 1044 /* test function returned value when trtype is NULL but str not NULL */ 1045 CU_ASSERT(spdk_nvme_transport_id_parse_trtype(trtype, str) == (-EINVAL)); 1046 1047 /* test function returned value when str is NULL but trtype not NULL */ 1048 trtype = &sct; 1049 str = NULL; 1050 CU_ASSERT(spdk_nvme_transport_id_parse_trtype(trtype, str) == (-EINVAL)); 1051 1052 /* test function returned value when str and strtype not NULL, but str value 1053 * not "PCIe" or "RDMA" */ 1054 str = "unit_test"; 1055 CU_ASSERT(spdk_nvme_transport_id_parse_trtype(trtype, str) == 0); 1056 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_CUSTOM); 1057 1058 /* test trtype value when use function "strcasecmp" to compare str and "PCIe",not case-sensitive */ 1059 str = "PCIe"; 1060 spdk_nvme_transport_id_parse_trtype(trtype, str); 1061 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_PCIE); 1062 1063 str = "pciE"; 1064 spdk_nvme_transport_id_parse_trtype(trtype, str); 1065 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_PCIE); 1066 1067 /* test trtype value when use function "strcasecmp" to compare str and "RDMA",not case-sensitive */ 1068 str = "RDMA"; 1069 spdk_nvme_transport_id_parse_trtype(trtype, str); 1070 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_RDMA); 1071 1072 str = "rdma"; 1073 spdk_nvme_transport_id_parse_trtype(trtype, str); 1074 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_RDMA); 1075 1076 /* test trtype value when use function "strcasecmp" to compare str and "FC",not case-sensitive */ 1077 str = "FC"; 1078 spdk_nvme_transport_id_parse_trtype(trtype, str); 1079 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_FC); 1080 1081 str = "fc"; 1082 spdk_nvme_transport_id_parse_trtype(trtype, str); 1083 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_FC); 1084 1085 /* test trtype value when use function "strcasecmp" to compare str and "TCP",not case-sensitive */ 1086 str = "TCP"; 1087 spdk_nvme_transport_id_parse_trtype(trtype, str); 1088 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_TCP); 1089 1090 str = "tcp"; 1091 spdk_nvme_transport_id_parse_trtype(trtype, str); 1092 CU_ASSERT((*trtype) == SPDK_NVME_TRANSPORT_TCP); 1093 } 1094 1095 static void 1096 test_spdk_nvme_transport_id_parse_adrfam(void) 1097 { 1098 1099 enum spdk_nvmf_adrfam *adrfam; 1100 enum spdk_nvmf_adrfam sct; 1101 char *str; 1102 1103 adrfam = NULL; 1104 str = "unit_test"; 1105 1106 /* test function returned value when adrfam is NULL but str not NULL */ 1107 CU_ASSERT(spdk_nvme_transport_id_parse_adrfam(adrfam, str) == (-EINVAL)); 1108 1109 /* test function returned value when str is NULL but adrfam not NULL */ 1110 adrfam = &sct; 1111 str = NULL; 1112 CU_ASSERT(spdk_nvme_transport_id_parse_adrfam(adrfam, str) == (-EINVAL)); 1113 1114 /* test function returned value when str and adrfam not NULL, but str value 1115 * not "IPv4" or "IPv6" or "IB" or "FC" */ 1116 str = "unit_test"; 1117 CU_ASSERT(spdk_nvme_transport_id_parse_adrfam(adrfam, str) == (-ENOENT)); 1118 1119 /* test adrfam value when use function "strcasecmp" to compare str and "IPv4",not case-sensitive */ 1120 str = "IPv4"; 1121 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1122 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_IPV4); 1123 1124 str = "ipV4"; 1125 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1126 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_IPV4); 1127 1128 /* test adrfam value when use function "strcasecmp" to compare str and "IPv6",not case-sensitive */ 1129 str = "IPv6"; 1130 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1131 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_IPV6); 1132 1133 str = "ipV6"; 1134 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1135 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_IPV6); 1136 1137 /* test adrfam value when use function "strcasecmp" to compare str and "IB",not case-sensitive */ 1138 str = "IB"; 1139 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1140 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_IB); 1141 1142 str = "ib"; 1143 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1144 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_IB); 1145 1146 /* test adrfam value when use function "strcasecmp" to compare str and "FC",not case-sensitive */ 1147 str = "FC"; 1148 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1149 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_FC); 1150 1151 str = "fc"; 1152 spdk_nvme_transport_id_parse_adrfam(adrfam, str); 1153 CU_ASSERT((*adrfam) == SPDK_NVMF_ADRFAM_FC); 1154 1155 } 1156 1157 static void 1158 test_trid_trtype_str(void) 1159 { 1160 const char *s; 1161 1162 s = spdk_nvme_transport_id_trtype_str(-5); 1163 CU_ASSERT(s == NULL); 1164 1165 s = spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_PCIE); 1166 SPDK_CU_ASSERT_FATAL(s != NULL); 1167 CU_ASSERT(strcmp(s, "PCIe") == 0); 1168 1169 s = spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA); 1170 SPDK_CU_ASSERT_FATAL(s != NULL); 1171 CU_ASSERT(strcmp(s, "RDMA") == 0); 1172 1173 s = spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_FC); 1174 SPDK_CU_ASSERT_FATAL(s != NULL); 1175 CU_ASSERT(strcmp(s, "FC") == 0); 1176 1177 s = spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_TCP); 1178 SPDK_CU_ASSERT_FATAL(s != NULL); 1179 CU_ASSERT(strcmp(s, "TCP") == 0); 1180 } 1181 1182 static void 1183 test_trid_adrfam_str(void) 1184 { 1185 const char *s; 1186 1187 s = spdk_nvme_transport_id_adrfam_str(-5); 1188 CU_ASSERT(s == NULL); 1189 1190 s = spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_IPV4); 1191 SPDK_CU_ASSERT_FATAL(s != NULL); 1192 CU_ASSERT(strcmp(s, "IPv4") == 0); 1193 1194 s = spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_IPV6); 1195 SPDK_CU_ASSERT_FATAL(s != NULL); 1196 CU_ASSERT(strcmp(s, "IPv6") == 0); 1197 1198 s = spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_IB); 1199 SPDK_CU_ASSERT_FATAL(s != NULL); 1200 CU_ASSERT(strcmp(s, "IB") == 0); 1201 1202 s = spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_FC); 1203 SPDK_CU_ASSERT_FATAL(s != NULL); 1204 CU_ASSERT(strcmp(s, "FC") == 0); 1205 } 1206 1207 /* stub callback used by the test_nvme_request_check_timeout */ 1208 static bool ut_timeout_cb_call = false; 1209 static void 1210 dummy_timeout_cb(void *cb_arg, struct spdk_nvme_ctrlr *ctrlr, 1211 struct spdk_nvme_qpair *qpair, uint16_t cid) 1212 { 1213 ut_timeout_cb_call = true; 1214 } 1215 1216 static void 1217 test_nvme_request_check_timeout(void) 1218 { 1219 int rc; 1220 struct spdk_nvme_qpair qpair; 1221 struct nvme_request req; 1222 struct spdk_nvme_ctrlr_process active_proc; 1223 uint16_t cid = 0; 1224 uint64_t now_tick = 0; 1225 1226 memset(&qpair, 0x0, sizeof(qpair)); 1227 memset(&req, 0x0, sizeof(req)); 1228 memset(&active_proc, 0x0, sizeof(active_proc)); 1229 req.qpair = &qpair; 1230 active_proc.timeout_cb_fn = dummy_timeout_cb; 1231 1232 /* if have called timeout_cb_fn then return directly */ 1233 req.timed_out = true; 1234 rc = nvme_request_check_timeout(&req, cid, &active_proc, now_tick); 1235 CU_ASSERT(rc == 0); 1236 CU_ASSERT(ut_timeout_cb_call == false); 1237 1238 /* if timeout isn't enabled then return directly */ 1239 req.timed_out = false; 1240 req.submit_tick = 0; 1241 rc = nvme_request_check_timeout(&req, cid, &active_proc, now_tick); 1242 CU_ASSERT(rc == 0); 1243 CU_ASSERT(ut_timeout_cb_call == false); 1244 1245 /* req->pid isn't right then return directly */ 1246 req.submit_tick = 1; 1247 req.pid = g_spdk_nvme_pid + 1; 1248 rc = nvme_request_check_timeout(&req, cid, &active_proc, now_tick); 1249 CU_ASSERT(rc == 0); 1250 CU_ASSERT(ut_timeout_cb_call == false); 1251 1252 /* AER command has no timeout */ 1253 req.pid = g_spdk_nvme_pid; 1254 req.cmd.opc = SPDK_NVME_OPC_ASYNC_EVENT_REQUEST; 1255 rc = nvme_request_check_timeout(&req, cid, &active_proc, now_tick); 1256 CU_ASSERT(rc == 0); 1257 CU_ASSERT(ut_timeout_cb_call == false); 1258 1259 /* time isn't out */ 1260 qpair.id = 1; 1261 rc = nvme_request_check_timeout(&req, cid, &active_proc, now_tick); 1262 CU_ASSERT(rc == 1); 1263 CU_ASSERT(ut_timeout_cb_call == false); 1264 1265 now_tick = 2; 1266 rc = nvme_request_check_timeout(&req, cid, &active_proc, now_tick); 1267 CU_ASSERT(req.timed_out == true); 1268 CU_ASSERT(ut_timeout_cb_call == true); 1269 CU_ASSERT(rc == 0); 1270 } 1271 1272 struct nvme_completion_poll_status g_status; 1273 uint64_t completion_delay_us, timeout_in_usecs; 1274 int g_process_comp_result; 1275 pthread_mutex_t g_robust_lock = PTHREAD_MUTEX_INITIALIZER; 1276 1277 int 1278 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) 1279 { 1280 spdk_delay_us(completion_delay_us); 1281 1282 g_status.done = completion_delay_us < timeout_in_usecs && g_process_comp_result == 0 ? true : false; 1283 1284 return g_process_comp_result; 1285 } 1286 1287 static void 1288 test_nvme_wait_for_completion(void) 1289 { 1290 struct spdk_nvme_qpair qpair; 1291 struct spdk_nvme_ctrlr ctrlr; 1292 int rc = 0; 1293 1294 memset(&ctrlr, 0, sizeof(ctrlr)); 1295 ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 1296 memset(&qpair, 0, sizeof(qpair)); 1297 qpair.ctrlr = &ctrlr; 1298 1299 /* completion timeout */ 1300 memset(&g_status, 0, sizeof(g_status)); 1301 completion_delay_us = 2000000; 1302 timeout_in_usecs = 1000000; 1303 rc = nvme_wait_for_completion_timeout(&qpair, &g_status, timeout_in_usecs); 1304 CU_ASSERT(g_status.timed_out == true); 1305 CU_ASSERT(g_status.done == false); 1306 CU_ASSERT(rc == -ECANCELED); 1307 1308 /* spdk_nvme_qpair_process_completions returns error */ 1309 memset(&g_status, 0, sizeof(g_status)); 1310 g_process_comp_result = -1; 1311 completion_delay_us = 1000000; 1312 timeout_in_usecs = 2000000; 1313 rc = nvme_wait_for_completion_timeout(&qpair, &g_status, timeout_in_usecs); 1314 CU_ASSERT(rc == -ECANCELED); 1315 CU_ASSERT(g_status.timed_out == true); 1316 CU_ASSERT(g_status.done == false); 1317 CU_ASSERT(g_status.cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1318 CU_ASSERT(g_status.cpl.status.sc == SPDK_NVME_SC_ABORTED_SQ_DELETION); 1319 1320 g_process_comp_result = 0; 1321 1322 /* complete in time */ 1323 memset(&g_status, 0, sizeof(g_status)); 1324 completion_delay_us = 1000000; 1325 timeout_in_usecs = 2000000; 1326 rc = nvme_wait_for_completion_timeout(&qpair, &g_status, timeout_in_usecs); 1327 CU_ASSERT(g_status.timed_out == false); 1328 CU_ASSERT(g_status.done == true); 1329 CU_ASSERT(rc == 0); 1330 1331 /* nvme_wait_for_completion */ 1332 /* spdk_nvme_qpair_process_completions returns error */ 1333 memset(&g_status, 0, sizeof(g_status)); 1334 g_process_comp_result = -1; 1335 rc = nvme_wait_for_completion(&qpair, &g_status); 1336 CU_ASSERT(rc == -ECANCELED); 1337 CU_ASSERT(g_status.timed_out == true); 1338 CU_ASSERT(g_status.done == false); 1339 CU_ASSERT(g_status.cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1340 CU_ASSERT(g_status.cpl.status.sc == SPDK_NVME_SC_ABORTED_SQ_DELETION); 1341 1342 /* successful completion */ 1343 memset(&g_status, 0, sizeof(g_status)); 1344 g_process_comp_result = 0; 1345 rc = nvme_wait_for_completion(&qpair, &g_status); 1346 CU_ASSERT(rc == 0); 1347 CU_ASSERT(g_status.timed_out == false); 1348 CU_ASSERT(g_status.done == true); 1349 1350 /* completion timeout */ 1351 memset(&g_status, 0, sizeof(g_status)); 1352 completion_delay_us = 2000000; 1353 timeout_in_usecs = 1000000; 1354 rc = nvme_wait_for_completion_robust_lock_timeout(&qpair, &g_status, &g_robust_lock, 1355 timeout_in_usecs); 1356 CU_ASSERT(g_status.timed_out == true); 1357 CU_ASSERT(g_status.done == false); 1358 CU_ASSERT(rc == -ECANCELED); 1359 1360 /* spdk_nvme_qpair_process_completions returns error */ 1361 memset(&g_status, 0, sizeof(g_status)); 1362 g_process_comp_result = -1; 1363 completion_delay_us = 1000000; 1364 timeout_in_usecs = 2000000; 1365 rc = nvme_wait_for_completion_robust_lock_timeout(&qpair, &g_status, &g_robust_lock, 1366 timeout_in_usecs); 1367 CU_ASSERT(rc == -ECANCELED); 1368 CU_ASSERT(g_status.timed_out == true); 1369 CU_ASSERT(g_status.done == false); 1370 CU_ASSERT(g_status.cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1371 CU_ASSERT(g_status.cpl.status.sc == SPDK_NVME_SC_ABORTED_SQ_DELETION); 1372 1373 g_process_comp_result = 0; 1374 1375 /* complete in time */ 1376 memset(&g_status, 0, sizeof(g_status)); 1377 completion_delay_us = 1000000; 1378 timeout_in_usecs = 2000000; 1379 rc = nvme_wait_for_completion_robust_lock_timeout(&qpair, &g_status, &g_robust_lock, 1380 timeout_in_usecs); 1381 CU_ASSERT(g_status.timed_out == false); 1382 CU_ASSERT(g_status.done == true); 1383 CU_ASSERT(rc == 0); 1384 1385 /* nvme_wait_for_completion */ 1386 /* spdk_nvme_qpair_process_completions returns error */ 1387 memset(&g_status, 0, sizeof(g_status)); 1388 g_process_comp_result = -1; 1389 rc = nvme_wait_for_completion_robust_lock(&qpair, &g_status, &g_robust_lock); 1390 CU_ASSERT(rc == -ECANCELED); 1391 CU_ASSERT(g_status.timed_out == true); 1392 CU_ASSERT(g_status.done == false); 1393 CU_ASSERT(g_status.cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1394 CU_ASSERT(g_status.cpl.status.sc == SPDK_NVME_SC_ABORTED_SQ_DELETION); 1395 1396 /* successful completion */ 1397 memset(&g_status, 0, sizeof(g_status)); 1398 g_process_comp_result = 0; 1399 rc = nvme_wait_for_completion_robust_lock(&qpair, &g_status, &g_robust_lock); 1400 CU_ASSERT(rc == 0); 1401 CU_ASSERT(g_status.timed_out == false); 1402 CU_ASSERT(g_status.done == true); 1403 } 1404 1405 static void 1406 test_nvme_ctrlr_probe_internal(void) 1407 { 1408 struct spdk_nvme_probe_ctx *probe_ctx; 1409 struct spdk_nvme_transport_id trid = {}; 1410 struct nvme_driver dummy; 1411 int rc; 1412 1413 probe_ctx = calloc(1, sizeof(*probe_ctx)); 1414 CU_ASSERT(probe_ctx != NULL); 1415 1416 MOCK_SET(spdk_process_is_primary, true); 1417 MOCK_SET(spdk_memzone_reserve, (void *)&dummy); 1418 g_spdk_nvme_driver = NULL; 1419 rc = nvme_driver_init(); 1420 CU_ASSERT(rc == 0); 1421 1422 ut_test_probe_internal = true; 1423 MOCK_SET(dummy_probe_cb, true); 1424 trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 1425 nvme_probe_ctx_init(probe_ctx, &trid, NULL, dummy_probe_cb, NULL, NULL); 1426 rc = nvme_probe_internal(probe_ctx, false); 1427 CU_ASSERT(rc < 0); 1428 CU_ASSERT(TAILQ_EMPTY(&probe_ctx->init_ctrlrs)); 1429 1430 free(probe_ctx); 1431 ut_test_probe_internal = false; 1432 } 1433 1434 static void 1435 test_spdk_nvme_parse_func(void) 1436 { 1437 struct spdk_nvme_host_id hostid = {}; 1438 char str[64] = {}; 1439 const char *rt_str = NULL; 1440 uint32_t prchk_flags; 1441 int rc; 1442 1443 /* Parse prchk flags. */ 1444 prchk_flags = 0; 1445 rt_str = spdk_nvme_prchk_flags_str(SPDK_NVME_IO_FLAGS_PRCHK_REFTAG); 1446 memcpy(str, rt_str, strlen(rt_str)); 1447 1448 rc = spdk_nvme_prchk_flags_parse(&prchk_flags, str); 1449 CU_ASSERT(rc == 0); 1450 CU_ASSERT(prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG); 1451 1452 prchk_flags = 0; 1453 rt_str = spdk_nvme_prchk_flags_str(SPDK_NVME_IO_FLAGS_PRCHK_GUARD); 1454 memcpy(str, rt_str, strlen(rt_str)); 1455 1456 rc = spdk_nvme_prchk_flags_parse(&prchk_flags, str); 1457 CU_ASSERT(prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD); 1458 CU_ASSERT(rc == 0); 1459 1460 prchk_flags = 0; 1461 rt_str = spdk_nvme_prchk_flags_str(SPDK_NVME_IO_FLAGS_PRCHK_REFTAG | 1462 SPDK_NVME_IO_FLAGS_PRCHK_GUARD); 1463 memcpy(str, rt_str, strlen(rt_str)); 1464 1465 rc = spdk_nvme_prchk_flags_parse(&prchk_flags, str); 1466 CU_ASSERT(rc == 0); 1467 CU_ASSERT(prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG); 1468 CU_ASSERT(prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD); 1469 1470 rc = spdk_nvme_prchk_flags_parse(NULL, NULL); 1471 CU_ASSERT(rc == -EINVAL); 1472 1473 /* Parse host id. */ 1474 memcpy(str, "hostaddr:192.168.1.1", sizeof("hostaddr:192.168.1.1")); 1475 rc = spdk_nvme_host_id_parse(&hostid, str); 1476 CU_ASSERT(rc == 0); 1477 CU_ASSERT(!strncmp(hostid.hostaddr, "192.168.1.1", sizeof("192.168.1.1"))); 1478 1479 memset(&hostid, 0, sizeof(hostid)); 1480 memcpy(str, "hostsvcid:192.168.1.2", sizeof("hostsvcid:192.168.1.2")); 1481 rc = spdk_nvme_host_id_parse(&hostid, str); 1482 CU_ASSERT(rc == 0); 1483 CU_ASSERT(!strncmp(hostid.hostsvcid, "192.168.1.2", sizeof("192.168.1.2"))); 1484 1485 /* Unknown transport ID key */ 1486 memset(&hostid, 0, sizeof(hostid)); 1487 memcpy(str, "trtype:xxx", sizeof("trtype:xxx")); 1488 rc = spdk_nvme_host_id_parse(&hostid, str); 1489 CU_ASSERT(rc == 0); 1490 CU_ASSERT(hostid.hostaddr[0] == '\0' && hostid.hostsvcid[0] == '\0'); 1491 } 1492 1493 static void 1494 test_spdk_nvme_detach_async(void) 1495 { 1496 int rc = 1; 1497 struct spdk_nvme_ctrlr ctrlr1, ctrlr2; 1498 struct nvme_driver test_driver; 1499 struct spdk_nvme_detach_ctx *detach_ctx; 1500 struct nvme_ctrlr_detach_ctx *ctx; 1501 1502 detach_ctx = NULL; 1503 memset(&ctrlr1, 0, sizeof(ctrlr1)); 1504 ctrlr1.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 1505 memset(&ctrlr2, 0, sizeof(ctrlr2)); 1506 ctrlr2.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 1507 1508 g_spdk_nvme_driver = &test_driver; 1509 TAILQ_INIT(&test_driver.shared_attached_ctrlrs); 1510 TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr1, tailq); 1511 TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr2, tailq); 1512 CU_ASSERT(pthread_mutex_init(&test_driver.lock, NULL) == 0); 1513 MOCK_SET(nvme_ctrlr_get_ref_count, 1); 1514 1515 rc = spdk_nvme_detach_async(&ctrlr1, &detach_ctx); 1516 CU_ASSERT(rc == 0); 1517 CU_ASSERT(ctrlr1.is_destructed == true); 1518 CU_ASSERT(detach_ctx != NULL); 1519 1520 rc = spdk_nvme_detach_async(&ctrlr2, &detach_ctx); 1521 CU_ASSERT(rc == 0); 1522 CU_ASSERT(ctrlr2.is_destructed == true); 1523 CU_ASSERT(detach_ctx != NULL); 1524 1525 CU_ASSERT(TAILQ_EMPTY(&test_driver.shared_attached_ctrlrs) == false); 1526 1527 rc = spdk_nvme_detach_poll_async(detach_ctx); 1528 CU_ASSERT(rc == 0); 1529 CU_ASSERT(TAILQ_EMPTY(&test_driver.shared_attached_ctrlrs) == true); 1530 1531 /* ctrlr1 is a PCIe controller but ctrlr2 is an non-PCIe controller. 1532 * Even for this case, detachment should complete successfully. 1533 */ 1534 detach_ctx = NULL; 1535 memset(&ctrlr1, 0, sizeof(ctrlr1)); 1536 ctrlr1.trid.trtype = SPDK_NVME_TRANSPORT_RDMA; 1537 memset(&ctrlr2, 0, sizeof(ctrlr2)); 1538 ctrlr2.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 1539 TAILQ_INIT(&g_nvme_attached_ctrlrs); 1540 TAILQ_INSERT_TAIL(&g_nvme_attached_ctrlrs, &ctrlr1, tailq); 1541 TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr2, tailq); 1542 1543 rc = spdk_nvme_detach_async(&ctrlr1, &detach_ctx); 1544 CU_ASSERT(rc == 0); 1545 CU_ASSERT(ctrlr1.is_destructed == true); 1546 CU_ASSERT(detach_ctx != NULL); 1547 1548 rc = spdk_nvme_detach_async(&ctrlr2, &detach_ctx); 1549 CU_ASSERT(rc == 0); 1550 CU_ASSERT(ctrlr2.is_destructed == true); 1551 CU_ASSERT(detach_ctx != NULL); 1552 1553 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs) == false); 1554 CU_ASSERT(TAILQ_EMPTY(&test_driver.shared_attached_ctrlrs) == false); 1555 1556 rc = spdk_nvme_detach_poll_async(detach_ctx); 1557 CU_ASSERT(rc == 0); 1558 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs) == true); 1559 CU_ASSERT(TAILQ_EMPTY(&test_driver.shared_attached_ctrlrs) == true); 1560 1561 /* Test if ctrlr2 can be detached by using the same context that 1562 * ctrlr1 uses while ctrlr1 is being detached. 1563 */ 1564 detach_ctx = NULL; 1565 memset(&ctrlr1, 0, sizeof(ctrlr1)); 1566 ctrlr1.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 1567 memset(&ctrlr2, 0, sizeof(ctrlr2)); 1568 ctrlr2.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 1569 TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr1, tailq); 1570 TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr2, tailq); 1571 1572 rc = spdk_nvme_detach_async(&ctrlr1, &detach_ctx); 1573 CU_ASSERT(rc == 0); 1574 CU_ASSERT(ctrlr1.is_destructed == true); 1575 SPDK_CU_ASSERT_FATAL(detach_ctx != NULL); 1576 1577 ctx = TAILQ_FIRST(&detach_ctx->head); 1578 SPDK_CU_ASSERT_FATAL(ctx != NULL); 1579 CU_ASSERT(ctx->ctrlr == &ctrlr1); 1580 CU_ASSERT(ctx->shutdown_complete == true); 1581 1582 /* Set ctx->shutdown_complete for ctrlr1 to false to allow ctrlr2 to 1583 * add to detach_ctx while spdk_nvme_detach_poll_async() is being 1584 * executed. 1585 */ 1586 ctx->shutdown_complete = false; 1587 1588 rc = spdk_nvme_detach_poll_async(detach_ctx); 1589 CU_ASSERT(rc == -EAGAIN); 1590 1591 rc = spdk_nvme_detach_async(&ctrlr2, &detach_ctx); 1592 CU_ASSERT(rc == 0); 1593 CU_ASSERT(ctrlr2.is_destructed == true); 1594 1595 /* After ctrlr2 is added to detach_ctx, set ctx->shutdown_complete for 1596 * ctrlr1 to true to complete spdk_nvme_detach_poll_async(). 1597 */ 1598 ctx->shutdown_complete = true; 1599 1600 rc = spdk_nvme_detach_poll_async(detach_ctx); 1601 CU_ASSERT(rc == 0); 1602 CU_ASSERT(TAILQ_EMPTY(&test_driver.shared_attached_ctrlrs) == true); 1603 1604 g_spdk_nvme_driver = NULL; 1605 pthread_mutex_destroy(&test_driver.lock); 1606 MOCK_CLEAR(nvme_ctrlr_get_ref_count); 1607 } 1608 1609 static void 1610 test_nvme_parse_addr(void) 1611 { 1612 struct sockaddr_storage dst_addr; 1613 int rc = 0; 1614 long int port; 1615 1616 memset(&dst_addr, 0, sizeof(dst_addr)); 1617 /* case1: getaddrinfo failed */ 1618 rc = nvme_parse_addr(&dst_addr, AF_INET, NULL, NULL, &port); 1619 CU_ASSERT(rc != 0); 1620 1621 /* case2: res->ai_addrlen < sizeof(*sa). Expect: Pass. */ 1622 rc = nvme_parse_addr(&dst_addr, AF_INET, "12.34.56.78", "23", &port); 1623 CU_ASSERT(rc == 0); 1624 CU_ASSERT(port == 23); 1625 CU_ASSERT(dst_addr.ss_family == AF_INET); 1626 } 1627 1628 int 1629 main(int argc, char **argv) 1630 { 1631 CU_pSuite suite = NULL; 1632 unsigned int num_failures; 1633 1634 CU_initialize_registry(); 1635 1636 suite = CU_add_suite("nvme", NULL, NULL); 1637 1638 CU_ADD_TEST(suite, test_opc_data_transfer); 1639 CU_ADD_TEST(suite, test_spdk_nvme_transport_id_parse_trtype); 1640 CU_ADD_TEST(suite, test_spdk_nvme_transport_id_parse_adrfam); 1641 CU_ADD_TEST(suite, test_trid_parse_and_compare); 1642 CU_ADD_TEST(suite, test_trid_trtype_str); 1643 CU_ADD_TEST(suite, test_trid_adrfam_str); 1644 CU_ADD_TEST(suite, test_nvme_ctrlr_probe); 1645 CU_ADD_TEST(suite, test_spdk_nvme_probe); 1646 CU_ADD_TEST(suite, test_spdk_nvme_connect); 1647 CU_ADD_TEST(suite, test_nvme_ctrlr_probe_internal); 1648 CU_ADD_TEST(suite, test_nvme_init_controllers); 1649 CU_ADD_TEST(suite, test_nvme_driver_init); 1650 CU_ADD_TEST(suite, test_spdk_nvme_detach); 1651 CU_ADD_TEST(suite, test_nvme_completion_poll_cb); 1652 CU_ADD_TEST(suite, test_nvme_user_copy_cmd_complete); 1653 CU_ADD_TEST(suite, test_nvme_allocate_request_null); 1654 CU_ADD_TEST(suite, test_nvme_allocate_request); 1655 CU_ADD_TEST(suite, test_nvme_free_request); 1656 CU_ADD_TEST(suite, test_nvme_allocate_request_user_copy); 1657 CU_ADD_TEST(suite, test_nvme_robust_mutex_init_shared); 1658 CU_ADD_TEST(suite, test_nvme_request_check_timeout); 1659 CU_ADD_TEST(suite, test_nvme_wait_for_completion); 1660 CU_ADD_TEST(suite, test_spdk_nvme_parse_func); 1661 CU_ADD_TEST(suite, test_spdk_nvme_detach_async); 1662 CU_ADD_TEST(suite, test_nvme_parse_addr); 1663 1664 num_failures = spdk_ut_run_tests(argc, argv, NULL); 1665 CU_cleanup_registry(); 1666 return num_failures; 1667 } 1668