1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) Intel Corporation. All rights reserved. 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 "spdk_internal/log.h" 37 #include "spdk/rpc.h" 38 #include "spdk/util.h" 39 #include "spdk/string.h" 40 #include "spdk/env.h" 41 42 #include "spdk/scsi.h" 43 #include "spdk/vhost.h" 44 #include "vhost_internal.h" 45 #include "spdk/bdev.h" 46 47 struct rpc_vhost_scsi_ctrlr { 48 char *ctrlr; 49 char *cpumask; 50 }; 51 52 static void 53 free_rpc_vhost_scsi_ctrlr(struct rpc_vhost_scsi_ctrlr *req) 54 { 55 free(req->ctrlr); 56 free(req->cpumask); 57 } 58 59 static const struct spdk_json_object_decoder rpc_construct_vhost_ctrlr[] = { 60 {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string }, 61 {"cpumask", offsetof(struct rpc_vhost_scsi_ctrlr, cpumask), spdk_json_decode_string, true}, 62 }; 63 64 static void 65 spdk_rpc_construct_vhost_scsi_controller(struct spdk_jsonrpc_request *request, 66 const struct spdk_json_val *params) 67 { 68 struct rpc_vhost_scsi_ctrlr req = {0}; 69 struct spdk_json_write_ctx *w; 70 int rc; 71 72 if (spdk_json_decode_object(params, rpc_construct_vhost_ctrlr, 73 SPDK_COUNTOF(rpc_construct_vhost_ctrlr), 74 &req)) { 75 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 76 rc = -EINVAL; 77 goto invalid; 78 } 79 80 rc = spdk_vhost_scsi_dev_construct(req.ctrlr, req.cpumask); 81 if (rc < 0) { 82 goto invalid; 83 } 84 85 free_rpc_vhost_scsi_ctrlr(&req); 86 87 w = spdk_jsonrpc_begin_result(request); 88 if (w == NULL) { 89 return; 90 } 91 92 spdk_json_write_bool(w, true); 93 spdk_jsonrpc_end_result(request, w); 94 return; 95 96 invalid: 97 free_rpc_vhost_scsi_ctrlr(&req); 98 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 99 spdk_strerror(-rc)); 100 } 101 SPDK_RPC_REGISTER("construct_vhost_scsi_controller", spdk_rpc_construct_vhost_scsi_controller, 102 SPDK_RPC_RUNTIME) 103 104 struct rpc_add_vhost_scsi_ctrlr_lun { 105 char *ctrlr; 106 uint32_t scsi_target_num; 107 char *bdev_name; 108 109 struct spdk_jsonrpc_request *request; 110 }; 111 112 static void 113 free_rpc_add_vhost_scsi_ctrlr_lun(struct rpc_add_vhost_scsi_ctrlr_lun *req) 114 { 115 free(req->ctrlr); 116 free(req->bdev_name); 117 free(req); 118 } 119 120 static const struct spdk_json_object_decoder rpc_vhost_add_lun[] = { 121 {"ctrlr", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, ctrlr), spdk_json_decode_string }, 122 {"scsi_target_num", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, scsi_target_num), spdk_json_decode_uint32}, 123 {"bdev_name", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, bdev_name), spdk_json_decode_string }, 124 }; 125 126 static int 127 spdk_rpc_add_vhost_scsi_lun_cb(struct spdk_vhost_dev *vdev, void *arg) 128 { 129 struct rpc_add_vhost_scsi_ctrlr_lun *rpc = arg; 130 struct spdk_jsonrpc_request *request = rpc->request; 131 struct spdk_json_write_ctx *w; 132 int rc; 133 134 if (vdev == NULL) { 135 rc = -ENODEV; 136 goto invalid; 137 } 138 139 rc = spdk_vhost_scsi_dev_add_tgt(vdev, rpc->scsi_target_num, rpc->bdev_name); 140 if (rc < 0) { 141 goto invalid; 142 } 143 144 free_rpc_add_vhost_scsi_ctrlr_lun(rpc); 145 146 w = spdk_jsonrpc_begin_result(request); 147 if (w == NULL) { 148 return -1; 149 } 150 151 spdk_json_write_bool(w, true); 152 spdk_jsonrpc_end_result(request, w); 153 return 0; 154 155 invalid: 156 free_rpc_add_vhost_scsi_ctrlr_lun(rpc); 157 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 158 spdk_strerror(-rc)); 159 return rc; 160 } 161 162 static void 163 spdk_rpc_add_vhost_scsi_lun(struct spdk_jsonrpc_request *request, 164 const struct spdk_json_val *params) 165 { 166 struct rpc_add_vhost_scsi_ctrlr_lun *req; 167 int rc; 168 169 req = calloc(1, sizeof(*req)); 170 if (req == NULL) { 171 rc = -ENOMEM; 172 goto invalid; 173 } 174 175 req->request = request; 176 if (spdk_json_decode_object(params, rpc_vhost_add_lun, 177 SPDK_COUNTOF(rpc_vhost_add_lun), 178 req)) { 179 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 180 rc = -EINVAL; 181 goto invalid; 182 } 183 184 if (req->ctrlr == NULL) { 185 SPDK_ERRLOG("No controller name\n"); 186 rc = -EINVAL; 187 goto invalid; 188 } 189 190 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_add_vhost_scsi_lun_cb, req); 191 192 return; 193 194 invalid: 195 if (req) { 196 free_rpc_add_vhost_scsi_ctrlr_lun(req); 197 } 198 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 199 spdk_strerror(-rc)); 200 } 201 SPDK_RPC_REGISTER("add_vhost_scsi_lun", spdk_rpc_add_vhost_scsi_lun, SPDK_RPC_RUNTIME) 202 203 struct rpc_remove_vhost_scsi_ctrlr_target { 204 char *ctrlr; 205 uint32_t scsi_target_num; 206 207 struct spdk_jsonrpc_request *request; 208 }; 209 210 static void 211 free_rpc_remove_vhost_scsi_ctrlr_target(struct rpc_remove_vhost_scsi_ctrlr_target *req) 212 { 213 free(req->ctrlr); 214 free(req); 215 } 216 217 static const struct spdk_json_object_decoder rpc_vhost_remove_target[] = { 218 {"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, ctrlr), spdk_json_decode_string }, 219 {"scsi_target_num", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, scsi_target_num), spdk_json_decode_uint32}, 220 }; 221 222 static int 223 spdk_rpc_remove_vhost_scsi_target_finish_cb(struct spdk_vhost_dev *vdev, void *arg) 224 { 225 struct rpc_remove_vhost_scsi_ctrlr_target *rpc = arg; 226 struct spdk_jsonrpc_request *request = rpc->request; 227 struct spdk_json_write_ctx *w; 228 229 free_rpc_remove_vhost_scsi_ctrlr_target(rpc); 230 231 w = spdk_jsonrpc_begin_result(request); 232 if (w == NULL) { 233 return -1; 234 } 235 236 spdk_json_write_bool(w, true); 237 spdk_jsonrpc_end_result(request, w); 238 return 0; 239 } 240 241 static int 242 spdk_rpc_remove_vhost_scsi_target_cb(struct spdk_vhost_dev *vdev, void *arg) 243 { 244 struct rpc_remove_vhost_scsi_ctrlr_target *rpc = arg; 245 struct spdk_jsonrpc_request *request = rpc->request; 246 int rc; 247 248 if (vdev == NULL) { 249 rc = -ENODEV; 250 goto invalid; 251 } 252 253 rc = spdk_vhost_scsi_dev_remove_tgt(vdev, rpc->scsi_target_num, 254 spdk_rpc_remove_vhost_scsi_target_finish_cb, rpc); 255 if (rc < 0) { 256 goto invalid; 257 } 258 259 return 0; 260 261 invalid: 262 free_rpc_remove_vhost_scsi_ctrlr_target(rpc); 263 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc)); 264 return rc; 265 } 266 267 static void 268 spdk_rpc_remove_vhost_scsi_target(struct spdk_jsonrpc_request *request, 269 const struct spdk_json_val *params) 270 { 271 struct rpc_remove_vhost_scsi_ctrlr_target *req; 272 int rc; 273 274 req = calloc(1, sizeof(*req)); 275 if (req == NULL) { 276 rc = -ENOMEM; 277 goto invalid; 278 } 279 280 req->request = request; 281 if (spdk_json_decode_object(params, rpc_vhost_remove_target, 282 SPDK_COUNTOF(rpc_vhost_remove_target), 283 req)) { 284 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 285 rc = -EINVAL; 286 goto invalid; 287 } 288 289 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_remove_vhost_scsi_target_cb, req); 290 291 return; 292 293 invalid: 294 if (req) { 295 free_rpc_remove_vhost_scsi_ctrlr_target(req); 296 } 297 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 298 spdk_strerror(-rc)); 299 } 300 301 SPDK_RPC_REGISTER("remove_vhost_scsi_target", spdk_rpc_remove_vhost_scsi_target, SPDK_RPC_RUNTIME) 302 303 struct rpc_vhost_blk_ctrlr { 304 char *ctrlr; 305 char *dev_name; 306 char *cpumask; 307 bool readonly; 308 }; 309 310 static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = { 311 {"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string }, 312 {"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string }, 313 {"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true}, 314 {"readonly", offsetof(struct rpc_vhost_blk_ctrlr, readonly), spdk_json_decode_bool, true}, 315 }; 316 317 static void 318 free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req) 319 { 320 free(req->ctrlr); 321 free(req->dev_name); 322 free(req->cpumask); 323 } 324 325 static void 326 spdk_rpc_construct_vhost_blk_controller(struct spdk_jsonrpc_request *request, 327 const struct spdk_json_val *params) 328 { 329 struct rpc_vhost_blk_ctrlr req = {0}; 330 struct spdk_json_write_ctx *w; 331 int rc; 332 333 if (spdk_json_decode_object(params, rpc_construct_vhost_blk_ctrlr, 334 SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr), 335 &req)) { 336 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 337 rc = -EINVAL; 338 goto invalid; 339 } 340 341 rc = spdk_vhost_blk_construct(req.ctrlr, req.cpumask, req.dev_name, req.readonly); 342 if (rc < 0) { 343 goto invalid; 344 } 345 346 free_rpc_vhost_blk_ctrlr(&req); 347 348 w = spdk_jsonrpc_begin_result(request); 349 if (w == NULL) { 350 return; 351 } 352 353 spdk_json_write_bool(w, true); 354 spdk_jsonrpc_end_result(request, w); 355 return; 356 357 invalid: 358 free_rpc_vhost_blk_ctrlr(&req); 359 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 360 spdk_strerror(-rc)); 361 362 } 363 SPDK_RPC_REGISTER("construct_vhost_blk_controller", spdk_rpc_construct_vhost_blk_controller, 364 SPDK_RPC_RUNTIME) 365 366 struct rpc_remove_vhost_ctrlr { 367 char *ctrlr; 368 369 struct spdk_jsonrpc_request *request; 370 }; 371 372 static const struct spdk_json_object_decoder rpc_remove_vhost_ctrlr[] = { 373 {"ctrlr", offsetof(struct rpc_remove_vhost_ctrlr, ctrlr), spdk_json_decode_string }, 374 }; 375 376 static void 377 free_rpc_remove_vhost_ctrlr(struct rpc_remove_vhost_ctrlr *req) 378 { 379 free(req->ctrlr); 380 free(req); 381 } 382 383 static int 384 spdk_rpc_remove_vhost_controller_cb(struct spdk_vhost_dev *vdev, void *arg) 385 { 386 struct rpc_remove_vhost_ctrlr *ctx = arg; 387 struct spdk_jsonrpc_request *request = ctx->request; 388 struct spdk_json_write_ctx *w; 389 int rc; 390 391 if (vdev == NULL) { 392 rc = -ENODEV; 393 goto invalid; 394 } 395 396 rc = spdk_vhost_dev_remove(vdev); 397 if (rc < 0) { 398 goto invalid; 399 } 400 401 free_rpc_remove_vhost_ctrlr(ctx); 402 403 w = spdk_jsonrpc_begin_result(request); 404 if (w == NULL) { 405 return 0; 406 } 407 408 spdk_json_write_bool(w, true); 409 spdk_jsonrpc_end_result(request, w); 410 return 0; 411 412 invalid: 413 free_rpc_remove_vhost_ctrlr(ctx); 414 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 415 spdk_strerror(-rc)); 416 return -1; 417 } 418 419 static void 420 spdk_rpc_remove_vhost_controller(struct spdk_jsonrpc_request *request, 421 const struct spdk_json_val *params) 422 { 423 struct rpc_remove_vhost_ctrlr *req; 424 int rc; 425 426 req = calloc(1, sizeof(*req)); 427 if (req == NULL) { 428 rc = -ENOMEM; 429 goto invalid; 430 } 431 432 req->request = request; 433 if (spdk_json_decode_object(params, rpc_remove_vhost_ctrlr, 434 SPDK_COUNTOF(rpc_remove_vhost_ctrlr), req)) { 435 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 436 rc = -EINVAL; 437 goto invalid; 438 } 439 440 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_remove_vhost_controller_cb, req); 441 return; 442 443 invalid: 444 if (req) { 445 free_rpc_remove_vhost_ctrlr(req); 446 } 447 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 448 spdk_strerror(-rc)); 449 450 } 451 SPDK_RPC_REGISTER("remove_vhost_controller", spdk_rpc_remove_vhost_controller, SPDK_RPC_RUNTIME) 452 453 struct rpc_get_vhost_ctrlrs { 454 struct spdk_json_write_ctx *w; 455 struct spdk_jsonrpc_request *request; 456 }; 457 458 static int 459 spdk_rpc_get_vhost_controllers_cb(struct spdk_vhost_dev *vdev, void *arg) 460 { 461 struct rpc_get_vhost_ctrlrs *ctx = arg; 462 463 if (vdev == NULL) { 464 spdk_json_write_array_end(ctx->w); 465 spdk_jsonrpc_end_result(ctx->request, ctx->w); 466 free(ctx); 467 return 0; 468 } 469 470 spdk_json_write_object_begin(ctx->w); 471 472 spdk_json_write_name(ctx->w, "ctrlr"); 473 spdk_json_write_string(ctx->w, spdk_vhost_dev_get_name(vdev)); 474 475 spdk_json_write_name(ctx->w, "cpumask"); 476 spdk_json_write_string_fmt(ctx->w, "0x%s", spdk_cpuset_fmt(vdev->cpumask)); 477 478 spdk_json_write_name(ctx->w, "backend_specific"); 479 480 spdk_json_write_object_begin(ctx->w); 481 spdk_vhost_dump_info_json(vdev, ctx->w); 482 spdk_json_write_object_end(ctx->w); 483 484 spdk_json_write_object_end(ctx->w); // ctrl 485 486 return 0; 487 } 488 489 490 static void 491 spdk_rpc_get_vhost_controllers(struct spdk_jsonrpc_request *request, 492 const struct spdk_json_val *params) 493 { 494 struct rpc_get_vhost_ctrlrs *ctx; 495 struct spdk_json_write_ctx *w; 496 497 if (params != NULL) { 498 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 499 "get_vhost_controllers requires no parameters"); 500 return; 501 } 502 503 w = spdk_jsonrpc_begin_result(request); 504 if (w == NULL) { 505 return; 506 } 507 508 spdk_json_write_array_begin(w); 509 510 ctx = calloc(1, sizeof(*ctx)); 511 if (ctx == NULL) { 512 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 513 spdk_strerror(ENOMEM)); 514 return; 515 } 516 517 ctx->w = w; 518 ctx->request = request; 519 spdk_vhost_call_external_event_foreach(spdk_rpc_get_vhost_controllers_cb, ctx); 520 } 521 SPDK_RPC_REGISTER("get_vhost_controllers", spdk_rpc_get_vhost_controllers, SPDK_RPC_RUNTIME) 522 523 524 struct rpc_vhost_ctrlr_coalescing { 525 char *ctrlr; 526 uint32_t delay_base_us; 527 uint32_t iops_threshold; 528 struct spdk_jsonrpc_request *request; 529 }; 530 531 static const struct spdk_json_object_decoder rpc_set_vhost_ctrlr_coalescing[] = { 532 {"ctrlr", offsetof(struct rpc_vhost_ctrlr_coalescing, ctrlr), spdk_json_decode_string }, 533 {"delay_base_us", offsetof(struct rpc_vhost_ctrlr_coalescing, delay_base_us), spdk_json_decode_uint32}, 534 {"iops_threshold", offsetof(struct rpc_vhost_ctrlr_coalescing, iops_threshold), spdk_json_decode_uint32}, 535 }; 536 537 static void 538 free_rpc_set_vhost_controllers_event_coalescing(struct rpc_vhost_ctrlr_coalescing *req) 539 { 540 if (!req) { 541 return; 542 } 543 544 free(req->ctrlr); 545 free(req); 546 } 547 548 static int 549 spdk_rpc_set_vhost_controller_coalescing_cb(struct spdk_vhost_dev *vdev, void *arg) 550 { 551 struct rpc_vhost_ctrlr_coalescing *req = arg; 552 struct spdk_json_write_ctx *w; 553 int rc; 554 555 if (vdev == NULL) { 556 rc = -ENODEV; 557 goto invalid; 558 } 559 560 rc = spdk_vhost_set_coalescing(vdev, req->delay_base_us, req->iops_threshold); 561 if (rc) { 562 goto invalid; 563 } 564 565 w = spdk_jsonrpc_begin_result(req->request); 566 if (w != NULL) { 567 spdk_json_write_bool(w, true); 568 spdk_jsonrpc_end_result(req->request, w); 569 } 570 571 free_rpc_set_vhost_controllers_event_coalescing(req); 572 return 0; 573 574 invalid: 575 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 576 spdk_strerror(-rc)); 577 free_rpc_set_vhost_controllers_event_coalescing(req); 578 return 0; 579 } 580 581 static void 582 spdk_rpc_set_vhost_controller_coalescing(struct spdk_jsonrpc_request *request, 583 const struct spdk_json_val *params) 584 { 585 struct rpc_vhost_ctrlr_coalescing *req; 586 int rc; 587 588 req = calloc(1, sizeof(struct rpc_vhost_ctrlr_coalescing)); 589 if (!req) { 590 rc = -ENOMEM; 591 goto invalid; 592 } 593 594 if (spdk_json_decode_object(params, rpc_set_vhost_ctrlr_coalescing, 595 SPDK_COUNTOF(rpc_set_vhost_ctrlr_coalescing), req)) { 596 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 597 rc = -EINVAL; 598 goto invalid; 599 } 600 601 req->request = request; 602 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_set_vhost_controller_coalescing_cb, req); 603 return; 604 605 invalid: 606 free_rpc_set_vhost_controllers_event_coalescing(req); 607 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 608 spdk_strerror(-rc)); 609 } 610 SPDK_RPC_REGISTER("set_vhost_controller_coalescing", spdk_rpc_set_vhost_controller_coalescing, 611 SPDK_RPC_RUNTIME) 612 613 struct rpc_vhost_nvme_ctrlr { 614 char *ctrlr; 615 uint32_t io_queues; 616 char *cpumask; 617 }; 618 619 static const struct spdk_json_object_decoder rpc_construct_vhost_nvme_ctrlr[] = { 620 {"ctrlr", offsetof(struct rpc_vhost_nvme_ctrlr, ctrlr), spdk_json_decode_string }, 621 {"io_queues", offsetof(struct rpc_vhost_nvme_ctrlr, io_queues), spdk_json_decode_uint32}, 622 {"cpumask", offsetof(struct rpc_vhost_nvme_ctrlr, cpumask), spdk_json_decode_string, true}, 623 }; 624 625 static void 626 free_rpc_vhost_nvme_ctrlr(struct rpc_vhost_nvme_ctrlr *req) 627 { 628 free(req->ctrlr); 629 free(req->cpumask); 630 } 631 632 static void 633 spdk_rpc_construct_vhost_nvme_controller(struct spdk_jsonrpc_request *request, 634 const struct spdk_json_val *params) 635 { 636 struct rpc_vhost_nvme_ctrlr req = {0}; 637 struct spdk_json_write_ctx *w; 638 int rc; 639 640 if (spdk_json_decode_object(params, rpc_construct_vhost_nvme_ctrlr, 641 SPDK_COUNTOF(rpc_construct_vhost_nvme_ctrlr), 642 &req)) { 643 rc = -EINVAL; 644 goto invalid; 645 } 646 647 rc = spdk_vhost_nvme_dev_construct(req.ctrlr, req.cpumask, req.io_queues); 648 if (rc < 0) { 649 free_rpc_vhost_nvme_ctrlr(&req); 650 goto invalid; 651 } 652 653 free_rpc_vhost_nvme_ctrlr(&req); 654 655 w = spdk_jsonrpc_begin_result(request); 656 if (w == NULL) { 657 return; 658 } 659 660 spdk_json_write_bool(w, true); 661 spdk_jsonrpc_end_result(request, w); 662 return; 663 664 invalid: 665 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 666 spdk_strerror(-rc)); 667 668 } 669 SPDK_RPC_REGISTER("construct_vhost_nvme_controller", spdk_rpc_construct_vhost_nvme_controller, 670 SPDK_RPC_RUNTIME) 671 672 struct rpc_add_vhost_nvme_ctrlr_ns { 673 char *ctrlr; 674 char *bdev_name; 675 struct spdk_jsonrpc_request *request; 676 }; 677 678 static void 679 free_rpc_add_vhost_nvme_ctrlr_ns(struct rpc_add_vhost_nvme_ctrlr_ns *req) 680 { 681 free(req->ctrlr); 682 free(req->bdev_name); 683 free(req); 684 } 685 686 static const struct spdk_json_object_decoder rpc_vhost_nvme_add_ns[] = { 687 {"ctrlr", offsetof(struct rpc_add_vhost_nvme_ctrlr_ns, ctrlr), spdk_json_decode_string }, 688 {"bdev_name", offsetof(struct rpc_add_vhost_nvme_ctrlr_ns, bdev_name), spdk_json_decode_string }, 689 }; 690 691 static int 692 spdk_rpc_add_vhost_nvme_ns_cb(struct spdk_vhost_dev *vdev, void *arg) 693 { 694 struct rpc_add_vhost_nvme_ctrlr_ns *rpc = arg; 695 struct spdk_jsonrpc_request *request = rpc->request; 696 struct spdk_json_write_ctx *w; 697 int rc; 698 699 if (vdev == NULL) { 700 rc = -ENODEV; 701 goto invalid; 702 } 703 704 rc = spdk_vhost_nvme_dev_add_ns(vdev, rpc->bdev_name); 705 if (rc < 0) { 706 goto invalid; 707 } 708 free_rpc_add_vhost_nvme_ctrlr_ns(rpc); 709 710 w = spdk_jsonrpc_begin_result(request); 711 if (w == NULL) { 712 return -1; 713 } 714 715 spdk_json_write_bool(w, true); 716 spdk_jsonrpc_end_result(request, w); 717 return 0; 718 719 invalid: 720 free_rpc_add_vhost_nvme_ctrlr_ns(rpc); 721 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 722 spdk_strerror(-rc)); 723 return rc; 724 } 725 726 static void 727 spdk_rpc_add_vhost_nvme_ns(struct spdk_jsonrpc_request *request, 728 const struct spdk_json_val *params) 729 { 730 struct rpc_add_vhost_nvme_ctrlr_ns *req; 731 int rc; 732 733 req = calloc(1, sizeof(*req)); 734 if (req == NULL) { 735 rc = -ENOMEM; 736 goto invalid; 737 } 738 739 req->request = request; 740 if (spdk_json_decode_object(params, rpc_vhost_nvme_add_ns, 741 SPDK_COUNTOF(rpc_vhost_nvme_add_ns), 742 req)) { 743 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 744 rc = -EINVAL; 745 goto invalid; 746 } 747 748 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_add_vhost_nvme_ns_cb, req); 749 return; 750 751 invalid: 752 if (req) { 753 free_rpc_add_vhost_nvme_ctrlr_ns(req); 754 } 755 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 756 spdk_strerror(-rc)); 757 } 758 SPDK_RPC_REGISTER("add_vhost_nvme_ns", spdk_rpc_add_vhost_nvme_ns, SPDK_RPC_RUNTIME) 759 760 761 SPDK_LOG_REGISTER_COMPONENT("vhost_rpc", SPDK_LOG_VHOST_RPC) 762