1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. All rights reserved. 3 * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 8 #include "common/lib/ut_multithread.c" 9 #include "spdk_cunit.h" 10 #include "spdk_internal/mock.h" 11 12 #include "spdk/bdev_module.h" 13 #include "nvmf/subsystem.c" 14 #include <uuid/uuid.h> 15 16 SPDK_LOG_REGISTER_COMPONENT(nvmf) 17 18 DEFINE_STUB(spdk_bdev_module_claim_bdev, 19 int, 20 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 21 struct spdk_bdev_module *module), 0); 22 23 DEFINE_STUB_V(spdk_bdev_module_release_bdev, 24 (struct spdk_bdev *bdev)); 25 26 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, 27 (const struct spdk_bdev *bdev), 512); 28 29 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t, 30 (const struct spdk_bdev *bdev), 0); 31 32 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool, 33 (const struct spdk_bdev *bdev), false); 34 35 DEFINE_STUB(spdk_bdev_io_type_supported, bool, 36 (struct spdk_bdev *bdev, 37 enum spdk_bdev_io_type io_type), false); 38 39 DEFINE_STUB(spdk_nvmf_transport_stop_listen, 40 int, 41 (struct spdk_nvmf_transport *transport, 42 const struct spdk_nvme_transport_id *trid), 0); 43 44 DEFINE_STUB_V(nvmf_update_discovery_log, 45 (struct spdk_nvmf_tgt *tgt, const char *hostnqn)); 46 47 DEFINE_STUB(spdk_nvmf_qpair_disconnect, 48 int, 49 (struct spdk_nvmf_qpair *qpair, 50 nvmf_qpair_disconnect_cb cb_fn, void *ctx), 0); 51 52 DEFINE_STUB(nvmf_transport_find_listener, 53 struct spdk_nvmf_listener *, 54 (struct spdk_nvmf_transport *transport, 55 const struct spdk_nvme_transport_id *trid), NULL); 56 57 DEFINE_STUB(spdk_nvmf_transport_get_first, 58 struct spdk_nvmf_transport *, 59 (struct spdk_nvmf_tgt *tgt), NULL); 60 61 DEFINE_STUB(spdk_nvmf_transport_get_next, 62 struct spdk_nvmf_transport *, 63 (struct spdk_nvmf_transport *transport), NULL); 64 65 DEFINE_STUB(spdk_nvmf_request_complete, 66 int, 67 (struct spdk_nvmf_request *req), 0); 68 69 DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice, 70 int, 71 (struct spdk_nvmf_ctrlr *ctrlr), 0); 72 73 DEFINE_STUB(spdk_nvme_transport_id_trtype_str, 74 const char *, 75 (enum spdk_nvme_transport_type trtype), NULL); 76 77 int 78 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport, 79 const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts) 80 { 81 return 0; 82 } 83 84 void 85 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport, 86 struct spdk_nvme_transport_id *trid, 87 struct spdk_nvmf_discovery_log_page_entry *entry) 88 { 89 entry->trtype = 42; 90 } 91 92 static struct spdk_nvmf_transport g_transport = {}; 93 94 struct spdk_nvmf_transport * 95 spdk_nvmf_transport_create(const char *transport_name, 96 struct spdk_nvmf_transport_opts *tprt_opts) 97 { 98 if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) { 99 return &g_transport; 100 } 101 102 return NULL; 103 } 104 105 struct spdk_nvmf_subsystem * 106 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 107 { 108 return NULL; 109 } 110 111 struct spdk_nvmf_transport * 112 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name) 113 { 114 if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) { 115 return &g_transport; 116 } 117 118 return NULL; 119 } 120 121 int 122 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, 123 struct spdk_nvmf_subsystem *subsystem) 124 { 125 return 0; 126 } 127 128 int 129 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, 130 struct spdk_nvmf_subsystem *subsystem, 131 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 132 { 133 return 0; 134 } 135 136 void 137 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, 138 struct spdk_nvmf_subsystem *subsystem, 139 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 140 { 141 } 142 143 void 144 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group, 145 struct spdk_nvmf_subsystem *subsystem, 146 uint32_t nsid, 147 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 148 { 149 } 150 151 void 152 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group, 153 struct spdk_nvmf_subsystem *subsystem, 154 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 155 { 156 } 157 158 int 159 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str) 160 { 161 if (trtype == NULL || str == NULL) { 162 return -EINVAL; 163 } 164 165 if (strcasecmp(str, "PCIe") == 0) { 166 *trtype = SPDK_NVME_TRANSPORT_PCIE; 167 } else if (strcasecmp(str, "RDMA") == 0) { 168 *trtype = SPDK_NVME_TRANSPORT_RDMA; 169 } else { 170 return -ENOENT; 171 } 172 return 0; 173 } 174 175 int 176 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1, 177 const struct spdk_nvme_transport_id *trid2) 178 { 179 return 0; 180 } 181 182 int32_t 183 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr) 184 { 185 return -1; 186 } 187 188 int32_t 189 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) 190 { 191 return -1; 192 } 193 194 int 195 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr) 196 { 197 return -1; 198 } 199 200 void 201 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr) 202 { 203 } 204 205 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL; 206 static uint32_t g_ns_changed_nsid = 0; 207 void 208 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 209 { 210 g_ns_changed_ctrlr = ctrlr; 211 g_ns_changed_nsid = nsid; 212 } 213 214 static struct spdk_bdev g_bdevs[] = { 215 { .name = "bdev1" }, 216 { .name = "bdev2" }, 217 }; 218 219 struct spdk_bdev_desc { 220 struct spdk_bdev *bdev; 221 }; 222 223 int 224 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb, 225 void *event_ctx, struct spdk_bdev_desc **_desc) 226 { 227 struct spdk_bdev_desc *desc; 228 size_t i; 229 230 for (i = 0; i < sizeof(g_bdevs); i++) { 231 if (strcmp(bdev_name, g_bdevs[i].name) == 0) { 232 233 desc = calloc(1, sizeof(*desc)); 234 SPDK_CU_ASSERT_FATAL(desc != NULL); 235 236 desc->bdev = &g_bdevs[i]; 237 *_desc = desc; 238 return 0; 239 } 240 } 241 242 return -EINVAL; 243 } 244 245 void 246 spdk_bdev_close(struct spdk_bdev_desc *desc) 247 { 248 free(desc); 249 } 250 251 struct spdk_bdev * 252 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc) 253 { 254 return desc->bdev; 255 } 256 257 const char * 258 spdk_bdev_get_name(const struct spdk_bdev *bdev) 259 { 260 return "test"; 261 } 262 263 const struct spdk_uuid * 264 spdk_bdev_get_uuid(const struct spdk_bdev *bdev) 265 { 266 return &bdev->uuid; 267 } 268 269 static void 270 test_spdk_nvmf_subsystem_add_ns(void) 271 { 272 struct spdk_nvmf_tgt tgt = {}; 273 struct spdk_nvmf_subsystem subsystem = { 274 .max_nsid = 1024, 275 .ns = NULL, 276 .tgt = &tgt, 277 }; 278 struct spdk_nvmf_ns_opts ns_opts; 279 uint32_t nsid; 280 int rc; 281 282 subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *)); 283 SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL); 284 subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t)); 285 SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL); 286 287 tgt.max_subsystems = 1024; 288 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 289 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 290 291 /* Request a specific NSID */ 292 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 293 ns_opts.nsid = 5; 294 nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL); 295 CU_ASSERT(nsid == 5); 296 CU_ASSERT(subsystem.max_nsid == 1024); 297 SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL); 298 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]); 299 300 /* Request an NSID that is already in use */ 301 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 302 ns_opts.nsid = 5; 303 nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL); 304 CU_ASSERT(nsid == 0); 305 CU_ASSERT(subsystem.max_nsid == 1024); 306 307 /* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */ 308 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 309 ns_opts.nsid = 0xFFFFFFFF; 310 nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL); 311 CU_ASSERT(nsid == 0); 312 CU_ASSERT(subsystem.max_nsid == 1024); 313 314 rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5); 315 CU_ASSERT(rc == 0); 316 317 free(subsystem.ns); 318 free(subsystem.ana_group); 319 free(tgt.subsystems); 320 } 321 322 static void 323 nvmf_test_create_subsystem(void) 324 { 325 struct spdk_nvmf_tgt tgt = {}; 326 char nqn[256]; 327 struct spdk_nvmf_subsystem *subsystem; 328 int rc; 329 330 tgt.max_subsystems = 1024; 331 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 332 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 333 334 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 335 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 336 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 337 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 338 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 339 CU_ASSERT(rc == 0); 340 341 /* valid name with complex reverse domain */ 342 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1"); 343 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 344 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 345 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 346 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 347 CU_ASSERT(rc == 0); 348 349 /* Valid name discovery controller */ 350 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 351 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 352 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 353 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 354 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 355 CU_ASSERT(rc == 0); 356 357 /* Invalid name, no user supplied string */ 358 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 359 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 360 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 361 362 /* Valid name, only contains top-level domain name */ 363 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1"); 364 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 365 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 366 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 367 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 368 CU_ASSERT(rc == 0); 369 370 /* Invalid name, domain label > 63 characters */ 371 snprintf(nqn, sizeof(nqn), 372 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub"); 373 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 374 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 375 376 /* Invalid name, domain label starts with digit */ 377 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub"); 378 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 379 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 380 381 /* Invalid name, domain label starts with - */ 382 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1"); 383 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 384 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 385 386 /* Invalid name, domain label ends with - */ 387 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1"); 388 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 389 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 390 391 /* Invalid name, domain label with multiple consecutive periods */ 392 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1"); 393 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 394 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 395 396 /* Longest valid name */ 397 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 398 memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn)); 399 nqn[223] = '\0'; 400 CU_ASSERT(strlen(nqn) == 223); 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 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 405 CU_ASSERT(rc == 0); 406 407 /* Invalid name, too long */ 408 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:"); 409 memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn)); 410 nqn[224] = '\0'; 411 CU_ASSERT(strlen(nqn) == 224); 412 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 413 CU_ASSERT(subsystem == NULL); 414 415 /* Valid name using uuid format */ 416 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc"); 417 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 418 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 419 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 420 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 421 CU_ASSERT(rc == 0); 422 423 /* Invalid name user string contains an invalid utf-8 character */ 424 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1"); 425 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 426 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 427 428 /* Valid name with non-ascii but valid utf-8 characters */ 429 snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80"); 430 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 431 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 432 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 433 rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 434 CU_ASSERT(rc == 0); 435 436 /* Invalid uuid (too long) */ 437 snprintf(nqn, sizeof(nqn), 438 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef"); 439 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 440 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 441 442 /* Invalid uuid (dashes placed incorrectly) */ 443 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc"); 444 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 445 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 446 447 /* Invalid uuid (invalid characters in uuid) */ 448 snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc"); 449 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 450 SPDK_CU_ASSERT_FATAL(subsystem == NULL); 451 452 free(tgt.subsystems); 453 } 454 455 static void 456 test_spdk_nvmf_subsystem_set_sn(void) 457 { 458 struct spdk_nvmf_subsystem subsystem = {}; 459 460 /* Basic valid serial number */ 461 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0); 462 CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0); 463 464 /* Exactly 20 characters (valid) */ 465 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0); 466 CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0); 467 468 /* 21 characters (too long, invalid) */ 469 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0); 470 471 /* Non-ASCII characters (invalid) */ 472 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0); 473 } 474 475 /* 476 * Reservation Unit Test Configuration 477 * -------- -------- -------- 478 * | Host A | | Host B | | Host C | 479 * -------- -------- -------- 480 * / \ | | 481 * -------- -------- ------- ------- 482 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C| 483 * -------- -------- ------- ------- 484 * \ \ / / 485 * \ \ / / 486 * \ \ / / 487 * -------------------------------------- 488 * | NAMESPACE 1 | 489 * -------------------------------------- 490 */ 491 static struct spdk_nvmf_subsystem g_subsystem; 492 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; 493 static struct spdk_nvmf_ns g_ns; 494 static struct spdk_bdev g_bdev; 495 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; 496 497 void 498 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr) 499 { 500 } 501 502 static void 503 ut_reservation_init(void) 504 { 505 506 TAILQ_INIT(&g_subsystem.ctrlrs); 507 508 memset(&g_ns, 0, sizeof(g_ns)); 509 TAILQ_INIT(&g_ns.registrants); 510 g_ns.subsystem = &g_subsystem; 511 g_ns.ptpl_file = NULL; 512 g_ns.ptpl_activated = false; 513 spdk_uuid_generate(&g_bdev.uuid); 514 g_ns.bdev = &g_bdev; 515 516 /* Host A has two controllers */ 517 spdk_uuid_generate(&g_ctrlr1_A.hostid); 518 TAILQ_INIT(&g_ctrlr1_A.log_head); 519 g_ctrlr1_A.subsys = &g_subsystem; 520 g_ctrlr1_A.num_avail_log_pages = 0; 521 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link); 522 spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); 523 TAILQ_INIT(&g_ctrlr2_A.log_head); 524 g_ctrlr2_A.subsys = &g_subsystem; 525 g_ctrlr2_A.num_avail_log_pages = 0; 526 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link); 527 528 /* Host B has 1 controller */ 529 spdk_uuid_generate(&g_ctrlr_B.hostid); 530 TAILQ_INIT(&g_ctrlr_B.log_head); 531 g_ctrlr_B.subsys = &g_subsystem; 532 g_ctrlr_B.num_avail_log_pages = 0; 533 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link); 534 535 /* Host C has 1 controller */ 536 spdk_uuid_generate(&g_ctrlr_C.hostid); 537 TAILQ_INIT(&g_ctrlr_C.log_head); 538 g_ctrlr_C.subsys = &g_subsystem; 539 g_ctrlr_C.num_avail_log_pages = 0; 540 TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link); 541 } 542 543 static void 544 ut_reservation_deinit(void) 545 { 546 struct spdk_nvmf_registrant *reg, *tmp; 547 struct spdk_nvmf_reservation_log *log, *log_tmp; 548 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 549 550 TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) { 551 TAILQ_REMOVE(&g_ns.registrants, reg, link); 552 free(reg); 553 } 554 TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) { 555 TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link); 556 free(log); 557 } 558 g_ctrlr1_A.num_avail_log_pages = 0; 559 TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) { 560 TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link); 561 free(log); 562 } 563 g_ctrlr2_A.num_avail_log_pages = 0; 564 TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) { 565 TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link); 566 free(log); 567 } 568 g_ctrlr_B.num_avail_log_pages = 0; 569 TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) { 570 TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link); 571 free(log); 572 } 573 g_ctrlr_C.num_avail_log_pages = 0; 574 575 TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) { 576 TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link); 577 } 578 } 579 580 static struct spdk_nvmf_request * 581 ut_reservation_build_req(uint32_t length) 582 { 583 struct spdk_nvmf_request *req; 584 585 req = calloc(1, sizeof(*req)); 586 assert(req != NULL); 587 588 req->data = calloc(1, length); 589 assert(req->data != NULL); 590 req->length = length; 591 592 req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg)); 593 assert(req->cmd != NULL); 594 595 req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg)); 596 assert(req->rsp != NULL); 597 598 return req; 599 } 600 601 static void 602 ut_reservation_free_req(struct spdk_nvmf_request *req) 603 { 604 free(req->cmd); 605 free(req->rsp); 606 free(req->data); 607 free(req); 608 } 609 610 static void 611 ut_reservation_build_register_request(struct spdk_nvmf_request *req, 612 uint8_t rrega, uint8_t iekey, 613 uint8_t cptpl, uint64_t crkey, 614 uint64_t nrkey) 615 { 616 struct spdk_nvme_reservation_register_data key; 617 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 618 619 key.crkey = crkey; 620 key.nrkey = nrkey; 621 cmd->cdw10 = 0; 622 cmd->cdw10_bits.resv_register.rrega = rrega; 623 cmd->cdw10_bits.resv_register.iekey = iekey; 624 cmd->cdw10_bits.resv_register.cptpl = cptpl; 625 memcpy(req->data, &key, sizeof(key)); 626 } 627 628 static void 629 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req, 630 uint8_t racqa, uint8_t iekey, 631 uint8_t rtype, uint64_t crkey, 632 uint64_t prkey) 633 { 634 struct spdk_nvme_reservation_acquire_data key; 635 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 636 637 key.crkey = crkey; 638 key.prkey = prkey; 639 cmd->cdw10 = 0; 640 cmd->cdw10_bits.resv_acquire.racqa = racqa; 641 cmd->cdw10_bits.resv_acquire.iekey = iekey; 642 cmd->cdw10_bits.resv_acquire.rtype = rtype; 643 memcpy(req->data, &key, sizeof(key)); 644 } 645 646 static void 647 ut_reservation_build_release_request(struct spdk_nvmf_request *req, 648 uint8_t rrela, uint8_t iekey, 649 uint8_t rtype, uint64_t crkey) 650 { 651 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 652 653 cmd->cdw10 = 0; 654 cmd->cdw10_bits.resv_release.rrela = rrela; 655 cmd->cdw10_bits.resv_release.iekey = iekey; 656 cmd->cdw10_bits.resv_release.rtype = rtype; 657 memcpy(req->data, &crkey, sizeof(crkey)); 658 } 659 660 /* 661 * Construct four registrants for other test cases. 662 * 663 * g_ctrlr1_A register with key 0xa1. 664 * g_ctrlr2_A register with key 0xa1. 665 * g_ctrlr_B register with key 0xb1. 666 * g_ctrlr_C register with key 0xc1. 667 * */ 668 static void 669 ut_reservation_build_registrants(void) 670 { 671 struct spdk_nvmf_request *req; 672 struct spdk_nvme_cpl *rsp; 673 struct spdk_nvmf_registrant *reg; 674 uint32_t gen; 675 676 req = ut_reservation_build_req(16); 677 rsp = &req->rsp->nvme_cpl; 678 SPDK_CU_ASSERT_FATAL(req != NULL); 679 gen = g_ns.gen; 680 681 /* TEST CASE: g_ctrlr1_A register with a new key */ 682 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 683 0, 0, 0, 0xa1); 684 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 685 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 686 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 687 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1); 688 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1); 689 690 /* TEST CASE: g_ctrlr2_A register with a new key, because it has same 691 * Host Identifier with g_ctrlr1_A, so the register key should same. 692 */ 693 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 694 0, 0, 0, 0xa2); 695 nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req); 696 /* Reservation conflict for other key than 0xa1 */ 697 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 698 699 /* g_ctrlr_B register with a new key */ 700 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 701 0, 0, 0, 0xb1); 702 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 703 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 704 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 705 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1); 706 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2); 707 708 /* g_ctrlr_C register with a new key */ 709 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 710 0, 0, 0, 0xc1); 711 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 712 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 713 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 714 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1); 715 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3); 716 717 ut_reservation_free_req(req); 718 } 719 720 static void 721 test_reservation_register(void) 722 { 723 struct spdk_nvmf_request *req; 724 struct spdk_nvme_cpl *rsp; 725 struct spdk_nvmf_registrant *reg; 726 uint32_t gen; 727 728 ut_reservation_init(); 729 730 req = ut_reservation_build_req(16); 731 rsp = &req->rsp->nvme_cpl; 732 SPDK_CU_ASSERT_FATAL(req != NULL); 733 734 ut_reservation_build_registrants(); 735 736 /* TEST CASE: Replace g_ctrlr1_A with a new key */ 737 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 738 0, 0, 0xa1, 0xa11); 739 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 740 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 741 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 742 SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11); 743 744 /* TEST CASE: Host A with g_ctrlr1_A get reservation with 745 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 746 */ 747 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 748 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0); 749 gen = g_ns.gen; 750 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 751 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 752 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 753 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 754 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11); 755 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 756 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 757 758 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */ 759 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 760 1, 0, 0, 0); 761 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req); 762 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 763 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 764 SPDK_CU_ASSERT_FATAL(reg == NULL); 765 766 /* TEST CASE: g_ctrlr_B unregister with correct key */ 767 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 768 0, 0, 0xb1, 0); 769 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 770 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 771 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 772 SPDK_CU_ASSERT_FATAL(reg == NULL); 773 774 /* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY disabled */ 775 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 776 0, 0, 0, 0xb1); 777 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 778 SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS); 779 780 /* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY enabled */ 781 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 782 1, 0, 0, 0xb1); 783 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 784 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 785 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 786 SPDK_CU_ASSERT_FATAL(reg != NULL); 787 788 /* TEST CASE: g_ctrlr_B replace new key with IEKEY enabled and wrong crkey */ 789 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY, 790 1, 0, 0xff, 0xb2); 791 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 792 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 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(reg->rkey == 0xb2); 796 797 /* TEST CASE: g_ctrlr1_A unregister with correct key, 798 * reservation should be removed as well. 799 */ 800 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 801 0, 0, 0xa11, 0); 802 nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 803 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 804 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 805 SPDK_CU_ASSERT_FATAL(reg == NULL); 806 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 807 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 808 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 809 810 ut_reservation_free_req(req); 811 ut_reservation_deinit(); 812 } 813 814 static void 815 test_reservation_register_with_ptpl(void) 816 { 817 struct spdk_nvmf_request *req; 818 struct spdk_nvme_cpl *rsp; 819 struct spdk_nvmf_registrant *reg; 820 bool update_sgroup = false; 821 int rc; 822 struct spdk_nvmf_reservation_info info; 823 824 ut_reservation_init(); 825 826 req = ut_reservation_build_req(16); 827 rsp = &req->rsp->nvme_cpl; 828 SPDK_CU_ASSERT_FATAL(req != NULL); 829 830 /* TEST CASE: No persistent file, register with PTPL enabled will fail */ 831 g_ns.ptpl_file = NULL; 832 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 833 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 834 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 835 SPDK_CU_ASSERT_FATAL(update_sgroup == false); 836 SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS); 837 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 838 SPDK_CU_ASSERT_FATAL(reg == NULL); 839 840 /* TEST CASE: Enable PTPL */ 841 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 842 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 843 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 844 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 845 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 846 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 847 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 848 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 849 SPDK_CU_ASSERT_FATAL(reg != NULL); 850 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 851 /* Load reservation information from configuration file */ 852 memset(&info, 0, sizeof(info)); 853 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 854 SPDK_CU_ASSERT_FATAL(rc == 0); 855 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 856 857 /* TEST CASE: Disable PTPL */ 858 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 859 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 860 SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1); 861 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 862 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 863 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 864 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false); 865 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 866 SPDK_CU_ASSERT_FATAL(rc < 0); 867 unlink(g_ns.ptpl_file); 868 869 ut_reservation_free_req(req); 870 ut_reservation_deinit(); 871 } 872 873 static void 874 test_reservation_acquire_preempt_1(void) 875 { 876 struct spdk_nvmf_request *req; 877 struct spdk_nvme_cpl *rsp; 878 struct spdk_nvmf_registrant *reg; 879 uint32_t gen; 880 881 ut_reservation_init(); 882 883 req = ut_reservation_build_req(16); 884 rsp = &req->rsp->nvme_cpl; 885 SPDK_CU_ASSERT_FATAL(req != NULL); 886 887 ut_reservation_build_registrants(); 888 889 gen = g_ns.gen; 890 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with 891 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE. 892 */ 893 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 894 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 895 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 896 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 897 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 898 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 899 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1); 900 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 901 SPDK_CU_ASSERT_FATAL(g_ns.gen == gen); 902 903 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A, 904 * g_ctrl1_A registrant is unregistered. 905 */ 906 gen = g_ns.gen; 907 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 908 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1); 909 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 910 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 911 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 912 SPDK_CU_ASSERT_FATAL(reg == NULL); 913 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 914 SPDK_CU_ASSERT_FATAL(reg != NULL); 915 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 916 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 917 SPDK_CU_ASSERT_FATAL(reg != NULL); 918 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 919 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 920 921 /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B 922 * with valid key and PRKEY set to 0, all registrants other the host that issued 923 * the command are unregistered. 924 */ 925 gen = g_ns.gen; 926 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 927 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0); 928 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 929 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 930 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 931 SPDK_CU_ASSERT_FATAL(reg == NULL); 932 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 933 SPDK_CU_ASSERT_FATAL(reg == NULL); 934 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 935 SPDK_CU_ASSERT_FATAL(reg != NULL); 936 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 937 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 938 SPDK_CU_ASSERT_FATAL(g_ns.gen > gen); 939 940 ut_reservation_free_req(req); 941 ut_reservation_deinit(); 942 } 943 944 static void 945 test_reservation_acquire_release_with_ptpl(void) 946 { 947 struct spdk_nvmf_request *req; 948 struct spdk_nvme_cpl *rsp; 949 struct spdk_nvmf_registrant *reg; 950 bool update_sgroup = false; 951 struct spdk_uuid holder_uuid; 952 int rc; 953 struct spdk_nvmf_reservation_info info; 954 955 ut_reservation_init(); 956 957 req = ut_reservation_build_req(16); 958 rsp = &req->rsp->nvme_cpl; 959 SPDK_CU_ASSERT_FATAL(req != NULL); 960 961 /* TEST CASE: Enable PTPL */ 962 g_ns.ptpl_file = "/tmp/Ns1PR.cfg"; 963 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0, 964 SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1); 965 update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req); 966 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 967 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 968 SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true); 969 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 970 SPDK_CU_ASSERT_FATAL(reg != NULL); 971 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid)); 972 /* Load reservation information from configuration file */ 973 memset(&info, 0, sizeof(info)); 974 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 975 SPDK_CU_ASSERT_FATAL(rc == 0); 976 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 977 978 /* TEST CASE: Acquire the reservation */ 979 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 980 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 981 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0); 982 update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 983 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 984 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 985 memset(&info, 0, sizeof(info)); 986 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 987 SPDK_CU_ASSERT_FATAL(rc == 0); 988 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 989 SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 990 SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1); 991 spdk_uuid_parse(&holder_uuid, info.holder_uuid); 992 SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid)); 993 994 /* TEST CASE: Release the reservation */ 995 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 996 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 997 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1); 998 update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req); 999 SPDK_CU_ASSERT_FATAL(update_sgroup == true); 1000 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1001 memset(&info, 0, sizeof(info)); 1002 rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info); 1003 SPDK_CU_ASSERT_FATAL(rc == 0); 1004 SPDK_CU_ASSERT_FATAL(info.rtype == 0); 1005 SPDK_CU_ASSERT_FATAL(info.crkey == 0); 1006 SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true); 1007 unlink(g_ns.ptpl_file); 1008 1009 ut_reservation_free_req(req); 1010 ut_reservation_deinit(); 1011 } 1012 1013 static void 1014 test_reservation_release(void) 1015 { 1016 struct spdk_nvmf_request *req; 1017 struct spdk_nvme_cpl *rsp; 1018 struct spdk_nvmf_registrant *reg; 1019 1020 ut_reservation_init(); 1021 1022 req = ut_reservation_build_req(16); 1023 rsp = &req->rsp->nvme_cpl; 1024 SPDK_CU_ASSERT_FATAL(req != NULL); 1025 1026 ut_reservation_build_registrants(); 1027 1028 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with 1029 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS 1030 */ 1031 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1032 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0); 1033 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req); 1034 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1035 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 1036 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1037 SPDK_CU_ASSERT_FATAL(g_ns.holder == reg); 1038 1039 /* Test Case: Host B release the reservation */ 1040 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1041 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1); 1042 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1043 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1044 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1045 SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0); 1046 SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL); 1047 1048 /* Test Case: Host C clear the registrants */ 1049 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1050 0, 0xc1); 1051 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req); 1052 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1053 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid); 1054 SPDK_CU_ASSERT_FATAL(reg == NULL); 1055 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid); 1056 SPDK_CU_ASSERT_FATAL(reg == NULL); 1057 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid); 1058 SPDK_CU_ASSERT_FATAL(reg == NULL); 1059 reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid); 1060 SPDK_CU_ASSERT_FATAL(reg == NULL); 1061 1062 ut_reservation_free_req(req); 1063 ut_reservation_deinit(); 1064 } 1065 1066 void 1067 nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, 1068 struct spdk_nvmf_ns *ns, 1069 enum spdk_nvme_reservation_notification_log_page_type type) 1070 { 1071 ctrlr->num_avail_log_pages++; 1072 } 1073 1074 static void 1075 test_reservation_unregister_notification(void) 1076 { 1077 struct spdk_nvmf_request *req; 1078 struct spdk_nvme_cpl *rsp; 1079 1080 ut_reservation_init(); 1081 1082 req = ut_reservation_build_req(16); 1083 SPDK_CU_ASSERT_FATAL(req != NULL); 1084 rsp = &req->rsp->nvme_cpl; 1085 1086 ut_reservation_build_registrants(); 1087 1088 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1089 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1090 */ 1091 rsp->status.sc = 0xff; 1092 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1093 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1094 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1095 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1096 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1097 1098 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration. 1099 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for 1100 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY 1101 * type. 1102 */ 1103 rsp->status.sc = 0xff; 1104 g_ctrlr1_A.num_avail_log_pages = 0; 1105 g_ctrlr2_A.num_avail_log_pages = 0; 1106 g_ctrlr_B.num_avail_log_pages = 5; 1107 g_ctrlr_C.num_avail_log_pages = 0; 1108 ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY, 1109 0, 0, 0xb1, 0); 1110 nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req); 1111 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1112 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1113 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1114 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1115 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1116 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1117 1118 ut_reservation_free_req(req); 1119 ut_reservation_deinit(); 1120 } 1121 1122 static void 1123 test_reservation_release_notification(void) 1124 { 1125 struct spdk_nvmf_request *req; 1126 struct spdk_nvme_cpl *rsp; 1127 1128 ut_reservation_init(); 1129 1130 req = ut_reservation_build_req(16); 1131 SPDK_CU_ASSERT_FATAL(req != NULL); 1132 rsp = &req->rsp->nvme_cpl; 1133 1134 ut_reservation_build_registrants(); 1135 1136 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1137 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1138 */ 1139 rsp->status.sc = 0xff; 1140 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1141 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1142 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1143 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1144 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1145 1146 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1147 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1148 */ 1149 rsp->status.sc = 0xff; 1150 g_ctrlr1_A.num_avail_log_pages = 0; 1151 g_ctrlr2_A.num_avail_log_pages = 0; 1152 g_ctrlr_B.num_avail_log_pages = 5; 1153 g_ctrlr_C.num_avail_log_pages = 0; 1154 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1155 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1); 1156 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1157 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1158 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1159 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1160 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1161 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1162 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1163 1164 ut_reservation_free_req(req); 1165 ut_reservation_deinit(); 1166 } 1167 1168 static void 1169 test_reservation_release_notification_write_exclusive(void) 1170 { 1171 struct spdk_nvmf_request *req; 1172 struct spdk_nvme_cpl *rsp; 1173 1174 ut_reservation_init(); 1175 1176 req = ut_reservation_build_req(16); 1177 SPDK_CU_ASSERT_FATAL(req != NULL); 1178 rsp = &req->rsp->nvme_cpl; 1179 1180 ut_reservation_build_registrants(); 1181 1182 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1183 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE 1184 */ 1185 rsp->status.sc = 0xff; 1186 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1187 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0); 1188 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1189 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1190 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 1191 1192 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation. 1193 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 1194 * no reservation notification occurs. 1195 */ 1196 rsp->status.sc = 0xff; 1197 g_ctrlr1_A.num_avail_log_pages = 5; 1198 g_ctrlr2_A.num_avail_log_pages = 5; 1199 g_ctrlr_B.num_avail_log_pages = 5; 1200 g_ctrlr_C.num_avail_log_pages = 5; 1201 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0, 1202 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1); 1203 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1204 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1205 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1206 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages); 1207 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages); 1208 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1209 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1210 1211 ut_reservation_free_req(req); 1212 ut_reservation_deinit(); 1213 } 1214 1215 static void 1216 test_reservation_clear_notification(void) 1217 { 1218 struct spdk_nvmf_request *req; 1219 struct spdk_nvme_cpl *rsp; 1220 1221 ut_reservation_init(); 1222 1223 req = ut_reservation_build_req(16); 1224 SPDK_CU_ASSERT_FATAL(req != NULL); 1225 rsp = &req->rsp->nvme_cpl; 1226 1227 ut_reservation_build_registrants(); 1228 1229 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1230 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1231 */ 1232 rsp->status.sc = 0xff; 1233 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1234 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1235 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1236 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1237 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1238 1239 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation. 1240 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C. 1241 */ 1242 rsp->status.sc = 0xff; 1243 g_ctrlr1_A.num_avail_log_pages = 0; 1244 g_ctrlr2_A.num_avail_log_pages = 0; 1245 g_ctrlr_B.num_avail_log_pages = 5; 1246 g_ctrlr_C.num_avail_log_pages = 0; 1247 ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0, 1248 0, 0xb1); 1249 nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req); 1250 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1251 SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0); 1252 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1253 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1254 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages); 1255 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages); 1256 1257 ut_reservation_free_req(req); 1258 ut_reservation_deinit(); 1259 } 1260 1261 static void 1262 test_reservation_preempt_notification(void) 1263 { 1264 struct spdk_nvmf_request *req; 1265 struct spdk_nvme_cpl *rsp; 1266 1267 ut_reservation_init(); 1268 1269 req = ut_reservation_build_req(16); 1270 SPDK_CU_ASSERT_FATAL(req != NULL); 1271 rsp = &req->rsp->nvme_cpl; 1272 1273 ut_reservation_build_registrants(); 1274 1275 /* ACQUIRE: Host B with g_ctrlr_B get reservation with 1276 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY 1277 */ 1278 rsp->status.sc = 0xff; 1279 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0, 1280 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0); 1281 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req); 1282 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1283 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1284 1285 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B, 1286 * g_ctrlr_B registrant is unregistered, and reservation is preempted. 1287 * Registration Preempted notification sends to g_ctrlr_B. 1288 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A. 1289 */ 1290 rsp->status.sc = 0xff; 1291 g_ctrlr1_A.num_avail_log_pages = 0; 1292 g_ctrlr2_A.num_avail_log_pages = 0; 1293 g_ctrlr_B.num_avail_log_pages = 0; 1294 g_ctrlr_C.num_avail_log_pages = 5; 1295 ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0, 1296 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1); 1297 nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req); 1298 SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS); 1299 SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1300 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages); 1301 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages); 1302 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages); 1303 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages); 1304 1305 ut_reservation_free_req(req); 1306 ut_reservation_deinit(); 1307 } 1308 1309 static int 1310 nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf) 1311 { 1312 return 0; 1313 } 1314 1315 static void 1316 nvmf_tgt_destroy_poll_group(void *io_device, void *ctx_buf) 1317 { 1318 } 1319 1320 static void 1321 test_spdk_nvmf_ns_event(void) 1322 { 1323 struct spdk_nvmf_tgt tgt = {}; 1324 struct spdk_nvmf_subsystem subsystem = { 1325 .max_nsid = 1024, 1326 .ns = NULL, 1327 .tgt = &tgt, 1328 }; 1329 struct spdk_nvmf_ctrlr ctrlr = { 1330 .subsys = &subsystem 1331 }; 1332 struct spdk_nvmf_ns_opts ns_opts; 1333 uint32_t nsid; 1334 struct spdk_bdev *bdev; 1335 1336 subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *)); 1337 SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL); 1338 subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t)); 1339 SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL); 1340 1341 tgt.max_subsystems = 1024; 1342 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1343 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1344 1345 spdk_io_device_register(&tgt, 1346 nvmf_tgt_create_poll_group, 1347 nvmf_tgt_destroy_poll_group, 1348 sizeof(struct spdk_nvmf_poll_group), 1349 NULL); 1350 1351 /* Add one namespace */ 1352 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1353 nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL); 1354 CU_ASSERT(nsid == 1); 1355 CU_ASSERT(NULL != subsystem.ns[0]); 1356 CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]); 1357 1358 bdev = subsystem.ns[nsid - 1]->bdev; 1359 1360 /* Add one controller */ 1361 TAILQ_INIT(&subsystem.ctrlrs); 1362 TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link); 1363 1364 /* Namespace resize event */ 1365 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1366 g_ns_changed_nsid = 0xFFFFFFFF; 1367 g_ns_changed_ctrlr = NULL; 1368 nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]); 1369 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1370 1371 poll_threads(); 1372 CU_ASSERT(1 == g_ns_changed_nsid); 1373 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1374 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1375 1376 /* Namespace remove event */ 1377 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1378 g_ns_changed_nsid = 0xFFFFFFFF; 1379 g_ns_changed_ctrlr = NULL; 1380 nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]); 1381 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); 1382 CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid); 1383 CU_ASSERT(NULL == g_ns_changed_ctrlr); 1384 1385 poll_threads(); 1386 CU_ASSERT(1 == g_ns_changed_nsid); 1387 CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); 1388 CU_ASSERT(NULL == subsystem.ns[0]); 1389 CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); 1390 1391 spdk_io_device_unregister(&tgt, NULL); 1392 1393 poll_threads(); 1394 1395 free(subsystem.ns); 1396 free(subsystem.ana_group); 1397 free(tgt.subsystems); 1398 } 1399 1400 static void 1401 test_nvmf_ns_reservation_add_remove_registrant(void) 1402 { 1403 struct spdk_nvmf_ns ns = {}; 1404 struct spdk_nvmf_ctrlr ctrlr = {}; 1405 struct spdk_nvmf_registrant *reg = NULL; 1406 int rc; 1407 1408 TAILQ_INIT(&ns.registrants); 1409 spdk_uuid_generate(&ctrlr.hostid); 1410 1411 rc = nvmf_ns_reservation_add_registrant(&ns, &ctrlr, 0xa11); 1412 CU_ASSERT(rc == 0); 1413 reg = TAILQ_FIRST(&ns.registrants); 1414 SPDK_CU_ASSERT_FATAL(reg != NULL); 1415 CU_ASSERT(ns.gen == 1); 1416 CU_ASSERT(reg->rkey == 0xa11); 1417 CU_ASSERT(!strncmp((uint8_t *)®->hostid, (uint8_t *)&ctrlr.hostid, sizeof(ctrlr.hostid))); 1418 1419 nvmf_ns_reservation_remove_registrant(&ns, reg); 1420 CU_ASSERT(TAILQ_EMPTY(&ns.registrants)); 1421 CU_ASSERT(ns.gen == 2); 1422 } 1423 1424 static void 1425 test_nvmf_subsystem_destroy_cb(void *cb_arg) 1426 { 1427 } 1428 1429 static void 1430 test_nvmf_subsystem_add_ctrlr(void) 1431 { 1432 int rc; 1433 struct spdk_nvmf_ctrlr ctrlr = {}; 1434 struct spdk_nvmf_tgt tgt = {}; 1435 char nqn[256] = "nqn.2016-06.io.spdk:subsystem1"; 1436 struct spdk_nvmf_subsystem *subsystem = NULL; 1437 1438 tgt.max_subsystems = 1024; 1439 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1440 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1441 1442 subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0); 1443 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 1444 ctrlr.subsys = subsystem; 1445 1446 ctrlr.dynamic_ctrlr = true; 1447 rc = nvmf_subsystem_add_ctrlr(subsystem, &ctrlr); 1448 CU_ASSERT(rc == 0); 1449 CU_ASSERT(!TAILQ_EMPTY(&subsystem->ctrlrs)); 1450 CU_ASSERT(ctrlr.cntlid == 1); 1451 CU_ASSERT(nvmf_subsystem_get_ctrlr(subsystem, 1) == &ctrlr); 1452 1453 nvmf_subsystem_remove_ctrlr(subsystem, &ctrlr); 1454 CU_ASSERT(TAILQ_EMPTY(&subsystem->ctrlrs)); 1455 rc = spdk_nvmf_subsystem_destroy(subsystem, test_nvmf_subsystem_destroy_cb, NULL); 1456 CU_ASSERT(rc == 0); 1457 free(tgt.subsystems); 1458 } 1459 1460 static void 1461 test_spdk_nvmf_subsystem_add_host(void) 1462 { 1463 struct spdk_nvmf_tgt tgt = {}; 1464 struct spdk_nvmf_subsystem *subsystem = NULL; 1465 int rc; 1466 const char hostnqn[] = "nqn.2016-06.io.spdk:host1"; 1467 const char subsystemnqn[] = "nqn.2016-06.io.spdk:subsystem1"; 1468 1469 tgt.max_subsystems = 1024; 1470 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 1471 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 1472 1473 subsystem = spdk_nvmf_subsystem_create(&tgt, subsystemnqn, SPDK_NVMF_SUBTYPE_NVME, 0); 1474 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 1475 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, subsystemnqn); 1476 1477 rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn); 1478 CU_ASSERT(rc == 0); 1479 CU_ASSERT(!TAILQ_EMPTY(&subsystem->hosts)); 1480 1481 /* Add existing nqn, this function is allowed to be called if the nqn was previously added. */ 1482 rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn); 1483 CU_ASSERT(rc == 0); 1484 1485 rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn); 1486 CU_ASSERT(rc == 0); 1487 CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts)); 1488 1489 /* No available nqn */ 1490 rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn); 1491 CU_ASSERT(rc == -ENOENT); 1492 1493 spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 1494 free(tgt.subsystems); 1495 } 1496 1497 static void 1498 test_nvmf_ns_reservation_report(void) 1499 { 1500 struct spdk_nvmf_ns ns = {}; 1501 struct spdk_nvmf_ctrlr ctrlr = {}; 1502 struct spdk_nvmf_request req = {}; 1503 union nvmf_h2c_msg cmd = {}; 1504 union nvmf_c2h_msg rsp = {}; 1505 struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data; 1506 struct spdk_nvme_reservation_status_extended_data *status_data; 1507 struct spdk_nvmf_registrant *reg; 1508 1509 req.data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2); 1510 reg = calloc(2, sizeof(struct spdk_nvmf_registrant)); 1511 SPDK_CU_ASSERT_FATAL(req.data != NULL && reg != NULL); 1512 1513 req.cmd = &cmd; 1514 req.rsp = &rsp; 1515 ns.gen = 1; 1516 ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE; 1517 ns.ptpl_activated = true; 1518 cmd.nvme_cmd.cdw11_bits.resv_report.eds = true; 1519 cmd.nvme_cmd.cdw10 = 100; 1520 reg[0].rkey = 0xa; 1521 reg[1].rkey = 0xb; 1522 spdk_uuid_generate(®[0].hostid); 1523 spdk_uuid_generate(®[1].hostid); 1524 TAILQ_INIT(&ns.registrants); 1525 TAILQ_INSERT_TAIL(&ns.registrants, ®[0], link); 1526 TAILQ_INSERT_TAIL(&ns.registrants, ®[1], link); 1527 1528 nvmf_ns_reservation_report(&ns, &ctrlr, &req); 1529 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1530 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 1531 /* Get ctrlr data and status data pointers */ 1532 ctrlr_data = (void *)((uint64_t)req.data + sizeof(*status_data)); 1533 status_data = (void *)req.data; 1534 SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL); 1535 CU_ASSERT(status_data->data.gen == 1); 1536 CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 1537 CU_ASSERT(status_data->data.ptpls == true); 1538 CU_ASSERT(status_data->data.regctl == 2); 1539 CU_ASSERT(ctrlr_data->cntlid == 0xffff); 1540 CU_ASSERT(ctrlr_data->rcsts.status == false); 1541 CU_ASSERT(ctrlr_data->rkey == 0xa); 1542 CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, ®[0].hostid)); 1543 /* Check second ctrlr data */ 1544 ctrlr_data++; 1545 CU_ASSERT(ctrlr_data->cntlid == 0xffff); 1546 CU_ASSERT(ctrlr_data->rcsts.status == false); 1547 CU_ASSERT(ctrlr_data->rkey == 0xb); 1548 CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, ®[1].hostid)); 1549 1550 /* extended controller data structure */ 1551 memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2); 1552 memset(req.rsp, 0, sizeof(*req.rsp)); 1553 cmd.nvme_cmd.cdw11_bits.resv_report.eds = false; 1554 1555 nvmf_ns_reservation_report(&ns, &ctrlr, &req); 1556 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT); 1557 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1558 1559 /* Transfer length invalid */ 1560 memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2); 1561 memset(req.rsp, 0, sizeof(*req.rsp)); 1562 cmd.nvme_cmd.cdw11_bits.resv_report.eds = true; 1563 cmd.nvme_cmd.cdw10 = 0; 1564 1565 nvmf_ns_reservation_report(&ns, &ctrlr, &req); 1566 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR); 1567 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1568 1569 free(req.data); 1570 free(reg); 1571 } 1572 1573 static void 1574 test_nvmf_valid_nqn(void) 1575 { 1576 bool rc; 1577 char uuid[SPDK_NVMF_UUID_STRING_LEN + 1] = {}; 1578 char nqn[SPDK_NVMF_NQN_MAX_LEN + 1] = {}; 1579 struct spdk_uuid s_uuid = {}; 1580 1581 spdk_uuid_generate(&s_uuid); 1582 uuid_unparse((void *)&s_uuid, uuid); 1583 1584 /* discovery nqn */ 1585 snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_DISCOVERY_NQN); 1586 1587 rc = nvmf_valid_nqn(nqn); 1588 CU_ASSERT(rc == true); 1589 1590 /* nqn with uuid */ 1591 memset(nqn, 0xff, sizeof(nqn)); 1592 snprintf(nqn, sizeof(nqn), "%s%s", SPDK_NVMF_NQN_UUID_PRE, uuid); 1593 1594 rc = nvmf_valid_nqn(nqn); 1595 CU_ASSERT(rc == true); 1596 1597 /* Check nqn valid reverse domain */ 1598 memset(nqn, 0xff, sizeof(nqn)); 1599 snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io.spdk:cnode1"); 1600 1601 rc = nvmf_valid_nqn(nqn); 1602 CU_ASSERT(rc == true); 1603 1604 /* Invalid nqn length */ 1605 memset(nqn, 0xff, sizeof(nqn)); 1606 snprintf(nqn, sizeof(nqn), "%s", "nqn."); 1607 1608 rc = nvmf_valid_nqn(nqn); 1609 CU_ASSERT(rc == false); 1610 1611 /* Copy uuid to the nqn string, but omit the last character to make it invalid */ 1612 memset(nqn, 0, SPDK_NVMF_NQN_MAX_LEN + 1); 1613 snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_NQN_UUID_PRE); 1614 memcpy(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid, SPDK_NVMF_UUID_STRING_LEN - 1); 1615 1616 rc = nvmf_valid_nqn(nqn); 1617 CU_ASSERT(rc == false); 1618 1619 /* Invalid domain */ 1620 memset(nqn, 0xff, SPDK_NVMF_NQN_MAX_LEN + 1); 1621 snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io...spdk:cnode1"); 1622 1623 rc = nvmf_valid_nqn(nqn); 1624 CU_ASSERT(rc == false); 1625 } 1626 1627 static void 1628 test_nvmf_ns_reservation_restore(void) 1629 { 1630 struct spdk_nvmf_ns ns = {}; 1631 struct spdk_nvmf_reservation_info info = {}; 1632 struct spdk_bdev bdev = {}; 1633 struct spdk_uuid s_uuid = {}; 1634 struct spdk_nvmf_registrant *reg0, *reg1; 1635 char uuid[SPDK_UUID_STRING_LEN] = {}; 1636 int rc; 1637 1638 ns.bdev = &bdev; 1639 TAILQ_INIT(&ns.registrants); 1640 info.ptpl_activated = true; 1641 info.num_regs = 2; 1642 info.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS; 1643 info.registrants[0].rkey = 0xb; 1644 info.registrants[1].rkey = 0xc; 1645 1646 /* Generate and prepare uuids, make sure bdev and info uuid are the same */ 1647 spdk_uuid_generate(&s_uuid); 1648 uuid_unparse((void *)&s_uuid, uuid); 1649 snprintf(info.holder_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1650 snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1651 snprintf(info.registrants[0].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1652 spdk_uuid_copy(&bdev.uuid, &s_uuid); 1653 spdk_uuid_generate(&s_uuid); 1654 uuid_unparse((void *)&s_uuid, uuid); 1655 snprintf(info.registrants[1].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1656 1657 /* info->rkey not exist in registrants */ 1658 info.crkey = 0xa; 1659 1660 rc = nvmf_ns_reservation_restore(&ns, &info); 1661 CU_ASSERT(rc == -EINVAL); 1662 1663 /* info->rkey exists in registrants */ 1664 info.crkey = 0xb; 1665 1666 rc = nvmf_ns_reservation_restore(&ns, &info); 1667 CU_ASSERT(rc == 0); 1668 CU_ASSERT(ns.crkey == 0xb); 1669 CU_ASSERT(ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1670 CU_ASSERT(ns.ptpl_activated == true); 1671 /* Check two registrant`s rkey */ 1672 reg0 = TAILQ_FIRST(&ns.registrants); 1673 reg1 = TAILQ_NEXT(reg0, link); 1674 CU_ASSERT(ns.holder == reg0); 1675 CU_ASSERT(reg0->rkey = 0xb); 1676 CU_ASSERT(reg1->rkey = 0xc); 1677 1678 rc = nvmf_ns_reservation_clear_all_registrants(&ns); 1679 CU_ASSERT(rc == 2); 1680 CU_ASSERT(TAILQ_EMPTY(&ns.registrants)); 1681 1682 /* Existing bdev UUID is different with configuration */ 1683 spdk_uuid_generate(&s_uuid); 1684 uuid_unparse((void *)&s_uuid, uuid); 1685 snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid); 1686 spdk_uuid_generate(&s_uuid); 1687 spdk_uuid_copy(&bdev.uuid, &s_uuid); 1688 1689 rc = nvmf_ns_reservation_restore(&ns, &info); 1690 CU_ASSERT(rc == -EINVAL); 1691 } 1692 1693 int main(int argc, char **argv) 1694 { 1695 CU_pSuite suite = NULL; 1696 unsigned int num_failures; 1697 1698 CU_set_error_action(CUEA_ABORT); 1699 CU_initialize_registry(); 1700 1701 suite = CU_add_suite("nvmf", NULL, NULL); 1702 1703 CU_ADD_TEST(suite, nvmf_test_create_subsystem); 1704 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns); 1705 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn); 1706 CU_ADD_TEST(suite, test_reservation_register); 1707 CU_ADD_TEST(suite, test_reservation_register_with_ptpl); 1708 CU_ADD_TEST(suite, test_reservation_acquire_preempt_1); 1709 CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl); 1710 CU_ADD_TEST(suite, test_reservation_release); 1711 CU_ADD_TEST(suite, test_reservation_unregister_notification); 1712 CU_ADD_TEST(suite, test_reservation_release_notification); 1713 CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive); 1714 CU_ADD_TEST(suite, test_reservation_clear_notification); 1715 CU_ADD_TEST(suite, test_reservation_preempt_notification); 1716 CU_ADD_TEST(suite, test_spdk_nvmf_ns_event); 1717 CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant); 1718 CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr); 1719 CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host); 1720 CU_ADD_TEST(suite, test_nvmf_ns_reservation_report); 1721 CU_ADD_TEST(suite, test_nvmf_valid_nqn); 1722 CU_ADD_TEST(suite, test_nvmf_ns_reservation_restore); 1723 1724 allocate_threads(1); 1725 set_thread(0); 1726 1727 CU_basic_set_mode(CU_BRM_VERBOSE); 1728 CU_basic_run_tests(); 1729 num_failures = CU_get_number_of_failures(); 1730 CU_cleanup_registry(); 1731 1732 free_threads(); 1733 1734 return num_failures; 1735 } 1736