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