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