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