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