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