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 char *name; 455 struct spdk_json_write_ctx *w; 456 struct spdk_jsonrpc_request *request; 457 }; 458 459 static void 460 _spdk_rpc_get_vhost_controller(struct spdk_json_write_ctx *w, struct spdk_vhost_dev *vdev) 461 { 462 uint32_t delay_base_us, iops_threshold; 463 464 spdk_vhost_get_coalescing(vdev, &delay_base_us, &iops_threshold); 465 466 spdk_json_write_object_begin(w); 467 468 spdk_json_write_named_string(w, "ctrlr", spdk_vhost_dev_get_name(vdev)); 469 spdk_json_write_named_string_fmt(w, "cpumask", "0x%s", spdk_cpuset_fmt(vdev->cpumask)); 470 spdk_json_write_named_uint32(w, "delay_base_us", delay_base_us); 471 spdk_json_write_named_uint32(w, "iops_threshold", iops_threshold); 472 spdk_json_write_named_string(w, "socket", vdev->path); 473 474 spdk_json_write_named_object_begin(w, "backend_specific"); 475 spdk_vhost_dump_info_json(vdev, w); 476 spdk_json_write_object_end(w); 477 478 spdk_json_write_object_end(w); 479 } 480 481 static int 482 spdk_rpc_get_vhost_controllers_cb(struct spdk_vhost_dev *vdev, void *arg) 483 { 484 struct rpc_get_vhost_ctrlrs *ctx = arg; 485 486 assert(ctx->name == NULL); 487 488 if (vdev == NULL) { 489 spdk_json_write_array_end(ctx->w); 490 spdk_jsonrpc_end_result(ctx->request, ctx->w); 491 free(ctx); 492 return 0; 493 } 494 495 _spdk_rpc_get_vhost_controller(ctx->w, vdev); 496 return 0; 497 } 498 499 static int 500 spdk_rpc_get_vhost_controller_cb(struct spdk_vhost_dev *vdev, void *arg) 501 { 502 struct rpc_get_vhost_ctrlrs *ctx = arg; 503 504 assert(ctx->name != NULL); 505 506 if (vdev == NULL) { 507 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 508 spdk_strerror(ENODEV)); 509 goto free_name_ctx; 510 } 511 512 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 513 if (ctx->w == NULL) { 514 goto free_name_ctx; 515 } 516 517 spdk_json_write_array_begin(ctx->w); 518 _spdk_rpc_get_vhost_controller(ctx->w, vdev); 519 spdk_json_write_array_end(ctx->w); 520 521 spdk_jsonrpc_end_result(ctx->request, ctx->w); 522 523 free_name_ctx: 524 free(ctx->name); 525 free(ctx); 526 return 0; 527 } 528 529 static const struct spdk_json_object_decoder rpc_get_vhost_ctrlrs_decoders[] = { 530 {"name", offsetof(struct rpc_get_vhost_ctrlrs, name), spdk_json_decode_string, true}, 531 }; 532 533 static void 534 spdk_rpc_get_vhost_controllers(struct spdk_jsonrpc_request *request, 535 const struct spdk_json_val *params) 536 { 537 struct rpc_get_vhost_ctrlrs *ctx; 538 struct spdk_json_write_ctx *w; 539 540 ctx = calloc(1, sizeof(*ctx)); 541 if (ctx == NULL) { 542 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 543 spdk_strerror(ENOMEM)); 544 return; 545 } 546 547 if (params && spdk_json_decode_object(params, rpc_get_vhost_ctrlrs_decoders, 548 SPDK_COUNTOF(rpc_get_vhost_ctrlrs_decoders), ctx)) { 549 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 550 free(ctx); 551 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 552 "Invalid parameters"); 553 return; 554 } 555 556 if (ctx->name) { 557 ctx->request = request; 558 spdk_vhost_call_external_event(ctx->name, spdk_rpc_get_vhost_controller_cb, ctx); 559 return; 560 } 561 562 w = spdk_jsonrpc_begin_result(request); 563 if (w == NULL) { 564 free(ctx); 565 return; 566 } 567 568 spdk_json_write_array_begin(w); 569 570 ctx->w = w; 571 ctx->request = request; 572 spdk_vhost_call_external_event_foreach(spdk_rpc_get_vhost_controllers_cb, ctx); 573 } 574 SPDK_RPC_REGISTER("get_vhost_controllers", spdk_rpc_get_vhost_controllers, SPDK_RPC_RUNTIME) 575 576 577 struct rpc_vhost_ctrlr_coalescing { 578 char *ctrlr; 579 uint32_t delay_base_us; 580 uint32_t iops_threshold; 581 struct spdk_jsonrpc_request *request; 582 }; 583 584 static const struct spdk_json_object_decoder rpc_set_vhost_ctrlr_coalescing[] = { 585 {"ctrlr", offsetof(struct rpc_vhost_ctrlr_coalescing, ctrlr), spdk_json_decode_string }, 586 {"delay_base_us", offsetof(struct rpc_vhost_ctrlr_coalescing, delay_base_us), spdk_json_decode_uint32}, 587 {"iops_threshold", offsetof(struct rpc_vhost_ctrlr_coalescing, iops_threshold), spdk_json_decode_uint32}, 588 }; 589 590 static void 591 free_rpc_set_vhost_controllers_event_coalescing(struct rpc_vhost_ctrlr_coalescing *req) 592 { 593 if (!req) { 594 return; 595 } 596 597 free(req->ctrlr); 598 free(req); 599 } 600 601 static int 602 spdk_rpc_set_vhost_controller_coalescing_cb(struct spdk_vhost_dev *vdev, void *arg) 603 { 604 struct rpc_vhost_ctrlr_coalescing *req = arg; 605 struct spdk_json_write_ctx *w; 606 int rc; 607 608 if (vdev == NULL) { 609 rc = -ENODEV; 610 goto invalid; 611 } 612 613 rc = spdk_vhost_set_coalescing(vdev, req->delay_base_us, req->iops_threshold); 614 if (rc) { 615 goto invalid; 616 } 617 618 w = spdk_jsonrpc_begin_result(req->request); 619 if (w != NULL) { 620 spdk_json_write_bool(w, true); 621 spdk_jsonrpc_end_result(req->request, w); 622 } 623 624 free_rpc_set_vhost_controllers_event_coalescing(req); 625 return 0; 626 627 invalid: 628 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 629 spdk_strerror(-rc)); 630 free_rpc_set_vhost_controllers_event_coalescing(req); 631 return 0; 632 } 633 634 static void 635 spdk_rpc_set_vhost_controller_coalescing(struct spdk_jsonrpc_request *request, 636 const struct spdk_json_val *params) 637 { 638 struct rpc_vhost_ctrlr_coalescing *req; 639 int rc; 640 641 req = calloc(1, sizeof(struct rpc_vhost_ctrlr_coalescing)); 642 if (!req) { 643 rc = -ENOMEM; 644 goto invalid; 645 } 646 647 if (spdk_json_decode_object(params, rpc_set_vhost_ctrlr_coalescing, 648 SPDK_COUNTOF(rpc_set_vhost_ctrlr_coalescing), req)) { 649 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 650 rc = -EINVAL; 651 goto invalid; 652 } 653 654 req->request = request; 655 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_set_vhost_controller_coalescing_cb, req); 656 return; 657 658 invalid: 659 free_rpc_set_vhost_controllers_event_coalescing(req); 660 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 661 spdk_strerror(-rc)); 662 } 663 SPDK_RPC_REGISTER("set_vhost_controller_coalescing", spdk_rpc_set_vhost_controller_coalescing, 664 SPDK_RPC_RUNTIME) 665 666 struct rpc_vhost_nvme_ctrlr { 667 char *ctrlr; 668 uint32_t io_queues; 669 char *cpumask; 670 }; 671 672 static const struct spdk_json_object_decoder rpc_construct_vhost_nvme_ctrlr[] = { 673 {"ctrlr", offsetof(struct rpc_vhost_nvme_ctrlr, ctrlr), spdk_json_decode_string }, 674 {"io_queues", offsetof(struct rpc_vhost_nvme_ctrlr, io_queues), spdk_json_decode_uint32}, 675 {"cpumask", offsetof(struct rpc_vhost_nvme_ctrlr, cpumask), spdk_json_decode_string, true}, 676 }; 677 678 static void 679 free_rpc_vhost_nvme_ctrlr(struct rpc_vhost_nvme_ctrlr *req) 680 { 681 free(req->ctrlr); 682 free(req->cpumask); 683 } 684 685 static void 686 spdk_rpc_construct_vhost_nvme_controller(struct spdk_jsonrpc_request *request, 687 const struct spdk_json_val *params) 688 { 689 struct rpc_vhost_nvme_ctrlr req = {}; 690 struct spdk_json_write_ctx *w; 691 int rc; 692 693 if (spdk_json_decode_object(params, rpc_construct_vhost_nvme_ctrlr, 694 SPDK_COUNTOF(rpc_construct_vhost_nvme_ctrlr), 695 &req)) { 696 rc = -EINVAL; 697 goto invalid; 698 } 699 700 rc = spdk_vhost_nvme_dev_construct(req.ctrlr, req.cpumask, req.io_queues); 701 if (rc < 0) { 702 goto invalid; 703 } 704 705 free_rpc_vhost_nvme_ctrlr(&req); 706 707 w = spdk_jsonrpc_begin_result(request); 708 if (w == NULL) { 709 return; 710 } 711 712 spdk_json_write_bool(w, true); 713 spdk_jsonrpc_end_result(request, w); 714 return; 715 716 invalid: 717 free_rpc_vhost_nvme_ctrlr(&req); 718 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 719 spdk_strerror(-rc)); 720 721 } 722 SPDK_RPC_REGISTER("construct_vhost_nvme_controller", spdk_rpc_construct_vhost_nvme_controller, 723 SPDK_RPC_RUNTIME) 724 725 struct rpc_add_vhost_nvme_ctrlr_ns { 726 char *ctrlr; 727 char *bdev_name; 728 struct spdk_jsonrpc_request *request; 729 }; 730 731 static void 732 free_rpc_add_vhost_nvme_ctrlr_ns(struct rpc_add_vhost_nvme_ctrlr_ns *req) 733 { 734 free(req->ctrlr); 735 free(req->bdev_name); 736 free(req); 737 } 738 739 static const struct spdk_json_object_decoder rpc_vhost_nvme_add_ns[] = { 740 {"ctrlr", offsetof(struct rpc_add_vhost_nvme_ctrlr_ns, ctrlr), spdk_json_decode_string }, 741 {"bdev_name", offsetof(struct rpc_add_vhost_nvme_ctrlr_ns, bdev_name), spdk_json_decode_string }, 742 }; 743 744 static int 745 spdk_rpc_add_vhost_nvme_ns_cb(struct spdk_vhost_dev *vdev, void *arg) 746 { 747 struct rpc_add_vhost_nvme_ctrlr_ns *rpc = arg; 748 struct spdk_jsonrpc_request *request = rpc->request; 749 struct spdk_json_write_ctx *w; 750 int rc; 751 752 if (vdev == NULL) { 753 rc = -ENODEV; 754 goto invalid; 755 } 756 757 rc = spdk_vhost_nvme_dev_add_ns(vdev, rpc->bdev_name); 758 if (rc < 0) { 759 goto invalid; 760 } 761 free_rpc_add_vhost_nvme_ctrlr_ns(rpc); 762 763 w = spdk_jsonrpc_begin_result(request); 764 if (w == NULL) { 765 return -1; 766 } 767 768 spdk_json_write_bool(w, true); 769 spdk_jsonrpc_end_result(request, w); 770 return 0; 771 772 invalid: 773 free_rpc_add_vhost_nvme_ctrlr_ns(rpc); 774 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 775 spdk_strerror(-rc)); 776 return rc; 777 } 778 779 static void 780 spdk_rpc_add_vhost_nvme_ns(struct spdk_jsonrpc_request *request, 781 const struct spdk_json_val *params) 782 { 783 struct rpc_add_vhost_nvme_ctrlr_ns *req; 784 int rc; 785 786 req = calloc(1, sizeof(*req)); 787 if (req == NULL) { 788 rc = -ENOMEM; 789 goto invalid; 790 } 791 792 req->request = request; 793 if (spdk_json_decode_object(params, rpc_vhost_nvme_add_ns, 794 SPDK_COUNTOF(rpc_vhost_nvme_add_ns), 795 req)) { 796 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 797 rc = -EINVAL; 798 goto invalid; 799 } 800 801 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_add_vhost_nvme_ns_cb, req); 802 return; 803 804 invalid: 805 if (req) { 806 free_rpc_add_vhost_nvme_ctrlr_ns(req); 807 } 808 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 809 spdk_strerror(-rc)); 810 } 811 SPDK_RPC_REGISTER("add_vhost_nvme_ns", spdk_rpc_add_vhost_nvme_ns, SPDK_RPC_RUNTIME) 812 813 814 SPDK_LOG_REGISTER_COMPONENT("vhost_rpc", SPDK_LOG_VHOST_RPC) 815