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 static void 467 ut_reservation_init(void) 468 { 469 470 TAILQ_INIT(&g_subsystem.ctrlrs); 471 472 memset(&g_ns, 0, sizeof(g_ns)); 473 TAILQ_INIT(&g_ns.registrants); 474 g_ns.subsystem = &g_subsystem; 475 476 /* Host A has two controllers */ 477 spdk_uuid_generate(&g_ctrlr1_A.hostid); 478 TAILQ_INIT(&g_ctrlr1_A.log_head); 479 g_ctrlr1_A.subsys = &g_subsystem; 480 g_ctrlr1_A.num_avail_log_pages = 0; 481 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link); 482 spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); 483 TAILQ_INIT(&g_ctrlr2_A.log_head); 484 g_ctrlr2_A.subsys = &g_subsystem; 485 g_ctrlr2_A.num_avail_log_pages = 0; 486 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link); 487 488 /* Host B has 1 controller */ 489 spdk_uuid_generate(&g_ctrlr_B.hostid); 490 TAILQ_INIT(&g_ctrlr_B.log_head); 491 g_ctrlr_B.subsys = &g_subsystem; 492 g_ctrlr_B.num_avail_log_pages = 0; 493 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link); 494 495 /* Host C has 1 controller */ 496 spdk_uuid_generate(&g_ctrlr_C.hostid); 497 TAILQ_INIT(&g_ctrlr_C.log_head); 498 g_ctrlr_C.subsys = &g_subsystem; 499 g_ctrlr_C.num_avail_log_pages = 0; 500 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link); 501 } 502 503 static void 504 ut_reservation_deinit(void) 505 { 506 struct spdk_nvmf_registrant *reg, *tmp; 507 struct spdk_nvmf_reservation_log *log, *log_tmp; 508 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 509 510 TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) { 511 TAILQ_REMOVE(&g_ns.registrants, reg, link); 512 free(reg); 513 } 514 TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) { 515 TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link); 516 free(log); 517 } 518 g_ctrlr1_A.num_avail_log_pages = 0; 519 TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) { 520 TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link); 521 free(log); 522 } 523 g_ctrlr2_A.num_avail_log_pages = 0; 524 TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) { 525 TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link); 526 free(log); 527 } 528 g_ctrlr_B.num_avail_log_pages = 0; 529 TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) { 530 TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link); 531 free(log); 532 } 533 g_ctrlr_C.num_avail_log_pages = 0; 534 535 TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) { 536 TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link); 537 } 538 } 539 540 static struct spdk_nvmf_request * 541 ut_reservation_build_req(uint32_t length) 542 { 543 struct spdk_nvmf_request *req; 544 545 req = calloc(1, sizeof(*req)); 546 assert(req != NULL); 547 548 req->data = calloc(1, length); 549 assert(req->data != NULL); 550 req->length = length; 551 552 req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg)); 553 assert(req->cmd != NULL); 554 555 req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg)); 556 assert(req->rsp != NULL); 557 558 return req; 559 } 560 561 static void 562 ut_reservation_free_req(struct spdk_nvmf_request *req) 563 { 564 free(req->cmd); 565 free(req->rsp); 566 free(req->data); 567 free(req); 568 } 569 570 static void 571 ut_reservation_build_register_request(struct spdk_nvmf_request *req, 572 uint8_t rrega, uint8_t iekey, 573 uint8_t cptpl, uint64_t crkey, 574 uint64_t nrkey) 575 { 576 uint32_t cdw10; 577 struct spdk_nvme_reservation_register_data key; 578 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 579 580 cdw10 = ((cptpl << 30) | (iekey << 3) | rrega); 581 key.crkey = crkey; 582 key.nrkey = nrkey; 583 cmd->cdw10 = cdw10; 584 memcpy(req->data, &key, sizeof(key)); 585 } 586 587 static void 588 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req, 589 uint8_t racqa, uint8_t iekey, 590 uint8_t rtype, uint64_t crkey, 591 uint64_t prkey) 592 { 593 uint32_t cdw10; 594 struct spdk_nvme_reservation_acquire_data key; 595 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 596 597 cdw10 = ((rtype << 8) | (iekey << 3) | racqa); 598 key.crkey = crkey; 599 key.prkey = prkey; 600 cmd->cdw10 = cdw10; 601 memcpy(req->data, &key, sizeof(key)); 602 } 603 604 static void 605 ut_reservation_build_release_request(struct spdk_nvmf_request *req, 606 uint8_t rrela, uint8_t iekey, 607 uint8_t rtype, uint64_t crkey) 608 { 609 uint32_t cdw10; 610 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 611 612 cdw10 = ((rtype << 8) | (iekey << 3) | rrela); 613 cmd->cdw10 = cdw10; 614 memcpy(req->data, &crkey, sizeof(crkey)); 615 } 616 617 /* 618 * Construct four registrants for other test cases. 619 * 620 * g_ctrlr1_A register with key 0xa1. 621 * g_ctrlr2_A register with key 0xa1. 622 * g_ctrlr_B register with key 0xb1. 623 * g_ctrlr_C register with key 0xc1. 624 * */ 625 static void 626 ut_reservation_build_registrants(void) 627 { 628 struct spdk_nvmf_request *req; 629 struct spdk_nvme_cpl *rsp; 630 struct spdk_nvmf_registrant *reg; 631 uint32_t gen; 632 633 req = ut_reservation_build_req(16); 634 rsp = &req->rsp->nvme_cpl; 635 SPDK_CU_ASSERT_FATAL(req != NULL); 636 gen = g_ns.gen; 637 638 /* TEST CASE: g_ctrlr1_A register with a new key */ 639 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 640 0, 0, 0, 0xa1); 641 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 642 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 643 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 644 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1); 645 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1); 646 647 /* TEST CASE: g_ctrlr2_A register with a new key, because it has same 648 * Host Identifier with g_ctrlr1_A, so the register key should same. 649 */ 650 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 651 0, 0, 0, 0xa2); 652 nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req); 653 /* Reservation conflict for other key than 0xa1 */ 654 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 655 656 /* g_ctrlr_B register with a new key */ 657 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 658 0, 0, 0, 0xb1); 659 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 660 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 661 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 662 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1); 663 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2); 664 665 /* g_ctrlr_C register with a new key */ 666 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 667 0, 0, 0, 0xc1); 668 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 669 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 670 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 671 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1); 672 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3); 673 674 ut_reservation_free_req(req); 675 } 676 677 static void 678 test_reservation_register(void) 679 { 680 struct spdk_nvmf_request *req; 681 struct spdk_nvme_cpl *rsp; 682 struct spdk_nvmf_registrant *reg; 683 uint32_t gen; 684 685 ut_reservation_init(); 686 687 req = ut_reservation_build_req(16); 688 rsp = &req->rsp->nvme_cpl; 689 SPDK_CU_ASSERT_FATAL(req != NULL); 690 691 ut_reservation_build_registrants(); 692 693 /* TEST CASE: Replace g_ctrlr1_A with a new key */ 694 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 695 0, 0, 0xa1, 0xa11); 696 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 697 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 698 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 699 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11); 700 701 /* TEST CASE: Host A with g_ctrlr1_A get reservation with 702 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 703 */ 704 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 705 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0); 706 gen = g_ns.gen; 707 nvmf_ns_reservation_acquire(&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(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 711 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11); 712 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 713 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 714 715 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */ 716 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 717 1, 0, 0, 0); 718 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 719 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 720 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 721 SPDK_CU_ASSERT_FATAL(reg == NULL); 722 723 /* TEST CASE: g_ctrlr_B unregister with correct key */ 724 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 725 0, 0, 0xb1, 0); 726 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 727 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 728 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 729 SPDK_CU_ASSERT_FATAL(reg == NULL); 730 731 /* TEST CASE: g_ctrlr1_A unregister with correct key, 732 * reservation should be removed as well. 733 */ 734 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 735 0, 0, 0xa11, 0); 736 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 737 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 738 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 739 SPDK_CU_ASSERT_FATAL(reg == NULL); 740 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 741 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 742 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 743 744 ut_reservation_free_req(req); 745 ut_reservation_deinit(); 746 } 747 748 static void 749 test_reservation_acquire_preempt_1(void) 750 { 751 struct spdk_nvmf_request *req; 752 struct spdk_nvme_cpl *rsp; 753 struct spdk_nvmf_registrant *reg; 754 uint32_t gen; 755 756 ut_reservation_init(); 757 758 req = ut_reservation_build_req(16); 759 rsp = &req->rsp->nvme_cpl; 760 SPDK_CU_ASSERT_FATAL(req != NULL); 761 762 ut_reservation_build_registrants(); 763 764 gen = g_ns.gen; 765 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with 766 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE. 767 */ 768 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 769 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 770 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 771 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 772 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 773 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 774 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1); 775 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 776 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 777 778 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A, 779 * g_ctrl1_A registrant is unregistred. 780 */ 781 gen = g_ns.gen; 782 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 783 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1); 784 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 785 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 786 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 787 SPDK_CU_ASSERT_FATAL(reg == NULL); 788 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 789 SPDK_CU_ASSERT_FATAL(reg != NULL); 790 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 791 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 792 SPDK_CU_ASSERT_FATAL(reg != NULL); 793 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 794 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 795 796 /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B 797 * with valid key and PRKEY set to 0, all registrants other the host that issued 798 * the command are unregistered. 799 */ 800 gen = g_ns.gen; 801 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 802 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0); 803 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 804 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 805 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 806 SPDK_CU_ASSERT_FATAL(reg == NULL); 807 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 808 SPDK_CU_ASSERT_FATAL(reg == NULL); 809 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 810 SPDK_CU_ASSERT_FATAL(reg != NULL); 811 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 812 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 813 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 814 815 ut_reservation_free_req(req); 816 ut_reservation_deinit(); 817 } 818 819 static void 820 test_reservation_release(void) 821 { 822 struct spdk_nvmf_request *req; 823 struct spdk_nvme_cpl *rsp; 824 struct spdk_nvmf_registrant *reg; 825 826 ut_reservation_init(); 827 828 req = ut_reservation_build_req(16); 829 rsp = &req->rsp->nvme_cpl; 830 SPDK_CU_ASSERT_FATAL(req != NULL); 831 832 ut_reservation_build_registrants(); 833 834 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with 835 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS 836 */ 837 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 838 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0); 839 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 840 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 841 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 842 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 843 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 844 845 /* Test Case: Host B release the reservation */ 846 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 847 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1); 848 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 849 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 850 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 851 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 852 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 853 854 /* Test Case: Host C clear the registrants */ 855 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 856 0, 0xc1); 857 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req); 858 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 859 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 860 SPDK_CU_ASSERT_FATAL(reg == NULL); 861 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 862 SPDK_CU_ASSERT_FATAL(reg == NULL); 863 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 864 SPDK_CU_ASSERT_FATAL(reg == NULL); 865 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 866 SPDK_CU_ASSERT_FATAL(reg == NULL); 867 868 ut_reservation_free_req(req); 869 ut_reservation_deinit(); 870 } 871 872 void 873 spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, 874 struct spdk_nvmf_ns *ns, 875 enum spdk_nvme_reservation_notification_log_page_type type) 876 { 877 ctrlr->num_avail_log_pages++; 878 } 879 880 static void 881 test_reservation_unregister_notification(void) 882 { 883 struct spdk_nvmf_request *req; 884 struct spdk_nvme_cpl *rsp; 885 886 ut_reservation_init(); 887 888 req = ut_reservation_build_req(16); 889 SPDK_CU_ASSERT_FATAL(req != NULL); 890 rsp = &req->rsp->nvme_cpl; 891 892 ut_reservation_build_registrants(); 893 894 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 895 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 896 */ 897 rsp->status.sc = 0xff; 898 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 899 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 900 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 901 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 902 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 903 904 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration. 905 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for 906 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY 907 * type. 908 */ 909 rsp->status.sc = 0xff; 910 g_ctrlr1_A.num_avail_log_pages = 0; 911 g_ctrlr2_A.num_avail_log_pages = 0; 912 g_ctrlr_B.num_avail_log_pages = 5; 913 g_ctrlr_C.num_avail_log_pages = 0; 914 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 915 0, 0, 0xb1, 0); 916 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 917 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 918 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 919 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 920 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 921 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 922 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 923 924 ut_reservation_free_req(req); 925 ut_reservation_deinit(); 926 } 927 928 static void 929 test_reservation_release_notification(void) 930 { 931 struct spdk_nvmf_request *req; 932 struct spdk_nvme_cpl *rsp; 933 934 ut_reservation_init(); 935 936 req = ut_reservation_build_req(16); 937 SPDK_CU_ASSERT_FATAL(req != NULL); 938 rsp = &req->rsp->nvme_cpl; 939 940 ut_reservation_build_registrants(); 941 942 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 943 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 944 */ 945 rsp->status.sc = 0xff; 946 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 947 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 948 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 949 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 950 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 951 952 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 953 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 954 */ 955 rsp->status.sc = 0xff; 956 g_ctrlr1_A.num_avail_log_pages = 0; 957 g_ctrlr2_A.num_avail_log_pages = 0; 958 g_ctrlr_B.num_avail_log_pages = 5; 959 g_ctrlr_C.num_avail_log_pages = 0; 960 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 961 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1); 962 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 963 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 964 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 965 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 966 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 967 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 968 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 969 970 ut_reservation_free_req(req); 971 ut_reservation_deinit(); 972 } 973 974 static void 975 test_reservation_release_notification_write_exclusive(void) 976 { 977 struct spdk_nvmf_request *req; 978 struct spdk_nvme_cpl *rsp; 979 980 ut_reservation_init(); 981 982 req = ut_reservation_build_req(16); 983 SPDK_CU_ASSERT_FATAL(req != NULL); 984 rsp = &req->rsp->nvme_cpl; 985 986 ut_reservation_build_registrants(); 987 988 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 989 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 990 */ 991 rsp->status.sc = 0xff; 992 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 993 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0); 994 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 995 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 996 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 997 998 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 999 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 1000 * no reservation notification occurs. 1001 */ 1002 rsp->status.sc = 0xff; 1003 g_ctrlr1_A.num_avail_log_pages = 5; 1004 g_ctrlr2_A.num_avail_log_pages = 5; 1005 g_ctrlr_B.num_avail_log_pages = 5; 1006 g_ctrlr_C.num_avail_log_pages = 5; 1007 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1008 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1); 1009 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1010 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1011 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1012 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages); 1013 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages); 1014 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1015 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1016 1017 ut_reservation_free_req(req); 1018 ut_reservation_deinit(); 1019 } 1020 1021 static void 1022 test_reservation_clear_notification(void) 1023 { 1024 struct spdk_nvmf_request *req; 1025 struct spdk_nvme_cpl *rsp; 1026 1027 ut_reservation_init(); 1028 1029 req = ut_reservation_build_req(16); 1030 SPDK_CU_ASSERT_FATAL(req != NULL); 1031 rsp = &req->rsp->nvme_cpl; 1032 1033 ut_reservation_build_registrants(); 1034 1035 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1036 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1037 */ 1038 rsp->status.sc = 0xff; 1039 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1040 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1041 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1042 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1043 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1044 1045 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation. 1046 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1047 */ 1048 rsp->status.sc = 0xff; 1049 g_ctrlr1_A.num_avail_log_pages = 0; 1050 g_ctrlr2_A.num_avail_log_pages = 0; 1051 g_ctrlr_B.num_avail_log_pages = 5; 1052 g_ctrlr_C.num_avail_log_pages = 0; 1053 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1054 0, 0xb1); 1055 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1056 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1057 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1058 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1059 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1060 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1061 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1062 1063 ut_reservation_free_req(req); 1064 ut_reservation_deinit(); 1065 } 1066 1067 static void 1068 test_reservation_preempt_notification(void) 1069 { 1070 struct spdk_nvmf_request *req; 1071 struct spdk_nvme_cpl *rsp; 1072 1073 ut_reservation_init(); 1074 1075 req = ut_reservation_build_req(16); 1076 SPDK_CU_ASSERT_FATAL(req != NULL); 1077 rsp = &req->rsp->nvme_cpl; 1078 1079 ut_reservation_build_registrants(); 1080 1081 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1082 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1083 */ 1084 rsp->status.sc = 0xff; 1085 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1086 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1087 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1088 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1089 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1090 1091 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B, 1092 * g_ctrlr_B registrant is unregistred, and reservation is preempted. 1093 * Registration Preempted notification sends to g_ctrlr_B. 1094 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A. 1095 */ 1096 rsp->status.sc = 0xff; 1097 g_ctrlr1_A.num_avail_log_pages = 0; 1098 g_ctrlr2_A.num_avail_log_pages = 0; 1099 g_ctrlr_B.num_avail_log_pages = 0; 1100 g_ctrlr_C.num_avail_log_pages = 5; 1101 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 1102 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1); 1103 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 1104 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1105 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1106 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1107 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1108 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages); 1109 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1110 1111 ut_reservation_free_req(req); 1112 ut_reservation_deinit(); 1113 } 1114 1115 int main(int argc, char **argv) 1116 { 1117 CU_pSuite suite = NULL; 1118 unsigned int num_failures; 1119 1120 if (CU_initialize_registry() != CUE_SUCCESS) { 1121 return CU_get_error(); 1122 } 1123 1124 suite = CU_add_suite("nvmf", NULL, NULL); 1125 if (suite == NULL) { 1126 CU_cleanup_registry(); 1127 return CU_get_error(); 1128 } 1129 1130 if ( 1131 CU_add_test(suite, "create_subsystem", nvmf_test_create_subsystem) == NULL || 1132 CU_add_test(suite, "nvmf_subsystem_add_ns", test_spdk_nvmf_subsystem_add_ns) == NULL || 1133 CU_add_test(suite, "nvmf_subsystem_set_sn", test_spdk_nvmf_subsystem_set_sn) == NULL || 1134 CU_add_test(suite, "reservation_register", test_reservation_register) == NULL || 1135 CU_add_test(suite, "reservation_acquire_preempt_1", test_reservation_acquire_preempt_1) == NULL || 1136 CU_add_test(suite, "reservation_release", test_reservation_release) == NULL || 1137 CU_add_test(suite, "reservation_unregister_notification", 1138 test_reservation_unregister_notification) == NULL || 1139 CU_add_test(suite, "reservation_release_notification", 1140 test_reservation_release_notification) == NULL || 1141 CU_add_test(suite, "reservation_release_notification_write_exclusive", 1142 test_reservation_release_notification_write_exclusive) == NULL || 1143 CU_add_test(suite, "reservation_clear_notification", test_reservation_clear_notification) == NULL || 1144 CU_add_test(suite, "reservation_preempt_notification", 1145 test_reservation_preempt_notification) == NULL 1146 ) { 1147 CU_cleanup_registry(); 1148 return CU_get_error(); 1149 } 1150 1151 allocate_threads(1); 1152 set_thread(0); 1153 1154 CU_basic_set_mode(CU_BRM_VERBOSE); 1155 CU_basic_run_tests(); 1156 num_failures = CU_get_number_of_failures(); 1157 CU_cleanup_registry(); 1158 1159 free_threads(); 1160 1161 return num_failures; 1162 } 1163