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