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