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 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->allocated == false) { 786 return -1; 787 } 788 789 spdk_bdev_close(ns->desc); 790 ns->allocated = false; 791 subsystem->num_allocated_nsid--; 792 793 return 0; 794 } 795 796 static void 797 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 798 void *cb_arg, int status) 799 { 800 struct spdk_nvmf_ns *ns = cb_arg; 801 802 spdk_nvmf_subsystem_remove_ns(ns->subsystem, ns->id); 803 804 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 805 } 806 807 static void 808 spdk_nvmf_ns_hot_remove(void *remove_ctx) 809 { 810 struct spdk_nvmf_ns *ns = remove_ctx; 811 int rc; 812 813 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns); 814 if (rc) { 815 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 816 } 817 } 818 819 uint32_t 820 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 821 uint32_t nsid) 822 { 823 struct spdk_nvmf_ns *ns; 824 uint32_t i; 825 int rc; 826 827 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 828 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 829 return 0; 830 } 831 832 if (nsid == SPDK_NVME_GLOBAL_NS_TAG) { 833 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", nsid); 834 return 0; 835 } 836 837 if (nsid > subsystem->max_nsid || 838 (nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) { 839 struct spdk_nvmf_ns *new_ns_array; 840 uint32_t new_max_nsid; 841 842 if (nsid > subsystem->max_nsid) { 843 new_max_nsid = nsid; 844 } else { 845 new_max_nsid = subsystem->max_nsid + 1; 846 } 847 848 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 849 SPDK_ERRLOG("Can't extend NSID range with active connections\n"); 850 return 0; 851 } 852 853 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns) * new_max_nsid); 854 if (new_ns_array == NULL) { 855 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 856 return 0; 857 } 858 859 memset(new_ns_array + subsystem->max_nsid, 0, 860 sizeof(struct spdk_nvmf_ns) * (new_max_nsid - subsystem->max_nsid)); 861 subsystem->ns = new_ns_array; 862 subsystem->max_nsid = new_max_nsid; 863 } 864 865 if (nsid == 0) { 866 /* NSID not specified - find a free index */ 867 for (i = 0; i < subsystem->max_nsid; i++) { 868 if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) { 869 nsid = i + 1; 870 break; 871 } 872 } 873 if (nsid == 0) { 874 SPDK_ERRLOG("All available NSIDs in use\n"); 875 return 0; 876 } 877 } else { 878 /* Specific NSID requested */ 879 if (_spdk_nvmf_subsystem_get_ns(subsystem, nsid)) { 880 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", nsid); 881 return 0; 882 } 883 } 884 885 ns = &subsystem->ns[nsid - 1]; 886 memset(ns, 0, sizeof(*ns)); 887 ns->bdev = bdev; 888 ns->id = nsid; 889 ns->subsystem = subsystem; 890 rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc); 891 if (rc != 0) { 892 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 893 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 894 return 0; 895 } 896 ns->allocated = true; 897 898 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 899 spdk_nvmf_subsystem_get_nqn(subsystem), 900 spdk_bdev_get_name(bdev), 901 nsid); 902 903 subsystem->max_nsid = spdk_max(subsystem->max_nsid, nsid); 904 subsystem->num_allocated_nsid++; 905 906 return nsid; 907 } 908 909 static uint32_t 910 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 911 uint32_t prev_nsid) 912 { 913 uint32_t nsid; 914 915 if (prev_nsid >= subsystem->max_nsid) { 916 return 0; 917 } 918 919 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 920 if (subsystem->ns[nsid - 1].allocated) { 921 return nsid; 922 } 923 } 924 925 return 0; 926 } 927 928 struct spdk_nvmf_ns * 929 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 930 { 931 uint32_t first_nsid; 932 933 first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 934 return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid); 935 } 936 937 struct spdk_nvmf_ns * 938 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 939 struct spdk_nvmf_ns *prev_ns) 940 { 941 uint32_t next_nsid; 942 943 next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->id); 944 return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid); 945 } 946 947 struct spdk_nvmf_ns * 948 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 949 { 950 return _spdk_nvmf_subsystem_get_ns(subsystem, nsid); 951 } 952 953 uint32_t 954 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 955 { 956 return ns->id; 957 } 958 959 struct spdk_bdev * 960 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 961 { 962 return ns->bdev; 963 } 964 965 const char * 966 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 967 { 968 return subsystem->sn; 969 } 970 971 int 972 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 973 { 974 size_t len, max_len; 975 976 max_len = sizeof(subsystem->sn) - 1; 977 len = strlen(sn); 978 if (len > max_len) { 979 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 980 sn, len, max_len); 981 return -1; 982 } 983 984 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 985 986 return 0; 987 } 988 989 const char * 990 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem) 991 { 992 return subsystem->subnqn; 993 } 994 995 /* Workaround for astyle formatting bug */ 996 typedef enum spdk_nvmf_subtype nvmf_subtype_t; 997 998 nvmf_subtype_t 999 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 1000 { 1001 return subsystem->subtype; 1002 } 1003 1004 static uint16_t 1005 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 1006 { 1007 int count; 1008 1009 /* 1010 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 1011 * before we find one that is unused (or find that all values are in use). 1012 */ 1013 for (count = 0; count < 0xFFF0 - 1; count++) { 1014 subsystem->next_cntlid++; 1015 if (subsystem->next_cntlid >= 0xFFF0) { 1016 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 1017 subsystem->next_cntlid = 1; 1018 } 1019 1020 /* Check if a controller with this cntlid currently exists. */ 1021 if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 1022 /* Found unused cntlid */ 1023 return subsystem->next_cntlid; 1024 } 1025 } 1026 1027 /* All valid cntlid values are in use. */ 1028 return 0xFFFF; 1029 } 1030 1031 int 1032 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 1033 { 1034 ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem); 1035 if (ctrlr->cntlid == 0xFFFF) { 1036 /* Unable to get a cntlid */ 1037 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 1038 return -EBUSY; 1039 } 1040 1041 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1042 1043 return 0; 1044 } 1045 1046 void 1047 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1048 struct spdk_nvmf_ctrlr *ctrlr) 1049 { 1050 assert(subsystem == ctrlr->subsys); 1051 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1052 } 1053 1054 struct spdk_nvmf_ctrlr * 1055 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1056 { 1057 struct spdk_nvmf_ctrlr *ctrlr; 1058 1059 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1060 if (ctrlr->cntlid == cntlid) { 1061 return ctrlr; 1062 } 1063 } 1064 1065 return NULL; 1066 } 1067