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 #include <uuid/uuid.h> 43 44 SPDK_LOG_REGISTER_COMPONENT(nvmf) 45 46 DEFINE_STUB(spdk_bdev_module_claim_bdev, 47 int, 48 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 49 struct spdk_bdev_module *module), 0); 50 51 DEFINE_STUB_V(spdk_bdev_module_release_bdev, 52 (struct spdk_bdev *bdev)); 53 54 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, 55 (const struct spdk_bdev *bdev), 512); 56 57 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t, 58 (const struct spdk_bdev *bdev), 0); 59 60 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool, 61 (const struct spdk_bdev *bdev), false); 62 63 DEFINE_STUB(spdk_bdev_io_type_supported, bool, 64 (struct spdk_bdev *bdev, 65 enum spdk_bdev_io_type io_type), false); 66 67 DEFINE_STUB(spdk_nvmf_transport_stop_listen, 68 int, 69 (struct spdk_nvmf_transport *transport, 70 const struct spdk_nvme_transport_id *trid), 0); 71 72 DEFINE_STUB_V(nvmf_update_discovery_log, 73 (struct spdk_nvmf_tgt *tgt, const char *hostnqn)); 74 75 DEFINE_STUB(spdk_nvmf_qpair_disconnect, 76 int, 77 (struct spdk_nvmf_qpair *qpair, 78 nvmf_qpair_disconnect_cb cb_fn, void *ctx), 0); 79 80 DEFINE_STUB(nvmf_transport_find_listener, 81 struct spdk_nvmf_listener *, 82 (struct spdk_nvmf_transport *transport, 83 const struct spdk_nvme_transport_id *trid), NULL); 84 85 DEFINE_STUB(spdk_nvmf_transport_get_first, 86 struct spdk_nvmf_transport *, 87 (struct spdk_nvmf_tgt *tgt), NULL); 88 89 DEFINE_STUB(spdk_nvmf_transport_get_next, 90 struct spdk_nvmf_transport *, 91 (struct spdk_nvmf_transport *transport), NULL); 92 93 DEFINE_STUB(spdk_nvmf_request_complete, 94 int, 95 (struct spdk_nvmf_request *req), 0); 96 97 DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice, 98 int, 99 (struct spdk_nvmf_ctrlr *ctrlr), 0); 100 101 DEFINE_STUB(spdk_nvme_transport_id_trtype_str, 102 const char *, 103 (enum spdk_nvme_transport_type trtype), NULL); 104 105 int 106 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport, 107 const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts) 108 { 109 return 0; 110 } 111 112 void 113 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport, 114 struct spdk_nvme_transport_id *trid, 115 struct spdk_nvmf_discovery_log_page_entry *entry) 116 { 117 entry->trtype = 42; 118 } 119 120 static struct spdk_nvmf_transport g_transport = {}; 121 122 struct spdk_nvmf_transport * 123 spdk_nvmf_transport_create(const char *transport_name, 124 struct spdk_nvmf_transport_opts *tprt_opts) 125 { 126 if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) { 127 return &g_transport; 128 } 129 130 return NULL; 131 } 132 133 struct spdk_nvmf_subsystem * 134 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 135 { 136 return NULL; 137 } 138 139 struct spdk_nvmf_transport * 140 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name) 141 { 142 if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) { 143 return &g_transport; 144 } 145 146 return NULL; 147 } 148 149 int 150 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, 151 struct spdk_nvmf_subsystem *subsystem) 152 { 153 return 0; 154 } 155 156 int 157 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, 158 struct spdk_nvmf_subsystem *subsystem, 159 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 160 { 161 return 0; 162 } 163 164 void 165 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, 166 struct spdk_nvmf_subsystem *subsystem, 167 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 168 { 169 } 170 171 void 172 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group, 173 struct spdk_nvmf_subsystem *subsystem, 174 uint32_t nsid, 175 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 176 { 177 } 178 179 void 180 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group, 181 struct spdk_nvmf_subsystem *subsystem, 182 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 183 { 184 } 185 186 int 187 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str) 188 { 189 if (trtype == NULL || str == NULL) { 190 return -EINVAL; 191 } 192 193 if (strcasecmp(str, "PCIe") == 0) { 194 *trtype = SPDK_NVME_TRANSPORT_PCIE; 195 } else if (strcasecmp(str, "RDMA") == 0) { 196 *trtype = SPDK_NVME_TRANSPORT_RDMA; 197 } else { 198 return -ENOENT; 199 } 200 return 0; 201 } 202 203 int 204 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1, 205 const struct spdk_nvme_transport_id *trid2) 206 { 207 return 0; 208 } 209 210 int32_t 211 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr) 212 { 213 return -1; 214 } 215 216 int32_t 217 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) 218 { 219 return -1; 220 } 221 222 int 223 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr) 224 { 225 return -1; 226 } 227 228 void 229 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr) 230 { 231 } 232 233 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL; 234 static uint32_t g_ns_changed_nsid = 0; 235 void 236 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 237 { 238 g_ns_changed_ctrlr = ctrlr; 239 g_ns_changed_nsid = nsid; 240 } 241 242 static struct spdk_bdev g_bdevs[] = { 243 { .name = "bdev1" }, 244 { .name = "bdev2" }, 245 }; 246 247 struct spdk_bdev_desc { 248 struct spdk_bdev *bdev; 249 }; 250 251 int 252 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb, 253 void *event_ctx, struct spdk_bdev_desc **_desc) 254 { 255 struct spdk_bdev_desc *desc; 256 size_t i; 257 258 for (i = 0; i < sizeof(g_bdevs); i++) { 259 if (strcmp(bdev_name, g_bdevs[i].name) == 0) { 260 261 desc = calloc(1, sizeof(*desc)); 262 SPDK_CU_ASSERT_FATAL(desc != NULL); 263 264 desc->bdev = &g_bdevs[i]; 265 *_desc = desc; 266 return 0; 267 } 268 } 269 270 return -EINVAL; 271 } 272 273 void 274 spdk_bdev_close(struct spdk_bdev_desc *desc) 275 { 276 free(desc); 277 } 278 279 struct spdk_bdev * 280 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc) 281 { 282 return desc->bdev; 283 } 284 285 const char * 286 spdk_bdev_get_name(const struct spdk_bdev *bdev) 287 { 288 return "test"; 289 } 290 291 const struct spdk_uuid * 292 spdk_bdev_get_uuid(const struct spdk_bdev *bdev) 293 { 294 return &bdev->uuid; 295 } 296 297 static void 298 test_spdk_nvmf_subsystem_add_ns(void) 299 { 300 struct spdk_nvmf_tgt tgt = {}; 301 struct spdk_nvmf_subsystem subsystem = { 302 .max_nsid = 1024, 303 .ns = NULL, 304 .tgt = &tgt, 305 }; 306 struct spdk_nvmf_ns_opts ns_opts; 307 uint32_t nsid; 308 int rc; 309 310 subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *)); 311 SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL); 312 subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t)); 313 SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL); 314 315 tgt.max_subsystems = 1024; 316 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 317 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 318 319 /* Request a specific NSID */ 320 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 321 ns_opts.nsid = 5; 322 nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL); 323 CU_ASSERT(nsid == 5); 324 CU_ASSERT(subsystem.max_nsid == 1024); 325 SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL); 326 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]); 327 328 /* Request an NSID that is already in use */ 329 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 330 ns_opts.nsid = 5; 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 /* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */ 336 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 337 ns_opts.nsid = 0xFFFFFFFF; 338 nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL); 339 CU_ASSERT(nsid == 0); 340 CU_ASSERT(subsystem.max_nsid == 1024); 341 342 rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5); 343 CU_ASSERT(rc == 0); 344 345 free(subsystem.ns); 346 free(subsystem.ana_group); 347 free(tgt.subsystems); 348 } 349 350 static void 351 nvmf_test_create_subsystem(void) 352 { 353 struct spdk_nvmf_tgt tgt = {}; 354 char nqn[256]; 355 struct spdk_nvmf_subsystem *subsystem; 356 int rc; 357 358 tgt.max_subsystems = 1024; 359 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 360 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 361 362 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 363 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 364 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 365 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 366 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 367 CU_ASSERT(rc == 0); 368 369 /* valid name with complex reverse domain */ 370 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1"); 371 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 372 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 373 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 374 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 375 CU_ASSERT(rc == 0); 376 377 /* Valid name discovery controller */ 378 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 379 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 380 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 381 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 382 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 383 CU_ASSERT(rc == 0); 384 385 /* Invalid name, no user supplied string */ 386 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 387 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 388 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 389 390 /* Valid name, only contains top-level domain name */ 391 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 392 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 393 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 394 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 395 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 396 CU_ASSERT(rc == 0); 397 398 /* Invalid name, domain label > 63 characters */ 399 snprintf(nqn, sizeof(nqn), 400 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub"); 401 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 402 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 403 404 /* Invalid name, domain label starts with digit */ 405 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub"); 406 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 407 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 408 409 /* Invalid name, domain label starts with - */ 410 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1"); 411 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 412 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 413 414 /* Invalid name, domain label ends with - */ 415 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1"); 416 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 417 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 418 419 /* Invalid name, domain label with multiple consecutive periods */ 420 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1"); 421 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 422 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 423 424 /* Longest valid name */ 425 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 426 memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn)); 427 nqn[223] = '\0'; 428 CU_ASSERT(strlen(nqn) == 223); 429 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 430 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 431 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 432 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 433 CU_ASSERT(rc == 0); 434 435 /* Invalid name, too long */ 436 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 437 memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn)); 438 nqn[224] = '\0'; 439 CU_ASSERT(strlen(nqn) == 224); 440 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 441 CU_ASSERT(subsystem == NULL); 442 443 /* Valid name using uuid format */ 444 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc"); 445 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 446 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 447 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 448 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 449 CU_ASSERT(rc == 0); 450 451 /* Invalid name user string contains an invalid utf-8 character */ 452 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1"); 453 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 454 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 455 456 /* Valid name with non-ascii but valid utf-8 characters */ 457 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80"); 458 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 459 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 460 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 461 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 462 CU_ASSERT(rc == 0); 463 464 /* Invalid uuid (too long) */ 465 snprintf(nqn, sizeof(nqn), 466 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef"); 467 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 468 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 469 470 /* Invalid uuid (dashes placed incorrectly) */ 471 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc"); 472 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 473 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 474 475 /* Invalid uuid (invalid characters in uuid) */ 476 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc"); 477 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 478 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 479 480 free(tgt.subsystems); 481 } 482 483 static void 484 test_spdk_nvmf_subsystem_set_sn(void) 485 { 486 struct spdk_nvmf_subsystem subsystem = {}; 487 488 /* Basic valid serial number */ 489 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0); 490 CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0); 491 492 /* Exactly 20 characters (valid) */ 493 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0); 494 CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0); 495 496 /* 21 characters (too long, invalid) */ 497 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0); 498 499 /* Non-ASCII characters (invalid) */ 500 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0); 501 } 502 503 /* 504 * Reservation Unit Test Configuration 505 * -------- -------- -------- 506 * | Host A | | Host B | | Host C | 507 * -------- -------- -------- 508 * / \ | | 509 * -------- -------- ------- ------- 510 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C| 511 * -------- -------- ------- ------- 512 * \ \ / / 513 * \ \ / / 514 * \ \ / / 515 * -------------------------------------- 516 * | NAMESPACE 1 | 517 * -------------------------------------- 518 */ 519 static struct spdk_nvmf_subsystem g_subsystem; 520 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; 521 static struct spdk_nvmf_ns g_ns; 522 static struct spdk_bdev g_bdev; 523 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; 524 525 void 526 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr) 527 { 528 } 529 530 static void 531 ut_reservation_init(void) 532 { 533 534 TAILQ_INIT(&g_subsystem.ctrlrs); 535 536 memset(&g_ns, 0, sizeof(g_ns)); 537 TAILQ_INIT(&g_ns.registrants); 538 g_ns.subsystem = &g_subsystem; 539 g_ns.ptpl_file = NULL; 540 g_ns.ptpl_activated = false; 541 spdk_uuid_generate(&g_bdev.uuid); 542 g_ns.bdev = &g_bdev; 543 544 /* Host A has two controllers */ 545 spdk_uuid_generate(&g_ctrlr1_A.hostid); 546 TAILQ_INIT(&g_ctrlr1_A.log_head); 547 g_ctrlr1_A.subsys = &g_subsystem; 548 g_ctrlr1_A.num_avail_log_pages = 0; 549 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link); 550 spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); 551 TAILQ_INIT(&g_ctrlr2_A.log_head); 552 g_ctrlr2_A.subsys = &g_subsystem; 553 g_ctrlr2_A.num_avail_log_pages = 0; 554 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link); 555 556 /* Host B has 1 controller */ 557 spdk_uuid_generate(&g_ctrlr_B.hostid); 558 TAILQ_INIT(&g_ctrlr_B.log_head); 559 g_ctrlr_B.subsys = &g_subsystem; 560 g_ctrlr_B.num_avail_log_pages = 0; 561 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link); 562 563 /* Host C has 1 controller */ 564 spdk_uuid_generate(&g_ctrlr_C.hostid); 565 TAILQ_INIT(&g_ctrlr_C.log_head); 566 g_ctrlr_C.subsys = &g_subsystem; 567 g_ctrlr_C.num_avail_log_pages = 0; 568 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link); 569 } 570 571 static void 572 ut_reservation_deinit(void) 573 { 574 struct spdk_nvmf_registrant *reg, *tmp; 575 struct spdk_nvmf_reservation_log *log, *log_tmp; 576 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 577 578 TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) { 579 TAILQ_REMOVE(&g_ns.registrants, reg, link); 580 free(reg); 581 } 582 TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) { 583 TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link); 584 free(log); 585 } 586 g_ctrlr1_A.num_avail_log_pages = 0; 587 TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) { 588 TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link); 589 free(log); 590 } 591 g_ctrlr2_A.num_avail_log_pages = 0; 592 TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) { 593 TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link); 594 free(log); 595 } 596 g_ctrlr_B.num_avail_log_pages = 0; 597 TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) { 598 TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link); 599 free(log); 600 } 601 g_ctrlr_C.num_avail_log_pages = 0; 602 603 TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) { 604 TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link); 605 } 606 } 607 608 static struct spdk_nvmf_request * 609 ut_reservation_build_req(uint32_t length) 610 { 611 struct spdk_nvmf_request *req; 612 613 req = calloc(1, sizeof(*req)); 614 assert(req != NULL); 615 616 req->data = calloc(1, length); 617 assert(req->data != NULL); 618 req->length = length; 619 620 req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg)); 621 assert(req->cmd != NULL); 622 623 req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg)); 624 assert(req->rsp != NULL); 625 626 return req; 627 } 628 629 static void 630 ut_reservation_free_req(struct spdk_nvmf_request *req) 631 { 632 free(req->cmd); 633 free(req->rsp); 634 free(req->data); 635 free(req); 636 } 637 638 static void 639 ut_reservation_build_register_request(struct spdk_nvmf_request *req, 640 uint8_t rrega, uint8_t iekey, 641 uint8_t cptpl, uint64_t crkey, 642 uint64_t nrkey) 643 { 644 struct spdk_nvme_reservation_register_data key; 645 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 646 647 key.crkey = crkey; 648 key.nrkey = nrkey; 649 cmd->cdw10 = 0; 650 cmd->cdw10_bits.resv_register.rrega = rrega; 651 cmd->cdw10_bits.resv_register.iekey = iekey; 652 cmd->cdw10_bits.resv_register.cptpl = cptpl; 653 memcpy(req->data, &key, sizeof(key)); 654 } 655 656 static void 657 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req, 658 uint8_t racqa, uint8_t iekey, 659 uint8_t rtype, uint64_t crkey, 660 uint64_t prkey) 661 { 662 struct spdk_nvme_reservation_acquire_data key; 663 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 664 665 key.crkey = crkey; 666 key.prkey = prkey; 667 cmd->cdw10 = 0; 668 cmd->cdw10_bits.resv_acquire.racqa = racqa; 669 cmd->cdw10_bits.resv_acquire.iekey = iekey; 670 cmd->cdw10_bits.resv_acquire.rtype = rtype; 671 memcpy(req->data, &key, sizeof(key)); 672 } 673 674 static void 675 ut_reservation_build_release_request(struct spdk_nvmf_request *req, 676 uint8_t rrela, uint8_t iekey, 677 uint8_t rtype, uint64_t crkey) 678 { 679 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 680 681 cmd->cdw10 = 0; 682 cmd->cdw10_bits.resv_release.rrela = rrela; 683 cmd->cdw10_bits.resv_release.iekey = iekey; 684 cmd->cdw10_bits.resv_release.rtype = rtype; 685 memcpy(req->data, &crkey, sizeof(crkey)); 686 } 687 688 /* 689 * Construct four registrants for other test cases. 690 * 691 * g_ctrlr1_A register with key 0xa1. 692 * g_ctrlr2_A register with key 0xa1. 693 * g_ctrlr_B register with key 0xb1. 694 * g_ctrlr_C register with key 0xc1. 695 * */ 696 static void 697 ut_reservation_build_registrants(void) 698 { 699 struct spdk_nvmf_request *req; 700 struct spdk_nvme_cpl *rsp; 701 struct spdk_nvmf_registrant *reg; 702 uint32_t gen; 703 704 req = ut_reservation_build_req(16); 705 rsp = &req->rsp->nvme_cpl; 706 SPDK_CU_ASSERT_FATAL(req != NULL); 707 gen = g_ns.gen; 708 709 /* TEST CASE: g_ctrlr1_A register with a new key */ 710 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 711 0, 0, 0, 0xa1); 712 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 713 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 714 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 715 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1); 716 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1); 717 718 /* TEST CASE: g_ctrlr2_A register with a new key, because it has same 719 * Host Identifier with g_ctrlr1_A, so the register key should same. 720 */ 721 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 722 0, 0, 0, 0xa2); 723 nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req); 724 /* Reservation conflict for other key than 0xa1 */ 725 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 726 727 /* g_ctrlr_B register with a new key */ 728 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 729 0, 0, 0, 0xb1); 730 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 731 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 732 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 733 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1); 734 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2); 735 736 /* g_ctrlr_C register with a new key */ 737 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 738 0, 0, 0, 0xc1); 739 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 740 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 741 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 742 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1); 743 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3); 744 745 ut_reservation_free_req(req); 746 } 747 748 static void 749 test_reservation_register(void) 750 { 751 struct spdk_nvmf_request *req; 752 struct spdk_nvme_cpl *rsp; 753 struct spdk_nvmf_registrant *reg; 754 uint32_t gen; 755 756 ut_reservation_init(); 757 758 req = ut_reservation_build_req(16); 759 rsp = &req->rsp->nvme_cpl; 760 SPDK_CU_ASSERT_FATAL(req != NULL); 761 762 ut_reservation_build_registrants(); 763 764 /* TEST CASE: Replace g_ctrlr1_A with a new key */ 765 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 766 0, 0, 0xa1, 0xa11); 767 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 768 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 769 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 770 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11); 771 772 /* TEST CASE: Host A with g_ctrlr1_A get reservation with 773 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 774 */ 775 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 776 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0); 777 gen = g_ns.gen; 778 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 779 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 780 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 781 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 782 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11); 783 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 784 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 785 786 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */ 787 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 788 1, 0, 0, 0); 789 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 790 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 791 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 792 SPDK_CU_ASSERT_FATAL(reg == NULL); 793 794 /* TEST CASE: g_ctrlr_B unregister with correct key */ 795 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 796 0, 0, 0xb1, 0); 797 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 798 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 799 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 800 SPDK_CU_ASSERT_FATAL(reg == NULL); 801 802 /* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY disabled */ 803 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 804 0, 0, 0, 0xb1); 805 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 806 SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS); 807 808 /* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY enabled */ 809 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 810 1, 0, 0, 0xb1); 811 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 812 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 813 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 814 SPDK_CU_ASSERT_FATAL(reg != NULL); 815 816 /* TEST CASE: g_ctrlr_B replace new key with IEKEY enabled and wrong crkey */ 817 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 818 1, 0, 0xff, 0xb2); 819 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 820 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 821 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 822 SPDK_CU_ASSERT_FATAL(reg != NULL); 823 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb2); 824 825 /* TEST CASE: g_ctrlr1_A unregister with correct key, 826 * reservation should be removed as well. 827 */ 828 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 829 0, 0, 0xa11, 0); 830 nvmf_ns_reservation_register(&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(reg == NULL); 834 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 835 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 836 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 837 838 ut_reservation_free_req(req); 839 ut_reservation_deinit(); 840 } 841 842 static void 843 test_reservation_register_with_ptpl(void) 844 { 845 struct spdk_nvmf_request *req; 846 struct spdk_nvme_cpl *rsp; 847 struct spdk_nvmf_registrant *reg; 848 bool update_sgroup = false; 849 int rc; 850 struct spdk_nvmf_reservation_info info; 851 852 ut_reservation_init(); 853 854 req = ut_reservation_build_req(16); 855 rsp = &req->rsp->nvme_cpl; 856 SPDK_CU_ASSERT_FATAL(req != NULL); 857 858 /* TEST CASE: No persistent file, register with PTPL enabled will fail */ 859 g_ns.ptpl_file = NULL; 860 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 861 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 862 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 863 SPDK_CU_ASSERT_FATAL(update_sgroup == false); 864 SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS); 865 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 866 SPDK_CU_ASSERT_FATAL(reg == NULL); 867 868 /* TEST CASE: Enable PTPL */ 869 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 870 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 871 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 872 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 873 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 874 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 875 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 876 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 877 SPDK_CU_ASSERT_FATAL(reg != NULL); 878 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 879 /* Load reservation information from configuration file */ 880 memset(&info, 0, sizeof(info)); 881 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 882 SPDK_CU_ASSERT_FATAL(rc == 0); 883 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 884 885 /* TEST CASE: Disable PTPL */ 886 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 887 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 888 SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1); 889 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 890 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 891 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 892 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false); 893 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 894 SPDK_CU_ASSERT_FATAL(rc < 0); 895 unlink(g_ns.ptpl_file); 896 897 ut_reservation_free_req(req); 898 ut_reservation_deinit(); 899 } 900 901 static void 902 test_reservation_acquire_preempt_1(void) 903 { 904 struct spdk_nvmf_request *req; 905 struct spdk_nvme_cpl *rsp; 906 struct spdk_nvmf_registrant *reg; 907 uint32_t gen; 908 909 ut_reservation_init(); 910 911 req = ut_reservation_build_req(16); 912 rsp = &req->rsp->nvme_cpl; 913 SPDK_CU_ASSERT_FATAL(req != NULL); 914 915 ut_reservation_build_registrants(); 916 917 gen = g_ns.gen; 918 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with 919 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE. 920 */ 921 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 922 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 923 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 924 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 925 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 926 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 927 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1); 928 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 929 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 930 931 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A, 932 * g_ctrl1_A registrant is unregistered. 933 */ 934 gen = g_ns.gen; 935 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 936 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1); 937 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 938 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 939 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 940 SPDK_CU_ASSERT_FATAL(reg == NULL); 941 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 942 SPDK_CU_ASSERT_FATAL(reg != NULL); 943 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 944 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 945 SPDK_CU_ASSERT_FATAL(reg != NULL); 946 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 947 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 948 949 /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B 950 * with valid key and PRKEY set to 0, all registrants other the host that issued 951 * the command are unregistered. 952 */ 953 gen = g_ns.gen; 954 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 955 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0); 956 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 957 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 958 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 959 SPDK_CU_ASSERT_FATAL(reg == NULL); 960 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 961 SPDK_CU_ASSERT_FATAL(reg == NULL); 962 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 963 SPDK_CU_ASSERT_FATAL(reg != NULL); 964 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 965 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 966 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 967 968 ut_reservation_free_req(req); 969 ut_reservation_deinit(); 970 } 971 972 static void 973 test_reservation_acquire_release_with_ptpl(void) 974 { 975 struct spdk_nvmf_request *req; 976 struct spdk_nvme_cpl *rsp; 977 struct spdk_nvmf_registrant *reg; 978 bool update_sgroup = false; 979 struct spdk_uuid holder_uuid; 980 int rc; 981 struct spdk_nvmf_reservation_info info; 982 983 ut_reservation_init(); 984 985 req = ut_reservation_build_req(16); 986 rsp = &req->rsp->nvme_cpl; 987 SPDK_CU_ASSERT_FATAL(req != NULL); 988 989 /* TEST CASE: Enable PTPL */ 990 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 991 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 992 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 993 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 994 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 995 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 996 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 997 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 998 SPDK_CU_ASSERT_FATAL(reg != NULL); 999 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 1000 /* Load reservation information from configuration file */ 1001 memset(&info, 0, sizeof(info)); 1002 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 1003 SPDK_CU_ASSERT_FATAL(rc == 0); 1004 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 1005 1006 /* TEST CASE: Acquire the reservation */ 1007 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 1008 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1009 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 1010 update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 1011 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 1012 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1013 memset(&info, 0, sizeof(info)); 1014 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 1015 SPDK_CU_ASSERT_FATAL(rc == 0); 1016 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 1017 SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1018 SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1); 1019 spdk_uuid_parse(&holder_uuid, info.holder_uuid); 1020 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid)); 1021 1022 /* TEST CASE: Release the reservation */ 1023 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 1024 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1025 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1); 1026 update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req); 1027 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 1028 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1029 memset(&info, 0, sizeof(info)); 1030 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 1031 SPDK_CU_ASSERT_FATAL(rc == 0); 1032 SPDK_CU_ASSERT_FATAL(info.rtype == 0); 1033 SPDK_CU_ASSERT_FATAL(info.crkey == 0); 1034 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 1035 unlink(g_ns.ptpl_file); 1036 1037 ut_reservation_free_req(req); 1038 ut_reservation_deinit(); 1039 } 1040 1041 static void 1042 test_reservation_release(void) 1043 { 1044 struct spdk_nvmf_request *req; 1045 struct spdk_nvme_cpl *rsp; 1046 struct spdk_nvmf_registrant *reg; 1047 1048 ut_reservation_init(); 1049 1050 req = ut_reservation_build_req(16); 1051 rsp = &req->rsp->nvme_cpl; 1052 SPDK_CU_ASSERT_FATAL(req != NULL); 1053 1054 ut_reservation_build_registrants(); 1055 1056 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with 1057 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS 1058 */ 1059 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1060 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0); 1061 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 1062 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1063 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 1064 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1065 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 1066 1067 /* Test Case: Host B release the reservation */ 1068 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1069 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1); 1070 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1071 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1072 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1073 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 1074 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 1075 1076 /* Test Case: Host C clear the registrants */ 1077 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1078 0, 0xc1); 1079 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req); 1080 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1081 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 1082 SPDK_CU_ASSERT_FATAL(reg == NULL); 1083 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 1084 SPDK_CU_ASSERT_FATAL(reg == NULL); 1085 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 1086 SPDK_CU_ASSERT_FATAL(reg == NULL); 1087 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 1088 SPDK_CU_ASSERT_FATAL(reg == NULL); 1089 1090 ut_reservation_free_req(req); 1091 ut_reservation_deinit(); 1092 } 1093 1094 void 1095 nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, 1096 struct spdk_nvmf_ns *ns, 1097 enum spdk_nvme_reservation_notification_log_page_type type) 1098 { 1099 ctrlr->num_avail_log_pages++; 1100 } 1101 1102 static void 1103 test_reservation_unregister_notification(void) 1104 { 1105 struct spdk_nvmf_request *req; 1106 struct spdk_nvme_cpl *rsp; 1107 1108 ut_reservation_init(); 1109 1110 req = ut_reservation_build_req(16); 1111 SPDK_CU_ASSERT_FATAL(req != NULL); 1112 rsp = &req->rsp->nvme_cpl; 1113 1114 ut_reservation_build_registrants(); 1115 1116 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1117 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1118 */ 1119 rsp->status.sc = 0xff; 1120 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1121 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1122 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1123 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1124 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1125 1126 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration. 1127 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for 1128 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY 1129 * type. 1130 */ 1131 rsp->status.sc = 0xff; 1132 g_ctrlr1_A.num_avail_log_pages = 0; 1133 g_ctrlr2_A.num_avail_log_pages = 0; 1134 g_ctrlr_B.num_avail_log_pages = 5; 1135 g_ctrlr_C.num_avail_log_pages = 0; 1136 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 1137 0, 0, 0xb1, 0); 1138 nvmf_ns_reservation_register(&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(1 == g_ctrlr1_A.num_avail_log_pages); 1142 SPDK_CU_ASSERT_FATAL(1 == 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(1 == 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_release_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 release the reservation. 1175 * Reservation release 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_RELEASE, 0, 1183 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 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_release_notification_write_exclusive(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 1212 */ 1213 rsp->status.sc = 0xff; 1214 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1215 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 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); 1219 1220 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1221 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 1222 * no reservation notification occurs. 1223 */ 1224 rsp->status.sc = 0xff; 1225 g_ctrlr1_A.num_avail_log_pages = 5; 1226 g_ctrlr2_A.num_avail_log_pages = 5; 1227 g_ctrlr_B.num_avail_log_pages = 5; 1228 g_ctrlr_C.num_avail_log_pages = 5; 1229 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1230 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1); 1231 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1232 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1233 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1234 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages); 1235 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages); 1236 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1237 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1238 1239 ut_reservation_free_req(req); 1240 ut_reservation_deinit(); 1241 } 1242 1243 static void 1244 test_reservation_clear_notification(void) 1245 { 1246 struct spdk_nvmf_request *req; 1247 struct spdk_nvme_cpl *rsp; 1248 1249 ut_reservation_init(); 1250 1251 req = ut_reservation_build_req(16); 1252 SPDK_CU_ASSERT_FATAL(req != NULL); 1253 rsp = &req->rsp->nvme_cpl; 1254 1255 ut_reservation_build_registrants(); 1256 1257 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1258 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1259 */ 1260 rsp->status.sc = 0xff; 1261 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1262 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1263 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1264 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1265 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1266 1267 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation. 1268 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1269 */ 1270 rsp->status.sc = 0xff; 1271 g_ctrlr1_A.num_avail_log_pages = 0; 1272 g_ctrlr2_A.num_avail_log_pages = 0; 1273 g_ctrlr_B.num_avail_log_pages = 5; 1274 g_ctrlr_C.num_avail_log_pages = 0; 1275 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1276 0, 0xb1); 1277 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1278 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1279 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1280 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1281 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1282 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1283 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1284 1285 ut_reservation_free_req(req); 1286 ut_reservation_deinit(); 1287 } 1288 1289 static void 1290 test_reservation_preempt_notification(void) 1291 { 1292 struct spdk_nvmf_request *req; 1293 struct spdk_nvme_cpl *rsp; 1294 1295 ut_reservation_init(); 1296 1297 req = ut_reservation_build_req(16); 1298 SPDK_CU_ASSERT_FATAL(req != NULL); 1299 rsp = &req->rsp->nvme_cpl; 1300 1301 ut_reservation_build_registrants(); 1302 1303 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1304 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1305 */ 1306 rsp->status.sc = 0xff; 1307 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1308 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1309 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1310 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1311 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1312 1313 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B, 1314 * g_ctrlr_B registrant is unregistered, and reservation is preempted. 1315 * Registration Preempted notification sends to g_ctrlr_B. 1316 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A. 1317 */ 1318 rsp->status.sc = 0xff; 1319 g_ctrlr1_A.num_avail_log_pages = 0; 1320 g_ctrlr2_A.num_avail_log_pages = 0; 1321 g_ctrlr_B.num_avail_log_pages = 0; 1322 g_ctrlr_C.num_avail_log_pages = 5; 1323 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 1324 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1); 1325 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 1326 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1327 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1328 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1329 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1330 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages); 1331 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1332 1333 ut_reservation_free_req(req); 1334 ut_reservation_deinit(); 1335 } 1336 1337 static int 1338 nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf) 1339 { 1340 return 0; 1341 } 1342 1343 static void 1344 nvmf_tgt_destroy_poll_group(void *io_device, void *ctx_buf) 1345 { 1346 } 1347 1348 static void 1349 test_spdk_nvmf_ns_event(void) 1350 { 1351 struct spdk_nvmf_tgt tgt = {}; 1352 struct spdk_nvmf_subsystem subsystem = { 1353 .max_nsid = 1024, 1354 .ns = NULL, 1355 .tgt = &tgt, 1356 }; 1357 struct spdk_nvmf_ctrlr ctrlr = { 1358 .subsys = &subsystem 1359 }; 1360 struct spdk_nvmf_ns_opts ns_opts; 1361 uint32_t nsid; 1362 struct spdk_bdev *bdev; 1363 1364 subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *)); 1365 SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL); 1366 subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t)); 1367 SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL); 1368 1369 tgt.max_subsystems = 1024; 1370 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1371 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1372 1373 spdk_io_device_register(&tgt, 1374 nvmf_tgt_create_poll_group, 1375 nvmf_tgt_destroy_poll_group, 1376 sizeof(struct spdk_nvmf_poll_group), 1377 NULL); 1378 1379 /* Add one namespace */ 1380 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1381 nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL); 1382 CU_ASSERT(nsid == 1); 1383 CU_ASSERT(NULL != subsystem.ns[0]); 1384 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]); 1385 1386 bdev = subsystem.ns[nsid - 1]->bdev; 1387 1388 /* Add one controller */ 1389 TAILQ_INIT(&subsystem.ctrlrs); 1390 TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link); 1391 1392 /* Namespace resize event */ 1393 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1394 g_ns_changed_nsid = 0xFFFFFFFF; 1395 g_ns_changed_ctrlr = NULL; 1396 nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]); 1397 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1398 1399 poll_threads(); 1400 CU_ASSERT(1 == g_ns_changed_nsid); 1401 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1402 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1403 1404 /* Namespace remove event */ 1405 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1406 g_ns_changed_nsid = 0xFFFFFFFF; 1407 g_ns_changed_ctrlr = NULL; 1408 nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]); 1409 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1410 CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid); 1411 CU_ASSERT(NULL == g_ns_changed_ctrlr); 1412 1413 poll_threads(); 1414 CU_ASSERT(1 == g_ns_changed_nsid); 1415 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1416 CU_ASSERT(NULL == subsystem.ns[0]); 1417 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1418 1419 spdk_io_device_unregister(&tgt, NULL); 1420 1421 poll_threads(); 1422 1423 free(subsystem.ns); 1424 free(subsystem.ana_group); 1425 free(tgt.subsystems); 1426 } 1427 1428 static void 1429 test_nvmf_ns_reservation_add_remove_registrant(void) 1430 { 1431 struct spdk_nvmf_ns ns = {}; 1432 struct spdk_nvmf_ctrlr ctrlr = {}; 1433 struct spdk_nvmf_registrant *reg = NULL; 1434 int rc; 1435 1436 TAILQ_INIT(&ns.registrants); 1437 spdk_uuid_generate(&ctrlr.hostid); 1438 1439 rc = nvmf_ns_reservation_add_registrant(&ns, &ctrlr, 0xa11); 1440 CU_ASSERT(rc == 0); 1441 reg = TAILQ_FIRST(&ns.registrants); 1442 SPDK_CU_ASSERT_FATAL(reg != NULL); 1443 CU_ASSERT(ns.gen == 1); 1444 CU_ASSERT(reg->rkey == 0xa11); 1445 CU_ASSERT(!strncmp((uint8_t *)®->hostid, (uint8_t *)&ctrlr.hostid, sizeof(ctrlr.hostid))); 1446 1447 nvmf_ns_reservation_remove_registrant(&ns, reg); 1448 CU_ASSERT(TAILQ_EMPTY(&ns.registrants)); 1449 CU_ASSERT(ns.gen == 2); 1450 } 1451 1452 static void 1453 test_nvmf_subsystem_destroy_cb(void *cb_arg) 1454 { 1455 } 1456 1457 static void 1458 test_nvmf_subsystem_add_ctrlr(void) 1459 { 1460 int rc; 1461 struct spdk_nvmf_ctrlr ctrlr = {}; 1462 struct spdk_nvmf_tgt tgt = {}; 1463 char nqn[256] = "nqn.2016-06.io.spdk:subsystem1"; 1464 struct spdk_nvmf_subsystem *subsystem = NULL; 1465 1466 tgt.max_subsystems = 1024; 1467 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1468 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1469 1470 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 1471 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 1472 ctrlr.subsys = subsystem; 1473 1474 ctrlr.dynamic_ctrlr = true; 1475 rc = nvmf_subsystem_add_ctrlr(subsystem, &ctrlr); 1476 CU_ASSERT(rc == 0); 1477 CU_ASSERT(!TAILQ_EMPTY(&subsystem->ctrlrs)); 1478 CU_ASSERT(ctrlr.cntlid == 1); 1479 CU_ASSERT(nvmf_subsystem_get_ctrlr(subsystem, 1) == &ctrlr); 1480 1481 nvmf_subsystem_remove_ctrlr(subsystem, &ctrlr); 1482 CU_ASSERT(TAILQ_EMPTY(&subsystem->ctrlrs)); 1483 rc = spdk_nvmf_subsystem_destroy(subsystem, test_nvmf_subsystem_destroy_cb, NULL); 1484 CU_ASSERT(rc == 0); 1485 free(tgt.subsystems); 1486 } 1487 1488 static void 1489 test_spdk_nvmf_subsystem_add_host(void) 1490 { 1491 struct spdk_nvmf_tgt tgt = {}; 1492 struct spdk_nvmf_subsystem *subsystem = NULL; 1493 int rc; 1494 const char hostnqn[] = "nqn.2016-06.io.spdk:host1"; 1495 const char subsystemnqn[] = "nqn.2016-06.io.spdk:subsystem1"; 1496 1497 tgt.max_subsystems = 1024; 1498 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1499 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1500 1501 subsystem = spdk_nvmf_subsystem_create(&tgt, subsystemnqn, SPDK_NVMF_SUBTYPE_NVME, 0); 1502 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 1503 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, subsystemnqn); 1504 1505 rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn); 1506 CU_ASSERT(rc == 0); 1507 CU_ASSERT(!TAILQ_EMPTY(&subsystem->hosts)); 1508 1509 /* Add existing nqn, this function is allowed to be called if the nqn was previously added. */ 1510 rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn); 1511 CU_ASSERT(rc == 0); 1512 1513 rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn); 1514 CU_ASSERT(rc == 0); 1515 CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts)); 1516 1517 /* No available nqn */ 1518 rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn); 1519 CU_ASSERT(rc == -ENOENT); 1520 1521 spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 1522 free(tgt.subsystems); 1523 } 1524 1525 static void 1526 test_nvmf_ns_reservation_report(void) 1527 { 1528 struct spdk_nvmf_ns ns = {}; 1529 struct spdk_nvmf_ctrlr ctrlr = {}; 1530 struct spdk_nvmf_request req = {}; 1531 union nvmf_h2c_msg cmd = {}; 1532 union nvmf_c2h_msg rsp = {}; 1533 struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data; 1534 struct spdk_nvme_reservation_status_extended_data *status_data; 1535 struct spdk_nvmf_registrant *reg; 1536 1537 req.data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2); 1538 reg = calloc(2, sizeof(struct spdk_nvmf_registrant)); 1539 SPDK_CU_ASSERT_FATAL(req.data != NULL && reg != NULL); 1540 1541 req.cmd = &cmd; 1542 req.rsp = &rsp; 1543 ns.gen = 1; 1544 ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE; 1545 ns.ptpl_activated = true; 1546 cmd.nvme_cmd.cdw11_bits.resv_report.eds = true; 1547 cmd.nvme_cmd.cdw10 = 100; 1548 reg[0].rkey = 0xa; 1549 reg[1].rkey = 0xb; 1550 spdk_uuid_generate(®[0].hostid); 1551 spdk_uuid_generate(®[1].hostid); 1552 TAILQ_INIT(&ns.registrants); 1553 TAILQ_INSERT_TAIL(&ns.registrants, ®[0], link); 1554 TAILQ_INSERT_TAIL(&ns.registrants, ®[1], link); 1555 1556 nvmf_ns_reservation_report(&ns, &ctrlr, &req); 1557 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1558 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 1559 /* Get ctrlr data and status data pointers */ 1560 ctrlr_data = (void *)((uint64_t)req.data + sizeof(*status_data)); 1561 status_data = (void *)req.data; 1562 SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL); 1563 CU_ASSERT(status_data->data.gen == 1); 1564 CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 1565 CU_ASSERT(status_data->data.ptpls == true); 1566 CU_ASSERT(status_data->data.regctl == 2); 1567 CU_ASSERT(ctrlr_data->cntlid == 0xffff); 1568 CU_ASSERT(ctrlr_data->rcsts.status == false); 1569 CU_ASSERT(ctrlr_data->rkey == 0xa); 1570 CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, ®[0].hostid)); 1571 /* Check second ctrlr data */ 1572 ctrlr_data++; 1573 CU_ASSERT(ctrlr_data->cntlid == 0xffff); 1574 CU_ASSERT(ctrlr_data->rcsts.status == false); 1575 CU_ASSERT(ctrlr_data->rkey == 0xb); 1576 CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, ®[1].hostid)); 1577 1578 /* extended controller data structure */ 1579 memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2); 1580 memset(req.rsp, 0, sizeof(*req.rsp)); 1581 cmd.nvme_cmd.cdw11_bits.resv_report.eds = false; 1582 1583 nvmf_ns_reservation_report(&ns, &ctrlr, &req); 1584 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT); 1585 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1586 1587 /* Transfer length invalid */ 1588 memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2); 1589 memset(req.rsp, 0, sizeof(*req.rsp)); 1590 cmd.nvme_cmd.cdw11_bits.resv_report.eds = true; 1591 cmd.nvme_cmd.cdw10 = 0; 1592 1593 nvmf_ns_reservation_report(&ns, &ctrlr, &req); 1594 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR); 1595 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1596 1597 free(req.data); 1598 free(reg); 1599 } 1600 1601 static void 1602 test_nvmf_valid_nqn(void) 1603 { 1604 bool rc; 1605 char uuid[SPDK_NVMF_UUID_STRING_LEN + 1] = {}; 1606 char nqn[SPDK_NVMF_NQN_MAX_LEN + 1] = {}; 1607 struct spdk_uuid s_uuid = {}; 1608 1609 spdk_uuid_generate(&s_uuid); 1610 uuid_unparse((void *)&s_uuid, uuid); 1611 1612 /* discovery nqn */ 1613 snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_DISCOVERY_NQN); 1614 1615 rc = nvmf_valid_nqn(nqn); 1616 CU_ASSERT(rc == true); 1617 1618 /* nqn with uuid */ 1619 memset(nqn, 0xff, sizeof(nqn)); 1620 snprintf(nqn, sizeof(nqn), "%s%s", SPDK_NVMF_NQN_UUID_PRE, uuid); 1621 1622 rc = nvmf_valid_nqn(nqn); 1623 CU_ASSERT(rc == true); 1624 1625 /* Check nqn valid reverse domain */ 1626 memset(nqn, 0xff, sizeof(nqn)); 1627 snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io.spdk:cnode1"); 1628 1629 rc = nvmf_valid_nqn(nqn); 1630 CU_ASSERT(rc == true); 1631 1632 /* Invalid nqn length */ 1633 memset(nqn, 0xff, sizeof(nqn)); 1634 snprintf(nqn, sizeof(nqn), "%s", "nqn."); 1635 1636 rc = nvmf_valid_nqn(nqn); 1637 CU_ASSERT(rc == false); 1638 1639 /* Copy uuid to the nqn string, but omit the last character to make it invalid */ 1640 memset(nqn, 0, SPDK_NVMF_NQN_MAX_LEN + 1); 1641 snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_NQN_UUID_PRE); 1642 memcpy(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid, SPDK_NVMF_UUID_STRING_LEN - 1); 1643 1644 rc = nvmf_valid_nqn(nqn); 1645 CU_ASSERT(rc == false); 1646 1647 /* Invalid domain */ 1648 memset(nqn, 0xff, SPDK_NVMF_NQN_MAX_LEN + 1); 1649 snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io...spdk:cnode1"); 1650 1651 rc = nvmf_valid_nqn(nqn); 1652 CU_ASSERT(rc == false); 1653 } 1654 1655 static void 1656 test_nvmf_ns_reservation_restore(void) 1657 { 1658 struct spdk_nvmf_ns ns = {}; 1659 struct spdk_nvmf_reservation_info info = {}; 1660 struct spdk_bdev bdev = {}; 1661 struct spdk_uuid s_uuid = {}; 1662 struct spdk_nvmf_registrant *reg0, *reg1; 1663 char uuid[SPDK_UUID_STRING_LEN] = {}; 1664 int rc; 1665 1666 ns.bdev = &bdev; 1667 TAILQ_INIT(&ns.registrants); 1668 info.ptpl_activated = true; 1669 info.num_regs = 2; 1670 info.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS; 1671 info.registrants[0].rkey = 0xb; 1672 info.registrants[1].rkey = 0xc; 1673 1674 /* Generate and prepare uuids, make sure bdev and info uuid are the same */ 1675 spdk_uuid_generate(&s_uuid); 1676 uuid_unparse((void *)&s_uuid, uuid); 1677 snprintf(info.holder_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1678 snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1679 snprintf(info.registrants[0].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1680 spdk_uuid_copy(&bdev.uuid, &s_uuid); 1681 spdk_uuid_generate(&s_uuid); 1682 uuid_unparse((void *)&s_uuid, uuid); 1683 snprintf(info.registrants[1].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1684 1685 /* info->rkey not exist in registrants */ 1686 info.crkey = 0xa; 1687 1688 rc = nvmf_ns_reservation_restore(&ns, &info); 1689 CU_ASSERT(rc == -EINVAL); 1690 1691 /* info->rkey exists in registrants */ 1692 info.crkey = 0xb; 1693 1694 rc = nvmf_ns_reservation_restore(&ns, &info); 1695 CU_ASSERT(rc == 0); 1696 CU_ASSERT(ns.crkey == 0xb); 1697 CU_ASSERT(ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1698 CU_ASSERT(ns.ptpl_activated == true); 1699 /* Check two registrant`s rkey */ 1700 reg0 = TAILQ_FIRST(&ns.registrants); 1701 reg1 = TAILQ_NEXT(reg0, link); 1702 CU_ASSERT(ns.holder == reg0); 1703 CU_ASSERT(reg0->rkey = 0xb); 1704 CU_ASSERT(reg1->rkey = 0xc); 1705 1706 rc = nvmf_ns_reservation_clear_all_registrants(&ns); 1707 CU_ASSERT(rc == 2); 1708 CU_ASSERT(TAILQ_EMPTY(&ns.registrants)); 1709 1710 /* Existing bdev UUID is different with configuration */ 1711 spdk_uuid_generate(&s_uuid); 1712 uuid_unparse((void *)&s_uuid, uuid); 1713 snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1714 spdk_uuid_generate(&s_uuid); 1715 spdk_uuid_copy(&bdev.uuid, &s_uuid); 1716 1717 rc = nvmf_ns_reservation_restore(&ns, &info); 1718 CU_ASSERT(rc == -EINVAL); 1719 } 1720 1721 int main(int argc, char **argv) 1722 { 1723 CU_pSuite suite = NULL; 1724 unsigned int num_failures; 1725 1726 CU_set_error_action(CUEA_ABORT); 1727 CU_initialize_registry(); 1728 1729 suite = CU_add_suite("nvmf", NULL, NULL); 1730 1731 CU_ADD_TEST(suite, nvmf_test_create_subsystem); 1732 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns); 1733 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn); 1734 CU_ADD_TEST(suite, test_reservation_register); 1735 CU_ADD_TEST(suite, test_reservation_register_with_ptpl); 1736 CU_ADD_TEST(suite, test_reservation_acquire_preempt_1); 1737 CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl); 1738 CU_ADD_TEST(suite, test_reservation_release); 1739 CU_ADD_TEST(suite, test_reservation_unregister_notification); 1740 CU_ADD_TEST(suite, test_reservation_release_notification); 1741 CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive); 1742 CU_ADD_TEST(suite, test_reservation_clear_notification); 1743 CU_ADD_TEST(suite, test_reservation_preempt_notification); 1744 CU_ADD_TEST(suite, test_spdk_nvmf_ns_event); 1745 CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant); 1746 CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr); 1747 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host); 1748 CU_ADD_TEST(suite, test_nvmf_ns_reservation_report); 1749 CU_ADD_TEST(suite, test_nvmf_valid_nqn); 1750 CU_ADD_TEST(suite, test_nvmf_ns_reservation_restore); 1751 1752 allocate_threads(1); 1753 set_thread(0); 1754 1755 CU_basic_set_mode(CU_BRM_VERBOSE); 1756 CU_basic_run_tests(); 1757 num_failures = CU_get_number_of_failures(); 1758 CU_cleanup_registry(); 1759 1760 free_threads(); 1761 1762 return num_failures; 1763 } 1764