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