1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "nvmf_internal.h" 37 #include "transport.h" 38 39 #include "spdk/event.h" 40 #include "spdk/likely.h" 41 #include "spdk/string.h" 42 #include "spdk/trace.h" 43 #include "spdk/nvmf_spec.h" 44 #include "spdk/uuid.h" 45 #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 380 switch (state) { 381 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 382 expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 383 break; 384 case SPDK_NVMF_SUBSYSTEM_ACTIVATING: 385 expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 386 break; 387 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 388 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 389 break; 390 case SPDK_NVMF_SUBSYSTEM_PAUSING: 391 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 392 break; 393 case SPDK_NVMF_SUBSYSTEM_PAUSED: 394 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 395 break; 396 case SPDK_NVMF_SUBSYSTEM_RESUMING: 397 expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED; 398 break; 399 case SPDK_NVMF_SUBSYSTEM_DEACTIVATING: 400 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 401 break; 402 default: 403 assert(false); 404 return -1; 405 } 406 407 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 408 if (actual_old_state != expected_old_state) { 409 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING && 410 state == SPDK_NVMF_SUBSYSTEM_ACTIVE) { 411 expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 412 } 413 /* This is for the case when activating the subsystem fails. */ 414 if (actual_old_state == SPDK_NVMF_SUBSYSTEM_ACTIVATING && 415 state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) { 416 expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 417 } 418 actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state); 419 } 420 assert(actual_old_state == expected_old_state); 421 return actual_old_state - expected_old_state; 422 } 423 424 struct subsystem_state_change_ctx { 425 struct spdk_nvmf_subsystem *subsystem; 426 427 enum spdk_nvmf_subsystem_state requested_state; 428 429 spdk_nvmf_subsystem_state_change_done cb_fn; 430 void *cb_arg; 431 }; 432 433 static void 434 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status) 435 { 436 struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 437 438 if (status == 0) { 439 status = spdk_nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state); 440 if (status) { 441 status = -1; 442 } 443 } 444 445 if (ctx->cb_fn) { 446 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 447 } 448 free(ctx); 449 } 450 451 static void 452 subsystem_state_change_continue(void *ctx, int status) 453 { 454 struct spdk_io_channel_iter *i = ctx; 455 spdk_for_each_channel_continue(i, status); 456 } 457 458 static void 459 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i) 460 { 461 struct subsystem_state_change_ctx *ctx; 462 struct spdk_io_channel *ch; 463 struct spdk_nvmf_poll_group *group; 464 465 ctx = spdk_io_channel_iter_get_ctx(i); 466 ch = spdk_io_channel_iter_get_channel(i); 467 group = spdk_io_channel_get_ctx(ch); 468 469 switch (ctx->requested_state) { 470 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 471 spdk_nvmf_poll_group_remove_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 472 break; 473 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 474 if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) { 475 spdk_nvmf_poll_group_add_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 476 } else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) { 477 spdk_nvmf_poll_group_resume_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 478 } 479 break; 480 case SPDK_NVMF_SUBSYSTEM_PAUSED: 481 spdk_nvmf_poll_group_pause_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i); 482 break; 483 default: 484 assert(false); 485 break; 486 } 487 } 488 489 static int 490 spdk_nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem, 491 enum spdk_nvmf_subsystem_state requested_state, 492 spdk_nvmf_subsystem_state_change_done cb_fn, 493 void *cb_arg) 494 { 495 struct subsystem_state_change_ctx *ctx; 496 enum spdk_nvmf_subsystem_state intermediate_state; 497 int rc; 498 499 switch (requested_state) { 500 case SPDK_NVMF_SUBSYSTEM_INACTIVE: 501 intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING; 502 break; 503 case SPDK_NVMF_SUBSYSTEM_ACTIVE: 504 if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) { 505 intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING; 506 } else { 507 intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING; 508 } 509 break; 510 case SPDK_NVMF_SUBSYSTEM_PAUSED: 511 intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING; 512 break; 513 default: 514 assert(false); 515 return -EINVAL; 516 } 517 518 ctx = calloc(1, sizeof(*ctx)); 519 if (!ctx) { 520 return -ENOMEM; 521 } 522 523 rc = spdk_nvmf_subsystem_set_state(subsystem, intermediate_state); 524 if (rc) { 525 free(ctx); 526 return rc; 527 } 528 529 ctx->subsystem = subsystem; 530 ctx->requested_state = requested_state; 531 ctx->cb_fn = cb_fn; 532 ctx->cb_arg = cb_arg; 533 534 spdk_for_each_channel(subsystem->tgt, 535 subsystem_state_change_on_pg, 536 ctx, 537 subsystem_state_change_done); 538 539 return 0; 540 } 541 542 int 543 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem, 544 spdk_nvmf_subsystem_state_change_done cb_fn, 545 void *cb_arg) 546 { 547 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 548 } 549 550 int 551 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem, 552 spdk_nvmf_subsystem_state_change_done cb_fn, 553 void *cb_arg) 554 { 555 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg); 556 } 557 558 int 559 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem, 560 spdk_nvmf_subsystem_state_change_done cb_fn, 561 void *cb_arg) 562 { 563 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg); 564 } 565 566 int 567 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem, 568 spdk_nvmf_subsystem_state_change_done cb_fn, 569 void *cb_arg) 570 { 571 return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg); 572 } 573 574 struct spdk_nvmf_subsystem * 575 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt) 576 { 577 struct spdk_nvmf_subsystem *subsystem; 578 uint32_t sid; 579 580 for (sid = 0; sid < tgt->max_subsystems; sid++) { 581 subsystem = tgt->subsystems[sid]; 582 if (subsystem) { 583 return subsystem; 584 } 585 } 586 587 return NULL; 588 } 589 590 struct spdk_nvmf_subsystem * 591 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem) 592 { 593 uint32_t sid; 594 struct spdk_nvmf_tgt *tgt; 595 596 if (!subsystem) { 597 return NULL; 598 } 599 600 tgt = subsystem->tgt; 601 602 for (sid = subsystem->id + 1; sid < tgt->max_subsystems; sid++) { 603 subsystem = tgt->subsystems[sid]; 604 if (subsystem) { 605 return subsystem; 606 } 607 } 608 609 return NULL; 610 } 611 612 static struct spdk_nvmf_host * 613 _spdk_nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 614 { 615 struct spdk_nvmf_host *host = NULL; 616 617 TAILQ_FOREACH(host, &subsystem->hosts, link) { 618 if (strcmp(hostnqn, host->nqn) == 0) { 619 return host; 620 } 621 } 622 623 return NULL; 624 } 625 626 int 627 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 628 { 629 struct spdk_nvmf_host *host; 630 631 if (!spdk_nvmf_valid_nqn(hostnqn)) { 632 return -EINVAL; 633 } 634 635 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 636 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 637 return -EAGAIN; 638 } 639 640 if (_spdk_nvmf_subsystem_find_host(subsystem, hostnqn)) { 641 /* This subsystem already allows the specified host. */ 642 return 0; 643 } 644 645 host = calloc(1, sizeof(*host)); 646 if (!host) { 647 return -ENOMEM; 648 } 649 650 snprintf(host->nqn, sizeof(host->nqn), "%s", hostnqn); 651 652 TAILQ_INSERT_HEAD(&subsystem->hosts, host, link); 653 subsystem->tgt->discovery_genctr++; 654 655 return 0; 656 } 657 658 int 659 spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 660 { 661 struct spdk_nvmf_host *host; 662 663 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 664 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 665 return -EAGAIN; 666 } 667 668 host = _spdk_nvmf_subsystem_find_host(subsystem, hostnqn); 669 if (host == NULL) { 670 return -ENOENT; 671 } 672 673 _spdk_nvmf_subsystem_remove_host(subsystem, host); 674 return 0; 675 } 676 677 int 678 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host) 679 { 680 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 681 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 682 return -EAGAIN; 683 } 684 685 subsystem->allow_any_host = allow_any_host; 686 687 return 0; 688 } 689 690 bool 691 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem) 692 { 693 return subsystem->allow_any_host; 694 } 695 696 bool 697 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn) 698 { 699 if (!hostnqn) { 700 return false; 701 } 702 703 if (subsystem->allow_any_host) { 704 return true; 705 } 706 707 return _spdk_nvmf_subsystem_find_host(subsystem, hostnqn) != NULL; 708 } 709 710 struct spdk_nvmf_host * 711 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem) 712 { 713 return TAILQ_FIRST(&subsystem->hosts); 714 } 715 716 717 struct spdk_nvmf_host * 718 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem, 719 struct spdk_nvmf_host *prev_host) 720 { 721 return TAILQ_NEXT(prev_host, link); 722 } 723 724 const char * 725 spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host) 726 { 727 return host->nqn; 728 } 729 730 static struct spdk_nvmf_listener * 731 _spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, 732 const struct spdk_nvme_transport_id *trid) 733 { 734 struct spdk_nvmf_listener *listener; 735 736 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 737 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 738 return listener; 739 } 740 } 741 742 return NULL; 743 } 744 745 int 746 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, 747 struct spdk_nvme_transport_id *trid) 748 { 749 struct spdk_nvmf_transport *transport; 750 struct spdk_nvmf_listener *listener; 751 752 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 753 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 754 return -EAGAIN; 755 } 756 757 if (_spdk_nvmf_subsystem_find_listener(subsystem, trid)) { 758 /* Listener already exists in this subsystem */ 759 return 0; 760 } 761 762 transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype); 763 if (transport == NULL) { 764 SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype); 765 return -EINVAL; 766 } 767 768 listener = calloc(1, sizeof(*listener)); 769 if (!listener) { 770 return -ENOMEM; 771 } 772 773 listener->trid = *trid; 774 listener->transport = transport; 775 776 TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link); 777 778 return 0; 779 } 780 781 int 782 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, 783 const struct spdk_nvme_transport_id *trid) 784 { 785 struct spdk_nvmf_listener *listener; 786 787 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 788 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 789 return -EAGAIN; 790 } 791 792 listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid); 793 if (listener == NULL) { 794 return -ENOENT; 795 } 796 797 _nvmf_subsystem_remove_listener(subsystem, listener); 798 799 return 0; 800 } 801 802 bool 803 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, 804 struct spdk_nvme_transport_id *trid) 805 { 806 struct spdk_nvmf_listener *listener; 807 808 if (!strcmp(subsystem->subnqn, SPDK_NVMF_DISCOVERY_NQN)) { 809 return true; 810 } 811 812 TAILQ_FOREACH(listener, &subsystem->listeners, link) { 813 if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) { 814 return true; 815 } 816 } 817 818 return false; 819 } 820 821 struct spdk_nvmf_listener * 822 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem) 823 { 824 return TAILQ_FIRST(&subsystem->listeners); 825 } 826 827 struct spdk_nvmf_listener * 828 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem, 829 struct spdk_nvmf_listener *prev_listener) 830 { 831 return TAILQ_NEXT(prev_listener, link); 832 } 833 834 const struct spdk_nvme_transport_id * 835 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener) 836 { 837 return &listener->trid; 838 } 839 840 struct subsystem_update_ns_ctx { 841 struct spdk_nvmf_subsystem *subsystem; 842 843 spdk_nvmf_subsystem_state_change_done cb_fn; 844 void *cb_arg; 845 }; 846 847 static void 848 subsystem_update_ns_done(struct spdk_io_channel_iter *i, int status) 849 { 850 struct subsystem_update_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 851 852 if (ctx->cb_fn) { 853 ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status); 854 } 855 free(ctx); 856 } 857 858 static void 859 subsystem_update_ns_on_pg(struct spdk_io_channel_iter *i) 860 { 861 int rc; 862 struct subsystem_update_ns_ctx *ctx; 863 struct spdk_nvmf_poll_group *group; 864 struct spdk_nvmf_subsystem *subsystem; 865 866 ctx = spdk_io_channel_iter_get_ctx(i); 867 group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i)); 868 subsystem = ctx->subsystem; 869 870 rc = spdk_nvmf_poll_group_update_subsystem(group, subsystem); 871 spdk_for_each_channel_continue(i, rc); 872 } 873 874 static int 875 spdk_nvmf_subsystem_update_ns(struct spdk_nvmf_subsystem *subsystem, spdk_channel_for_each_cpl cpl, 876 void *ctx) 877 { 878 spdk_for_each_channel(subsystem->tgt, 879 subsystem_update_ns_on_pg, 880 ctx, 881 cpl); 882 883 return 0; 884 } 885 886 static void 887 spdk_nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 888 { 889 struct spdk_nvmf_ctrlr *ctrlr; 890 891 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 892 spdk_nvmf_ctrlr_ns_changed(ctrlr, nsid); 893 } 894 } 895 896 int 897 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 898 { 899 struct spdk_nvmf_ns *ns; 900 struct spdk_nvmf_registrant *reg, *reg_tmp; 901 902 assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED || 903 subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); 904 905 if (nsid == 0 || nsid > subsystem->max_nsid) { 906 return -1; 907 } 908 909 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 910 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 911 return -1; 912 } 913 914 ns = subsystem->ns[nsid - 1]; 915 if (!ns) { 916 return -1; 917 } 918 919 subsystem->ns[nsid - 1] = NULL; 920 921 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 922 TAILQ_REMOVE(&ns->registrants, reg, link); 923 free(reg); 924 } 925 spdk_bdev_module_release_bdev(ns->bdev); 926 spdk_bdev_close(ns->desc); 927 if (ns->ptpl_file) { 928 free(ns->ptpl_file); 929 } 930 free(ns); 931 932 spdk_nvmf_subsystem_ns_changed(subsystem, nsid); 933 934 return 0; 935 } 936 937 static void 938 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem, 939 void *cb_arg, int status) 940 { 941 struct spdk_nvmf_ns *ns = cb_arg; 942 int rc; 943 944 rc = spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid); 945 if (rc != 0) { 946 SPDK_ERRLOG("Failed to make changes to NVME-oF subsystem with id: %u\n", subsystem->id); 947 } 948 949 spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); 950 } 951 952 static void 953 spdk_nvmf_ns_hot_remove(void *remove_ctx) 954 { 955 struct spdk_nvmf_ns *ns = remove_ctx; 956 int rc; 957 958 rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns); 959 if (rc) { 960 SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n"); 961 } 962 } 963 964 void 965 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size) 966 { 967 /* All current fields are set to 0 by default. */ 968 memset(opts, 0, opts_size); 969 } 970 971 /* Dummy bdev module used to to claim bdevs. */ 972 static struct spdk_bdev_module ns_bdev_module = { 973 .name = "NVMe-oF Target", 974 }; 975 976 static int 977 spdk_nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info); 978 static int 979 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info); 980 981 uint32_t 982 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, 983 const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size, 984 const char *ptpl_file) 985 { 986 struct spdk_nvmf_ns_opts opts; 987 struct spdk_nvmf_ns *ns; 988 struct spdk_nvmf_reservation_info info = {0}; 989 int rc; 990 991 if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || 992 subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) { 993 return 0; 994 } 995 996 if (spdk_bdev_get_md_size(bdev) != 0 && !spdk_bdev_is_md_interleaved(bdev)) { 997 SPDK_ERRLOG("Can't attach bdev with separate metadata.\n"); 998 return 0; 999 } 1000 1001 spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts)); 1002 if (user_opts) { 1003 memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size)); 1004 } 1005 1006 if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) { 1007 opts.uuid = *spdk_bdev_get_uuid(bdev); 1008 } 1009 1010 if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) { 1011 SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid); 1012 return 0; 1013 } 1014 1015 if (opts.nsid == 0) { 1016 /* 1017 * NSID not specified - find a free index. 1018 * 1019 * If no free slots are found, opts.nsid will be subsystem->max_nsid + 1, which will 1020 * expand max_nsid if possible. 1021 */ 1022 for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) { 1023 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) { 1024 break; 1025 } 1026 } 1027 } 1028 1029 if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) { 1030 SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid); 1031 return 0; 1032 } 1033 1034 if (opts.nsid > subsystem->max_nsid) { 1035 struct spdk_nvmf_ns **new_ns_array; 1036 1037 /* If MaxNamespaces was specified, we can't extend max_nsid beyond it. */ 1038 if (subsystem->max_allowed_nsid > 0 && opts.nsid > subsystem->max_allowed_nsid) { 1039 SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n"); 1040 return 0; 1041 } 1042 1043 /* If a controller is connected, we can't change NN. */ 1044 if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { 1045 SPDK_ERRLOG("Can't extend NSID range while controllers are connected\n"); 1046 return 0; 1047 } 1048 1049 new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid); 1050 if (new_ns_array == NULL) { 1051 SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); 1052 return 0; 1053 } 1054 1055 memset(new_ns_array + subsystem->max_nsid, 0, 1056 sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid)); 1057 subsystem->ns = new_ns_array; 1058 subsystem->max_nsid = opts.nsid; 1059 } 1060 1061 ns = calloc(1, sizeof(*ns)); 1062 if (ns == NULL) { 1063 SPDK_ERRLOG("Namespace allocation failed\n"); 1064 return 0; 1065 } 1066 1067 ns->bdev = bdev; 1068 ns->opts = opts; 1069 ns->subsystem = subsystem; 1070 rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc); 1071 if (rc != 0) { 1072 SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n", 1073 subsystem->subnqn, spdk_bdev_get_name(bdev), rc); 1074 free(ns); 1075 return 0; 1076 } 1077 rc = spdk_bdev_module_claim_bdev(bdev, ns->desc, &ns_bdev_module); 1078 if (rc != 0) { 1079 spdk_bdev_close(ns->desc); 1080 free(ns); 1081 return 0; 1082 } 1083 subsystem->ns[opts.nsid - 1] = ns; 1084 ns->nsid = opts.nsid; 1085 TAILQ_INIT(&ns->registrants); 1086 1087 if (ptpl_file) { 1088 rc = spdk_nvmf_ns_load_reservation(ptpl_file, &info); 1089 if (!rc) { 1090 rc = nvmf_ns_reservation_restore(ns, &info); 1091 if (rc) { 1092 SPDK_ERRLOG("Subsystem restore reservation failed\n"); 1093 subsystem->ns[opts.nsid - 1] = NULL; 1094 spdk_bdev_close(ns->desc); 1095 free(ns); 1096 return 0; 1097 } 1098 } 1099 ns->ptpl_file = strdup(ptpl_file); 1100 } 1101 1102 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", 1103 spdk_nvmf_subsystem_get_nqn(subsystem), 1104 spdk_bdev_get_name(bdev), 1105 opts.nsid); 1106 1107 spdk_nvmf_subsystem_ns_changed(subsystem, opts.nsid); 1108 1109 return opts.nsid; 1110 } 1111 1112 static uint32_t 1113 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem, 1114 uint32_t prev_nsid) 1115 { 1116 uint32_t nsid; 1117 1118 if (prev_nsid >= subsystem->max_nsid) { 1119 return 0; 1120 } 1121 1122 for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) { 1123 if (subsystem->ns[nsid - 1]) { 1124 return nsid; 1125 } 1126 } 1127 1128 return 0; 1129 } 1130 1131 struct spdk_nvmf_ns * 1132 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem) 1133 { 1134 uint32_t first_nsid; 1135 1136 first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0); 1137 return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid); 1138 } 1139 1140 struct spdk_nvmf_ns * 1141 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem, 1142 struct spdk_nvmf_ns *prev_ns) 1143 { 1144 uint32_t next_nsid; 1145 1146 next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid); 1147 return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid); 1148 } 1149 1150 struct spdk_nvmf_ns * 1151 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 1152 { 1153 return _spdk_nvmf_subsystem_get_ns(subsystem, nsid); 1154 } 1155 1156 uint32_t 1157 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns) 1158 { 1159 return ns->opts.nsid; 1160 } 1161 1162 struct spdk_bdev * 1163 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns) 1164 { 1165 return ns->bdev; 1166 } 1167 1168 void 1169 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts, 1170 size_t opts_size) 1171 { 1172 memset(opts, 0, opts_size); 1173 memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size)); 1174 } 1175 1176 const char * 1177 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem) 1178 { 1179 return subsystem->sn; 1180 } 1181 1182 int 1183 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn) 1184 { 1185 size_t len, max_len; 1186 1187 max_len = sizeof(subsystem->sn) - 1; 1188 len = strlen(sn); 1189 if (len > max_len) { 1190 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n", 1191 sn, len, max_len); 1192 return -1; 1193 } 1194 1195 if (!spdk_nvmf_valid_ascii_string(sn, len)) { 1196 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n"); 1197 SPDK_LOGDUMP(SPDK_LOG_NVMF, "sn", sn, len); 1198 return -1; 1199 } 1200 1201 snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn); 1202 1203 return 0; 1204 } 1205 1206 const char * 1207 spdk_nvmf_subsystem_get_mn(const struct spdk_nvmf_subsystem *subsystem) 1208 { 1209 return subsystem->mn; 1210 } 1211 1212 int 1213 spdk_nvmf_subsystem_set_mn(struct spdk_nvmf_subsystem *subsystem, const char *mn) 1214 { 1215 size_t len, max_len; 1216 1217 if (mn == NULL) { 1218 mn = MODEL_NUMBER_DEFAULT; 1219 } 1220 max_len = sizeof(subsystem->mn) - 1; 1221 len = strlen(mn); 1222 if (len > max_len) { 1223 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid mn \"%s\": length %zu > max %zu\n", 1224 mn, len, max_len); 1225 return -1; 1226 } 1227 1228 if (!spdk_nvmf_valid_ascii_string(mn, len)) { 1229 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII mn\n"); 1230 SPDK_LOGDUMP(SPDK_LOG_NVMF, "mn", mn, len); 1231 return -1; 1232 } 1233 1234 snprintf(subsystem->mn, sizeof(subsystem->mn), "%s", mn); 1235 1236 return 0; 1237 } 1238 1239 const char * 1240 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem) 1241 { 1242 return subsystem->subnqn; 1243 } 1244 1245 /* Workaround for astyle formatting bug */ 1246 typedef enum spdk_nvmf_subtype nvmf_subtype_t; 1247 1248 nvmf_subtype_t 1249 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem) 1250 { 1251 return subsystem->subtype; 1252 } 1253 1254 static uint16_t 1255 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem) 1256 { 1257 int count; 1258 1259 /* 1260 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1 1261 * before we find one that is unused (or find that all values are in use). 1262 */ 1263 for (count = 0; count < 0xFFF0 - 1; count++) { 1264 subsystem->next_cntlid++; 1265 if (subsystem->next_cntlid >= 0xFFF0) { 1266 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 1267 subsystem->next_cntlid = 1; 1268 } 1269 1270 /* Check if a controller with this cntlid currently exists. */ 1271 if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) { 1272 /* Found unused cntlid */ 1273 return subsystem->next_cntlid; 1274 } 1275 } 1276 1277 /* All valid cntlid values are in use. */ 1278 return 0xFFFF; 1279 } 1280 1281 int 1282 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr) 1283 { 1284 ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem); 1285 if (ctrlr->cntlid == 0xFFFF) { 1286 /* Unable to get a cntlid */ 1287 SPDK_ERRLOG("Reached max simultaneous ctrlrs\n"); 1288 return -EBUSY; 1289 } 1290 1291 TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link); 1292 1293 return 0; 1294 } 1295 1296 void 1297 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 1298 struct spdk_nvmf_ctrlr *ctrlr) 1299 { 1300 assert(subsystem == ctrlr->subsys); 1301 TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link); 1302 } 1303 1304 struct spdk_nvmf_ctrlr * 1305 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid) 1306 { 1307 struct spdk_nvmf_ctrlr *ctrlr; 1308 1309 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1310 if (ctrlr->cntlid == cntlid) { 1311 return ctrlr; 1312 } 1313 } 1314 1315 return NULL; 1316 } 1317 1318 uint32_t 1319 spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem) 1320 { 1321 return subsystem->max_allowed_nsid; 1322 } 1323 1324 struct _nvmf_ns_registrant { 1325 uint64_t rkey; 1326 char *host_uuid; 1327 }; 1328 1329 struct _nvmf_ns_registrants { 1330 size_t num_regs; 1331 struct _nvmf_ns_registrant reg[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1332 }; 1333 1334 struct _nvmf_ns_reservation { 1335 bool ptpl_activated; 1336 enum spdk_nvme_reservation_type rtype; 1337 uint64_t crkey; 1338 char *bdev_uuid; 1339 char *holder_uuid; 1340 struct _nvmf_ns_registrants regs; 1341 }; 1342 1343 static const struct spdk_json_object_decoder nvmf_ns_pr_reg_decoders[] = { 1344 {"rkey", offsetof(struct _nvmf_ns_registrant, rkey), spdk_json_decode_uint64}, 1345 {"host_uuid", offsetof(struct _nvmf_ns_registrant, host_uuid), spdk_json_decode_string}, 1346 }; 1347 1348 static int 1349 nvmf_decode_ns_pr_reg(const struct spdk_json_val *val, void *out) 1350 { 1351 struct _nvmf_ns_registrant *reg = out; 1352 1353 return spdk_json_decode_object(val, nvmf_ns_pr_reg_decoders, 1354 SPDK_COUNTOF(nvmf_ns_pr_reg_decoders), reg); 1355 } 1356 1357 static int 1358 nvmf_decode_ns_pr_regs(const struct spdk_json_val *val, void *out) 1359 { 1360 struct _nvmf_ns_registrants *regs = out; 1361 1362 return spdk_json_decode_array(val, nvmf_decode_ns_pr_reg, regs->reg, 1363 SPDK_NVMF_MAX_NUM_REGISTRANTS, ®s->num_regs, 1364 sizeof(struct _nvmf_ns_registrant)); 1365 } 1366 1367 static const struct spdk_json_object_decoder nvmf_ns_pr_decoders[] = { 1368 {"ptpl", offsetof(struct _nvmf_ns_reservation, ptpl_activated), spdk_json_decode_bool, true}, 1369 {"rtype", offsetof(struct _nvmf_ns_reservation, rtype), spdk_json_decode_uint32, true}, 1370 {"crkey", offsetof(struct _nvmf_ns_reservation, crkey), spdk_json_decode_uint64, true}, 1371 {"bdev_uuid", offsetof(struct _nvmf_ns_reservation, bdev_uuid), spdk_json_decode_string}, 1372 {"holder_uuid", offsetof(struct _nvmf_ns_reservation, holder_uuid), spdk_json_decode_string, true}, 1373 {"registrants", offsetof(struct _nvmf_ns_reservation, regs), nvmf_decode_ns_pr_regs}, 1374 }; 1375 1376 static int 1377 spdk_nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info) 1378 { 1379 FILE *fd; 1380 size_t json_size; 1381 ssize_t values_cnt, rc; 1382 void *json = NULL, *end; 1383 struct spdk_json_val *values = NULL; 1384 struct _nvmf_ns_reservation res = {}; 1385 uint32_t i; 1386 1387 fd = fopen(file, "r"); 1388 /* It's not an error if the file does not exist */ 1389 if (!fd) { 1390 SPDK_NOTICELOG("File %s does not exist\n", file); 1391 return -ENOENT; 1392 } 1393 1394 /* Load all persist file contents into a local buffer */ 1395 json = spdk_posix_file_load(fd, &json_size); 1396 fclose(fd); 1397 if (!json) { 1398 SPDK_ERRLOG("Load persit file %s failed\n", file); 1399 return -ENOMEM; 1400 } 1401 1402 rc = spdk_json_parse(json, json_size, NULL, 0, &end, 0); 1403 if (rc < 0) { 1404 SPDK_NOTICELOG("Parsing JSON configuration failed (%zd)\n", rc); 1405 goto exit; 1406 } 1407 1408 values_cnt = rc; 1409 values = calloc(values_cnt, sizeof(struct spdk_json_val)); 1410 if (values == NULL) { 1411 goto exit; 1412 } 1413 1414 rc = spdk_json_parse(json, json_size, values, values_cnt, &end, 0); 1415 if (rc != values_cnt) { 1416 SPDK_ERRLOG("Parsing JSON configuration failed (%zd)\n", rc); 1417 goto exit; 1418 } 1419 1420 /* Decode json */ 1421 if (spdk_json_decode_object(values, nvmf_ns_pr_decoders, 1422 SPDK_COUNTOF(nvmf_ns_pr_decoders), 1423 &res)) { 1424 SPDK_ERRLOG("Invalid objects in the persist file %s\n", file); 1425 rc = -EINVAL; 1426 goto exit; 1427 } 1428 1429 if (res.regs.num_regs > SPDK_NVMF_MAX_NUM_REGISTRANTS) { 1430 SPDK_ERRLOG("Can only support up to %u registrants\n", SPDK_NVMF_MAX_NUM_REGISTRANTS); 1431 rc = -ERANGE; 1432 goto exit; 1433 } 1434 1435 rc = 0; 1436 info->ptpl_activated = res.ptpl_activated; 1437 info->rtype = res.rtype; 1438 info->crkey = res.crkey; 1439 snprintf(info->bdev_uuid, sizeof(info->bdev_uuid), "%s", res.bdev_uuid); 1440 snprintf(info->holder_uuid, sizeof(info->holder_uuid), "%s", res.holder_uuid); 1441 info->num_regs = res.regs.num_regs; 1442 for (i = 0; i < res.regs.num_regs; i++) { 1443 info->registrants[i].rkey = res.regs.reg[i].rkey; 1444 snprintf(info->registrants[i].host_uuid, sizeof(info->registrants[i].host_uuid), "%s", 1445 res.regs.reg[i].host_uuid); 1446 } 1447 1448 exit: 1449 free(json); 1450 free(values); 1451 free(res.bdev_uuid); 1452 free(res.holder_uuid); 1453 for (i = 0; i < res.regs.num_regs; i++) { 1454 free(res.regs.reg[i].host_uuid); 1455 } 1456 1457 return rc; 1458 } 1459 1460 static bool 1461 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns); 1462 1463 static int 1464 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info) 1465 { 1466 uint32_t i; 1467 struct spdk_nvmf_registrant *reg, *holder = NULL; 1468 struct spdk_uuid bdev_uuid, holder_uuid; 1469 1470 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "NSID %u, PTPL %u, Number of registrants %u\n", 1471 ns->nsid, info->ptpl_activated, info->num_regs); 1472 1473 /* it's not an error */ 1474 if (!info->ptpl_activated || !info->num_regs) { 1475 return 0; 1476 } 1477 1478 spdk_uuid_parse(&bdev_uuid, info->bdev_uuid); 1479 if (spdk_uuid_compare(&bdev_uuid, spdk_bdev_get_uuid(ns->bdev))) { 1480 SPDK_ERRLOG("Existing bdev UUID is not same with configuration file\n"); 1481 return -EINVAL; 1482 } 1483 1484 ns->crkey = info->crkey; 1485 ns->rtype = info->rtype; 1486 ns->ptpl_activated = info->ptpl_activated; 1487 spdk_uuid_parse(&holder_uuid, info->holder_uuid); 1488 1489 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev UUID %s\n", info->bdev_uuid); 1490 if (info->rtype) { 1491 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Holder UUID %s, RTYPE %u, RKEY 0x%"PRIx64"\n", 1492 info->holder_uuid, info->rtype, info->crkey); 1493 } 1494 1495 for (i = 0; i < info->num_regs; i++) { 1496 reg = calloc(1, sizeof(*reg)); 1497 if (!reg) { 1498 return -ENOMEM; 1499 } 1500 spdk_uuid_parse(®->hostid, info->registrants[i].host_uuid); 1501 reg->rkey = info->registrants[i].rkey; 1502 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1503 if (!spdk_uuid_compare(&holder_uuid, ®->hostid)) { 1504 holder = reg; 1505 } 1506 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Registrant RKEY 0x%"PRIx64", Host UUID %s\n", 1507 info->registrants[i].rkey, info->registrants[i].host_uuid); 1508 } 1509 1510 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1511 ns->holder = TAILQ_FIRST(&ns->registrants); 1512 } else { 1513 ns->holder = holder; 1514 } 1515 1516 return 0; 1517 } 1518 1519 static int 1520 spdk_nvmf_ns_json_write_cb(void *cb_ctx, const void *data, size_t size) 1521 { 1522 char *file = cb_ctx; 1523 size_t rc; 1524 FILE *fd; 1525 1526 fd = fopen(file, "w"); 1527 if (!fd) { 1528 SPDK_ERRLOG("Can't open file %s for write\n", file); 1529 return -ENOENT; 1530 } 1531 rc = fwrite(data, 1, size, fd); 1532 fclose(fd); 1533 1534 return rc == size ? 0 : -1; 1535 } 1536 1537 static int 1538 spdk_nvmf_ns_reservation_update(const char *file, struct spdk_nvmf_reservation_info *info) 1539 { 1540 struct spdk_json_write_ctx *w; 1541 uint32_t i; 1542 int rc = 0; 1543 1544 w = spdk_json_write_begin(spdk_nvmf_ns_json_write_cb, (void *)file, 0); 1545 if (w == NULL) { 1546 return -ENOMEM; 1547 } 1548 /* clear the configuration file */ 1549 if (!info->ptpl_activated) { 1550 goto exit; 1551 } 1552 1553 spdk_json_write_object_begin(w); 1554 spdk_json_write_named_bool(w, "ptpl", info->ptpl_activated); 1555 spdk_json_write_named_uint32(w, "rtype", info->rtype); 1556 spdk_json_write_named_uint64(w, "crkey", info->crkey); 1557 spdk_json_write_named_string(w, "bdev_uuid", info->bdev_uuid); 1558 spdk_json_write_named_string(w, "holder_uuid", info->holder_uuid); 1559 1560 spdk_json_write_named_array_begin(w, "registrants"); 1561 for (i = 0; i < info->num_regs; i++) { 1562 spdk_json_write_object_begin(w); 1563 spdk_json_write_named_uint64(w, "rkey", info->registrants[i].rkey); 1564 spdk_json_write_named_string(w, "host_uuid", info->registrants[i].host_uuid); 1565 spdk_json_write_object_end(w); 1566 } 1567 spdk_json_write_array_end(w); 1568 spdk_json_write_object_end(w); 1569 1570 exit: 1571 rc = spdk_json_write_end(w); 1572 return rc; 1573 } 1574 1575 static int 1576 nvmf_ns_update_reservation_info(struct spdk_nvmf_ns *ns) 1577 { 1578 struct spdk_nvmf_reservation_info info; 1579 struct spdk_nvmf_registrant *reg, *tmp; 1580 uint32_t i = 0; 1581 1582 assert(ns != NULL); 1583 1584 if (!ns->bdev || !ns->ptpl_file) { 1585 return 0; 1586 } 1587 1588 memset(&info, 0, sizeof(info)); 1589 spdk_uuid_fmt_lower(info.bdev_uuid, sizeof(info.bdev_uuid), spdk_bdev_get_uuid(ns->bdev)); 1590 1591 if (ns->rtype) { 1592 info.rtype = ns->rtype; 1593 info.crkey = ns->crkey; 1594 if (!nvmf_ns_reservation_all_registrants_type(ns)) { 1595 assert(ns->holder != NULL); 1596 spdk_uuid_fmt_lower(info.holder_uuid, sizeof(info.holder_uuid), &ns->holder->hostid); 1597 } 1598 } 1599 1600 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1601 spdk_uuid_fmt_lower(info.registrants[i].host_uuid, sizeof(info.registrants[i].host_uuid), 1602 ®->hostid); 1603 info.registrants[i++].rkey = reg->rkey; 1604 } 1605 1606 info.num_regs = i; 1607 info.ptpl_activated = ns->ptpl_activated; 1608 1609 return spdk_nvmf_ns_reservation_update(ns->ptpl_file, &info); 1610 } 1611 1612 static struct spdk_nvmf_registrant * 1613 nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns, 1614 struct spdk_uuid *uuid) 1615 { 1616 struct spdk_nvmf_registrant *reg, *tmp; 1617 1618 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1619 if (!spdk_uuid_compare(®->hostid, uuid)) { 1620 return reg; 1621 } 1622 } 1623 1624 return NULL; 1625 } 1626 1627 /* Generate reservation notice log to registered HostID controllers */ 1628 static void 1629 nvmf_subsystem_gen_ctrlr_notification(struct spdk_nvmf_subsystem *subsystem, 1630 struct spdk_nvmf_ns *ns, 1631 struct spdk_uuid *hostid_list, 1632 uint32_t num_hostid, 1633 enum spdk_nvme_reservation_notification_log_page_type type) 1634 { 1635 struct spdk_nvmf_ctrlr *ctrlr; 1636 uint32_t i; 1637 1638 for (i = 0; i < num_hostid; i++) { 1639 TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { 1640 if (!spdk_uuid_compare(&ctrlr->hostid, &hostid_list[i])) { 1641 spdk_nvmf_ctrlr_reservation_notice_log(ctrlr, ns, type); 1642 } 1643 } 1644 } 1645 } 1646 1647 /* Get all registrants' hostid other than the controller who issued the command */ 1648 static uint32_t 1649 nvmf_ns_reservation_get_all_other_hostid(struct spdk_nvmf_ns *ns, 1650 struct spdk_uuid *hostid_list, 1651 uint32_t max_num_hostid, 1652 struct spdk_uuid *current_hostid) 1653 { 1654 struct spdk_nvmf_registrant *reg, *tmp; 1655 uint32_t num_hostid = 0; 1656 1657 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1658 if (spdk_uuid_compare(®->hostid, current_hostid)) { 1659 if (num_hostid == max_num_hostid) { 1660 assert(false); 1661 return max_num_hostid; 1662 } 1663 hostid_list[num_hostid++] = reg->hostid; 1664 } 1665 } 1666 1667 return num_hostid; 1668 } 1669 1670 /* Calculate the unregistered HostID list according to list 1671 * prior to execute preempt command and list after executing 1672 * preempt command. 1673 */ 1674 static uint32_t 1675 nvmf_ns_reservation_get_unregistered_hostid(struct spdk_uuid *old_hostid_list, 1676 uint32_t old_num_hostid, 1677 struct spdk_uuid *remaining_hostid_list, 1678 uint32_t remaining_num_hostid) 1679 { 1680 struct spdk_uuid temp_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1681 uint32_t i, j, num_hostid = 0; 1682 bool found; 1683 1684 if (!remaining_num_hostid) { 1685 return old_num_hostid; 1686 } 1687 1688 for (i = 0; i < old_num_hostid; i++) { 1689 found = false; 1690 for (j = 0; j < remaining_num_hostid; j++) { 1691 if (!spdk_uuid_compare(&old_hostid_list[i], &remaining_hostid_list[j])) { 1692 found = true; 1693 break; 1694 } 1695 } 1696 if (!found) { 1697 spdk_uuid_copy(&temp_hostid_list[num_hostid++], &old_hostid_list[i]); 1698 } 1699 } 1700 1701 if (num_hostid) { 1702 memcpy(old_hostid_list, temp_hostid_list, sizeof(struct spdk_uuid) * num_hostid); 1703 } 1704 1705 return num_hostid; 1706 } 1707 1708 /* current reservation type is all registrants or not */ 1709 static bool 1710 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns) 1711 { 1712 return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS || 1713 ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); 1714 } 1715 1716 /* current registrant is reservation holder or not */ 1717 static bool 1718 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns, 1719 struct spdk_nvmf_registrant *reg) 1720 { 1721 if (!reg) { 1722 return false; 1723 } 1724 1725 if (nvmf_ns_reservation_all_registrants_type(ns)) { 1726 return true; 1727 } 1728 1729 return (ns->holder == reg); 1730 } 1731 1732 static int 1733 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns, 1734 struct spdk_nvmf_ctrlr *ctrlr, 1735 uint64_t nrkey) 1736 { 1737 struct spdk_nvmf_registrant *reg; 1738 1739 reg = calloc(1, sizeof(*reg)); 1740 if (!reg) { 1741 return -ENOMEM; 1742 } 1743 1744 reg->rkey = nrkey; 1745 /* set hostid for the registrant */ 1746 spdk_uuid_copy(®->hostid, &ctrlr->hostid); 1747 TAILQ_INSERT_TAIL(&ns->registrants, reg, link); 1748 ns->gen++; 1749 1750 return 0; 1751 } 1752 1753 static void 1754 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns) 1755 { 1756 ns->rtype = 0; 1757 ns->crkey = 0; 1758 ns->holder = NULL; 1759 } 1760 1761 /* release the reservation if the last registrant was removed */ 1762 static void 1763 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns, 1764 struct spdk_nvmf_registrant *reg) 1765 { 1766 struct spdk_nvmf_registrant *next_reg; 1767 1768 /* no reservation holder */ 1769 if (!ns->holder) { 1770 assert(ns->rtype == 0); 1771 return; 1772 } 1773 1774 next_reg = TAILQ_FIRST(&ns->registrants); 1775 if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) { 1776 /* the next valid registrant is the new holder now */ 1777 ns->holder = next_reg; 1778 } else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 1779 /* release the reservation */ 1780 nvmf_ns_reservation_release_reservation(ns); 1781 } 1782 } 1783 1784 static void 1785 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns, 1786 struct spdk_nvmf_registrant *reg) 1787 { 1788 TAILQ_REMOVE(&ns->registrants, reg, link); 1789 nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg); 1790 free(reg); 1791 ns->gen++; 1792 return; 1793 } 1794 1795 static uint32_t 1796 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns, 1797 uint64_t rkey) 1798 { 1799 struct spdk_nvmf_registrant *reg, *tmp; 1800 uint32_t count = 0; 1801 1802 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 1803 if (reg->rkey == rkey) { 1804 nvmf_ns_reservation_remove_registrant(ns, reg); 1805 count++; 1806 } 1807 } 1808 return count; 1809 } 1810 1811 static uint32_t 1812 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns, 1813 struct spdk_nvmf_registrant *reg) 1814 { 1815 struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2; 1816 uint32_t count = 0; 1817 1818 TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) { 1819 if (reg_tmp != reg) { 1820 nvmf_ns_reservation_remove_registrant(ns, reg_tmp); 1821 count++; 1822 } 1823 } 1824 return count; 1825 } 1826 1827 static uint32_t 1828 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns) 1829 { 1830 struct spdk_nvmf_registrant *reg, *reg_tmp; 1831 uint32_t count = 0; 1832 1833 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) { 1834 nvmf_ns_reservation_remove_registrant(ns, reg); 1835 count++; 1836 } 1837 return count; 1838 } 1839 1840 static void 1841 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey, 1842 enum spdk_nvme_reservation_type rtype, 1843 struct spdk_nvmf_registrant *holder) 1844 { 1845 ns->rtype = rtype; 1846 ns->crkey = rkey; 1847 assert(ns->holder == NULL); 1848 ns->holder = holder; 1849 } 1850 1851 static bool 1852 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns, 1853 struct spdk_nvmf_ctrlr *ctrlr, 1854 struct spdk_nvmf_request *req) 1855 { 1856 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1857 uint8_t rrega, iekey, cptpl, rtype; 1858 struct spdk_nvme_reservation_register_data key; 1859 struct spdk_nvmf_registrant *reg; 1860 uint8_t status = SPDK_NVME_SC_SUCCESS; 1861 bool update_sgroup = false; 1862 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1863 uint32_t num_hostid = 0; 1864 int rc; 1865 1866 rrega = cmd->cdw10 & 0x7u; 1867 iekey = (cmd->cdw10 >> 3) & 0x1u; 1868 cptpl = (cmd->cdw10 >> 30) & 0x3u; 1869 1870 if (req->data && req->length >= sizeof(key)) { 1871 memcpy(&key, req->data, sizeof(key)); 1872 } else { 1873 SPDK_ERRLOG("No key provided. Failing request.\n"); 1874 status = SPDK_NVME_SC_INVALID_FIELD; 1875 goto exit; 1876 } 1877 1878 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, " 1879 "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n", 1880 rrega, iekey, cptpl, key.crkey, key.nrkey); 1881 1882 if (cptpl == SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON) { 1883 /* Ture to OFF state, and need to be updated in the configuration file */ 1884 if (ns->ptpl_activated) { 1885 ns->ptpl_activated = 0; 1886 update_sgroup = true; 1887 } 1888 } else if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) { 1889 if (ns->ptpl_file == NULL) { 1890 status = SPDK_NVME_SC_INVALID_FIELD; 1891 goto exit; 1892 } else if (ns->ptpl_activated == 0) { 1893 ns->ptpl_activated = 1; 1894 update_sgroup = true; 1895 } 1896 } 1897 1898 /* current Host Identifier has registrant or not */ 1899 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 1900 1901 switch (rrega) { 1902 case SPDK_NVME_RESERVE_REGISTER_KEY: 1903 if (!reg) { 1904 /* register new controller */ 1905 if (key.nrkey == 0) { 1906 SPDK_ERRLOG("Can't register zeroed new key\n"); 1907 status = SPDK_NVME_SC_INVALID_FIELD; 1908 goto exit; 1909 } 1910 rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey); 1911 if (rc < 0) { 1912 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 1913 goto exit; 1914 } 1915 update_sgroup = true; 1916 } else { 1917 /* register with same key is not an error */ 1918 if (reg->rkey != key.nrkey) { 1919 SPDK_ERRLOG("The same host already register a " 1920 "key with 0x%"PRIx64"\n", 1921 reg->rkey); 1922 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1923 goto exit; 1924 } 1925 } 1926 break; 1927 case SPDK_NVME_RESERVE_UNREGISTER_KEY: 1928 if (!reg || (!iekey && reg->rkey != key.crkey)) { 1929 SPDK_ERRLOG("No registrant or current key doesn't match " 1930 "with existing registrant key\n"); 1931 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1932 goto exit; 1933 } 1934 1935 rtype = ns->rtype; 1936 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 1937 SPDK_NVMF_MAX_NUM_REGISTRANTS, 1938 &ctrlr->hostid); 1939 1940 nvmf_ns_reservation_remove_registrant(ns, reg); 1941 1942 if (!ns->rtype && num_hostid && (rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY || 1943 rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY)) { 1944 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 1945 hostid_list, 1946 num_hostid, 1947 SPDK_NVME_RESERVATION_RELEASED); 1948 } 1949 update_sgroup = true; 1950 break; 1951 case SPDK_NVME_RESERVE_REPLACE_KEY: 1952 if (!reg || (!iekey && reg->rkey != key.crkey)) { 1953 SPDK_ERRLOG("No registrant or current key doesn't match " 1954 "with existing registrant key\n"); 1955 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 1956 goto exit; 1957 } 1958 if (key.nrkey == 0) { 1959 SPDK_ERRLOG("Can't register zeroed new key\n"); 1960 status = SPDK_NVME_SC_INVALID_FIELD; 1961 goto exit; 1962 } 1963 reg->rkey = key.nrkey; 1964 update_sgroup = true; 1965 break; 1966 default: 1967 status = SPDK_NVME_SC_INVALID_FIELD; 1968 goto exit; 1969 } 1970 1971 exit: 1972 if (update_sgroup) { 1973 rc = nvmf_ns_update_reservation_info(ns); 1974 if (rc != 0) { 1975 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 1976 } 1977 } 1978 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 1979 req->rsp->nvme_cpl.status.sc = status; 1980 return update_sgroup; 1981 } 1982 1983 static bool 1984 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns, 1985 struct spdk_nvmf_ctrlr *ctrlr, 1986 struct spdk_nvmf_request *req) 1987 { 1988 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 1989 uint8_t racqa, iekey, rtype; 1990 struct spdk_nvme_reservation_acquire_data key; 1991 struct spdk_nvmf_registrant *reg; 1992 bool all_regs = false; 1993 uint32_t count = 0; 1994 bool update_sgroup = true; 1995 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1996 uint32_t num_hostid = 0; 1997 struct spdk_uuid new_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 1998 uint32_t new_num_hostid = 0; 1999 bool reservation_released = false; 2000 uint8_t status = SPDK_NVME_SC_SUCCESS; 2001 2002 racqa = cmd->cdw10 & 0x7u; 2003 iekey = (cmd->cdw10 >> 3) & 0x1u; 2004 rtype = (cmd->cdw10 >> 8) & 0xffu; 2005 2006 if (req->data && req->length >= sizeof(key)) { 2007 memcpy(&key, req->data, sizeof(key)); 2008 } else { 2009 SPDK_ERRLOG("No key provided. Failing request.\n"); 2010 status = SPDK_NVME_SC_INVALID_FIELD; 2011 goto exit; 2012 } 2013 2014 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, " 2015 "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n", 2016 racqa, iekey, rtype, key.crkey, key.prkey); 2017 2018 if (iekey || rtype > SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS) { 2019 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 2020 status = SPDK_NVME_SC_INVALID_FIELD; 2021 update_sgroup = false; 2022 goto exit; 2023 } 2024 2025 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 2026 /* must be registrant and CRKEY must match */ 2027 if (!reg || reg->rkey != key.crkey) { 2028 SPDK_ERRLOG("No registrant or current key doesn't match " 2029 "with existing registrant key\n"); 2030 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2031 update_sgroup = false; 2032 goto exit; 2033 } 2034 2035 all_regs = nvmf_ns_reservation_all_registrants_type(ns); 2036 2037 switch (racqa) { 2038 case SPDK_NVME_RESERVE_ACQUIRE: 2039 /* it's not an error for the holder to acquire same reservation type again */ 2040 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) { 2041 /* do nothing */ 2042 update_sgroup = false; 2043 } else if (ns->holder == NULL) { 2044 /* fisrt time to acquire the reservation */ 2045 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 2046 } else { 2047 SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n"); 2048 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2049 update_sgroup = false; 2050 goto exit; 2051 } 2052 break; 2053 case SPDK_NVME_RESERVE_PREEMPT: 2054 /* no reservation holder */ 2055 if (!ns->holder) { 2056 /* unregister with PRKEY */ 2057 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2058 break; 2059 } 2060 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 2061 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2062 &ctrlr->hostid); 2063 2064 /* only 1 reservation holder and reservation key is valid */ 2065 if (!all_regs) { 2066 /* preempt itself */ 2067 if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && 2068 ns->crkey == key.prkey) { 2069 ns->rtype = rtype; 2070 reservation_released = true; 2071 break; 2072 } 2073 2074 if (ns->crkey == key.prkey) { 2075 nvmf_ns_reservation_remove_registrant(ns, ns->holder); 2076 nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); 2077 reservation_released = true; 2078 } else if (key.prkey != 0) { 2079 nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2080 } else { 2081 /* PRKEY is zero */ 2082 SPDK_ERRLOG("Current PRKEY is zero\n"); 2083 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2084 update_sgroup = false; 2085 goto exit; 2086 } 2087 } else { 2088 /* release all other registrants except for the current one */ 2089 if (key.prkey == 0) { 2090 nvmf_ns_reservation_remove_all_other_registrants(ns, reg); 2091 assert(ns->holder == reg); 2092 } else { 2093 count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey); 2094 if (count == 0) { 2095 SPDK_ERRLOG("PRKEY doesn't match any registrant\n"); 2096 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2097 update_sgroup = false; 2098 goto exit; 2099 } 2100 } 2101 } 2102 break; 2103 default: 2104 status = SPDK_NVME_SC_INVALID_FIELD; 2105 update_sgroup = false; 2106 break; 2107 } 2108 2109 exit: 2110 if (update_sgroup && racqa == SPDK_NVME_RESERVE_PREEMPT) { 2111 new_num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, new_hostid_list, 2112 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2113 &ctrlr->hostid); 2114 /* Preempt notification occurs on the unregistered controllers 2115 * other than the controller who issued the command. 2116 */ 2117 num_hostid = nvmf_ns_reservation_get_unregistered_hostid(hostid_list, 2118 num_hostid, 2119 new_hostid_list, 2120 new_num_hostid); 2121 if (num_hostid) { 2122 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2123 hostid_list, 2124 num_hostid, 2125 SPDK_NVME_REGISTRATION_PREEMPTED); 2126 2127 } 2128 /* Reservation released notification occurs on the 2129 * controllers which are the remaining registrants other than 2130 * the controller who issued the command. 2131 */ 2132 if (reservation_released && new_num_hostid) { 2133 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2134 new_hostid_list, 2135 new_num_hostid, 2136 SPDK_NVME_RESERVATION_RELEASED); 2137 2138 } 2139 } 2140 if (update_sgroup && ns->ptpl_activated) { 2141 if (nvmf_ns_update_reservation_info(ns)) { 2142 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2143 } 2144 } 2145 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2146 req->rsp->nvme_cpl.status.sc = status; 2147 return update_sgroup; 2148 } 2149 2150 static bool 2151 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns, 2152 struct spdk_nvmf_ctrlr *ctrlr, 2153 struct spdk_nvmf_request *req) 2154 { 2155 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2156 uint8_t rrela, iekey, rtype; 2157 struct spdk_nvmf_registrant *reg; 2158 uint64_t crkey; 2159 uint8_t status = SPDK_NVME_SC_SUCCESS; 2160 bool update_sgroup = true; 2161 struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 2162 uint32_t num_hostid = 0; 2163 2164 rrela = cmd->cdw10 & 0x7u; 2165 iekey = (cmd->cdw10 >> 3) & 0x1u; 2166 rtype = (cmd->cdw10 >> 8) & 0xffu; 2167 2168 if (req->data && req->length >= sizeof(crkey)) { 2169 memcpy(&crkey, req->data, sizeof(crkey)); 2170 } else { 2171 SPDK_ERRLOG("No key provided. Failing request.\n"); 2172 status = SPDK_NVME_SC_INVALID_FIELD; 2173 goto exit; 2174 } 2175 2176 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, " 2177 "CRKEY 0x%"PRIx64"\n", rrela, iekey, rtype, crkey); 2178 2179 if (iekey) { 2180 SPDK_ERRLOG("Ignore existing key field set to 1\n"); 2181 status = SPDK_NVME_SC_INVALID_FIELD; 2182 update_sgroup = false; 2183 goto exit; 2184 } 2185 2186 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid); 2187 if (!reg || reg->rkey != crkey) { 2188 SPDK_ERRLOG("No registrant or current key doesn't match " 2189 "with existing registrant key\n"); 2190 status = SPDK_NVME_SC_RESERVATION_CONFLICT; 2191 update_sgroup = false; 2192 goto exit; 2193 } 2194 2195 num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list, 2196 SPDK_NVMF_MAX_NUM_REGISTRANTS, 2197 &ctrlr->hostid); 2198 2199 switch (rrela) { 2200 case SPDK_NVME_RESERVE_RELEASE: 2201 if (!ns->holder) { 2202 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n"); 2203 update_sgroup = false; 2204 goto exit; 2205 } 2206 if (ns->rtype != rtype) { 2207 SPDK_ERRLOG("Type doesn't match\n"); 2208 status = SPDK_NVME_SC_INVALID_FIELD; 2209 update_sgroup = false; 2210 goto exit; 2211 } 2212 if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) { 2213 /* not the reservation holder, this isn't an error */ 2214 update_sgroup = false; 2215 goto exit; 2216 } 2217 2218 rtype = ns->rtype; 2219 nvmf_ns_reservation_release_reservation(ns); 2220 2221 if (num_hostid && rtype != SPDK_NVME_RESERVE_WRITE_EXCLUSIVE && 2222 rtype != SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS) { 2223 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2224 hostid_list, 2225 num_hostid, 2226 SPDK_NVME_RESERVATION_RELEASED); 2227 } 2228 break; 2229 case SPDK_NVME_RESERVE_CLEAR: 2230 nvmf_ns_reservation_clear_all_registrants(ns); 2231 if (num_hostid) { 2232 nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns, 2233 hostid_list, 2234 num_hostid, 2235 SPDK_NVME_RESERVATION_PREEMPTED); 2236 } 2237 break; 2238 default: 2239 status = SPDK_NVME_SC_INVALID_FIELD; 2240 update_sgroup = false; 2241 goto exit; 2242 } 2243 2244 exit: 2245 if (update_sgroup && ns->ptpl_activated) { 2246 if (nvmf_ns_update_reservation_info(ns)) { 2247 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2248 } 2249 } 2250 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2251 req->rsp->nvme_cpl.status.sc = status; 2252 return update_sgroup; 2253 } 2254 2255 static void 2256 nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns, 2257 struct spdk_nvmf_ctrlr *ctrlr, 2258 struct spdk_nvmf_request *req) 2259 { 2260 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2261 struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; 2262 struct spdk_nvmf_ctrlr *ctrlr_tmp; 2263 struct spdk_nvmf_registrant *reg, *tmp; 2264 struct spdk_nvme_reservation_status_extended_data *status_data; 2265 struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data; 2266 uint8_t *payload; 2267 uint32_t len, count = 0; 2268 uint32_t regctl = 0; 2269 uint8_t status = SPDK_NVME_SC_SUCCESS; 2270 2271 if (req->data == NULL) { 2272 SPDK_ERRLOG("No data transfer specified for request. " 2273 " Unable to transfer back response.\n"); 2274 status = SPDK_NVME_SC_INVALID_FIELD; 2275 goto exit; 2276 } 2277 2278 /* NVMeoF uses Extended Data Structure */ 2279 if ((cmd->cdw11 & 0x00000001u) == 0) { 2280 SPDK_ERRLOG("NVMeoF uses extended controller data structure, " 2281 "please set EDS bit in cdw11 and try again\n"); 2282 status = SPDK_NVME_SC_INVALID_FIELD; 2283 goto exit; 2284 } 2285 2286 /* Get number of registerd controllers, one Host may have more than 2287 * one controller based on different ports. 2288 */ 2289 TAILQ_FOREACH(ctrlr_tmp, &subsystem->ctrlrs, link) { 2290 reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr_tmp->hostid); 2291 if (reg) { 2292 regctl++; 2293 } 2294 } 2295 2296 len = sizeof(*status_data) + sizeof(*ctrlr_data) * regctl; 2297 payload = calloc(1, len); 2298 if (!payload) { 2299 status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 2300 goto exit; 2301 } 2302 2303 status_data = (struct spdk_nvme_reservation_status_extended_data *)payload; 2304 status_data->data.gen = ns->gen; 2305 status_data->data.rtype = ns->rtype; 2306 status_data->data.regctl = regctl; 2307 status_data->data.ptpls = ns->ptpl_activated; 2308 2309 TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { 2310 assert(count <= regctl); 2311 ctrlr_data = (struct spdk_nvme_registered_ctrlr_extended_data *) 2312 (payload + sizeof(*status_data) + sizeof(*ctrlr_data) * count); 2313 /* Set to 0xffffh for dynamic controller */ 2314 ctrlr_data->cntlid = 0xffff; 2315 ctrlr_data->rcsts.status = (ns->holder == reg) ? true : false; 2316 ctrlr_data->rkey = reg->rkey; 2317 spdk_uuid_copy((struct spdk_uuid *)ctrlr_data->hostid, ®->hostid); 2318 count++; 2319 } 2320 2321 memcpy(req->data, payload, spdk_min(len, (cmd->cdw10 + 1) * sizeof(uint32_t))); 2322 free(payload); 2323 2324 exit: 2325 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 2326 req->rsp->nvme_cpl.status.sc = status; 2327 return; 2328 } 2329 2330 static void 2331 spdk_nvmf_ns_reservation_complete(void *ctx) 2332 { 2333 struct spdk_nvmf_request *req = ctx; 2334 2335 spdk_nvmf_request_complete(req); 2336 } 2337 2338 static void 2339 _nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem, 2340 void *cb_arg, int status) 2341 { 2342 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg; 2343 struct spdk_nvmf_poll_group *group = req->qpair->group; 2344 2345 spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req); 2346 } 2347 2348 void 2349 spdk_nvmf_ns_reservation_request(void *ctx) 2350 { 2351 struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx; 2352 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 2353 struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; 2354 struct subsystem_update_ns_ctx *update_ctx; 2355 uint32_t nsid; 2356 struct spdk_nvmf_ns *ns; 2357 bool update_sgroup = false; 2358 2359 nsid = cmd->nsid; 2360 ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid); 2361 assert(ns != NULL); 2362 2363 switch (cmd->opc) { 2364 case SPDK_NVME_OPC_RESERVATION_REGISTER: 2365 update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req); 2366 break; 2367 case SPDK_NVME_OPC_RESERVATION_ACQUIRE: 2368 update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req); 2369 break; 2370 case SPDK_NVME_OPC_RESERVATION_RELEASE: 2371 update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req); 2372 break; 2373 case SPDK_NVME_OPC_RESERVATION_REPORT: 2374 nvmf_ns_reservation_report(ns, ctrlr, req); 2375 break; 2376 default: 2377 break; 2378 } 2379 2380 /* update reservation information to subsystem's poll group */ 2381 if (update_sgroup) { 2382 update_ctx = calloc(1, sizeof(*update_ctx)); 2383 if (update_ctx == NULL) { 2384 SPDK_ERRLOG("Can't alloc subsystem poll group update context\n"); 2385 goto update_done; 2386 } 2387 update_ctx->subsystem = ctrlr->subsys; 2388 update_ctx->cb_fn = _nvmf_ns_reservation_update_done; 2389 update_ctx->cb_arg = req; 2390 2391 spdk_nvmf_subsystem_update_ns(ctrlr->subsys, subsystem_update_ns_done, update_ctx); 2392 return; 2393 } 2394 2395 update_done: 2396 _nvmf_ns_reservation_update_done(ctrlr->subsys, (void *)req, 0); 2397 } 2398