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