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 /* current reservation type is all registrants or not */ 1307 static bool 1308 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns) 1309 { 1310 return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS || 1311 ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); 1312 } 1313 1314 /* current registrant is reservation holder or not */ 1315 static bool 1316 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns, 1317 struct spdk_nvmf_registrant *reg) 1318 { 1319 if (!reg) { 1320 return false; 1321 } 1322 1323 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1324 return true; 1325 } 1326 1327 return (ns->holder == reg); 1328 } 1329 1330 static int 1331 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns, 1332 struct spdk_nvmf_ctrlr *ctrlr, 1333 uint64_t nrkey) 1334 { 1335 struct spdk_nvmf_registrant *reg; 1336 1337 reg = calloc(1, sizeof(*reg)); 1338 if (!reg) { 1339 return -ENOMEM; 1340 } 1341 1342 reg->rkey = nrkey; 1343 /* set hostid for the registrant */ 1344 spdk_uuid_copy(®->hostid, &ctrlr->hostid); 1345 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1346 ns->gen++; 1347 1348 return 0; 1349 } 1350 1351 static void 1352 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns) 1353 { 1354 ns->rtype = 0; 1355 ns->crkey = 0; 1356 ns->holder = NULL; 1357 } 1358 1359 /* release the reservation if the last registrant was removed */ 1360 static void 1361 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns, 1362 struct spdk_nvmf_registrant *reg) 1363 { 1364 struct spdk_nvmf_registrant *next_reg; 1365 1366 /* no reservation holder */ 1367 if (!ns->holder) { 1368 assert(ns->rtype == 0); 1369 return; 1370 } 1371 1372 next_reg = TAILQ_FIRST(&ns->registrants); 1373 if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) { 1374 /* the next valid registrant is the new holder now */ 1375 ns->holder = next_reg; 1376 } else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 1377 /* release the reservation */ 1378 nvmf_ns_reservation_release_reservation(ns); 1379 } 1380 } 1381 1382 static void 1383 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns, 1384 struct spdk_nvmf_registrant *reg) 1385 { 1386 TAILQ_REMOVE(&ns->registrants, reg, link); 1387 nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg); 1388 free(reg); 1389 ns->gen++; 1390 return; 1391 } 1392 1393 static uint32_t 1394 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns, 1395 uint64_t rkey) 1396 { 1397 struct spdk_nvmf_registrant *reg, *tmp; 1398 uint32_t count = 0; 1399 1400 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1401 if (reg->rkey == rkey) { 1402 nvmf_ns_reservation_remove_registrant(ns, reg); 1403 count++; 1404 } 1405 } 1406 return count; 1407 } 1408 1409 static uint32_t 1410 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns, 1411 struct spdk_nvmf_registrant *reg) 1412 { 1413 struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2; 1414 uint32_t count = 0; 1415 1416 TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) { 1417 if (reg_tmp != reg) { 1418 nvmf_ns_reservation_remove_registrant(ns, reg_tmp); 1419 count++; 1420 } 1421 } 1422 return count; 1423 } 1424 1425 static uint32_t 1426 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns) 1427 { 1428 struct spdk_nvmf_registrant *reg, *reg_tmp; 1429 uint32_t count = 0; 1430 1431 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 1432 nvmf_ns_reservation_remove_registrant(ns, reg); 1433 count++; 1434 } 1435 return count; 1436 } 1437 1438 static void 1439 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey, 1440 enum spdk_nvme_reservation_type rtype, 1441 struct spdk_nvmf_registrant *holder) 1442 { 1443 ns->rtype = rtype; 1444 ns->crkey = rkey; 1445 assert(ns->holder == NULL); 1446 ns->holder = holder; 1447 } 1448 1449 static bool 1450 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns, 1451 struct spdk_nvmf_ctrlr *ctrlr, 1452 struct spdk_nvmf_request *req) 1453 { 1454 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1455 uint8_t rrega, iekey, cptpl; 1456 struct spdk_nvme_reservation_register_data key; 1457 struct spdk_nvmf_registrant *reg; 1458 uint8_t status = SPDK_NVME_SC_SUCCESS; 1459 bool update_sgroup = false; 1460 int rc; 1461 1462 rrega = cmd->cdw10 & 0x7u; 1463 iekey = (cmd->cdw10 >> 3) & 0x1u; 1464 cptpl = (cmd->cdw10 >> 30) & 0x3u; 1465 memcpy(&key, req->data, sizeof(key)); 1466 1467 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, " 1468 "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n", 1469 rrega, iekey, cptpl, key.crkey, key.nrkey); 1470 1471 /* TODO: doesn't support for now */ 1472 if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) { 1473 SPDK_ERRLOG("Can't change persist through power loss for now\n"); 1474 status = SPDK_NVME_SC_INVALID_FIELD; 1475 goto exit; 1476 } 1477 1478 /* current Host Identifier has registrant or not */ 1479 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1480 1481 switch (rrega) { 1482 case SPDK_NVME_RESERVE_REGISTER_KEY: 1483 if (!reg) { 1484 /* register new controller */ 1485 if (key.nrkey == 0) { 1486 SPDK_ERRLOG("Can't register zeroed new key\n"); 1487 status = SPDK_NVME_SC_INVALID_FIELD; 1488 goto exit; 1489 } 1490 rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey); 1491 if (rc < 0) { 1492 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 1493 goto exit; 1494 } 1495 } else { 1496 /* register with same key is not an error */ 1497 if (reg->rkey != key.nrkey) { 1498 SPDK_ERRLOG("The same host already register a " 1499 "key with 0x%"PRIx64"\n", 1500 reg->rkey); 1501 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1502 goto exit; 1503 } 1504 } 1505 break; 1506 case SPDK_NVME_RESERVE_UNREGISTER_KEY: 1507 if (!reg || (!iekey && reg->rkey != key.crkey)) { 1508 SPDK_ERRLOG("No registrant or current key doesn't match " 1509 "with existing registrant key\n"); 1510 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1511 goto exit; 1512 } 1513 nvmf_ns_reservation_remove_registrant(ns, reg); 1514 update_sgroup = true; 1515 break; 1516 case SPDK_NVME_RESERVE_REPLACE_KEY: 1517 if (!reg || (!iekey && reg->rkey != key.crkey)) { 1518 SPDK_ERRLOG("No registrant or current key doesn't match " 1519 "with existing registrant key\n"); 1520 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1521 goto exit; 1522 } 1523 if (key.nrkey == 0) { 1524 SPDK_ERRLOG("Can't register zeroed new key\n"); 1525 status = SPDK_NVME_SC_INVALID_FIELD; 1526 goto exit; 1527 } 1528 reg->rkey = key.nrkey; 1529 break; 1530 default: 1531 status = SPDK_NVME_SC_INVALID_FIELD; 1532 goto exit; 1533 } 1534 1535 exit: 1536 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1537 req->rsp->nvme_cpl.status.sc = status; 1538 return update_sgroup; 1539 } 1540 1541 static bool 1542 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns, 1543 struct spdk_nvmf_ctrlr *ctrlr, 1544 struct spdk_nvmf_request *req) 1545 { 1546 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1547 uint8_t racqa, iekey, rtype; 1548 struct spdk_nvme_reservation_acquire_data key; 1549 struct spdk_nvmf_registrant *reg; 1550 bool all_regs = false; 1551 uint32_t count = 0; 1552 bool update_sgroup = true; 1553 uint8_t status = SPDK_NVME_SC_SUCCESS; 1554 1555 racqa = cmd->cdw10 & 0x7u; 1556 iekey = (cmd->cdw10 >> 3) & 0x1u; 1557 rtype = (cmd->cdw10 >> 8) & 0xffu; 1558 memcpy(&key, req->data, sizeof(key)); 1559 1560 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, " 1561 "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n", 1562 racqa, iekey, rtype, key.crkey, key.prkey); 1563 1564 if (iekey) { 1565 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 1566 status = SPDK_NVME_SC_INVALID_FIELD; 1567 update_sgroup = false; 1568 goto exit; 1569 } 1570 1571 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1572 /* must be registrant and CRKEY must match */ 1573 if (!reg || reg->rkey != key.crkey) { 1574 SPDK_ERRLOG("No registrant or current key doesn't match " 1575 "with existing registrant key\n"); 1576 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1577 update_sgroup = false; 1578 goto exit; 1579 } 1580 1581 all_regs = nvmf_ns_reservation_all_registrants_type(ns); 1582 1583 switch (racqa) { 1584 case SPDK_NVME_RESERVE_ACQUIRE: 1585 /* it's not an error for the holder to acquire same reservation type again */ 1586 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) { 1587 /* do nothing */ 1588 update_sgroup = false; 1589 } else if (ns->holder == NULL) { 1590 /* fisrt time to acquire the reservation */ 1591 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 1592 } else { 1593 SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n"); 1594 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1595 update_sgroup = false; 1596 goto exit; 1597 } 1598 break; 1599 case SPDK_NVME_RESERVE_PREEMPT: 1600 /* no reservation holder */ 1601 if (!ns->holder) { 1602 /* unregister with PRKEY */ 1603 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 1604 break; 1605 } 1606 /* only 1 reservation holder and reservation key is valid */ 1607 if (!all_regs) { 1608 /* preempt itself */ 1609 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && 1610 ns->crkey == key.prkey) { 1611 ns->rtype = rtype; 1612 break; 1613 } 1614 1615 if (ns->crkey == key.prkey) { 1616 nvmf_ns_reservation_remove_registrant(ns, ns->holder); 1617 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 1618 } else if (key.prkey != 0) { 1619 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 1620 } else { 1621 /* PRKEY is zero */ 1622 SPDK_ERRLOG("Current PRKEY is zero\n"); 1623 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1624 update_sgroup = false; 1625 goto exit; 1626 } 1627 } else { 1628 /* release all other registrants except for the current one */ 1629 if (key.prkey == 0) { 1630 nvmf_ns_reservation_remove_all_other_registrants(ns, reg); 1631 assert(ns->holder == reg); 1632 } else { 1633 count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 1634 if (count == 0) { 1635 SPDK_ERRLOG("PRKEY doesn't match any registrant\n"); 1636 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1637 update_sgroup = false; 1638 goto exit; 1639 } 1640 } 1641 } 1642 break; 1643 default: 1644 update_sgroup = false; 1645 break; 1646 } 1647 1648 exit: 1649 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1650 req->rsp->nvme_cpl.status.sc = status; 1651 return update_sgroup; 1652 } 1653 1654 static bool 1655 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns, 1656 struct spdk_nvmf_ctrlr *ctrlr, 1657 struct spdk_nvmf_request *req) 1658 { 1659 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1660 uint8_t rrela, iekey, rtype; 1661 struct spdk_nvmf_registrant *reg; 1662 uint64_t crkey; 1663 uint8_t status = SPDK_NVME_SC_SUCCESS; 1664 bool update_sgroup = true; 1665 1666 rrela = cmd->cdw10 & 0x7u; 1667 iekey = (cmd->cdw10 >> 3) & 0x1u; 1668 rtype = (cmd->cdw10 >> 8) & 0xffu; 1669 memcpy(&crkey, req->data, sizeof(crkey)); 1670 1671 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, " 1672 "CRKEY 0x%"PRIx64"\n", rrela, iekey, rtype, crkey); 1673 1674 if (iekey) { 1675 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 1676 status = SPDK_NVME_SC_INVALID_FIELD; 1677 update_sgroup = false; 1678 goto exit; 1679 } 1680 1681 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1682 if (!reg || reg->rkey != crkey) { 1683 SPDK_ERRLOG("No registrant or current key doesn't match " 1684 "with existing registrant key\n"); 1685 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1686 update_sgroup = false; 1687 goto exit; 1688 } 1689 1690 switch (rrela) { 1691 case SPDK_NVME_RESERVE_RELEASE: 1692 if (!ns->holder) { 1693 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n"); 1694 update_sgroup = false; 1695 goto exit; 1696 } 1697 if (ns->rtype != rtype) { 1698 SPDK_ERRLOG("Type doesn't match\n"); 1699 status = SPDK_NVME_SC_INVALID_FIELD; 1700 update_sgroup = false; 1701 goto exit; 1702 } 1703 if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 1704 /* not the reservation holder, this isn't an error */ 1705 update_sgroup = false; 1706 goto exit; 1707 } 1708 nvmf_ns_reservation_release_reservation(ns); 1709 break; 1710 case SPDK_NVME_RESERVE_CLEAR: 1711 nvmf_ns_reservation_clear_all_registrants(ns); 1712 break; 1713 default: 1714 status = SPDK_NVME_SC_INVALID_FIELD; 1715 update_sgroup = false; 1716 goto exit; 1717 } 1718 1719 exit: 1720 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1721 req->rsp->nvme_cpl.status.sc = status; 1722 return update_sgroup; 1723 } 1724 1725 static void 1726 nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns, 1727 struct spdk_nvmf_ctrlr *ctrlr, 1728 struct spdk_nvmf_request *req) 1729 { 1730 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1731 struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; 1732 struct spdk_nvmf_ctrlr *ctrlr_tmp; 1733 struct spdk_nvmf_registrant *reg, *tmp; 1734 struct spdk_nvme_reservation_status_extended_data *status_data; 1735 struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data; 1736 uint8_t *payload; 1737 uint32_t len, count = 0; 1738 uint32_t regctl = 0; 1739 uint8_t status = SPDK_NVME_SC_SUCCESS; 1740 1741 /* NVMeoF uses Extended Data Structure */ 1742 if ((cmd->cdw11 & 0x00000001u) == 0) { 1743 SPDK_ERRLOG("NVMeoF uses extended controller data structure, " 1744 "please set EDS bit in cdw11 and try again\n"); 1745 status = SPDK_NVME_SC_INVALID_FIELD; 1746 goto exit; 1747 } 1748 1749 /* Get number of registerd controllers, one Host may have more than 1750 * one controller based on different ports. 1751 */ 1752 TAILQ_FOREACH(ctrlr_tmp, &subsystem->ctrlrs, link) { 1753 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr_tmp->hostid); 1754 if (reg) { 1755 regctl++; 1756 } 1757 } 1758 1759 len = sizeof(*status_data) + sizeof(*ctrlr_data) * regctl; 1760 payload = calloc(1, len); 1761 if (!payload) { 1762 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 1763 goto exit; 1764 } 1765 1766 status_data = (struct spdk_nvme_reservation_status_extended_data *)payload; 1767 status_data->data.gen = ns->gen; 1768 status_data->data.rtype = ns->rtype; 1769 status_data->data.regctl = regctl; 1770 /* TODO: Don't support Persist Through Power Loss State for now */ 1771 status_data->data.ptpls = 0; 1772 1773 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1774 assert(count <= regctl); 1775 ctrlr_data = (struct spdk_nvme_registered_ctrlr_extended_data *) 1776 (payload + sizeof(*status_data) + sizeof(*ctrlr_data) * count); 1777 /* Set to 0xffffh for dynamic controller */ 1778 ctrlr_data->cntlid = 0xffff; 1779 ctrlr_data->rcsts.status = (ns->holder == reg) ? true : false; 1780 ctrlr_data->rkey = reg->rkey; 1781 spdk_uuid_copy((struct spdk_uuid *)ctrlr_data->hostid, ®->hostid); 1782 count++; 1783 } 1784 1785 memcpy(req->data, payload, spdk_min(len, (cmd->cdw10 + 1) * sizeof(uint32_t))); 1786 free(payload); 1787 1788 exit: 1789 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1790 req->rsp->nvme_cpl.status.sc = status; 1791 return; 1792 } 1793 1794 static void 1795 spdk_nvmf_ns_reservation_complete(void *ctx) 1796 { 1797 struct spdk_nvmf_request *req = ctx; 1798 1799 spdk_nvmf_request_complete(req); 1800 } 1801 1802 static void 1803 _nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem, 1804 void *cb_arg, int status) 1805 { 1806 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg; 1807 struct spdk_nvmf_poll_group *group = req->qpair->group; 1808 1809 spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req); 1810 } 1811 1812 void 1813 spdk_nvmf_ns_reservation_request(void *ctx) 1814 { 1815 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx; 1816 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1817 struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; 1818 struct subsystem_update_ns_ctx *update_ctx; 1819 uint32_t nsid; 1820 struct spdk_nvmf_ns *ns; 1821 bool update_sgroup = false; 1822 1823 nsid = cmd->nsid; 1824 ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid); 1825 assert(ns != NULL); 1826 1827 switch (cmd->opc) { 1828 case SPDK_NVME_OPC_RESERVATION_REGISTER: 1829 update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req); 1830 break; 1831 case SPDK_NVME_OPC_RESERVATION_ACQUIRE: 1832 update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req); 1833 break; 1834 case SPDK_NVME_OPC_RESERVATION_RELEASE: 1835 update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req); 1836 break; 1837 case SPDK_NVME_OPC_RESERVATION_REPORT: 1838 nvmf_ns_reservation_report(ns, ctrlr, req); 1839 break; 1840 default: 1841 break; 1842 } 1843 1844 /* update reservation information to subsystem's poll group */ 1845 if (update_sgroup) { 1846 update_ctx = calloc(1, sizeof(*update_ctx)); 1847 if (update_ctx == NULL) { 1848 SPDK_ERRLOG("Can't alloc subsystem poll group update context\n"); 1849 goto update_done; 1850 } 1851 update_ctx->subsystem = ctrlr->subsys; 1852 update_ctx->cb_fn = _nvmf_ns_reservation_update_done; 1853 update_ctx->cb_arg = req; 1854 1855 spdk_nvmf_subsystem_update_ns(ctrlr->subsys, subsystem_update_ns_done, update_ctx); 1856 return; 1857 } 1858 1859 update_done: 1860 _nvmf_ns_reservation_update_done(ctrlr->subsys, (void *)req, 0); 1861 } 1862