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 for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL; 317 ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) { 318 if (ns->bdev == NULL) { 319 continue; 320 } 321 spdk_bdev_close(ns->desc); 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 int 653 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, 654 struct spdk_nvme_transport_id *trid) 655 { 656 struct spdk_nvmf_transport *transport; 657 struct spdk_nvmf_listener *listener; 658 659 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 660 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 661 return -EAGAIN; 662 } 663 664 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype); 665 if (transport == NULL) { 666 SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype); 667 return -EINVAL; 668 } 669 670 listener = calloc(1, sizeof(*listener)); 671 if (!listener) { 672 return -ENOMEM; 673 } 674 675 listener->trid = *trid; 676 listener->transport = transport; 677 678 TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link); 679 680 return 0; 681 } 682 683 /* 684 * TODO: this is the whitelist and will be called during connection setup 685 */ 686 bool 687 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, 688 struct spdk_nvme_transport_id *trid) 689 { 690 struct spdk_nvmf_listener *listener; 691 692 if (TAILQ_EMPTY(&subsystem->listeners)) { 693 return true; 694 } 695 696 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 697 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 698 return true; 699 } 700 } 701 702 return false; 703 } 704 705 struct spdk_nvmf_listener * 706 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem) 707 { 708 return TAILQ_FIRST(&subsystem->listeners); 709 } 710 711 struct spdk_nvmf_listener * 712 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem, 713 struct spdk_nvmf_listener *prev_listener) 714 { 715 return TAILQ_NEXT(prev_listener, link); 716 } 717 718 719 const struct spdk_nvme_transport_id * 720 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener) 721 { 722 return &listener->trid; 723 } 724 725 int 726 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 727 { 728 struct spdk_nvmf_ns *ns; 729 730 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED || 731 subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 732 733 if (nsid == 0 || nsid > subsystem->max_nsid) { 734 return -1; 735 } 736 737 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 738 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 739 return -1; 740 } 741 742 ns = &subsystem->ns[nsid - 1]; 743 if (ns->allocated == false) { 744 return -1; 745 } 746 747 spdk_bdev_close(ns->desc); 748 ns->allocated = false; 749 subsystem->num_allocated_nsid--; 750 751 return 0; 752 } 753 754 static void 755 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 756 void *cb_arg, int status) 757 { 758 struct spdk_nvmf_ns *ns = cb_arg; 759 760 spdk_nvmf_subsystem_remove_ns(ns->subsystem, ns->id); 761 762 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 763 } 764 765 static void 766 spdk_nvmf_ns_hot_remove(void *remove_ctx) 767 { 768 struct spdk_nvmf_ns *ns = remove_ctx; 769 int rc; 770 771 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns); 772 if (rc) { 773 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 774 } 775 } 776 777 uint32_t 778 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 779 uint32_t nsid) 780 { 781 struct spdk_nvmf_ns *ns; 782 uint32_t i; 783 int rc; 784 785 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 786 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 787 return 0; 788 } 789 790 if (nsid == SPDK_NVME_GLOBAL_NS_TAG) { 791 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", nsid); 792 return 0; 793 } 794 795 if (nsid > subsystem->max_nsid || 796 (nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) { 797 struct spdk_nvmf_ns *new_ns_array; 798 uint32_t new_max_nsid; 799 800 if (nsid > subsystem->max_nsid) { 801 new_max_nsid = nsid; 802 } else { 803 new_max_nsid = subsystem->max_nsid + 1; 804 } 805 806 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 807 SPDK_ERRLOG("Can't extend NSID range with active connections\n"); 808 return 0; 809 } 810 811 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns) * new_max_nsid); 812 if (new_ns_array == NULL) { 813 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 814 return 0; 815 } 816 817 memset(new_ns_array + subsystem->max_nsid, 0, 818 sizeof(struct spdk_nvmf_ns) * (new_max_nsid - subsystem->max_nsid)); 819 subsystem->ns = new_ns_array; 820 subsystem->max_nsid = new_max_nsid; 821 } 822 823 if (nsid == 0) { 824 /* NSID not specified - find a free index */ 825 for (i = 0; i < subsystem->max_nsid; i++) { 826 if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) { 827 nsid = i + 1; 828 break; 829 } 830 } 831 if (nsid == 0) { 832 SPDK_ERRLOG("All available NSIDs in use\n"); 833 return 0; 834 } 835 } else { 836 /* Specific NSID requested */ 837 if (_spdk_nvmf_subsystem_get_ns(subsystem, nsid)) { 838 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", nsid); 839 return 0; 840 } 841 } 842 843 ns = &subsystem->ns[nsid - 1]; 844 memset(ns, 0, sizeof(*ns)); 845 ns->bdev = bdev; 846 ns->id = nsid; 847 ns->subsystem = subsystem; 848 rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc); 849 if (rc != 0) { 850 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 851 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 852 return 0; 853 } 854 ns->allocated = true; 855 856 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 857 spdk_nvmf_subsystem_get_nqn(subsystem), 858 spdk_bdev_get_name(bdev), 859 nsid); 860 861 subsystem->max_nsid = spdk_max(subsystem->max_nsid, nsid); 862 subsystem->num_allocated_nsid++; 863 864 return nsid; 865 } 866 867 static uint32_t 868 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 869 uint32_t prev_nsid) 870 { 871 uint32_t nsid; 872 873 if (prev_nsid >= subsystem->max_nsid) { 874 return 0; 875 } 876 877 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 878 if (subsystem->ns[nsid - 1].allocated) { 879 return nsid; 880 } 881 } 882 883 return 0; 884 } 885 886 struct spdk_nvmf_ns * 887 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 888 { 889 uint32_t first_nsid; 890 891 first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 892 return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid); 893 } 894 895 struct spdk_nvmf_ns * 896 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 897 struct spdk_nvmf_ns *prev_ns) 898 { 899 uint32_t next_nsid; 900 901 next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->id); 902 return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid); 903 } 904 905 struct spdk_nvmf_ns * 906 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 907 { 908 return _spdk_nvmf_subsystem_get_ns(subsystem, nsid); 909 } 910 911 uint32_t 912 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 913 { 914 return ns->id; 915 } 916 917 struct spdk_bdev * 918 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 919 { 920 return ns->bdev; 921 } 922 923 const char * 924 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 925 { 926 return subsystem->sn; 927 } 928 929 int 930 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 931 { 932 size_t len, max_len; 933 934 max_len = sizeof(subsystem->sn) - 1; 935 len = strlen(sn); 936 if (len > max_len) { 937 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 938 sn, len, max_len); 939 return -1; 940 } 941 942 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 943 944 return 0; 945 } 946 947 const char * 948 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem) 949 { 950 return subsystem->subnqn; 951 } 952 953 /* Workaround for astyle formatting bug */ 954 typedef enum spdk_nvmf_subtype nvmf_subtype_t; 955 956 nvmf_subtype_t 957 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 958 { 959 return subsystem->subtype; 960 } 961 962 static uint16_t 963 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 964 { 965 int count; 966 967 /* 968 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 969 * before we find one that is unused (or find that all values are in use). 970 */ 971 for (count = 0; count < 0xFFF0 - 1; count++) { 972 subsystem->next_cntlid++; 973 if (subsystem->next_cntlid >= 0xFFF0) { 974 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 975 subsystem->next_cntlid = 1; 976 } 977 978 /* Check if a controller with this cntlid currently exists. */ 979 if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 980 /* Found unused cntlid */ 981 return subsystem->next_cntlid; 982 } 983 } 984 985 /* All valid cntlid values are in use. */ 986 return 0xFFFF; 987 } 988 989 int 990 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 991 { 992 ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem); 993 if (ctrlr->cntlid == 0xFFFF) { 994 /* Unable to get a cntlid */ 995 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 996 return -EBUSY; 997 } 998 999 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1000 1001 return 0; 1002 } 1003 1004 void 1005 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1006 struct spdk_nvmf_ctrlr *ctrlr) 1007 { 1008 assert(subsystem == ctrlr->subsys); 1009 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1010 } 1011 1012 struct spdk_nvmf_ctrlr * 1013 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1014 { 1015 struct spdk_nvmf_ctrlr *ctrlr; 1016 1017 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1018 if (ctrlr->cntlid == cntlid) { 1019 return ctrlr; 1020 } 1021 } 1022 1023 return NULL; 1024 } 1025