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_vhost_create_scsi_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 rpc_vhost_create_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_vhost_create_scsi_ctrlr, 73 SPDK_COUNTOF(rpc_vhost_create_scsi_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 spdk_json_write_bool(w, true); 89 spdk_jsonrpc_end_result(request, w); 90 return; 91 92 invalid: 93 free_rpc_vhost_scsi_ctrlr(&req); 94 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 95 spdk_strerror(-rc)); 96 } 97 SPDK_RPC_REGISTER("vhost_create_scsi_controller", rpc_vhost_create_scsi_controller, 98 SPDK_RPC_RUNTIME) 99 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_create_scsi_controller, construct_vhost_scsi_controller) 100 101 struct rpc_vhost_scsi_ctrlr_add_target { 102 char *ctrlr; 103 int32_t scsi_target_num; 104 char *bdev_name; 105 }; 106 107 static void 108 free_rpc_vhost_scsi_ctrlr_add_target(struct rpc_vhost_scsi_ctrlr_add_target *req) 109 { 110 free(req->ctrlr); 111 free(req->bdev_name); 112 } 113 114 static const struct spdk_json_object_decoder rpc_vhost_scsi_ctrlr_add_target[] = { 115 {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, ctrlr), spdk_json_decode_string }, 116 {"scsi_target_num", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, scsi_target_num), spdk_json_decode_int32}, 117 {"bdev_name", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, bdev_name), spdk_json_decode_string }, 118 }; 119 120 static void 121 rpc_vhost_scsi_controller_add_target(struct spdk_jsonrpc_request *request, 122 const struct spdk_json_val *params) 123 { 124 struct rpc_vhost_scsi_ctrlr_add_target req = {0}; 125 struct spdk_json_write_ctx *w; 126 struct spdk_vhost_dev *vdev; 127 int rc; 128 129 if (spdk_json_decode_object(params, rpc_vhost_scsi_ctrlr_add_target, 130 SPDK_COUNTOF(rpc_vhost_scsi_ctrlr_add_target), 131 &req)) { 132 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 133 rc = -EINVAL; 134 goto invalid; 135 } 136 137 spdk_vhost_lock(); 138 vdev = spdk_vhost_dev_find(req.ctrlr); 139 if (vdev == NULL) { 140 spdk_vhost_unlock(); 141 rc = -ENODEV; 142 goto invalid; 143 } 144 145 rc = spdk_vhost_scsi_dev_add_tgt(vdev, req.scsi_target_num, req.bdev_name); 146 spdk_vhost_unlock(); 147 if (rc < 0) { 148 goto invalid; 149 } 150 151 free_rpc_vhost_scsi_ctrlr_add_target(&req); 152 153 w = spdk_jsonrpc_begin_result(request); 154 spdk_json_write_int32(w, rc); 155 spdk_jsonrpc_end_result(request, w); 156 return; 157 158 invalid: 159 free_rpc_vhost_scsi_ctrlr_add_target(&req); 160 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 161 spdk_strerror(-rc)); 162 } 163 SPDK_RPC_REGISTER("vhost_scsi_controller_add_target", rpc_vhost_scsi_controller_add_target, 164 SPDK_RPC_RUNTIME) 165 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_scsi_controller_add_target, add_vhost_scsi_lun) 166 167 struct rpc_remove_vhost_scsi_ctrlr_target { 168 char *ctrlr; 169 uint32_t scsi_target_num; 170 }; 171 172 static void 173 free_rpc_remove_vhost_scsi_ctrlr_target(struct rpc_remove_vhost_scsi_ctrlr_target *req) 174 { 175 free(req->ctrlr); 176 } 177 178 static const struct spdk_json_object_decoder rpc_vhost_remove_target[] = { 179 {"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, ctrlr), spdk_json_decode_string }, 180 {"scsi_target_num", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, scsi_target_num), spdk_json_decode_uint32}, 181 }; 182 183 static int 184 rpc_vhost_scsi_controller_remove_target_finish_cb(struct spdk_vhost_dev *vdev, void *arg) 185 { 186 struct spdk_jsonrpc_request *request = arg; 187 struct spdk_json_write_ctx *w; 188 189 w = spdk_jsonrpc_begin_result(request); 190 spdk_json_write_bool(w, true); 191 spdk_jsonrpc_end_result(request, w); 192 return 0; 193 } 194 195 static void 196 rpc_vhost_scsi_controller_remove_target(struct spdk_jsonrpc_request *request, 197 const struct spdk_json_val *params) 198 { 199 struct rpc_remove_vhost_scsi_ctrlr_target req = {0}; 200 struct spdk_vhost_dev *vdev; 201 int rc; 202 203 if (spdk_json_decode_object(params, rpc_vhost_remove_target, 204 SPDK_COUNTOF(rpc_vhost_remove_target), 205 &req)) { 206 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 207 rc = -EINVAL; 208 goto invalid; 209 } 210 211 spdk_vhost_lock(); 212 vdev = spdk_vhost_dev_find(req.ctrlr); 213 if (vdev == NULL) { 214 spdk_vhost_unlock(); 215 rc = -ENODEV; 216 goto invalid; 217 } 218 219 rc = spdk_vhost_scsi_dev_remove_tgt(vdev, req.scsi_target_num, 220 rpc_vhost_scsi_controller_remove_target_finish_cb, 221 request); 222 spdk_vhost_unlock(); 223 if (rc < 0) { 224 goto invalid; 225 } 226 227 free_rpc_remove_vhost_scsi_ctrlr_target(&req); 228 return; 229 230 invalid: 231 free_rpc_remove_vhost_scsi_ctrlr_target(&req); 232 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 233 spdk_strerror(-rc)); 234 } 235 236 SPDK_RPC_REGISTER("vhost_scsi_controller_remove_target", 237 rpc_vhost_scsi_controller_remove_target, SPDK_RPC_RUNTIME) 238 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_scsi_controller_remove_target, remove_vhost_scsi_target) 239 240 struct rpc_vhost_blk_ctrlr { 241 char *ctrlr; 242 char *dev_name; 243 char *cpumask; 244 bool readonly; 245 bool packed_ring; 246 }; 247 248 static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = { 249 {"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string }, 250 {"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string }, 251 {"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true}, 252 {"readonly", offsetof(struct rpc_vhost_blk_ctrlr, readonly), spdk_json_decode_bool, true}, 253 {"packed_ring", offsetof(struct rpc_vhost_blk_ctrlr, packed_ring), spdk_json_decode_bool, true}, 254 }; 255 256 static void 257 free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req) 258 { 259 free(req->ctrlr); 260 free(req->dev_name); 261 free(req->cpumask); 262 } 263 264 static void 265 rpc_vhost_create_blk_controller(struct spdk_jsonrpc_request *request, 266 const struct spdk_json_val *params) 267 { 268 struct rpc_vhost_blk_ctrlr req = {0}; 269 struct spdk_json_write_ctx *w; 270 int rc; 271 272 if (spdk_json_decode_object(params, rpc_construct_vhost_blk_ctrlr, 273 SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr), 274 &req)) { 275 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 276 rc = -EINVAL; 277 goto invalid; 278 } 279 280 rc = spdk_vhost_blk_construct(req.ctrlr, req.cpumask, req.dev_name, 281 req.readonly, req.packed_ring); 282 if (rc < 0) { 283 goto invalid; 284 } 285 286 free_rpc_vhost_blk_ctrlr(&req); 287 288 w = spdk_jsonrpc_begin_result(request); 289 spdk_json_write_bool(w, true); 290 spdk_jsonrpc_end_result(request, w); 291 return; 292 293 invalid: 294 free_rpc_vhost_blk_ctrlr(&req); 295 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 296 spdk_strerror(-rc)); 297 298 } 299 SPDK_RPC_REGISTER("vhost_create_blk_controller", rpc_vhost_create_blk_controller, 300 SPDK_RPC_RUNTIME) 301 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_create_blk_controller, construct_vhost_blk_controller) 302 303 struct rpc_delete_vhost_ctrlr { 304 char *ctrlr; 305 }; 306 307 static const struct spdk_json_object_decoder rpc_delete_vhost_ctrlr_decoder[] = { 308 {"ctrlr", offsetof(struct rpc_delete_vhost_ctrlr, ctrlr), spdk_json_decode_string }, 309 }; 310 311 static void 312 free_rpc_delete_vhost_ctrlr(struct rpc_delete_vhost_ctrlr *req) 313 { 314 free(req->ctrlr); 315 } 316 317 static void 318 rpc_vhost_delete_controller(struct spdk_jsonrpc_request *request, 319 const struct spdk_json_val *params) 320 { 321 struct rpc_delete_vhost_ctrlr req = {0}; 322 struct spdk_json_write_ctx *w; 323 struct spdk_vhost_dev *vdev; 324 int rc; 325 326 if (spdk_json_decode_object(params, rpc_delete_vhost_ctrlr_decoder, 327 SPDK_COUNTOF(rpc_delete_vhost_ctrlr_decoder), &req)) { 328 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 329 rc = -EINVAL; 330 goto invalid; 331 } 332 333 spdk_vhost_lock(); 334 vdev = spdk_vhost_dev_find(req.ctrlr); 335 if (vdev == NULL) { 336 spdk_vhost_unlock(); 337 rc = -ENODEV; 338 goto invalid; 339 } 340 341 rc = spdk_vhost_dev_remove(vdev); 342 spdk_vhost_unlock(); 343 if (rc < 0) { 344 goto invalid; 345 } 346 347 free_rpc_delete_vhost_ctrlr(&req); 348 349 w = spdk_jsonrpc_begin_result(request); 350 spdk_json_write_bool(w, true); 351 spdk_jsonrpc_end_result(request, w); 352 353 return; 354 355 invalid: 356 free_rpc_delete_vhost_ctrlr(&req); 357 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 358 spdk_strerror(-rc)); 359 360 } 361 SPDK_RPC_REGISTER("vhost_delete_controller", rpc_vhost_delete_controller, SPDK_RPC_RUNTIME) 362 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_delete_controller, remove_vhost_controller) 363 364 struct rpc_get_vhost_ctrlrs { 365 char *name; 366 }; 367 368 static void 369 _rpc_get_vhost_controller(struct spdk_json_write_ctx *w, struct spdk_vhost_dev *vdev) 370 { 371 uint32_t delay_base_us, iops_threshold; 372 373 spdk_vhost_get_coalescing(vdev, &delay_base_us, &iops_threshold); 374 375 spdk_json_write_object_begin(w); 376 377 spdk_json_write_named_string(w, "ctrlr", spdk_vhost_dev_get_name(vdev)); 378 spdk_json_write_named_string_fmt(w, "cpumask", "0x%s", 379 spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread))); 380 spdk_json_write_named_uint32(w, "delay_base_us", delay_base_us); 381 spdk_json_write_named_uint32(w, "iops_threshold", iops_threshold); 382 spdk_json_write_named_string(w, "socket", vdev->path); 383 384 spdk_json_write_named_object_begin(w, "backend_specific"); 385 vhost_dump_info_json(vdev, w); 386 spdk_json_write_object_end(w); 387 388 spdk_json_write_object_end(w); 389 } 390 391 static const struct spdk_json_object_decoder rpc_get_vhost_ctrlrs_decoders[] = { 392 {"name", offsetof(struct rpc_get_vhost_ctrlrs, name), spdk_json_decode_string, true}, 393 }; 394 395 static void 396 free_rpc_get_vhost_ctrlrs(struct rpc_get_vhost_ctrlrs *req) 397 { 398 free(req->name); 399 } 400 401 static void 402 rpc_vhost_get_controllers(struct spdk_jsonrpc_request *request, 403 const struct spdk_json_val *params) 404 { 405 struct rpc_get_vhost_ctrlrs req = {0}; 406 struct spdk_json_write_ctx *w; 407 struct spdk_vhost_dev *vdev; 408 int rc; 409 410 if (params && spdk_json_decode_object(params, rpc_get_vhost_ctrlrs_decoders, 411 SPDK_COUNTOF(rpc_get_vhost_ctrlrs_decoders), &req)) { 412 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 413 rc = -EINVAL; 414 goto invalid; 415 } 416 417 spdk_vhost_lock(); 418 if (req.name != NULL) { 419 vdev = spdk_vhost_dev_find(req.name); 420 if (vdev == NULL) { 421 spdk_vhost_unlock(); 422 rc = -ENODEV; 423 goto invalid; 424 } 425 426 free_rpc_get_vhost_ctrlrs(&req); 427 428 w = spdk_jsonrpc_begin_result(request); 429 spdk_json_write_array_begin(w); 430 431 _rpc_get_vhost_controller(w, vdev); 432 spdk_vhost_unlock(); 433 434 spdk_json_write_array_end(w); 435 spdk_jsonrpc_end_result(request, w); 436 return; 437 } 438 439 free_rpc_get_vhost_ctrlrs(&req); 440 441 w = spdk_jsonrpc_begin_result(request); 442 spdk_json_write_array_begin(w); 443 444 vdev = spdk_vhost_dev_next(NULL); 445 while (vdev != NULL) { 446 _rpc_get_vhost_controller(w, vdev); 447 vdev = spdk_vhost_dev_next(vdev); 448 } 449 spdk_vhost_unlock(); 450 451 spdk_json_write_array_end(w); 452 spdk_jsonrpc_end_result(request, w); 453 return; 454 455 invalid: 456 free_rpc_get_vhost_ctrlrs(&req); 457 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 458 spdk_strerror(-rc)); 459 } 460 SPDK_RPC_REGISTER("vhost_get_controllers", rpc_vhost_get_controllers, SPDK_RPC_RUNTIME) 461 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_get_controllers, get_vhost_controllers) 462 463 464 struct rpc_vhost_ctrlr_coalescing { 465 char *ctrlr; 466 uint32_t delay_base_us; 467 uint32_t iops_threshold; 468 }; 469 470 static const struct spdk_json_object_decoder rpc_set_vhost_ctrlr_coalescing[] = { 471 {"ctrlr", offsetof(struct rpc_vhost_ctrlr_coalescing, ctrlr), spdk_json_decode_string }, 472 {"delay_base_us", offsetof(struct rpc_vhost_ctrlr_coalescing, delay_base_us), spdk_json_decode_uint32}, 473 {"iops_threshold", offsetof(struct rpc_vhost_ctrlr_coalescing, iops_threshold), spdk_json_decode_uint32}, 474 }; 475 476 static void 477 free_rpc_set_vhost_controllers_event_coalescing(struct rpc_vhost_ctrlr_coalescing *req) 478 { 479 free(req->ctrlr); 480 } 481 482 static void 483 rpc_vhost_controller_set_coalescing(struct spdk_jsonrpc_request *request, 484 const struct spdk_json_val *params) 485 { 486 struct rpc_vhost_ctrlr_coalescing req = {0}; 487 struct spdk_json_write_ctx *w; 488 struct spdk_vhost_dev *vdev; 489 int rc; 490 491 if (spdk_json_decode_object(params, rpc_set_vhost_ctrlr_coalescing, 492 SPDK_COUNTOF(rpc_set_vhost_ctrlr_coalescing), &req)) { 493 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 494 rc = -EINVAL; 495 goto invalid; 496 } 497 498 spdk_vhost_lock(); 499 vdev = spdk_vhost_dev_find(req.ctrlr); 500 if (vdev == NULL) { 501 spdk_vhost_unlock(); 502 rc = -ENODEV; 503 goto invalid; 504 } 505 506 rc = spdk_vhost_set_coalescing(vdev, req.delay_base_us, req.iops_threshold); 507 spdk_vhost_unlock(); 508 if (rc) { 509 goto invalid; 510 } 511 512 free_rpc_set_vhost_controllers_event_coalescing(&req); 513 514 w = spdk_jsonrpc_begin_result(request); 515 spdk_json_write_bool(w, true); 516 spdk_jsonrpc_end_result(request, w); 517 518 return; 519 520 invalid: 521 free_rpc_set_vhost_controllers_event_coalescing(&req); 522 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 523 spdk_strerror(-rc)); 524 } 525 SPDK_RPC_REGISTER("vhost_controller_set_coalescing", rpc_vhost_controller_set_coalescing, 526 SPDK_RPC_RUNTIME) 527 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_controller_set_coalescing, set_vhost_controller_coalescing) 528 529 #ifdef SPDK_CONFIG_VHOST_INTERNAL_LIB 530 531 struct rpc_vhost_nvme_ctrlr { 532 char *ctrlr; 533 uint32_t io_queues; 534 char *cpumask; 535 }; 536 537 static const struct spdk_json_object_decoder rpc_construct_vhost_nvme_ctrlr[] = { 538 {"ctrlr", offsetof(struct rpc_vhost_nvme_ctrlr, ctrlr), spdk_json_decode_string }, 539 {"io_queues", offsetof(struct rpc_vhost_nvme_ctrlr, io_queues), spdk_json_decode_uint32}, 540 {"cpumask", offsetof(struct rpc_vhost_nvme_ctrlr, cpumask), spdk_json_decode_string, true}, 541 }; 542 543 static void 544 free_rpc_vhost_nvme_ctrlr(struct rpc_vhost_nvme_ctrlr *req) 545 { 546 free(req->ctrlr); 547 free(req->cpumask); 548 } 549 550 static void 551 rpc_vhost_create_nvme_controller(struct spdk_jsonrpc_request *request, 552 const struct spdk_json_val *params) 553 { 554 struct rpc_vhost_nvme_ctrlr req = {}; 555 struct spdk_json_write_ctx *w; 556 int rc; 557 558 if (spdk_json_decode_object(params, rpc_construct_vhost_nvme_ctrlr, 559 SPDK_COUNTOF(rpc_construct_vhost_nvme_ctrlr), 560 &req)) { 561 rc = -EINVAL; 562 goto invalid; 563 } 564 565 rc = vhost_nvme_dev_construct(req.ctrlr, req.cpumask, req.io_queues); 566 if (rc < 0) { 567 goto invalid; 568 } 569 570 free_rpc_vhost_nvme_ctrlr(&req); 571 572 w = spdk_jsonrpc_begin_result(request); 573 spdk_json_write_bool(w, true); 574 spdk_jsonrpc_end_result(request, w); 575 return; 576 577 invalid: 578 free_rpc_vhost_nvme_ctrlr(&req); 579 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 580 spdk_strerror(-rc)); 581 582 } 583 SPDK_RPC_REGISTER("vhost_create_nvme_controller", rpc_vhost_create_nvme_controller, 584 SPDK_RPC_RUNTIME) 585 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_create_nvme_controller, construct_vhost_nvme_controller) 586 587 struct rpc_vhost_nvme_ctrlr_add_ns { 588 char *ctrlr; 589 char *bdev_name; 590 }; 591 592 static void 593 free_rpc_vhost_nvme_ctrlr_add_ns(struct rpc_vhost_nvme_ctrlr_add_ns *req) 594 { 595 free(req->ctrlr); 596 free(req->bdev_name); 597 } 598 599 static const struct spdk_json_object_decoder rpc_vhost_nvme_add_ns[] = { 600 {"ctrlr", offsetof(struct rpc_vhost_nvme_ctrlr_add_ns, ctrlr), spdk_json_decode_string }, 601 {"bdev_name", offsetof(struct rpc_vhost_nvme_ctrlr_add_ns, bdev_name), spdk_json_decode_string }, 602 }; 603 604 static void 605 rpc_vhost_nvme_controller_add_ns(struct spdk_jsonrpc_request *request, 606 const struct spdk_json_val *params) 607 { 608 struct rpc_vhost_nvme_ctrlr_add_ns req = {0}; 609 struct spdk_json_write_ctx *w; 610 struct spdk_vhost_dev *vdev; 611 int rc; 612 613 if (spdk_json_decode_object(params, rpc_vhost_nvme_add_ns, 614 SPDK_COUNTOF(rpc_vhost_nvme_add_ns), 615 &req)) { 616 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 617 rc = -EINVAL; 618 goto invalid; 619 } 620 621 spdk_vhost_lock(); 622 vdev = spdk_vhost_dev_find(req.ctrlr); 623 if (vdev == NULL) { 624 spdk_vhost_unlock(); 625 rc = -ENODEV; 626 goto invalid; 627 } 628 629 rc = vhost_nvme_dev_add_ns(vdev, req.bdev_name); 630 spdk_vhost_unlock(); 631 if (rc < 0) { 632 goto invalid; 633 } 634 free_rpc_vhost_nvme_ctrlr_add_ns(&req); 635 636 w = spdk_jsonrpc_begin_result(request); 637 spdk_json_write_bool(w, true); 638 spdk_jsonrpc_end_result(request, w); 639 return; 640 641 invalid: 642 free_rpc_vhost_nvme_ctrlr_add_ns(&req); 643 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 644 spdk_strerror(-rc)); 645 } 646 SPDK_RPC_REGISTER("vhost_nvme_controller_add_ns", rpc_vhost_nvme_controller_add_ns, 647 SPDK_RPC_RUNTIME) 648 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_nvme_controller_add_ns, add_vhost_nvme_ns) 649 650 #endif /* SPDK_CONFIG_VHOST_INTERNAL_LIB */ 651 652 SPDK_LOG_REGISTER_COMPONENT("vhost_rpc", SPDK_LOG_VHOST_RPC) 653