1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "nvmf_internal.h" 37 #include "transport.h" 38 39 #include "spdk/event.h" 40 #include "spdk/likely.h" 41 #include "spdk/string.h" 42 #include "spdk/trace.h" 43 #include "spdk/nvmf_spec.h" 44 #include "spdk/uuid.h" 45 #include "spdk/json.h" 46 #include "spdk/file.h" 47 48 #include "spdk/bdev_module.h" 49 #include "spdk_internal/log.h" 50 #include "spdk_internal/utf.h" 51 52 #define MODEL_NUMBER_DEFAULT "SPDK bdev Controller" 53 54 /* 55 * States for parsing valid domains in NQNs according to RFC 1034 56 */ 57 enum spdk_nvmf_nqn_domain_states { 58 /* First character of a domain must be a letter */ 59 SPDK_NVMF_DOMAIN_ACCEPT_LETTER = 0, 60 61 /* Subsequent characters can be any of letter, digit, or hyphen */ 62 SPDK_NVMF_DOMAIN_ACCEPT_LDH = 1, 63 64 /* A domain label must end with either a letter or digit */ 65 SPDK_NVMF_DOMAIN_ACCEPT_ANY = 2 66 }; 67 68 /* Returns true if is a valid ASCII string as defined by the NVMe spec */ 69 static bool 70 nvmf_valid_ascii_string(const void *buf, size_t size) 71 { 72 const uint8_t *str = buf; 73 size_t i; 74 75 for (i = 0; i < size; i++) { 76 if (str[i] < 0x20 || str[i] > 0x7E) { 77 return false; 78 } 79 } 80 81 return true; 82 } 83 84 static bool 85 nvmf_valid_nqn(const char *nqn) 86 { 87 size_t len; 88 struct spdk_uuid uuid_value; 89 uint32_t i; 90 int bytes_consumed; 91 uint32_t domain_label_length; 92 char *reverse_domain_end; 93 uint32_t reverse_domain_end_index; 94 enum spdk_nvmf_nqn_domain_states domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER; 95 96 /* Check for length requirements */ 97 len = strlen(nqn); 98 if (len > SPDK_NVMF_NQN_MAX_LEN) { 99 SPDK_ERRLOG("Invalid NQN \"%s\": length %zu > max %d\n", nqn, len, SPDK_NVMF_NQN_MAX_LEN); 100 return false; 101 } 102 103 /* The nqn must be at least as long as SPDK_NVMF_NQN_MIN_LEN to contain the necessary prefix. */ 104 if (len < SPDK_NVMF_NQN_MIN_LEN) { 105 SPDK_ERRLOG("Invalid NQN \"%s\": length %zu < min %d\n", nqn, len, SPDK_NVMF_NQN_MIN_LEN); 106 return false; 107 } 108 109 /* Check for discovery controller nqn */ 110 if (!strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN)) { 111 return true; 112 } 113 114 /* Check for equality with the generic nqn structure of the form "nqn.2014-08.org.nvmexpress:uuid:11111111-2222-3333-4444-555555555555" */ 115 if (!strncmp(nqn, SPDK_NVMF_NQN_UUID_PRE, SPDK_NVMF_NQN_UUID_PRE_LEN)) { 116 if (len != SPDK_NVMF_NQN_UUID_PRE_LEN + SPDK_NVMF_UUID_STRING_LEN) { 117 SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not the correct length\n", nqn); 118 return false; 119 } 120 121 if (spdk_uuid_parse(&uuid_value, &nqn[SPDK_NVMF_NQN_UUID_PRE_LEN])) { 122 SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not formatted correctly\n", nqn); 123 return false; 124 } 125 return true; 126 } 127 128 /* If the nqn does not match the uuid structure, the next several checks validate the form "nqn.yyyy-mm.reverse.domain:user-string" */ 129 130 if (strncmp(nqn, "nqn.", 4) != 0) { 131 SPDK_ERRLOG("Invalid NQN \"%s\": NQN must begin with \"nqn.\".\n", nqn); 132 return false; 133 } 134 135 /* Check for yyyy-mm. */ 136 if (!(isdigit(nqn[4]) && isdigit(nqn[5]) && isdigit(nqn[6]) && isdigit(nqn[7]) && 137 nqn[8] == '-' && isdigit(nqn[9]) && isdigit(nqn[10]) && nqn[11] == '.')) { 138 SPDK_ERRLOG("Invalid date code in NQN \"%s\"\n", nqn); 139 return false; 140 } 141 142 reverse_domain_end = strchr(nqn, ':'); 143 if (reverse_domain_end != NULL && (reverse_domain_end_index = reverse_domain_end - nqn) < len - 1) { 144 } else { 145 SPDK_ERRLOG("Invalid NQN \"%s\". NQN must contain user specified name with a ':' as a prefix.\n", 146 nqn); 147 return false; 148 } 149 150 /* Check for valid reverse domain */ 151 domain_label_length = 0; 152 for (i = 12; i < reverse_domain_end_index; i++) { 153 if (domain_label_length > SPDK_DOMAIN_LABEL_MAX_LEN) { 154 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". At least one Label is too long.\n", nqn); 155 return false; 156 } 157 158 switch (domain_state) { 159 160 case SPDK_NVMF_DOMAIN_ACCEPT_LETTER: { 161 if (isalpha(nqn[i])) { 162 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY; 163 domain_label_length++; 164 break; 165 } else { 166 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must start with a letter.\n", nqn); 167 return false; 168 } 169 } 170 171 case SPDK_NVMF_DOMAIN_ACCEPT_LDH: { 172 if (isalpha(nqn[i]) || isdigit(nqn[i])) { 173 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY; 174 domain_label_length++; 175 break; 176 } else if (nqn[i] == '-') { 177 if (i == reverse_domain_end_index - 1) { 178 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n", 179 nqn); 180 return false; 181 } 182 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH; 183 domain_label_length++; 184 break; 185 } else if (nqn[i] == '.') { 186 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n", 187 nqn); 188 return false; 189 } else { 190 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n", 191 nqn); 192 return false; 193 } 194 } 195 196 case SPDK_NVMF_DOMAIN_ACCEPT_ANY: { 197 if (isalpha(nqn[i]) || isdigit(nqn[i])) { 198 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY; 199 domain_label_length++; 200 break; 201 } else if (nqn[i] == '-') { 202 if (i == reverse_domain_end_index - 1) { 203 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n", 204 nqn); 205 return false; 206 } 207 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH; 208 domain_label_length++; 209 break; 210 } else if (nqn[i] == '.') { 211 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER; 212 domain_label_length = 0; 213 break; 214 } else { 215 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n", 216 nqn); 217 return false; 218 } 219 } 220 } 221 } 222 223 i = reverse_domain_end_index + 1; 224 while (i < len) { 225 bytes_consumed = utf8_valid(&nqn[i], &nqn[len]); 226 if (bytes_consumed <= 0) { 227 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only valid utf-8.\n", nqn); 228 return false; 229 } 230 231 i += bytes_consumed; 232 } 233 return true; 234 } 235 236 struct spdk_nvmf_subsystem * 237 spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt, 238 const char *nqn, 239 enum spdk_nvmf_subtype type, 240 uint32_t num_ns) 241 { 242 struct spdk_nvmf_subsystem *subsystem; 243 uint32_t sid; 244 245 if (spdk_nvmf_tgt_find_subsystem(tgt, nqn)) { 246 SPDK_ERRLOG("Subsystem NQN '%s' already exists\n", nqn); 247 return NULL; 248 } 249 250 if (!nvmf_valid_nqn(nqn)) { 251 return NULL; 252 } 253 254 if (type == SPDK_NVMF_SUBTYPE_DISCOVERY && num_ns != 0) { 255 SPDK_ERRLOG("Discovery subsystem cannot have namespaces.\n"); 256 return NULL; 257 } 258 259 /* Find a free subsystem id (sid) */ 260 for (sid = 0; sid < tgt->max_subsystems; sid++) { 261 if (tgt->subsystems[sid] == NULL) { 262 break; 263 } 264 } 265 if (sid >= tgt->max_subsystems) { 266 return NULL; 267 } 268 269 subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem)); 270 if (subsystem == NULL) { 271 return NULL; 272 } 273 274 subsystem->thread = spdk_get_thread(); 275 subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 276 subsystem->tgt = tgt; 277 subsystem->id = sid; 278 subsystem->subtype = type; 279 subsystem->max_nsid = num_ns; 280 subsystem->max_allowed_nsid = num_ns; 281 subsystem->next_cntlid = 0; 282 snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn); 283 TAILQ_INIT(&subsystem->listeners); 284 TAILQ_INIT(&subsystem->hosts); 285 TAILQ_INIT(&subsystem->ctrlrs); 286 287 if (num_ns != 0) { 288 subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *)); 289 if (subsystem->ns == NULL) { 290 SPDK_ERRLOG("Namespace memory allocation failed\n"); 291 free(subsystem); 292 return NULL; 293 } 294 } 295 296 memset(subsystem->sn, '0', sizeof(subsystem->sn) - 1); 297 subsystem->sn[sizeof(subsystem->sn) - 1] = '\0'; 298 299 snprintf(subsystem->mn, sizeof(subsystem->mn), "%s", 300 MODEL_NUMBER_DEFAULT); 301 302 tgt->subsystems[sid] = subsystem; 303 tgt->discovery_genctr++; 304 305 return subsystem; 306 } 307 308 static void 309 _spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_host *host) 310 { 311 TAILQ_REMOVE(&subsystem->hosts, host, link); 312 free(host); 313 } 314 315 static void 316 _nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, 317 struct spdk_nvmf_subsystem_listener *listener, 318 bool stop) 319 { 320 struct spdk_nvmf_transport *transport; 321 322 if (stop) { 323 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, listener->trid->trstring); 324 if (transport != NULL) { 325 spdk_nvmf_transport_stop_listen(transport, listener->trid); 326 } 327 } 328 329 TAILQ_REMOVE(&subsystem->listeners, listener, link); 330 free(listener); 331 } 332 333 void 334 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem) 335 { 336 struct spdk_nvmf_host *host, *host_tmp; 337 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 338 struct spdk_nvmf_ns *ns; 339 340 if (!subsystem) { 341 return; 342 } 343 344 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 345 346 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem); 347 348 nvmf_subsystem_remove_all_listeners(subsystem, false); 349 350 TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) { 351 _spdk_nvmf_subsystem_remove_host(subsystem, host); 352 } 353 354 TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) { 355 nvmf_ctrlr_destruct(ctrlr); 356 } 357 358 ns = spdk_nvmf_subsystem_get_first_ns(subsystem); 359 while (ns != NULL) { 360 struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns); 361 362 spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 363 ns = next_ns; 364 } 365 366 free(subsystem->ns); 367 368 subsystem->tgt->subsystems[subsystem->id] = NULL; 369 subsystem->tgt->discovery_genctr++; 370 371 free(subsystem); 372 } 373 374 static int 375 nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem, 376 enum spdk_nvmf_subsystem_state state) 377 { 378 enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state; 379 bool exchanged; 380 381 switch (state) { 382 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 383 expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 384 break; 385 case SPDK_NVMF_SUBSYSTEM_ACTIVATING: 386 expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 387 break; 388 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 389 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 390 break; 391 case SPDK_NVMF_SUBSYSTEM_PAUSING: 392 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 393 break; 394 case SPDK_NVMF_SUBSYSTEM_PAUSED: 395 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 396 break; 397 case SPDK_NVMF_SUBSYSTEM_RESUMING: 398 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED; 399 break; 400 case SPDK_NVMF_SUBSYSTEM_DEACTIVATING: 401 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 402 break; 403 default: 404 assert(false); 405 return -1; 406 } 407 408 actual_old_state = expected_old_state; 409 exchanged = __atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false, 410 __ATOMIC_RELAXED, __ATOMIC_RELAXED); 411 if (spdk_unlikely(exchanged == false)) { 412 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING && 413 state == SPDK_NVMF_SUBSYSTEM_ACTIVE) { 414 expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 415 } 416 /* This is for the case when activating the subsystem fails. */ 417 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_ACTIVATING && 418 state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) { 419 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 420 } 421 actual_old_state = expected_old_state; 422 __atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false, 423 __ATOMIC_RELAXED, __ATOMIC_RELAXED); 424 } 425 assert(actual_old_state == expected_old_state); 426 return actual_old_state - expected_old_state; 427 } 428 429 struct subsystem_state_change_ctx { 430 struct spdk_nvmf_subsystem *subsystem; 431 432 enum spdk_nvmf_subsystem_state requested_state; 433 434 spdk_nvmf_subsystem_state_change_done cb_fn; 435 void *cb_arg; 436 }; 437 438 static void 439 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status) 440 { 441 struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 442 443 if (status == 0) { 444 status = nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state); 445 if (status) { 446 status = -1; 447 } 448 } 449 450 if (ctx->cb_fn) { 451 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 452 } 453 free(ctx); 454 } 455 456 static void 457 subsystem_state_change_continue(void *ctx, int status) 458 { 459 struct spdk_io_channel_iter *i = ctx; 460 spdk_for_each_channel_continue(i, status); 461 } 462 463 static void 464 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i) 465 { 466 struct subsystem_state_change_ctx *ctx; 467 struct spdk_io_channel *ch; 468 struct spdk_nvmf_poll_group *group; 469 470 ctx = spdk_io_channel_iter_get_ctx(i); 471 ch = spdk_io_channel_iter_get_channel(i); 472 group = spdk_io_channel_get_ctx(ch); 473 474 switch (ctx->requested_state) { 475 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 476 nvmf_poll_group_remove_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 477 break; 478 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 479 if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) { 480 nvmf_poll_group_add_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 481 } else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) { 482 nvmf_poll_group_resume_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 483 } 484 break; 485 case SPDK_NVMF_SUBSYSTEM_PAUSED: 486 nvmf_poll_group_pause_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 487 break; 488 default: 489 assert(false); 490 break; 491 } 492 } 493 494 static int 495 nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem, 496 enum spdk_nvmf_subsystem_state requested_state, 497 spdk_nvmf_subsystem_state_change_done cb_fn, 498 void *cb_arg) 499 { 500 struct subsystem_state_change_ctx *ctx; 501 enum spdk_nvmf_subsystem_state intermediate_state; 502 int rc; 503 504 switch (requested_state) { 505 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 506 intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 507 break; 508 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 509 if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) { 510 intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 511 } else { 512 intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 513 } 514 break; 515 case SPDK_NVMF_SUBSYSTEM_PAUSED: 516 intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 517 break; 518 default: 519 assert(false); 520 return -EINVAL; 521 } 522 523 ctx = calloc(1, sizeof(*ctx)); 524 if (!ctx) { 525 return -ENOMEM; 526 } 527 528 rc = nvmf_subsystem_set_state(subsystem, intermediate_state); 529 if (rc) { 530 free(ctx); 531 return rc; 532 } 533 534 ctx->subsystem = subsystem; 535 ctx->requested_state = requested_state; 536 ctx->cb_fn = cb_fn; 537 ctx->cb_arg = cb_arg; 538 539 spdk_for_each_channel(subsystem->tgt, 540 subsystem_state_change_on_pg, 541 ctx, 542 subsystem_state_change_done); 543 544 return 0; 545 } 546 547 int 548 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem, 549 spdk_nvmf_subsystem_state_change_done cb_fn, 550 void *cb_arg) 551 { 552 return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 553 } 554 555 int 556 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem, 557 spdk_nvmf_subsystem_state_change_done cb_fn, 558 void *cb_arg) 559 { 560 return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg); 561 } 562 563 int 564 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem, 565 spdk_nvmf_subsystem_state_change_done cb_fn, 566 void *cb_arg) 567 { 568 return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg); 569 } 570 571 int 572 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem, 573 spdk_nvmf_subsystem_state_change_done cb_fn, 574 void *cb_arg) 575 { 576 return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 577 } 578 579 struct spdk_nvmf_subsystem * 580 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt) 581 { 582 struct spdk_nvmf_subsystem *subsystem; 583 uint32_t sid; 584 585 for (sid = 0; sid < tgt->max_subsystems; sid++) { 586 subsystem = tgt->subsystems[sid]; 587 if (subsystem) { 588 return subsystem; 589 } 590 } 591 592 return NULL; 593 } 594 595 struct spdk_nvmf_subsystem * 596 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem) 597 { 598 uint32_t sid; 599 struct spdk_nvmf_tgt *tgt; 600 601 if (!subsystem) { 602 return NULL; 603 } 604 605 tgt = subsystem->tgt; 606 607 for (sid = subsystem->id + 1; sid < tgt->max_subsystems; sid++) { 608 subsystem = tgt->subsystems[sid]; 609 if (subsystem) { 610 return subsystem; 611 } 612 } 613 614 return NULL; 615 } 616 617 static struct spdk_nvmf_host * 618 _spdk_nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 619 { 620 struct spdk_nvmf_host *host = NULL; 621 622 TAILQ_FOREACH(host, &subsystem->hosts, link) { 623 if (strcmp(hostnqn, host->nqn) == 0) { 624 return host; 625 } 626 } 627 628 return NULL; 629 } 630 631 int 632 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 633 { 634 struct spdk_nvmf_host *host; 635 636 if (!nvmf_valid_nqn(hostnqn)) { 637 return -EINVAL; 638 } 639 640 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 641 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 642 return -EAGAIN; 643 } 644 645 if (_spdk_nvmf_subsystem_find_host(subsystem, hostnqn)) { 646 /* This subsystem already allows the specified host. */ 647 return 0; 648 } 649 650 host = calloc(1, sizeof(*host)); 651 if (!host) { 652 return -ENOMEM; 653 } 654 655 snprintf(host->nqn, sizeof(host->nqn), "%s", hostnqn); 656 657 TAILQ_INSERT_HEAD(&subsystem->hosts, host, link); 658 subsystem->tgt->discovery_genctr++; 659 660 return 0; 661 } 662 663 int 664 spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 665 { 666 struct spdk_nvmf_host *host; 667 668 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 669 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 670 return -EAGAIN; 671 } 672 673 host = _spdk_nvmf_subsystem_find_host(subsystem, hostnqn); 674 if (host == NULL) { 675 return -ENOENT; 676 } 677 678 _spdk_nvmf_subsystem_remove_host(subsystem, host); 679 return 0; 680 } 681 682 int 683 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host) 684 { 685 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 686 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 687 return -EAGAIN; 688 } 689 690 subsystem->allow_any_host = allow_any_host; 691 692 return 0; 693 } 694 695 bool 696 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem) 697 { 698 return subsystem->allow_any_host; 699 } 700 701 bool 702 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 703 { 704 if (!hostnqn) { 705 return false; 706 } 707 708 if (subsystem->allow_any_host) { 709 return true; 710 } 711 712 return _spdk_nvmf_subsystem_find_host(subsystem, hostnqn) != NULL; 713 } 714 715 struct spdk_nvmf_host * 716 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem) 717 { 718 return TAILQ_FIRST(&subsystem->hosts); 719 } 720 721 722 struct spdk_nvmf_host * 723 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem, 724 struct spdk_nvmf_host *prev_host) 725 { 726 return TAILQ_NEXT(prev_host, link); 727 } 728 729 const char * 730 spdk_nvmf_host_get_nqn(const struct spdk_nvmf_host *host) 731 { 732 return host->nqn; 733 } 734 735 struct spdk_nvmf_subsystem_listener * 736 nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, 737 const struct spdk_nvme_transport_id *trid) 738 { 739 struct spdk_nvmf_subsystem_listener *listener; 740 741 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 742 if (spdk_nvme_transport_id_compare(listener->trid, trid) == 0) { 743 return listener; 744 } 745 } 746 747 return NULL; 748 } 749 750 /** 751 * Function to be called once the target is listening. 752 * 753 * \param ctx Context argument passed to this function. 754 * \param status 0 if it completed successfully, or negative errno if it failed. 755 */ 756 static void 757 _nvmf_subsystem_add_listener_done(void *ctx, int status) 758 { 759 struct spdk_nvmf_subsystem_listener *listener = ctx; 760 761 if (status) { 762 listener->cb_fn(listener->cb_arg, status); 763 free(listener); 764 return; 765 } 766 767 TAILQ_INSERT_HEAD(&listener->subsystem->listeners, listener, link); 768 listener->subsystem->tgt->discovery_genctr++; 769 listener->cb_fn(listener->cb_arg, status); 770 } 771 772 void 773 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, 774 struct spdk_nvme_transport_id *trid, 775 spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, 776 void *cb_arg) 777 { 778 struct spdk_nvmf_transport *transport; 779 struct spdk_nvmf_subsystem_listener *listener; 780 struct spdk_nvmf_listener *tr_listener; 781 782 assert(cb_fn != NULL); 783 784 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 785 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 786 cb_fn(cb_arg, -EAGAIN); 787 return; 788 } 789 790 if (nvmf_subsystem_find_listener(subsystem, trid)) { 791 /* Listener already exists in this subsystem */ 792 cb_fn(cb_arg, 0); 793 return; 794 } 795 796 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trstring); 797 if (transport == NULL) { 798 SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype); 799 cb_fn(cb_arg, -EINVAL); 800 return; 801 } 802 803 tr_listener = nvmf_transport_find_listener(transport, trid); 804 if (!tr_listener) { 805 SPDK_ERRLOG("Cannot find transport listener for %s\n", trid->traddr); 806 cb_fn(cb_arg, -EINVAL); 807 return; 808 } 809 810 listener = calloc(1, sizeof(*listener)); 811 if (!listener) { 812 cb_fn(cb_arg, -ENOMEM); 813 return; 814 } 815 816 listener->trid = &tr_listener->trid; 817 listener->transport = transport; 818 listener->cb_fn = cb_fn; 819 listener->cb_arg = cb_arg; 820 listener->subsystem = subsystem; 821 822 if (transport->ops->listen_associate != NULL) { 823 transport->ops->listen_associate(transport, subsystem, trid, 824 _nvmf_subsystem_add_listener_done, 825 listener); 826 } else { 827 _nvmf_subsystem_add_listener_done(listener, 0); 828 } 829 } 830 831 int 832 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, 833 const struct spdk_nvme_transport_id *trid) 834 { 835 struct spdk_nvmf_subsystem_listener *listener; 836 837 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 838 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 839 return -EAGAIN; 840 } 841 842 listener = nvmf_subsystem_find_listener(subsystem, trid); 843 if (listener == NULL) { 844 return -ENOENT; 845 } 846 847 _nvmf_subsystem_remove_listener(subsystem, listener, false); 848 849 return 0; 850 } 851 852 void 853 nvmf_subsystem_remove_all_listeners(struct spdk_nvmf_subsystem *subsystem, 854 bool stop) 855 { 856 struct spdk_nvmf_subsystem_listener *listener, *listener_tmp; 857 858 TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) { 859 _nvmf_subsystem_remove_listener(subsystem, listener, stop); 860 } 861 } 862 863 bool 864 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, 865 const struct spdk_nvme_transport_id *trid) 866 { 867 struct spdk_nvmf_subsystem_listener *listener; 868 869 if (!strcmp(subsystem->subnqn, SPDK_NVMF_DISCOVERY_NQN)) { 870 return true; 871 } 872 873 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 874 if (spdk_nvme_transport_id_compare(listener->trid, trid) == 0) { 875 return true; 876 } 877 } 878 879 return false; 880 } 881 882 struct spdk_nvmf_subsystem_listener * 883 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem) 884 { 885 return TAILQ_FIRST(&subsystem->listeners); 886 } 887 888 struct spdk_nvmf_subsystem_listener * 889 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem, 890 struct spdk_nvmf_subsystem_listener *prev_listener) 891 { 892 return TAILQ_NEXT(prev_listener, link); 893 } 894 895 const struct spdk_nvme_transport_id * 896 spdk_nvmf_subsystem_listener_get_trid(struct spdk_nvmf_subsystem_listener *listener) 897 { 898 return listener->trid; 899 } 900 901 void 902 spdk_nvmf_subsystem_allow_any_listener(struct spdk_nvmf_subsystem *subsystem, 903 bool allow_any_listener) 904 { 905 subsystem->allow_any_listener = allow_any_listener; 906 } 907 908 bool 909 spdk_nvmf_subsytem_any_listener_allowed(struct spdk_nvmf_subsystem *subsystem) 910 { 911 return subsystem->allow_any_listener; 912 } 913 914 915 struct subsystem_update_ns_ctx { 916 struct spdk_nvmf_subsystem *subsystem; 917 918 spdk_nvmf_subsystem_state_change_done cb_fn; 919 void *cb_arg; 920 }; 921 922 static void 923 subsystem_update_ns_done(struct spdk_io_channel_iter *i, int status) 924 { 925 struct subsystem_update_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 926 927 if (ctx->cb_fn) { 928 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 929 } 930 free(ctx); 931 } 932 933 static void 934 subsystem_update_ns_on_pg(struct spdk_io_channel_iter *i) 935 { 936 int rc; 937 struct subsystem_update_ns_ctx *ctx; 938 struct spdk_nvmf_poll_group *group; 939 struct spdk_nvmf_subsystem *subsystem; 940 941 ctx = spdk_io_channel_iter_get_ctx(i); 942 group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i)); 943 subsystem = ctx->subsystem; 944 945 rc = nvmf_poll_group_update_subsystem(group, subsystem); 946 spdk_for_each_channel_continue(i, rc); 947 } 948 949 static int 950 nvmf_subsystem_update_ns(struct spdk_nvmf_subsystem *subsystem, spdk_channel_for_each_cpl cpl, 951 void *ctx) 952 { 953 spdk_for_each_channel(subsystem->tgt, 954 subsystem_update_ns_on_pg, 955 ctx, 956 cpl); 957 958 return 0; 959 } 960 961 static void 962 nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 963 { 964 struct spdk_nvmf_ctrlr *ctrlr; 965 966 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 967 nvmf_ctrlr_ns_changed(ctrlr, nsid); 968 } 969 } 970 971 int 972 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 973 { 974 struct spdk_nvmf_ns *ns; 975 struct spdk_nvmf_registrant *reg, *reg_tmp; 976 977 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 978 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 979 assert(false); 980 return -1; 981 } 982 983 if (nsid == 0 || nsid > subsystem->max_nsid) { 984 return -1; 985 } 986 987 ns = subsystem->ns[nsid - 1]; 988 if (!ns) { 989 return -1; 990 } 991 992 subsystem->ns[nsid - 1] = NULL; 993 994 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 995 TAILQ_REMOVE(&ns->registrants, reg, link); 996 free(reg); 997 } 998 spdk_bdev_module_release_bdev(ns->bdev); 999 spdk_bdev_close(ns->desc); 1000 if (ns->ptpl_file) { 1001 free(ns->ptpl_file); 1002 } 1003 free(ns); 1004 1005 nvmf_subsystem_ns_changed(subsystem, nsid); 1006 1007 return 0; 1008 } 1009 1010 static void 1011 _nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 1012 void *cb_arg, int status) 1013 { 1014 struct spdk_nvmf_ns *ns = cb_arg; 1015 int rc; 1016 1017 rc = spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 1018 if (rc != 0) { 1019 SPDK_ERRLOG("Failed to make changes to NVME-oF subsystem with id: %u\n", subsystem->id); 1020 } 1021 1022 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 1023 } 1024 1025 static void 1026 nvmf_ns_hot_remove(void *remove_ctx) 1027 { 1028 struct spdk_nvmf_ns *ns = remove_ctx; 1029 int rc; 1030 1031 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_hot_remove, ns); 1032 if (rc) { 1033 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 1034 } 1035 } 1036 1037 static void 1038 _nvmf_ns_resize(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status) 1039 { 1040 struct spdk_nvmf_ns *ns = cb_arg; 1041 1042 nvmf_subsystem_ns_changed(subsystem, ns->opts.nsid); 1043 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 1044 } 1045 1046 static void 1047 nvmf_ns_resize(void *event_ctx) 1048 { 1049 struct spdk_nvmf_ns *ns = event_ctx; 1050 int rc; 1051 1052 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_resize, ns); 1053 if (rc) { 1054 SPDK_ERRLOG("Unable to pause subsystem to process namespace resize!\n"); 1055 } 1056 } 1057 1058 static void 1059 nvmf_ns_event(enum spdk_bdev_event_type type, 1060 struct spdk_bdev *bdev, 1061 void *event_ctx) 1062 { 1063 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev event: type %d, name %s, subsystem_id %d, ns_id %d\n", 1064 type, 1065 bdev->name, 1066 ((struct spdk_nvmf_ns *)event_ctx)->subsystem->id, 1067 ((struct spdk_nvmf_ns *)event_ctx)->nsid); 1068 1069 switch (type) { 1070 case SPDK_BDEV_EVENT_REMOVE: 1071 nvmf_ns_hot_remove(event_ctx); 1072 break; 1073 case SPDK_BDEV_EVENT_RESIZE: 1074 nvmf_ns_resize(event_ctx); 1075 break; 1076 default: 1077 SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type); 1078 break; 1079 } 1080 } 1081 1082 void 1083 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size) 1084 { 1085 /* All current fields are set to 0 by default. */ 1086 memset(opts, 0, opts_size); 1087 } 1088 1089 /* Dummy bdev module used to to claim bdevs. */ 1090 static struct spdk_bdev_module ns_bdev_module = { 1091 .name = "NVMe-oF Target", 1092 }; 1093 1094 static int 1095 nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info); 1096 static int 1097 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info); 1098 1099 uint32_t 1100 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 1101 const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size, 1102 const char *ptpl_file) 1103 { 1104 struct spdk_nvmf_ns_opts opts; 1105 struct spdk_nvmf_ns *ns; 1106 struct spdk_nvmf_reservation_info info = {0}; 1107 int rc; 1108 1109 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 1110 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 1111 return 0; 1112 } 1113 1114 if (spdk_bdev_get_md_size(bdev) != 0 && !spdk_bdev_is_md_interleaved(bdev)) { 1115 SPDK_ERRLOG("Can't attach bdev with separate metadata.\n"); 1116 return 0; 1117 } 1118 1119 spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts)); 1120 if (user_opts) { 1121 memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size)); 1122 } 1123 1124 if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) { 1125 opts.uuid = *spdk_bdev_get_uuid(bdev); 1126 } 1127 1128 if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) { 1129 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid); 1130 return 0; 1131 } 1132 1133 if (opts.nsid == 0) { 1134 /* 1135 * NSID not specified - find a free index. 1136 * 1137 * If no free slots are found, opts.nsid will be subsystem->max_nsid + 1, which will 1138 * expand max_nsid if possible. 1139 */ 1140 for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) { 1141 if (_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) { 1142 break; 1143 } 1144 } 1145 } 1146 1147 if (_nvmf_subsystem_get_ns(subsystem, opts.nsid)) { 1148 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid); 1149 return 0; 1150 } 1151 1152 if (opts.nsid > subsystem->max_nsid) { 1153 struct spdk_nvmf_ns **new_ns_array; 1154 1155 /* If MaxNamespaces was specified, we can't extend max_nsid beyond it. */ 1156 if (subsystem->max_allowed_nsid > 0 && opts.nsid > subsystem->max_allowed_nsid) { 1157 SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n"); 1158 return 0; 1159 } 1160 1161 /* If a controller is connected, we can't change NN. */ 1162 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 1163 SPDK_ERRLOG("Can't extend NSID range while controllers are connected\n"); 1164 return 0; 1165 } 1166 1167 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid); 1168 if (new_ns_array == NULL) { 1169 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 1170 return 0; 1171 } 1172 1173 memset(new_ns_array + subsystem->max_nsid, 0, 1174 sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid)); 1175 subsystem->ns = new_ns_array; 1176 subsystem->max_nsid = opts.nsid; 1177 } 1178 1179 ns = calloc(1, sizeof(*ns)); 1180 if (ns == NULL) { 1181 SPDK_ERRLOG("Namespace allocation failed\n"); 1182 return 0; 1183 } 1184 1185 ns->bdev = bdev; 1186 ns->opts = opts; 1187 ns->subsystem = subsystem; 1188 rc = spdk_bdev_open_ext(bdev->name, true, nvmf_ns_event, ns, &ns->desc); 1189 if (rc != 0) { 1190 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 1191 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 1192 free(ns); 1193 return 0; 1194 } 1195 rc = spdk_bdev_module_claim_bdev(bdev, ns->desc, &ns_bdev_module); 1196 if (rc != 0) { 1197 spdk_bdev_close(ns->desc); 1198 free(ns); 1199 return 0; 1200 } 1201 subsystem->ns[opts.nsid - 1] = ns; 1202 ns->nsid = opts.nsid; 1203 TAILQ_INIT(&ns->registrants); 1204 1205 if (ptpl_file) { 1206 rc = nvmf_ns_load_reservation(ptpl_file, &info); 1207 if (!rc) { 1208 rc = nvmf_ns_reservation_restore(ns, &info); 1209 if (rc) { 1210 SPDK_ERRLOG("Subsystem restore reservation failed\n"); 1211 subsystem->ns[opts.nsid - 1] = NULL; 1212 spdk_bdev_close(ns->desc); 1213 free(ns); 1214 return 0; 1215 } 1216 } 1217 ns->ptpl_file = strdup(ptpl_file); 1218 } 1219 1220 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 1221 spdk_nvmf_subsystem_get_nqn(subsystem), 1222 spdk_bdev_get_name(bdev), 1223 opts.nsid); 1224 1225 nvmf_subsystem_ns_changed(subsystem, opts.nsid); 1226 1227 return opts.nsid; 1228 } 1229 1230 static uint32_t 1231 nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 1232 uint32_t prev_nsid) 1233 { 1234 uint32_t nsid; 1235 1236 if (prev_nsid >= subsystem->max_nsid) { 1237 return 0; 1238 } 1239 1240 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 1241 if (subsystem->ns[nsid - 1]) { 1242 return nsid; 1243 } 1244 } 1245 1246 return 0; 1247 } 1248 1249 struct spdk_nvmf_ns * 1250 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 1251 { 1252 uint32_t first_nsid; 1253 1254 first_nsid = nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 1255 return _nvmf_subsystem_get_ns(subsystem, first_nsid); 1256 } 1257 1258 struct spdk_nvmf_ns * 1259 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 1260 struct spdk_nvmf_ns *prev_ns) 1261 { 1262 uint32_t next_nsid; 1263 1264 next_nsid = nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid); 1265 return _nvmf_subsystem_get_ns(subsystem, next_nsid); 1266 } 1267 1268 struct spdk_nvmf_ns * 1269 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 1270 { 1271 return _nvmf_subsystem_get_ns(subsystem, nsid); 1272 } 1273 1274 uint32_t 1275 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 1276 { 1277 return ns->opts.nsid; 1278 } 1279 1280 struct spdk_bdev * 1281 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 1282 { 1283 return ns->bdev; 1284 } 1285 1286 void 1287 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts, 1288 size_t opts_size) 1289 { 1290 memset(opts, 0, opts_size); 1291 memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size)); 1292 } 1293 1294 const char * 1295 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 1296 { 1297 return subsystem->sn; 1298 } 1299 1300 int 1301 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 1302 { 1303 size_t len, max_len; 1304 1305 max_len = sizeof(subsystem->sn) - 1; 1306 len = strlen(sn); 1307 if (len > max_len) { 1308 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 1309 sn, len, max_len); 1310 return -1; 1311 } 1312 1313 if (!nvmf_valid_ascii_string(sn, len)) { 1314 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n"); 1315 SPDK_LOGDUMP(SPDK_LOG_NVMF, "sn", sn, len); 1316 return -1; 1317 } 1318 1319 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 1320 1321 return 0; 1322 } 1323 1324 const char * 1325 spdk_nvmf_subsystem_get_mn(const struct spdk_nvmf_subsystem *subsystem) 1326 { 1327 return subsystem->mn; 1328 } 1329 1330 int 1331 spdk_nvmf_subsystem_set_mn(struct spdk_nvmf_subsystem *subsystem, const char *mn) 1332 { 1333 size_t len, max_len; 1334 1335 if (mn == NULL) { 1336 mn = MODEL_NUMBER_DEFAULT; 1337 } 1338 max_len = sizeof(subsystem->mn) - 1; 1339 len = strlen(mn); 1340 if (len > max_len) { 1341 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid mn \"%s\": length %zu > max %zu\n", 1342 mn, len, max_len); 1343 return -1; 1344 } 1345 1346 if (!nvmf_valid_ascii_string(mn, len)) { 1347 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII mn\n"); 1348 SPDK_LOGDUMP(SPDK_LOG_NVMF, "mn", mn, len); 1349 return -1; 1350 } 1351 1352 snprintf(subsystem->mn, sizeof(subsystem->mn), "%s", mn); 1353 1354 return 0; 1355 } 1356 1357 const char * 1358 spdk_nvmf_subsystem_get_nqn(const struct spdk_nvmf_subsystem *subsystem) 1359 { 1360 return subsystem->subnqn; 1361 } 1362 1363 enum spdk_nvmf_subtype spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 1364 { 1365 return subsystem->subtype; 1366 } 1367 1368 uint32_t 1369 spdk_nvmf_subsystem_get_max_nsid(struct spdk_nvmf_subsystem *subsystem) 1370 { 1371 return subsystem->max_nsid; 1372 } 1373 1374 static uint16_t 1375 nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 1376 { 1377 int count; 1378 1379 /* 1380 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 1381 * before we find one that is unused (or find that all values are in use). 1382 */ 1383 for (count = 0; count < 0xFFF0 - 1; count++) { 1384 subsystem->next_cntlid++; 1385 if (subsystem->next_cntlid >= 0xFFF0) { 1386 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 1387 subsystem->next_cntlid = 1; 1388 } 1389 1390 /* Check if a controller with this cntlid currently exists. */ 1391 if (nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 1392 /* Found unused cntlid */ 1393 return subsystem->next_cntlid; 1394 } 1395 } 1396 1397 /* All valid cntlid values are in use. */ 1398 return 0xFFFF; 1399 } 1400 1401 int 1402 nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 1403 { 1404 ctrlr->cntlid = nvmf_subsystem_gen_cntlid(subsystem); 1405 if (ctrlr->cntlid == 0xFFFF) { 1406 /* Unable to get a cntlid */ 1407 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 1408 return -EBUSY; 1409 } 1410 1411 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1412 1413 return 0; 1414 } 1415 1416 void 1417 nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1418 struct spdk_nvmf_ctrlr *ctrlr) 1419 { 1420 assert(subsystem == ctrlr->subsys); 1421 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1422 } 1423 1424 struct spdk_nvmf_ctrlr * 1425 nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1426 { 1427 struct spdk_nvmf_ctrlr *ctrlr; 1428 1429 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1430 if (ctrlr->cntlid == cntlid) { 1431 return ctrlr; 1432 } 1433 } 1434 1435 return NULL; 1436 } 1437 1438 uint32_t 1439 spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem) 1440 { 1441 return subsystem->max_allowed_nsid; 1442 } 1443 1444 struct _nvmf_ns_registrant { 1445 uint64_t rkey; 1446 char *host_uuid; 1447 }; 1448 1449 struct _nvmf_ns_registrants { 1450 size_t num_regs; 1451 struct _nvmf_ns_registrant reg[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1452 }; 1453 1454 struct _nvmf_ns_reservation { 1455 bool ptpl_activated; 1456 enum spdk_nvme_reservation_type rtype; 1457 uint64_t crkey; 1458 char *bdev_uuid; 1459 char *holder_uuid; 1460 struct _nvmf_ns_registrants regs; 1461 }; 1462 1463 static const struct spdk_json_object_decoder nvmf_ns_pr_reg_decoders[] = { 1464 {"rkey", offsetof(struct _nvmf_ns_registrant, rkey), spdk_json_decode_uint64}, 1465 {"host_uuid", offsetof(struct _nvmf_ns_registrant, host_uuid), spdk_json_decode_string}, 1466 }; 1467 1468 static int 1469 nvmf_decode_ns_pr_reg(const struct spdk_json_val *val, void *out) 1470 { 1471 struct _nvmf_ns_registrant *reg = out; 1472 1473 return spdk_json_decode_object(val, nvmf_ns_pr_reg_decoders, 1474 SPDK_COUNTOF(nvmf_ns_pr_reg_decoders), reg); 1475 } 1476 1477 static int 1478 nvmf_decode_ns_pr_regs(const struct spdk_json_val *val, void *out) 1479 { 1480 struct _nvmf_ns_registrants *regs = out; 1481 1482 return spdk_json_decode_array(val, nvmf_decode_ns_pr_reg, regs->reg, 1483 SPDK_NVMF_MAX_NUM_REGISTRANTS, ®s->num_regs, 1484 sizeof(struct _nvmf_ns_registrant)); 1485 } 1486 1487 static const struct spdk_json_object_decoder nvmf_ns_pr_decoders[] = { 1488 {"ptpl", offsetof(struct _nvmf_ns_reservation, ptpl_activated), spdk_json_decode_bool, true}, 1489 {"rtype", offsetof(struct _nvmf_ns_reservation, rtype), spdk_json_decode_uint32, true}, 1490 {"crkey", offsetof(struct _nvmf_ns_reservation, crkey), spdk_json_decode_uint64, true}, 1491 {"bdev_uuid", offsetof(struct _nvmf_ns_reservation, bdev_uuid), spdk_json_decode_string}, 1492 {"holder_uuid", offsetof(struct _nvmf_ns_reservation, holder_uuid), spdk_json_decode_string, true}, 1493 {"registrants", offsetof(struct _nvmf_ns_reservation, regs), nvmf_decode_ns_pr_regs}, 1494 }; 1495 1496 static int 1497 nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info) 1498 { 1499 FILE *fd; 1500 size_t json_size; 1501 ssize_t values_cnt, rc; 1502 void *json = NULL, *end; 1503 struct spdk_json_val *values = NULL; 1504 struct _nvmf_ns_reservation res = {}; 1505 uint32_t i; 1506 1507 fd = fopen(file, "r"); 1508 /* It's not an error if the file does not exist */ 1509 if (!fd) { 1510 SPDK_NOTICELOG("File %s does not exist\n", file); 1511 return -ENOENT; 1512 } 1513 1514 /* Load all persist file contents into a local buffer */ 1515 json = spdk_posix_file_load(fd, &json_size); 1516 fclose(fd); 1517 if (!json) { 1518 SPDK_ERRLOG("Load persit file %s failed\n", file); 1519 return -ENOMEM; 1520 } 1521 1522 rc = spdk_json_parse(json, json_size, NULL, 0, &end, 0); 1523 if (rc < 0) { 1524 SPDK_NOTICELOG("Parsing JSON configuration failed (%zd)\n", rc); 1525 goto exit; 1526 } 1527 1528 values_cnt = rc; 1529 values = calloc(values_cnt, sizeof(struct spdk_json_val)); 1530 if (values == NULL) { 1531 goto exit; 1532 } 1533 1534 rc = spdk_json_parse(json, json_size, values, values_cnt, &end, 0); 1535 if (rc != values_cnt) { 1536 SPDK_ERRLOG("Parsing JSON configuration failed (%zd)\n", rc); 1537 goto exit; 1538 } 1539 1540 /* Decode json */ 1541 if (spdk_json_decode_object(values, nvmf_ns_pr_decoders, 1542 SPDK_COUNTOF(nvmf_ns_pr_decoders), 1543 &res)) { 1544 SPDK_ERRLOG("Invalid objects in the persist file %s\n", file); 1545 rc = -EINVAL; 1546 goto exit; 1547 } 1548 1549 if (res.regs.num_regs > SPDK_NVMF_MAX_NUM_REGISTRANTS) { 1550 SPDK_ERRLOG("Can only support up to %u registrants\n", SPDK_NVMF_MAX_NUM_REGISTRANTS); 1551 rc = -ERANGE; 1552 goto exit; 1553 } 1554 1555 rc = 0; 1556 info->ptpl_activated = res.ptpl_activated; 1557 info->rtype = res.rtype; 1558 info->crkey = res.crkey; 1559 snprintf(info->bdev_uuid, sizeof(info->bdev_uuid), "%s", res.bdev_uuid); 1560 snprintf(info->holder_uuid, sizeof(info->holder_uuid), "%s", res.holder_uuid); 1561 info->num_regs = res.regs.num_regs; 1562 for (i = 0; i < res.regs.num_regs; i++) { 1563 info->registrants[i].rkey = res.regs.reg[i].rkey; 1564 snprintf(info->registrants[i].host_uuid, sizeof(info->registrants[i].host_uuid), "%s", 1565 res.regs.reg[i].host_uuid); 1566 } 1567 1568 exit: 1569 free(json); 1570 free(values); 1571 free(res.bdev_uuid); 1572 free(res.holder_uuid); 1573 for (i = 0; i < res.regs.num_regs; i++) { 1574 free(res.regs.reg[i].host_uuid); 1575 } 1576 1577 return rc; 1578 } 1579 1580 static bool 1581 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns); 1582 1583 static int 1584 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info) 1585 { 1586 uint32_t i; 1587 struct spdk_nvmf_registrant *reg, *holder = NULL; 1588 struct spdk_uuid bdev_uuid, holder_uuid; 1589 1590 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "NSID %u, PTPL %u, Number of registrants %u\n", 1591 ns->nsid, info->ptpl_activated, info->num_regs); 1592 1593 /* it's not an error */ 1594 if (!info->ptpl_activated || !info->num_regs) { 1595 return 0; 1596 } 1597 1598 spdk_uuid_parse(&bdev_uuid, info->bdev_uuid); 1599 if (spdk_uuid_compare(&bdev_uuid, spdk_bdev_get_uuid(ns->bdev))) { 1600 SPDK_ERRLOG("Existing bdev UUID is not same with configuration file\n"); 1601 return -EINVAL; 1602 } 1603 1604 ns->crkey = info->crkey; 1605 ns->rtype = info->rtype; 1606 ns->ptpl_activated = info->ptpl_activated; 1607 spdk_uuid_parse(&holder_uuid, info->holder_uuid); 1608 1609 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev UUID %s\n", info->bdev_uuid); 1610 if (info->rtype) { 1611 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Holder UUID %s, RTYPE %u, RKEY 0x%"PRIx64"\n", 1612 info->holder_uuid, info->rtype, info->crkey); 1613 } 1614 1615 for (i = 0; i < info->num_regs; i++) { 1616 reg = calloc(1, sizeof(*reg)); 1617 if (!reg) { 1618 return -ENOMEM; 1619 } 1620 spdk_uuid_parse(®->hostid, info->registrants[i].host_uuid); 1621 reg->rkey = info->registrants[i].rkey; 1622 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1623 if (!spdk_uuid_compare(&holder_uuid, ®->hostid)) { 1624 holder = reg; 1625 } 1626 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Registrant RKEY 0x%"PRIx64", Host UUID %s\n", 1627 info->registrants[i].rkey, info->registrants[i].host_uuid); 1628 } 1629 1630 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1631 ns->holder = TAILQ_FIRST(&ns->registrants); 1632 } else { 1633 ns->holder = holder; 1634 } 1635 1636 return 0; 1637 } 1638 1639 static int 1640 nvmf_ns_json_write_cb(void *cb_ctx, const void *data, size_t size) 1641 { 1642 char *file = cb_ctx; 1643 size_t rc; 1644 FILE *fd; 1645 1646 fd = fopen(file, "w"); 1647 if (!fd) { 1648 SPDK_ERRLOG("Can't open file %s for write\n", file); 1649 return -ENOENT; 1650 } 1651 rc = fwrite(data, 1, size, fd); 1652 fclose(fd); 1653 1654 return rc == size ? 0 : -1; 1655 } 1656 1657 static int 1658 nvmf_ns_reservation_update(const char *file, struct spdk_nvmf_reservation_info *info) 1659 { 1660 struct spdk_json_write_ctx *w; 1661 uint32_t i; 1662 int rc = 0; 1663 1664 w = spdk_json_write_begin(nvmf_ns_json_write_cb, (void *)file, 0); 1665 if (w == NULL) { 1666 return -ENOMEM; 1667 } 1668 /* clear the configuration file */ 1669 if (!info->ptpl_activated) { 1670 goto exit; 1671 } 1672 1673 spdk_json_write_object_begin(w); 1674 spdk_json_write_named_bool(w, "ptpl", info->ptpl_activated); 1675 spdk_json_write_named_uint32(w, "rtype", info->rtype); 1676 spdk_json_write_named_uint64(w, "crkey", info->crkey); 1677 spdk_json_write_named_string(w, "bdev_uuid", info->bdev_uuid); 1678 spdk_json_write_named_string(w, "holder_uuid", info->holder_uuid); 1679 1680 spdk_json_write_named_array_begin(w, "registrants"); 1681 for (i = 0; i < info->num_regs; i++) { 1682 spdk_json_write_object_begin(w); 1683 spdk_json_write_named_uint64(w, "rkey", info->registrants[i].rkey); 1684 spdk_json_write_named_string(w, "host_uuid", info->registrants[i].host_uuid); 1685 spdk_json_write_object_end(w); 1686 } 1687 spdk_json_write_array_end(w); 1688 spdk_json_write_object_end(w); 1689 1690 exit: 1691 rc = spdk_json_write_end(w); 1692 return rc; 1693 } 1694 1695 static int 1696 nvmf_ns_update_reservation_info(struct spdk_nvmf_ns *ns) 1697 { 1698 struct spdk_nvmf_reservation_info info; 1699 struct spdk_nvmf_registrant *reg, *tmp; 1700 uint32_t i = 0; 1701 1702 assert(ns != NULL); 1703 1704 if (!ns->bdev || !ns->ptpl_file) { 1705 return 0; 1706 } 1707 1708 memset(&info, 0, sizeof(info)); 1709 spdk_uuid_fmt_lower(info.bdev_uuid, sizeof(info.bdev_uuid), spdk_bdev_get_uuid(ns->bdev)); 1710 1711 if (ns->rtype) { 1712 info.rtype = ns->rtype; 1713 info.crkey = ns->crkey; 1714 if (!nvmf_ns_reservation_all_registrants_type(ns)) { 1715 assert(ns->holder != NULL); 1716 spdk_uuid_fmt_lower(info.holder_uuid, sizeof(info.holder_uuid), &ns->holder->hostid); 1717 } 1718 } 1719 1720 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1721 spdk_uuid_fmt_lower(info.registrants[i].host_uuid, sizeof(info.registrants[i].host_uuid), 1722 ®->hostid); 1723 info.registrants[i++].rkey = reg->rkey; 1724 } 1725 1726 info.num_regs = i; 1727 info.ptpl_activated = ns->ptpl_activated; 1728 1729 return nvmf_ns_reservation_update(ns->ptpl_file, &info); 1730 } 1731 1732 static struct spdk_nvmf_registrant * 1733 nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns, 1734 struct spdk_uuid *uuid) 1735 { 1736 struct spdk_nvmf_registrant *reg, *tmp; 1737 1738 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1739 if (!spdk_uuid_compare(®->hostid, uuid)) { 1740 return reg; 1741 } 1742 } 1743 1744 return NULL; 1745 } 1746 1747 /* Generate reservation notice log to registered HostID controllers */ 1748 static void 1749 nvmf_subsystem_gen_ctrlr_notification(struct spdk_nvmf_subsystem *subsystem, 1750 struct spdk_nvmf_ns *ns, 1751 struct spdk_uuid *hostid_list, 1752 uint32_t num_hostid, 1753 enum spdk_nvme_reservation_notification_log_page_type type) 1754 { 1755 struct spdk_nvmf_ctrlr *ctrlr; 1756 uint32_t i; 1757 1758 for (i = 0; i < num_hostid; i++) { 1759 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1760 if (!spdk_uuid_compare(&ctrlr->hostid, &hostid_list[i])) { 1761 nvmf_ctrlr_reservation_notice_log(ctrlr, ns, type); 1762 } 1763 } 1764 } 1765 } 1766 1767 /* Get all registrants' hostid other than the controller who issued the command */ 1768 static uint32_t 1769 nvmf_ns_reservation_get_all_other_hostid(struct spdk_nvmf_ns *ns, 1770 struct spdk_uuid *hostid_list, 1771 uint32_t max_num_hostid, 1772 struct spdk_uuid *current_hostid) 1773 { 1774 struct spdk_nvmf_registrant *reg, *tmp; 1775 uint32_t num_hostid = 0; 1776 1777 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1778 if (spdk_uuid_compare(®->hostid, current_hostid)) { 1779 if (num_hostid == max_num_hostid) { 1780 assert(false); 1781 return max_num_hostid; 1782 } 1783 hostid_list[num_hostid++] = reg->hostid; 1784 } 1785 } 1786 1787 return num_hostid; 1788 } 1789 1790 /* Calculate the unregistered HostID list according to list 1791 * prior to execute preempt command and list after executing 1792 * preempt command. 1793 */ 1794 static uint32_t 1795 nvmf_ns_reservation_get_unregistered_hostid(struct spdk_uuid *old_hostid_list, 1796 uint32_t old_num_hostid, 1797 struct spdk_uuid *remaining_hostid_list, 1798 uint32_t remaining_num_hostid) 1799 { 1800 struct spdk_uuid temp_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1801 uint32_t i, j, num_hostid = 0; 1802 bool found; 1803 1804 if (!remaining_num_hostid) { 1805 return old_num_hostid; 1806 } 1807 1808 for (i = 0; i < old_num_hostid; i++) { 1809 found = false; 1810 for (j = 0; j < remaining_num_hostid; j++) { 1811 if (!spdk_uuid_compare(&old_hostid_list[i], &remaining_hostid_list[j])) { 1812 found = true; 1813 break; 1814 } 1815 } 1816 if (!found) { 1817 spdk_uuid_copy(&temp_hostid_list[num_hostid++], &old_hostid_list[i]); 1818 } 1819 } 1820 1821 if (num_hostid) { 1822 memcpy(old_hostid_list, temp_hostid_list, sizeof(struct spdk_uuid) * num_hostid); 1823 } 1824 1825 return num_hostid; 1826 } 1827 1828 /* current reservation type is all registrants or not */ 1829 static bool 1830 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns) 1831 { 1832 return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS || 1833 ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); 1834 } 1835 1836 /* current registrant is reservation holder or not */ 1837 static bool 1838 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns, 1839 struct spdk_nvmf_registrant *reg) 1840 { 1841 if (!reg) { 1842 return false; 1843 } 1844 1845 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1846 return true; 1847 } 1848 1849 return (ns->holder == reg); 1850 } 1851 1852 static int 1853 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns, 1854 struct spdk_nvmf_ctrlr *ctrlr, 1855 uint64_t nrkey) 1856 { 1857 struct spdk_nvmf_registrant *reg; 1858 1859 reg = calloc(1, sizeof(*reg)); 1860 if (!reg) { 1861 return -ENOMEM; 1862 } 1863 1864 reg->rkey = nrkey; 1865 /* set hostid for the registrant */ 1866 spdk_uuid_copy(®->hostid, &ctrlr->hostid); 1867 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1868 ns->gen++; 1869 1870 return 0; 1871 } 1872 1873 static void 1874 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns) 1875 { 1876 ns->rtype = 0; 1877 ns->crkey = 0; 1878 ns->holder = NULL; 1879 } 1880 1881 /* release the reservation if the last registrant was removed */ 1882 static void 1883 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns, 1884 struct spdk_nvmf_registrant *reg) 1885 { 1886 struct spdk_nvmf_registrant *next_reg; 1887 1888 /* no reservation holder */ 1889 if (!ns->holder) { 1890 assert(ns->rtype == 0); 1891 return; 1892 } 1893 1894 next_reg = TAILQ_FIRST(&ns->registrants); 1895 if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) { 1896 /* the next valid registrant is the new holder now */ 1897 ns->holder = next_reg; 1898 } else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 1899 /* release the reservation */ 1900 nvmf_ns_reservation_release_reservation(ns); 1901 } 1902 } 1903 1904 static void 1905 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns, 1906 struct spdk_nvmf_registrant *reg) 1907 { 1908 TAILQ_REMOVE(&ns->registrants, reg, link); 1909 nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg); 1910 free(reg); 1911 ns->gen++; 1912 return; 1913 } 1914 1915 static uint32_t 1916 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns, 1917 uint64_t rkey) 1918 { 1919 struct spdk_nvmf_registrant *reg, *tmp; 1920 uint32_t count = 0; 1921 1922 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1923 if (reg->rkey == rkey) { 1924 nvmf_ns_reservation_remove_registrant(ns, reg); 1925 count++; 1926 } 1927 } 1928 return count; 1929 } 1930 1931 static uint32_t 1932 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns, 1933 struct spdk_nvmf_registrant *reg) 1934 { 1935 struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2; 1936 uint32_t count = 0; 1937 1938 TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) { 1939 if (reg_tmp != reg) { 1940 nvmf_ns_reservation_remove_registrant(ns, reg_tmp); 1941 count++; 1942 } 1943 } 1944 return count; 1945 } 1946 1947 static uint32_t 1948 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns) 1949 { 1950 struct spdk_nvmf_registrant *reg, *reg_tmp; 1951 uint32_t count = 0; 1952 1953 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 1954 nvmf_ns_reservation_remove_registrant(ns, reg); 1955 count++; 1956 } 1957 return count; 1958 } 1959 1960 static void 1961 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey, 1962 enum spdk_nvme_reservation_type rtype, 1963 struct spdk_nvmf_registrant *holder) 1964 { 1965 ns->rtype = rtype; 1966 ns->crkey = rkey; 1967 assert(ns->holder == NULL); 1968 ns->holder = holder; 1969 } 1970 1971 static bool 1972 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns, 1973 struct spdk_nvmf_ctrlr *ctrlr, 1974 struct spdk_nvmf_request *req) 1975 { 1976 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1977 uint8_t rrega, iekey, cptpl, rtype; 1978 struct spdk_nvme_reservation_register_data key; 1979 struct spdk_nvmf_registrant *reg; 1980 uint8_t status = SPDK_NVME_SC_SUCCESS; 1981 bool update_sgroup = false; 1982 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1983 uint32_t num_hostid = 0; 1984 int rc; 1985 1986 rrega = cmd->cdw10_bits.resv_register.rrega; 1987 iekey = cmd->cdw10_bits.resv_register.iekey; 1988 cptpl = cmd->cdw10_bits.resv_register.cptpl; 1989 1990 if (req->data && req->length >= sizeof(key)) { 1991 memcpy(&key, req->data, sizeof(key)); 1992 } else { 1993 SPDK_ERRLOG("No key provided. Failing request.\n"); 1994 status = SPDK_NVME_SC_INVALID_FIELD; 1995 goto exit; 1996 } 1997 1998 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, " 1999 "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n", 2000 rrega, iekey, cptpl, key.crkey, key.nrkey); 2001 2002 if (cptpl == SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON) { 2003 /* Ture to OFF state, and need to be updated in the configuration file */ 2004 if (ns->ptpl_activated) { 2005 ns->ptpl_activated = 0; 2006 update_sgroup = true; 2007 } 2008 } else if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) { 2009 if (ns->ptpl_file == NULL) { 2010 status = SPDK_NVME_SC_INVALID_FIELD; 2011 goto exit; 2012 } else if (ns->ptpl_activated == 0) { 2013 ns->ptpl_activated = 1; 2014 update_sgroup = true; 2015 } 2016 } 2017 2018 /* current Host Identifier has registrant or not */ 2019 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 2020 2021 switch (rrega) { 2022 case SPDK_NVME_RESERVE_REGISTER_KEY: 2023 if (!reg) { 2024 /* register new controller */ 2025 if (key.nrkey == 0) { 2026 SPDK_ERRLOG("Can't register zeroed new key\n"); 2027 status = SPDK_NVME_SC_INVALID_FIELD; 2028 goto exit; 2029 } 2030 rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey); 2031 if (rc < 0) { 2032 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2033 goto exit; 2034 } 2035 update_sgroup = true; 2036 } else { 2037 /* register with same key is not an error */ 2038 if (reg->rkey != key.nrkey) { 2039 SPDK_ERRLOG("The same host already register a " 2040 "key with 0x%"PRIx64"\n", 2041 reg->rkey); 2042 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2043 goto exit; 2044 } 2045 } 2046 break; 2047 case SPDK_NVME_RESERVE_UNREGISTER_KEY: 2048 if (!reg || (!iekey && reg->rkey != key.crkey)) { 2049 SPDK_ERRLOG("No registrant or current key doesn't match " 2050 "with existing registrant key\n"); 2051 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2052 goto exit; 2053 } 2054 2055 rtype = ns->rtype; 2056 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 2057 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2058 &ctrlr->hostid); 2059 2060 nvmf_ns_reservation_remove_registrant(ns, reg); 2061 2062 if (!ns->rtype && num_hostid && (rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY || 2063 rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY)) { 2064 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2065 hostid_list, 2066 num_hostid, 2067 SPDK_NVME_RESERVATION_RELEASED); 2068 } 2069 update_sgroup = true; 2070 break; 2071 case SPDK_NVME_RESERVE_REPLACE_KEY: 2072 if (!reg || (!iekey && reg->rkey != key.crkey)) { 2073 SPDK_ERRLOG("No registrant or current key doesn't match " 2074 "with existing registrant key\n"); 2075 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2076 goto exit; 2077 } 2078 if (key.nrkey == 0) { 2079 SPDK_ERRLOG("Can't register zeroed new key\n"); 2080 status = SPDK_NVME_SC_INVALID_FIELD; 2081 goto exit; 2082 } 2083 reg->rkey = key.nrkey; 2084 update_sgroup = true; 2085 break; 2086 default: 2087 status = SPDK_NVME_SC_INVALID_FIELD; 2088 goto exit; 2089 } 2090 2091 exit: 2092 if (update_sgroup) { 2093 rc = nvmf_ns_update_reservation_info(ns); 2094 if (rc != 0) { 2095 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2096 } 2097 } 2098 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2099 req->rsp->nvme_cpl.status.sc = status; 2100 return update_sgroup; 2101 } 2102 2103 static bool 2104 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns, 2105 struct spdk_nvmf_ctrlr *ctrlr, 2106 struct spdk_nvmf_request *req) 2107 { 2108 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2109 uint8_t racqa, iekey, rtype; 2110 struct spdk_nvme_reservation_acquire_data key; 2111 struct spdk_nvmf_registrant *reg; 2112 bool all_regs = false; 2113 uint32_t count = 0; 2114 bool update_sgroup = true; 2115 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 2116 uint32_t num_hostid = 0; 2117 struct spdk_uuid new_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 2118 uint32_t new_num_hostid = 0; 2119 bool reservation_released = false; 2120 uint8_t status = SPDK_NVME_SC_SUCCESS; 2121 2122 racqa = cmd->cdw10_bits.resv_acquire.racqa; 2123 iekey = cmd->cdw10_bits.resv_acquire.iekey; 2124 rtype = cmd->cdw10_bits.resv_acquire.rtype; 2125 2126 if (req->data && req->length >= sizeof(key)) { 2127 memcpy(&key, req->data, sizeof(key)); 2128 } else { 2129 SPDK_ERRLOG("No key provided. Failing request.\n"); 2130 status = SPDK_NVME_SC_INVALID_FIELD; 2131 goto exit; 2132 } 2133 2134 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, " 2135 "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n", 2136 racqa, iekey, rtype, key.crkey, key.prkey); 2137 2138 if (iekey || rtype > SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS) { 2139 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 2140 status = SPDK_NVME_SC_INVALID_FIELD; 2141 update_sgroup = false; 2142 goto exit; 2143 } 2144 2145 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 2146 /* must be registrant and CRKEY must match */ 2147 if (!reg || reg->rkey != key.crkey) { 2148 SPDK_ERRLOG("No registrant or current key doesn't match " 2149 "with existing registrant key\n"); 2150 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2151 update_sgroup = false; 2152 goto exit; 2153 } 2154 2155 all_regs = nvmf_ns_reservation_all_registrants_type(ns); 2156 2157 switch (racqa) { 2158 case SPDK_NVME_RESERVE_ACQUIRE: 2159 /* it's not an error for the holder to acquire same reservation type again */ 2160 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) { 2161 /* do nothing */ 2162 update_sgroup = false; 2163 } else if (ns->holder == NULL) { 2164 /* fisrt time to acquire the reservation */ 2165 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 2166 } else { 2167 SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n"); 2168 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2169 update_sgroup = false; 2170 goto exit; 2171 } 2172 break; 2173 case SPDK_NVME_RESERVE_PREEMPT: 2174 /* no reservation holder */ 2175 if (!ns->holder) { 2176 /* unregister with PRKEY */ 2177 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2178 break; 2179 } 2180 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 2181 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2182 &ctrlr->hostid); 2183 2184 /* only 1 reservation holder and reservation key is valid */ 2185 if (!all_regs) { 2186 /* preempt itself */ 2187 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && 2188 ns->crkey == key.prkey) { 2189 ns->rtype = rtype; 2190 reservation_released = true; 2191 break; 2192 } 2193 2194 if (ns->crkey == key.prkey) { 2195 nvmf_ns_reservation_remove_registrant(ns, ns->holder); 2196 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 2197 reservation_released = true; 2198 } else if (key.prkey != 0) { 2199 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2200 } else { 2201 /* PRKEY is zero */ 2202 SPDK_ERRLOG("Current PRKEY is zero\n"); 2203 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2204 update_sgroup = false; 2205 goto exit; 2206 } 2207 } else { 2208 /* release all other registrants except for the current one */ 2209 if (key.prkey == 0) { 2210 nvmf_ns_reservation_remove_all_other_registrants(ns, reg); 2211 assert(ns->holder == reg); 2212 } else { 2213 count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2214 if (count == 0) { 2215 SPDK_ERRLOG("PRKEY doesn't match any registrant\n"); 2216 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2217 update_sgroup = false; 2218 goto exit; 2219 } 2220 } 2221 } 2222 break; 2223 default: 2224 status = SPDK_NVME_SC_INVALID_FIELD; 2225 update_sgroup = false; 2226 break; 2227 } 2228 2229 exit: 2230 if (update_sgroup && racqa == SPDK_NVME_RESERVE_PREEMPT) { 2231 new_num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, new_hostid_list, 2232 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2233 &ctrlr->hostid); 2234 /* Preempt notification occurs on the unregistered controllers 2235 * other than the controller who issued the command. 2236 */ 2237 num_hostid = nvmf_ns_reservation_get_unregistered_hostid(hostid_list, 2238 num_hostid, 2239 new_hostid_list, 2240 new_num_hostid); 2241 if (num_hostid) { 2242 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2243 hostid_list, 2244 num_hostid, 2245 SPDK_NVME_REGISTRATION_PREEMPTED); 2246 2247 } 2248 /* Reservation released notification occurs on the 2249 * controllers which are the remaining registrants other than 2250 * the controller who issued the command. 2251 */ 2252 if (reservation_released && new_num_hostid) { 2253 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2254 new_hostid_list, 2255 new_num_hostid, 2256 SPDK_NVME_RESERVATION_RELEASED); 2257 2258 } 2259 } 2260 if (update_sgroup && ns->ptpl_activated) { 2261 if (nvmf_ns_update_reservation_info(ns)) { 2262 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2263 } 2264 } 2265 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2266 req->rsp->nvme_cpl.status.sc = status; 2267 return update_sgroup; 2268 } 2269 2270 static bool 2271 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns, 2272 struct spdk_nvmf_ctrlr *ctrlr, 2273 struct spdk_nvmf_request *req) 2274 { 2275 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2276 uint8_t rrela, iekey, rtype; 2277 struct spdk_nvmf_registrant *reg; 2278 uint64_t crkey; 2279 uint8_t status = SPDK_NVME_SC_SUCCESS; 2280 bool update_sgroup = true; 2281 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 2282 uint32_t num_hostid = 0; 2283 2284 rrela = cmd->cdw10_bits.resv_release.rrela; 2285 iekey = cmd->cdw10_bits.resv_release.iekey; 2286 rtype = cmd->cdw10_bits.resv_release.rtype; 2287 2288 if (req->data && req->length >= sizeof(crkey)) { 2289 memcpy(&crkey, req->data, sizeof(crkey)); 2290 } else { 2291 SPDK_ERRLOG("No key provided. Failing request.\n"); 2292 status = SPDK_NVME_SC_INVALID_FIELD; 2293 goto exit; 2294 } 2295 2296 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, " 2297 "CRKEY 0x%"PRIx64"\n", rrela, iekey, rtype, crkey); 2298 2299 if (iekey) { 2300 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 2301 status = SPDK_NVME_SC_INVALID_FIELD; 2302 update_sgroup = false; 2303 goto exit; 2304 } 2305 2306 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 2307 if (!reg || reg->rkey != crkey) { 2308 SPDK_ERRLOG("No registrant or current key doesn't match " 2309 "with existing registrant key\n"); 2310 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2311 update_sgroup = false; 2312 goto exit; 2313 } 2314 2315 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 2316 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2317 &ctrlr->hostid); 2318 2319 switch (rrela) { 2320 case SPDK_NVME_RESERVE_RELEASE: 2321 if (!ns->holder) { 2322 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n"); 2323 update_sgroup = false; 2324 goto exit; 2325 } 2326 if (ns->rtype != rtype) { 2327 SPDK_ERRLOG("Type doesn't match\n"); 2328 status = SPDK_NVME_SC_INVALID_FIELD; 2329 update_sgroup = false; 2330 goto exit; 2331 } 2332 if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 2333 /* not the reservation holder, this isn't an error */ 2334 update_sgroup = false; 2335 goto exit; 2336 } 2337 2338 rtype = ns->rtype; 2339 nvmf_ns_reservation_release_reservation(ns); 2340 2341 if (num_hostid && rtype != SPDK_NVME_RESERVE_WRITE_EXCLUSIVE && 2342 rtype != SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS) { 2343 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2344 hostid_list, 2345 num_hostid, 2346 SPDK_NVME_RESERVATION_RELEASED); 2347 } 2348 break; 2349 case SPDK_NVME_RESERVE_CLEAR: 2350 nvmf_ns_reservation_clear_all_registrants(ns); 2351 if (num_hostid) { 2352 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2353 hostid_list, 2354 num_hostid, 2355 SPDK_NVME_RESERVATION_PREEMPTED); 2356 } 2357 break; 2358 default: 2359 status = SPDK_NVME_SC_INVALID_FIELD; 2360 update_sgroup = false; 2361 goto exit; 2362 } 2363 2364 exit: 2365 if (update_sgroup && ns->ptpl_activated) { 2366 if (nvmf_ns_update_reservation_info(ns)) { 2367 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2368 } 2369 } 2370 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2371 req->rsp->nvme_cpl.status.sc = status; 2372 return update_sgroup; 2373 } 2374 2375 static void 2376 nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns, 2377 struct spdk_nvmf_ctrlr *ctrlr, 2378 struct spdk_nvmf_request *req) 2379 { 2380 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2381 struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; 2382 struct spdk_nvmf_ctrlr *ctrlr_tmp; 2383 struct spdk_nvmf_registrant *reg, *tmp; 2384 struct spdk_nvme_reservation_status_extended_data *status_data; 2385 struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data; 2386 uint8_t *payload; 2387 uint32_t len, count = 0; 2388 uint32_t regctl = 0; 2389 uint8_t status = SPDK_NVME_SC_SUCCESS; 2390 2391 if (req->data == NULL) { 2392 SPDK_ERRLOG("No data transfer specified for request. " 2393 " Unable to transfer back response.\n"); 2394 status = SPDK_NVME_SC_INVALID_FIELD; 2395 goto exit; 2396 } 2397 2398 if (!cmd->cdw11_bits.resv_report.eds) { 2399 SPDK_ERRLOG("NVMeoF uses extended controller data structure, " 2400 "please set EDS bit in cdw11 and try again\n"); 2401 status = SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT; 2402 goto exit; 2403 } 2404 2405 /* Get number of registerd controllers, one Host may have more than 2406 * one controller based on different ports. 2407 */ 2408 TAILQ_FOREACH(ctrlr_tmp, &subsystem->ctrlrs, link) { 2409 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr_tmp->hostid); 2410 if (reg) { 2411 regctl++; 2412 } 2413 } 2414 2415 len = sizeof(*status_data) + sizeof(*ctrlr_data) * regctl; 2416 payload = calloc(1, len); 2417 if (!payload) { 2418 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2419 goto exit; 2420 } 2421 2422 status_data = (struct spdk_nvme_reservation_status_extended_data *)payload; 2423 status_data->data.gen = ns->gen; 2424 status_data->data.rtype = ns->rtype; 2425 status_data->data.regctl = regctl; 2426 status_data->data.ptpls = ns->ptpl_activated; 2427 2428 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 2429 assert(count <= regctl); 2430 ctrlr_data = (struct spdk_nvme_registered_ctrlr_extended_data *) 2431 (payload + sizeof(*status_data) + sizeof(*ctrlr_data) * count); 2432 /* Set to 0xffffh for dynamic controller */ 2433 ctrlr_data->cntlid = 0xffff; 2434 ctrlr_data->rcsts.status = (ns->holder == reg) ? true : false; 2435 ctrlr_data->rkey = reg->rkey; 2436 spdk_uuid_copy((struct spdk_uuid *)ctrlr_data->hostid, ®->hostid); 2437 count++; 2438 } 2439 2440 memcpy(req->data, payload, spdk_min(len, (cmd->cdw10 + 1) * sizeof(uint32_t))); 2441 free(payload); 2442 2443 exit: 2444 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2445 req->rsp->nvme_cpl.status.sc = status; 2446 return; 2447 } 2448 2449 static void 2450 nvmf_ns_reservation_complete(void *ctx) 2451 { 2452 struct spdk_nvmf_request *req = ctx; 2453 2454 spdk_nvmf_request_complete(req); 2455 } 2456 2457 static void 2458 _nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem, 2459 void *cb_arg, int status) 2460 { 2461 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg; 2462 struct spdk_nvmf_poll_group *group = req->qpair->group; 2463 2464 spdk_thread_send_msg(group->thread, nvmf_ns_reservation_complete, req); 2465 } 2466 2467 void 2468 nvmf_ns_reservation_request(void *ctx) 2469 { 2470 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx; 2471 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2472 struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; 2473 struct subsystem_update_ns_ctx *update_ctx; 2474 uint32_t nsid; 2475 struct spdk_nvmf_ns *ns; 2476 bool update_sgroup = false; 2477 2478 nsid = cmd->nsid; 2479 ns = _nvmf_subsystem_get_ns(ctrlr->subsys, nsid); 2480 assert(ns != NULL); 2481 2482 switch (cmd->opc) { 2483 case SPDK_NVME_OPC_RESERVATION_REGISTER: 2484 update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req); 2485 break; 2486 case SPDK_NVME_OPC_RESERVATION_ACQUIRE: 2487 update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req); 2488 break; 2489 case SPDK_NVME_OPC_RESERVATION_RELEASE: 2490 update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req); 2491 break; 2492 case SPDK_NVME_OPC_RESERVATION_REPORT: 2493 nvmf_ns_reservation_report(ns, ctrlr, req); 2494 break; 2495 default: 2496 break; 2497 } 2498 2499 /* update reservation information to subsystem's poll group */ 2500 if (update_sgroup) { 2501 update_ctx = calloc(1, sizeof(*update_ctx)); 2502 if (update_ctx == NULL) { 2503 SPDK_ERRLOG("Can't alloc subsystem poll group update context\n"); 2504 goto update_done; 2505 } 2506 update_ctx->subsystem = ctrlr->subsys; 2507 update_ctx->cb_fn = _nvmf_ns_reservation_update_done; 2508 update_ctx->cb_arg = req; 2509 2510 nvmf_subsystem_update_ns(ctrlr->subsys, subsystem_update_ns_done, update_ctx); 2511 return; 2512 } 2513 2514 update_done: 2515 _nvmf_ns_reservation_update_done(ctrlr->subsys, (void *)req, 0); 2516 } 2517