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