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