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 { 319 struct spdk_nvmf_transport *transport; 320 321 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, listener->trid.trtype); 322 if (transport != NULL) { 323 spdk_nvmf_transport_stop_listen(transport, &listener->trid); 324 } 325 326 TAILQ_REMOVE(&subsystem->listeners, listener, link); 327 free(listener); 328 } 329 330 void 331 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem) 332 { 333 struct spdk_nvmf_listener *listener, *listener_tmp; 334 struct spdk_nvmf_host *host, *host_tmp; 335 struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp; 336 struct spdk_nvmf_ns *ns; 337 338 if (!subsystem) { 339 return; 340 } 341 342 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 343 344 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem); 345 346 TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) { 347 _nvmf_subsystem_remove_listener(subsystem, listener); 348 } 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 static 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->trtype); 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 783 return 0; 784 } 785 786 int 787 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, 788 const struct spdk_nvme_transport_id *trid) 789 { 790 struct spdk_nvmf_listener *listener; 791 792 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 793 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 794 return -EAGAIN; 795 } 796 797 listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid); 798 if (listener == NULL) { 799 return -ENOENT; 800 } 801 802 _nvmf_subsystem_remove_listener(subsystem, listener); 803 804 return 0; 805 } 806 807 bool 808 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, 809 struct spdk_nvme_transport_id *trid) 810 { 811 struct spdk_nvmf_listener *listener; 812 813 if (!strcmp(subsystem->subnqn, SPDK_NVMF_DISCOVERY_NQN)) { 814 return true; 815 } 816 817 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 818 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 819 return true; 820 } 821 } 822 823 return false; 824 } 825 826 struct spdk_nvmf_listener * 827 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem) 828 { 829 return TAILQ_FIRST(&subsystem->listeners); 830 } 831 832 struct spdk_nvmf_listener * 833 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem, 834 struct spdk_nvmf_listener *prev_listener) 835 { 836 return TAILQ_NEXT(prev_listener, link); 837 } 838 839 const struct spdk_nvme_transport_id * 840 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener) 841 { 842 return &listener->trid; 843 } 844 845 void 846 spdk_nvmf_subsystem_allow_any_listener(struct spdk_nvmf_subsystem *subsystem, 847 bool allow_any_listener) 848 { 849 subsystem->allow_any_listener = allow_any_listener; 850 } 851 852 bool 853 spdk_nvmf_subsytem_any_listener_allowed(struct spdk_nvmf_subsystem *subsystem) 854 { 855 return subsystem->allow_any_listener; 856 } 857 858 859 struct subsystem_update_ns_ctx { 860 struct spdk_nvmf_subsystem *subsystem; 861 862 spdk_nvmf_subsystem_state_change_done cb_fn; 863 void *cb_arg; 864 }; 865 866 static void 867 subsystem_update_ns_done(struct spdk_io_channel_iter *i, int status) 868 { 869 struct subsystem_update_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 870 871 if (ctx->cb_fn) { 872 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 873 } 874 free(ctx); 875 } 876 877 static void 878 subsystem_update_ns_on_pg(struct spdk_io_channel_iter *i) 879 { 880 int rc; 881 struct subsystem_update_ns_ctx *ctx; 882 struct spdk_nvmf_poll_group *group; 883 struct spdk_nvmf_subsystem *subsystem; 884 885 ctx = spdk_io_channel_iter_get_ctx(i); 886 group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i)); 887 subsystem = ctx->subsystem; 888 889 rc = spdk_nvmf_poll_group_update_subsystem(group, subsystem); 890 spdk_for_each_channel_continue(i, rc); 891 } 892 893 static int 894 spdk_nvmf_subsystem_update_ns(struct spdk_nvmf_subsystem *subsystem, spdk_channel_for_each_cpl cpl, 895 void *ctx) 896 { 897 spdk_for_each_channel(subsystem->tgt, 898 subsystem_update_ns_on_pg, 899 ctx, 900 cpl); 901 902 return 0; 903 } 904 905 static void 906 spdk_nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 907 { 908 struct spdk_nvmf_ctrlr *ctrlr; 909 910 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 911 spdk_nvmf_ctrlr_ns_changed(ctrlr, nsid); 912 } 913 } 914 915 int 916 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 917 { 918 struct spdk_nvmf_ns *ns; 919 struct spdk_nvmf_registrant *reg, *reg_tmp; 920 921 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 922 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 923 assert(false); 924 return -1; 925 } 926 927 if (nsid == 0 || nsid > subsystem->max_nsid) { 928 return -1; 929 } 930 931 ns = subsystem->ns[nsid - 1]; 932 if (!ns) { 933 return -1; 934 } 935 936 subsystem->ns[nsid - 1] = NULL; 937 938 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 939 TAILQ_REMOVE(&ns->registrants, reg, link); 940 free(reg); 941 } 942 spdk_bdev_module_release_bdev(ns->bdev); 943 spdk_bdev_close(ns->desc); 944 if (ns->ptpl_file) { 945 free(ns->ptpl_file); 946 } 947 free(ns); 948 949 spdk_nvmf_subsystem_ns_changed(subsystem, nsid); 950 951 return 0; 952 } 953 954 static void 955 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 956 void *cb_arg, int status) 957 { 958 struct spdk_nvmf_ns *ns = cb_arg; 959 int rc; 960 961 rc = spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 962 if (rc != 0) { 963 SPDK_ERRLOG("Failed to make changes to NVME-oF subsystem with id: %u\n", subsystem->id); 964 } 965 966 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 967 } 968 969 static void 970 spdk_nvmf_ns_hot_remove(void *remove_ctx) 971 { 972 struct spdk_nvmf_ns *ns = remove_ctx; 973 int rc; 974 975 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns); 976 if (rc) { 977 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 978 } 979 } 980 981 static void 982 _spdk_nvmf_ns_resize(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status) 983 { 984 struct spdk_nvmf_ns *ns = cb_arg; 985 986 spdk_nvmf_subsystem_ns_changed(subsystem, ns->opts.nsid); 987 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 988 } 989 990 static void 991 spdk_nvmf_ns_resize(void *event_ctx) 992 { 993 struct spdk_nvmf_ns *ns = event_ctx; 994 int rc; 995 996 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_resize, ns); 997 if (rc) { 998 SPDK_ERRLOG("Unable to pause subsystem to process namespace resize!\n"); 999 } 1000 } 1001 1002 static void 1003 spdk_nvmf_ns_event(enum spdk_bdev_event_type type, 1004 struct spdk_bdev *bdev, 1005 void *event_ctx) 1006 { 1007 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev event: type %d, name %s, subsystem_id %d, ns_id %d\n", 1008 type, 1009 bdev->name, 1010 ((struct spdk_nvmf_ns *)event_ctx)->subsystem->id, 1011 ((struct spdk_nvmf_ns *)event_ctx)->nsid); 1012 1013 switch (type) { 1014 case SPDK_BDEV_EVENT_REMOVE: 1015 spdk_nvmf_ns_hot_remove(event_ctx); 1016 break; 1017 case SPDK_BDEV_EVENT_RESIZE: 1018 spdk_nvmf_ns_resize(event_ctx); 1019 break; 1020 default: 1021 SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type); 1022 break; 1023 } 1024 } 1025 1026 void 1027 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size) 1028 { 1029 /* All current fields are set to 0 by default. */ 1030 memset(opts, 0, opts_size); 1031 } 1032 1033 /* Dummy bdev module used to to claim bdevs. */ 1034 static struct spdk_bdev_module ns_bdev_module = { 1035 .name = "NVMe-oF Target", 1036 }; 1037 1038 static int 1039 spdk_nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info); 1040 static int 1041 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info); 1042 1043 uint32_t 1044 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 1045 const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size, 1046 const char *ptpl_file) 1047 { 1048 struct spdk_nvmf_ns_opts opts; 1049 struct spdk_nvmf_ns *ns; 1050 struct spdk_nvmf_reservation_info info = {0}; 1051 int rc; 1052 1053 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 1054 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 1055 return 0; 1056 } 1057 1058 if (spdk_bdev_get_md_size(bdev) != 0 && !spdk_bdev_is_md_interleaved(bdev)) { 1059 SPDK_ERRLOG("Can't attach bdev with separate metadata.\n"); 1060 return 0; 1061 } 1062 1063 spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts)); 1064 if (user_opts) { 1065 memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size)); 1066 } 1067 1068 if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) { 1069 opts.uuid = *spdk_bdev_get_uuid(bdev); 1070 } 1071 1072 if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) { 1073 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid); 1074 return 0; 1075 } 1076 1077 if (opts.nsid == 0) { 1078 /* 1079 * NSID not specified - find a free index. 1080 * 1081 * If no free slots are found, opts.nsid will be subsystem->max_nsid + 1, which will 1082 * expand max_nsid if possible. 1083 */ 1084 for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) { 1085 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) { 1086 break; 1087 } 1088 } 1089 } 1090 1091 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) { 1092 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid); 1093 return 0; 1094 } 1095 1096 if (opts.nsid > subsystem->max_nsid) { 1097 struct spdk_nvmf_ns **new_ns_array; 1098 1099 /* If MaxNamespaces was specified, we can't extend max_nsid beyond it. */ 1100 if (subsystem->max_allowed_nsid > 0 && opts.nsid > subsystem->max_allowed_nsid) { 1101 SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n"); 1102 return 0; 1103 } 1104 1105 /* If a controller is connected, we can't change NN. */ 1106 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 1107 SPDK_ERRLOG("Can't extend NSID range while controllers are connected\n"); 1108 return 0; 1109 } 1110 1111 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid); 1112 if (new_ns_array == NULL) { 1113 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 1114 return 0; 1115 } 1116 1117 memset(new_ns_array + subsystem->max_nsid, 0, 1118 sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid)); 1119 subsystem->ns = new_ns_array; 1120 subsystem->max_nsid = opts.nsid; 1121 } 1122 1123 ns = calloc(1, sizeof(*ns)); 1124 if (ns == NULL) { 1125 SPDK_ERRLOG("Namespace allocation failed\n"); 1126 return 0; 1127 } 1128 1129 ns->bdev = bdev; 1130 ns->opts = opts; 1131 ns->subsystem = subsystem; 1132 rc = spdk_bdev_open_ext(bdev->name, true, spdk_nvmf_ns_event, ns, &ns->desc); 1133 if (rc != 0) { 1134 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 1135 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 1136 free(ns); 1137 return 0; 1138 } 1139 rc = spdk_bdev_module_claim_bdev(bdev, ns->desc, &ns_bdev_module); 1140 if (rc != 0) { 1141 spdk_bdev_close(ns->desc); 1142 free(ns); 1143 return 0; 1144 } 1145 subsystem->ns[opts.nsid - 1] = ns; 1146 ns->nsid = opts.nsid; 1147 TAILQ_INIT(&ns->registrants); 1148 1149 if (ptpl_file) { 1150 rc = spdk_nvmf_ns_load_reservation(ptpl_file, &info); 1151 if (!rc) { 1152 rc = nvmf_ns_reservation_restore(ns, &info); 1153 if (rc) { 1154 SPDK_ERRLOG("Subsystem restore reservation failed\n"); 1155 subsystem->ns[opts.nsid - 1] = NULL; 1156 spdk_bdev_close(ns->desc); 1157 free(ns); 1158 return 0; 1159 } 1160 } 1161 ns->ptpl_file = strdup(ptpl_file); 1162 } 1163 1164 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 1165 spdk_nvmf_subsystem_get_nqn(subsystem), 1166 spdk_bdev_get_name(bdev), 1167 opts.nsid); 1168 1169 spdk_nvmf_subsystem_ns_changed(subsystem, opts.nsid); 1170 1171 return opts.nsid; 1172 } 1173 1174 static uint32_t 1175 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 1176 uint32_t prev_nsid) 1177 { 1178 uint32_t nsid; 1179 1180 if (prev_nsid >= subsystem->max_nsid) { 1181 return 0; 1182 } 1183 1184 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 1185 if (subsystem->ns[nsid - 1]) { 1186 return nsid; 1187 } 1188 } 1189 1190 return 0; 1191 } 1192 1193 struct spdk_nvmf_ns * 1194 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 1195 { 1196 uint32_t first_nsid; 1197 1198 first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 1199 return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid); 1200 } 1201 1202 struct spdk_nvmf_ns * 1203 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 1204 struct spdk_nvmf_ns *prev_ns) 1205 { 1206 uint32_t next_nsid; 1207 1208 next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid); 1209 return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid); 1210 } 1211 1212 struct spdk_nvmf_ns * 1213 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 1214 { 1215 return _spdk_nvmf_subsystem_get_ns(subsystem, nsid); 1216 } 1217 1218 uint32_t 1219 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 1220 { 1221 return ns->opts.nsid; 1222 } 1223 1224 struct spdk_bdev * 1225 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 1226 { 1227 return ns->bdev; 1228 } 1229 1230 void 1231 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts, 1232 size_t opts_size) 1233 { 1234 memset(opts, 0, opts_size); 1235 memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size)); 1236 } 1237 1238 const char * 1239 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 1240 { 1241 return subsystem->sn; 1242 } 1243 1244 int 1245 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 1246 { 1247 size_t len, max_len; 1248 1249 max_len = sizeof(subsystem->sn) - 1; 1250 len = strlen(sn); 1251 if (len > max_len) { 1252 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 1253 sn, len, max_len); 1254 return -1; 1255 } 1256 1257 if (!spdk_nvmf_valid_ascii_string(sn, len)) { 1258 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n"); 1259 SPDK_LOGDUMP(SPDK_LOG_NVMF, "sn", sn, len); 1260 return -1; 1261 } 1262 1263 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 1264 1265 return 0; 1266 } 1267 1268 const char * 1269 spdk_nvmf_subsystem_get_mn(const struct spdk_nvmf_subsystem *subsystem) 1270 { 1271 return subsystem->mn; 1272 } 1273 1274 int 1275 spdk_nvmf_subsystem_set_mn(struct spdk_nvmf_subsystem *subsystem, const char *mn) 1276 { 1277 size_t len, max_len; 1278 1279 if (mn == NULL) { 1280 mn = MODEL_NUMBER_DEFAULT; 1281 } 1282 max_len = sizeof(subsystem->mn) - 1; 1283 len = strlen(mn); 1284 if (len > max_len) { 1285 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid mn \"%s\": length %zu > max %zu\n", 1286 mn, len, max_len); 1287 return -1; 1288 } 1289 1290 if (!spdk_nvmf_valid_ascii_string(mn, len)) { 1291 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII mn\n"); 1292 SPDK_LOGDUMP(SPDK_LOG_NVMF, "mn", mn, len); 1293 return -1; 1294 } 1295 1296 snprintf(subsystem->mn, sizeof(subsystem->mn), "%s", mn); 1297 1298 return 0; 1299 } 1300 1301 const char * 1302 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem) 1303 { 1304 return subsystem->subnqn; 1305 } 1306 1307 /* Workaround for astyle formatting bug */ 1308 typedef enum spdk_nvmf_subtype nvmf_subtype_t; 1309 1310 nvmf_subtype_t 1311 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 1312 { 1313 return subsystem->subtype; 1314 } 1315 1316 static uint16_t 1317 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 1318 { 1319 int count; 1320 1321 /* 1322 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 1323 * before we find one that is unused (or find that all values are in use). 1324 */ 1325 for (count = 0; count < 0xFFF0 - 1; count++) { 1326 subsystem->next_cntlid++; 1327 if (subsystem->next_cntlid >= 0xFFF0) { 1328 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 1329 subsystem->next_cntlid = 1; 1330 } 1331 1332 /* Check if a controller with this cntlid currently exists. */ 1333 if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 1334 /* Found unused cntlid */ 1335 return subsystem->next_cntlid; 1336 } 1337 } 1338 1339 /* All valid cntlid values are in use. */ 1340 return 0xFFFF; 1341 } 1342 1343 int 1344 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 1345 { 1346 ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem); 1347 if (ctrlr->cntlid == 0xFFFF) { 1348 /* Unable to get a cntlid */ 1349 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 1350 return -EBUSY; 1351 } 1352 1353 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1354 1355 return 0; 1356 } 1357 1358 void 1359 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1360 struct spdk_nvmf_ctrlr *ctrlr) 1361 { 1362 assert(subsystem == ctrlr->subsys); 1363 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1364 } 1365 1366 struct spdk_nvmf_ctrlr * 1367 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1368 { 1369 struct spdk_nvmf_ctrlr *ctrlr; 1370 1371 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1372 if (ctrlr->cntlid == cntlid) { 1373 return ctrlr; 1374 } 1375 } 1376 1377 return NULL; 1378 } 1379 1380 uint32_t 1381 spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem) 1382 { 1383 return subsystem->max_allowed_nsid; 1384 } 1385 1386 struct _nvmf_ns_registrant { 1387 uint64_t rkey; 1388 char *host_uuid; 1389 }; 1390 1391 struct _nvmf_ns_registrants { 1392 size_t num_regs; 1393 struct _nvmf_ns_registrant reg[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1394 }; 1395 1396 struct _nvmf_ns_reservation { 1397 bool ptpl_activated; 1398 enum spdk_nvme_reservation_type rtype; 1399 uint64_t crkey; 1400 char *bdev_uuid; 1401 char *holder_uuid; 1402 struct _nvmf_ns_registrants regs; 1403 }; 1404 1405 static const struct spdk_json_object_decoder nvmf_ns_pr_reg_decoders[] = { 1406 {"rkey", offsetof(struct _nvmf_ns_registrant, rkey), spdk_json_decode_uint64}, 1407 {"host_uuid", offsetof(struct _nvmf_ns_registrant, host_uuid), spdk_json_decode_string}, 1408 }; 1409 1410 static int 1411 nvmf_decode_ns_pr_reg(const struct spdk_json_val *val, void *out) 1412 { 1413 struct _nvmf_ns_registrant *reg = out; 1414 1415 return spdk_json_decode_object(val, nvmf_ns_pr_reg_decoders, 1416 SPDK_COUNTOF(nvmf_ns_pr_reg_decoders), reg); 1417 } 1418 1419 static int 1420 nvmf_decode_ns_pr_regs(const struct spdk_json_val *val, void *out) 1421 { 1422 struct _nvmf_ns_registrants *regs = out; 1423 1424 return spdk_json_decode_array(val, nvmf_decode_ns_pr_reg, regs->reg, 1425 SPDK_NVMF_MAX_NUM_REGISTRANTS, ®s->num_regs, 1426 sizeof(struct _nvmf_ns_registrant)); 1427 } 1428 1429 static const struct spdk_json_object_decoder nvmf_ns_pr_decoders[] = { 1430 {"ptpl", offsetof(struct _nvmf_ns_reservation, ptpl_activated), spdk_json_decode_bool, true}, 1431 {"rtype", offsetof(struct _nvmf_ns_reservation, rtype), spdk_json_decode_uint32, true}, 1432 {"crkey", offsetof(struct _nvmf_ns_reservation, crkey), spdk_json_decode_uint64, true}, 1433 {"bdev_uuid", offsetof(struct _nvmf_ns_reservation, bdev_uuid), spdk_json_decode_string}, 1434 {"holder_uuid", offsetof(struct _nvmf_ns_reservation, holder_uuid), spdk_json_decode_string, true}, 1435 {"registrants", offsetof(struct _nvmf_ns_reservation, regs), nvmf_decode_ns_pr_regs}, 1436 }; 1437 1438 static int 1439 spdk_nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info) 1440 { 1441 FILE *fd; 1442 size_t json_size; 1443 ssize_t values_cnt, rc; 1444 void *json = NULL, *end; 1445 struct spdk_json_val *values = NULL; 1446 struct _nvmf_ns_reservation res = {}; 1447 uint32_t i; 1448 1449 fd = fopen(file, "r"); 1450 /* It's not an error if the file does not exist */ 1451 if (!fd) { 1452 SPDK_NOTICELOG("File %s does not exist\n", file); 1453 return -ENOENT; 1454 } 1455 1456 /* Load all persist file contents into a local buffer */ 1457 json = spdk_posix_file_load(fd, &json_size); 1458 fclose(fd); 1459 if (!json) { 1460 SPDK_ERRLOG("Load persit file %s failed\n", file); 1461 return -ENOMEM; 1462 } 1463 1464 rc = spdk_json_parse(json, json_size, NULL, 0, &end, 0); 1465 if (rc < 0) { 1466 SPDK_NOTICELOG("Parsing JSON configuration failed (%zd)\n", rc); 1467 goto exit; 1468 } 1469 1470 values_cnt = rc; 1471 values = calloc(values_cnt, sizeof(struct spdk_json_val)); 1472 if (values == NULL) { 1473 goto exit; 1474 } 1475 1476 rc = spdk_json_parse(json, json_size, values, values_cnt, &end, 0); 1477 if (rc != values_cnt) { 1478 SPDK_ERRLOG("Parsing JSON configuration failed (%zd)\n", rc); 1479 goto exit; 1480 } 1481 1482 /* Decode json */ 1483 if (spdk_json_decode_object(values, nvmf_ns_pr_decoders, 1484 SPDK_COUNTOF(nvmf_ns_pr_decoders), 1485 &res)) { 1486 SPDK_ERRLOG("Invalid objects in the persist file %s\n", file); 1487 rc = -EINVAL; 1488 goto exit; 1489 } 1490 1491 if (res.regs.num_regs > SPDK_NVMF_MAX_NUM_REGISTRANTS) { 1492 SPDK_ERRLOG("Can only support up to %u registrants\n", SPDK_NVMF_MAX_NUM_REGISTRANTS); 1493 rc = -ERANGE; 1494 goto exit; 1495 } 1496 1497 rc = 0; 1498 info->ptpl_activated = res.ptpl_activated; 1499 info->rtype = res.rtype; 1500 info->crkey = res.crkey; 1501 snprintf(info->bdev_uuid, sizeof(info->bdev_uuid), "%s", res.bdev_uuid); 1502 snprintf(info->holder_uuid, sizeof(info->holder_uuid), "%s", res.holder_uuid); 1503 info->num_regs = res.regs.num_regs; 1504 for (i = 0; i < res.regs.num_regs; i++) { 1505 info->registrants[i].rkey = res.regs.reg[i].rkey; 1506 snprintf(info->registrants[i].host_uuid, sizeof(info->registrants[i].host_uuid), "%s", 1507 res.regs.reg[i].host_uuid); 1508 } 1509 1510 exit: 1511 free(json); 1512 free(values); 1513 free(res.bdev_uuid); 1514 free(res.holder_uuid); 1515 for (i = 0; i < res.regs.num_regs; i++) { 1516 free(res.regs.reg[i].host_uuid); 1517 } 1518 1519 return rc; 1520 } 1521 1522 static bool 1523 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns); 1524 1525 static int 1526 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info) 1527 { 1528 uint32_t i; 1529 struct spdk_nvmf_registrant *reg, *holder = NULL; 1530 struct spdk_uuid bdev_uuid, holder_uuid; 1531 1532 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "NSID %u, PTPL %u, Number of registrants %u\n", 1533 ns->nsid, info->ptpl_activated, info->num_regs); 1534 1535 /* it's not an error */ 1536 if (!info->ptpl_activated || !info->num_regs) { 1537 return 0; 1538 } 1539 1540 spdk_uuid_parse(&bdev_uuid, info->bdev_uuid); 1541 if (spdk_uuid_compare(&bdev_uuid, spdk_bdev_get_uuid(ns->bdev))) { 1542 SPDK_ERRLOG("Existing bdev UUID is not same with configuration file\n"); 1543 return -EINVAL; 1544 } 1545 1546 ns->crkey = info->crkey; 1547 ns->rtype = info->rtype; 1548 ns->ptpl_activated = info->ptpl_activated; 1549 spdk_uuid_parse(&holder_uuid, info->holder_uuid); 1550 1551 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev UUID %s\n", info->bdev_uuid); 1552 if (info->rtype) { 1553 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Holder UUID %s, RTYPE %u, RKEY 0x%"PRIx64"\n", 1554 info->holder_uuid, info->rtype, info->crkey); 1555 } 1556 1557 for (i = 0; i < info->num_regs; i++) { 1558 reg = calloc(1, sizeof(*reg)); 1559 if (!reg) { 1560 return -ENOMEM; 1561 } 1562 spdk_uuid_parse(®->hostid, info->registrants[i].host_uuid); 1563 reg->rkey = info->registrants[i].rkey; 1564 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1565 if (!spdk_uuid_compare(&holder_uuid, ®->hostid)) { 1566 holder = reg; 1567 } 1568 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Registrant RKEY 0x%"PRIx64", Host UUID %s\n", 1569 info->registrants[i].rkey, info->registrants[i].host_uuid); 1570 } 1571 1572 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1573 ns->holder = TAILQ_FIRST(&ns->registrants); 1574 } else { 1575 ns->holder = holder; 1576 } 1577 1578 return 0; 1579 } 1580 1581 static int 1582 spdk_nvmf_ns_json_write_cb(void *cb_ctx, const void *data, size_t size) 1583 { 1584 char *file = cb_ctx; 1585 size_t rc; 1586 FILE *fd; 1587 1588 fd = fopen(file, "w"); 1589 if (!fd) { 1590 SPDK_ERRLOG("Can't open file %s for write\n", file); 1591 return -ENOENT; 1592 } 1593 rc = fwrite(data, 1, size, fd); 1594 fclose(fd); 1595 1596 return rc == size ? 0 : -1; 1597 } 1598 1599 static int 1600 spdk_nvmf_ns_reservation_update(const char *file, struct spdk_nvmf_reservation_info *info) 1601 { 1602 struct spdk_json_write_ctx *w; 1603 uint32_t i; 1604 int rc = 0; 1605 1606 w = spdk_json_write_begin(spdk_nvmf_ns_json_write_cb, (void *)file, 0); 1607 if (w == NULL) { 1608 return -ENOMEM; 1609 } 1610 /* clear the configuration file */ 1611 if (!info->ptpl_activated) { 1612 goto exit; 1613 } 1614 1615 spdk_json_write_object_begin(w); 1616 spdk_json_write_named_bool(w, "ptpl", info->ptpl_activated); 1617 spdk_json_write_named_uint32(w, "rtype", info->rtype); 1618 spdk_json_write_named_uint64(w, "crkey", info->crkey); 1619 spdk_json_write_named_string(w, "bdev_uuid", info->bdev_uuid); 1620 spdk_json_write_named_string(w, "holder_uuid", info->holder_uuid); 1621 1622 spdk_json_write_named_array_begin(w, "registrants"); 1623 for (i = 0; i < info->num_regs; i++) { 1624 spdk_json_write_object_begin(w); 1625 spdk_json_write_named_uint64(w, "rkey", info->registrants[i].rkey); 1626 spdk_json_write_named_string(w, "host_uuid", info->registrants[i].host_uuid); 1627 spdk_json_write_object_end(w); 1628 } 1629 spdk_json_write_array_end(w); 1630 spdk_json_write_object_end(w); 1631 1632 exit: 1633 rc = spdk_json_write_end(w); 1634 return rc; 1635 } 1636 1637 static int 1638 nvmf_ns_update_reservation_info(struct spdk_nvmf_ns *ns) 1639 { 1640 struct spdk_nvmf_reservation_info info; 1641 struct spdk_nvmf_registrant *reg, *tmp; 1642 uint32_t i = 0; 1643 1644 assert(ns != NULL); 1645 1646 if (!ns->bdev || !ns->ptpl_file) { 1647 return 0; 1648 } 1649 1650 memset(&info, 0, sizeof(info)); 1651 spdk_uuid_fmt_lower(info.bdev_uuid, sizeof(info.bdev_uuid), spdk_bdev_get_uuid(ns->bdev)); 1652 1653 if (ns->rtype) { 1654 info.rtype = ns->rtype; 1655 info.crkey = ns->crkey; 1656 if (!nvmf_ns_reservation_all_registrants_type(ns)) { 1657 assert(ns->holder != NULL); 1658 spdk_uuid_fmt_lower(info.holder_uuid, sizeof(info.holder_uuid), &ns->holder->hostid); 1659 } 1660 } 1661 1662 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1663 spdk_uuid_fmt_lower(info.registrants[i].host_uuid, sizeof(info.registrants[i].host_uuid), 1664 ®->hostid); 1665 info.registrants[i++].rkey = reg->rkey; 1666 } 1667 1668 info.num_regs = i; 1669 info.ptpl_activated = ns->ptpl_activated; 1670 1671 return spdk_nvmf_ns_reservation_update(ns->ptpl_file, &info); 1672 } 1673 1674 static struct spdk_nvmf_registrant * 1675 nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns, 1676 struct spdk_uuid *uuid) 1677 { 1678 struct spdk_nvmf_registrant *reg, *tmp; 1679 1680 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1681 if (!spdk_uuid_compare(®->hostid, uuid)) { 1682 return reg; 1683 } 1684 } 1685 1686 return NULL; 1687 } 1688 1689 /* Generate reservation notice log to registered HostID controllers */ 1690 static void 1691 nvmf_subsystem_gen_ctrlr_notification(struct spdk_nvmf_subsystem *subsystem, 1692 struct spdk_nvmf_ns *ns, 1693 struct spdk_uuid *hostid_list, 1694 uint32_t num_hostid, 1695 enum spdk_nvme_reservation_notification_log_page_type type) 1696 { 1697 struct spdk_nvmf_ctrlr *ctrlr; 1698 uint32_t i; 1699 1700 for (i = 0; i < num_hostid; i++) { 1701 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1702 if (!spdk_uuid_compare(&ctrlr->hostid, &hostid_list[i])) { 1703 spdk_nvmf_ctrlr_reservation_notice_log(ctrlr, ns, type); 1704 } 1705 } 1706 } 1707 } 1708 1709 /* Get all registrants' hostid other than the controller who issued the command */ 1710 static uint32_t 1711 nvmf_ns_reservation_get_all_other_hostid(struct spdk_nvmf_ns *ns, 1712 struct spdk_uuid *hostid_list, 1713 uint32_t max_num_hostid, 1714 struct spdk_uuid *current_hostid) 1715 { 1716 struct spdk_nvmf_registrant *reg, *tmp; 1717 uint32_t num_hostid = 0; 1718 1719 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1720 if (spdk_uuid_compare(®->hostid, current_hostid)) { 1721 if (num_hostid == max_num_hostid) { 1722 assert(false); 1723 return max_num_hostid; 1724 } 1725 hostid_list[num_hostid++] = reg->hostid; 1726 } 1727 } 1728 1729 return num_hostid; 1730 } 1731 1732 /* Calculate the unregistered HostID list according to list 1733 * prior to execute preempt command and list after executing 1734 * preempt command. 1735 */ 1736 static uint32_t 1737 nvmf_ns_reservation_get_unregistered_hostid(struct spdk_uuid *old_hostid_list, 1738 uint32_t old_num_hostid, 1739 struct spdk_uuid *remaining_hostid_list, 1740 uint32_t remaining_num_hostid) 1741 { 1742 struct spdk_uuid temp_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1743 uint32_t i, j, num_hostid = 0; 1744 bool found; 1745 1746 if (!remaining_num_hostid) { 1747 return old_num_hostid; 1748 } 1749 1750 for (i = 0; i < old_num_hostid; i++) { 1751 found = false; 1752 for (j = 0; j < remaining_num_hostid; j++) { 1753 if (!spdk_uuid_compare(&old_hostid_list[i], &remaining_hostid_list[j])) { 1754 found = true; 1755 break; 1756 } 1757 } 1758 if (!found) { 1759 spdk_uuid_copy(&temp_hostid_list[num_hostid++], &old_hostid_list[i]); 1760 } 1761 } 1762 1763 if (num_hostid) { 1764 memcpy(old_hostid_list, temp_hostid_list, sizeof(struct spdk_uuid) * num_hostid); 1765 } 1766 1767 return num_hostid; 1768 } 1769 1770 /* current reservation type is all registrants or not */ 1771 static bool 1772 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns) 1773 { 1774 return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS || 1775 ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); 1776 } 1777 1778 /* current registrant is reservation holder or not */ 1779 static bool 1780 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns, 1781 struct spdk_nvmf_registrant *reg) 1782 { 1783 if (!reg) { 1784 return false; 1785 } 1786 1787 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1788 return true; 1789 } 1790 1791 return (ns->holder == reg); 1792 } 1793 1794 static int 1795 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns, 1796 struct spdk_nvmf_ctrlr *ctrlr, 1797 uint64_t nrkey) 1798 { 1799 struct spdk_nvmf_registrant *reg; 1800 1801 reg = calloc(1, sizeof(*reg)); 1802 if (!reg) { 1803 return -ENOMEM; 1804 } 1805 1806 reg->rkey = nrkey; 1807 /* set hostid for the registrant */ 1808 spdk_uuid_copy(®->hostid, &ctrlr->hostid); 1809 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1810 ns->gen++; 1811 1812 return 0; 1813 } 1814 1815 static void 1816 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns) 1817 { 1818 ns->rtype = 0; 1819 ns->crkey = 0; 1820 ns->holder = NULL; 1821 } 1822 1823 /* release the reservation if the last registrant was removed */ 1824 static void 1825 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns, 1826 struct spdk_nvmf_registrant *reg) 1827 { 1828 struct spdk_nvmf_registrant *next_reg; 1829 1830 /* no reservation holder */ 1831 if (!ns->holder) { 1832 assert(ns->rtype == 0); 1833 return; 1834 } 1835 1836 next_reg = TAILQ_FIRST(&ns->registrants); 1837 if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) { 1838 /* the next valid registrant is the new holder now */ 1839 ns->holder = next_reg; 1840 } else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 1841 /* release the reservation */ 1842 nvmf_ns_reservation_release_reservation(ns); 1843 } 1844 } 1845 1846 static void 1847 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns, 1848 struct spdk_nvmf_registrant *reg) 1849 { 1850 TAILQ_REMOVE(&ns->registrants, reg, link); 1851 nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg); 1852 free(reg); 1853 ns->gen++; 1854 return; 1855 } 1856 1857 static uint32_t 1858 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns, 1859 uint64_t rkey) 1860 { 1861 struct spdk_nvmf_registrant *reg, *tmp; 1862 uint32_t count = 0; 1863 1864 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1865 if (reg->rkey == rkey) { 1866 nvmf_ns_reservation_remove_registrant(ns, reg); 1867 count++; 1868 } 1869 } 1870 return count; 1871 } 1872 1873 static uint32_t 1874 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns, 1875 struct spdk_nvmf_registrant *reg) 1876 { 1877 struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2; 1878 uint32_t count = 0; 1879 1880 TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) { 1881 if (reg_tmp != reg) { 1882 nvmf_ns_reservation_remove_registrant(ns, reg_tmp); 1883 count++; 1884 } 1885 } 1886 return count; 1887 } 1888 1889 static uint32_t 1890 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns) 1891 { 1892 struct spdk_nvmf_registrant *reg, *reg_tmp; 1893 uint32_t count = 0; 1894 1895 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 1896 nvmf_ns_reservation_remove_registrant(ns, reg); 1897 count++; 1898 } 1899 return count; 1900 } 1901 1902 static void 1903 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey, 1904 enum spdk_nvme_reservation_type rtype, 1905 struct spdk_nvmf_registrant *holder) 1906 { 1907 ns->rtype = rtype; 1908 ns->crkey = rkey; 1909 assert(ns->holder == NULL); 1910 ns->holder = holder; 1911 } 1912 1913 static bool 1914 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns, 1915 struct spdk_nvmf_ctrlr *ctrlr, 1916 struct spdk_nvmf_request *req) 1917 { 1918 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1919 uint8_t rrega, iekey, cptpl, rtype; 1920 struct spdk_nvme_reservation_register_data key; 1921 struct spdk_nvmf_registrant *reg; 1922 uint8_t status = SPDK_NVME_SC_SUCCESS; 1923 bool update_sgroup = false; 1924 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1925 uint32_t num_hostid = 0; 1926 int rc; 1927 1928 rrega = cmd->cdw10 & 0x7u; 1929 iekey = (cmd->cdw10 >> 3) & 0x1u; 1930 cptpl = (cmd->cdw10 >> 30) & 0x3u; 1931 1932 if (req->data && req->length >= sizeof(key)) { 1933 memcpy(&key, req->data, sizeof(key)); 1934 } else { 1935 SPDK_ERRLOG("No key provided. Failing request.\n"); 1936 status = SPDK_NVME_SC_INVALID_FIELD; 1937 goto exit; 1938 } 1939 1940 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, " 1941 "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n", 1942 rrega, iekey, cptpl, key.crkey, key.nrkey); 1943 1944 if (cptpl == SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON) { 1945 /* Ture to OFF state, and need to be updated in the configuration file */ 1946 if (ns->ptpl_activated) { 1947 ns->ptpl_activated = 0; 1948 update_sgroup = true; 1949 } 1950 } else if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) { 1951 if (ns->ptpl_file == NULL) { 1952 status = SPDK_NVME_SC_INVALID_FIELD; 1953 goto exit; 1954 } else if (ns->ptpl_activated == 0) { 1955 ns->ptpl_activated = 1; 1956 update_sgroup = true; 1957 } 1958 } 1959 1960 /* current Host Identifier has registrant or not */ 1961 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1962 1963 switch (rrega) { 1964 case SPDK_NVME_RESERVE_REGISTER_KEY: 1965 if (!reg) { 1966 /* register new controller */ 1967 if (key.nrkey == 0) { 1968 SPDK_ERRLOG("Can't register zeroed new key\n"); 1969 status = SPDK_NVME_SC_INVALID_FIELD; 1970 goto exit; 1971 } 1972 rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey); 1973 if (rc < 0) { 1974 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 1975 goto exit; 1976 } 1977 update_sgroup = true; 1978 } else { 1979 /* register with same key is not an error */ 1980 if (reg->rkey != key.nrkey) { 1981 SPDK_ERRLOG("The same host already register a " 1982 "key with 0x%"PRIx64"\n", 1983 reg->rkey); 1984 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1985 goto exit; 1986 } 1987 } 1988 break; 1989 case SPDK_NVME_RESERVE_UNREGISTER_KEY: 1990 if (!reg || (!iekey && reg->rkey != key.crkey)) { 1991 SPDK_ERRLOG("No registrant or current key doesn't match " 1992 "with existing registrant key\n"); 1993 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1994 goto exit; 1995 } 1996 1997 rtype = ns->rtype; 1998 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 1999 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2000 &ctrlr->hostid); 2001 2002 nvmf_ns_reservation_remove_registrant(ns, reg); 2003 2004 if (!ns->rtype && num_hostid && (rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY || 2005 rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY)) { 2006 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2007 hostid_list, 2008 num_hostid, 2009 SPDK_NVME_RESERVATION_RELEASED); 2010 } 2011 update_sgroup = true; 2012 break; 2013 case SPDK_NVME_RESERVE_REPLACE_KEY: 2014 if (!reg || (!iekey && reg->rkey != key.crkey)) { 2015 SPDK_ERRLOG("No registrant or current key doesn't match " 2016 "with existing registrant key\n"); 2017 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2018 goto exit; 2019 } 2020 if (key.nrkey == 0) { 2021 SPDK_ERRLOG("Can't register zeroed new key\n"); 2022 status = SPDK_NVME_SC_INVALID_FIELD; 2023 goto exit; 2024 } 2025 reg->rkey = key.nrkey; 2026 update_sgroup = true; 2027 break; 2028 default: 2029 status = SPDK_NVME_SC_INVALID_FIELD; 2030 goto exit; 2031 } 2032 2033 exit: 2034 if (update_sgroup) { 2035 rc = nvmf_ns_update_reservation_info(ns); 2036 if (rc != 0) { 2037 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2038 } 2039 } 2040 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2041 req->rsp->nvme_cpl.status.sc = status; 2042 return update_sgroup; 2043 } 2044 2045 static bool 2046 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns, 2047 struct spdk_nvmf_ctrlr *ctrlr, 2048 struct spdk_nvmf_request *req) 2049 { 2050 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2051 uint8_t racqa, iekey, rtype; 2052 struct spdk_nvme_reservation_acquire_data key; 2053 struct spdk_nvmf_registrant *reg; 2054 bool all_regs = false; 2055 uint32_t count = 0; 2056 bool update_sgroup = true; 2057 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 2058 uint32_t num_hostid = 0; 2059 struct spdk_uuid new_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 2060 uint32_t new_num_hostid = 0; 2061 bool reservation_released = false; 2062 uint8_t status = SPDK_NVME_SC_SUCCESS; 2063 2064 racqa = cmd->cdw10 & 0x7u; 2065 iekey = (cmd->cdw10 >> 3) & 0x1u; 2066 rtype = (cmd->cdw10 >> 8) & 0xffu; 2067 2068 if (req->data && req->length >= sizeof(key)) { 2069 memcpy(&key, req->data, sizeof(key)); 2070 } else { 2071 SPDK_ERRLOG("No key provided. Failing request.\n"); 2072 status = SPDK_NVME_SC_INVALID_FIELD; 2073 goto exit; 2074 } 2075 2076 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, " 2077 "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n", 2078 racqa, iekey, rtype, key.crkey, key.prkey); 2079 2080 if (iekey || rtype > SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS) { 2081 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 2082 status = SPDK_NVME_SC_INVALID_FIELD; 2083 update_sgroup = false; 2084 goto exit; 2085 } 2086 2087 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 2088 /* must be registrant and CRKEY must match */ 2089 if (!reg || reg->rkey != key.crkey) { 2090 SPDK_ERRLOG("No registrant or current key doesn't match " 2091 "with existing registrant key\n"); 2092 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2093 update_sgroup = false; 2094 goto exit; 2095 } 2096 2097 all_regs = nvmf_ns_reservation_all_registrants_type(ns); 2098 2099 switch (racqa) { 2100 case SPDK_NVME_RESERVE_ACQUIRE: 2101 /* it's not an error for the holder to acquire same reservation type again */ 2102 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) { 2103 /* do nothing */ 2104 update_sgroup = false; 2105 } else if (ns->holder == NULL) { 2106 /* fisrt time to acquire the reservation */ 2107 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 2108 } else { 2109 SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n"); 2110 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2111 update_sgroup = false; 2112 goto exit; 2113 } 2114 break; 2115 case SPDK_NVME_RESERVE_PREEMPT: 2116 /* no reservation holder */ 2117 if (!ns->holder) { 2118 /* unregister with PRKEY */ 2119 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2120 break; 2121 } 2122 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 2123 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2124 &ctrlr->hostid); 2125 2126 /* only 1 reservation holder and reservation key is valid */ 2127 if (!all_regs) { 2128 /* preempt itself */ 2129 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && 2130 ns->crkey == key.prkey) { 2131 ns->rtype = rtype; 2132 reservation_released = true; 2133 break; 2134 } 2135 2136 if (ns->crkey == key.prkey) { 2137 nvmf_ns_reservation_remove_registrant(ns, ns->holder); 2138 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 2139 reservation_released = true; 2140 } else if (key.prkey != 0) { 2141 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2142 } else { 2143 /* PRKEY is zero */ 2144 SPDK_ERRLOG("Current PRKEY is zero\n"); 2145 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2146 update_sgroup = false; 2147 goto exit; 2148 } 2149 } else { 2150 /* release all other registrants except for the current one */ 2151 if (key.prkey == 0) { 2152 nvmf_ns_reservation_remove_all_other_registrants(ns, reg); 2153 assert(ns->holder == reg); 2154 } else { 2155 count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2156 if (count == 0) { 2157 SPDK_ERRLOG("PRKEY doesn't match any registrant\n"); 2158 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2159 update_sgroup = false; 2160 goto exit; 2161 } 2162 } 2163 } 2164 break; 2165 default: 2166 status = SPDK_NVME_SC_INVALID_FIELD; 2167 update_sgroup = false; 2168 break; 2169 } 2170 2171 exit: 2172 if (update_sgroup && racqa == SPDK_NVME_RESERVE_PREEMPT) { 2173 new_num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, new_hostid_list, 2174 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2175 &ctrlr->hostid); 2176 /* Preempt notification occurs on the unregistered controllers 2177 * other than the controller who issued the command. 2178 */ 2179 num_hostid = nvmf_ns_reservation_get_unregistered_hostid(hostid_list, 2180 num_hostid, 2181 new_hostid_list, 2182 new_num_hostid); 2183 if (num_hostid) { 2184 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2185 hostid_list, 2186 num_hostid, 2187 SPDK_NVME_REGISTRATION_PREEMPTED); 2188 2189 } 2190 /* Reservation released notification occurs on the 2191 * controllers which are the remaining registrants other than 2192 * the controller who issued the command. 2193 */ 2194 if (reservation_released && new_num_hostid) { 2195 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2196 new_hostid_list, 2197 new_num_hostid, 2198 SPDK_NVME_RESERVATION_RELEASED); 2199 2200 } 2201 } 2202 if (update_sgroup && ns->ptpl_activated) { 2203 if (nvmf_ns_update_reservation_info(ns)) { 2204 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2205 } 2206 } 2207 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2208 req->rsp->nvme_cpl.status.sc = status; 2209 return update_sgroup; 2210 } 2211 2212 static bool 2213 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns, 2214 struct spdk_nvmf_ctrlr *ctrlr, 2215 struct spdk_nvmf_request *req) 2216 { 2217 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2218 uint8_t rrela, iekey, rtype; 2219 struct spdk_nvmf_registrant *reg; 2220 uint64_t crkey; 2221 uint8_t status = SPDK_NVME_SC_SUCCESS; 2222 bool update_sgroup = true; 2223 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 2224 uint32_t num_hostid = 0; 2225 2226 rrela = cmd->cdw10 & 0x7u; 2227 iekey = (cmd->cdw10 >> 3) & 0x1u; 2228 rtype = (cmd->cdw10 >> 8) & 0xffu; 2229 2230 if (req->data && req->length >= sizeof(crkey)) { 2231 memcpy(&crkey, req->data, sizeof(crkey)); 2232 } else { 2233 SPDK_ERRLOG("No key provided. Failing request.\n"); 2234 status = SPDK_NVME_SC_INVALID_FIELD; 2235 goto exit; 2236 } 2237 2238 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, " 2239 "CRKEY 0x%"PRIx64"\n", rrela, iekey, rtype, crkey); 2240 2241 if (iekey) { 2242 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 2243 status = SPDK_NVME_SC_INVALID_FIELD; 2244 update_sgroup = false; 2245 goto exit; 2246 } 2247 2248 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 2249 if (!reg || reg->rkey != crkey) { 2250 SPDK_ERRLOG("No registrant or current key doesn't match " 2251 "with existing registrant key\n"); 2252 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2253 update_sgroup = false; 2254 goto exit; 2255 } 2256 2257 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 2258 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2259 &ctrlr->hostid); 2260 2261 switch (rrela) { 2262 case SPDK_NVME_RESERVE_RELEASE: 2263 if (!ns->holder) { 2264 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n"); 2265 update_sgroup = false; 2266 goto exit; 2267 } 2268 if (ns->rtype != rtype) { 2269 SPDK_ERRLOG("Type doesn't match\n"); 2270 status = SPDK_NVME_SC_INVALID_FIELD; 2271 update_sgroup = false; 2272 goto exit; 2273 } 2274 if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 2275 /* not the reservation holder, this isn't an error */ 2276 update_sgroup = false; 2277 goto exit; 2278 } 2279 2280 rtype = ns->rtype; 2281 nvmf_ns_reservation_release_reservation(ns); 2282 2283 if (num_hostid && rtype != SPDK_NVME_RESERVE_WRITE_EXCLUSIVE && 2284 rtype != SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS) { 2285 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2286 hostid_list, 2287 num_hostid, 2288 SPDK_NVME_RESERVATION_RELEASED); 2289 } 2290 break; 2291 case SPDK_NVME_RESERVE_CLEAR: 2292 nvmf_ns_reservation_clear_all_registrants(ns); 2293 if (num_hostid) { 2294 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2295 hostid_list, 2296 num_hostid, 2297 SPDK_NVME_RESERVATION_PREEMPTED); 2298 } 2299 break; 2300 default: 2301 status = SPDK_NVME_SC_INVALID_FIELD; 2302 update_sgroup = false; 2303 goto exit; 2304 } 2305 2306 exit: 2307 if (update_sgroup && ns->ptpl_activated) { 2308 if (nvmf_ns_update_reservation_info(ns)) { 2309 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2310 } 2311 } 2312 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2313 req->rsp->nvme_cpl.status.sc = status; 2314 return update_sgroup; 2315 } 2316 2317 static void 2318 nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns, 2319 struct spdk_nvmf_ctrlr *ctrlr, 2320 struct spdk_nvmf_request *req) 2321 { 2322 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2323 struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; 2324 struct spdk_nvmf_ctrlr *ctrlr_tmp; 2325 struct spdk_nvmf_registrant *reg, *tmp; 2326 struct spdk_nvme_reservation_status_extended_data *status_data; 2327 struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data; 2328 uint8_t *payload; 2329 uint32_t len, count = 0; 2330 uint32_t regctl = 0; 2331 uint8_t status = SPDK_NVME_SC_SUCCESS; 2332 2333 if (req->data == NULL) { 2334 SPDK_ERRLOG("No data transfer specified for request. " 2335 " Unable to transfer back response.\n"); 2336 status = SPDK_NVME_SC_INVALID_FIELD; 2337 goto exit; 2338 } 2339 2340 /* NVMeoF uses Extended Data Structure */ 2341 if ((cmd->cdw11 & 0x00000001u) == 0) { 2342 SPDK_ERRLOG("NVMeoF uses extended controller data structure, " 2343 "please set EDS bit in cdw11 and try again\n"); 2344 status = SPDK_NVME_SC_INVALID_FIELD; 2345 goto exit; 2346 } 2347 2348 /* Get number of registerd controllers, one Host may have more than 2349 * one controller based on different ports. 2350 */ 2351 TAILQ_FOREACH(ctrlr_tmp, &subsystem->ctrlrs, link) { 2352 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr_tmp->hostid); 2353 if (reg) { 2354 regctl++; 2355 } 2356 } 2357 2358 len = sizeof(*status_data) + sizeof(*ctrlr_data) * regctl; 2359 payload = calloc(1, len); 2360 if (!payload) { 2361 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2362 goto exit; 2363 } 2364 2365 status_data = (struct spdk_nvme_reservation_status_extended_data *)payload; 2366 status_data->data.gen = ns->gen; 2367 status_data->data.rtype = ns->rtype; 2368 status_data->data.regctl = regctl; 2369 status_data->data.ptpls = ns->ptpl_activated; 2370 2371 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 2372 assert(count <= regctl); 2373 ctrlr_data = (struct spdk_nvme_registered_ctrlr_extended_data *) 2374 (payload + sizeof(*status_data) + sizeof(*ctrlr_data) * count); 2375 /* Set to 0xffffh for dynamic controller */ 2376 ctrlr_data->cntlid = 0xffff; 2377 ctrlr_data->rcsts.status = (ns->holder == reg) ? true : false; 2378 ctrlr_data->rkey = reg->rkey; 2379 spdk_uuid_copy((struct spdk_uuid *)ctrlr_data->hostid, ®->hostid); 2380 count++; 2381 } 2382 2383 memcpy(req->data, payload, spdk_min(len, (cmd->cdw10 + 1) * sizeof(uint32_t))); 2384 free(payload); 2385 2386 exit: 2387 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2388 req->rsp->nvme_cpl.status.sc = status; 2389 return; 2390 } 2391 2392 static void 2393 spdk_nvmf_ns_reservation_complete(void *ctx) 2394 { 2395 struct spdk_nvmf_request *req = ctx; 2396 2397 spdk_nvmf_request_complete(req); 2398 } 2399 2400 static void 2401 _nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem, 2402 void *cb_arg, int status) 2403 { 2404 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg; 2405 struct spdk_nvmf_poll_group *group = req->qpair->group; 2406 2407 spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req); 2408 } 2409 2410 void 2411 spdk_nvmf_ns_reservation_request(void *ctx) 2412 { 2413 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx; 2414 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2415 struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; 2416 struct subsystem_update_ns_ctx *update_ctx; 2417 uint32_t nsid; 2418 struct spdk_nvmf_ns *ns; 2419 bool update_sgroup = false; 2420 2421 nsid = cmd->nsid; 2422 ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid); 2423 assert(ns != NULL); 2424 2425 switch (cmd->opc) { 2426 case SPDK_NVME_OPC_RESERVATION_REGISTER: 2427 update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req); 2428 break; 2429 case SPDK_NVME_OPC_RESERVATION_ACQUIRE: 2430 update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req); 2431 break; 2432 case SPDK_NVME_OPC_RESERVATION_RELEASE: 2433 update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req); 2434 break; 2435 case SPDK_NVME_OPC_RESERVATION_REPORT: 2436 nvmf_ns_reservation_report(ns, ctrlr, req); 2437 break; 2438 default: 2439 break; 2440 } 2441 2442 /* update reservation information to subsystem's poll group */ 2443 if (update_sgroup) { 2444 update_ctx = calloc(1, sizeof(*update_ctx)); 2445 if (update_ctx == NULL) { 2446 SPDK_ERRLOG("Can't alloc subsystem poll group update context\n"); 2447 goto update_done; 2448 } 2449 update_ctx->subsystem = ctrlr->subsys; 2450 update_ctx->cb_fn = _nvmf_ns_reservation_update_done; 2451 update_ctx->cb_arg = req; 2452 2453 spdk_nvmf_subsystem_update_ns(ctrlr->subsys, subsystem_update_ns_done, update_ctx); 2454 return; 2455 } 2456 2457 update_done: 2458 _nvmf_ns_reservation_update_done(ctrlr->subsys, (void *)req, 0); 2459 } 2460