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