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/bdev_module.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_subsystems; sid++) { 257 if (tgt->subsystems[sid] == NULL) { 258 break; 259 } 260 } 261 if (sid >= tgt->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 subsystem->max_allowed_nsid = num_ns; 277 subsystem->next_cntlid = 0; 278 snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn); 279 TAILQ_INIT(&subsystem->listeners); 280 TAILQ_INIT(&subsystem->hosts); 281 TAILQ_INIT(&subsystem->ctrlrs); 282 283 if (num_ns != 0) { 284 subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *)); 285 if (subsystem->ns == NULL) { 286 SPDK_ERRLOG("Namespace memory allocation failed\n"); 287 free(subsystem); 288 return NULL; 289 } 290 } 291 292 memset(subsystem->sn, '0', sizeof(subsystem->sn) - 1); 293 subsystem->sn[sizeof(subsystem->sn) - 1] = '\n'; 294 295 tgt->subsystems[sid] = subsystem; 296 tgt->discovery_genctr++; 297 298 return subsystem; 299 } 300 301 static void 302 _spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_host *host) 303 { 304 TAILQ_REMOVE(&subsystem->hosts, host, link); 305 free(host->nqn); 306 free(host); 307 } 308 309 static int _spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid); 310 311 void 312 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem) 313 { 314 struct spdk_nvmf_listener *listener, *listener_tmp; 315 struct spdk_nvmf_host *host, *host_tmp; 316 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 317 struct spdk_nvmf_ns *ns; 318 319 if (!subsystem) { 320 return; 321 } 322 323 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 324 325 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem); 326 327 TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) { 328 TAILQ_REMOVE(&subsystem->listeners, listener, link); 329 free(listener); 330 } 331 332 TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) { 333 _spdk_nvmf_subsystem_remove_host(subsystem, host); 334 } 335 336 TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) { 337 spdk_nvmf_ctrlr_destruct(ctrlr); 338 } 339 340 ns = spdk_nvmf_subsystem_get_first_ns(subsystem); 341 while (ns != NULL) { 342 struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns); 343 344 _spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 345 ns = next_ns; 346 } 347 348 free(subsystem->ns); 349 350 subsystem->tgt->subsystems[subsystem->id] = NULL; 351 subsystem->tgt->discovery_genctr++; 352 353 free(subsystem); 354 } 355 356 static int 357 spdk_nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem, 358 enum spdk_nvmf_subsystem_state state) 359 { 360 enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state; 361 362 switch (state) { 363 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 364 expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 365 break; 366 case SPDK_NVMF_SUBSYSTEM_ACTIVATING: 367 expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 368 break; 369 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 370 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 371 break; 372 case SPDK_NVMF_SUBSYSTEM_PAUSING: 373 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 374 break; 375 case SPDK_NVMF_SUBSYSTEM_PAUSED: 376 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 377 break; 378 case SPDK_NVMF_SUBSYSTEM_RESUMING: 379 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED; 380 break; 381 case SPDK_NVMF_SUBSYSTEM_DEACTIVATING: 382 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 383 break; 384 default: 385 assert(false); 386 return -1; 387 } 388 389 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 390 if (actual_old_state != expected_old_state) { 391 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING && 392 state == SPDK_NVMF_SUBSYSTEM_ACTIVE) { 393 expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 394 } 395 /* This is for the case when activating the subsystem fails. */ 396 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_ACTIVATING && 397 state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) { 398 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 399 } 400 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 401 } 402 assert(actual_old_state == expected_old_state); 403 return actual_old_state - expected_old_state; 404 } 405 406 struct subsystem_state_change_ctx { 407 struct spdk_nvmf_subsystem *subsystem; 408 409 enum spdk_nvmf_subsystem_state requested_state; 410 411 spdk_nvmf_subsystem_state_change_done cb_fn; 412 void *cb_arg; 413 }; 414 415 static void 416 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status) 417 { 418 struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 419 420 if (status == 0) { 421 status = spdk_nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state); 422 if (status) { 423 status = -1; 424 } 425 } 426 427 if (ctx->cb_fn) { 428 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 429 } 430 free(ctx); 431 } 432 433 static void 434 subsystem_state_change_continue(void *ctx, int status) 435 { 436 struct spdk_io_channel_iter *i = ctx; 437 spdk_for_each_channel_continue(i, status); 438 } 439 440 static void 441 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i) 442 { 443 struct subsystem_state_change_ctx *ctx; 444 struct spdk_io_channel *ch; 445 struct spdk_nvmf_poll_group *group; 446 447 ctx = spdk_io_channel_iter_get_ctx(i); 448 ch = spdk_io_channel_iter_get_channel(i); 449 group = spdk_io_channel_get_ctx(ch); 450 451 switch (ctx->requested_state) { 452 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 453 spdk_nvmf_poll_group_remove_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 454 break; 455 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 456 if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) { 457 spdk_nvmf_poll_group_add_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 458 } else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) { 459 spdk_nvmf_poll_group_resume_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 460 } 461 break; 462 case SPDK_NVMF_SUBSYSTEM_PAUSED: 463 spdk_nvmf_poll_group_pause_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 464 break; 465 default: 466 assert(false); 467 break; 468 } 469 } 470 471 static int 472 spdk_nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem, 473 enum spdk_nvmf_subsystem_state requested_state, 474 spdk_nvmf_subsystem_state_change_done cb_fn, 475 void *cb_arg) 476 { 477 struct subsystem_state_change_ctx *ctx; 478 enum spdk_nvmf_subsystem_state intermediate_state; 479 int rc; 480 481 switch (requested_state) { 482 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 483 intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 484 break; 485 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 486 if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) { 487 intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 488 } else { 489 intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 490 } 491 break; 492 case SPDK_NVMF_SUBSYSTEM_PAUSED: 493 intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 494 break; 495 default: 496 assert(false); 497 return -EINVAL; 498 } 499 500 ctx = calloc(1, sizeof(*ctx)); 501 if (!ctx) { 502 return -ENOMEM; 503 } 504 505 rc = spdk_nvmf_subsystem_set_state(subsystem, intermediate_state); 506 if (rc) { 507 free(ctx); 508 return rc; 509 } 510 511 ctx->subsystem = subsystem; 512 ctx->requested_state = requested_state; 513 ctx->cb_fn = cb_fn; 514 ctx->cb_arg = cb_arg; 515 516 spdk_for_each_channel(subsystem->tgt, 517 subsystem_state_change_on_pg, 518 ctx, 519 subsystem_state_change_done); 520 521 return 0; 522 } 523 524 int 525 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem, 526 spdk_nvmf_subsystem_state_change_done cb_fn, 527 void *cb_arg) 528 { 529 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 530 } 531 532 int 533 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem, 534 spdk_nvmf_subsystem_state_change_done cb_fn, 535 void *cb_arg) 536 { 537 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg); 538 } 539 540 int 541 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem, 542 spdk_nvmf_subsystem_state_change_done cb_fn, 543 void *cb_arg) 544 { 545 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg); 546 } 547 548 int 549 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem, 550 spdk_nvmf_subsystem_state_change_done cb_fn, 551 void *cb_arg) 552 { 553 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 554 } 555 556 struct spdk_nvmf_subsystem * 557 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt) 558 { 559 struct spdk_nvmf_subsystem *subsystem; 560 uint32_t sid; 561 562 for (sid = 0; sid < tgt->max_subsystems; sid++) { 563 subsystem = tgt->subsystems[sid]; 564 if (subsystem) { 565 return subsystem; 566 } 567 } 568 569 return NULL; 570 } 571 572 struct spdk_nvmf_subsystem * 573 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem) 574 { 575 uint32_t sid; 576 struct spdk_nvmf_tgt *tgt; 577 578 if (!subsystem) { 579 return NULL; 580 } 581 582 tgt = subsystem->tgt; 583 584 for (sid = subsystem->id + 1; sid < tgt->max_subsystems; sid++) { 585 subsystem = tgt->subsystems[sid]; 586 if (subsystem) { 587 return subsystem; 588 } 589 } 590 591 return NULL; 592 } 593 594 static struct spdk_nvmf_host * 595 _spdk_nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 596 { 597 struct spdk_nvmf_host *host = NULL; 598 599 TAILQ_FOREACH(host, &subsystem->hosts, link) { 600 if (strcmp(hostnqn, host->nqn) == 0) { 601 return host; 602 } 603 } 604 605 return NULL; 606 } 607 608 int 609 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 610 { 611 struct spdk_nvmf_host *host; 612 613 if (!spdk_nvmf_valid_nqn(hostnqn)) { 614 return -EINVAL; 615 } 616 617 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 618 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 619 return -EAGAIN; 620 } 621 622 if (_spdk_nvmf_subsystem_find_host(subsystem, hostnqn)) { 623 /* This subsystem already allows the specified host. */ 624 return 0; 625 } 626 627 host = calloc(1, sizeof(*host)); 628 if (!host) { 629 return -ENOMEM; 630 } 631 host->nqn = strdup(hostnqn); 632 if (!host->nqn) { 633 free(host); 634 return -ENOMEM; 635 } 636 637 TAILQ_INSERT_HEAD(&subsystem->hosts, host, link); 638 subsystem->tgt->discovery_genctr++; 639 640 return 0; 641 } 642 643 int 644 spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 645 { 646 struct spdk_nvmf_host *host; 647 648 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 649 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 650 return -EAGAIN; 651 } 652 653 host = _spdk_nvmf_subsystem_find_host(subsystem, hostnqn); 654 if (host == NULL) { 655 return -ENOENT; 656 } 657 658 _spdk_nvmf_subsystem_remove_host(subsystem, host); 659 return 0; 660 } 661 662 int 663 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host) 664 { 665 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 666 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 667 return -EAGAIN; 668 } 669 670 subsystem->allow_any_host = allow_any_host; 671 672 return 0; 673 } 674 675 bool 676 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem) 677 { 678 return subsystem->allow_any_host; 679 } 680 681 bool 682 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 683 { 684 if (!hostnqn) { 685 return false; 686 } 687 688 if (subsystem->allow_any_host) { 689 return true; 690 } 691 692 return _spdk_nvmf_subsystem_find_host(subsystem, hostnqn) != NULL; 693 } 694 695 struct spdk_nvmf_host * 696 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem) 697 { 698 return TAILQ_FIRST(&subsystem->hosts); 699 } 700 701 702 struct spdk_nvmf_host * 703 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem, 704 struct spdk_nvmf_host *prev_host) 705 { 706 return TAILQ_NEXT(prev_host, link); 707 } 708 709 const char * 710 spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host) 711 { 712 return host->nqn; 713 } 714 715 static struct spdk_nvmf_listener * 716 _spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, 717 const struct spdk_nvme_transport_id *trid) 718 { 719 struct spdk_nvmf_listener *listener; 720 721 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 722 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 723 return listener; 724 } 725 } 726 727 return NULL; 728 } 729 730 int 731 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, 732 struct spdk_nvme_transport_id *trid) 733 { 734 struct spdk_nvmf_transport *transport; 735 struct spdk_nvmf_listener *listener; 736 737 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 738 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 739 return -EAGAIN; 740 } 741 742 if (_spdk_nvmf_subsystem_find_listener(subsystem, trid)) { 743 /* Listener already exists in this subsystem */ 744 return 0; 745 } 746 747 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype); 748 if (transport == NULL) { 749 SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype); 750 return -EINVAL; 751 } 752 753 listener = calloc(1, sizeof(*listener)); 754 if (!listener) { 755 return -ENOMEM; 756 } 757 758 listener->trid = *trid; 759 listener->transport = transport; 760 761 TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link); 762 763 return 0; 764 } 765 766 int 767 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, 768 const struct spdk_nvme_transport_id *trid) 769 { 770 struct spdk_nvmf_listener *listener; 771 772 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 773 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 774 return -EAGAIN; 775 } 776 777 listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid); 778 if (listener == NULL) { 779 return -ENOENT; 780 } 781 782 TAILQ_REMOVE(&subsystem->listeners, listener, link); 783 free(listener); 784 785 return 0; 786 } 787 788 bool 789 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, 790 struct spdk_nvme_transport_id *trid) 791 { 792 struct spdk_nvmf_listener *listener; 793 794 if (!strcmp(subsystem->subnqn, SPDK_NVMF_DISCOVERY_NQN)) { 795 return true; 796 } 797 798 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 799 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 800 return true; 801 } 802 } 803 804 return false; 805 } 806 807 struct spdk_nvmf_listener * 808 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem) 809 { 810 return TAILQ_FIRST(&subsystem->listeners); 811 } 812 813 struct spdk_nvmf_listener * 814 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem, 815 struct spdk_nvmf_listener *prev_listener) 816 { 817 return TAILQ_NEXT(prev_listener, link); 818 } 819 820 const struct spdk_nvme_transport_id * 821 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener) 822 { 823 return &listener->trid; 824 } 825 826 struct subsystem_update_ns_ctx { 827 struct spdk_nvmf_subsystem *subsystem; 828 829 spdk_nvmf_subsystem_state_change_done cb_fn; 830 void *cb_arg; 831 }; 832 833 static void 834 subsystem_update_ns_done(struct spdk_io_channel_iter *i, int status) 835 { 836 struct subsystem_update_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 837 838 if (ctx->cb_fn) { 839 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 840 } 841 free(ctx); 842 } 843 844 static void 845 subsystem_update_ns_on_pg(struct spdk_io_channel_iter *i) 846 { 847 int rc; 848 struct subsystem_update_ns_ctx *ctx; 849 struct spdk_nvmf_poll_group *group; 850 struct spdk_nvmf_subsystem *subsystem; 851 852 ctx = spdk_io_channel_iter_get_ctx(i); 853 group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i)); 854 subsystem = ctx->subsystem; 855 856 rc = spdk_nvmf_poll_group_update_subsystem(group, subsystem); 857 spdk_for_each_channel_continue(i, rc); 858 } 859 860 static int 861 spdk_nvmf_subsystem_update_ns(struct spdk_nvmf_subsystem *subsystem, spdk_channel_for_each_cpl cpl, 862 void *ctx) 863 { 864 spdk_for_each_channel(subsystem->tgt, 865 subsystem_update_ns_on_pg, 866 ctx, 867 cpl); 868 869 return 0; 870 } 871 872 static void 873 spdk_nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 874 { 875 struct spdk_nvmf_ctrlr *ctrlr; 876 877 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 878 spdk_nvmf_ctrlr_ns_changed(ctrlr, nsid); 879 } 880 } 881 882 static int 883 _spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 884 { 885 struct spdk_nvmf_ns *ns; 886 struct spdk_nvmf_registrant *reg, *reg_tmp; 887 888 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED || 889 subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 890 891 if (nsid == 0 || nsid > subsystem->max_nsid) { 892 return -1; 893 } 894 895 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 896 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 897 return -1; 898 } 899 900 ns = subsystem->ns[nsid - 1]; 901 if (!ns) { 902 return -1; 903 } 904 905 subsystem->ns[nsid - 1] = NULL; 906 907 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 908 TAILQ_REMOVE(&ns->registrants, reg, link); 909 free(reg); 910 } 911 spdk_bdev_module_release_bdev(ns->bdev); 912 spdk_bdev_close(ns->desc); 913 free(ns); 914 915 spdk_nvmf_subsystem_ns_changed(subsystem, nsid); 916 917 return 0; 918 } 919 920 int 921 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid, 922 spdk_nvmf_subsystem_state_change_done cb_fn, void *cb_arg) 923 { 924 int rc; 925 struct subsystem_update_ns_ctx *ctx; 926 927 rc = _spdk_nvmf_subsystem_remove_ns(subsystem, nsid); 928 if (rc < 0) { 929 return rc; 930 } 931 932 ctx = calloc(1, sizeof(*ctx)); 933 934 if (ctx == NULL) { 935 return -ENOMEM; 936 } 937 938 ctx->subsystem = subsystem; 939 ctx->cb_fn = cb_fn; 940 ctx->cb_arg = cb_arg; 941 942 spdk_nvmf_subsystem_update_ns(subsystem, subsystem_update_ns_done, ctx); 943 944 return 0; 945 } 946 947 static void 948 _spdk_nvmf_ns_hot_remove_done(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status) 949 { 950 if (status != 0) { 951 SPDK_ERRLOG("Failed to make changes to NVMe-oF subsystem with id %u\n", subsystem->id); 952 } 953 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 954 } 955 956 static void 957 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 958 void *cb_arg, int status) 959 { 960 struct spdk_nvmf_ns *ns = cb_arg; 961 962 spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid, _spdk_nvmf_ns_hot_remove_done, 963 subsystem); 964 } 965 966 static void 967 spdk_nvmf_ns_hot_remove(void *remove_ctx) 968 { 969 struct spdk_nvmf_ns *ns = remove_ctx; 970 int rc; 971 972 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns); 973 if (rc) { 974 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 975 } 976 } 977 978 void 979 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size) 980 { 981 /* All current fields are set to 0 by default. */ 982 memset(opts, 0, opts_size); 983 } 984 985 /* Dummy bdev module used to to claim bdevs. */ 986 static struct spdk_bdev_module ns_bdev_module = { 987 .name = "NVMe-oF Target", 988 }; 989 990 uint32_t 991 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 992 const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size) 993 { 994 struct spdk_nvmf_ns_opts opts; 995 struct spdk_nvmf_ns *ns; 996 int rc; 997 998 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 999 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 1000 return 0; 1001 } 1002 1003 spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts)); 1004 if (user_opts) { 1005 memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size)); 1006 } 1007 1008 if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) { 1009 opts.uuid = *spdk_bdev_get_uuid(bdev); 1010 } 1011 1012 if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) { 1013 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid); 1014 return 0; 1015 } 1016 1017 if (opts.nsid == 0) { 1018 /* 1019 * NSID not specified - find a free index. 1020 * 1021 * If no free slots are found, opts.nsid will be subsystem->max_nsid + 1, which will 1022 * expand max_nsid if possible. 1023 */ 1024 for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) { 1025 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) { 1026 break; 1027 } 1028 } 1029 } 1030 1031 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) { 1032 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid); 1033 return 0; 1034 } 1035 1036 if (opts.nsid > subsystem->max_nsid) { 1037 struct spdk_nvmf_ns **new_ns_array; 1038 1039 /* If MaxNamespaces was specified, we can't extend max_nsid beyond it. */ 1040 if (subsystem->max_allowed_nsid > 0 && opts.nsid > subsystem->max_allowed_nsid) { 1041 SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n"); 1042 return 0; 1043 } 1044 1045 /* If a controller is connected, we can't change NN. */ 1046 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 1047 SPDK_ERRLOG("Can't extend NSID range while controllers are connected\n"); 1048 return 0; 1049 } 1050 1051 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid); 1052 if (new_ns_array == NULL) { 1053 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 1054 return 0; 1055 } 1056 1057 memset(new_ns_array + subsystem->max_nsid, 0, 1058 sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid)); 1059 subsystem->ns = new_ns_array; 1060 subsystem->max_nsid = opts.nsid; 1061 } 1062 1063 ns = calloc(1, sizeof(*ns)); 1064 if (ns == NULL) { 1065 SPDK_ERRLOG("Namespace allocation failed\n"); 1066 return 0; 1067 } 1068 1069 ns->bdev = bdev; 1070 ns->opts = opts; 1071 ns->subsystem = subsystem; 1072 rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc); 1073 if (rc != 0) { 1074 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 1075 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 1076 free(ns); 1077 return 0; 1078 } 1079 rc = spdk_bdev_module_claim_bdev(bdev, ns->desc, &ns_bdev_module); 1080 if (rc != 0) { 1081 spdk_bdev_close(ns->desc); 1082 free(ns); 1083 return 0; 1084 } 1085 subsystem->ns[opts.nsid - 1] = ns; 1086 ns->nsid = opts.nsid; 1087 TAILQ_INIT(&ns->registrants); 1088 1089 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 1090 spdk_nvmf_subsystem_get_nqn(subsystem), 1091 spdk_bdev_get_name(bdev), 1092 opts.nsid); 1093 1094 spdk_nvmf_subsystem_ns_changed(subsystem, opts.nsid); 1095 1096 return opts.nsid; 1097 } 1098 1099 static uint32_t 1100 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 1101 uint32_t prev_nsid) 1102 { 1103 uint32_t nsid; 1104 1105 if (prev_nsid >= subsystem->max_nsid) { 1106 return 0; 1107 } 1108 1109 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 1110 if (subsystem->ns[nsid - 1]) { 1111 return nsid; 1112 } 1113 } 1114 1115 return 0; 1116 } 1117 1118 struct spdk_nvmf_ns * 1119 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 1120 { 1121 uint32_t first_nsid; 1122 1123 first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 1124 return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid); 1125 } 1126 1127 struct spdk_nvmf_ns * 1128 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 1129 struct spdk_nvmf_ns *prev_ns) 1130 { 1131 uint32_t next_nsid; 1132 1133 next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid); 1134 return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid); 1135 } 1136 1137 struct spdk_nvmf_ns * 1138 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 1139 { 1140 return _spdk_nvmf_subsystem_get_ns(subsystem, nsid); 1141 } 1142 1143 uint32_t 1144 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 1145 { 1146 return ns->opts.nsid; 1147 } 1148 1149 struct spdk_bdev * 1150 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 1151 { 1152 return ns->bdev; 1153 } 1154 1155 void 1156 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts, 1157 size_t opts_size) 1158 { 1159 memset(opts, 0, opts_size); 1160 memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size)); 1161 } 1162 1163 const char * 1164 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 1165 { 1166 return subsystem->sn; 1167 } 1168 1169 int 1170 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 1171 { 1172 size_t len, max_len; 1173 1174 max_len = sizeof(subsystem->sn) - 1; 1175 len = strlen(sn); 1176 if (len > max_len) { 1177 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 1178 sn, len, max_len); 1179 return -1; 1180 } 1181 1182 if (!spdk_nvmf_valid_ascii_string(sn, len)) { 1183 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n"); 1184 SPDK_LOGDUMP(SPDK_LOG_NVMF, "sn", sn, len); 1185 return -1; 1186 } 1187 1188 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 1189 1190 return 0; 1191 } 1192 1193 const char * 1194 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem) 1195 { 1196 return subsystem->subnqn; 1197 } 1198 1199 /* Workaround for astyle formatting bug */ 1200 typedef enum spdk_nvmf_subtype nvmf_subtype_t; 1201 1202 nvmf_subtype_t 1203 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 1204 { 1205 return subsystem->subtype; 1206 } 1207 1208 static uint16_t 1209 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 1210 { 1211 int count; 1212 1213 /* 1214 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 1215 * before we find one that is unused (or find that all values are in use). 1216 */ 1217 for (count = 0; count < 0xFFF0 - 1; count++) { 1218 subsystem->next_cntlid++; 1219 if (subsystem->next_cntlid >= 0xFFF0) { 1220 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 1221 subsystem->next_cntlid = 1; 1222 } 1223 1224 /* Check if a controller with this cntlid currently exists. */ 1225 if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 1226 /* Found unused cntlid */ 1227 return subsystem->next_cntlid; 1228 } 1229 } 1230 1231 /* All valid cntlid values are in use. */ 1232 return 0xFFFF; 1233 } 1234 1235 int 1236 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 1237 { 1238 ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem); 1239 if (ctrlr->cntlid == 0xFFFF) { 1240 /* Unable to get a cntlid */ 1241 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 1242 return -EBUSY; 1243 } 1244 1245 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1246 1247 return 0; 1248 } 1249 1250 void 1251 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1252 struct spdk_nvmf_ctrlr *ctrlr) 1253 { 1254 assert(subsystem == ctrlr->subsys); 1255 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1256 } 1257 1258 struct spdk_nvmf_ctrlr * 1259 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1260 { 1261 struct spdk_nvmf_ctrlr *ctrlr; 1262 1263 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1264 if (ctrlr->cntlid == cntlid) { 1265 return ctrlr; 1266 } 1267 } 1268 1269 return NULL; 1270 } 1271 1272 uint32_t 1273 spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem) 1274 { 1275 return subsystem->max_allowed_nsid; 1276 } 1277 1278 static struct spdk_nvmf_registrant * 1279 nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns, 1280 struct spdk_uuid *uuid) 1281 { 1282 struct spdk_nvmf_registrant *reg, *tmp; 1283 1284 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1285 if (spdk_uuid_compare(®->hostid, uuid) == 0) { 1286 return reg; 1287 } 1288 } 1289 1290 return NULL; 1291 } 1292 1293 /* current reservation type is all registrants or not */ 1294 static bool 1295 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns) 1296 { 1297 return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS || 1298 ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); 1299 } 1300 1301 /* current registrant is reservation holder or not */ 1302 static bool 1303 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns, 1304 struct spdk_nvmf_registrant *reg) 1305 { 1306 if (!reg) { 1307 return false; 1308 } 1309 1310 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1311 return true; 1312 } 1313 1314 return (ns->holder == reg); 1315 } 1316 1317 static int 1318 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns, 1319 struct spdk_nvmf_ctrlr *ctrlr, 1320 uint64_t nrkey) 1321 { 1322 struct spdk_nvmf_registrant *reg; 1323 1324 reg = calloc(1, sizeof(*reg)); 1325 if (!reg) { 1326 return -ENOMEM; 1327 } 1328 1329 reg->rkey = nrkey; 1330 /* set hostid for the registrant */ 1331 spdk_uuid_copy(®->hostid, &ctrlr->hostid); 1332 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1333 ns->gen++; 1334 1335 return 0; 1336 } 1337 1338 static void 1339 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns) 1340 { 1341 ns->rtype = 0; 1342 ns->crkey = 0; 1343 ns->holder = NULL; 1344 } 1345 1346 /* release the reservation if the last registrant was removed */ 1347 static void 1348 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns, 1349 struct spdk_nvmf_registrant *reg) 1350 { 1351 struct spdk_nvmf_registrant *next_reg; 1352 1353 /* no reservation holder */ 1354 if (!ns->holder) { 1355 assert(ns->rtype == 0); 1356 return; 1357 } 1358 1359 next_reg = TAILQ_FIRST(&ns->registrants); 1360 if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) { 1361 /* the next valid registrant is the new holder now */ 1362 ns->holder = next_reg; 1363 } else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 1364 /* release the reservation */ 1365 nvmf_ns_reservation_release_reservation(ns); 1366 } 1367 } 1368 1369 static void 1370 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns, 1371 struct spdk_nvmf_registrant *reg) 1372 { 1373 TAILQ_REMOVE(&ns->registrants, reg, link); 1374 nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg); 1375 free(reg); 1376 ns->gen++; 1377 return; 1378 } 1379 1380 static uint32_t 1381 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns, 1382 uint64_t rkey) 1383 { 1384 struct spdk_nvmf_registrant *reg, *tmp; 1385 uint32_t count = 0; 1386 1387 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1388 if (reg->rkey == rkey) { 1389 nvmf_ns_reservation_remove_registrant(ns, reg); 1390 count++; 1391 } 1392 } 1393 return count; 1394 } 1395 1396 static uint32_t 1397 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns, 1398 struct spdk_nvmf_registrant *reg) 1399 { 1400 struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2; 1401 uint32_t count = 0; 1402 1403 TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) { 1404 if (reg_tmp != reg) { 1405 nvmf_ns_reservation_remove_registrant(ns, reg_tmp); 1406 count++; 1407 } 1408 } 1409 return count; 1410 } 1411 1412 static uint32_t 1413 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns) 1414 { 1415 struct spdk_nvmf_registrant *reg, *reg_tmp; 1416 uint32_t count = 0; 1417 1418 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 1419 nvmf_ns_reservation_remove_registrant(ns, reg); 1420 count++; 1421 } 1422 return count; 1423 } 1424 1425 static void 1426 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey, 1427 enum spdk_nvme_reservation_type rtype, 1428 struct spdk_nvmf_registrant *holder) 1429 { 1430 ns->rtype = rtype; 1431 ns->crkey = rkey; 1432 assert(ns->holder == NULL); 1433 ns->holder = holder; 1434 } 1435 1436 static void 1437 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns, 1438 struct spdk_nvmf_ctrlr *ctrlr, 1439 struct spdk_nvmf_request *req) 1440 { 1441 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1442 uint8_t rrega, iekey, cptpl; 1443 struct spdk_nvme_reservation_register_data key; 1444 struct spdk_nvmf_registrant *reg; 1445 uint8_t status = SPDK_NVME_SC_SUCCESS; 1446 int rc; 1447 1448 rrega = cmd->cdw10 & 0x7u; 1449 iekey = (cmd->cdw10 >> 3) & 0x1u; 1450 cptpl = (cmd->cdw10 >> 30) & 0x3u; 1451 memcpy(&key, req->data, sizeof(key)); 1452 1453 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, " 1454 "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n", 1455 rrega, iekey, cptpl, key.crkey, key.nrkey); 1456 1457 /* TODO: doesn't support for now */ 1458 if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) { 1459 SPDK_ERRLOG("Can't change persist through power loss for now\n"); 1460 status = SPDK_NVME_SC_INVALID_FIELD; 1461 goto exit; 1462 } 1463 1464 /* current Host Identifier has registrant or not */ 1465 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1466 1467 switch (rrega) { 1468 case SPDK_NVME_RESERVE_REGISTER_KEY: 1469 if (!reg) { 1470 /* register new controller */ 1471 if (key.nrkey == 0) { 1472 SPDK_ERRLOG("Can't register zeroed new key\n"); 1473 status = SPDK_NVME_SC_INVALID_FIELD; 1474 goto exit; 1475 } 1476 rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey); 1477 if (rc < 0) { 1478 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 1479 goto exit; 1480 } 1481 } else { 1482 /* register with same key is not an error */ 1483 if (reg->rkey != key.nrkey) { 1484 SPDK_ERRLOG("The same host already register a " 1485 "key with 0x%"PRIx64"\n", 1486 reg->rkey); 1487 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1488 goto exit; 1489 } 1490 } 1491 break; 1492 case SPDK_NVME_RESERVE_UNREGISTER_KEY: 1493 if (!reg || (!iekey && reg->rkey != key.crkey)) { 1494 SPDK_ERRLOG("No registrant or current key doesn't match " 1495 "with existing registrant key\n"); 1496 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1497 goto exit; 1498 } 1499 nvmf_ns_reservation_remove_registrant(ns, reg); 1500 break; 1501 case SPDK_NVME_RESERVE_REPLACE_KEY: 1502 if (!reg || (!iekey && reg->rkey != key.crkey)) { 1503 SPDK_ERRLOG("No registrant or current key doesn't match " 1504 "with existing registrant key\n"); 1505 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1506 goto exit; 1507 } 1508 if (key.nrkey == 0) { 1509 SPDK_ERRLOG("Can't register zeroed new key\n"); 1510 status = SPDK_NVME_SC_INVALID_FIELD; 1511 goto exit; 1512 } 1513 reg->rkey = key.nrkey; 1514 break; 1515 default: 1516 status = SPDK_NVME_SC_INVALID_FIELD; 1517 goto exit; 1518 } 1519 1520 exit: 1521 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1522 req->rsp->nvme_cpl.status.sc = status; 1523 return; 1524 } 1525 1526 static void 1527 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns, 1528 struct spdk_nvmf_ctrlr *ctrlr, 1529 struct spdk_nvmf_request *req) 1530 { 1531 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1532 uint8_t racqa, iekey, rtype; 1533 struct spdk_nvme_reservation_acquire_data key; 1534 struct spdk_nvmf_registrant *reg; 1535 bool all_regs = false; 1536 uint32_t count = 0; 1537 uint8_t status = SPDK_NVME_SC_SUCCESS; 1538 1539 racqa = cmd->cdw10 & 0x7u; 1540 iekey = (cmd->cdw10 >> 3) & 0x1u; 1541 rtype = (cmd->cdw10 >> 8) & 0xffu; 1542 memcpy(&key, req->data, sizeof(key)); 1543 1544 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIIRE: RACQA %u, IEKEY %u, RTYPE %u, " 1545 "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n", 1546 racqa, iekey, rtype, key.crkey, key.prkey); 1547 1548 if (iekey) { 1549 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 1550 status = SPDK_NVME_SC_INVALID_FIELD; 1551 goto exit; 1552 } 1553 1554 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1555 /* must be registrant and CRKEY must match */ 1556 if (!reg || reg->rkey != key.crkey) { 1557 SPDK_ERRLOG("No registrant or current key doesn't match " 1558 "with existing registrant key\n"); 1559 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1560 goto exit; 1561 } 1562 1563 all_regs = nvmf_ns_reservation_all_registrants_type(ns); 1564 1565 switch (racqa) { 1566 case SPDK_NVME_RESERVE_ACQUIRE: 1567 /* it's not an error for the holder to acquire same reservation type again */ 1568 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) { 1569 /* do nothing */ 1570 } else if (ns->holder == NULL) { 1571 /* fisrt time to acquire the reservation */ 1572 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 1573 } else { 1574 SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n"); 1575 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1576 goto exit; 1577 } 1578 break; 1579 case SPDK_NVME_RESERVE_PREEMPT: 1580 /* no reservation holder */ 1581 if (!ns->holder) { 1582 /* unregister with PRKEY */ 1583 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 1584 break; 1585 } 1586 /* only 1 reservation holder and reservation key is valid */ 1587 if (!all_regs) { 1588 /* preempt itself */ 1589 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && 1590 ns->crkey == key.prkey) { 1591 ns->rtype = rtype; 1592 break; 1593 } 1594 1595 if (ns->crkey == key.prkey) { 1596 nvmf_ns_reservation_remove_registrant(ns, ns->holder); 1597 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 1598 } else if (key.prkey != 0) { 1599 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 1600 } else { 1601 /* PRKEY is zero */ 1602 SPDK_ERRLOG("Current PRKEY is zero\n"); 1603 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1604 goto exit; 1605 } 1606 } else { 1607 /* release all other registrants except for the current one */ 1608 if (key.prkey == 0) { 1609 nvmf_ns_reservation_remove_all_other_registrants(ns, reg); 1610 assert(ns->holder == reg); 1611 } else { 1612 count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 1613 if (count == 0) { 1614 SPDK_ERRLOG("PRKEY doesn't match any registrant\n"); 1615 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1616 goto exit; 1617 } 1618 } 1619 } 1620 break; 1621 default: 1622 break; 1623 } 1624 1625 exit: 1626 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1627 req->rsp->nvme_cpl.status.sc = status; 1628 return; 1629 } 1630 1631 static void 1632 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns, 1633 struct spdk_nvmf_ctrlr *ctrlr, 1634 struct spdk_nvmf_request *req) 1635 { 1636 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1637 uint8_t rrela, iekey, rtype; 1638 struct spdk_nvmf_registrant *reg; 1639 uint64_t crkey; 1640 uint8_t status = SPDK_NVME_SC_SUCCESS; 1641 1642 rrela = cmd->cdw10 & 0x7u; 1643 iekey = (cmd->cdw10 >> 3) & 0x1u; 1644 rtype = (cmd->cdw10 >> 8) & 0xffu; 1645 memcpy(&crkey, req->data, sizeof(crkey)); 1646 1647 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, " 1648 "CRKEY 0x%"PRIx64"\n", rrela, iekey, rtype, crkey); 1649 1650 if (iekey) { 1651 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 1652 status = SPDK_NVME_SC_INVALID_FIELD; 1653 goto exit; 1654 } 1655 1656 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1657 if (!reg || reg->rkey != crkey) { 1658 SPDK_ERRLOG("No registrant or current key doesn't match " 1659 "with existing registrant key\n"); 1660 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1661 goto exit; 1662 } 1663 1664 switch (rrela) { 1665 case SPDK_NVME_RESERVE_RELEASE: 1666 if (!ns->holder) { 1667 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n"); 1668 goto exit; 1669 } 1670 if (ns->rtype != rtype) { 1671 SPDK_ERRLOG("Type doesn't match\n"); 1672 status = SPDK_NVME_SC_INVALID_FIELD; 1673 goto exit; 1674 } 1675 if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 1676 /* not the reservation holder, this isn't an error */ 1677 goto exit; 1678 } 1679 nvmf_ns_reservation_release_reservation(ns); 1680 break; 1681 case SPDK_NVME_RESERVE_CLEAR: 1682 nvmf_ns_reservation_clear_all_registrants(ns); 1683 break; 1684 default: 1685 status = SPDK_NVME_SC_INVALID_FIELD; 1686 goto exit; 1687 } 1688 1689 exit: 1690 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1691 req->rsp->nvme_cpl.status.sc = status; 1692 return; 1693 } 1694 1695 static void 1696 spdk_nvmf_ns_reservation_complete(void *ctx) 1697 { 1698 struct spdk_nvmf_request *req = ctx; 1699 1700 spdk_nvmf_request_complete(req); 1701 } 1702 1703 void 1704 spdk_nvmf_ns_reservation_request(void *ctx) 1705 { 1706 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx; 1707 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1708 struct spdk_nvmf_poll_group *group = req->qpair->group; 1709 struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; 1710 uint32_t nsid; 1711 struct spdk_nvmf_ns *ns; 1712 1713 nsid = cmd->nsid; 1714 ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid); 1715 assert(ns != NULL); 1716 1717 switch (cmd->opc) { 1718 case SPDK_NVME_OPC_RESERVATION_REGISTER: 1719 nvmf_ns_reservation_register(ns, ctrlr, req); 1720 break; 1721 case SPDK_NVME_OPC_RESERVATION_ACQUIRE: 1722 nvmf_ns_reservation_acquire(ns, ctrlr, req); 1723 break; 1724 case SPDK_NVME_OPC_RESERVATION_RELEASE: 1725 nvmf_ns_reservation_release(ns, ctrlr, req); 1726 break; 1727 default: 1728 break; 1729 } 1730 spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req); 1731 } 1732