1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "common/lib/ut_multithread.c" 37 #include "spdk_cunit.h" 38 #include "spdk_internal/mock.h" 39 #include "spdk_internal/thread.h" 40 41 #include "nvmf/subsystem.c" 42 43 SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF) 44 45 DEFINE_STUB(spdk_bdev_module_claim_bdev, 46 int, 47 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 48 struct spdk_bdev_module *module), 0); 49 50 DEFINE_STUB_V(spdk_bdev_module_release_bdev, 51 (struct spdk_bdev *bdev)); 52 53 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, 54 (const struct spdk_bdev *bdev), 512); 55 56 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t, 57 (const struct spdk_bdev *bdev), 0); 58 59 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool, 60 (const struct spdk_bdev *bdev), false); 61 62 DEFINE_STUB(spdk_nvmf_transport_stop_listen, 63 int, 64 (struct spdk_nvmf_transport *transport, 65 const struct spdk_nvme_transport_id *trid), 0); 66 67 uint32_t 68 spdk_env_get_current_core(void) 69 { 70 return 0; 71 } 72 73 struct spdk_event * 74 spdk_event_allocate(uint32_t core, spdk_event_fn fn, void *arg1, void *arg2) 75 { 76 return NULL; 77 } 78 79 void 80 spdk_event_call(struct spdk_event *event) 81 { 82 83 } 84 85 int 86 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport, 87 const struct spdk_nvme_transport_id *trid) 88 { 89 return 0; 90 } 91 92 void 93 spdk_nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport, 94 struct spdk_nvme_transport_id *trid, 95 struct spdk_nvmf_discovery_log_page_entry *entry) 96 { 97 entry->trtype = 42; 98 } 99 100 static struct spdk_nvmf_transport g_transport = {}; 101 102 struct spdk_nvmf_transport * 103 spdk_nvmf_transport_create(enum spdk_nvme_transport_type type, 104 struct spdk_nvmf_transport_opts *tprt_opts) 105 { 106 if (type == SPDK_NVME_TRANSPORT_RDMA) { 107 return &g_transport; 108 } 109 110 return NULL; 111 } 112 113 struct spdk_nvmf_subsystem * 114 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 115 { 116 return NULL; 117 } 118 119 struct spdk_nvmf_transport * 120 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, enum spdk_nvme_transport_type trtype) 121 { 122 if (trtype == SPDK_NVME_TRANSPORT_RDMA) { 123 return &g_transport; 124 } 125 126 return NULL; 127 } 128 129 int 130 spdk_nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, 131 struct spdk_nvmf_subsystem *subsystem) 132 { 133 return 0; 134 } 135 136 int 137 spdk_nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, 138 struct spdk_nvmf_subsystem *subsystem, 139 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 140 { 141 return 0; 142 } 143 144 void 145 spdk_nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, 146 struct spdk_nvmf_subsystem *subsystem, 147 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 148 { 149 } 150 151 void 152 spdk_nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group, 153 struct spdk_nvmf_subsystem *subsystem, 154 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 155 { 156 } 157 158 void 159 spdk_nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group, 160 struct spdk_nvmf_subsystem *subsystem, 161 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 162 { 163 } 164 165 int 166 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str) 167 { 168 if (trtype == NULL || str == NULL) { 169 return -EINVAL; 170 } 171 172 if (strcasecmp(str, "PCIe") == 0) { 173 *trtype = SPDK_NVME_TRANSPORT_PCIE; 174 } else if (strcasecmp(str, "RDMA") == 0) { 175 *trtype = SPDK_NVME_TRANSPORT_RDMA; 176 } else { 177 return -ENOENT; 178 } 179 return 0; 180 } 181 182 int 183 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1, 184 const struct spdk_nvme_transport_id *trid2) 185 { 186 return 0; 187 } 188 189 int32_t 190 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr) 191 { 192 return -1; 193 } 194 195 int32_t 196 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) 197 { 198 return -1; 199 } 200 201 int 202 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr) 203 { 204 return -1; 205 } 206 207 void 208 spdk_nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr) 209 { 210 } 211 212 void 213 spdk_nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 214 { 215 } 216 217 int 218 spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb, 219 void *remove_ctx, struct spdk_bdev_desc **desc) 220 { 221 return 0; 222 } 223 224 void 225 spdk_bdev_close(struct spdk_bdev_desc *desc) 226 { 227 } 228 229 const char * 230 spdk_bdev_get_name(const struct spdk_bdev *bdev) 231 { 232 return "test"; 233 } 234 235 const struct spdk_uuid * 236 spdk_bdev_get_uuid(const struct spdk_bdev *bdev) 237 { 238 return &bdev->uuid; 239 } 240 241 static void 242 test_spdk_nvmf_subsystem_add_ns(void) 243 { 244 struct spdk_nvmf_tgt tgt = {}; 245 struct spdk_nvmf_subsystem subsystem = { 246 .max_nsid = 0, 247 .ns = NULL, 248 .tgt = &tgt 249 }; 250 struct spdk_bdev bdev1 = {}, bdev2 = {}; 251 struct spdk_nvmf_ns_opts ns_opts; 252 uint32_t nsid; 253 int rc; 254 255 tgt.max_subsystems = 1024; 256 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 257 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 258 259 /* Allow NSID to be assigned automatically */ 260 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 261 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts), NULL); 262 /* NSID 1 is the first unused ID */ 263 CU_ASSERT(nsid == 1); 264 CU_ASSERT(subsystem.max_nsid == 1); 265 SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL); 266 SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL); 267 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &bdev1); 268 269 /* Request a specific NSID */ 270 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 271 ns_opts.nsid = 5; 272 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL); 273 CU_ASSERT(nsid == 5); 274 CU_ASSERT(subsystem.max_nsid == 5); 275 SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL); 276 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &bdev2); 277 278 /* Request an NSID that is already in use */ 279 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 280 ns_opts.nsid = 5; 281 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL); 282 CU_ASSERT(nsid == 0); 283 CU_ASSERT(subsystem.max_nsid == 5); 284 285 /* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */ 286 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 287 ns_opts.nsid = 0xFFFFFFFF; 288 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL); 289 CU_ASSERT(nsid == 0); 290 CU_ASSERT(subsystem.max_nsid == 5); 291 292 rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 1); 293 CU_ASSERT(rc == 0); 294 rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5); 295 CU_ASSERT(rc == 0); 296 297 free(subsystem.ns); 298 free(tgt.subsystems); 299 } 300 301 static void 302 nvmf_test_create_subsystem(void) 303 { 304 struct spdk_nvmf_tgt tgt = {}; 305 char nqn[256]; 306 struct spdk_nvmf_subsystem *subsystem; 307 308 tgt.max_subsystems = 1024; 309 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 310 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 311 312 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 313 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 314 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 315 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 316 spdk_nvmf_subsystem_destroy(subsystem); 317 318 /* valid name with complex reverse domain */ 319 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1"); 320 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 321 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 322 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 323 spdk_nvmf_subsystem_destroy(subsystem); 324 325 /* Valid name discovery controller */ 326 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 327 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 328 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 329 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 330 spdk_nvmf_subsystem_destroy(subsystem); 331 332 333 /* Invalid name, no user supplied string */ 334 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 335 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 336 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 337 338 /* Valid name, only contains top-level domain name */ 339 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 340 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 341 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 342 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 343 spdk_nvmf_subsystem_destroy(subsystem); 344 345 /* Invalid name, domain label > 63 characters */ 346 snprintf(nqn, sizeof(nqn), 347 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub"); 348 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 349 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 350 351 /* Invalid name, domain label starts with digit */ 352 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub"); 353 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 354 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 355 356 /* Invalid name, domain label starts with - */ 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 361 /* Invalid name, domain label ends with - */ 362 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1"); 363 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 364 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 365 366 /* Invalid name, domain label with multiple consecutive periods */ 367 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1"); 368 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 369 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 370 371 /* Longest valid name */ 372 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 373 memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn)); 374 nqn[223] = '\0'; 375 CU_ASSERT(strlen(nqn) == 223); 376 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 377 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 378 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 379 spdk_nvmf_subsystem_destroy(subsystem); 380 381 /* Invalid name, too long */ 382 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 383 memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn)); 384 nqn[224] = '\0'; 385 CU_ASSERT(strlen(nqn) == 224); 386 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 387 CU_ASSERT(subsystem == NULL); 388 389 /* Valid name using uuid format */ 390 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc"); 391 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 392 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 393 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 394 spdk_nvmf_subsystem_destroy(subsystem); 395 396 /* Invalid name user string contains an invalid utf-8 character */ 397 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1"); 398 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 399 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 400 401 /* Valid name with non-ascii but valid utf-8 characters */ 402 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80"); 403 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 404 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 405 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 406 spdk_nvmf_subsystem_destroy(subsystem); 407 408 /* Invalid uuid (too long) */ 409 snprintf(nqn, sizeof(nqn), 410 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef"); 411 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 412 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 413 414 /* Invalid uuid (dashes placed incorrectly) */ 415 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc"); 416 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 417 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 418 419 /* Invalid uuid (invalid characters in uuid) */ 420 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc"); 421 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 422 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 423 424 free(tgt.subsystems); 425 } 426 427 static void 428 test_spdk_nvmf_subsystem_set_sn(void) 429 { 430 struct spdk_nvmf_subsystem subsystem = {}; 431 432 /* Basic valid serial number */ 433 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0); 434 CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0); 435 436 /* Exactly 20 characters (valid) */ 437 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0); 438 CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0); 439 440 /* 21 characters (too long, invalid) */ 441 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0); 442 443 /* Non-ASCII characters (invalid) */ 444 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0); 445 } 446 447 /* 448 * Reservation Unit Test Configuration 449 * -------- -------- -------- 450 * | Host A | | Host B | | Host C | 451 * -------- -------- -------- 452 * / \ | | 453 * -------- -------- ------- ------- 454 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C| 455 * -------- -------- ------- ------- 456 * \ \ / / 457 * \ \ / / 458 * \ \ / / 459 * -------------------------------------- 460 * | NAMESPACE 1 | 461 * -------------------------------------- 462 */ 463 static struct spdk_nvmf_subsystem g_subsystem; 464 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; 465 static struct spdk_nvmf_ns g_ns; 466 static struct spdk_bdev g_bdev; 467 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; 468 469 void 470 spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr) 471 { 472 } 473 474 static void 475 ut_reservation_init(void) 476 { 477 478 TAILQ_INIT(&g_subsystem.ctrlrs); 479 480 memset(&g_ns, 0, sizeof(g_ns)); 481 TAILQ_INIT(&g_ns.registrants); 482 g_ns.subsystem = &g_subsystem; 483 g_ns.ptpl_file = NULL; 484 g_ns.ptpl_activated = false; 485 spdk_uuid_generate(&g_bdev.uuid); 486 g_ns.bdev = &g_bdev; 487 488 /* Host A has two controllers */ 489 spdk_uuid_generate(&g_ctrlr1_A.hostid); 490 TAILQ_INIT(&g_ctrlr1_A.log_head); 491 g_ctrlr1_A.subsys = &g_subsystem; 492 g_ctrlr1_A.num_avail_log_pages = 0; 493 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link); 494 spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); 495 TAILQ_INIT(&g_ctrlr2_A.log_head); 496 g_ctrlr2_A.subsys = &g_subsystem; 497 g_ctrlr2_A.num_avail_log_pages = 0; 498 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link); 499 500 /* Host B has 1 controller */ 501 spdk_uuid_generate(&g_ctrlr_B.hostid); 502 TAILQ_INIT(&g_ctrlr_B.log_head); 503 g_ctrlr_B.subsys = &g_subsystem; 504 g_ctrlr_B.num_avail_log_pages = 0; 505 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link); 506 507 /* Host C has 1 controller */ 508 spdk_uuid_generate(&g_ctrlr_C.hostid); 509 TAILQ_INIT(&g_ctrlr_C.log_head); 510 g_ctrlr_C.subsys = &g_subsystem; 511 g_ctrlr_C.num_avail_log_pages = 0; 512 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link); 513 } 514 515 static void 516 ut_reservation_deinit(void) 517 { 518 struct spdk_nvmf_registrant *reg, *tmp; 519 struct spdk_nvmf_reservation_log *log, *log_tmp; 520 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 521 522 TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) { 523 TAILQ_REMOVE(&g_ns.registrants, reg, link); 524 free(reg); 525 } 526 TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) { 527 TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link); 528 free(log); 529 } 530 g_ctrlr1_A.num_avail_log_pages = 0; 531 TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) { 532 TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link); 533 free(log); 534 } 535 g_ctrlr2_A.num_avail_log_pages = 0; 536 TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) { 537 TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link); 538 free(log); 539 } 540 g_ctrlr_B.num_avail_log_pages = 0; 541 TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) { 542 TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link); 543 free(log); 544 } 545 g_ctrlr_C.num_avail_log_pages = 0; 546 547 TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) { 548 TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link); 549 } 550 } 551 552 static struct spdk_nvmf_request * 553 ut_reservation_build_req(uint32_t length) 554 { 555 struct spdk_nvmf_request *req; 556 557 req = calloc(1, sizeof(*req)); 558 assert(req != NULL); 559 560 req->data = calloc(1, length); 561 assert(req->data != NULL); 562 req->length = length; 563 564 req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg)); 565 assert(req->cmd != NULL); 566 567 req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg)); 568 assert(req->rsp != NULL); 569 570 return req; 571 } 572 573 static void 574 ut_reservation_free_req(struct spdk_nvmf_request *req) 575 { 576 free(req->cmd); 577 free(req->rsp); 578 free(req->data); 579 free(req); 580 } 581 582 static void 583 ut_reservation_build_register_request(struct spdk_nvmf_request *req, 584 uint8_t rrega, uint8_t iekey, 585 uint8_t cptpl, uint64_t crkey, 586 uint64_t nrkey) 587 { 588 uint32_t cdw10; 589 struct spdk_nvme_reservation_register_data key; 590 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 591 592 cdw10 = (((uint32_t)cptpl << 30) | ((uint32_t)iekey << 3) | rrega); 593 key.crkey = crkey; 594 key.nrkey = nrkey; 595 cmd->cdw10 = cdw10; 596 memcpy(req->data, &key, sizeof(key)); 597 } 598 599 static void 600 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req, 601 uint8_t racqa, uint8_t iekey, 602 uint8_t rtype, uint64_t crkey, 603 uint64_t prkey) 604 { 605 uint32_t cdw10; 606 struct spdk_nvme_reservation_acquire_data key; 607 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 608 609 cdw10 = ((rtype << 8) | (iekey << 3) | racqa); 610 key.crkey = crkey; 611 key.prkey = prkey; 612 cmd->cdw10 = cdw10; 613 memcpy(req->data, &key, sizeof(key)); 614 } 615 616 static void 617 ut_reservation_build_release_request(struct spdk_nvmf_request *req, 618 uint8_t rrela, uint8_t iekey, 619 uint8_t rtype, uint64_t crkey) 620 { 621 uint32_t cdw10; 622 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 623 624 cdw10 = ((rtype << 8) | (iekey << 3) | rrela); 625 cmd->cdw10 = cdw10; 626 memcpy(req->data, &crkey, sizeof(crkey)); 627 } 628 629 /* 630 * Construct four registrants for other test cases. 631 * 632 * g_ctrlr1_A register with key 0xa1. 633 * g_ctrlr2_A register with key 0xa1. 634 * g_ctrlr_B register with key 0xb1. 635 * g_ctrlr_C register with key 0xc1. 636 * */ 637 static void 638 ut_reservation_build_registrants(void) 639 { 640 struct spdk_nvmf_request *req; 641 struct spdk_nvme_cpl *rsp; 642 struct spdk_nvmf_registrant *reg; 643 uint32_t gen; 644 645 req = ut_reservation_build_req(16); 646 rsp = &req->rsp->nvme_cpl; 647 SPDK_CU_ASSERT_FATAL(req != NULL); 648 gen = g_ns.gen; 649 650 /* TEST CASE: g_ctrlr1_A register with a new key */ 651 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 652 0, 0, 0, 0xa1); 653 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 654 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 655 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 656 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1); 657 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1); 658 659 /* TEST CASE: g_ctrlr2_A register with a new key, because it has same 660 * Host Identifier with g_ctrlr1_A, so the register key should same. 661 */ 662 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 663 0, 0, 0, 0xa2); 664 nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req); 665 /* Reservation conflict for other key than 0xa1 */ 666 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 667 668 /* g_ctrlr_B register with a new key */ 669 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 670 0, 0, 0, 0xb1); 671 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 672 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 673 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 674 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1); 675 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2); 676 677 /* g_ctrlr_C register with a new key */ 678 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 679 0, 0, 0, 0xc1); 680 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 681 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 682 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 683 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1); 684 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3); 685 686 ut_reservation_free_req(req); 687 } 688 689 static void 690 test_reservation_register(void) 691 { 692 struct spdk_nvmf_request *req; 693 struct spdk_nvme_cpl *rsp; 694 struct spdk_nvmf_registrant *reg; 695 uint32_t gen; 696 697 ut_reservation_init(); 698 699 req = ut_reservation_build_req(16); 700 rsp = &req->rsp->nvme_cpl; 701 SPDK_CU_ASSERT_FATAL(req != NULL); 702 703 ut_reservation_build_registrants(); 704 705 /* TEST CASE: Replace g_ctrlr1_A with a new key */ 706 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 707 0, 0, 0xa1, 0xa11); 708 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 709 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 710 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 711 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11); 712 713 /* TEST CASE: Host A with g_ctrlr1_A get reservation with 714 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 715 */ 716 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 717 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0); 718 gen = g_ns.gen; 719 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 720 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 721 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 722 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 723 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11); 724 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 725 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 726 727 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */ 728 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 729 1, 0, 0, 0); 730 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 731 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 732 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 733 SPDK_CU_ASSERT_FATAL(reg == NULL); 734 735 /* TEST CASE: g_ctrlr_B unregister with correct key */ 736 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 737 0, 0, 0xb1, 0); 738 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 739 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 740 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 741 SPDK_CU_ASSERT_FATAL(reg == NULL); 742 743 /* TEST CASE: g_ctrlr1_A unregister with correct key, 744 * reservation should be removed as well. 745 */ 746 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 747 0, 0, 0xa11, 0); 748 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 749 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 750 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 751 SPDK_CU_ASSERT_FATAL(reg == NULL); 752 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 753 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 754 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 755 756 ut_reservation_free_req(req); 757 ut_reservation_deinit(); 758 } 759 760 static void 761 test_reservation_register_with_ptpl(void) 762 { 763 struct spdk_nvmf_request *req; 764 struct spdk_nvme_cpl *rsp; 765 struct spdk_nvmf_registrant *reg; 766 bool update_sgroup = false; 767 int rc; 768 struct spdk_nvmf_reservation_info info; 769 770 ut_reservation_init(); 771 772 req = ut_reservation_build_req(16); 773 rsp = &req->rsp->nvme_cpl; 774 SPDK_CU_ASSERT_FATAL(req != NULL); 775 776 /* TEST CASE: No persistent file, register with PTPL enabled will fail */ 777 g_ns.ptpl_file = NULL; 778 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 779 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 780 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 781 SPDK_CU_ASSERT_FATAL(update_sgroup == false); 782 SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS); 783 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 784 SPDK_CU_ASSERT_FATAL(reg == NULL); 785 786 /* TEST CASE: Enable PTPL */ 787 g_ns.ptpl_file = "/var/log/Ns1PR.cfg"; 788 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 789 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 790 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 791 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 792 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 793 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 794 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 795 SPDK_CU_ASSERT_FATAL(reg != NULL); 796 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 797 /* Load reservation information from configuration file */ 798 memset(&info, 0, sizeof(info)); 799 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 800 SPDK_CU_ASSERT_FATAL(rc == 0); 801 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 802 803 /* TEST CASE: Disable PTPL */ 804 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 805 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 806 SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1); 807 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 808 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 809 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 810 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false); 811 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 812 SPDK_CU_ASSERT_FATAL(rc < 0); 813 unlink(g_ns.ptpl_file); 814 815 ut_reservation_free_req(req); 816 ut_reservation_deinit(); 817 } 818 819 static void 820 test_reservation_acquire_preempt_1(void) 821 { 822 struct spdk_nvmf_request *req; 823 struct spdk_nvme_cpl *rsp; 824 struct spdk_nvmf_registrant *reg; 825 uint32_t gen; 826 827 ut_reservation_init(); 828 829 req = ut_reservation_build_req(16); 830 rsp = &req->rsp->nvme_cpl; 831 SPDK_CU_ASSERT_FATAL(req != NULL); 832 833 ut_reservation_build_registrants(); 834 835 gen = g_ns.gen; 836 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with 837 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE. 838 */ 839 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 840 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 841 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 842 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 843 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 844 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 845 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1); 846 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 847 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 848 849 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A, 850 * g_ctrl1_A registrant is unregistred. 851 */ 852 gen = g_ns.gen; 853 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 854 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1); 855 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 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 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 860 SPDK_CU_ASSERT_FATAL(reg != NULL); 861 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 862 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 863 SPDK_CU_ASSERT_FATAL(reg != NULL); 864 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 865 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 866 867 /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B 868 * with valid key and PRKEY set to 0, all registrants other the host that issued 869 * the command are unregistered. 870 */ 871 gen = g_ns.gen; 872 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 873 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0); 874 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 875 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 876 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 877 SPDK_CU_ASSERT_FATAL(reg == NULL); 878 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 879 SPDK_CU_ASSERT_FATAL(reg == NULL); 880 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 881 SPDK_CU_ASSERT_FATAL(reg != NULL); 882 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 883 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 884 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 885 886 ut_reservation_free_req(req); 887 ut_reservation_deinit(); 888 } 889 890 static void 891 test_reservation_acquire_release_with_ptpl(void) 892 { 893 struct spdk_nvmf_request *req; 894 struct spdk_nvme_cpl *rsp; 895 struct spdk_nvmf_registrant *reg; 896 bool update_sgroup = false; 897 struct spdk_uuid holder_uuid; 898 int rc; 899 struct spdk_nvmf_reservation_info info; 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 /* TEST CASE: Enable PTPL */ 908 g_ns.ptpl_file = "/var/log/Ns1PR.cfg"; 909 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 910 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 911 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 912 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 913 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 914 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 915 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 916 SPDK_CU_ASSERT_FATAL(reg != NULL); 917 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 918 /* Load reservation information from configuration file */ 919 memset(&info, 0, sizeof(info)); 920 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 921 SPDK_CU_ASSERT_FATAL(rc == 0); 922 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 923 924 /* TEST CASE: Acquire the reservation */ 925 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 926 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 927 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 928 update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 929 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 930 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 931 memset(&info, 0, sizeof(info)); 932 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 933 SPDK_CU_ASSERT_FATAL(rc == 0); 934 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 935 SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 936 SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1); 937 spdk_uuid_parse(&holder_uuid, info.holder_uuid); 938 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid)); 939 940 /* TEST CASE: Release the reservation */ 941 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 942 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 943 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1); 944 update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req); 945 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 946 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 947 memset(&info, 0, sizeof(info)); 948 rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 949 SPDK_CU_ASSERT_FATAL(rc == 0); 950 SPDK_CU_ASSERT_FATAL(info.rtype == 0); 951 SPDK_CU_ASSERT_FATAL(info.crkey == 0); 952 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 953 unlink(g_ns.ptpl_file); 954 955 ut_reservation_free_req(req); 956 ut_reservation_deinit(); 957 } 958 959 static void 960 test_reservation_release(void) 961 { 962 struct spdk_nvmf_request *req; 963 struct spdk_nvme_cpl *rsp; 964 struct spdk_nvmf_registrant *reg; 965 966 ut_reservation_init(); 967 968 req = ut_reservation_build_req(16); 969 rsp = &req->rsp->nvme_cpl; 970 SPDK_CU_ASSERT_FATAL(req != NULL); 971 972 ut_reservation_build_registrants(); 973 974 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with 975 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS 976 */ 977 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 978 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0); 979 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 980 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 981 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 982 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 983 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 984 985 /* Test Case: Host B release the reservation */ 986 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 987 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1); 988 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 989 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 990 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 991 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 992 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 993 994 /* Test Case: Host C clear the registrants */ 995 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 996 0, 0xc1); 997 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req); 998 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 999 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 1000 SPDK_CU_ASSERT_FATAL(reg == NULL); 1001 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 1002 SPDK_CU_ASSERT_FATAL(reg == NULL); 1003 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 1004 SPDK_CU_ASSERT_FATAL(reg == NULL); 1005 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 1006 SPDK_CU_ASSERT_FATAL(reg == NULL); 1007 1008 ut_reservation_free_req(req); 1009 ut_reservation_deinit(); 1010 } 1011 1012 void 1013 spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, 1014 struct spdk_nvmf_ns *ns, 1015 enum spdk_nvme_reservation_notification_log_page_type type) 1016 { 1017 ctrlr->num_avail_log_pages++; 1018 } 1019 1020 static void 1021 test_reservation_unregister_notification(void) 1022 { 1023 struct spdk_nvmf_request *req; 1024 struct spdk_nvme_cpl *rsp; 1025 1026 ut_reservation_init(); 1027 1028 req = ut_reservation_build_req(16); 1029 SPDK_CU_ASSERT_FATAL(req != NULL); 1030 rsp = &req->rsp->nvme_cpl; 1031 1032 ut_reservation_build_registrants(); 1033 1034 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1035 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1036 */ 1037 rsp->status.sc = 0xff; 1038 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1039 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1040 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1041 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1042 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1043 1044 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration. 1045 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for 1046 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY 1047 * type. 1048 */ 1049 rsp->status.sc = 0xff; 1050 g_ctrlr1_A.num_avail_log_pages = 0; 1051 g_ctrlr2_A.num_avail_log_pages = 0; 1052 g_ctrlr_B.num_avail_log_pages = 5; 1053 g_ctrlr_C.num_avail_log_pages = 0; 1054 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 1055 0, 0, 0xb1, 0); 1056 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 1057 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1058 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1059 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1060 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1061 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1062 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1063 1064 ut_reservation_free_req(req); 1065 ut_reservation_deinit(); 1066 } 1067 1068 static void 1069 test_reservation_release_notification(void) 1070 { 1071 struct spdk_nvmf_request *req; 1072 struct spdk_nvme_cpl *rsp; 1073 1074 ut_reservation_init(); 1075 1076 req = ut_reservation_build_req(16); 1077 SPDK_CU_ASSERT_FATAL(req != NULL); 1078 rsp = &req->rsp->nvme_cpl; 1079 1080 ut_reservation_build_registrants(); 1081 1082 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1083 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1084 */ 1085 rsp->status.sc = 0xff; 1086 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1087 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1088 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1089 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1090 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1091 1092 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1093 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1094 */ 1095 rsp->status.sc = 0xff; 1096 g_ctrlr1_A.num_avail_log_pages = 0; 1097 g_ctrlr2_A.num_avail_log_pages = 0; 1098 g_ctrlr_B.num_avail_log_pages = 5; 1099 g_ctrlr_C.num_avail_log_pages = 0; 1100 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1101 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1); 1102 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1103 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1104 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1105 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1106 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1107 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1108 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1109 1110 ut_reservation_free_req(req); 1111 ut_reservation_deinit(); 1112 } 1113 1114 static void 1115 test_reservation_release_notification_write_exclusive(void) 1116 { 1117 struct spdk_nvmf_request *req; 1118 struct spdk_nvme_cpl *rsp; 1119 1120 ut_reservation_init(); 1121 1122 req = ut_reservation_build_req(16); 1123 SPDK_CU_ASSERT_FATAL(req != NULL); 1124 rsp = &req->rsp->nvme_cpl; 1125 1126 ut_reservation_build_registrants(); 1127 1128 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1129 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 1130 */ 1131 rsp->status.sc = 0xff; 1132 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1133 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0); 1134 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1135 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1136 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 1137 1138 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1139 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 1140 * no reservation notification occurs. 1141 */ 1142 rsp->status.sc = 0xff; 1143 g_ctrlr1_A.num_avail_log_pages = 5; 1144 g_ctrlr2_A.num_avail_log_pages = 5; 1145 g_ctrlr_B.num_avail_log_pages = 5; 1146 g_ctrlr_C.num_avail_log_pages = 5; 1147 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1148 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1); 1149 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1150 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1151 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1152 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages); 1153 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages); 1154 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1155 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1156 1157 ut_reservation_free_req(req); 1158 ut_reservation_deinit(); 1159 } 1160 1161 static void 1162 test_reservation_clear_notification(void) 1163 { 1164 struct spdk_nvmf_request *req; 1165 struct spdk_nvme_cpl *rsp; 1166 1167 ut_reservation_init(); 1168 1169 req = ut_reservation_build_req(16); 1170 SPDK_CU_ASSERT_FATAL(req != NULL); 1171 rsp = &req->rsp->nvme_cpl; 1172 1173 ut_reservation_build_registrants(); 1174 1175 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1176 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1177 */ 1178 rsp->status.sc = 0xff; 1179 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1180 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1181 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1182 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1183 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1184 1185 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation. 1186 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1187 */ 1188 rsp->status.sc = 0xff; 1189 g_ctrlr1_A.num_avail_log_pages = 0; 1190 g_ctrlr2_A.num_avail_log_pages = 0; 1191 g_ctrlr_B.num_avail_log_pages = 5; 1192 g_ctrlr_C.num_avail_log_pages = 0; 1193 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1194 0, 0xb1); 1195 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1196 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1197 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1198 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1199 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1200 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1201 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1202 1203 ut_reservation_free_req(req); 1204 ut_reservation_deinit(); 1205 } 1206 1207 static void 1208 test_reservation_preempt_notification(void) 1209 { 1210 struct spdk_nvmf_request *req; 1211 struct spdk_nvme_cpl *rsp; 1212 1213 ut_reservation_init(); 1214 1215 req = ut_reservation_build_req(16); 1216 SPDK_CU_ASSERT_FATAL(req != NULL); 1217 rsp = &req->rsp->nvme_cpl; 1218 1219 ut_reservation_build_registrants(); 1220 1221 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1222 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1223 */ 1224 rsp->status.sc = 0xff; 1225 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1226 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1227 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1228 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1229 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1230 1231 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B, 1232 * g_ctrlr_B registrant is unregistred, and reservation is preempted. 1233 * Registration Preempted notification sends to g_ctrlr_B. 1234 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A. 1235 */ 1236 rsp->status.sc = 0xff; 1237 g_ctrlr1_A.num_avail_log_pages = 0; 1238 g_ctrlr2_A.num_avail_log_pages = 0; 1239 g_ctrlr_B.num_avail_log_pages = 0; 1240 g_ctrlr_C.num_avail_log_pages = 5; 1241 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 1242 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1); 1243 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 1244 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1245 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1246 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1247 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1248 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages); 1249 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1250 1251 ut_reservation_free_req(req); 1252 ut_reservation_deinit(); 1253 } 1254 1255 int main(int argc, char **argv) 1256 { 1257 CU_pSuite suite = NULL; 1258 unsigned int num_failures; 1259 1260 if (CU_initialize_registry() != CUE_SUCCESS) { 1261 return CU_get_error(); 1262 } 1263 1264 suite = CU_add_suite("nvmf", NULL, NULL); 1265 if (suite == NULL) { 1266 CU_cleanup_registry(); 1267 return CU_get_error(); 1268 } 1269 1270 if ( 1271 CU_add_test(suite, "create_subsystem", nvmf_test_create_subsystem) == NULL || 1272 CU_add_test(suite, "nvmf_subsystem_add_ns", test_spdk_nvmf_subsystem_add_ns) == NULL || 1273 CU_add_test(suite, "nvmf_subsystem_set_sn", test_spdk_nvmf_subsystem_set_sn) == NULL || 1274 CU_add_test(suite, "reservation_register", test_reservation_register) == NULL || 1275 CU_add_test(suite, "reservation_register_with_ptpl", test_reservation_register_with_ptpl) == NULL || 1276 CU_add_test(suite, "reservation_acquire_preempt_1", test_reservation_acquire_preempt_1) == NULL || 1277 CU_add_test(suite, "reservation_acquire_release_with_ptpl", 1278 test_reservation_acquire_release_with_ptpl) == NULL || 1279 CU_add_test(suite, "reservation_release", test_reservation_release) == NULL || 1280 CU_add_test(suite, "reservation_unregister_notification", 1281 test_reservation_unregister_notification) == NULL || 1282 CU_add_test(suite, "reservation_release_notification", 1283 test_reservation_release_notification) == NULL || 1284 CU_add_test(suite, "reservation_release_notification_write_exclusive", 1285 test_reservation_release_notification_write_exclusive) == NULL || 1286 CU_add_test(suite, "reservation_clear_notification", test_reservation_clear_notification) == NULL || 1287 CU_add_test(suite, "reservation_preempt_notification", 1288 test_reservation_preempt_notification) == NULL 1289 ) { 1290 CU_cleanup_registry(); 1291 return CU_get_error(); 1292 } 1293 1294 allocate_threads(1); 1295 set_thread(0); 1296 1297 CU_basic_set_mode(CU_BRM_VERBOSE); 1298 CU_basic_run_tests(); 1299 num_failures = CU_get_number_of_failures(); 1300 CU_cleanup_registry(); 1301 1302 free_threads(); 1303 1304 return num_failures; 1305 } 1306