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 char buf[64]; 72 73 if (spdk_json_decode_object(params, rpc_construct_vhost_ctrlr, 74 SPDK_COUNTOF(rpc_construct_vhost_ctrlr), 75 &req)) { 76 SPDK_DEBUGLOG(SPDK_TRACE_VHOST_RPC, "spdk_json_decode_object failed\n"); 77 rc = -EINVAL; 78 goto invalid; 79 } 80 81 rc = spdk_vhost_scsi_dev_construct(req.ctrlr, req.cpumask); 82 if (rc < 0) { 83 goto invalid; 84 } 85 86 free_rpc_vhost_scsi_ctrlr(&req); 87 88 w = spdk_jsonrpc_begin_result(request); 89 if (w == NULL) { 90 return; 91 } 92 93 spdk_json_write_bool(w, true); 94 spdk_jsonrpc_end_result(request, w); 95 return; 96 97 invalid: 98 spdk_strerror_r(-rc, buf, sizeof(buf)); 99 free_rpc_vhost_scsi_ctrlr(&req); 100 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 101 } 102 SPDK_RPC_REGISTER("construct_vhost_scsi_controller", spdk_rpc_construct_vhost_scsi_controller) 103 104 struct rpc_add_vhost_scsi_ctrlr_lun { 105 char *ctrlr; 106 uint32_t scsi_dev_num; 107 char *lun_name; 108 109 struct spdk_jsonrpc_request *request; 110 }; 111 112 static void 113 free_rpc_add_vhost_scsi_ctrlr_lun(struct rpc_add_vhost_scsi_ctrlr_lun *req) 114 { 115 free(req->ctrlr); 116 free(req->lun_name); 117 free(req); 118 } 119 120 static const struct spdk_json_object_decoder rpc_vhost_add_lun[] = { 121 {"ctrlr", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, ctrlr), spdk_json_decode_string }, 122 {"scsi_dev_num", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, scsi_dev_num), spdk_json_decode_uint32}, 123 {"lun_name", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, lun_name), spdk_json_decode_string }, 124 }; 125 126 static int 127 spdk_rpc_add_vhost_scsi_lun_cb(struct spdk_vhost_dev *vdev, void *arg) 128 { 129 struct rpc_add_vhost_scsi_ctrlr_lun *rpc = arg; 130 struct spdk_jsonrpc_request *request = rpc->request; 131 struct spdk_json_write_ctx *w; 132 int rc; 133 char buf[64]; 134 135 if (vdev == NULL) { 136 rc = -ENODEV; 137 goto invalid; 138 } 139 140 rc = spdk_vhost_scsi_dev_add_dev(vdev, rpc->scsi_dev_num, rpc->lun_name); 141 if (rc < 0) { 142 goto invalid; 143 } 144 145 free_rpc_add_vhost_scsi_ctrlr_lun(rpc); 146 147 w = spdk_jsonrpc_begin_result(request); 148 if (w == NULL) { 149 return -1; 150 } 151 152 spdk_json_write_bool(w, true); 153 spdk_jsonrpc_end_result(request, w); 154 return 0; 155 156 invalid: 157 free_rpc_add_vhost_scsi_ctrlr_lun(rpc); 158 spdk_strerror_r(-rc, buf, sizeof(buf)); 159 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 160 return rc; 161 } 162 163 static void 164 spdk_rpc_add_vhost_scsi_lun(struct spdk_jsonrpc_request *request, 165 const struct spdk_json_val *params) 166 { 167 struct rpc_add_vhost_scsi_ctrlr_lun *req; 168 char buf[64]; 169 int rc; 170 171 req = calloc(1, sizeof(*req)); 172 if (req == NULL) { 173 rc = -ENOMEM; 174 goto invalid; 175 } 176 177 req->request = request; 178 if (spdk_json_decode_object(params, rpc_vhost_add_lun, 179 SPDK_COUNTOF(rpc_vhost_add_lun), 180 req)) { 181 SPDK_DEBUGLOG(SPDK_TRACE_VHOST_RPC, "spdk_json_decode_object failed\n"); 182 rc = -EINVAL; 183 goto invalid; 184 } 185 186 if (req->ctrlr == NULL) { 187 SPDK_ERRLOG("No controller name\n"); 188 rc = -EINVAL; 189 goto invalid; 190 } 191 192 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_add_vhost_scsi_lun_cb, req); 193 194 return; 195 196 invalid: 197 if (req) { 198 free_rpc_add_vhost_scsi_ctrlr_lun(req); 199 } 200 spdk_strerror_r(-rc, buf, sizeof(buf)); 201 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 202 } 203 SPDK_RPC_REGISTER("add_vhost_scsi_lun", spdk_rpc_add_vhost_scsi_lun) 204 205 struct rpc_remove_vhost_scsi_ctrlr_dev { 206 char *ctrlr; 207 uint32_t scsi_dev_num; 208 209 struct spdk_jsonrpc_request *request; 210 }; 211 212 static void 213 free_rpc_remove_vhost_scsi_ctrlr_dev(struct rpc_remove_vhost_scsi_ctrlr_dev *req) 214 { 215 free(req->ctrlr); 216 free(req); 217 } 218 219 static const struct spdk_json_object_decoder rpc_vhost_remove_dev[] = { 220 {"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr_dev, ctrlr), spdk_json_decode_string }, 221 {"scsi_dev_num", offsetof(struct rpc_remove_vhost_scsi_ctrlr_dev, scsi_dev_num), spdk_json_decode_uint32}, 222 }; 223 224 static int 225 spdk_rpc_remove_vhost_scsi_dev_finish_cb(struct spdk_vhost_dev *vdev, void *arg) 226 { 227 struct rpc_remove_vhost_scsi_ctrlr_dev *rpc = arg; 228 struct spdk_jsonrpc_request *request = rpc->request; 229 struct spdk_json_write_ctx *w; 230 231 free_rpc_remove_vhost_scsi_ctrlr_dev(rpc); 232 233 w = spdk_jsonrpc_begin_result(request); 234 if (w == NULL) { 235 return -1; 236 } 237 238 spdk_json_write_bool(w, true); 239 spdk_jsonrpc_end_result(request, w); 240 return 0; 241 } 242 243 static int 244 spdk_rpc_remove_vhost_scsi_dev_cb(struct spdk_vhost_dev *vdev, void *arg) 245 { 246 struct rpc_remove_vhost_scsi_ctrlr_dev *rpc = arg; 247 struct spdk_jsonrpc_request *request = rpc->request; 248 char buf[64]; 249 int rc; 250 251 if (vdev == NULL) { 252 rc = -ENODEV; 253 goto invalid; 254 } 255 256 rc = spdk_vhost_scsi_dev_remove_dev(vdev, rpc->scsi_dev_num, 257 spdk_rpc_remove_vhost_scsi_dev_finish_cb, rpc); 258 if (rc < 0) { 259 goto invalid; 260 } 261 262 return 0; 263 264 invalid: 265 free_rpc_remove_vhost_scsi_ctrlr_dev(rpc); 266 spdk_strerror_r(-rc, buf, sizeof(buf)); 267 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 268 return rc; 269 } 270 271 static void 272 spdk_rpc_remove_vhost_scsi_dev(struct spdk_jsonrpc_request *request, 273 const struct spdk_json_val *params) 274 { 275 struct rpc_remove_vhost_scsi_ctrlr_dev *req; 276 int rc; 277 char buf[64]; 278 279 req = calloc(1, sizeof(*req)); 280 if (req == NULL) { 281 rc = -ENOMEM; 282 goto invalid; 283 } 284 285 req->request = request; 286 if (spdk_json_decode_object(params, rpc_vhost_remove_dev, 287 SPDK_COUNTOF(rpc_vhost_remove_dev), 288 req)) { 289 SPDK_DEBUGLOG(SPDK_TRACE_VHOST_RPC, "spdk_json_decode_object failed\n"); 290 rc = -EINVAL; 291 goto invalid; 292 } 293 294 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_remove_vhost_scsi_dev_cb, req); 295 296 return; 297 298 invalid: 299 if (req) { 300 free_rpc_remove_vhost_scsi_ctrlr_dev(req); 301 } 302 spdk_strerror_r(-rc, buf, sizeof(buf)); 303 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 304 } 305 306 SPDK_RPC_REGISTER("remove_vhost_scsi_dev", spdk_rpc_remove_vhost_scsi_dev) 307 308 struct rpc_vhost_blk_ctrlr { 309 char *ctrlr; 310 char *dev_name; 311 char *cpumask; 312 bool readonly; 313 }; 314 315 static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = { 316 {"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string }, 317 {"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string }, 318 {"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true}, 319 {"readonly", offsetof(struct rpc_vhost_blk_ctrlr, readonly), spdk_json_decode_bool, true}, 320 }; 321 322 static void 323 free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req) 324 { 325 free(req->ctrlr); 326 free(req->dev_name); 327 free(req->cpumask); 328 } 329 330 static void 331 spdk_rpc_construct_vhost_blk_controller(struct spdk_jsonrpc_request *request, 332 const struct spdk_json_val *params) 333 { 334 struct rpc_vhost_blk_ctrlr req = {0}; 335 struct spdk_json_write_ctx *w; 336 int rc; 337 char buf[64]; 338 339 if (spdk_json_decode_object(params, rpc_construct_vhost_blk_ctrlr, 340 SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr), 341 &req)) { 342 SPDK_DEBUGLOG(SPDK_TRACE_VHOST_RPC, "spdk_json_decode_object failed\n"); 343 rc = -EINVAL; 344 goto invalid; 345 } 346 347 rc = spdk_vhost_blk_construct(req.ctrlr, req.cpumask, req.dev_name, req.readonly); 348 if (rc < 0) { 349 goto invalid; 350 } 351 352 free_rpc_vhost_blk_ctrlr(&req); 353 354 w = spdk_jsonrpc_begin_result(request); 355 if (w == NULL) { 356 return; 357 } 358 359 spdk_json_write_bool(w, true); 360 spdk_jsonrpc_end_result(request, w); 361 return; 362 363 invalid: 364 spdk_strerror_r(-rc, buf, sizeof(buf)); 365 free_rpc_vhost_blk_ctrlr(&req); 366 spdk_jsonrpc_send_error_response(request, 367 SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 368 369 } 370 SPDK_RPC_REGISTER("construct_vhost_blk_controller", spdk_rpc_construct_vhost_blk_controller) 371 372 struct rpc_remove_vhost_ctrlr { 373 char *ctrlr; 374 375 struct spdk_jsonrpc_request *request; 376 }; 377 378 static const struct spdk_json_object_decoder rpc_remove_vhost_ctrlr[] = { 379 {"ctrlr", offsetof(struct rpc_remove_vhost_ctrlr, ctrlr), spdk_json_decode_string }, 380 }; 381 382 static void 383 free_rpc_remove_vhost_ctrlr(struct rpc_remove_vhost_ctrlr *req) 384 { 385 free(req->ctrlr); 386 free(req); 387 } 388 389 static int 390 spdk_rpc_remove_vhost_controller_cb(struct spdk_vhost_dev *vdev, void *arg) 391 { 392 struct rpc_remove_vhost_ctrlr *ctx = arg; 393 struct spdk_jsonrpc_request *request = ctx->request; 394 struct spdk_json_write_ctx *w; 395 int rc; 396 char buf[64]; 397 398 if (vdev == NULL) { 399 rc = -ENODEV; 400 goto invalid; 401 } 402 403 rc = spdk_remove_vhost_controller(vdev); 404 if (rc < 0) { 405 goto invalid; 406 } 407 408 free_rpc_remove_vhost_ctrlr(ctx); 409 410 w = spdk_jsonrpc_begin_result(request); 411 if (w == NULL) { 412 return 0; 413 } 414 415 spdk_json_write_bool(w, true); 416 spdk_jsonrpc_end_result(request, w); 417 return 0; 418 419 invalid: 420 free_rpc_remove_vhost_ctrlr(ctx); 421 spdk_strerror_r(-rc, buf, sizeof(buf)); 422 spdk_jsonrpc_send_error_response(request, 423 SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 424 return -1; 425 } 426 427 static void 428 spdk_rpc_remove_vhost_controller(struct spdk_jsonrpc_request *request, 429 const struct spdk_json_val *params) 430 { 431 struct rpc_remove_vhost_ctrlr *req; 432 char buf[64]; 433 int rc; 434 435 req = calloc(1, sizeof(*req)); 436 if (req == NULL) { 437 rc = -ENOMEM; 438 goto invalid; 439 } 440 441 req->request = request; 442 if (spdk_json_decode_object(params, rpc_remove_vhost_ctrlr, 443 SPDK_COUNTOF(rpc_remove_vhost_ctrlr), req)) { 444 SPDK_DEBUGLOG(SPDK_TRACE_VHOST_RPC, "spdk_json_decode_object failed\n"); 445 rc = -EINVAL; 446 goto invalid; 447 } 448 449 spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_remove_vhost_controller_cb, req); 450 return; 451 452 invalid: 453 if (req) { 454 free_rpc_remove_vhost_ctrlr(req); 455 } 456 spdk_strerror_r(-rc, buf, sizeof(buf)); 457 spdk_jsonrpc_send_error_response(request, 458 SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf); 459 460 } 461 SPDK_RPC_REGISTER("remove_vhost_controller", spdk_rpc_remove_vhost_controller) 462 463 struct rpc_get_vhost_ctrlrs { 464 struct spdk_json_write_ctx *w; 465 struct spdk_jsonrpc_request *request; 466 }; 467 468 static int 469 spdk_rpc_get_vhost_controllers_cb(struct spdk_vhost_dev *vdev, void *arg) 470 { 471 struct rpc_get_vhost_ctrlrs *ctx = arg; 472 473 if (vdev == NULL) { 474 spdk_json_write_array_end(ctx->w); 475 spdk_jsonrpc_end_result(ctx->request, ctx->w); 476 free(ctx); 477 return 0; 478 } 479 480 spdk_json_write_object_begin(ctx->w); 481 482 spdk_json_write_name(ctx->w, "ctrlr"); 483 spdk_json_write_string(ctx->w, spdk_vhost_dev_get_name(vdev)); 484 485 spdk_json_write_name(ctx->w, "cpumask"); 486 spdk_json_write_string_fmt(ctx->w, "%#" PRIx64, spdk_vhost_dev_get_cpumask(vdev)); 487 488 spdk_json_write_name(ctx->w, "backend_specific"); 489 490 spdk_json_write_object_begin(ctx->w); 491 spdk_vhost_dump_config_json(vdev, ctx->w); 492 spdk_json_write_object_end(ctx->w); 493 494 spdk_json_write_object_end(ctx->w); // ctrl 495 496 return 0; 497 } 498 499 500 static void 501 spdk_rpc_get_vhost_controllers(struct spdk_jsonrpc_request *request, 502 const struct spdk_json_val *params) 503 { 504 struct rpc_get_vhost_ctrlrs *ctx; 505 struct spdk_json_write_ctx *w; 506 char buf[64]; 507 508 if (params != NULL) { 509 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 510 "get_vhost_controllers requires no parameters"); 511 return; 512 } 513 514 w = spdk_jsonrpc_begin_result(request); 515 if (w == NULL) { 516 return; 517 } 518 519 spdk_json_write_array_begin(w); 520 521 ctx = calloc(1, sizeof(*ctx)); 522 if (ctx == NULL) { 523 spdk_strerror_r(-ENOMEM, buf, sizeof(buf)); 524 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, buf); 525 return; 526 } 527 528 ctx->w = w; 529 ctx->request = request; 530 spdk_vhost_call_external_event_foreach(spdk_rpc_get_vhost_controllers_cb, ctx); 531 } 532 SPDK_RPC_REGISTER("get_vhost_controllers", spdk_rpc_get_vhost_controllers) 533 534 SPDK_LOG_REGISTER_TRACE_FLAG("vhost_rpc", SPDK_TRACE_VHOST_RPC) 535