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 spdk_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", spdk_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 spdk_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", spdk_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 spdk_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 spdk_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 spdk_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 spdk_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 }; 246 247 static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = { 248 {"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string }, 249 {"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string }, 250 {"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true}, 251 {"readonly", offsetof(struct rpc_vhost_blk_ctrlr, readonly), spdk_json_decode_bool, true}, 252 }; 253 254 static void 255 free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req) 256 { 257 free(req->ctrlr); 258 free(req->dev_name); 259 free(req->cpumask); 260 } 261 262 static void 263 spdk_rpc_vhost_create_blk_controller(struct spdk_jsonrpc_request *request, 264 const struct spdk_json_val *params) 265 { 266 struct rpc_vhost_blk_ctrlr req = {0}; 267 struct spdk_json_write_ctx *w; 268 int rc; 269 270 if (spdk_json_decode_object(params, rpc_construct_vhost_blk_ctrlr, 271 SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr), 272 &req)) { 273 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 274 rc = -EINVAL; 275 goto invalid; 276 } 277 278 rc = spdk_vhost_blk_construct(req.ctrlr, req.cpumask, req.dev_name, req.readonly); 279 if (rc < 0) { 280 goto invalid; 281 } 282 283 free_rpc_vhost_blk_ctrlr(&req); 284 285 w = spdk_jsonrpc_begin_result(request); 286 spdk_json_write_bool(w, true); 287 spdk_jsonrpc_end_result(request, w); 288 return; 289 290 invalid: 291 free_rpc_vhost_blk_ctrlr(&req); 292 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 293 spdk_strerror(-rc)); 294 295 } 296 SPDK_RPC_REGISTER("vhost_create_blk_controller", spdk_rpc_vhost_create_blk_controller, 297 SPDK_RPC_RUNTIME) 298 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_create_blk_controller, construct_vhost_blk_controller) 299 300 struct rpc_delete_vhost_ctrlr { 301 char *ctrlr; 302 }; 303 304 static const struct spdk_json_object_decoder rpc_delete_vhost_ctrlr_decoder[] = { 305 {"ctrlr", offsetof(struct rpc_delete_vhost_ctrlr, ctrlr), spdk_json_decode_string }, 306 }; 307 308 static void 309 free_rpc_delete_vhost_ctrlr(struct rpc_delete_vhost_ctrlr *req) 310 { 311 free(req->ctrlr); 312 } 313 314 static void 315 spdk_rpc_vhost_delete_controller(struct spdk_jsonrpc_request *request, 316 const struct spdk_json_val *params) 317 { 318 struct rpc_delete_vhost_ctrlr req = {0}; 319 struct spdk_json_write_ctx *w; 320 struct spdk_vhost_dev *vdev; 321 int rc; 322 323 if (spdk_json_decode_object(params, rpc_delete_vhost_ctrlr_decoder, 324 SPDK_COUNTOF(rpc_delete_vhost_ctrlr_decoder), &req)) { 325 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 326 rc = -EINVAL; 327 goto invalid; 328 } 329 330 spdk_vhost_lock(); 331 vdev = spdk_vhost_dev_find(req.ctrlr); 332 if (vdev == NULL) { 333 spdk_vhost_unlock(); 334 rc = -ENODEV; 335 goto invalid; 336 } 337 338 rc = spdk_vhost_dev_remove(vdev); 339 spdk_vhost_unlock(); 340 if (rc < 0) { 341 goto invalid; 342 } 343 344 free_rpc_delete_vhost_ctrlr(&req); 345 346 w = spdk_jsonrpc_begin_result(request); 347 spdk_json_write_bool(w, true); 348 spdk_jsonrpc_end_result(request, w); 349 350 return; 351 352 invalid: 353 free_rpc_delete_vhost_ctrlr(&req); 354 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 355 spdk_strerror(-rc)); 356 357 } 358 SPDK_RPC_REGISTER("vhost_delete_controller", spdk_rpc_vhost_delete_controller, SPDK_RPC_RUNTIME) 359 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_delete_controller, remove_vhost_controller) 360 361 struct rpc_get_vhost_ctrlrs { 362 char *name; 363 }; 364 365 static void 366 _spdk_rpc_get_vhost_controller(struct spdk_json_write_ctx *w, struct spdk_vhost_dev *vdev) 367 { 368 uint32_t delay_base_us, iops_threshold; 369 370 spdk_vhost_get_coalescing(vdev, &delay_base_us, &iops_threshold); 371 372 spdk_json_write_object_begin(w); 373 374 spdk_json_write_named_string(w, "ctrlr", spdk_vhost_dev_get_name(vdev)); 375 spdk_json_write_named_string_fmt(w, "cpumask", "0x%s", spdk_cpuset_fmt(vdev->cpumask)); 376 spdk_json_write_named_uint32(w, "delay_base_us", delay_base_us); 377 spdk_json_write_named_uint32(w, "iops_threshold", iops_threshold); 378 spdk_json_write_named_string(w, "socket", vdev->path); 379 380 spdk_json_write_named_object_begin(w, "backend_specific"); 381 vhost_dump_info_json(vdev, w); 382 spdk_json_write_object_end(w); 383 384 spdk_json_write_object_end(w); 385 } 386 387 static const struct spdk_json_object_decoder rpc_get_vhost_ctrlrs_decoders[] = { 388 {"name", offsetof(struct rpc_get_vhost_ctrlrs, name), spdk_json_decode_string, true}, 389 }; 390 391 static void 392 free_rpc_get_vhost_ctrlrs(struct rpc_get_vhost_ctrlrs *req) 393 { 394 free(req->name); 395 } 396 397 static void 398 spdk_rpc_vhost_get_controllers(struct spdk_jsonrpc_request *request, 399 const struct spdk_json_val *params) 400 { 401 struct rpc_get_vhost_ctrlrs req = {0}; 402 struct spdk_json_write_ctx *w; 403 struct spdk_vhost_dev *vdev; 404 int rc; 405 406 if (params && spdk_json_decode_object(params, rpc_get_vhost_ctrlrs_decoders, 407 SPDK_COUNTOF(rpc_get_vhost_ctrlrs_decoders), &req)) { 408 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 409 rc = -EINVAL; 410 goto invalid; 411 } 412 413 spdk_vhost_lock(); 414 if (req.name != NULL) { 415 vdev = spdk_vhost_dev_find(req.name); 416 if (vdev == NULL) { 417 spdk_vhost_unlock(); 418 rc = -ENODEV; 419 goto invalid; 420 } 421 422 free_rpc_get_vhost_ctrlrs(&req); 423 424 w = spdk_jsonrpc_begin_result(request); 425 spdk_json_write_array_begin(w); 426 427 _spdk_rpc_get_vhost_controller(w, vdev); 428 spdk_vhost_unlock(); 429 430 spdk_json_write_array_end(w); 431 spdk_jsonrpc_end_result(request, w); 432 return; 433 } 434 435 free_rpc_get_vhost_ctrlrs(&req); 436 437 w = spdk_jsonrpc_begin_result(request); 438 spdk_json_write_array_begin(w); 439 440 vdev = spdk_vhost_dev_next(NULL); 441 while (vdev != NULL) { 442 _spdk_rpc_get_vhost_controller(w, vdev); 443 vdev = spdk_vhost_dev_next(vdev); 444 } 445 spdk_vhost_unlock(); 446 447 spdk_json_write_array_end(w); 448 spdk_jsonrpc_end_result(request, w); 449 return; 450 451 invalid: 452 free_rpc_get_vhost_ctrlrs(&req); 453 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 454 spdk_strerror(-rc)); 455 } 456 SPDK_RPC_REGISTER("vhost_get_controllers", spdk_rpc_vhost_get_controllers, SPDK_RPC_RUNTIME) 457 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_get_controllers, get_vhost_controllers) 458 459 460 struct rpc_vhost_ctrlr_coalescing { 461 char *ctrlr; 462 uint32_t delay_base_us; 463 uint32_t iops_threshold; 464 }; 465 466 static const struct spdk_json_object_decoder rpc_set_vhost_ctrlr_coalescing[] = { 467 {"ctrlr", offsetof(struct rpc_vhost_ctrlr_coalescing, ctrlr), spdk_json_decode_string }, 468 {"delay_base_us", offsetof(struct rpc_vhost_ctrlr_coalescing, delay_base_us), spdk_json_decode_uint32}, 469 {"iops_threshold", offsetof(struct rpc_vhost_ctrlr_coalescing, iops_threshold), spdk_json_decode_uint32}, 470 }; 471 472 static void 473 free_rpc_set_vhost_controllers_event_coalescing(struct rpc_vhost_ctrlr_coalescing *req) 474 { 475 free(req->ctrlr); 476 } 477 478 static void 479 spdk_rpc_vhost_controller_set_coalescing(struct spdk_jsonrpc_request *request, 480 const struct spdk_json_val *params) 481 { 482 struct rpc_vhost_ctrlr_coalescing req = {0}; 483 struct spdk_json_write_ctx *w; 484 struct spdk_vhost_dev *vdev; 485 int rc; 486 487 if (spdk_json_decode_object(params, rpc_set_vhost_ctrlr_coalescing, 488 SPDK_COUNTOF(rpc_set_vhost_ctrlr_coalescing), &req)) { 489 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 490 rc = -EINVAL; 491 goto invalid; 492 } 493 494 spdk_vhost_lock(); 495 vdev = spdk_vhost_dev_find(req.ctrlr); 496 if (vdev == NULL) { 497 spdk_vhost_unlock(); 498 rc = -ENODEV; 499 goto invalid; 500 } 501 502 rc = spdk_vhost_set_coalescing(vdev, req.delay_base_us, req.iops_threshold); 503 spdk_vhost_unlock(); 504 if (rc) { 505 goto invalid; 506 } 507 508 free_rpc_set_vhost_controllers_event_coalescing(&req); 509 510 w = spdk_jsonrpc_begin_result(request); 511 spdk_json_write_bool(w, true); 512 spdk_jsonrpc_end_result(request, w); 513 514 return; 515 516 invalid: 517 free_rpc_set_vhost_controllers_event_coalescing(&req); 518 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 519 spdk_strerror(-rc)); 520 } 521 SPDK_RPC_REGISTER("vhost_controller_set_coalescing", spdk_rpc_vhost_controller_set_coalescing, 522 SPDK_RPC_RUNTIME) 523 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_controller_set_coalescing, set_vhost_controller_coalescing) 524 525 #ifdef SPDK_CONFIG_VHOST_INTERNAL_LIB 526 527 struct rpc_vhost_nvme_ctrlr { 528 char *ctrlr; 529 uint32_t io_queues; 530 char *cpumask; 531 }; 532 533 static const struct spdk_json_object_decoder rpc_construct_vhost_nvme_ctrlr[] = { 534 {"ctrlr", offsetof(struct rpc_vhost_nvme_ctrlr, ctrlr), spdk_json_decode_string }, 535 {"io_queues", offsetof(struct rpc_vhost_nvme_ctrlr, io_queues), spdk_json_decode_uint32}, 536 {"cpumask", offsetof(struct rpc_vhost_nvme_ctrlr, cpumask), spdk_json_decode_string, true}, 537 }; 538 539 static void 540 free_rpc_vhost_nvme_ctrlr(struct rpc_vhost_nvme_ctrlr *req) 541 { 542 free(req->ctrlr); 543 free(req->cpumask); 544 } 545 546 static void 547 spdk_rpc_vhost_create_nvme_controller(struct spdk_jsonrpc_request *request, 548 const struct spdk_json_val *params) 549 { 550 struct rpc_vhost_nvme_ctrlr req = {}; 551 struct spdk_json_write_ctx *w; 552 int rc; 553 554 if (spdk_json_decode_object(params, rpc_construct_vhost_nvme_ctrlr, 555 SPDK_COUNTOF(rpc_construct_vhost_nvme_ctrlr), 556 &req)) { 557 rc = -EINVAL; 558 goto invalid; 559 } 560 561 rc = vhost_nvme_dev_construct(req.ctrlr, req.cpumask, req.io_queues); 562 if (rc < 0) { 563 goto invalid; 564 } 565 566 free_rpc_vhost_nvme_ctrlr(&req); 567 568 w = spdk_jsonrpc_begin_result(request); 569 spdk_json_write_bool(w, true); 570 spdk_jsonrpc_end_result(request, w); 571 return; 572 573 invalid: 574 free_rpc_vhost_nvme_ctrlr(&req); 575 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 576 spdk_strerror(-rc)); 577 578 } 579 SPDK_RPC_REGISTER("vhost_create_nvme_controller", spdk_rpc_vhost_create_nvme_controller, 580 SPDK_RPC_RUNTIME) 581 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_create_nvme_controller, construct_vhost_nvme_controller) 582 583 struct rpc_vhost_nvme_ctrlr_add_ns { 584 char *ctrlr; 585 char *bdev_name; 586 }; 587 588 static void 589 free_rpc_vhost_nvme_ctrlr_add_ns(struct rpc_vhost_nvme_ctrlr_add_ns *req) 590 { 591 free(req->ctrlr); 592 free(req->bdev_name); 593 } 594 595 static const struct spdk_json_object_decoder rpc_vhost_nvme_add_ns[] = { 596 {"ctrlr", offsetof(struct rpc_vhost_nvme_ctrlr_add_ns, ctrlr), spdk_json_decode_string }, 597 {"bdev_name", offsetof(struct rpc_vhost_nvme_ctrlr_add_ns, bdev_name), spdk_json_decode_string }, 598 }; 599 600 static void 601 spdk_rpc_vhost_nvme_controller_add_ns(struct spdk_jsonrpc_request *request, 602 const struct spdk_json_val *params) 603 { 604 struct rpc_vhost_nvme_ctrlr_add_ns req = {0}; 605 struct spdk_json_write_ctx *w; 606 struct spdk_vhost_dev *vdev; 607 int rc; 608 609 if (spdk_json_decode_object(params, rpc_vhost_nvme_add_ns, 610 SPDK_COUNTOF(rpc_vhost_nvme_add_ns), 611 &req)) { 612 SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n"); 613 rc = -EINVAL; 614 goto invalid; 615 } 616 617 spdk_vhost_lock(); 618 vdev = spdk_vhost_dev_find(req.ctrlr); 619 if (vdev == NULL) { 620 spdk_vhost_unlock(); 621 rc = -ENODEV; 622 goto invalid; 623 } 624 625 rc = vhost_nvme_dev_add_ns(vdev, req.bdev_name); 626 spdk_vhost_unlock(); 627 if (rc < 0) { 628 goto invalid; 629 } 630 free_rpc_vhost_nvme_ctrlr_add_ns(&req); 631 632 w = spdk_jsonrpc_begin_result(request); 633 spdk_json_write_bool(w, true); 634 spdk_jsonrpc_end_result(request, w); 635 return; 636 637 invalid: 638 free_rpc_vhost_nvme_ctrlr_add_ns(&req); 639 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 640 spdk_strerror(-rc)); 641 } 642 SPDK_RPC_REGISTER("vhost_nvme_controller_add_ns", spdk_rpc_vhost_nvme_controller_add_ns, 643 SPDK_RPC_RUNTIME) 644 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(vhost_nvme_controller_add_ns, add_vhost_nvme_ns) 645 646 #endif /* SPDK_CONFIG_VHOST_INTERNAL_LIB */ 647 648 SPDK_LOG_REGISTER_COMPONENT("vhost_rpc", SPDK_LOG_VHOST_RPC) 649