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(const char *transport_name, 86 struct spdk_nvmf_transport_opts *tprt_opts) 87 { 88 if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(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, const char *transport_name) 103 { 104 if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) { 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 struct spdk_nvme_reservation_register_data key; 575 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 576 577 key.crkey = crkey; 578 key.nrkey = nrkey; 579 cmd->cdw10 = 0; 580 cmd->cdw10_bits.resv_register.rrega = rrega; 581 cmd->cdw10_bits.resv_register.iekey = iekey; 582 cmd->cdw10_bits.resv_register.cptpl = cptpl; 583 memcpy(req->data, &key, sizeof(key)); 584 } 585 586 static void 587 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req, 588 uint8_t racqa, uint8_t iekey, 589 uint8_t rtype, uint64_t crkey, 590 uint64_t prkey) 591 { 592 struct spdk_nvme_reservation_acquire_data key; 593 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 594 595 key.crkey = crkey; 596 key.prkey = prkey; 597 cmd->cdw10 = 0; 598 cmd->cdw10_bits.resv_acquire.racqa = racqa; 599 cmd->cdw10_bits.resv_acquire.iekey = iekey; 600 cmd->cdw10_bits.resv_acquire.rtype = rtype; 601 memcpy(req->data, &key, sizeof(key)); 602 } 603 604 static void 605 ut_reservation_build_release_request(struct spdk_nvmf_request *req, 606 uint8_t rrela, uint8_t iekey, 607 uint8_t rtype, uint64_t crkey) 608 { 609 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 610 611 cmd->cdw10 = 0; 612 cmd->cdw10_bits.resv_release.rrela = rrela; 613 cmd->cdw10_bits.resv_release.iekey = iekey; 614 cmd->cdw10_bits.resv_release.rtype = rtype; 615 memcpy(req->data, &crkey, sizeof(crkey)); 616 } 617 618 /* 619 * Construct four registrants for other test cases. 620 * 621 * g_ctrlr1_A register with key 0xa1. 622 * g_ctrlr2_A register with key 0xa1. 623 * g_ctrlr_B register with key 0xb1. 624 * g_ctrlr_C register with key 0xc1. 625 * */ 626 static void 627 ut_reservation_build_registrants(void) 628 { 629 struct spdk_nvmf_request *req; 630 struct spdk_nvme_cpl *rsp; 631 struct spdk_nvmf_registrant *reg; 632 uint32_t gen; 633 634 req = ut_reservation_build_req(16); 635 rsp = &req->rsp->nvme_cpl; 636 SPDK_CU_ASSERT_FATAL(req != NULL); 637 gen = g_ns.gen; 638 639 /* TEST CASE: g_ctrlr1_A register with a new key */ 640 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 641 0, 0, 0, 0xa1); 642 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 643 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 644 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 645 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1); 646 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1); 647 648 /* TEST CASE: g_ctrlr2_A register with a new key, because it has same 649 * Host Identifier with g_ctrlr1_A, so the register key should same. 650 */ 651 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 652 0, 0, 0, 0xa2); 653 nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req); 654 /* Reservation conflict for other key than 0xa1 */ 655 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 656 657 /* g_ctrlr_B register with a new key */ 658 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 659 0, 0, 0, 0xb1); 660 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 661 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 662 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 663 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1); 664 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2); 665 666 /* g_ctrlr_C register with a new key */ 667 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 668 0, 0, 0, 0xc1); 669 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 670 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 671 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 672 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1); 673 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3); 674 675 ut_reservation_free_req(req); 676 } 677 678 static void 679 test_reservation_register(void) 680 { 681 struct spdk_nvmf_request *req; 682 struct spdk_nvme_cpl *rsp; 683 struct spdk_nvmf_registrant *reg; 684 uint32_t gen; 685 686 ut_reservation_init(); 687 688 req = ut_reservation_build_req(16); 689 rsp = &req->rsp->nvme_cpl; 690 SPDK_CU_ASSERT_FATAL(req != NULL); 691 692 ut_reservation_build_registrants(); 693 694 /* TEST CASE: Replace g_ctrlr1_A with a new key */ 695 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 696 0, 0, 0xa1, 0xa11); 697 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 698 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 699 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 700 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11); 701 702 /* TEST CASE: Host A with g_ctrlr1_A get reservation with 703 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 704 */ 705 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 706 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0); 707 gen = g_ns.gen; 708 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 709 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 710 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 711 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 712 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11); 713 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 714 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 715 716 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */ 717 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 718 1, 0, 0, 0); 719 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 720 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 721 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 722 SPDK_CU_ASSERT_FATAL(reg == NULL); 723 724 /* TEST CASE: g_ctrlr_B unregister with correct key */ 725 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 726 0, 0, 0xb1, 0); 727 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 728 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 729 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 730 SPDK_CU_ASSERT_FATAL(reg == NULL); 731 732 /* TEST CASE: g_ctrlr1_A unregister with correct key, 733 * reservation should be removed as well. 734 */ 735 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 736 0, 0, 0xa11, 0); 737 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 738 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 739 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 740 SPDK_CU_ASSERT_FATAL(reg == NULL); 741 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 742 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 743 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 744 745 ut_reservation_free_req(req); 746 ut_reservation_deinit(); 747 } 748 749 static void 750 test_reservation_register_with_ptpl(void) 751 { 752 struct spdk_nvmf_request *req; 753 struct spdk_nvme_cpl *rsp; 754 struct spdk_nvmf_registrant *reg; 755 bool update_sgroup = false; 756 int rc; 757 struct spdk_nvmf_reservation_info info; 758 759 ut_reservation_init(); 760 761 req = ut_reservation_build_req(16); 762 rsp = &req->rsp->nvme_cpl; 763 SPDK_CU_ASSERT_FATAL(req != NULL); 764 765 /* TEST CASE: No persistent file, register with PTPL enabled will fail */ 766 g_ns.ptpl_file = NULL; 767 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 768 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 769 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 770 SPDK_CU_ASSERT_FATAL(update_sgroup == false); 771 SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS); 772 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 773 SPDK_CU_ASSERT_FATAL(reg == NULL); 774 775 /* TEST CASE: Enable PTPL */ 776 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 777 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 778 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 779 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 780 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 781 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 782 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 783 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 784 SPDK_CU_ASSERT_FATAL(reg != NULL); 785 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 786 /* Load reservation information from configuration file */ 787 memset(&info, 0, sizeof(info)); 788 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 789 SPDK_CU_ASSERT_FATAL(rc == 0); 790 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 791 792 /* TEST CASE: Disable PTPL */ 793 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 794 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 795 SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1); 796 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 797 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 798 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 799 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false); 800 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 801 SPDK_CU_ASSERT_FATAL(rc < 0); 802 unlink(g_ns.ptpl_file); 803 804 ut_reservation_free_req(req); 805 ut_reservation_deinit(); 806 } 807 808 static void 809 test_reservation_acquire_preempt_1(void) 810 { 811 struct spdk_nvmf_request *req; 812 struct spdk_nvme_cpl *rsp; 813 struct spdk_nvmf_registrant *reg; 814 uint32_t gen; 815 816 ut_reservation_init(); 817 818 req = ut_reservation_build_req(16); 819 rsp = &req->rsp->nvme_cpl; 820 SPDK_CU_ASSERT_FATAL(req != NULL); 821 822 ut_reservation_build_registrants(); 823 824 gen = g_ns.gen; 825 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with 826 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE. 827 */ 828 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 829 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 830 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 831 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 832 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 833 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 834 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1); 835 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 836 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 837 838 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A, 839 * g_ctrl1_A registrant is unregistred. 840 */ 841 gen = g_ns.gen; 842 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 843 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1); 844 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 845 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 846 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 847 SPDK_CU_ASSERT_FATAL(reg == NULL); 848 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 849 SPDK_CU_ASSERT_FATAL(reg != NULL); 850 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 851 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 852 SPDK_CU_ASSERT_FATAL(reg != NULL); 853 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 854 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 855 856 /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B 857 * with valid key and PRKEY set to 0, all registrants other the host that issued 858 * the command are unregistered. 859 */ 860 gen = g_ns.gen; 861 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 862 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0); 863 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 864 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 865 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 866 SPDK_CU_ASSERT_FATAL(reg == NULL); 867 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 868 SPDK_CU_ASSERT_FATAL(reg == NULL); 869 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 870 SPDK_CU_ASSERT_FATAL(reg != NULL); 871 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 872 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 873 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 874 875 ut_reservation_free_req(req); 876 ut_reservation_deinit(); 877 } 878 879 static void 880 test_reservation_acquire_release_with_ptpl(void) 881 { 882 struct spdk_nvmf_request *req; 883 struct spdk_nvme_cpl *rsp; 884 struct spdk_nvmf_registrant *reg; 885 bool update_sgroup = false; 886 struct spdk_uuid holder_uuid; 887 int rc; 888 struct spdk_nvmf_reservation_info info; 889 890 ut_reservation_init(); 891 892 req = ut_reservation_build_req(16); 893 rsp = &req->rsp->nvme_cpl; 894 SPDK_CU_ASSERT_FATAL(req != NULL); 895 896 /* TEST CASE: Enable PTPL */ 897 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 898 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 899 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 900 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 901 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 902 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 903 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 904 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 905 SPDK_CU_ASSERT_FATAL(reg != NULL); 906 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 907 /* Load reservation information from configuration file */ 908 memset(&info, 0, sizeof(info)); 909 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 910 SPDK_CU_ASSERT_FATAL(rc == 0); 911 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 912 913 /* TEST CASE: Acquire the reservation */ 914 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 915 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 916 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 917 update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 918 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 919 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 920 memset(&info, 0, sizeof(info)); 921 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 922 SPDK_CU_ASSERT_FATAL(rc == 0); 923 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 924 SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 925 SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1); 926 spdk_uuid_parse(&holder_uuid, info.holder_uuid); 927 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid)); 928 929 /* TEST CASE: Release the reservation */ 930 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 931 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 932 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1); 933 update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req); 934 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 935 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 936 memset(&info, 0, sizeof(info)); 937 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 938 SPDK_CU_ASSERT_FATAL(rc == 0); 939 SPDK_CU_ASSERT_FATAL(info.rtype == 0); 940 SPDK_CU_ASSERT_FATAL(info.crkey == 0); 941 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 942 unlink(g_ns.ptpl_file); 943 944 ut_reservation_free_req(req); 945 ut_reservation_deinit(); 946 } 947 948 static void 949 test_reservation_release(void) 950 { 951 struct spdk_nvmf_request *req; 952 struct spdk_nvme_cpl *rsp; 953 struct spdk_nvmf_registrant *reg; 954 955 ut_reservation_init(); 956 957 req = ut_reservation_build_req(16); 958 rsp = &req->rsp->nvme_cpl; 959 SPDK_CU_ASSERT_FATAL(req != NULL); 960 961 ut_reservation_build_registrants(); 962 963 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with 964 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS 965 */ 966 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 967 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0); 968 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 969 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 970 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 971 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 972 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 973 974 /* Test Case: Host B release the reservation */ 975 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 976 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1); 977 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 978 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 979 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 980 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 981 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 982 983 /* Test Case: Host C clear the registrants */ 984 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 985 0, 0xc1); 986 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req); 987 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 988 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 989 SPDK_CU_ASSERT_FATAL(reg == NULL); 990 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 991 SPDK_CU_ASSERT_FATAL(reg == NULL); 992 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 993 SPDK_CU_ASSERT_FATAL(reg == NULL); 994 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 995 SPDK_CU_ASSERT_FATAL(reg == NULL); 996 997 ut_reservation_free_req(req); 998 ut_reservation_deinit(); 999 } 1000 1001 void 1002 spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, 1003 struct spdk_nvmf_ns *ns, 1004 enum spdk_nvme_reservation_notification_log_page_type type) 1005 { 1006 ctrlr->num_avail_log_pages++; 1007 } 1008 1009 static void 1010 test_reservation_unregister_notification(void) 1011 { 1012 struct spdk_nvmf_request *req; 1013 struct spdk_nvme_cpl *rsp; 1014 1015 ut_reservation_init(); 1016 1017 req = ut_reservation_build_req(16); 1018 SPDK_CU_ASSERT_FATAL(req != NULL); 1019 rsp = &req->rsp->nvme_cpl; 1020 1021 ut_reservation_build_registrants(); 1022 1023 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1024 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1025 */ 1026 rsp->status.sc = 0xff; 1027 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1028 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1029 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1030 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1031 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1032 1033 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration. 1034 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for 1035 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY 1036 * type. 1037 */ 1038 rsp->status.sc = 0xff; 1039 g_ctrlr1_A.num_avail_log_pages = 0; 1040 g_ctrlr2_A.num_avail_log_pages = 0; 1041 g_ctrlr_B.num_avail_log_pages = 5; 1042 g_ctrlr_C.num_avail_log_pages = 0; 1043 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 1044 0, 0, 0xb1, 0); 1045 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 1046 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1047 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1048 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1049 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1050 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1051 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1052 1053 ut_reservation_free_req(req); 1054 ut_reservation_deinit(); 1055 } 1056 1057 static void 1058 test_reservation_release_notification(void) 1059 { 1060 struct spdk_nvmf_request *req; 1061 struct spdk_nvme_cpl *rsp; 1062 1063 ut_reservation_init(); 1064 1065 req = ut_reservation_build_req(16); 1066 SPDK_CU_ASSERT_FATAL(req != NULL); 1067 rsp = &req->rsp->nvme_cpl; 1068 1069 ut_reservation_build_registrants(); 1070 1071 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1072 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1073 */ 1074 rsp->status.sc = 0xff; 1075 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1076 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1077 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1078 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1079 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1080 1081 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1082 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1083 */ 1084 rsp->status.sc = 0xff; 1085 g_ctrlr1_A.num_avail_log_pages = 0; 1086 g_ctrlr2_A.num_avail_log_pages = 0; 1087 g_ctrlr_B.num_avail_log_pages = 5; 1088 g_ctrlr_C.num_avail_log_pages = 0; 1089 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1090 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1); 1091 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1092 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1093 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1094 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1095 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1096 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1097 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1098 1099 ut_reservation_free_req(req); 1100 ut_reservation_deinit(); 1101 } 1102 1103 static void 1104 test_reservation_release_notification_write_exclusive(void) 1105 { 1106 struct spdk_nvmf_request *req; 1107 struct spdk_nvme_cpl *rsp; 1108 1109 ut_reservation_init(); 1110 1111 req = ut_reservation_build_req(16); 1112 SPDK_CU_ASSERT_FATAL(req != NULL); 1113 rsp = &req->rsp->nvme_cpl; 1114 1115 ut_reservation_build_registrants(); 1116 1117 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1118 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 1119 */ 1120 rsp->status.sc = 0xff; 1121 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1122 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0); 1123 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1124 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1125 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 1126 1127 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1128 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 1129 * no reservation notification occurs. 1130 */ 1131 rsp->status.sc = 0xff; 1132 g_ctrlr1_A.num_avail_log_pages = 5; 1133 g_ctrlr2_A.num_avail_log_pages = 5; 1134 g_ctrlr_B.num_avail_log_pages = 5; 1135 g_ctrlr_C.num_avail_log_pages = 5; 1136 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1137 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1); 1138 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1139 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1140 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1141 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages); 1142 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages); 1143 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1144 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1145 1146 ut_reservation_free_req(req); 1147 ut_reservation_deinit(); 1148 } 1149 1150 static void 1151 test_reservation_clear_notification(void) 1152 { 1153 struct spdk_nvmf_request *req; 1154 struct spdk_nvme_cpl *rsp; 1155 1156 ut_reservation_init(); 1157 1158 req = ut_reservation_build_req(16); 1159 SPDK_CU_ASSERT_FATAL(req != NULL); 1160 rsp = &req->rsp->nvme_cpl; 1161 1162 ut_reservation_build_registrants(); 1163 1164 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1165 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1166 */ 1167 rsp->status.sc = 0xff; 1168 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1169 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1170 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1171 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1172 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1173 1174 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation. 1175 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1176 */ 1177 rsp->status.sc = 0xff; 1178 g_ctrlr1_A.num_avail_log_pages = 0; 1179 g_ctrlr2_A.num_avail_log_pages = 0; 1180 g_ctrlr_B.num_avail_log_pages = 5; 1181 g_ctrlr_C.num_avail_log_pages = 0; 1182 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1183 0, 0xb1); 1184 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1185 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1186 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1187 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1188 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1189 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1190 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1191 1192 ut_reservation_free_req(req); 1193 ut_reservation_deinit(); 1194 } 1195 1196 static void 1197 test_reservation_preempt_notification(void) 1198 { 1199 struct spdk_nvmf_request *req; 1200 struct spdk_nvme_cpl *rsp; 1201 1202 ut_reservation_init(); 1203 1204 req = ut_reservation_build_req(16); 1205 SPDK_CU_ASSERT_FATAL(req != NULL); 1206 rsp = &req->rsp->nvme_cpl; 1207 1208 ut_reservation_build_registrants(); 1209 1210 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1211 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1212 */ 1213 rsp->status.sc = 0xff; 1214 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1215 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1216 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1217 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1218 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1219 1220 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B, 1221 * g_ctrlr_B registrant is unregistred, and reservation is preempted. 1222 * Registration Preempted notification sends to g_ctrlr_B. 1223 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A. 1224 */ 1225 rsp->status.sc = 0xff; 1226 g_ctrlr1_A.num_avail_log_pages = 0; 1227 g_ctrlr2_A.num_avail_log_pages = 0; 1228 g_ctrlr_B.num_avail_log_pages = 0; 1229 g_ctrlr_C.num_avail_log_pages = 5; 1230 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 1231 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1); 1232 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 1233 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1234 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1235 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1236 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1237 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages); 1238 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1239 1240 ut_reservation_free_req(req); 1241 ut_reservation_deinit(); 1242 } 1243 1244 static void 1245 test_spdk_nvmf_ns_event(void) 1246 { 1247 struct spdk_nvmf_tgt tgt = {}; 1248 struct spdk_nvmf_subsystem subsystem = { 1249 .max_nsid = 0, 1250 .ns = NULL, 1251 .tgt = &tgt 1252 }; 1253 struct spdk_nvmf_ctrlr ctrlr = { 1254 .subsys = &subsystem 1255 }; 1256 struct spdk_bdev bdev1 = {}; 1257 struct spdk_nvmf_ns_opts ns_opts; 1258 uint32_t nsid; 1259 1260 tgt.max_subsystems = 1024; 1261 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1262 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1263 1264 /* Add one namespace */ 1265 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1266 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts), NULL); 1267 CU_ASSERT(nsid == 1); 1268 CU_ASSERT(NULL != subsystem.ns[0]); 1269 1270 /* Add one controller */ 1271 TAILQ_INIT(&subsystem.ctrlrs); 1272 TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link); 1273 1274 /* Namespace resize event */ 1275 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1276 g_ns_changed_nsid = 0xFFFFFFFF; 1277 g_ns_changed_ctrlr = NULL; 1278 spdk_nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, &bdev1, subsystem.ns[0]); 1279 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1280 1281 poll_threads(); 1282 CU_ASSERT(1 == g_ns_changed_nsid); 1283 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1284 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1285 1286 /* Namespace remove event */ 1287 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1288 g_ns_changed_nsid = 0xFFFFFFFF; 1289 g_ns_changed_ctrlr = NULL; 1290 spdk_nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, &bdev1, subsystem.ns[0]); 1291 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1292 CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid); 1293 CU_ASSERT(NULL == g_ns_changed_ctrlr); 1294 1295 poll_threads(); 1296 CU_ASSERT(1 == g_ns_changed_nsid); 1297 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1298 CU_ASSERT(NULL == subsystem.ns[0]); 1299 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1300 1301 free(subsystem.ns); 1302 free(tgt.subsystems); 1303 } 1304 1305 1306 int main(int argc, char **argv) 1307 { 1308 CU_pSuite suite = NULL; 1309 unsigned int num_failures; 1310 1311 CU_set_error_action(CUEA_ABORT); 1312 CU_initialize_registry(); 1313 1314 suite = CU_add_suite("nvmf", NULL, NULL); 1315 1316 CU_ADD_TEST(suite, nvmf_test_create_subsystem); 1317 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns); 1318 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn); 1319 CU_ADD_TEST(suite, test_reservation_register); 1320 CU_ADD_TEST(suite, test_reservation_register_with_ptpl); 1321 CU_ADD_TEST(suite, test_reservation_acquire_preempt_1); 1322 CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl); 1323 CU_ADD_TEST(suite, test_reservation_release); 1324 CU_ADD_TEST(suite, test_reservation_unregister_notification); 1325 CU_ADD_TEST(suite, test_reservation_release_notification); 1326 CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive); 1327 CU_ADD_TEST(suite, test_reservation_clear_notification); 1328 CU_ADD_TEST(suite, test_reservation_preempt_notification); 1329 CU_ADD_TEST(suite, test_spdk_nvmf_ns_event); 1330 1331 allocate_threads(1); 1332 set_thread(0); 1333 1334 CU_basic_set_mode(CU_BRM_VERBOSE); 1335 CU_basic_run_tests(); 1336 num_failures = CU_get_number_of_failures(); 1337 CU_cleanup_registry(); 1338 1339 free_threads(); 1340 1341 return num_failures; 1342 } 1343