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