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