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