1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 */ 6 7 #include "spdk/rpc.h" 8 #include "spdk/bdev.h" 9 #include "spdk/util.h" 10 #include "vbdev_lvol.h" 11 #include "spdk/string.h" 12 #include "spdk/log.h" 13 14 SPDK_LOG_REGISTER_COMPONENT(lvol_rpc) 15 16 struct rpc_shallow_copy_status { 17 uint32_t operation_id; 18 /* 19 * 0 means ongoing or successfully completed operation 20 * a negative value is the -errno of an aborted operation 21 */ 22 int result; 23 uint64_t copied_clusters; 24 uint64_t total_clusters; 25 LIST_ENTRY(rpc_shallow_copy_status) link; 26 }; 27 28 static uint32_t g_shallow_copy_count = 0; 29 static LIST_HEAD(, rpc_shallow_copy_status) g_shallow_copy_status_list = LIST_HEAD_INITIALIZER( 30 &g_shallow_copy_status_list); 31 32 struct rpc_bdev_lvol_create_lvstore { 33 char *lvs_name; 34 char *bdev_name; 35 uint32_t cluster_sz; 36 char *clear_method; 37 uint32_t num_md_pages_per_cluster_ratio; 38 uint32_t md_page_size; 39 }; 40 41 static int 42 vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name, 43 struct spdk_lvol_store **lvs) 44 { 45 if ((uuid == NULL && lvs_name == NULL)) { 46 SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n"); 47 return -EINVAL; 48 } else if ((uuid && lvs_name)) { 49 SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid, 50 lvs_name); 51 return -EINVAL; 52 } else if (uuid) { 53 *lvs = vbdev_get_lvol_store_by_uuid(uuid); 54 55 if (*lvs == NULL) { 56 SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid); 57 return -ENODEV; 58 } 59 } else if (lvs_name) { 60 61 *lvs = vbdev_get_lvol_store_by_name(lvs_name); 62 63 if (*lvs == NULL) { 64 SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name); 65 return -ENODEV; 66 } 67 } 68 return 0; 69 } 70 71 static void 72 free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req) 73 { 74 free(req->bdev_name); 75 free(req->lvs_name); 76 free(req->clear_method); 77 } 78 79 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = { 80 {"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string}, 81 {"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true}, 82 {"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string}, 83 {"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true}, 84 {"num_md_pages_per_cluster_ratio", offsetof(struct rpc_bdev_lvol_create_lvstore, num_md_pages_per_cluster_ratio), spdk_json_decode_uint32, true}, 85 {"md_page_size", offsetof(struct rpc_bdev_lvol_create_lvstore, md_page_size), spdk_json_decode_uint32, true}, 86 }; 87 88 static void 89 rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno) 90 { 91 struct spdk_json_write_ctx *w; 92 struct spdk_jsonrpc_request *request = cb_arg; 93 94 if (lvserrno != 0) { 95 goto invalid; 96 } 97 98 w = spdk_jsonrpc_begin_result(request); 99 spdk_json_write_uuid(w, &lvol_store->uuid); 100 spdk_jsonrpc_end_result(request, w); 101 return; 102 103 invalid: 104 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 105 spdk_strerror(-lvserrno)); 106 } 107 108 static void 109 rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request, 110 const struct spdk_json_val *params) 111 { 112 struct rpc_bdev_lvol_create_lvstore req = {}; 113 int rc = 0; 114 enum lvs_clear_method clear_method; 115 116 if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders, 117 SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders), 118 &req)) { 119 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 120 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 121 "spdk_json_decode_object failed"); 122 goto cleanup; 123 } 124 125 if (req.clear_method != NULL) { 126 if (!strcasecmp(req.clear_method, "none")) { 127 clear_method = LVS_CLEAR_WITH_NONE; 128 } else if (!strcasecmp(req.clear_method, "unmap")) { 129 clear_method = LVS_CLEAR_WITH_UNMAP; 130 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 131 clear_method = LVS_CLEAR_WITH_WRITE_ZEROES; 132 } else { 133 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter"); 134 goto cleanup; 135 } 136 } else { 137 clear_method = LVS_CLEAR_WITH_UNMAP; 138 } 139 140 rc = vbdev_lvs_create_ext(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method, 141 req.num_md_pages_per_cluster_ratio, req.md_page_size, 142 rpc_lvol_store_construct_cb, request); 143 if (rc < 0) { 144 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 145 goto cleanup; 146 } 147 free_rpc_bdev_lvol_create_lvstore(&req); 148 149 return; 150 151 cleanup: 152 free_rpc_bdev_lvol_create_lvstore(&req); 153 } 154 SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME) 155 156 struct rpc_bdev_lvol_rename_lvstore { 157 char *old_name; 158 char *new_name; 159 }; 160 161 static void 162 free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req) 163 { 164 free(req->old_name); 165 free(req->new_name); 166 } 167 168 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = { 169 {"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string}, 170 {"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string}, 171 }; 172 173 static void 174 rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno) 175 { 176 struct spdk_jsonrpc_request *request = cb_arg; 177 178 if (lvserrno != 0) { 179 goto invalid; 180 } 181 182 spdk_jsonrpc_send_bool_response(request, true); 183 return; 184 185 invalid: 186 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 187 spdk_strerror(-lvserrno)); 188 } 189 190 static void 191 rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request, 192 const struct spdk_json_val *params) 193 { 194 struct rpc_bdev_lvol_rename_lvstore req = {}; 195 struct spdk_lvol_store *lvs; 196 197 if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders, 198 SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders), 199 &req)) { 200 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 201 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 202 "spdk_json_decode_object failed"); 203 goto cleanup; 204 } 205 206 lvs = vbdev_get_lvol_store_by_name(req.old_name); 207 if (lvs == NULL) { 208 SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n"); 209 spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name); 210 goto cleanup; 211 } 212 213 vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request); 214 215 cleanup: 216 free_rpc_bdev_lvol_rename_lvstore(&req); 217 } 218 SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME) 219 220 struct rpc_bdev_lvol_delete_lvstore { 221 char *uuid; 222 char *lvs_name; 223 }; 224 225 static void 226 free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req) 227 { 228 free(req->uuid); 229 free(req->lvs_name); 230 } 231 232 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = { 233 {"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true}, 234 {"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true}, 235 }; 236 237 static void 238 rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno) 239 { 240 struct spdk_jsonrpc_request *request = cb_arg; 241 242 if (lvserrno != 0) { 243 goto invalid; 244 } 245 246 spdk_jsonrpc_send_bool_response(request, true); 247 return; 248 249 invalid: 250 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 251 spdk_strerror(-lvserrno)); 252 } 253 254 static void 255 rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request, 256 const struct spdk_json_val *params) 257 { 258 struct rpc_bdev_lvol_delete_lvstore req = {}; 259 struct spdk_lvol_store *lvs = NULL; 260 int rc; 261 262 if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders, 263 SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders), 264 &req)) { 265 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 266 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 267 "spdk_json_decode_object failed"); 268 goto cleanup; 269 } 270 271 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 272 if (rc != 0) { 273 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 274 goto cleanup; 275 } 276 277 vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request); 278 279 cleanup: 280 free_rpc_bdev_lvol_delete_lvstore(&req); 281 } 282 SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME) 283 284 struct rpc_bdev_lvol_create { 285 char *uuid; 286 char *lvs_name; 287 char *lvol_name; 288 uint64_t size_in_mib; 289 bool thin_provision; 290 char *clear_method; 291 }; 292 293 static void 294 free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req) 295 { 296 free(req->uuid); 297 free(req->lvs_name); 298 free(req->lvol_name); 299 free(req->clear_method); 300 } 301 302 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = { 303 {"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true}, 304 {"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true}, 305 {"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string}, 306 {"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64}, 307 {"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true}, 308 {"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true}, 309 }; 310 311 static void 312 rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 313 { 314 struct spdk_json_write_ctx *w; 315 struct spdk_jsonrpc_request *request = cb_arg; 316 317 if (lvolerrno != 0) { 318 goto invalid; 319 } 320 321 w = spdk_jsonrpc_begin_result(request); 322 spdk_json_write_string(w, lvol->unique_id); 323 spdk_jsonrpc_end_result(request, w); 324 return; 325 326 invalid: 327 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 328 spdk_strerror(-lvolerrno)); 329 } 330 331 static void 332 rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request, 333 const struct spdk_json_val *params) 334 { 335 struct rpc_bdev_lvol_create req = {}; 336 enum lvol_clear_method clear_method; 337 int rc = 0; 338 struct spdk_lvol_store *lvs = NULL; 339 340 SPDK_INFOLOG(lvol_rpc, "Creating blob\n"); 341 342 if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders, 343 SPDK_COUNTOF(rpc_bdev_lvol_create_decoders), 344 &req)) { 345 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 346 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 347 "spdk_json_decode_object failed"); 348 goto cleanup; 349 } 350 351 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 352 if (rc != 0) { 353 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 354 goto cleanup; 355 } 356 357 if (req.clear_method != NULL) { 358 if (!strcasecmp(req.clear_method, "none")) { 359 clear_method = LVOL_CLEAR_WITH_NONE; 360 } else if (!strcasecmp(req.clear_method, "unmap")) { 361 clear_method = LVOL_CLEAR_WITH_UNMAP; 362 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 363 clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES; 364 } else { 365 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option"); 366 goto cleanup; 367 } 368 } else { 369 clear_method = LVOL_CLEAR_WITH_DEFAULT; 370 } 371 372 rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024, 373 req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request); 374 if (rc < 0) { 375 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 376 goto cleanup; 377 } 378 379 cleanup: 380 free_rpc_bdev_lvol_create(&req); 381 } 382 383 SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME) 384 385 struct rpc_bdev_lvol_snapshot { 386 char *lvol_name; 387 char *snapshot_name; 388 }; 389 390 static void 391 free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req) 392 { 393 free(req->lvol_name); 394 free(req->snapshot_name); 395 } 396 397 static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = { 398 {"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string}, 399 {"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string}, 400 }; 401 402 static void 403 rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 404 { 405 struct spdk_json_write_ctx *w; 406 struct spdk_jsonrpc_request *request = cb_arg; 407 408 if (lvolerrno != 0) { 409 goto invalid; 410 } 411 412 w = spdk_jsonrpc_begin_result(request); 413 spdk_json_write_string(w, lvol->unique_id); 414 spdk_jsonrpc_end_result(request, w); 415 return; 416 417 invalid: 418 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 419 spdk_strerror(-lvolerrno)); 420 } 421 422 static void 423 rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request, 424 const struct spdk_json_val *params) 425 { 426 struct rpc_bdev_lvol_snapshot req = {}; 427 struct spdk_bdev *bdev; 428 struct spdk_lvol *lvol; 429 430 SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n"); 431 432 if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders, 433 SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders), 434 &req)) { 435 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 436 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 437 "spdk_json_decode_object failed"); 438 goto cleanup; 439 } 440 441 bdev = spdk_bdev_get_by_name(req.lvol_name); 442 if (bdev == NULL) { 443 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name); 444 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 445 goto cleanup; 446 } 447 448 lvol = vbdev_lvol_get_from_bdev(bdev); 449 if (lvol == NULL) { 450 SPDK_ERRLOG("lvol does not exist\n"); 451 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 452 goto cleanup; 453 } 454 455 vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request); 456 457 cleanup: 458 free_rpc_bdev_lvol_snapshot(&req); 459 } 460 461 SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME) 462 463 struct rpc_bdev_lvol_clone { 464 char *snapshot_name; 465 char *clone_name; 466 }; 467 468 static void 469 free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req) 470 { 471 free(req->snapshot_name); 472 free(req->clone_name); 473 } 474 475 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = { 476 {"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string}, 477 {"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true}, 478 }; 479 480 static void 481 rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 482 { 483 struct spdk_json_write_ctx *w; 484 struct spdk_jsonrpc_request *request = cb_arg; 485 486 if (lvolerrno != 0) { 487 goto invalid; 488 } 489 490 w = spdk_jsonrpc_begin_result(request); 491 spdk_json_write_string(w, lvol->unique_id); 492 spdk_jsonrpc_end_result(request, w); 493 return; 494 495 invalid: 496 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 497 spdk_strerror(-lvolerrno)); 498 } 499 500 static void 501 rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request, 502 const struct spdk_json_val *params) 503 { 504 struct rpc_bdev_lvol_clone req = {}; 505 struct spdk_bdev *bdev; 506 struct spdk_lvol *lvol; 507 508 SPDK_INFOLOG(lvol_rpc, "Cloning blob\n"); 509 510 if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders, 511 SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders), 512 &req)) { 513 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 514 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 515 "spdk_json_decode_object failed"); 516 goto cleanup; 517 } 518 519 bdev = spdk_bdev_get_by_name(req.snapshot_name); 520 if (bdev == NULL) { 521 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name); 522 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 523 goto cleanup; 524 } 525 526 lvol = vbdev_lvol_get_from_bdev(bdev); 527 if (lvol == NULL) { 528 SPDK_ERRLOG("lvol does not exist\n"); 529 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 530 goto cleanup; 531 } 532 533 vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request); 534 535 cleanup: 536 free_rpc_bdev_lvol_clone(&req); 537 } 538 539 SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME) 540 541 struct rpc_bdev_lvol_clone_bdev { 542 /* name or UUID. Whichever is used, the UUID will be stored in the lvol's metadata. */ 543 char *bdev_name; 544 char *lvs_name; 545 char *clone_name; 546 }; 547 548 static void 549 free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req) 550 { 551 free(req->bdev_name); 552 free(req->lvs_name); 553 free(req->clone_name); 554 } 555 556 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_bdev_decoders[] = { 557 { 558 "bdev", offsetof(struct rpc_bdev_lvol_clone_bdev, bdev_name), 559 spdk_json_decode_string, false 560 }, 561 { 562 "lvs_name", offsetof(struct rpc_bdev_lvol_clone_bdev, lvs_name), 563 spdk_json_decode_string, false 564 }, 565 { 566 "clone_name", offsetof(struct rpc_bdev_lvol_clone_bdev, clone_name), 567 spdk_json_decode_string, false 568 }, 569 }; 570 571 static void 572 rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 573 { 574 struct rpc_bdev_lvol_clone_bdev req = {}; 575 struct spdk_bdev *bdev; 576 struct spdk_lvol_store *lvs = NULL; 577 struct spdk_lvol *lvol; 578 int rc; 579 580 SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n"); 581 582 if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_bdev_decoders, 583 SPDK_COUNTOF(rpc_bdev_lvol_clone_bdev_decoders), &req)) { 584 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 585 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 586 "spdk_json_decode_object failed"); 587 goto cleanup; 588 } 589 590 rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs); 591 if (rc != 0) { 592 SPDK_INFOLOG(lvol_rpc, "lvs_name '%s' not found\n", req.lvs_name); 593 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 594 "lvs does not exist"); 595 goto cleanup; 596 } 597 598 bdev = spdk_bdev_get_by_name(req.bdev_name); 599 if (bdev == NULL) { 600 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.bdev_name); 601 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 602 "bdev does not exist"); 603 goto cleanup; 604 } 605 606 lvol = vbdev_lvol_get_from_bdev(bdev); 607 if (lvol != NULL && lvol->lvol_store == lvs) { 608 SPDK_INFOLOG(lvol_rpc, "bdev '%s' is an lvol in lvstore '%s\n", req.bdev_name, 609 req.lvs_name); 610 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 611 "bdev is an lvol in same lvs as clone; " 612 "use bdev_lvol_clone instead"); 613 goto cleanup; 614 } 615 616 vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name, 617 rpc_bdev_lvol_clone_cb, request); 618 cleanup: 619 free_rpc_bdev_lvol_clone_bdev(&req); 620 } 621 622 SPDK_RPC_REGISTER("bdev_lvol_clone_bdev", rpc_bdev_lvol_clone_bdev, SPDK_RPC_RUNTIME) 623 624 struct rpc_bdev_lvol_rename { 625 char *old_name; 626 char *new_name; 627 }; 628 629 static void 630 free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req) 631 { 632 free(req->old_name); 633 free(req->new_name); 634 } 635 636 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = { 637 {"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string}, 638 {"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string}, 639 }; 640 641 static void 642 rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno) 643 { 644 struct spdk_jsonrpc_request *request = cb_arg; 645 646 if (lvolerrno != 0) { 647 goto invalid; 648 } 649 650 spdk_jsonrpc_send_bool_response(request, true); 651 return; 652 653 invalid: 654 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 655 spdk_strerror(-lvolerrno)); 656 } 657 658 static void 659 rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request, 660 const struct spdk_json_val *params) 661 { 662 struct rpc_bdev_lvol_rename req = {}; 663 struct spdk_bdev *bdev; 664 struct spdk_lvol *lvol; 665 666 SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n"); 667 668 if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders, 669 SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders), 670 &req)) { 671 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 672 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 673 "spdk_json_decode_object failed"); 674 goto cleanup; 675 } 676 677 bdev = spdk_bdev_get_by_name(req.old_name); 678 if (bdev == NULL) { 679 SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name); 680 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 681 goto cleanup; 682 } 683 684 lvol = vbdev_lvol_get_from_bdev(bdev); 685 if (lvol == NULL) { 686 SPDK_ERRLOG("lvol does not exist\n"); 687 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 688 goto cleanup; 689 } 690 691 vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request); 692 693 cleanup: 694 free_rpc_bdev_lvol_rename(&req); 695 } 696 697 SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME) 698 699 struct rpc_bdev_lvol_inflate { 700 char *name; 701 }; 702 703 static void 704 free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req) 705 { 706 free(req->name); 707 } 708 709 static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = { 710 {"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string}, 711 }; 712 713 static void 714 rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno) 715 { 716 struct spdk_jsonrpc_request *request = cb_arg; 717 718 if (lvolerrno != 0) { 719 goto invalid; 720 } 721 722 spdk_jsonrpc_send_bool_response(request, true); 723 return; 724 725 invalid: 726 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 727 spdk_strerror(-lvolerrno)); 728 } 729 730 static void 731 rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request, 732 const struct spdk_json_val *params) 733 { 734 struct rpc_bdev_lvol_inflate req = {}; 735 struct spdk_bdev *bdev; 736 struct spdk_lvol *lvol; 737 738 SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n"); 739 740 if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders, 741 SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders), 742 &req)) { 743 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 744 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 745 "spdk_json_decode_object failed"); 746 goto cleanup; 747 } 748 749 bdev = spdk_bdev_get_by_name(req.name); 750 if (bdev == NULL) { 751 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 752 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 753 goto cleanup; 754 } 755 756 lvol = vbdev_lvol_get_from_bdev(bdev); 757 if (lvol == NULL) { 758 SPDK_ERRLOG("lvol does not exist\n"); 759 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 760 goto cleanup; 761 } 762 763 spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request); 764 765 cleanup: 766 free_rpc_bdev_lvol_inflate(&req); 767 } 768 769 SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME) 770 771 static void 772 rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request, 773 const struct spdk_json_val *params) 774 { 775 struct rpc_bdev_lvol_inflate req = {}; 776 struct spdk_bdev *bdev; 777 struct spdk_lvol *lvol; 778 779 SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n"); 780 781 if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders, 782 SPDK_COUNTOF(rpc_bdev_lvol_inflate_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("bdev '%s' does not exist\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_ERRLOG("lvol does not exist\n"); 800 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 801 goto cleanup; 802 } 803 804 spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request); 805 806 cleanup: 807 free_rpc_bdev_lvol_inflate(&req); 808 } 809 810 SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME) 811 812 struct rpc_bdev_lvol_resize { 813 char *name; 814 uint64_t size_in_mib; 815 }; 816 817 static void 818 free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req) 819 { 820 free(req->name); 821 } 822 823 static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = { 824 {"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string}, 825 {"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64}, 826 }; 827 828 static void 829 rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno) 830 { 831 struct spdk_jsonrpc_request *request = cb_arg; 832 833 if (lvolerrno != 0) { 834 goto invalid; 835 } 836 837 spdk_jsonrpc_send_bool_response(request, true); 838 return; 839 840 invalid: 841 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 842 spdk_strerror(-lvolerrno)); 843 } 844 845 static void 846 rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request, 847 const struct spdk_json_val *params) 848 { 849 struct rpc_bdev_lvol_resize req = {}; 850 struct spdk_bdev *bdev; 851 struct spdk_lvol *lvol; 852 853 SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n"); 854 855 if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders, 856 SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders), 857 &req)) { 858 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 859 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 860 "spdk_json_decode_object failed"); 861 goto cleanup; 862 } 863 864 bdev = spdk_bdev_get_by_name(req.name); 865 if (bdev == NULL) { 866 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 867 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 868 goto cleanup; 869 } 870 871 lvol = vbdev_lvol_get_from_bdev(bdev); 872 if (lvol == NULL) { 873 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 874 goto cleanup; 875 } 876 877 878 vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request); 879 880 cleanup: 881 free_rpc_bdev_lvol_resize(&req); 882 } 883 884 SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME) 885 886 struct rpc_set_ro_lvol_bdev { 887 char *name; 888 }; 889 890 static void 891 free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req) 892 { 893 free(req->name); 894 } 895 896 static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = { 897 {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string}, 898 }; 899 900 static void 901 rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno) 902 { 903 struct spdk_jsonrpc_request *request = cb_arg; 904 905 if (lvolerrno != 0) { 906 goto invalid; 907 } 908 909 spdk_jsonrpc_send_bool_response(request, true); 910 return; 911 912 invalid: 913 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 914 spdk_strerror(-lvolerrno)); 915 } 916 917 static void 918 rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request, 919 const struct spdk_json_val *params) 920 { 921 struct rpc_set_ro_lvol_bdev req = {}; 922 struct spdk_bdev *bdev; 923 struct spdk_lvol *lvol; 924 925 SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n"); 926 927 if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders, 928 SPDK_COUNTOF(rpc_set_ro_lvol_bdev_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 if (req.name == NULL) { 937 SPDK_ERRLOG("missing name param\n"); 938 spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter"); 939 goto cleanup; 940 } 941 942 bdev = spdk_bdev_get_by_name(req.name); 943 if (bdev == NULL) { 944 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 945 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 946 goto cleanup; 947 } 948 949 lvol = vbdev_lvol_get_from_bdev(bdev); 950 if (lvol == NULL) { 951 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 952 goto cleanup; 953 } 954 955 vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request); 956 957 cleanup: 958 free_rpc_set_ro_lvol_bdev(&req); 959 } 960 961 SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME) 962 963 struct rpc_bdev_lvol_delete { 964 char *name; 965 }; 966 967 static void 968 free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req) 969 { 970 free(req->name); 971 } 972 973 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = { 974 {"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string}, 975 }; 976 977 static void 978 rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno) 979 { 980 struct spdk_jsonrpc_request *request = cb_arg; 981 982 if (lvolerrno != 0) { 983 goto invalid; 984 } 985 986 spdk_jsonrpc_send_bool_response(request, true); 987 return; 988 989 invalid: 990 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 991 spdk_strerror(-lvolerrno)); 992 } 993 994 static void 995 rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request, 996 const struct spdk_json_val *params) 997 { 998 struct rpc_bdev_lvol_delete req = {}; 999 struct spdk_bdev *bdev; 1000 struct spdk_lvol *lvol; 1001 struct spdk_uuid uuid; 1002 char *lvs_name, *lvol_name; 1003 1004 if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders, 1005 SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders), 1006 &req)) { 1007 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1008 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1009 "spdk_json_decode_object failed"); 1010 goto cleanup; 1011 } 1012 1013 /* lvol is not degraded, get lvol via bdev name or alias */ 1014 bdev = spdk_bdev_get_by_name(req.name); 1015 if (bdev != NULL) { 1016 lvol = vbdev_lvol_get_from_bdev(bdev); 1017 if (lvol != NULL) { 1018 goto done; 1019 } 1020 } 1021 1022 /* lvol is degraded, get lvol via UUID */ 1023 if (spdk_uuid_parse(&uuid, req.name) == 0) { 1024 lvol = spdk_lvol_get_by_uuid(&uuid); 1025 if (lvol != NULL) { 1026 goto done; 1027 } 1028 } 1029 1030 /* lvol is degraded, get lvol via lvs_name/lvol_name */ 1031 lvol_name = strchr(req.name, '/'); 1032 if (lvol_name != NULL) { 1033 *lvol_name = '\0'; 1034 lvol_name++; 1035 lvs_name = req.name; 1036 lvol = spdk_lvol_get_by_names(lvs_name, lvol_name); 1037 if (lvol != NULL) { 1038 goto done; 1039 } 1040 } 1041 1042 /* Could not find lvol, degraded or not. */ 1043 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1044 goto cleanup; 1045 1046 done: 1047 vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request); 1048 1049 cleanup: 1050 free_rpc_bdev_lvol_delete(&req); 1051 } 1052 1053 SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME) 1054 1055 struct rpc_bdev_lvol_get_lvstores { 1056 char *uuid; 1057 char *lvs_name; 1058 }; 1059 1060 static void 1061 free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req) 1062 { 1063 free(req->uuid); 1064 free(req->lvs_name); 1065 } 1066 1067 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = { 1068 {"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true}, 1069 {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true}, 1070 }; 1071 1072 static void 1073 rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev) 1074 { 1075 struct spdk_blob_store *bs; 1076 uint64_t cluster_size; 1077 1078 bs = lvs_bdev->lvs->blobstore; 1079 cluster_size = spdk_bs_get_cluster_size(bs); 1080 1081 spdk_json_write_object_begin(w); 1082 1083 spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid); 1084 spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name); 1085 spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev)); 1086 spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs)); 1087 spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs)); 1088 spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs)); 1089 spdk_json_write_named_uint64(w, "cluster_size", cluster_size); 1090 1091 spdk_json_write_object_end(w); 1092 } 1093 1094 static void 1095 rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request, 1096 const struct spdk_json_val *params) 1097 { 1098 struct rpc_bdev_lvol_get_lvstores req = {}; 1099 struct spdk_json_write_ctx *w; 1100 struct lvol_store_bdev *lvs_bdev = NULL; 1101 struct spdk_lvol_store *lvs = NULL; 1102 int rc; 1103 1104 if (params != NULL) { 1105 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders, 1106 SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders), 1107 &req)) { 1108 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1109 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1110 "spdk_json_decode_object failed"); 1111 goto cleanup; 1112 } 1113 1114 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 1115 if (rc != 0) { 1116 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1117 goto cleanup; 1118 } 1119 1120 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs); 1121 if (lvs_bdev == NULL) { 1122 spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV)); 1123 goto cleanup; 1124 } 1125 } 1126 1127 w = spdk_jsonrpc_begin_result(request); 1128 spdk_json_write_array_begin(w); 1129 1130 if (lvs_bdev != NULL) { 1131 rpc_dump_lvol_store_info(w, lvs_bdev); 1132 } else { 1133 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL; 1134 lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) { 1135 rpc_dump_lvol_store_info(w, lvs_bdev); 1136 } 1137 } 1138 spdk_json_write_array_end(w); 1139 1140 spdk_jsonrpc_end_result(request, w); 1141 1142 cleanup: 1143 free_rpc_bdev_lvol_get_lvstores(&req); 1144 } 1145 1146 SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME) 1147 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores) 1148 1149 struct rpc_bdev_lvol_get_lvols { 1150 char *lvs_uuid; 1151 char *lvs_name; 1152 }; 1153 1154 static void 1155 free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req) 1156 { 1157 free(req->lvs_uuid); 1158 free(req->lvs_name); 1159 } 1160 1161 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = { 1162 {"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true}, 1163 {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true}, 1164 }; 1165 1166 static void 1167 rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol) 1168 { 1169 struct spdk_lvol_store *lvs = lvol->lvol_store; 1170 1171 spdk_json_write_object_begin(w); 1172 1173 spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name); 1174 spdk_json_write_named_string(w, "uuid", lvol->uuid_str); 1175 spdk_json_write_named_string(w, "name", lvol->name); 1176 spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob)); 1177 spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob)); 1178 spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob)); 1179 spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob)); 1180 spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob)); 1181 spdk_json_write_named_uint64(w, "num_allocated_clusters", 1182 spdk_blob_get_num_allocated_clusters(lvol->blob)); 1183 1184 spdk_json_write_named_object_begin(w, "lvs"); 1185 spdk_json_write_named_string(w, "name", lvs->name); 1186 spdk_json_write_named_uuid(w, "uuid", &lvs->uuid); 1187 spdk_json_write_object_end(w); 1188 1189 spdk_json_write_object_end(w); 1190 } 1191 1192 static void 1193 rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev) 1194 { 1195 struct spdk_lvol_store *lvs = lvs_bdev->lvs; 1196 struct spdk_lvol *lvol; 1197 1198 TAILQ_FOREACH(lvol, &lvs->lvols, link) { 1199 if (lvol->ref_count == 0) { 1200 continue; 1201 } 1202 rpc_dump_lvol(w, lvol); 1203 } 1204 } 1205 1206 static void 1207 rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 1208 { 1209 struct rpc_bdev_lvol_get_lvols req = {}; 1210 struct spdk_json_write_ctx *w; 1211 struct lvol_store_bdev *lvs_bdev = NULL; 1212 struct spdk_lvol_store *lvs = NULL; 1213 int rc; 1214 1215 if (params != NULL) { 1216 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders, 1217 SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders), 1218 &req)) { 1219 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1220 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1221 "spdk_json_decode_object failed"); 1222 goto cleanup; 1223 } 1224 1225 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs); 1226 if (rc != 0) { 1227 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1228 goto cleanup; 1229 } 1230 1231 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs); 1232 if (lvs_bdev == NULL) { 1233 spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV)); 1234 goto cleanup; 1235 } 1236 } 1237 1238 w = spdk_jsonrpc_begin_result(request); 1239 spdk_json_write_array_begin(w); 1240 1241 if (lvs_bdev != NULL) { 1242 rpc_dump_lvols(w, lvs_bdev); 1243 } else { 1244 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL; 1245 lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) { 1246 rpc_dump_lvols(w, lvs_bdev); 1247 } 1248 } 1249 spdk_json_write_array_end(w); 1250 1251 spdk_jsonrpc_end_result(request, w); 1252 1253 cleanup: 1254 free_rpc_bdev_lvol_get_lvols(&req); 1255 } 1256 1257 SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME) 1258 1259 struct rpc_bdev_lvol_grow_lvstore { 1260 char *uuid; 1261 char *lvs_name; 1262 }; 1263 1264 static void 1265 free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req) 1266 { 1267 free(req->uuid); 1268 free(req->lvs_name); 1269 } 1270 1271 static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = { 1272 {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true}, 1273 {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true}, 1274 }; 1275 1276 static void 1277 rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno) 1278 { 1279 struct spdk_jsonrpc_request *request = cb_arg; 1280 1281 if (lvserrno != 0) { 1282 goto invalid; 1283 } 1284 1285 spdk_jsonrpc_send_bool_response(request, true); 1286 return; 1287 1288 invalid: 1289 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1290 spdk_strerror(-lvserrno)); 1291 } 1292 1293 static void 1294 rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request, 1295 const struct spdk_json_val *params) 1296 { 1297 struct rpc_bdev_lvol_grow_lvstore req = {}; 1298 struct spdk_lvol_store *lvs = NULL; 1299 int rc; 1300 1301 if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders, 1302 SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders), 1303 &req)) { 1304 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1305 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1306 "spdk_json_decode_object failed"); 1307 goto cleanup; 1308 } 1309 1310 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 1311 if (rc != 0) { 1312 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1313 goto cleanup; 1314 } 1315 spdk_bdev_update_bs_blockcnt(lvs->bs_dev); 1316 spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request); 1317 1318 cleanup: 1319 free_rpc_bdev_lvol_grow_lvstore(&req); 1320 } 1321 SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME) 1322 1323 struct rpc_bdev_lvol_shallow_copy { 1324 char *src_lvol_name; 1325 char *dst_bdev_name; 1326 }; 1327 1328 struct rpc_bdev_lvol_shallow_copy_ctx { 1329 struct spdk_jsonrpc_request *request; 1330 struct rpc_shallow_copy_status *status; 1331 }; 1332 1333 static void 1334 free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req) 1335 { 1336 free(req->src_lvol_name); 1337 free(req->dst_bdev_name); 1338 } 1339 1340 static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = { 1341 {"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string}, 1342 {"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string}, 1343 }; 1344 1345 static void 1346 rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno) 1347 { 1348 struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg; 1349 1350 ctx->status->result = lvolerrno; 1351 1352 free(ctx); 1353 } 1354 1355 static void 1356 rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg) 1357 { 1358 struct rpc_shallow_copy_status *status = cb_arg; 1359 1360 status->copied_clusters = copied_clusters; 1361 } 1362 1363 static void 1364 rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request, 1365 const struct spdk_json_val *params) 1366 { 1367 struct rpc_bdev_lvol_shallow_copy req = {}; 1368 struct rpc_bdev_lvol_shallow_copy_ctx *ctx; 1369 struct spdk_lvol *src_lvol; 1370 struct spdk_bdev *src_lvol_bdev; 1371 struct rpc_shallow_copy_status *status; 1372 struct spdk_json_write_ctx *w; 1373 int rc; 1374 1375 SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n"); 1376 1377 if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders, 1378 SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders), 1379 &req)) { 1380 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1381 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1382 "spdk_json_decode_object failed"); 1383 goto cleanup; 1384 } 1385 1386 src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name); 1387 if (src_lvol_bdev == NULL) { 1388 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name); 1389 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1390 goto cleanup; 1391 } 1392 1393 src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev); 1394 if (src_lvol == NULL) { 1395 SPDK_ERRLOG("lvol does not exist\n"); 1396 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1397 goto cleanup; 1398 } 1399 1400 status = calloc(1, sizeof(*status)); 1401 if (status == NULL) { 1402 SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name); 1403 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1404 goto cleanup; 1405 } 1406 1407 status->operation_id = ++g_shallow_copy_count; 1408 status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob); 1409 1410 ctx = calloc(1, sizeof(*ctx)); 1411 if (ctx == NULL) { 1412 SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name); 1413 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1414 free(status); 1415 goto cleanup; 1416 } 1417 ctx->request = request; 1418 ctx->status = status; 1419 1420 LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link); 1421 rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name, 1422 rpc_bdev_lvol_shallow_copy_status_cb, status, 1423 rpc_bdev_lvol_shallow_copy_cb, ctx); 1424 1425 if (rc < 0) { 1426 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1427 spdk_strerror(-rc)); 1428 LIST_REMOVE(status, link); 1429 free(ctx); 1430 free(status); 1431 } else { 1432 w = spdk_jsonrpc_begin_result(request); 1433 1434 spdk_json_write_object_begin(w); 1435 spdk_json_write_named_uint32(w, "operation_id", status->operation_id); 1436 spdk_json_write_object_end(w); 1437 1438 spdk_jsonrpc_end_result(request, w); 1439 } 1440 1441 cleanup: 1442 free_rpc_bdev_lvol_shallow_copy(&req); 1443 } 1444 1445 SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy, 1446 SPDK_RPC_RUNTIME) 1447 1448 struct rpc_bdev_lvol_shallow_copy_status { 1449 char *src_lvol_name; 1450 uint32_t operation_id; 1451 }; 1452 1453 static void 1454 free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req) 1455 { 1456 free(req->src_lvol_name); 1457 } 1458 1459 static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = { 1460 {"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32}, 1461 }; 1462 1463 static void 1464 rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request, 1465 const struct spdk_json_val *params) 1466 { 1467 struct rpc_bdev_lvol_shallow_copy_status req = {}; 1468 struct rpc_shallow_copy_status *status; 1469 struct spdk_json_write_ctx *w; 1470 uint64_t copied_clusters, total_clusters; 1471 int result; 1472 1473 SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n"); 1474 1475 if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders, 1476 SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders), 1477 &req)) { 1478 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1479 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1480 "spdk_json_decode_object failed"); 1481 goto cleanup; 1482 } 1483 1484 LIST_FOREACH(status, &g_shallow_copy_status_list, link) { 1485 if (status->operation_id == req.operation_id) { 1486 break; 1487 } 1488 } 1489 1490 if (!status) { 1491 SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id); 1492 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1493 goto cleanup; 1494 } 1495 1496 copied_clusters = status->copied_clusters; 1497 total_clusters = status->total_clusters; 1498 result = status->result; 1499 1500 w = spdk_jsonrpc_begin_result(request); 1501 1502 spdk_json_write_object_begin(w); 1503 1504 spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters); 1505 spdk_json_write_named_uint64(w, "total_clusters", total_clusters); 1506 if (copied_clusters < total_clusters && result == 0) { 1507 spdk_json_write_named_string(w, "state", "in progress"); 1508 } else if (copied_clusters == total_clusters && result == 0) { 1509 spdk_json_write_named_string(w, "state", "complete"); 1510 LIST_REMOVE(status, link); 1511 free(status); 1512 } else { 1513 spdk_json_write_named_string(w, "state", "error"); 1514 spdk_json_write_named_string(w, "error", spdk_strerror(-result)); 1515 LIST_REMOVE(status, link); 1516 free(status); 1517 } 1518 1519 spdk_json_write_object_end(w); 1520 1521 spdk_jsonrpc_end_result(request, w); 1522 1523 cleanup: 1524 free_rpc_bdev_lvol_shallow_copy_status(&req); 1525 } 1526 1527 SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy, 1528 SPDK_RPC_RUNTIME) 1529 1530 struct rpc_bdev_lvol_set_parent { 1531 char *lvol_name; 1532 char *parent_name; 1533 }; 1534 1535 static void 1536 free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req) 1537 { 1538 free(req->lvol_name); 1539 free(req->parent_name); 1540 } 1541 1542 static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = { 1543 {"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string}, 1544 {"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string}, 1545 }; 1546 1547 static void 1548 rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno) 1549 { 1550 struct spdk_jsonrpc_request *request = cb_arg; 1551 1552 if (lvolerrno != 0) { 1553 goto invalid; 1554 } 1555 1556 spdk_jsonrpc_send_bool_response(request, true); 1557 return; 1558 1559 invalid: 1560 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1561 spdk_strerror(-lvolerrno)); 1562 } 1563 1564 static void 1565 rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request, 1566 const struct spdk_json_val *params) 1567 { 1568 struct rpc_bdev_lvol_set_parent req = {}; 1569 struct spdk_lvol *lvol, *snapshot; 1570 struct spdk_bdev *lvol_bdev, *snapshot_bdev; 1571 1572 SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n"); 1573 1574 if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders, 1575 SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders), 1576 &req)) { 1577 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1578 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1579 "spdk_json_decode_object failed"); 1580 goto cleanup; 1581 } 1582 1583 lvol_bdev = spdk_bdev_get_by_name(req.lvol_name); 1584 if (lvol_bdev == NULL) { 1585 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name); 1586 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1587 goto cleanup; 1588 } 1589 1590 lvol = vbdev_lvol_get_from_bdev(lvol_bdev); 1591 if (lvol == NULL) { 1592 SPDK_ERRLOG("lvol does not exist\n"); 1593 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1594 goto cleanup; 1595 } 1596 1597 snapshot_bdev = spdk_bdev_get_by_name(req.parent_name); 1598 if (snapshot_bdev == NULL) { 1599 SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name); 1600 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1601 goto cleanup; 1602 } 1603 1604 snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev); 1605 if (snapshot == NULL) { 1606 SPDK_ERRLOG("snapshot does not exist\n"); 1607 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1608 goto cleanup; 1609 } 1610 1611 spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request); 1612 1613 cleanup: 1614 free_rpc_bdev_lvol_set_parent(&req); 1615 } 1616 1617 SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME) 1618 1619 static void 1620 rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request, 1621 const struct spdk_json_val *params) 1622 { 1623 struct rpc_bdev_lvol_set_parent req = {}; 1624 struct spdk_lvol *lvol; 1625 struct spdk_bdev *lvol_bdev; 1626 1627 SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n"); 1628 1629 if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders, 1630 SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders), 1631 &req)) { 1632 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1633 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1634 "spdk_json_decode_object failed"); 1635 goto cleanup; 1636 } 1637 1638 lvol_bdev = spdk_bdev_get_by_name(req.lvol_name); 1639 if (lvol_bdev == NULL) { 1640 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name); 1641 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1642 goto cleanup; 1643 } 1644 1645 lvol = vbdev_lvol_get_from_bdev(lvol_bdev); 1646 if (lvol == NULL) { 1647 SPDK_ERRLOG("lvol does not exist\n"); 1648 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1649 goto cleanup; 1650 } 1651 1652 vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request); 1653 1654 cleanup: 1655 free_rpc_bdev_lvol_set_parent(&req); 1656 } 1657 1658 SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev, 1659 SPDK_RPC_RUNTIME) 1660