1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019 Mellanox Technologies LTD. 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 "common/lib/ut_multithread.c" 37 #include "spdk_cunit.h" 38 #include "spdk_internal/mock.h" 39 #include "spdk_internal/thread.h" 40 41 #include "nvmf/subsystem.c" 42 43 SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF) 44 45 DEFINE_STUB(spdk_bdev_module_claim_bdev, 46 int, 47 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 48 struct spdk_bdev_module *module), 0); 49 50 DEFINE_STUB_V(spdk_bdev_module_release_bdev, 51 (struct spdk_bdev *bdev)); 52 53 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, 54 (const struct spdk_bdev *bdev), 512); 55 56 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t, 57 (const struct spdk_bdev *bdev), 0); 58 59 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool, 60 (const struct spdk_bdev *bdev), false); 61 62 DEFINE_STUB(spdk_nvmf_transport_stop_listen, 63 int, 64 (struct spdk_nvmf_transport *transport, 65 const struct spdk_nvme_transport_id *trid), 0); 66 67 int 68 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport, 69 const struct spdk_nvme_transport_id *trid) 70 { 71 return 0; 72 } 73 74 void 75 spdk_nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport, 76 struct spdk_nvme_transport_id *trid, 77 struct spdk_nvmf_discovery_log_page_entry *entry) 78 { 79 entry->trtype = 42; 80 } 81 82 static struct spdk_nvmf_transport g_transport = {}; 83 84 struct spdk_nvmf_transport * 85 spdk_nvmf_transport_create(enum spdk_nvme_transport_type type, 86 struct spdk_nvmf_transport_opts *tprt_opts) 87 { 88 if (type == SPDK_NVME_TRANSPORT_RDMA) { 89 return &g_transport; 90 } 91 92 return NULL; 93 } 94 95 struct spdk_nvmf_subsystem * 96 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 97 { 98 return NULL; 99 } 100 101 struct spdk_nvmf_transport * 102 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, enum spdk_nvme_transport_type trtype) 103 { 104 if (trtype == SPDK_NVME_TRANSPORT_RDMA) { 105 return &g_transport; 106 } 107 108 return NULL; 109 } 110 111 int 112 spdk_nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, 113 struct spdk_nvmf_subsystem *subsystem) 114 { 115 return 0; 116 } 117 118 int 119 spdk_nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, 120 struct spdk_nvmf_subsystem *subsystem, 121 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 122 { 123 return 0; 124 } 125 126 void 127 spdk_nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, 128 struct spdk_nvmf_subsystem *subsystem, 129 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 130 { 131 } 132 133 void 134 spdk_nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group, 135 struct spdk_nvmf_subsystem *subsystem, 136 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 137 { 138 } 139 140 void 141 spdk_nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group, 142 struct spdk_nvmf_subsystem *subsystem, 143 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 144 { 145 } 146 147 int 148 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str) 149 { 150 if (trtype == NULL || str == NULL) { 151 return -EINVAL; 152 } 153 154 if (strcasecmp(str, "PCIe") == 0) { 155 *trtype = SPDK_NVME_TRANSPORT_PCIE; 156 } else if (strcasecmp(str, "RDMA") == 0) { 157 *trtype = SPDK_NVME_TRANSPORT_RDMA; 158 } else { 159 return -ENOENT; 160 } 161 return 0; 162 } 163 164 int 165 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1, 166 const struct spdk_nvme_transport_id *trid2) 167 { 168 return 0; 169 } 170 171 int32_t 172 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr) 173 { 174 return -1; 175 } 176 177 int32_t 178 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) 179 { 180 return -1; 181 } 182 183 int 184 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr) 185 { 186 return -1; 187 } 188 189 void 190 spdk_nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr) 191 { 192 } 193 194 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL; 195 static uint32_t g_ns_changed_nsid = 0; 196 void 197 spdk_nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 198 { 199 g_ns_changed_ctrlr = ctrlr; 200 g_ns_changed_nsid = nsid; 201 } 202 203 int 204 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb, 205 void *event_ctx, struct spdk_bdev_desc **_desc) 206 { 207 return 0; 208 } 209 210 void 211 spdk_bdev_close(struct spdk_bdev_desc *desc) 212 { 213 } 214 215 const char * 216 spdk_bdev_get_name(const struct spdk_bdev *bdev) 217 { 218 return "test"; 219 } 220 221 const struct spdk_uuid * 222 spdk_bdev_get_uuid(const struct spdk_bdev *bdev) 223 { 224 return &bdev->uuid; 225 } 226 227 static void 228 test_spdk_nvmf_subsystem_add_ns(void) 229 { 230 struct spdk_nvmf_tgt tgt = {}; 231 struct spdk_nvmf_subsystem subsystem = { 232 .max_nsid = 0, 233 .ns = NULL, 234 .tgt = &tgt 235 }; 236 struct spdk_bdev bdev1 = {}, bdev2 = {}; 237 struct spdk_nvmf_ns_opts ns_opts; 238 uint32_t nsid; 239 int rc; 240 241 tgt.max_subsystems = 1024; 242 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 243 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 244 245 /* Allow NSID to be assigned automatically */ 246 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 247 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts), NULL); 248 /* NSID 1 is the first unused ID */ 249 CU_ASSERT(nsid == 1); 250 CU_ASSERT(subsystem.max_nsid == 1); 251 SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL); 252 SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL); 253 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &bdev1); 254 255 /* Request a specific NSID */ 256 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 257 ns_opts.nsid = 5; 258 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL); 259 CU_ASSERT(nsid == 5); 260 CU_ASSERT(subsystem.max_nsid == 5); 261 SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL); 262 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &bdev2); 263 264 /* Request an NSID that is already in use */ 265 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 266 ns_opts.nsid = 5; 267 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL); 268 CU_ASSERT(nsid == 0); 269 CU_ASSERT(subsystem.max_nsid == 5); 270 271 /* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */ 272 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 273 ns_opts.nsid = 0xFFFFFFFF; 274 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL); 275 CU_ASSERT(nsid == 0); 276 CU_ASSERT(subsystem.max_nsid == 5); 277 278 rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 1); 279 CU_ASSERT(rc == 0); 280 rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5); 281 CU_ASSERT(rc == 0); 282 283 free(subsystem.ns); 284 free(tgt.subsystems); 285 } 286 287 static void 288 nvmf_test_create_subsystem(void) 289 { 290 struct spdk_nvmf_tgt tgt = {}; 291 char nqn[256]; 292 struct spdk_nvmf_subsystem *subsystem; 293 294 tgt.max_subsystems = 1024; 295 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 296 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 297 298 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 299 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 300 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 301 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 302 spdk_nvmf_subsystem_destroy(subsystem); 303 304 /* valid name with complex reverse domain */ 305 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1"); 306 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 307 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 308 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 309 spdk_nvmf_subsystem_destroy(subsystem); 310 311 /* Valid name discovery controller */ 312 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 313 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 314 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 315 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 316 spdk_nvmf_subsystem_destroy(subsystem); 317 318 319 /* Invalid name, no user supplied string */ 320 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 321 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 322 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 323 324 /* Valid name, only contains top-level domain name */ 325 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 326 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 327 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 328 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 329 spdk_nvmf_subsystem_destroy(subsystem); 330 331 /* Invalid name, domain label > 63 characters */ 332 snprintf(nqn, sizeof(nqn), 333 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub"); 334 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 335 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 336 337 /* Invalid name, domain label starts with digit */ 338 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub"); 339 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 340 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 341 342 /* Invalid name, domain label starts with - */ 343 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1"); 344 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 345 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 346 347 /* Invalid name, domain label ends with - */ 348 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1"); 349 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 350 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 351 352 /* Invalid name, domain label with multiple consecutive periods */ 353 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1"); 354 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 355 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 356 357 /* Longest valid name */ 358 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 359 memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn)); 360 nqn[223] = '\0'; 361 CU_ASSERT(strlen(nqn) == 223); 362 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 363 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 364 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 365 spdk_nvmf_subsystem_destroy(subsystem); 366 367 /* Invalid name, too long */ 368 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 369 memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn)); 370 nqn[224] = '\0'; 371 CU_ASSERT(strlen(nqn) == 224); 372 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 373 CU_ASSERT(subsystem == NULL); 374 375 /* Valid name using uuid format */ 376 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc"); 377 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 378 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 379 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 380 spdk_nvmf_subsystem_destroy(subsystem); 381 382 /* Invalid name user string contains an invalid utf-8 character */ 383 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1"); 384 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 385 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 386 387 /* Valid name with non-ascii but valid utf-8 characters */ 388 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80"); 389 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 390 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 391 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 392 spdk_nvmf_subsystem_destroy(subsystem); 393 394 /* Invalid uuid (too long) */ 395 snprintf(nqn, sizeof(nqn), 396 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef"); 397 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 398 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 399 400 /* Invalid uuid (dashes placed incorrectly) */ 401 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc"); 402 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 403 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 404 405 /* Invalid uuid (invalid characters in uuid) */ 406 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc"); 407 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 408 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 409 410 free(tgt.subsystems); 411 } 412 413 static void 414 test_spdk_nvmf_subsystem_set_sn(void) 415 { 416 struct spdk_nvmf_subsystem subsystem = {}; 417 418 /* Basic valid serial number */ 419 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0); 420 CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0); 421 422 /* Exactly 20 characters (valid) */ 423 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0); 424 CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0); 425 426 /* 21 characters (too long, invalid) */ 427 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0); 428 429 /* Non-ASCII characters (invalid) */ 430 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0); 431 } 432 433 /* 434 * Reservation Unit Test Configuration 435 * -------- -------- -------- 436 * | Host A | | Host B | | Host C | 437 * -------- -------- -------- 438 * / \ | | 439 * -------- -------- ------- ------- 440 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C| 441 * -------- -------- ------- ------- 442 * \ \ / / 443 * \ \ / / 444 * \ \ / / 445 * -------------------------------------- 446 * | NAMESPACE 1 | 447 * -------------------------------------- 448 */ 449 static struct spdk_nvmf_subsystem g_subsystem; 450 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; 451 static struct spdk_nvmf_ns g_ns; 452 static struct spdk_bdev g_bdev; 453 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; 454 455 void 456 spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr) 457 { 458 } 459 460 static void 461 ut_reservation_init(void) 462 { 463 464 TAILQ_INIT(&g_subsystem.ctrlrs); 465 466 memset(&g_ns, 0, sizeof(g_ns)); 467 TAILQ_INIT(&g_ns.registrants); 468 g_ns.subsystem = &g_subsystem; 469 g_ns.ptpl_file = NULL; 470 g_ns.ptpl_activated = false; 471 spdk_uuid_generate(&g_bdev.uuid); 472 g_ns.bdev = &g_bdev; 473 474 /* Host A has two controllers */ 475 spdk_uuid_generate(&g_ctrlr1_A.hostid); 476 TAILQ_INIT(&g_ctrlr1_A.log_head); 477 g_ctrlr1_A.subsys = &g_subsystem; 478 g_ctrlr1_A.num_avail_log_pages = 0; 479 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link); 480 spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); 481 TAILQ_INIT(&g_ctrlr2_A.log_head); 482 g_ctrlr2_A.subsys = &g_subsystem; 483 g_ctrlr2_A.num_avail_log_pages = 0; 484 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link); 485 486 /* Host B has 1 controller */ 487 spdk_uuid_generate(&g_ctrlr_B.hostid); 488 TAILQ_INIT(&g_ctrlr_B.log_head); 489 g_ctrlr_B.subsys = &g_subsystem; 490 g_ctrlr_B.num_avail_log_pages = 0; 491 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link); 492 493 /* Host C has 1 controller */ 494 spdk_uuid_generate(&g_ctrlr_C.hostid); 495 TAILQ_INIT(&g_ctrlr_C.log_head); 496 g_ctrlr_C.subsys = &g_subsystem; 497 g_ctrlr_C.num_avail_log_pages = 0; 498 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link); 499 } 500 501 static void 502 ut_reservation_deinit(void) 503 { 504 struct spdk_nvmf_registrant *reg, *tmp; 505 struct spdk_nvmf_reservation_log *log, *log_tmp; 506 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 507 508 TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) { 509 TAILQ_REMOVE(&g_ns.registrants, reg, link); 510 free(reg); 511 } 512 TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) { 513 TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link); 514 free(log); 515 } 516 g_ctrlr1_A.num_avail_log_pages = 0; 517 TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) { 518 TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link); 519 free(log); 520 } 521 g_ctrlr2_A.num_avail_log_pages = 0; 522 TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) { 523 TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link); 524 free(log); 525 } 526 g_ctrlr_B.num_avail_log_pages = 0; 527 TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) { 528 TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link); 529 free(log); 530 } 531 g_ctrlr_C.num_avail_log_pages = 0; 532 533 TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) { 534 TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link); 535 } 536 } 537 538 static struct spdk_nvmf_request * 539 ut_reservation_build_req(uint32_t length) 540 { 541 struct spdk_nvmf_request *req; 542 543 req = calloc(1, sizeof(*req)); 544 assert(req != NULL); 545 546 req->data = calloc(1, length); 547 assert(req->data != NULL); 548 req->length = length; 549 550 req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg)); 551 assert(req->cmd != NULL); 552 553 req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg)); 554 assert(req->rsp != NULL); 555 556 return req; 557 } 558 559 static void 560 ut_reservation_free_req(struct spdk_nvmf_request *req) 561 { 562 free(req->cmd); 563 free(req->rsp); 564 free(req->data); 565 free(req); 566 } 567 568 static void 569 ut_reservation_build_register_request(struct spdk_nvmf_request *req, 570 uint8_t rrega, uint8_t iekey, 571 uint8_t cptpl, uint64_t crkey, 572 uint64_t nrkey) 573 { 574 uint32_t cdw10; 575 struct spdk_nvme_reservation_register_data key; 576 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 577 578 cdw10 = (((uint32_t)cptpl << 30) | ((uint32_t)iekey << 3) | rrega); 579 key.crkey = crkey; 580 key.nrkey = nrkey; 581 cmd->cdw10 = cdw10; 582 memcpy(req->data, &key, sizeof(key)); 583 } 584 585 static void 586 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req, 587 uint8_t racqa, uint8_t iekey, 588 uint8_t rtype, uint64_t crkey, 589 uint64_t prkey) 590 { 591 uint32_t cdw10; 592 struct spdk_nvme_reservation_acquire_data key; 593 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 594 595 cdw10 = ((rtype << 8) | (iekey << 3) | racqa); 596 key.crkey = crkey; 597 key.prkey = prkey; 598 cmd->cdw10 = cdw10; 599 memcpy(req->data, &key, sizeof(key)); 600 } 601 602 static void 603 ut_reservation_build_release_request(struct spdk_nvmf_request *req, 604 uint8_t rrela, uint8_t iekey, 605 uint8_t rtype, uint64_t crkey) 606 { 607 uint32_t cdw10; 608 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 609 610 cdw10 = ((rtype << 8) | (iekey << 3) | rrela); 611 cmd->cdw10 = cdw10; 612 memcpy(req->data, &crkey, sizeof(crkey)); 613 } 614 615 /* 616 * Construct four registrants for other test cases. 617 * 618 * g_ctrlr1_A register with key 0xa1. 619 * g_ctrlr2_A register with key 0xa1. 620 * g_ctrlr_B register with key 0xb1. 621 * g_ctrlr_C register with key 0xc1. 622 * */ 623 static void 624 ut_reservation_build_registrants(void) 625 { 626 struct spdk_nvmf_request *req; 627 struct spdk_nvme_cpl *rsp; 628 struct spdk_nvmf_registrant *reg; 629 uint32_t gen; 630 631 req = ut_reservation_build_req(16); 632 rsp = &req->rsp->nvme_cpl; 633 SPDK_CU_ASSERT_FATAL(req != NULL); 634 gen = g_ns.gen; 635 636 /* TEST CASE: g_ctrlr1_A register with a new key */ 637 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 638 0, 0, 0, 0xa1); 639 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 640 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 641 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 642 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1); 643 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1); 644 645 /* TEST CASE: g_ctrlr2_A register with a new key, because it has same 646 * Host Identifier with g_ctrlr1_A, so the register key should same. 647 */ 648 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 649 0, 0, 0, 0xa2); 650 nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req); 651 /* Reservation conflict for other key than 0xa1 */ 652 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 653 654 /* g_ctrlr_B register with a new key */ 655 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 656 0, 0, 0, 0xb1); 657 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 658 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 659 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 660 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1); 661 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2); 662 663 /* g_ctrlr_C register with a new key */ 664 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 665 0, 0, 0, 0xc1); 666 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 667 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 668 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 669 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1); 670 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3); 671 672 ut_reservation_free_req(req); 673 } 674 675 static void 676 test_reservation_register(void) 677 { 678 struct spdk_nvmf_request *req; 679 struct spdk_nvme_cpl *rsp; 680 struct spdk_nvmf_registrant *reg; 681 uint32_t gen; 682 683 ut_reservation_init(); 684 685 req = ut_reservation_build_req(16); 686 rsp = &req->rsp->nvme_cpl; 687 SPDK_CU_ASSERT_FATAL(req != NULL); 688 689 ut_reservation_build_registrants(); 690 691 /* TEST CASE: Replace g_ctrlr1_A with a new key */ 692 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 693 0, 0, 0xa1, 0xa11); 694 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 695 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 696 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 697 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11); 698 699 /* TEST CASE: Host A with g_ctrlr1_A get reservation with 700 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 701 */ 702 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 703 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0); 704 gen = g_ns.gen; 705 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 706 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 707 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 708 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 709 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11); 710 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 711 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 712 713 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */ 714 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 715 1, 0, 0, 0); 716 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 717 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 718 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 719 SPDK_CU_ASSERT_FATAL(reg == NULL); 720 721 /* TEST CASE: g_ctrlr_B unregister with correct key */ 722 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 723 0, 0, 0xb1, 0); 724 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 725 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 726 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 727 SPDK_CU_ASSERT_FATAL(reg == NULL); 728 729 /* TEST CASE: g_ctrlr1_A unregister with correct key, 730 * reservation should be removed as well. 731 */ 732 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 733 0, 0, 0xa11, 0); 734 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 735 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 736 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 737 SPDK_CU_ASSERT_FATAL(reg == NULL); 738 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 739 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 740 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 741 742 ut_reservation_free_req(req); 743 ut_reservation_deinit(); 744 } 745 746 static void 747 test_reservation_register_with_ptpl(void) 748 { 749 struct spdk_nvmf_request *req; 750 struct spdk_nvme_cpl *rsp; 751 struct spdk_nvmf_registrant *reg; 752 bool update_sgroup = false; 753 int rc; 754 struct spdk_nvmf_reservation_info info; 755 756 ut_reservation_init(); 757 758 req = ut_reservation_build_req(16); 759 rsp = &req->rsp->nvme_cpl; 760 SPDK_CU_ASSERT_FATAL(req != NULL); 761 762 /* TEST CASE: No persistent file, register with PTPL enabled will fail */ 763 g_ns.ptpl_file = NULL; 764 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 765 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 766 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 767 SPDK_CU_ASSERT_FATAL(update_sgroup == false); 768 SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS); 769 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 770 SPDK_CU_ASSERT_FATAL(reg == NULL); 771 772 /* TEST CASE: Enable PTPL */ 773 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 774 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 775 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 776 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 777 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 778 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 779 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 780 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 781 SPDK_CU_ASSERT_FATAL(reg != NULL); 782 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 783 /* Load reservation information from configuration file */ 784 memset(&info, 0, sizeof(info)); 785 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 786 SPDK_CU_ASSERT_FATAL(rc == 0); 787 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 788 789 /* TEST CASE: Disable PTPL */ 790 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 791 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 792 SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1); 793 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 794 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 795 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 796 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false); 797 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 798 SPDK_CU_ASSERT_FATAL(rc < 0); 799 unlink(g_ns.ptpl_file); 800 801 ut_reservation_free_req(req); 802 ut_reservation_deinit(); 803 } 804 805 static void 806 test_reservation_acquire_preempt_1(void) 807 { 808 struct spdk_nvmf_request *req; 809 struct spdk_nvme_cpl *rsp; 810 struct spdk_nvmf_registrant *reg; 811 uint32_t gen; 812 813 ut_reservation_init(); 814 815 req = ut_reservation_build_req(16); 816 rsp = &req->rsp->nvme_cpl; 817 SPDK_CU_ASSERT_FATAL(req != NULL); 818 819 ut_reservation_build_registrants(); 820 821 gen = g_ns.gen; 822 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with 823 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE. 824 */ 825 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 826 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 827 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 828 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 829 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 830 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 831 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1); 832 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 833 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 834 835 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A, 836 * g_ctrl1_A registrant is unregistred. 837 */ 838 gen = g_ns.gen; 839 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 840 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1); 841 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 842 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 843 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 844 SPDK_CU_ASSERT_FATAL(reg == NULL); 845 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 846 SPDK_CU_ASSERT_FATAL(reg != NULL); 847 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 848 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 849 SPDK_CU_ASSERT_FATAL(reg != NULL); 850 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 851 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 852 853 /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B 854 * with valid key and PRKEY set to 0, all registrants other the host that issued 855 * the command are unregistered. 856 */ 857 gen = g_ns.gen; 858 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 859 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0); 860 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 861 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 862 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 863 SPDK_CU_ASSERT_FATAL(reg == NULL); 864 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 865 SPDK_CU_ASSERT_FATAL(reg == NULL); 866 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 867 SPDK_CU_ASSERT_FATAL(reg != NULL); 868 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 869 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 870 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 871 872 ut_reservation_free_req(req); 873 ut_reservation_deinit(); 874 } 875 876 static void 877 test_reservation_acquire_release_with_ptpl(void) 878 { 879 struct spdk_nvmf_request *req; 880 struct spdk_nvme_cpl *rsp; 881 struct spdk_nvmf_registrant *reg; 882 bool update_sgroup = false; 883 struct spdk_uuid holder_uuid; 884 int rc; 885 struct spdk_nvmf_reservation_info info; 886 887 ut_reservation_init(); 888 889 req = ut_reservation_build_req(16); 890 rsp = &req->rsp->nvme_cpl; 891 SPDK_CU_ASSERT_FATAL(req != NULL); 892 893 /* TEST CASE: Enable PTPL */ 894 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 895 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 896 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 897 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 898 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 899 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 900 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 901 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 902 SPDK_CU_ASSERT_FATAL(reg != NULL); 903 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 904 /* Load reservation information from configuration file */ 905 memset(&info, 0, sizeof(info)); 906 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 907 SPDK_CU_ASSERT_FATAL(rc == 0); 908 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 909 910 /* TEST CASE: Acquire the reservation */ 911 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 912 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 913 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 914 update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 915 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 916 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 917 memset(&info, 0, sizeof(info)); 918 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 919 SPDK_CU_ASSERT_FATAL(rc == 0); 920 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 921 SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 922 SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1); 923 spdk_uuid_parse(&holder_uuid, info.holder_uuid); 924 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid)); 925 926 /* TEST CASE: Release the reservation */ 927 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 928 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 929 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1); 930 update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req); 931 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 932 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 933 memset(&info, 0, sizeof(info)); 934 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 935 SPDK_CU_ASSERT_FATAL(rc == 0); 936 SPDK_CU_ASSERT_FATAL(info.rtype == 0); 937 SPDK_CU_ASSERT_FATAL(info.crkey == 0); 938 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 939 unlink(g_ns.ptpl_file); 940 941 ut_reservation_free_req(req); 942 ut_reservation_deinit(); 943 } 944 945 static void 946 test_reservation_release(void) 947 { 948 struct spdk_nvmf_request *req; 949 struct spdk_nvme_cpl *rsp; 950 struct spdk_nvmf_registrant *reg; 951 952 ut_reservation_init(); 953 954 req = ut_reservation_build_req(16); 955 rsp = &req->rsp->nvme_cpl; 956 SPDK_CU_ASSERT_FATAL(req != NULL); 957 958 ut_reservation_build_registrants(); 959 960 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with 961 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS 962 */ 963 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 964 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0); 965 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 966 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 967 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 968 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 969 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 970 971 /* Test Case: Host B release the reservation */ 972 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 973 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1); 974 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 975 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 976 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 977 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 978 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 979 980 /* Test Case: Host C clear the registrants */ 981 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 982 0, 0xc1); 983 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req); 984 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 985 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 986 SPDK_CU_ASSERT_FATAL(reg == NULL); 987 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 988 SPDK_CU_ASSERT_FATAL(reg == NULL); 989 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 990 SPDK_CU_ASSERT_FATAL(reg == NULL); 991 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 992 SPDK_CU_ASSERT_FATAL(reg == NULL); 993 994 ut_reservation_free_req(req); 995 ut_reservation_deinit(); 996 } 997 998 void 999 spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, 1000 struct spdk_nvmf_ns *ns, 1001 enum spdk_nvme_reservation_notification_log_page_type type) 1002 { 1003 ctrlr->num_avail_log_pages++; 1004 } 1005 1006 static void 1007 test_reservation_unregister_notification(void) 1008 { 1009 struct spdk_nvmf_request *req; 1010 struct spdk_nvme_cpl *rsp; 1011 1012 ut_reservation_init(); 1013 1014 req = ut_reservation_build_req(16); 1015 SPDK_CU_ASSERT_FATAL(req != NULL); 1016 rsp = &req->rsp->nvme_cpl; 1017 1018 ut_reservation_build_registrants(); 1019 1020 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1021 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1022 */ 1023 rsp->status.sc = 0xff; 1024 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1025 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1026 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1027 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1028 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1029 1030 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration. 1031 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for 1032 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY 1033 * type. 1034 */ 1035 rsp->status.sc = 0xff; 1036 g_ctrlr1_A.num_avail_log_pages = 0; 1037 g_ctrlr2_A.num_avail_log_pages = 0; 1038 g_ctrlr_B.num_avail_log_pages = 5; 1039 g_ctrlr_C.num_avail_log_pages = 0; 1040 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 1041 0, 0, 0xb1, 0); 1042 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 1043 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1044 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1045 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1046 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1047 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1048 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1049 1050 ut_reservation_free_req(req); 1051 ut_reservation_deinit(); 1052 } 1053 1054 static void 1055 test_reservation_release_notification(void) 1056 { 1057 struct spdk_nvmf_request *req; 1058 struct spdk_nvme_cpl *rsp; 1059 1060 ut_reservation_init(); 1061 1062 req = ut_reservation_build_req(16); 1063 SPDK_CU_ASSERT_FATAL(req != NULL); 1064 rsp = &req->rsp->nvme_cpl; 1065 1066 ut_reservation_build_registrants(); 1067 1068 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1069 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1070 */ 1071 rsp->status.sc = 0xff; 1072 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1073 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1074 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1075 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1076 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1077 1078 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1079 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1080 */ 1081 rsp->status.sc = 0xff; 1082 g_ctrlr1_A.num_avail_log_pages = 0; 1083 g_ctrlr2_A.num_avail_log_pages = 0; 1084 g_ctrlr_B.num_avail_log_pages = 5; 1085 g_ctrlr_C.num_avail_log_pages = 0; 1086 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1087 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1); 1088 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1089 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1090 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1091 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1092 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1093 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1094 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1095 1096 ut_reservation_free_req(req); 1097 ut_reservation_deinit(); 1098 } 1099 1100 static void 1101 test_reservation_release_notification_write_exclusive(void) 1102 { 1103 struct spdk_nvmf_request *req; 1104 struct spdk_nvme_cpl *rsp; 1105 1106 ut_reservation_init(); 1107 1108 req = ut_reservation_build_req(16); 1109 SPDK_CU_ASSERT_FATAL(req != NULL); 1110 rsp = &req->rsp->nvme_cpl; 1111 1112 ut_reservation_build_registrants(); 1113 1114 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1115 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 1116 */ 1117 rsp->status.sc = 0xff; 1118 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1119 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0); 1120 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1121 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1122 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 1123 1124 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1125 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 1126 * no reservation notification occurs. 1127 */ 1128 rsp->status.sc = 0xff; 1129 g_ctrlr1_A.num_avail_log_pages = 5; 1130 g_ctrlr2_A.num_avail_log_pages = 5; 1131 g_ctrlr_B.num_avail_log_pages = 5; 1132 g_ctrlr_C.num_avail_log_pages = 5; 1133 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1134 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1); 1135 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1136 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1137 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1138 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages); 1139 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages); 1140 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1141 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1142 1143 ut_reservation_free_req(req); 1144 ut_reservation_deinit(); 1145 } 1146 1147 static void 1148 test_reservation_clear_notification(void) 1149 { 1150 struct spdk_nvmf_request *req; 1151 struct spdk_nvme_cpl *rsp; 1152 1153 ut_reservation_init(); 1154 1155 req = ut_reservation_build_req(16); 1156 SPDK_CU_ASSERT_FATAL(req != NULL); 1157 rsp = &req->rsp->nvme_cpl; 1158 1159 ut_reservation_build_registrants(); 1160 1161 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1162 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1163 */ 1164 rsp->status.sc = 0xff; 1165 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1166 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1167 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1168 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1169 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1170 1171 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation. 1172 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1173 */ 1174 rsp->status.sc = 0xff; 1175 g_ctrlr1_A.num_avail_log_pages = 0; 1176 g_ctrlr2_A.num_avail_log_pages = 0; 1177 g_ctrlr_B.num_avail_log_pages = 5; 1178 g_ctrlr_C.num_avail_log_pages = 0; 1179 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1180 0, 0xb1); 1181 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1182 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1183 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1184 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1185 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1186 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1187 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1188 1189 ut_reservation_free_req(req); 1190 ut_reservation_deinit(); 1191 } 1192 1193 static void 1194 test_reservation_preempt_notification(void) 1195 { 1196 struct spdk_nvmf_request *req; 1197 struct spdk_nvme_cpl *rsp; 1198 1199 ut_reservation_init(); 1200 1201 req = ut_reservation_build_req(16); 1202 SPDK_CU_ASSERT_FATAL(req != NULL); 1203 rsp = &req->rsp->nvme_cpl; 1204 1205 ut_reservation_build_registrants(); 1206 1207 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1208 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1209 */ 1210 rsp->status.sc = 0xff; 1211 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1212 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1213 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1214 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1215 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1216 1217 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B, 1218 * g_ctrlr_B registrant is unregistred, and reservation is preempted. 1219 * Registration Preempted notification sends to g_ctrlr_B. 1220 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A. 1221 */ 1222 rsp->status.sc = 0xff; 1223 g_ctrlr1_A.num_avail_log_pages = 0; 1224 g_ctrlr2_A.num_avail_log_pages = 0; 1225 g_ctrlr_B.num_avail_log_pages = 0; 1226 g_ctrlr_C.num_avail_log_pages = 5; 1227 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 1228 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1); 1229 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 1230 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1231 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1232 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1233 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1234 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages); 1235 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1236 1237 ut_reservation_free_req(req); 1238 ut_reservation_deinit(); 1239 } 1240 1241 static void 1242 test_spdk_nvmf_ns_event(void) 1243 { 1244 struct spdk_nvmf_tgt tgt = {}; 1245 struct spdk_nvmf_subsystem subsystem = { 1246 .max_nsid = 0, 1247 .ns = NULL, 1248 .tgt = &tgt 1249 }; 1250 struct spdk_nvmf_ctrlr ctrlr = { 1251 .subsys = &subsystem 1252 }; 1253 struct spdk_bdev bdev1 = {}; 1254 struct spdk_nvmf_ns_opts ns_opts; 1255 uint32_t nsid; 1256 1257 tgt.max_subsystems = 1024; 1258 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1259 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1260 1261 /* Add one namespace */ 1262 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1263 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts), NULL); 1264 CU_ASSERT(nsid == 1); 1265 CU_ASSERT(NULL != subsystem.ns[0]); 1266 1267 /* Add one controller */ 1268 TAILQ_INIT(&subsystem.ctrlrs); 1269 TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link); 1270 1271 /* Namespace resize event */ 1272 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1273 g_ns_changed_nsid = 0xFFFFFFFF; 1274 g_ns_changed_ctrlr = NULL; 1275 spdk_nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, &bdev1, subsystem.ns[0]); 1276 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1277 1278 poll_threads(); 1279 CU_ASSERT(1 == g_ns_changed_nsid); 1280 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1281 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1282 1283 /* Namespace remove event */ 1284 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1285 g_ns_changed_nsid = 0xFFFFFFFF; 1286 g_ns_changed_ctrlr = NULL; 1287 spdk_nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, &bdev1, subsystem.ns[0]); 1288 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1289 CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid); 1290 CU_ASSERT(NULL == g_ns_changed_ctrlr); 1291 1292 poll_threads(); 1293 CU_ASSERT(1 == g_ns_changed_nsid); 1294 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1295 CU_ASSERT(NULL == subsystem.ns[0]); 1296 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1297 1298 free(subsystem.ns); 1299 free(tgt.subsystems); 1300 } 1301 1302 1303 int main(int argc, char **argv) 1304 { 1305 CU_pSuite suite = NULL; 1306 unsigned int num_failures; 1307 1308 if (CU_initialize_registry() != CUE_SUCCESS) { 1309 return CU_get_error(); 1310 } 1311 1312 suite = CU_add_suite("nvmf", NULL, NULL); 1313 if (suite == NULL) { 1314 CU_cleanup_registry(); 1315 return CU_get_error(); 1316 } 1317 1318 if ( 1319 CU_add_test(suite, "create_subsystem", nvmf_test_create_subsystem) == NULL || 1320 CU_add_test(suite, "nvmf_subsystem_add_ns", test_spdk_nvmf_subsystem_add_ns) == NULL || 1321 CU_add_test(suite, "nvmf_subsystem_set_sn", test_spdk_nvmf_subsystem_set_sn) == NULL || 1322 CU_add_test(suite, "reservation_register", test_reservation_register) == NULL || 1323 CU_add_test(suite, "reservation_register_with_ptpl", test_reservation_register_with_ptpl) == NULL || 1324 CU_add_test(suite, "reservation_acquire_preempt_1", test_reservation_acquire_preempt_1) == NULL || 1325 CU_add_test(suite, "reservation_acquire_release_with_ptpl", 1326 test_reservation_acquire_release_with_ptpl) == NULL || 1327 CU_add_test(suite, "reservation_release", test_reservation_release) == NULL || 1328 CU_add_test(suite, "reservation_unregister_notification", 1329 test_reservation_unregister_notification) == NULL || 1330 CU_add_test(suite, "reservation_release_notification", 1331 test_reservation_release_notification) == NULL || 1332 CU_add_test(suite, "reservation_release_notification_write_exclusive", 1333 test_reservation_release_notification_write_exclusive) == NULL || 1334 CU_add_test(suite, "reservation_clear_notification", test_reservation_clear_notification) == NULL || 1335 CU_add_test(suite, "reservation_preempt_notification", 1336 test_reservation_preempt_notification) == NULL || 1337 CU_add_test(suite, "spdk_nvmf_ns_event", test_spdk_nvmf_ns_event) == NULL 1338 ) { 1339 CU_cleanup_registry(); 1340 return CU_get_error(); 1341 } 1342 1343 allocate_threads(1); 1344 set_thread(0); 1345 1346 CU_basic_set_mode(CU_BRM_VERBOSE); 1347 CU_basic_run_tests(); 1348 num_failures = CU_get_number_of_failures(); 1349 CU_cleanup_registry(); 1350 1351 free_threads(); 1352 1353 return num_failures; 1354 } 1355