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