1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. All rights reserved. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 8 #include "spdk/log.h" 9 #include "spdk/rpc.h" 10 #include "spdk/util.h" 11 #include "spdk/string.h" 12 #include "spdk/env.h" 13 #include "spdk/log.h" 14 #include "spdk/scsi.h" 15 #include "spdk/vhost.h" 16 #include "vhost_internal.h" 17 #include "spdk/bdev.h" 18 19 struct rpc_vhost_scsi_ctrlr { 20 char *ctrlr; 21 char *cpumask; 22 bool delay; 23 }; 24 25 static void 26 free_rpc_vhost_scsi_ctrlr(struct rpc_vhost_scsi_ctrlr *req) 27 { 28 free(req->ctrlr); 29 free(req->cpumask); 30 } 31 32 static const struct spdk_json_object_decoder rpc_vhost_create_scsi_ctrlr[] = { 33 {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string }, 34 {"cpumask", offsetof(struct rpc_vhost_scsi_ctrlr, cpumask), spdk_json_decode_string, true}, 35 {"delay", offsetof(struct rpc_vhost_scsi_ctrlr, delay), spdk_json_decode_bool, true}, 36 }; 37 38 static void 39 rpc_vhost_create_scsi_controller(struct spdk_jsonrpc_request *request, 40 const struct spdk_json_val *params) 41 { 42 struct rpc_vhost_scsi_ctrlr req = {0}; 43 int rc; 44 45 if (spdk_json_decode_object(params, rpc_vhost_create_scsi_ctrlr, 46 SPDK_COUNTOF(rpc_vhost_create_scsi_ctrlr), 47 &req)) { 48 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 49 rc = -EINVAL; 50 goto invalid; 51 } 52 53 if (req.delay) { 54 rc = spdk_vhost_scsi_dev_construct_no_start(req.ctrlr, req.cpumask); 55 } else { 56 rc = spdk_vhost_scsi_dev_construct(req.ctrlr, req.cpumask); 57 } 58 if (rc < 0) { 59 goto invalid; 60 } 61 62 free_rpc_vhost_scsi_ctrlr(&req); 63 64 spdk_jsonrpc_send_bool_response(request, true); 65 return; 66 67 invalid: 68 free_rpc_vhost_scsi_ctrlr(&req); 69 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 70 spdk_strerror(-rc)); 71 } 72 SPDK_RPC_REGISTER("vhost_create_scsi_controller", rpc_vhost_create_scsi_controller, 73 SPDK_RPC_RUNTIME) 74 75 struct rpc_start_vhost_scsi_ctrlr { 76 char *ctrlr; 77 }; 78 79 static void 80 free_rpc_start_vhost_scsi_ctrlr(struct rpc_start_vhost_scsi_ctrlr *req) 81 { 82 free(req->ctrlr); 83 } 84 85 static const struct spdk_json_object_decoder rpc_start_vhost_scsi_ctrlr_decoder[] = { 86 {"ctrlr", offsetof(struct rpc_start_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string }, 87 }; 88 89 static void 90 rpc_vhost_start_scsi_controller(struct spdk_jsonrpc_request *request, 91 const struct spdk_json_val *params) 92 { 93 struct rpc_start_vhost_scsi_ctrlr req = {0}; 94 int rc; 95 96 if (spdk_json_decode_object(params, rpc_start_vhost_scsi_ctrlr_decoder, 97 SPDK_COUNTOF(rpc_start_vhost_scsi_ctrlr_decoder), 98 &req)) { 99 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 100 rc = -EINVAL; 101 goto invalid; 102 } 103 104 rc = vhost_scsi_controller_start(req.ctrlr); 105 if (rc < 0) { 106 goto invalid; 107 } 108 109 free_rpc_start_vhost_scsi_ctrlr(&req); 110 111 spdk_jsonrpc_send_bool_response(request, true); 112 return; 113 114 invalid: 115 free_rpc_start_vhost_scsi_ctrlr(&req); 116 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 117 spdk_strerror(-rc)); 118 } 119 SPDK_RPC_REGISTER("vhost_start_scsi_controller", rpc_vhost_start_scsi_controller, 120 SPDK_RPC_RUNTIME) 121 122 struct rpc_vhost_scsi_ctrlr_add_target { 123 char *ctrlr; 124 int32_t scsi_target_num; 125 char *bdev_name; 126 }; 127 128 static void 129 free_rpc_vhost_scsi_ctrlr_add_target(struct rpc_vhost_scsi_ctrlr_add_target *req) 130 { 131 free(req->ctrlr); 132 free(req->bdev_name); 133 } 134 135 static const struct spdk_json_object_decoder rpc_vhost_scsi_ctrlr_add_target[] = { 136 {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, ctrlr), spdk_json_decode_string }, 137 {"scsi_target_num", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, scsi_target_num), spdk_json_decode_int32}, 138 {"bdev_name", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, bdev_name), spdk_json_decode_string }, 139 }; 140 141 static void 142 rpc_vhost_scsi_controller_add_target(struct spdk_jsonrpc_request *request, 143 const struct spdk_json_val *params) 144 { 145 struct rpc_vhost_scsi_ctrlr_add_target req = {0}; 146 struct spdk_json_write_ctx *w; 147 struct spdk_vhost_dev *vdev; 148 int rc; 149 150 if (spdk_json_decode_object(params, rpc_vhost_scsi_ctrlr_add_target, 151 SPDK_COUNTOF(rpc_vhost_scsi_ctrlr_add_target), 152 &req)) { 153 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 154 rc = -EINVAL; 155 goto invalid; 156 } 157 158 spdk_vhost_lock(); 159 vdev = spdk_vhost_dev_find(req.ctrlr); 160 if (vdev == NULL) { 161 spdk_vhost_unlock(); 162 rc = -ENODEV; 163 goto invalid; 164 } 165 166 rc = spdk_vhost_scsi_dev_add_tgt(vdev, req.scsi_target_num, req.bdev_name); 167 spdk_vhost_unlock(); 168 if (rc < 0) { 169 goto invalid; 170 } 171 172 free_rpc_vhost_scsi_ctrlr_add_target(&req); 173 174 w = spdk_jsonrpc_begin_result(request); 175 spdk_json_write_int32(w, rc); 176 spdk_jsonrpc_end_result(request, w); 177 return; 178 179 invalid: 180 free_rpc_vhost_scsi_ctrlr_add_target(&req); 181 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 182 spdk_strerror(-rc)); 183 } 184 SPDK_RPC_REGISTER("vhost_scsi_controller_add_target", rpc_vhost_scsi_controller_add_target, 185 SPDK_RPC_RUNTIME) 186 187 struct rpc_remove_vhost_scsi_ctrlr_target { 188 char *ctrlr; 189 uint32_t scsi_target_num; 190 }; 191 192 static void 193 free_rpc_remove_vhost_scsi_ctrlr_target(struct rpc_remove_vhost_scsi_ctrlr_target *req) 194 { 195 free(req->ctrlr); 196 } 197 198 static const struct spdk_json_object_decoder rpc_vhost_remove_target[] = { 199 {"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, ctrlr), spdk_json_decode_string }, 200 {"scsi_target_num", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, scsi_target_num), spdk_json_decode_uint32}, 201 }; 202 203 static int 204 rpc_vhost_scsi_controller_remove_target_finish_cb(struct spdk_vhost_dev *vdev, void *arg) 205 { 206 struct spdk_jsonrpc_request *request = arg; 207 208 spdk_jsonrpc_send_bool_response(request, true); 209 return 0; 210 } 211 212 static void 213 rpc_vhost_scsi_controller_remove_target(struct spdk_jsonrpc_request *request, 214 const struct spdk_json_val *params) 215 { 216 struct rpc_remove_vhost_scsi_ctrlr_target req = {0}; 217 struct spdk_vhost_dev *vdev; 218 int rc; 219 220 if (spdk_json_decode_object(params, rpc_vhost_remove_target, 221 SPDK_COUNTOF(rpc_vhost_remove_target), 222 &req)) { 223 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 224 rc = -EINVAL; 225 goto invalid; 226 } 227 228 spdk_vhost_lock(); 229 vdev = spdk_vhost_dev_find(req.ctrlr); 230 if (vdev == NULL) { 231 spdk_vhost_unlock(); 232 rc = -ENODEV; 233 goto invalid; 234 } 235 236 rc = spdk_vhost_scsi_dev_remove_tgt(vdev, req.scsi_target_num, 237 rpc_vhost_scsi_controller_remove_target_finish_cb, 238 request); 239 spdk_vhost_unlock(); 240 if (rc < 0) { 241 goto invalid; 242 } 243 244 free_rpc_remove_vhost_scsi_ctrlr_target(&req); 245 return; 246 247 invalid: 248 free_rpc_remove_vhost_scsi_ctrlr_target(&req); 249 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 250 spdk_strerror(-rc)); 251 } 252 253 SPDK_RPC_REGISTER("vhost_scsi_controller_remove_target", 254 rpc_vhost_scsi_controller_remove_target, SPDK_RPC_RUNTIME) 255 256 struct rpc_vhost_blk_ctrlr { 257 char *ctrlr; 258 char *dev_name; 259 char *cpumask; 260 char *transport; 261 }; 262 263 static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = { 264 {"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string }, 265 {"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string }, 266 {"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true}, 267 {"transport", offsetof(struct rpc_vhost_blk_ctrlr, transport), spdk_json_decode_string, true}, 268 }; 269 270 static void 271 free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req) 272 { 273 free(req->ctrlr); 274 free(req->dev_name); 275 free(req->cpumask); 276 free(req->transport); 277 } 278 279 static void 280 rpc_vhost_create_blk_controller(struct spdk_jsonrpc_request *request, 281 const struct spdk_json_val *params) 282 { 283 struct rpc_vhost_blk_ctrlr req = {0}; 284 int rc; 285 286 if (spdk_json_decode_object_relaxed(params, rpc_construct_vhost_blk_ctrlr, 287 SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr), 288 &req)) { 289 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 290 rc = -EINVAL; 291 goto invalid; 292 } 293 294 rc = spdk_vhost_blk_construct(req.ctrlr, req.cpumask, req.dev_name, req.transport, params); 295 if (rc < 0) { 296 goto invalid; 297 } 298 299 free_rpc_vhost_blk_ctrlr(&req); 300 301 spdk_jsonrpc_send_bool_response(request, true); 302 return; 303 304 invalid: 305 free_rpc_vhost_blk_ctrlr(&req); 306 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 307 spdk_strerror(-rc)); 308 309 } 310 SPDK_RPC_REGISTER("vhost_create_blk_controller", rpc_vhost_create_blk_controller, 311 SPDK_RPC_RUNTIME) 312 313 struct rpc_delete_vhost_ctrlr { 314 char *ctrlr; 315 }; 316 317 static const struct spdk_json_object_decoder rpc_delete_vhost_ctrlr_decoder[] = { 318 {"ctrlr", offsetof(struct rpc_delete_vhost_ctrlr, ctrlr), spdk_json_decode_string }, 319 }; 320 321 static void 322 free_rpc_delete_vhost_ctrlr(struct rpc_delete_vhost_ctrlr *req) 323 { 324 free(req->ctrlr); 325 } 326 327 static void 328 rpc_vhost_delete_controller(struct spdk_jsonrpc_request *request, 329 const struct spdk_json_val *params) 330 { 331 struct rpc_delete_vhost_ctrlr req = {0}; 332 struct spdk_vhost_dev *vdev; 333 int rc; 334 335 if (spdk_json_decode_object(params, rpc_delete_vhost_ctrlr_decoder, 336 SPDK_COUNTOF(rpc_delete_vhost_ctrlr_decoder), &req)) { 337 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 338 rc = -EINVAL; 339 goto invalid; 340 } 341 342 spdk_vhost_lock(); 343 vdev = spdk_vhost_dev_find(req.ctrlr); 344 if (vdev == NULL) { 345 spdk_vhost_unlock(); 346 rc = -ENODEV; 347 goto invalid; 348 } 349 spdk_vhost_unlock(); 350 351 rc = spdk_vhost_dev_remove(vdev); 352 if (rc < 0) { 353 goto invalid; 354 } 355 356 free_rpc_delete_vhost_ctrlr(&req); 357 358 spdk_jsonrpc_send_bool_response(request, true); 359 return; 360 361 invalid: 362 free_rpc_delete_vhost_ctrlr(&req); 363 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 364 spdk_strerror(-rc)); 365 366 } 367 SPDK_RPC_REGISTER("vhost_delete_controller", rpc_vhost_delete_controller, SPDK_RPC_RUNTIME) 368 369 struct rpc_get_vhost_ctrlrs { 370 char *name; 371 }; 372 373 static void 374 _rpc_get_vhost_controller(struct spdk_json_write_ctx *w, struct spdk_vhost_dev *vdev) 375 { 376 uint32_t delay_base_us, iops_threshold; 377 378 spdk_vhost_get_coalescing(vdev, &delay_base_us, &iops_threshold); 379 380 spdk_json_write_object_begin(w); 381 382 spdk_json_write_named_string(w, "ctrlr", spdk_vhost_dev_get_name(vdev)); 383 spdk_json_write_named_string_fmt(w, "cpumask", "0x%s", 384 spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread))); 385 spdk_json_write_named_uint32(w, "delay_base_us", delay_base_us); 386 spdk_json_write_named_uint32(w, "iops_threshold", iops_threshold); 387 spdk_json_write_named_string(w, "socket", vdev->path); 388 spdk_json_write_named_array_begin(w, "sessions"); 389 vhost_session_info_json(vdev, w); 390 spdk_json_write_array_end(w); 391 392 spdk_json_write_named_object_begin(w, "backend_specific"); 393 vhost_dump_info_json(vdev, w); 394 spdk_json_write_object_end(w); 395 396 spdk_json_write_object_end(w); 397 } 398 399 static const struct spdk_json_object_decoder rpc_get_vhost_ctrlrs_decoders[] = { 400 {"name", offsetof(struct rpc_get_vhost_ctrlrs, name), spdk_json_decode_string, true}, 401 }; 402 403 static void 404 free_rpc_get_vhost_ctrlrs(struct rpc_get_vhost_ctrlrs *req) 405 { 406 free(req->name); 407 } 408 409 static void 410 rpc_vhost_get_controllers(struct spdk_jsonrpc_request *request, 411 const struct spdk_json_val *params) 412 { 413 struct rpc_get_vhost_ctrlrs req = {0}; 414 struct spdk_json_write_ctx *w; 415 struct spdk_vhost_dev *vdev; 416 int rc; 417 418 if (params && spdk_json_decode_object(params, rpc_get_vhost_ctrlrs_decoders, 419 SPDK_COUNTOF(rpc_get_vhost_ctrlrs_decoders), &req)) { 420 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 421 rc = -EINVAL; 422 goto invalid; 423 } 424 425 spdk_vhost_lock(); 426 if (req.name != NULL) { 427 vdev = spdk_vhost_dev_find(req.name); 428 if (vdev == NULL) { 429 spdk_vhost_unlock(); 430 rc = -ENODEV; 431 goto invalid; 432 } 433 434 free_rpc_get_vhost_ctrlrs(&req); 435 436 w = spdk_jsonrpc_begin_result(request); 437 spdk_json_write_array_begin(w); 438 439 _rpc_get_vhost_controller(w, vdev); 440 spdk_vhost_unlock(); 441 442 spdk_json_write_array_end(w); 443 spdk_jsonrpc_end_result(request, w); 444 return; 445 } 446 447 free_rpc_get_vhost_ctrlrs(&req); 448 449 w = spdk_jsonrpc_begin_result(request); 450 spdk_json_write_array_begin(w); 451 452 vdev = spdk_vhost_dev_next(NULL); 453 while (vdev != NULL) { 454 _rpc_get_vhost_controller(w, vdev); 455 vdev = spdk_vhost_dev_next(vdev); 456 } 457 spdk_vhost_unlock(); 458 459 spdk_json_write_array_end(w); 460 spdk_jsonrpc_end_result(request, w); 461 return; 462 463 invalid: 464 free_rpc_get_vhost_ctrlrs(&req); 465 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 466 spdk_strerror(-rc)); 467 } 468 SPDK_RPC_REGISTER("vhost_get_controllers", rpc_vhost_get_controllers, SPDK_RPC_RUNTIME) 469 470 471 struct rpc_vhost_ctrlr_coalescing { 472 char *ctrlr; 473 uint32_t delay_base_us; 474 uint32_t iops_threshold; 475 }; 476 477 static const struct spdk_json_object_decoder rpc_set_vhost_ctrlr_coalescing[] = { 478 {"ctrlr", offsetof(struct rpc_vhost_ctrlr_coalescing, ctrlr), spdk_json_decode_string }, 479 {"delay_base_us", offsetof(struct rpc_vhost_ctrlr_coalescing, delay_base_us), spdk_json_decode_uint32}, 480 {"iops_threshold", offsetof(struct rpc_vhost_ctrlr_coalescing, iops_threshold), spdk_json_decode_uint32}, 481 }; 482 483 static void 484 free_rpc_set_vhost_controllers_event_coalescing(struct rpc_vhost_ctrlr_coalescing *req) 485 { 486 free(req->ctrlr); 487 } 488 489 static void 490 rpc_vhost_controller_set_coalescing(struct spdk_jsonrpc_request *request, 491 const struct spdk_json_val *params) 492 { 493 struct rpc_vhost_ctrlr_coalescing req = {0}; 494 struct spdk_vhost_dev *vdev; 495 int rc; 496 497 if (spdk_json_decode_object(params, rpc_set_vhost_ctrlr_coalescing, 498 SPDK_COUNTOF(rpc_set_vhost_ctrlr_coalescing), &req)) { 499 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 500 rc = -EINVAL; 501 goto invalid; 502 } 503 504 spdk_vhost_lock(); 505 vdev = spdk_vhost_dev_find(req.ctrlr); 506 if (vdev == NULL) { 507 spdk_vhost_unlock(); 508 rc = -ENODEV; 509 goto invalid; 510 } 511 512 rc = spdk_vhost_set_coalescing(vdev, req.delay_base_us, req.iops_threshold); 513 spdk_vhost_unlock(); 514 if (rc) { 515 goto invalid; 516 } 517 518 free_rpc_set_vhost_controllers_event_coalescing(&req); 519 520 spdk_jsonrpc_send_bool_response(request, true); 521 return; 522 523 invalid: 524 free_rpc_set_vhost_controllers_event_coalescing(&req); 525 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 526 spdk_strerror(-rc)); 527 } 528 SPDK_RPC_REGISTER("vhost_controller_set_coalescing", rpc_vhost_controller_set_coalescing, 529 SPDK_RPC_RUNTIME) 530 531 struct rpc_get_transport { 532 char *name; 533 }; 534 535 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = { 536 {"name", offsetof(struct rpc_get_transport, name), spdk_json_decode_string, true}, 537 }; 538 539 static void 540 rpc_virtio_blk_get_transports(struct spdk_jsonrpc_request *request, 541 const struct spdk_json_val *params) 542 { 543 struct rpc_get_transport req = { 0 }; 544 struct spdk_json_write_ctx *w; 545 struct spdk_virtio_blk_transport *transport = NULL; 546 547 if (params) { 548 if (spdk_json_decode_object(params, rpc_get_transport_decoders, 549 SPDK_COUNTOF(rpc_get_transport_decoders), 550 &req)) { 551 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 552 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 553 return; 554 } 555 } 556 557 if (req.name) { 558 transport = virtio_blk_tgt_get_transport(req.name); 559 if (transport == NULL) { 560 SPDK_ERRLOG("transport '%s' does not exist\n", req.name); 561 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 562 free(req.name); 563 return; 564 } 565 } 566 567 w = spdk_jsonrpc_begin_result(request); 568 spdk_json_write_array_begin(w); 569 570 if (transport) { 571 virtio_blk_transport_dump_opts(transport, w); 572 } else { 573 for (transport = virtio_blk_transport_get_first(); transport != NULL; 574 transport = virtio_blk_transport_get_next(transport)) { 575 virtio_blk_transport_dump_opts(transport, w); 576 } 577 } 578 579 spdk_json_write_array_end(w); 580 spdk_jsonrpc_end_result(request, w); 581 free(req.name); 582 } 583 SPDK_RPC_REGISTER("virtio_blk_get_transports", rpc_virtio_blk_get_transports, SPDK_RPC_RUNTIME) 584 585 struct rpc_virtio_blk_create_transport { 586 char *name; 587 }; 588 589 static const struct spdk_json_object_decoder rpc_create_virtio_blk_transport[] = { 590 {"name", offsetof(struct rpc_virtio_blk_create_transport, name), spdk_json_decode_string}, 591 }; 592 593 static void 594 free_rpc_virtio_blk_create_transport(struct rpc_virtio_blk_create_transport *req) 595 { 596 free(req->name); 597 } 598 599 static void 600 rpc_virtio_blk_create_transport(struct spdk_jsonrpc_request *request, 601 const struct spdk_json_val *params) 602 { 603 struct rpc_virtio_blk_create_transport req = {0}; 604 int rc; 605 606 if (spdk_json_decode_object_relaxed(params, rpc_create_virtio_blk_transport, 607 SPDK_COUNTOF(rpc_create_virtio_blk_transport), &req)) { 608 SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n"); 609 rc = -EINVAL; 610 goto invalid; 611 } 612 613 spdk_vhost_lock(); 614 rc = virtio_blk_transport_create(req.name, params); 615 spdk_vhost_unlock(); 616 if (rc != 0) { 617 goto invalid; 618 } 619 620 free_rpc_virtio_blk_create_transport(&req); 621 spdk_jsonrpc_send_bool_response(request, true); 622 return; 623 624 invalid: 625 free_rpc_virtio_blk_create_transport(&req); 626 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 627 } 628 SPDK_RPC_REGISTER("virtio_blk_create_transport", rpc_virtio_blk_create_transport, 629 SPDK_RPC_RUNTIME) 630 631 SPDK_LOG_REGISTER_COMPONENT(vhost_rpc) 632