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