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->thread = spdk_get_thread(); 259 subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 260 subsystem->tgt = tgt; 261 subsystem->id = sid; 262 subsystem->subtype = type; 263 subsystem->max_nsid = num_ns; 264 subsystem->num_allocated_nsid = 0; 265 subsystem->next_cntlid = 0; 266 snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn); 267 TAILQ_INIT(&subsystem->listeners); 268 TAILQ_INIT(&subsystem->hosts); 269 TAILQ_INIT(&subsystem->ctrlrs); 270 271 if (num_ns != 0) { 272 subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *)); 273 if (subsystem->ns == NULL) { 274 SPDK_ERRLOG("Namespace memory allocation failed\n"); 275 free(subsystem); 276 return NULL; 277 } 278 } 279 280 tgt->subsystems[sid] = subsystem; 281 tgt->discovery_genctr++; 282 283 return subsystem; 284 } 285 286 static void 287 _spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_host *host) 288 { 289 TAILQ_REMOVE(&subsystem->hosts, host, link); 290 free(host->nqn); 291 free(host); 292 } 293 294 void 295 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem) 296 { 297 struct spdk_nvmf_listener *listener, *listener_tmp; 298 struct spdk_nvmf_host *host, *host_tmp; 299 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 300 struct spdk_nvmf_ns *ns; 301 302 if (!subsystem) { 303 return; 304 } 305 306 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 307 308 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem); 309 310 TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) { 311 TAILQ_REMOVE(&subsystem->listeners, listener, link); 312 free(listener); 313 } 314 315 TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) { 316 _spdk_nvmf_subsystem_remove_host(subsystem, host); 317 } 318 319 TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) { 320 spdk_nvmf_ctrlr_destruct(ctrlr); 321 } 322 323 ns = spdk_nvmf_subsystem_get_first_ns(subsystem); 324 while (ns != NULL) { 325 struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns); 326 327 spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 328 ns = next_ns; 329 } 330 331 free(subsystem->ns); 332 333 subsystem->tgt->subsystems[subsystem->id] = NULL; 334 subsystem->tgt->discovery_genctr++; 335 336 free(subsystem); 337 } 338 339 static int 340 spdk_nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem, 341 enum spdk_nvmf_subsystem_state state) 342 { 343 enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state; 344 345 switch (state) { 346 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 347 expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 348 break; 349 case SPDK_NVMF_SUBSYSTEM_ACTIVATING: 350 expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 351 break; 352 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 353 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 354 break; 355 case SPDK_NVMF_SUBSYSTEM_PAUSING: 356 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 357 break; 358 case SPDK_NVMF_SUBSYSTEM_PAUSED: 359 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 360 break; 361 case SPDK_NVMF_SUBSYSTEM_RESUMING: 362 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED; 363 break; 364 case SPDK_NVMF_SUBSYSTEM_DEACTIVATING: 365 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 366 break; 367 default: 368 assert(false); 369 return -1; 370 } 371 372 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 373 if (actual_old_state != expected_old_state) { 374 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING && 375 state == SPDK_NVMF_SUBSYSTEM_ACTIVE) { 376 expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 377 } 378 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 379 } 380 assert(actual_old_state == expected_old_state); 381 return actual_old_state - expected_old_state; 382 } 383 384 struct subsystem_state_change_ctx { 385 struct spdk_nvmf_subsystem *subsystem; 386 387 enum spdk_nvmf_subsystem_state requested_state; 388 389 spdk_nvmf_subsystem_state_change_done cb_fn; 390 void *cb_arg; 391 }; 392 393 static void 394 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status) 395 { 396 struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 397 398 if (status == 0) { 399 status = spdk_nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state); 400 if (status) { 401 status = -1; 402 } 403 } 404 405 if (ctx->cb_fn) { 406 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 407 } 408 free(ctx); 409 } 410 411 static void 412 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i) 413 { 414 struct subsystem_state_change_ctx *ctx; 415 struct spdk_io_channel *ch; 416 struct spdk_nvmf_poll_group *group; 417 int rc = -1; 418 419 ctx = spdk_io_channel_iter_get_ctx(i); 420 ch = spdk_io_channel_iter_get_channel(i); 421 group = spdk_io_channel_get_ctx(ch); 422 423 switch (ctx->requested_state) { 424 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 425 rc = spdk_nvmf_poll_group_remove_subsystem(group, ctx->subsystem); 426 break; 427 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 428 if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) { 429 rc = spdk_nvmf_poll_group_add_subsystem(group, ctx->subsystem); 430 } else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) { 431 rc = spdk_nvmf_poll_group_resume_subsystem(group, ctx->subsystem); 432 } 433 break; 434 case SPDK_NVMF_SUBSYSTEM_PAUSED: 435 rc = spdk_nvmf_poll_group_pause_subsystem(group, ctx->subsystem); 436 break; 437 default: 438 assert(false); 439 break; 440 } 441 442 spdk_for_each_channel_continue(i, rc); 443 } 444 445 static int 446 spdk_nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem, 447 enum spdk_nvmf_subsystem_state requested_state, 448 spdk_nvmf_subsystem_state_change_done cb_fn, 449 void *cb_arg) 450 { 451 struct subsystem_state_change_ctx *ctx; 452 enum spdk_nvmf_subsystem_state intermediate_state; 453 int rc; 454 455 switch (requested_state) { 456 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 457 intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 458 break; 459 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 460 if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) { 461 intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 462 } else { 463 intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 464 } 465 break; 466 case SPDK_NVMF_SUBSYSTEM_PAUSED: 467 intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 468 break; 469 default: 470 assert(false); 471 return -EINVAL; 472 } 473 474 ctx = calloc(1, sizeof(*ctx)); 475 if (!ctx) { 476 return -ENOMEM; 477 } 478 479 rc = spdk_nvmf_subsystem_set_state(subsystem, intermediate_state); 480 if (rc) { 481 free(ctx); 482 return rc; 483 } 484 485 ctx->subsystem = subsystem; 486 ctx->requested_state = requested_state; 487 ctx->cb_fn = cb_fn; 488 ctx->cb_arg = cb_arg; 489 490 spdk_for_each_channel(subsystem->tgt, 491 subsystem_state_change_on_pg, 492 ctx, 493 subsystem_state_change_done); 494 495 return 0; 496 } 497 498 int 499 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem, 500 spdk_nvmf_subsystem_state_change_done cb_fn, 501 void *cb_arg) 502 { 503 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 504 } 505 506 int 507 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem, 508 spdk_nvmf_subsystem_state_change_done cb_fn, 509 void *cb_arg) 510 { 511 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg); 512 } 513 514 int 515 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem, 516 spdk_nvmf_subsystem_state_change_done cb_fn, 517 void *cb_arg) 518 { 519 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg); 520 } 521 522 int 523 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem, 524 spdk_nvmf_subsystem_state_change_done cb_fn, 525 void *cb_arg) 526 { 527 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 528 } 529 530 struct spdk_nvmf_subsystem * 531 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt) 532 { 533 struct spdk_nvmf_subsystem *subsystem; 534 uint32_t sid; 535 536 for (sid = 0; sid < tgt->max_sid; sid++) { 537 subsystem = tgt->subsystems[sid]; 538 if (subsystem) { 539 return subsystem; 540 } 541 } 542 543 return NULL; 544 } 545 546 struct spdk_nvmf_subsystem * 547 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem) 548 { 549 uint32_t sid; 550 struct spdk_nvmf_tgt *tgt; 551 552 if (!subsystem) { 553 return NULL; 554 } 555 556 tgt = subsystem->tgt; 557 558 for (sid = subsystem->id + 1; sid < tgt->max_sid; sid++) { 559 subsystem = tgt->subsystems[sid]; 560 if (subsystem) { 561 return subsystem; 562 } 563 } 564 565 return NULL; 566 } 567 568 static struct spdk_nvmf_host * 569 _spdk_nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 570 { 571 struct spdk_nvmf_host *host = NULL; 572 573 TAILQ_FOREACH(host, &subsystem->hosts, link) { 574 if (strcmp(hostnqn, host->nqn) == 0) { 575 return host; 576 } 577 } 578 579 return NULL; 580 } 581 582 int 583 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 584 { 585 struct spdk_nvmf_host *host; 586 587 if (!spdk_nvmf_valid_nqn(hostnqn)) { 588 return -EINVAL; 589 } 590 591 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 592 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 593 return -EAGAIN; 594 } 595 596 if (_spdk_nvmf_subsystem_find_host(subsystem, hostnqn)) { 597 /* This subsystem already allows the specified host. */ 598 return 0; 599 } 600 601 host = calloc(1, sizeof(*host)); 602 if (!host) { 603 return -ENOMEM; 604 } 605 host->nqn = strdup(hostnqn); 606 if (!host->nqn) { 607 free(host); 608 return -ENOMEM; 609 } 610 611 TAILQ_INSERT_HEAD(&subsystem->hosts, host, link); 612 subsystem->tgt->discovery_genctr++; 613 614 return 0; 615 } 616 617 int 618 spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 619 { 620 struct spdk_nvmf_host *host; 621 622 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 623 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 624 return -EAGAIN; 625 } 626 627 host = _spdk_nvmf_subsystem_find_host(subsystem, hostnqn); 628 if (host == NULL) { 629 return -ENOENT; 630 } 631 632 _spdk_nvmf_subsystem_remove_host(subsystem, host); 633 return 0; 634 } 635 636 int 637 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host) 638 { 639 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 640 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 641 return -EAGAIN; 642 } 643 644 subsystem->allow_any_host = allow_any_host; 645 646 return 0; 647 } 648 649 bool 650 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem) 651 { 652 return subsystem->allow_any_host; 653 } 654 655 bool 656 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 657 { 658 if (!hostnqn) { 659 return false; 660 } 661 662 if (subsystem->allow_any_host) { 663 return true; 664 } 665 666 return _spdk_nvmf_subsystem_find_host(subsystem, hostnqn) != NULL; 667 } 668 669 struct spdk_nvmf_host * 670 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem) 671 { 672 return TAILQ_FIRST(&subsystem->hosts); 673 } 674 675 676 struct spdk_nvmf_host * 677 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem, 678 struct spdk_nvmf_host *prev_host) 679 { 680 return TAILQ_NEXT(prev_host, link); 681 } 682 683 const char * 684 spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host) 685 { 686 return host->nqn; 687 } 688 689 static struct spdk_nvmf_listener * 690 _spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, 691 const struct spdk_nvme_transport_id *trid) 692 { 693 struct spdk_nvmf_listener *listener; 694 695 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 696 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 697 return listener; 698 } 699 } 700 701 return NULL; 702 } 703 704 int 705 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, 706 struct spdk_nvme_transport_id *trid) 707 { 708 struct spdk_nvmf_transport *transport; 709 struct spdk_nvmf_listener *listener; 710 711 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 712 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 713 return -EAGAIN; 714 } 715 716 if (_spdk_nvmf_subsystem_find_listener(subsystem, trid)) { 717 /* Listener already exists in this subsystem */ 718 return 0; 719 } 720 721 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype); 722 if (transport == NULL) { 723 SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype); 724 return -EINVAL; 725 } 726 727 listener = calloc(1, sizeof(*listener)); 728 if (!listener) { 729 return -ENOMEM; 730 } 731 732 listener->trid = *trid; 733 listener->transport = transport; 734 735 TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link); 736 737 return 0; 738 } 739 740 int 741 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, 742 const struct spdk_nvme_transport_id *trid) 743 { 744 struct spdk_nvmf_listener *listener; 745 746 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 747 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 748 return -EAGAIN; 749 } 750 751 listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid); 752 if (listener == NULL) { 753 return -ENOENT; 754 } 755 756 TAILQ_REMOVE(&subsystem->listeners, listener, link); 757 free(listener); 758 759 return 0; 760 } 761 762 /* 763 * TODO: this is the whitelist and will be called during connection setup 764 */ 765 bool 766 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, 767 struct spdk_nvme_transport_id *trid) 768 { 769 struct spdk_nvmf_listener *listener; 770 771 if (TAILQ_EMPTY(&subsystem->listeners)) { 772 return true; 773 } 774 775 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 776 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 777 return true; 778 } 779 } 780 781 return false; 782 } 783 784 struct spdk_nvmf_listener * 785 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem) 786 { 787 return TAILQ_FIRST(&subsystem->listeners); 788 } 789 790 struct spdk_nvmf_listener * 791 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem, 792 struct spdk_nvmf_listener *prev_listener) 793 { 794 return TAILQ_NEXT(prev_listener, link); 795 } 796 797 798 const struct spdk_nvme_transport_id * 799 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener) 800 { 801 return &listener->trid; 802 } 803 804 int 805 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 806 { 807 struct spdk_nvmf_ns *ns; 808 809 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED || 810 subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 811 812 if (nsid == 0 || nsid > subsystem->max_nsid) { 813 return -1; 814 } 815 816 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 817 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 818 return -1; 819 } 820 821 ns = subsystem->ns[nsid - 1]; 822 if (!ns) { 823 return -1; 824 } 825 826 subsystem->ns[nsid - 1] = NULL; 827 828 spdk_bdev_close(ns->desc); 829 free(ns); 830 subsystem->num_allocated_nsid--; 831 832 return 0; 833 } 834 835 static void 836 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 837 void *cb_arg, int status) 838 { 839 struct spdk_nvmf_ns *ns = cb_arg; 840 841 spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 842 843 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 844 } 845 846 static void 847 spdk_nvmf_ns_hot_remove(void *remove_ctx) 848 { 849 struct spdk_nvmf_ns *ns = remove_ctx; 850 int rc; 851 852 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns); 853 if (rc) { 854 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 855 } 856 } 857 858 void 859 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size) 860 { 861 /* All current fields are set to 0 by default. */ 862 memset(opts, 0, opts_size); 863 } 864 865 uint32_t 866 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 867 const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size) 868 { 869 struct spdk_nvmf_ns_opts opts; 870 struct spdk_nvmf_ns *ns; 871 uint32_t i; 872 int rc; 873 874 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 875 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 876 return 0; 877 } 878 879 spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts)); 880 if (user_opts) { 881 memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size)); 882 } 883 884 if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) { 885 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid); 886 return 0; 887 } 888 889 if (opts.nsid > subsystem->max_nsid || 890 (opts.nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) { 891 struct spdk_nvmf_ns **new_ns_array; 892 uint32_t new_max_nsid; 893 894 if (opts.nsid > subsystem->max_nsid) { 895 new_max_nsid = opts.nsid; 896 } else { 897 new_max_nsid = subsystem->max_nsid + 1; 898 } 899 900 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 901 SPDK_ERRLOG("Can't extend NSID range with active connections\n"); 902 return 0; 903 } 904 905 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * new_max_nsid); 906 if (new_ns_array == NULL) { 907 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 908 return 0; 909 } 910 911 memset(new_ns_array + subsystem->max_nsid, 0, 912 sizeof(struct spdk_nvmf_ns *) * (new_max_nsid - subsystem->max_nsid)); 913 subsystem->ns = new_ns_array; 914 subsystem->max_nsid = new_max_nsid; 915 } 916 917 if (opts.nsid == 0) { 918 /* NSID not specified - find a free index */ 919 for (i = 0; i < subsystem->max_nsid; i++) { 920 if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) { 921 opts.nsid = i + 1; 922 break; 923 } 924 } 925 if (opts.nsid == 0) { 926 SPDK_ERRLOG("All available NSIDs in use\n"); 927 return 0; 928 } 929 } else { 930 /* Specific NSID requested */ 931 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) { 932 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid); 933 return 0; 934 } 935 } 936 937 ns = calloc(1, sizeof(*ns)); 938 if (ns == NULL) { 939 SPDK_ERRLOG("Namespace allocation failed\n"); 940 return 0; 941 } 942 943 ns->bdev = bdev; 944 ns->opts = opts; 945 ns->subsystem = subsystem; 946 rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc); 947 if (rc != 0) { 948 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 949 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 950 free(ns); 951 return 0; 952 } 953 subsystem->ns[opts.nsid - 1] = ns; 954 955 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 956 spdk_nvmf_subsystem_get_nqn(subsystem), 957 spdk_bdev_get_name(bdev), 958 opts.nsid); 959 960 subsystem->max_nsid = spdk_max(subsystem->max_nsid, opts.nsid); 961 subsystem->num_allocated_nsid++; 962 963 return opts.nsid; 964 } 965 966 static uint32_t 967 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 968 uint32_t prev_nsid) 969 { 970 uint32_t nsid; 971 972 if (prev_nsid >= subsystem->max_nsid) { 973 return 0; 974 } 975 976 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 977 if (subsystem->ns[nsid - 1]) { 978 return nsid; 979 } 980 } 981 982 return 0; 983 } 984 985 struct spdk_nvmf_ns * 986 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 987 { 988 uint32_t first_nsid; 989 990 first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 991 return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid); 992 } 993 994 struct spdk_nvmf_ns * 995 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 996 struct spdk_nvmf_ns *prev_ns) 997 { 998 uint32_t next_nsid; 999 1000 next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid); 1001 return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid); 1002 } 1003 1004 struct spdk_nvmf_ns * 1005 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 1006 { 1007 return _spdk_nvmf_subsystem_get_ns(subsystem, nsid); 1008 } 1009 1010 uint32_t 1011 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 1012 { 1013 return ns->opts.nsid; 1014 } 1015 1016 struct spdk_bdev * 1017 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 1018 { 1019 return ns->bdev; 1020 } 1021 1022 void 1023 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts, 1024 size_t opts_size) 1025 { 1026 memset(opts, 0, opts_size); 1027 memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size)); 1028 } 1029 1030 const char * 1031 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 1032 { 1033 return subsystem->sn; 1034 } 1035 1036 int 1037 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 1038 { 1039 size_t len, max_len; 1040 1041 max_len = sizeof(subsystem->sn) - 1; 1042 len = strlen(sn); 1043 if (len > max_len) { 1044 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 1045 sn, len, max_len); 1046 return -1; 1047 } 1048 1049 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 1050 1051 return 0; 1052 } 1053 1054 const char * 1055 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem) 1056 { 1057 return subsystem->subnqn; 1058 } 1059 1060 /* Workaround for astyle formatting bug */ 1061 typedef enum spdk_nvmf_subtype nvmf_subtype_t; 1062 1063 nvmf_subtype_t 1064 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 1065 { 1066 return subsystem->subtype; 1067 } 1068 1069 static uint16_t 1070 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 1071 { 1072 int count; 1073 1074 /* 1075 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 1076 * before we find one that is unused (or find that all values are in use). 1077 */ 1078 for (count = 0; count < 0xFFF0 - 1; count++) { 1079 subsystem->next_cntlid++; 1080 if (subsystem->next_cntlid >= 0xFFF0) { 1081 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 1082 subsystem->next_cntlid = 1; 1083 } 1084 1085 /* Check if a controller with this cntlid currently exists. */ 1086 if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 1087 /* Found unused cntlid */ 1088 return subsystem->next_cntlid; 1089 } 1090 } 1091 1092 /* All valid cntlid values are in use. */ 1093 return 0xFFFF; 1094 } 1095 1096 int 1097 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 1098 { 1099 ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem); 1100 if (ctrlr->cntlid == 0xFFFF) { 1101 /* Unable to get a cntlid */ 1102 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 1103 return -EBUSY; 1104 } 1105 1106 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1107 1108 return 0; 1109 } 1110 1111 void 1112 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1113 struct spdk_nvmf_ctrlr *ctrlr) 1114 { 1115 assert(subsystem == ctrlr->subsys); 1116 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1117 } 1118 1119 struct spdk_nvmf_ctrlr * 1120 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1121 { 1122 struct spdk_nvmf_ctrlr *ctrlr; 1123 1124 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1125 if (ctrlr->cntlid == cntlid) { 1126 return ctrlr; 1127 } 1128 } 1129 1130 return NULL; 1131 } 1132