1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "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 45 #include "spdk_internal/bdev.h" 46 #include "spdk_internal/log.h" 47 #include "spdk_internal/utf.h" 48 49 #include <uuid/uuid.h> 50 51 /* 52 * States for parsing valid domains in NQNs according to RFC 1034 53 */ 54 enum spdk_nvmf_nqn_domain_states { 55 /* First character of a domain must be a letter */ 56 SPDK_NVMF_DOMAIN_ACCEPT_LETTER = 0, 57 58 /* Subsequent characters can be any of letter, digit, or hyphen */ 59 SPDK_NVMF_DOMAIN_ACCEPT_LDH = 1, 60 61 /* A domain label must end with either a letter or digit */ 62 SPDK_NVMF_DOMAIN_ACCEPT_ANY = 2 63 }; 64 65 static bool 66 spdk_nvmf_valid_nqn(const char *nqn) 67 { 68 size_t len; 69 uuid_t uuid_value; 70 uint i; 71 int bytes_consumed; 72 uint domain_label_length; 73 char *reverse_domain_end; 74 uint reverse_domain_end_index; 75 enum spdk_nvmf_nqn_domain_states domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER; 76 77 /* Check for length requirements */ 78 len = strlen(nqn); 79 if (len > SPDK_NVMF_NQN_MAX_LEN) { 80 SPDK_ERRLOG("Invalid NQN \"%s\": length %zu > max %d\n", nqn, len, SPDK_NVMF_NQN_MAX_LEN); 81 return false; 82 } 83 84 /* The nqn must be at least as long as SPDK_NVMF_NQN_MIN_LEN to contain the necessary prefix. */ 85 if (len < SPDK_NVMF_NQN_MIN_LEN) { 86 SPDK_ERRLOG("Invalid NQN \"%s\": length %zu < min %d\n", nqn, len, SPDK_NVMF_NQN_MIN_LEN); 87 return false; 88 } 89 90 /* Check for discovery controller nqn */ 91 if (!strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN)) { 92 return true; 93 } 94 95 /* Check for equality with the generic nqn structure of the form "nqn.2014-08.org.nvmexpress:uuid:11111111-2222-3333-4444-555555555555" */ 96 if (!strncmp(nqn, SPDK_NVMF_NQN_UUID_PRE, SPDK_NVMF_NQN_UUID_PRE_LEN)) { 97 if (len != SPDK_NVMF_NQN_UUID_PRE_LEN + SPDK_NVMF_UUID_STRING_LEN) { 98 SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not the correct length\n", nqn); 99 return false; 100 } 101 102 if (uuid_parse(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid_value) == -1) { 103 SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not formatted correctly\n", nqn); 104 return false; 105 } 106 return true; 107 } 108 109 /* If the nqn does not match the uuid structure, the next several checks validate the form "nqn.yyyy-mm.reverse.domain:user-string" */ 110 111 if (strncmp(nqn, "nqn.", 4) != 0) { 112 SPDK_ERRLOG("Invalid NQN \"%s\": NQN must begin with \"nqn.\".\n", nqn); 113 return false; 114 } 115 116 /* Check for yyyy-mm. */ 117 if (!(isdigit(nqn[4]) && isdigit(nqn[5]) && isdigit(nqn[6]) && isdigit(nqn[7]) && 118 nqn[8] == '-' && isdigit(nqn[9]) && isdigit(nqn[10]) && nqn[11] == '.')) { 119 SPDK_ERRLOG("Invalid date code in NQN \"%s\"\n", nqn); 120 return false; 121 } 122 123 reverse_domain_end = strchr(nqn, ':'); 124 if (reverse_domain_end != NULL && (reverse_domain_end_index = reverse_domain_end - nqn) < len - 1) { 125 } else { 126 SPDK_ERRLOG("Invalid NQN \"%s\". NQN must contain user specified name with a ':' as a prefix.\n", 127 nqn); 128 return false; 129 } 130 131 /* Check for valid reverse domain */ 132 domain_label_length = 0; 133 for (i = 12; i < reverse_domain_end_index; i++) { 134 if (domain_label_length > SPDK_DOMAIN_LABEL_MAX_LEN) { 135 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". At least one Label is too long.\n", nqn); 136 return false; 137 } 138 139 switch (domain_state) { 140 141 case SPDK_NVMF_DOMAIN_ACCEPT_LETTER: { 142 if (isalpha(nqn[i])) { 143 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY; 144 domain_label_length++; 145 break; 146 } else { 147 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must start with a letter.\n", nqn); 148 return false; 149 } 150 } 151 152 case SPDK_NVMF_DOMAIN_ACCEPT_LDH: { 153 if (isalpha(nqn[i]) || isdigit(nqn[i])) { 154 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY; 155 domain_label_length++; 156 break; 157 } else if (nqn[i] == '-') { 158 if (i == reverse_domain_end_index - 1) { 159 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n", 160 nqn); 161 return false; 162 } 163 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH; 164 domain_label_length++; 165 break; 166 } else if (nqn[i] == '.') { 167 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n", 168 nqn); 169 return false; 170 } else { 171 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n", 172 nqn); 173 return false; 174 } 175 } 176 177 case SPDK_NVMF_DOMAIN_ACCEPT_ANY: { 178 if (isalpha(nqn[i]) || isdigit(nqn[i])) { 179 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY; 180 domain_label_length++; 181 break; 182 } else if (nqn[i] == '-') { 183 if (i == reverse_domain_end_index - 1) { 184 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n", 185 nqn); 186 return false; 187 } 188 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH; 189 domain_label_length++; 190 break; 191 } else if (nqn[i] == '.') { 192 domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER; 193 domain_label_length = 0; 194 break; 195 } else { 196 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n", 197 nqn); 198 return false; 199 } 200 } 201 } 202 } 203 204 i = reverse_domain_end_index + 1; 205 while (i < len) { 206 bytes_consumed = utf8_valid(&nqn[i], &nqn[len]); 207 if (bytes_consumed <= 0) { 208 SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only valid utf-8.\n", nqn); 209 return false; 210 } 211 212 i += bytes_consumed; 213 } 214 return true; 215 } 216 217 struct spdk_nvmf_subsystem * 218 spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt, 219 const char *nqn, 220 enum spdk_nvmf_subtype type, 221 uint32_t num_ns) 222 { 223 struct spdk_nvmf_subsystem *subsystem; 224 uint32_t sid; 225 226 if (!spdk_nvmf_valid_nqn(nqn)) { 227 return NULL; 228 } 229 230 if (type == SPDK_NVMF_SUBTYPE_DISCOVERY && num_ns != 0) { 231 SPDK_ERRLOG("Discovery subsystem cannot have namespaces.\n"); 232 return NULL; 233 } 234 235 /* Find a free subsystem id (sid) */ 236 for (sid = 0; sid < tgt->max_sid; sid++) { 237 if (tgt->subsystems[sid] == NULL) { 238 break; 239 } 240 } 241 if (sid == tgt->max_sid) { 242 struct spdk_nvmf_subsystem **subsys_array; 243 /* No free slots. Add more. */ 244 tgt->max_sid++; 245 subsys_array = realloc(tgt->subsystems, tgt->max_sid * sizeof(struct spdk_nvmf_subsystem *)); 246 if (!subsys_array) { 247 tgt->max_sid--; 248 return NULL; 249 } 250 tgt->subsystems = subsys_array; 251 } 252 253 subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem)); 254 if (subsystem == NULL) { 255 return NULL; 256 } 257 258 subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 259 subsystem->tgt = tgt; 260 subsystem->id = sid; 261 subsystem->subtype = type; 262 subsystem->max_nsid = num_ns; 263 subsystem->num_allocated_nsid = 0; 264 subsystem->next_cntlid = 0; 265 snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn); 266 TAILQ_INIT(&subsystem->listeners); 267 TAILQ_INIT(&subsystem->hosts); 268 TAILQ_INIT(&subsystem->ctrlrs); 269 270 if (num_ns != 0) { 271 subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *)); 272 if (subsystem->ns == NULL) { 273 SPDK_ERRLOG("Namespace memory allocation failed\n"); 274 free(subsystem); 275 return NULL; 276 } 277 } 278 279 tgt->subsystems[sid] = subsystem; 280 tgt->discovery_genctr++; 281 282 return subsystem; 283 } 284 285 void 286 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem) 287 { 288 struct spdk_nvmf_listener *listener, *listener_tmp; 289 struct spdk_nvmf_host *host, *host_tmp; 290 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 291 struct spdk_nvmf_ns *ns; 292 293 if (!subsystem) { 294 return; 295 } 296 297 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 298 299 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem); 300 301 TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) { 302 TAILQ_REMOVE(&subsystem->listeners, listener, link); 303 free(listener); 304 } 305 306 TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) { 307 TAILQ_REMOVE(&subsystem->hosts, host, link); 308 free(host->nqn); 309 free(host); 310 } 311 312 TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) { 313 spdk_nvmf_ctrlr_destruct(ctrlr); 314 } 315 316 ns = spdk_nvmf_subsystem_get_first_ns(subsystem); 317 while (ns != NULL) { 318 struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns); 319 320 spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 321 ns = next_ns; 322 } 323 324 free(subsystem->ns); 325 326 subsystem->tgt->subsystems[subsystem->id] = NULL; 327 subsystem->tgt->discovery_genctr++; 328 329 free(subsystem); 330 } 331 332 static int 333 spdk_nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem, 334 enum spdk_nvmf_subsystem_state state) 335 { 336 enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state; 337 338 switch (state) { 339 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 340 expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 341 break; 342 case SPDK_NVMF_SUBSYSTEM_ACTIVATING: 343 expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 344 break; 345 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 346 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 347 break; 348 case SPDK_NVMF_SUBSYSTEM_PAUSING: 349 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 350 break; 351 case SPDK_NVMF_SUBSYSTEM_PAUSED: 352 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 353 break; 354 case SPDK_NVMF_SUBSYSTEM_RESUMING: 355 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED; 356 break; 357 case SPDK_NVMF_SUBSYSTEM_DEACTIVATING: 358 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 359 break; 360 default: 361 assert(false); 362 return -1; 363 } 364 365 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 366 if (actual_old_state != expected_old_state) { 367 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING && 368 state == SPDK_NVMF_SUBSYSTEM_ACTIVE) { 369 expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 370 } 371 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 372 } 373 assert(actual_old_state == expected_old_state); 374 return actual_old_state - expected_old_state; 375 } 376 377 struct subsystem_state_change_ctx { 378 struct spdk_nvmf_subsystem *subsystem; 379 380 enum spdk_nvmf_subsystem_state requested_state; 381 382 spdk_nvmf_subsystem_state_change_done cb_fn; 383 void *cb_arg; 384 }; 385 386 static void 387 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status) 388 { 389 struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 390 391 if (status == 0) { 392 status = spdk_nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state); 393 if (status) { 394 status = -1; 395 } 396 } 397 398 if (ctx->cb_fn) { 399 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 400 } 401 free(ctx); 402 } 403 404 static void 405 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i) 406 { 407 struct subsystem_state_change_ctx *ctx; 408 struct spdk_io_channel *ch; 409 struct spdk_nvmf_poll_group *group; 410 int rc = -1; 411 412 ctx = spdk_io_channel_iter_get_ctx(i); 413 ch = spdk_io_channel_iter_get_channel(i); 414 group = spdk_io_channel_get_ctx(ch); 415 416 switch (ctx->requested_state) { 417 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 418 rc = spdk_nvmf_poll_group_remove_subsystem(group, ctx->subsystem); 419 break; 420 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 421 if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) { 422 rc = spdk_nvmf_poll_group_add_subsystem(group, ctx->subsystem); 423 } else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) { 424 rc = spdk_nvmf_poll_group_resume_subsystem(group, ctx->subsystem); 425 } 426 break; 427 case SPDK_NVMF_SUBSYSTEM_PAUSED: 428 rc = spdk_nvmf_poll_group_pause_subsystem(group, ctx->subsystem); 429 break; 430 default: 431 assert(false); 432 break; 433 } 434 435 spdk_for_each_channel_continue(i, rc); 436 } 437 438 static int 439 spdk_nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem, 440 enum spdk_nvmf_subsystem_state requested_state, 441 spdk_nvmf_subsystem_state_change_done cb_fn, 442 void *cb_arg) 443 { 444 struct subsystem_state_change_ctx *ctx; 445 enum spdk_nvmf_subsystem_state intermediate_state; 446 int rc; 447 448 switch (requested_state) { 449 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 450 intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 451 break; 452 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 453 if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) { 454 intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 455 } else { 456 intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 457 } 458 break; 459 case SPDK_NVMF_SUBSYSTEM_PAUSED: 460 intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 461 break; 462 default: 463 assert(false); 464 return -EINVAL; 465 } 466 467 ctx = calloc(1, sizeof(*ctx)); 468 if (!ctx) { 469 return -ENOMEM; 470 } 471 472 rc = spdk_nvmf_subsystem_set_state(subsystem, intermediate_state); 473 if (rc) { 474 free(ctx); 475 return rc; 476 } 477 478 ctx->subsystem = subsystem; 479 ctx->requested_state = requested_state; 480 ctx->cb_fn = cb_fn; 481 ctx->cb_arg = cb_arg; 482 483 spdk_for_each_channel(subsystem->tgt, 484 subsystem_state_change_on_pg, 485 ctx, 486 subsystem_state_change_done); 487 488 return 0; 489 } 490 491 int 492 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem, 493 spdk_nvmf_subsystem_state_change_done cb_fn, 494 void *cb_arg) 495 { 496 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 497 } 498 499 int 500 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem, 501 spdk_nvmf_subsystem_state_change_done cb_fn, 502 void *cb_arg) 503 { 504 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg); 505 } 506 507 int 508 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem, 509 spdk_nvmf_subsystem_state_change_done cb_fn, 510 void *cb_arg) 511 { 512 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg); 513 } 514 515 int 516 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem, 517 spdk_nvmf_subsystem_state_change_done cb_fn, 518 void *cb_arg) 519 { 520 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 521 } 522 523 struct spdk_nvmf_subsystem * 524 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt) 525 { 526 struct spdk_nvmf_subsystem *subsystem; 527 uint32_t sid; 528 529 for (sid = 0; sid < tgt->max_sid; sid++) { 530 subsystem = tgt->subsystems[sid]; 531 if (subsystem) { 532 return subsystem; 533 } 534 } 535 536 return NULL; 537 } 538 539 struct spdk_nvmf_subsystem * 540 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem) 541 { 542 uint32_t sid; 543 struct spdk_nvmf_tgt *tgt; 544 545 if (!subsystem) { 546 return NULL; 547 } 548 549 tgt = subsystem->tgt; 550 551 for (sid = subsystem->id + 1; sid < tgt->max_sid; sid++) { 552 subsystem = tgt->subsystems[sid]; 553 if (subsystem) { 554 return subsystem; 555 } 556 } 557 558 return NULL; 559 } 560 561 int 562 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 563 { 564 struct spdk_nvmf_host *host; 565 566 if (!spdk_nvmf_valid_nqn(hostnqn)) { 567 return -EINVAL; 568 } 569 570 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 571 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 572 return -EAGAIN; 573 } 574 575 host = calloc(1, sizeof(*host)); 576 if (!host) { 577 return -ENOMEM; 578 } 579 host->nqn = strdup(hostnqn); 580 if (!host->nqn) { 581 free(host); 582 return -ENOMEM; 583 } 584 585 TAILQ_INSERT_HEAD(&subsystem->hosts, host, link); 586 subsystem->tgt->discovery_genctr++; 587 588 return 0; 589 } 590 591 int 592 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host) 593 { 594 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 595 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 596 return -EAGAIN; 597 } 598 599 subsystem->allow_any_host = allow_any_host; 600 601 return 0; 602 } 603 604 bool 605 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem) 606 { 607 return subsystem->allow_any_host; 608 } 609 610 bool 611 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 612 { 613 struct spdk_nvmf_host *host; 614 615 if (!hostnqn) { 616 return false; 617 } 618 619 if (subsystem->allow_any_host) { 620 return true; 621 } 622 623 TAILQ_FOREACH(host, &subsystem->hosts, link) { 624 if (strcmp(hostnqn, host->nqn) == 0) { 625 return true; 626 } 627 } 628 629 return false; 630 } 631 632 struct spdk_nvmf_host * 633 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem) 634 { 635 return TAILQ_FIRST(&subsystem->hosts); 636 } 637 638 639 struct spdk_nvmf_host * 640 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem, 641 struct spdk_nvmf_host *prev_host) 642 { 643 return TAILQ_NEXT(prev_host, link); 644 } 645 646 const char * 647 spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host) 648 { 649 return host->nqn; 650 } 651 652 static struct spdk_nvmf_listener * 653 _spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, 654 const struct spdk_nvme_transport_id *trid) 655 { 656 struct spdk_nvmf_listener *listener; 657 658 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 659 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 660 return listener; 661 } 662 } 663 664 return NULL; 665 } 666 667 int 668 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, 669 struct spdk_nvme_transport_id *trid) 670 { 671 struct spdk_nvmf_transport *transport; 672 struct spdk_nvmf_listener *listener; 673 674 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 675 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 676 return -EAGAIN; 677 } 678 679 if (_spdk_nvmf_subsystem_find_listener(subsystem, trid)) { 680 /* Listener already exists in this subsystem */ 681 return 0; 682 } 683 684 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype); 685 if (transport == NULL) { 686 SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype); 687 return -EINVAL; 688 } 689 690 listener = calloc(1, sizeof(*listener)); 691 if (!listener) { 692 return -ENOMEM; 693 } 694 695 listener->trid = *trid; 696 listener->transport = transport; 697 698 TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link); 699 700 return 0; 701 } 702 703 int 704 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, 705 const struct spdk_nvme_transport_id *trid) 706 { 707 struct spdk_nvmf_listener *listener; 708 709 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 710 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 711 return -EAGAIN; 712 } 713 714 listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid); 715 if (listener == NULL) { 716 return -ENOENT; 717 } 718 719 TAILQ_REMOVE(&subsystem->listeners, listener, link); 720 free(listener); 721 722 return 0; 723 } 724 725 /* 726 * TODO: this is the whitelist and will be called during connection setup 727 */ 728 bool 729 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, 730 struct spdk_nvme_transport_id *trid) 731 { 732 struct spdk_nvmf_listener *listener; 733 734 if (TAILQ_EMPTY(&subsystem->listeners)) { 735 return true; 736 } 737 738 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 739 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 740 return true; 741 } 742 } 743 744 return false; 745 } 746 747 struct spdk_nvmf_listener * 748 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem) 749 { 750 return TAILQ_FIRST(&subsystem->listeners); 751 } 752 753 struct spdk_nvmf_listener * 754 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem, 755 struct spdk_nvmf_listener *prev_listener) 756 { 757 return TAILQ_NEXT(prev_listener, link); 758 } 759 760 761 const struct spdk_nvme_transport_id * 762 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener) 763 { 764 return &listener->trid; 765 } 766 767 int 768 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 769 { 770 struct spdk_nvmf_ns *ns; 771 772 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED || 773 subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 774 775 if (nsid == 0 || nsid > subsystem->max_nsid) { 776 return -1; 777 } 778 779 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 780 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 781 return -1; 782 } 783 784 ns = subsystem->ns[nsid - 1]; 785 if (!ns) { 786 return -1; 787 } 788 789 subsystem->ns[nsid - 1] = NULL; 790 791 spdk_bdev_close(ns->desc); 792 free(ns); 793 subsystem->num_allocated_nsid--; 794 795 return 0; 796 } 797 798 static void 799 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 800 void *cb_arg, int status) 801 { 802 struct spdk_nvmf_ns *ns = cb_arg; 803 804 spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 805 806 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 807 } 808 809 static void 810 spdk_nvmf_ns_hot_remove(void *remove_ctx) 811 { 812 struct spdk_nvmf_ns *ns = remove_ctx; 813 int rc; 814 815 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns); 816 if (rc) { 817 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 818 } 819 } 820 821 void 822 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size) 823 { 824 /* All current fields are set to 0 by default. */ 825 memset(opts, 0, opts_size); 826 } 827 828 uint32_t 829 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 830 const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size) 831 { 832 struct spdk_nvmf_ns_opts opts; 833 struct spdk_nvmf_ns *ns; 834 uint32_t i; 835 int rc; 836 837 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 838 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 839 return 0; 840 } 841 842 spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts)); 843 if (user_opts) { 844 memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size)); 845 } 846 847 if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) { 848 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid); 849 return 0; 850 } 851 852 if (opts.nsid > subsystem->max_nsid || 853 (opts.nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) { 854 struct spdk_nvmf_ns **new_ns_array; 855 uint32_t new_max_nsid; 856 857 if (opts.nsid > subsystem->max_nsid) { 858 new_max_nsid = opts.nsid; 859 } else { 860 new_max_nsid = subsystem->max_nsid + 1; 861 } 862 863 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 864 SPDK_ERRLOG("Can't extend NSID range with active connections\n"); 865 return 0; 866 } 867 868 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * new_max_nsid); 869 if (new_ns_array == NULL) { 870 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 871 return 0; 872 } 873 874 memset(new_ns_array + subsystem->max_nsid, 0, 875 sizeof(struct spdk_nvmf_ns *) * (new_max_nsid - subsystem->max_nsid)); 876 subsystem->ns = new_ns_array; 877 subsystem->max_nsid = new_max_nsid; 878 } 879 880 if (opts.nsid == 0) { 881 /* NSID not specified - find a free index */ 882 for (i = 0; i < subsystem->max_nsid; i++) { 883 if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) { 884 opts.nsid = i + 1; 885 break; 886 } 887 } 888 if (opts.nsid == 0) { 889 SPDK_ERRLOG("All available NSIDs in use\n"); 890 return 0; 891 } 892 } else { 893 /* Specific NSID requested */ 894 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) { 895 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid); 896 return 0; 897 } 898 } 899 900 ns = calloc(1, sizeof(*ns)); 901 if (ns == NULL) { 902 SPDK_ERRLOG("Namespace allocation failed\n"); 903 return 0; 904 } 905 906 ns->bdev = bdev; 907 ns->opts = opts; 908 ns->subsystem = subsystem; 909 rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc); 910 if (rc != 0) { 911 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 912 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 913 free(ns); 914 return 0; 915 } 916 subsystem->ns[opts.nsid - 1] = ns; 917 918 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 919 spdk_nvmf_subsystem_get_nqn(subsystem), 920 spdk_bdev_get_name(bdev), 921 opts.nsid); 922 923 subsystem->max_nsid = spdk_max(subsystem->max_nsid, opts.nsid); 924 subsystem->num_allocated_nsid++; 925 926 return opts.nsid; 927 } 928 929 static uint32_t 930 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 931 uint32_t prev_nsid) 932 { 933 uint32_t nsid; 934 935 if (prev_nsid >= subsystem->max_nsid) { 936 return 0; 937 } 938 939 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 940 if (subsystem->ns[nsid - 1]) { 941 return nsid; 942 } 943 } 944 945 return 0; 946 } 947 948 struct spdk_nvmf_ns * 949 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 950 { 951 uint32_t first_nsid; 952 953 first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 954 return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid); 955 } 956 957 struct spdk_nvmf_ns * 958 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 959 struct spdk_nvmf_ns *prev_ns) 960 { 961 uint32_t next_nsid; 962 963 next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid); 964 return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid); 965 } 966 967 struct spdk_nvmf_ns * 968 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 969 { 970 return _spdk_nvmf_subsystem_get_ns(subsystem, nsid); 971 } 972 973 uint32_t 974 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 975 { 976 return ns->opts.nsid; 977 } 978 979 struct spdk_bdev * 980 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 981 { 982 return ns->bdev; 983 } 984 985 void 986 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts, 987 size_t opts_size) 988 { 989 memset(opts, 0, opts_size); 990 memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size)); 991 } 992 993 const char * 994 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 995 { 996 return subsystem->sn; 997 } 998 999 int 1000 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 1001 { 1002 size_t len, max_len; 1003 1004 max_len = sizeof(subsystem->sn) - 1; 1005 len = strlen(sn); 1006 if (len > max_len) { 1007 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 1008 sn, len, max_len); 1009 return -1; 1010 } 1011 1012 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 1013 1014 return 0; 1015 } 1016 1017 const char * 1018 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem) 1019 { 1020 return subsystem->subnqn; 1021 } 1022 1023 /* Workaround for astyle formatting bug */ 1024 typedef enum spdk_nvmf_subtype nvmf_subtype_t; 1025 1026 nvmf_subtype_t 1027 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 1028 { 1029 return subsystem->subtype; 1030 } 1031 1032 static uint16_t 1033 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 1034 { 1035 int count; 1036 1037 /* 1038 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 1039 * before we find one that is unused (or find that all values are in use). 1040 */ 1041 for (count = 0; count < 0xFFF0 - 1; count++) { 1042 subsystem->next_cntlid++; 1043 if (subsystem->next_cntlid >= 0xFFF0) { 1044 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 1045 subsystem->next_cntlid = 1; 1046 } 1047 1048 /* Check if a controller with this cntlid currently exists. */ 1049 if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 1050 /* Found unused cntlid */ 1051 return subsystem->next_cntlid; 1052 } 1053 } 1054 1055 /* All valid cntlid values are in use. */ 1056 return 0xFFFF; 1057 } 1058 1059 int 1060 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 1061 { 1062 ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem); 1063 if (ctrlr->cntlid == 0xFFFF) { 1064 /* Unable to get a cntlid */ 1065 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 1066 return -EBUSY; 1067 } 1068 1069 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1070 1071 return 0; 1072 } 1073 1074 void 1075 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1076 struct spdk_nvmf_ctrlr *ctrlr) 1077 { 1078 assert(subsystem == ctrlr->subsys); 1079 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1080 } 1081 1082 struct spdk_nvmf_ctrlr * 1083 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1084 { 1085 struct spdk_nvmf_ctrlr *ctrlr; 1086 1087 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1088 if (ctrlr->cntlid == cntlid) { 1089 return ctrlr; 1090 } 1091 } 1092 1093 return NULL; 1094 } 1095