1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 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/rpc.h" 35 #include "spdk/bdev.h" 36 #include "spdk/util.h" 37 #include "vbdev_lvol.h" 38 #include "spdk/string.h" 39 #include "spdk_internal/log.h" 40 41 SPDK_LOG_REGISTER_COMPONENT("lvolrpc", SPDK_LOG_LVOL_RPC) 42 43 struct rpc_construct_lvol_store { 44 char *lvs_name; 45 char *bdev_name; 46 uint32_t cluster_sz; 47 char *clear_method; 48 }; 49 50 static int 51 vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name, 52 struct spdk_lvol_store **lvs) 53 { 54 if ((uuid == NULL && lvs_name == NULL)) { 55 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "lvs UUID nor lvs name specified\n"); 56 return -EINVAL; 57 } else if ((uuid && lvs_name)) { 58 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid, 59 lvs_name); 60 return -EINVAL; 61 } else if (uuid) { 62 *lvs = vbdev_get_lvol_store_by_uuid(uuid); 63 64 if (*lvs == NULL) { 65 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "blobstore with UUID '%s' not found\n", uuid); 66 return -ENODEV; 67 } 68 } else if (lvs_name) { 69 70 *lvs = vbdev_get_lvol_store_by_name(lvs_name); 71 72 if (*lvs == NULL) { 73 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "blobstore with name '%s' not found\n", lvs_name); 74 return -ENODEV; 75 } 76 } 77 return 0; 78 } 79 80 static void 81 free_rpc_construct_lvol_store(struct rpc_construct_lvol_store *req) 82 { 83 free(req->bdev_name); 84 free(req->lvs_name); 85 free(req->clear_method); 86 } 87 88 static const struct spdk_json_object_decoder rpc_construct_lvol_store_decoders[] = { 89 {"bdev_name", offsetof(struct rpc_construct_lvol_store, bdev_name), spdk_json_decode_string}, 90 {"cluster_sz", offsetof(struct rpc_construct_lvol_store, cluster_sz), spdk_json_decode_uint32, true}, 91 {"lvs_name", offsetof(struct rpc_construct_lvol_store, lvs_name), spdk_json_decode_string}, 92 {"clear_method", offsetof(struct rpc_construct_lvol_store, clear_method), spdk_json_decode_string, true}, 93 }; 94 95 static void 96 _spdk_rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno) 97 { 98 struct spdk_json_write_ctx *w; 99 char lvol_store_uuid[SPDK_UUID_STRING_LEN]; 100 struct spdk_jsonrpc_request *request = cb_arg; 101 102 if (lvserrno != 0) { 103 goto invalid; 104 } 105 106 spdk_uuid_fmt_lower(lvol_store_uuid, sizeof(lvol_store_uuid), &lvol_store->uuid); 107 108 w = spdk_jsonrpc_begin_result(request); 109 spdk_json_write_string(w, lvol_store_uuid); 110 spdk_jsonrpc_end_result(request, w); 111 return; 112 113 invalid: 114 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 115 spdk_strerror(-lvserrno)); 116 } 117 118 static void 119 spdk_rpc_construct_lvol_store(struct spdk_jsonrpc_request *request, 120 const struct spdk_json_val *params) 121 { 122 struct rpc_construct_lvol_store req = {}; 123 struct spdk_bdev *bdev; 124 int rc = 0; 125 enum lvs_clear_method clear_method; 126 127 if (spdk_json_decode_object(params, rpc_construct_lvol_store_decoders, 128 SPDK_COUNTOF(rpc_construct_lvol_store_decoders), 129 &req)) { 130 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 131 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 132 "spdk_json_decode_object failed"); 133 goto cleanup; 134 } 135 136 bdev = spdk_bdev_get_by_name(req.bdev_name); 137 if (bdev == NULL) { 138 SPDK_ERRLOG("bdev '%s' does not exist\n", req.bdev_name); 139 spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, "Bdev %s not found", req.bdev_name); 140 goto cleanup; 141 } 142 143 if (req.clear_method != NULL) { 144 if (!strcasecmp(req.clear_method, "none")) { 145 clear_method = LVS_CLEAR_WITH_NONE; 146 } else if (!strcasecmp(req.clear_method, "unmap")) { 147 clear_method = LVS_CLEAR_WITH_UNMAP; 148 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 149 clear_method = LVS_CLEAR_WITH_WRITE_ZEROES; 150 } else { 151 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter"); 152 goto cleanup; 153 } 154 } else { 155 clear_method = LVS_CLEAR_WITH_UNMAP; 156 } 157 158 rc = vbdev_lvs_create(bdev, req.lvs_name, req.cluster_sz, clear_method, 159 _spdk_rpc_lvol_store_construct_cb, request); 160 if (rc < 0) { 161 spdk_jsonrpc_send_error_response(request, -rc, spdk_strerror(rc)); 162 goto cleanup; 163 } 164 free_rpc_construct_lvol_store(&req); 165 166 return; 167 168 cleanup: 169 free_rpc_construct_lvol_store(&req); 170 } 171 SPDK_RPC_REGISTER("construct_lvol_store", spdk_rpc_construct_lvol_store, SPDK_RPC_RUNTIME) 172 173 struct rpc_rename_lvol_store { 174 char *old_name; 175 char *new_name; 176 }; 177 178 static void 179 free_rpc_rename_lvol_store(struct rpc_rename_lvol_store *req) 180 { 181 free(req->old_name); 182 free(req->new_name); 183 } 184 185 static const struct spdk_json_object_decoder rpc_rename_lvol_store_decoders[] = { 186 {"old_name", offsetof(struct rpc_rename_lvol_store, old_name), spdk_json_decode_string}, 187 {"new_name", offsetof(struct rpc_rename_lvol_store, new_name), spdk_json_decode_string}, 188 }; 189 190 static void 191 _spdk_rpc_rename_lvol_store_cb(void *cb_arg, int lvserrno) 192 { 193 struct spdk_json_write_ctx *w; 194 struct spdk_jsonrpc_request *request = cb_arg; 195 196 if (lvserrno != 0) { 197 goto invalid; 198 } 199 200 w = spdk_jsonrpc_begin_result(request); 201 spdk_json_write_bool(w, true); 202 spdk_jsonrpc_end_result(request, w); 203 return; 204 205 invalid: 206 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 207 spdk_strerror(-lvserrno)); 208 } 209 210 static void 211 spdk_rpc_rename_lvol_store(struct spdk_jsonrpc_request *request, 212 const struct spdk_json_val *params) 213 { 214 struct rpc_rename_lvol_store req = {}; 215 struct spdk_lvol_store *lvs; 216 217 if (spdk_json_decode_object(params, rpc_rename_lvol_store_decoders, 218 SPDK_COUNTOF(rpc_rename_lvol_store_decoders), 219 &req)) { 220 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 221 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 222 "spdk_json_decode_object failed"); 223 goto cleanup; 224 } 225 226 lvs = vbdev_get_lvol_store_by_name(req.old_name); 227 if (lvs == NULL) { 228 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "no lvs existing for given name\n"); 229 spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name); 230 goto cleanup; 231 } 232 233 vbdev_lvs_rename(lvs, req.new_name, _spdk_rpc_rename_lvol_store_cb, request); 234 235 cleanup: 236 free_rpc_rename_lvol_store(&req); 237 } 238 SPDK_RPC_REGISTER("rename_lvol_store", spdk_rpc_rename_lvol_store, SPDK_RPC_RUNTIME) 239 240 struct rpc_destroy_lvol_store { 241 char *uuid; 242 char *lvs_name; 243 }; 244 245 static void 246 free_rpc_destroy_lvol_store(struct rpc_destroy_lvol_store *req) 247 { 248 free(req->uuid); 249 free(req->lvs_name); 250 } 251 252 static const struct spdk_json_object_decoder rpc_destroy_lvol_store_decoders[] = { 253 {"uuid", offsetof(struct rpc_destroy_lvol_store, uuid), spdk_json_decode_string, true}, 254 {"lvs_name", offsetof(struct rpc_destroy_lvol_store, lvs_name), spdk_json_decode_string, true}, 255 }; 256 257 static void 258 _spdk_rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno) 259 { 260 struct spdk_json_write_ctx *w; 261 struct spdk_jsonrpc_request *request = cb_arg; 262 263 if (lvserrno != 0) { 264 goto invalid; 265 } 266 267 w = spdk_jsonrpc_begin_result(request); 268 spdk_json_write_bool(w, true); 269 spdk_jsonrpc_end_result(request, w); 270 return; 271 272 invalid: 273 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 274 spdk_strerror(-lvserrno)); 275 } 276 277 static void 278 spdk_rpc_destroy_lvol_store(struct spdk_jsonrpc_request *request, 279 const struct spdk_json_val *params) 280 { 281 struct rpc_destroy_lvol_store req = {}; 282 struct spdk_lvol_store *lvs = NULL; 283 int rc; 284 285 if (spdk_json_decode_object(params, rpc_destroy_lvol_store_decoders, 286 SPDK_COUNTOF(rpc_destroy_lvol_store_decoders), 287 &req)) { 288 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 289 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 290 "spdk_json_decode_object failed"); 291 goto cleanup; 292 } 293 294 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 295 if (rc != 0) { 296 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 297 goto cleanup; 298 } 299 300 vbdev_lvs_destruct(lvs, _spdk_rpc_lvol_store_destroy_cb, request); 301 302 cleanup: 303 free_rpc_destroy_lvol_store(&req); 304 } 305 SPDK_RPC_REGISTER("destroy_lvol_store", spdk_rpc_destroy_lvol_store, SPDK_RPC_RUNTIME) 306 307 struct rpc_construct_lvol_bdev { 308 char *uuid; 309 char *lvs_name; 310 char *lvol_name; 311 uint64_t size; 312 bool thin_provision; 313 char *clear_method; 314 }; 315 316 static void 317 free_rpc_construct_lvol_bdev(struct rpc_construct_lvol_bdev *req) 318 { 319 free(req->uuid); 320 free(req->lvs_name); 321 free(req->lvol_name); 322 free(req->clear_method); 323 } 324 325 static const struct spdk_json_object_decoder rpc_construct_lvol_bdev_decoders[] = { 326 {"uuid", offsetof(struct rpc_construct_lvol_bdev, uuid), spdk_json_decode_string, true}, 327 {"lvs_name", offsetof(struct rpc_construct_lvol_bdev, lvs_name), spdk_json_decode_string, true}, 328 {"lvol_name", offsetof(struct rpc_construct_lvol_bdev, lvol_name), spdk_json_decode_string}, 329 {"size", offsetof(struct rpc_construct_lvol_bdev, size), spdk_json_decode_uint64}, 330 {"thin_provision", offsetof(struct rpc_construct_lvol_bdev, thin_provision), spdk_json_decode_bool, true}, 331 {"clear_method", offsetof(struct rpc_construct_lvol_bdev, clear_method), spdk_json_decode_string, true}, 332 }; 333 334 static void 335 _spdk_rpc_construct_lvol_bdev_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 336 { 337 struct spdk_json_write_ctx *w; 338 struct spdk_jsonrpc_request *request = cb_arg; 339 340 if (lvolerrno != 0) { 341 goto invalid; 342 } 343 344 w = spdk_jsonrpc_begin_result(request); 345 spdk_json_write_string(w, lvol->unique_id); 346 spdk_jsonrpc_end_result(request, w); 347 return; 348 349 invalid: 350 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 351 spdk_strerror(-lvolerrno)); 352 } 353 354 static void 355 spdk_rpc_construct_lvol_bdev(struct spdk_jsonrpc_request *request, 356 const struct spdk_json_val *params) 357 { 358 struct rpc_construct_lvol_bdev req = {}; 359 enum lvol_clear_method clear_method; 360 int rc = 0; 361 struct spdk_lvol_store *lvs = NULL; 362 363 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Creating blob\n"); 364 365 if (spdk_json_decode_object(params, rpc_construct_lvol_bdev_decoders, 366 SPDK_COUNTOF(rpc_construct_lvol_bdev_decoders), 367 &req)) { 368 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 369 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 370 "spdk_json_decode_object failed"); 371 goto cleanup; 372 } 373 374 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 375 if (rc != 0) { 376 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 377 goto cleanup; 378 } 379 380 if (req.clear_method != NULL) { 381 if (!strcasecmp(req.clear_method, "none")) { 382 clear_method = LVOL_CLEAR_WITH_NONE; 383 } else if (!strcasecmp(req.clear_method, "unmap")) { 384 clear_method = LVOL_CLEAR_WITH_UNMAP; 385 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 386 clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES; 387 } else { 388 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option"); 389 goto cleanup; 390 } 391 } else { 392 clear_method = LVOL_CLEAR_WITH_DEFAULT; 393 } 394 395 rc = vbdev_lvol_create(lvs, req.lvol_name, req.size, req.thin_provision, 396 clear_method, _spdk_rpc_construct_lvol_bdev_cb, request); 397 if (rc < 0) { 398 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 399 goto cleanup; 400 } 401 402 cleanup: 403 free_rpc_construct_lvol_bdev(&req); 404 } 405 406 SPDK_RPC_REGISTER("construct_lvol_bdev", spdk_rpc_construct_lvol_bdev, SPDK_RPC_RUNTIME) 407 408 struct rpc_snapshot_lvol_bdev { 409 char *lvol_name; 410 char *snapshot_name; 411 }; 412 413 static void 414 free_rpc_snapshot_lvol_bdev(struct rpc_snapshot_lvol_bdev *req) 415 { 416 free(req->lvol_name); 417 free(req->snapshot_name); 418 } 419 420 static const struct spdk_json_object_decoder rpc_snapshot_lvol_bdev_decoders[] = { 421 {"lvol_name", offsetof(struct rpc_snapshot_lvol_bdev, lvol_name), spdk_json_decode_string}, 422 {"snapshot_name", offsetof(struct rpc_snapshot_lvol_bdev, snapshot_name), spdk_json_decode_string}, 423 }; 424 425 static void 426 _spdk_rpc_snapshot_lvol_bdev_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 427 { 428 struct spdk_json_write_ctx *w; 429 struct spdk_jsonrpc_request *request = cb_arg; 430 431 if (lvolerrno != 0) { 432 goto invalid; 433 } 434 435 w = spdk_jsonrpc_begin_result(request); 436 spdk_json_write_string(w, lvol->unique_id); 437 spdk_jsonrpc_end_result(request, w); 438 return; 439 440 invalid: 441 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 442 spdk_strerror(-lvolerrno)); 443 } 444 445 static void 446 spdk_rpc_snapshot_lvol_bdev(struct spdk_jsonrpc_request *request, 447 const struct spdk_json_val *params) 448 { 449 struct rpc_snapshot_lvol_bdev req = {}; 450 struct spdk_bdev *bdev; 451 struct spdk_lvol *lvol; 452 453 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Snapshotting blob\n"); 454 455 if (spdk_json_decode_object(params, rpc_snapshot_lvol_bdev_decoders, 456 SPDK_COUNTOF(rpc_snapshot_lvol_bdev_decoders), 457 &req)) { 458 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 459 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 460 "spdk_json_decode_object failed"); 461 goto cleanup; 462 } 463 464 bdev = spdk_bdev_get_by_name(req.lvol_name); 465 if (bdev == NULL) { 466 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "bdev '%s' does not exist\n", req.lvol_name); 467 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 468 goto cleanup; 469 } 470 471 lvol = vbdev_lvol_get_from_bdev(bdev); 472 if (lvol == NULL) { 473 SPDK_ERRLOG("lvol does not exist\n"); 474 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 475 goto cleanup; 476 } 477 478 vbdev_lvol_create_snapshot(lvol, req.snapshot_name, _spdk_rpc_snapshot_lvol_bdev_cb, request); 479 480 cleanup: 481 free_rpc_snapshot_lvol_bdev(&req); 482 } 483 484 SPDK_RPC_REGISTER("snapshot_lvol_bdev", spdk_rpc_snapshot_lvol_bdev, SPDK_RPC_RUNTIME) 485 486 struct rpc_clone_lvol_bdev { 487 char *snapshot_name; 488 char *clone_name; 489 }; 490 491 static void 492 free_rpc_clone_lvol_bdev(struct rpc_clone_lvol_bdev *req) 493 { 494 free(req->snapshot_name); 495 free(req->clone_name); 496 } 497 498 static const struct spdk_json_object_decoder rpc_clone_lvol_bdev_decoders[] = { 499 {"snapshot_name", offsetof(struct rpc_clone_lvol_bdev, snapshot_name), spdk_json_decode_string}, 500 {"clone_name", offsetof(struct rpc_clone_lvol_bdev, clone_name), spdk_json_decode_string, true}, 501 }; 502 503 static void 504 _spdk_rpc_clone_lvol_bdev_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 505 { 506 struct spdk_json_write_ctx *w; 507 struct spdk_jsonrpc_request *request = cb_arg; 508 509 if (lvolerrno != 0) { 510 goto invalid; 511 } 512 513 w = spdk_jsonrpc_begin_result(request); 514 spdk_json_write_string(w, lvol->unique_id); 515 spdk_jsonrpc_end_result(request, w); 516 return; 517 518 invalid: 519 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 520 spdk_strerror(-lvolerrno)); 521 } 522 523 static void 524 spdk_rpc_clone_lvol_bdev(struct spdk_jsonrpc_request *request, 525 const struct spdk_json_val *params) 526 { 527 struct rpc_clone_lvol_bdev req = {}; 528 struct spdk_bdev *bdev; 529 struct spdk_lvol *lvol; 530 531 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Cloning blob\n"); 532 533 if (spdk_json_decode_object(params, rpc_clone_lvol_bdev_decoders, 534 SPDK_COUNTOF(rpc_clone_lvol_bdev_decoders), 535 &req)) { 536 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 537 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 538 "spdk_json_decode_object failed"); 539 goto cleanup; 540 } 541 542 bdev = spdk_bdev_get_by_name(req.snapshot_name); 543 if (bdev == NULL) { 544 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "bdev '%s' does not exist\n", req.snapshot_name); 545 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 546 goto cleanup; 547 } 548 549 lvol = vbdev_lvol_get_from_bdev(bdev); 550 if (lvol == NULL) { 551 SPDK_ERRLOG("lvol does not exist\n"); 552 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 553 goto cleanup; 554 } 555 556 vbdev_lvol_create_clone(lvol, req.clone_name, _spdk_rpc_clone_lvol_bdev_cb, request); 557 558 cleanup: 559 free_rpc_clone_lvol_bdev(&req); 560 } 561 562 SPDK_RPC_REGISTER("clone_lvol_bdev", spdk_rpc_clone_lvol_bdev, SPDK_RPC_RUNTIME) 563 564 struct rpc_rename_lvol_bdev { 565 char *old_name; 566 char *new_name; 567 }; 568 569 static void 570 free_rpc_rename_lvol_bdev(struct rpc_rename_lvol_bdev *req) 571 { 572 free(req->old_name); 573 free(req->new_name); 574 } 575 576 static const struct spdk_json_object_decoder rpc_rename_lvol_bdev_decoders[] = { 577 {"old_name", offsetof(struct rpc_rename_lvol_bdev, old_name), spdk_json_decode_string}, 578 {"new_name", offsetof(struct rpc_rename_lvol_bdev, new_name), spdk_json_decode_string}, 579 }; 580 581 static void 582 _spdk_rpc_rename_lvol_bdev_cb(void *cb_arg, int lvolerrno) 583 { 584 struct spdk_json_write_ctx *w; 585 struct spdk_jsonrpc_request *request = cb_arg; 586 587 if (lvolerrno != 0) { 588 goto invalid; 589 } 590 591 w = spdk_jsonrpc_begin_result(request); 592 spdk_json_write_bool(w, true); 593 spdk_jsonrpc_end_result(request, w); 594 return; 595 596 invalid: 597 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 598 spdk_strerror(-lvolerrno)); 599 } 600 601 static void 602 spdk_rpc_rename_lvol_bdev(struct spdk_jsonrpc_request *request, 603 const struct spdk_json_val *params) 604 { 605 struct rpc_rename_lvol_bdev req = {}; 606 struct spdk_bdev *bdev; 607 struct spdk_lvol *lvol; 608 609 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Renaming lvol\n"); 610 611 if (spdk_json_decode_object(params, rpc_rename_lvol_bdev_decoders, 612 SPDK_COUNTOF(rpc_rename_lvol_bdev_decoders), 613 &req)) { 614 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 615 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 616 "spdk_json_decode_object failed"); 617 goto cleanup; 618 } 619 620 bdev = spdk_bdev_get_by_name(req.old_name); 621 if (bdev == NULL) { 622 SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name); 623 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 624 goto cleanup; 625 } 626 627 lvol = vbdev_lvol_get_from_bdev(bdev); 628 if (lvol == NULL) { 629 SPDK_ERRLOG("lvol does not exist\n"); 630 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 631 goto cleanup; 632 } 633 634 vbdev_lvol_rename(lvol, req.new_name, _spdk_rpc_rename_lvol_bdev_cb, request); 635 636 cleanup: 637 free_rpc_rename_lvol_bdev(&req); 638 } 639 640 SPDK_RPC_REGISTER("rename_lvol_bdev", spdk_rpc_rename_lvol_bdev, SPDK_RPC_RUNTIME) 641 642 struct rpc_inflate_lvol_bdev { 643 char *name; 644 }; 645 646 static void 647 free_rpc_inflate_lvol_bdev(struct rpc_inflate_lvol_bdev *req) 648 { 649 free(req->name); 650 } 651 652 static const struct spdk_json_object_decoder rpc_inflate_lvol_bdev_decoders[] = { 653 {"name", offsetof(struct rpc_inflate_lvol_bdev, name), spdk_json_decode_string}, 654 }; 655 656 static void 657 _spdk_rpc_inflate_lvol_bdev_cb(void *cb_arg, int lvolerrno) 658 { 659 struct spdk_json_write_ctx *w; 660 struct spdk_jsonrpc_request *request = cb_arg; 661 662 if (lvolerrno != 0) { 663 goto invalid; 664 } 665 666 w = spdk_jsonrpc_begin_result(request); 667 spdk_json_write_bool(w, true); 668 spdk_jsonrpc_end_result(request, w); 669 return; 670 671 invalid: 672 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 673 spdk_strerror(-lvolerrno)); 674 } 675 676 static void 677 spdk_rpc_inflate_lvol_bdev(struct spdk_jsonrpc_request *request, 678 const struct spdk_json_val *params) 679 { 680 struct rpc_inflate_lvol_bdev req = {}; 681 struct spdk_bdev *bdev; 682 struct spdk_lvol *lvol; 683 684 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Inflating lvol\n"); 685 686 if (spdk_json_decode_object(params, rpc_inflate_lvol_bdev_decoders, 687 SPDK_COUNTOF(rpc_inflate_lvol_bdev_decoders), 688 &req)) { 689 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 690 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 691 "spdk_json_decode_object failed"); 692 goto cleanup; 693 } 694 695 bdev = spdk_bdev_get_by_name(req.name); 696 if (bdev == NULL) { 697 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 698 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 699 goto cleanup; 700 } 701 702 lvol = vbdev_lvol_get_from_bdev(bdev); 703 if (lvol == NULL) { 704 SPDK_ERRLOG("lvol does not exist\n"); 705 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 706 goto cleanup; 707 } 708 709 spdk_lvol_inflate(lvol, _spdk_rpc_inflate_lvol_bdev_cb, request); 710 711 cleanup: 712 free_rpc_inflate_lvol_bdev(&req); 713 } 714 715 SPDK_RPC_REGISTER("inflate_lvol_bdev", spdk_rpc_inflate_lvol_bdev, SPDK_RPC_RUNTIME) 716 717 static void 718 spdk_rpc_decouple_parent_lvol_bdev(struct spdk_jsonrpc_request *request, 719 const struct spdk_json_val *params) 720 { 721 struct rpc_inflate_lvol_bdev req = {}; 722 struct spdk_bdev *bdev; 723 struct spdk_lvol *lvol; 724 725 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Decoupling parent of lvol\n"); 726 727 if (spdk_json_decode_object(params, rpc_inflate_lvol_bdev_decoders, 728 SPDK_COUNTOF(rpc_inflate_lvol_bdev_decoders), 729 &req)) { 730 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 731 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 732 "spdk_json_decode_object failed"); 733 goto cleanup; 734 } 735 736 bdev = spdk_bdev_get_by_name(req.name); 737 if (bdev == NULL) { 738 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 739 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 740 goto cleanup; 741 } 742 743 lvol = vbdev_lvol_get_from_bdev(bdev); 744 if (lvol == NULL) { 745 SPDK_ERRLOG("lvol does not exist\n"); 746 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 747 goto cleanup; 748 } 749 750 spdk_lvol_decouple_parent(lvol, _spdk_rpc_inflate_lvol_bdev_cb, request); 751 752 cleanup: 753 free_rpc_inflate_lvol_bdev(&req); 754 } 755 756 SPDK_RPC_REGISTER("decouple_parent_lvol_bdev", spdk_rpc_decouple_parent_lvol_bdev, SPDK_RPC_RUNTIME) 757 758 struct rpc_resize_lvol_bdev { 759 char *name; 760 uint64_t size; 761 }; 762 763 static void 764 free_rpc_resize_lvol_bdev(struct rpc_resize_lvol_bdev *req) 765 { 766 free(req->name); 767 } 768 769 static const struct spdk_json_object_decoder rpc_resize_lvol_bdev_decoders[] = { 770 {"name", offsetof(struct rpc_resize_lvol_bdev, name), spdk_json_decode_string}, 771 {"size", offsetof(struct rpc_resize_lvol_bdev, size), spdk_json_decode_uint64}, 772 }; 773 774 static void 775 _spdk_rpc_resize_lvol_bdev_cb(void *cb_arg, int lvolerrno) 776 { 777 struct spdk_json_write_ctx *w; 778 struct spdk_jsonrpc_request *request = cb_arg; 779 780 if (lvolerrno != 0) { 781 goto invalid; 782 } 783 784 w = spdk_jsonrpc_begin_result(request); 785 spdk_json_write_bool(w, true); 786 spdk_jsonrpc_end_result(request, w); 787 return; 788 789 invalid: 790 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 791 spdk_strerror(-lvolerrno)); 792 } 793 794 static void 795 spdk_rpc_resize_lvol_bdev(struct spdk_jsonrpc_request *request, 796 const struct spdk_json_val *params) 797 { 798 struct rpc_resize_lvol_bdev req = {}; 799 struct spdk_bdev *bdev; 800 struct spdk_lvol *lvol; 801 802 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Resizing lvol\n"); 803 804 if (spdk_json_decode_object(params, rpc_resize_lvol_bdev_decoders, 805 SPDK_COUNTOF(rpc_resize_lvol_bdev_decoders), 806 &req)) { 807 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 808 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 809 "spdk_json_decode_object failed"); 810 goto cleanup; 811 } 812 813 bdev = spdk_bdev_get_by_name(req.name); 814 if (bdev == NULL) { 815 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 816 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 817 goto cleanup; 818 } 819 820 lvol = vbdev_lvol_get_from_bdev(bdev); 821 if (lvol == NULL) { 822 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 823 goto cleanup; 824 } 825 826 vbdev_lvol_resize(lvol, req.size, _spdk_rpc_resize_lvol_bdev_cb, request); 827 828 cleanup: 829 free_rpc_resize_lvol_bdev(&req); 830 } 831 832 SPDK_RPC_REGISTER("resize_lvol_bdev", spdk_rpc_resize_lvol_bdev, SPDK_RPC_RUNTIME) 833 834 struct rpc_set_ro_lvol_bdev { 835 char *name; 836 }; 837 838 static void 839 free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req) 840 { 841 free(req->name); 842 } 843 844 static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = { 845 {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string}, 846 }; 847 848 static void 849 _spdk_rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno) 850 { 851 struct spdk_json_write_ctx *w; 852 struct spdk_jsonrpc_request *request = cb_arg; 853 854 if (lvolerrno != 0) { 855 goto invalid; 856 } 857 858 w = spdk_jsonrpc_begin_result(request); 859 spdk_json_write_bool(w, true); 860 spdk_jsonrpc_end_result(request, w); 861 return; 862 863 invalid: 864 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 865 spdk_strerror(-lvolerrno)); 866 } 867 868 static void 869 spdk_rpc_set_read_only_lvol_bdev(struct spdk_jsonrpc_request *request, 870 const struct spdk_json_val *params) 871 { 872 struct rpc_set_ro_lvol_bdev req = {}; 873 struct spdk_bdev *bdev; 874 struct spdk_lvol *lvol; 875 876 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Setting lvol as read only\n"); 877 878 if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders, 879 SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders), 880 &req)) { 881 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 882 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 883 "spdk_json_decode_object failed"); 884 goto cleanup; 885 } 886 887 if (req.name == NULL) { 888 SPDK_ERRLOG("missing name param\n"); 889 spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter"); 890 goto cleanup; 891 } 892 893 bdev = spdk_bdev_get_by_name(req.name); 894 if (bdev == NULL) { 895 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 896 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 897 goto cleanup; 898 } 899 900 lvol = vbdev_lvol_get_from_bdev(bdev); 901 if (lvol == NULL) { 902 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 903 goto cleanup; 904 } 905 906 vbdev_lvol_set_read_only(lvol, _spdk_rpc_set_ro_lvol_bdev_cb, request); 907 908 cleanup: 909 free_rpc_set_ro_lvol_bdev(&req); 910 } 911 912 SPDK_RPC_REGISTER("set_read_only_lvol_bdev", spdk_rpc_set_read_only_lvol_bdev, SPDK_RPC_RUNTIME) 913 914 struct rpc_destroy_lvol_bdev { 915 char *name; 916 }; 917 918 static void 919 free_rpc_destroy_lvol_bdev(struct rpc_destroy_lvol_bdev *req) 920 { 921 free(req->name); 922 } 923 924 static const struct spdk_json_object_decoder rpc_destroy_lvol_bdev_decoders[] = { 925 {"name", offsetof(struct rpc_destroy_lvol_bdev, name), spdk_json_decode_string}, 926 }; 927 928 static void 929 _spdk_rpc_destroy_lvol_bdev_cb(void *cb_arg, int lvolerrno) 930 { 931 struct spdk_json_write_ctx *w; 932 struct spdk_jsonrpc_request *request = cb_arg; 933 934 if (lvolerrno != 0) { 935 goto invalid; 936 } 937 938 w = spdk_jsonrpc_begin_result(request); 939 spdk_json_write_bool(w, true); 940 spdk_jsonrpc_end_result(request, w); 941 return; 942 943 invalid: 944 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 945 spdk_strerror(-lvolerrno)); 946 } 947 948 static void 949 spdk_rpc_destroy_lvol_bdev(struct spdk_jsonrpc_request *request, 950 const struct spdk_json_val *params) 951 { 952 struct rpc_destroy_lvol_bdev req = {}; 953 struct spdk_bdev *bdev; 954 struct spdk_lvol *lvol; 955 956 if (spdk_json_decode_object(params, rpc_destroy_lvol_bdev_decoders, 957 SPDK_COUNTOF(rpc_destroy_lvol_bdev_decoders), 958 &req)) { 959 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 960 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 961 "spdk_json_decode_object failed"); 962 goto cleanup; 963 } 964 965 bdev = spdk_bdev_get_by_name(req.name); 966 if (bdev == NULL) { 967 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 968 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 969 goto cleanup; 970 } 971 972 lvol = vbdev_lvol_get_from_bdev(bdev); 973 if (lvol == NULL) { 974 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 975 goto cleanup; 976 } 977 978 vbdev_lvol_destroy(lvol, _spdk_rpc_destroy_lvol_bdev_cb, request); 979 980 cleanup: 981 free_rpc_destroy_lvol_bdev(&req); 982 } 983 984 SPDK_RPC_REGISTER("destroy_lvol_bdev", spdk_rpc_destroy_lvol_bdev, SPDK_RPC_RUNTIME) 985 986 struct rpc_get_lvol_stores { 987 char *uuid; 988 char *lvs_name; 989 }; 990 991 static void 992 free_rpc_get_lvol_stores(struct rpc_get_lvol_stores *req) 993 { 994 free(req->uuid); 995 free(req->lvs_name); 996 } 997 998 static const struct spdk_json_object_decoder rpc_get_lvol_stores_decoders[] = { 999 {"uuid", offsetof(struct rpc_get_lvol_stores, uuid), spdk_json_decode_string, true}, 1000 {"lvs_name", offsetof(struct rpc_get_lvol_stores, lvs_name), spdk_json_decode_string, true}, 1001 }; 1002 1003 static void 1004 spdk_rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev) 1005 { 1006 struct spdk_blob_store *bs; 1007 uint64_t cluster_size, block_size; 1008 char uuid[SPDK_UUID_STRING_LEN]; 1009 1010 bs = lvs_bdev->lvs->blobstore; 1011 cluster_size = spdk_bs_get_cluster_size(bs); 1012 /* Block size of lvols is always size of blob store page */ 1013 block_size = spdk_bs_get_page_size(bs); 1014 1015 spdk_json_write_object_begin(w); 1016 1017 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &lvs_bdev->lvs->uuid); 1018 spdk_json_write_named_string(w, "uuid", uuid); 1019 1020 spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name); 1021 1022 spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev)); 1023 1024 spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs)); 1025 1026 spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs)); 1027 1028 spdk_json_write_named_uint64(w, "block_size", block_size); 1029 1030 spdk_json_write_named_uint64(w, "cluster_size", cluster_size); 1031 1032 spdk_json_write_object_end(w); 1033 } 1034 1035 static void 1036 spdk_rpc_get_lvol_stores(struct spdk_jsonrpc_request *request, 1037 const struct spdk_json_val *params) 1038 { 1039 struct rpc_get_lvol_stores req = {}; 1040 struct spdk_json_write_ctx *w; 1041 struct lvol_store_bdev *lvs_bdev = NULL; 1042 struct spdk_lvol_store *lvs = NULL; 1043 int rc; 1044 1045 if (params != NULL) { 1046 if (spdk_json_decode_object(params, rpc_get_lvol_stores_decoders, 1047 SPDK_COUNTOF(rpc_get_lvol_stores_decoders), 1048 &req)) { 1049 SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); 1050 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1051 "spdk_json_decode_object failed"); 1052 goto cleanup; 1053 } 1054 1055 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 1056 if (rc != 0) { 1057 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1058 goto cleanup; 1059 } 1060 1061 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs); 1062 if (lvs_bdev == NULL) { 1063 spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV)); 1064 goto cleanup; 1065 } 1066 } 1067 1068 w = spdk_jsonrpc_begin_result(request); 1069 spdk_json_write_array_begin(w); 1070 1071 if (lvs_bdev != NULL) { 1072 spdk_rpc_dump_lvol_store_info(w, lvs_bdev); 1073 } else { 1074 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL; 1075 lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) { 1076 spdk_rpc_dump_lvol_store_info(w, lvs_bdev); 1077 } 1078 } 1079 spdk_json_write_array_end(w); 1080 1081 spdk_jsonrpc_end_result(request, w); 1082 1083 cleanup: 1084 free_rpc_get_lvol_stores(&req); 1085 } 1086 1087 SPDK_RPC_REGISTER("get_lvol_stores", spdk_rpc_get_lvol_stores, SPDK_RPC_RUNTIME) 1088