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