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 spdk_json_write_named_uint64(w, "num_allocated_clusters", 1179 spdk_blob_get_num_allocated_clusters(lvol->blob)); 1180 1181 spdk_json_write_named_object_begin(w, "lvs"); 1182 spdk_json_write_named_string(w, "name", lvs->name); 1183 spdk_json_write_named_uuid(w, "uuid", &lvs->uuid); 1184 spdk_json_write_object_end(w); 1185 1186 spdk_json_write_object_end(w); 1187 } 1188 1189 static void 1190 rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev) 1191 { 1192 struct spdk_lvol_store *lvs = lvs_bdev->lvs; 1193 struct spdk_lvol *lvol; 1194 1195 TAILQ_FOREACH(lvol, &lvs->lvols, link) { 1196 if (lvol->ref_count == 0) { 1197 continue; 1198 } 1199 rpc_dump_lvol(w, lvol); 1200 } 1201 } 1202 1203 static void 1204 rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 1205 { 1206 struct rpc_bdev_lvol_get_lvols req = {}; 1207 struct spdk_json_write_ctx *w; 1208 struct lvol_store_bdev *lvs_bdev = NULL; 1209 struct spdk_lvol_store *lvs = NULL; 1210 int rc; 1211 1212 if (params != NULL) { 1213 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders, 1214 SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders), 1215 &req)) { 1216 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1217 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1218 "spdk_json_decode_object failed"); 1219 goto cleanup; 1220 } 1221 1222 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs); 1223 if (rc != 0) { 1224 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1225 goto cleanup; 1226 } 1227 1228 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs); 1229 if (lvs_bdev == NULL) { 1230 spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV)); 1231 goto cleanup; 1232 } 1233 } 1234 1235 w = spdk_jsonrpc_begin_result(request); 1236 spdk_json_write_array_begin(w); 1237 1238 if (lvs_bdev != NULL) { 1239 rpc_dump_lvols(w, lvs_bdev); 1240 } else { 1241 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL; 1242 lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) { 1243 rpc_dump_lvols(w, lvs_bdev); 1244 } 1245 } 1246 spdk_json_write_array_end(w); 1247 1248 spdk_jsonrpc_end_result(request, w); 1249 1250 cleanup: 1251 free_rpc_bdev_lvol_get_lvols(&req); 1252 } 1253 1254 SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME) 1255 1256 struct rpc_bdev_lvol_grow_lvstore { 1257 char *uuid; 1258 char *lvs_name; 1259 }; 1260 1261 static void 1262 free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req) 1263 { 1264 free(req->uuid); 1265 free(req->lvs_name); 1266 } 1267 1268 static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = { 1269 {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true}, 1270 {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true}, 1271 }; 1272 1273 static void 1274 rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno) 1275 { 1276 struct spdk_jsonrpc_request *request = cb_arg; 1277 1278 if (lvserrno != 0) { 1279 goto invalid; 1280 } 1281 1282 spdk_jsonrpc_send_bool_response(request, true); 1283 return; 1284 1285 invalid: 1286 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1287 spdk_strerror(-lvserrno)); 1288 } 1289 1290 static void 1291 rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request, 1292 const struct spdk_json_val *params) 1293 { 1294 struct rpc_bdev_lvol_grow_lvstore req = {}; 1295 struct spdk_lvol_store *lvs = NULL; 1296 int rc; 1297 1298 if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders, 1299 SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders), 1300 &req)) { 1301 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1302 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1303 "spdk_json_decode_object failed"); 1304 goto cleanup; 1305 } 1306 1307 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 1308 if (rc != 0) { 1309 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1310 goto cleanup; 1311 } 1312 spdk_bdev_update_bs_blockcnt(lvs->bs_dev); 1313 spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request); 1314 1315 cleanup: 1316 free_rpc_bdev_lvol_grow_lvstore(&req); 1317 } 1318 SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME) 1319 1320 struct rpc_bdev_lvol_shallow_copy { 1321 char *src_lvol_name; 1322 char *dst_bdev_name; 1323 }; 1324 1325 struct rpc_bdev_lvol_shallow_copy_ctx { 1326 struct spdk_jsonrpc_request *request; 1327 struct rpc_shallow_copy_status *status; 1328 }; 1329 1330 static void 1331 free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req) 1332 { 1333 free(req->src_lvol_name); 1334 free(req->dst_bdev_name); 1335 } 1336 1337 static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = { 1338 {"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string}, 1339 {"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string}, 1340 }; 1341 1342 static void 1343 rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno) 1344 { 1345 struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg; 1346 1347 ctx->status->result = lvolerrno; 1348 1349 free(ctx); 1350 } 1351 1352 static void 1353 rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg) 1354 { 1355 struct rpc_shallow_copy_status *status = cb_arg; 1356 1357 status->copied_clusters = copied_clusters; 1358 } 1359 1360 static void 1361 rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request, 1362 const struct spdk_json_val *params) 1363 { 1364 struct rpc_bdev_lvol_shallow_copy req = {}; 1365 struct rpc_bdev_lvol_shallow_copy_ctx *ctx; 1366 struct spdk_lvol *src_lvol; 1367 struct spdk_bdev *src_lvol_bdev; 1368 struct rpc_shallow_copy_status *status; 1369 struct spdk_json_write_ctx *w; 1370 int rc; 1371 1372 SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n"); 1373 1374 if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders, 1375 SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders), 1376 &req)) { 1377 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1378 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1379 "spdk_json_decode_object failed"); 1380 goto cleanup; 1381 } 1382 1383 src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name); 1384 if (src_lvol_bdev == NULL) { 1385 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name); 1386 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1387 goto cleanup; 1388 } 1389 1390 src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev); 1391 if (src_lvol == NULL) { 1392 SPDK_ERRLOG("lvol does not exist\n"); 1393 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1394 goto cleanup; 1395 } 1396 1397 status = calloc(1, sizeof(*status)); 1398 if (status == NULL) { 1399 SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name); 1400 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1401 goto cleanup; 1402 } 1403 1404 status->operation_id = ++g_shallow_copy_count; 1405 status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob); 1406 1407 ctx = calloc(1, sizeof(*ctx)); 1408 if (ctx == NULL) { 1409 SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name); 1410 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1411 free(status); 1412 goto cleanup; 1413 } 1414 ctx->request = request; 1415 ctx->status = status; 1416 1417 LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link); 1418 rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name, 1419 rpc_bdev_lvol_shallow_copy_status_cb, status, 1420 rpc_bdev_lvol_shallow_copy_cb, ctx); 1421 1422 if (rc < 0) { 1423 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1424 spdk_strerror(-rc)); 1425 LIST_REMOVE(status, link); 1426 free(ctx); 1427 free(status); 1428 } else { 1429 w = spdk_jsonrpc_begin_result(request); 1430 1431 spdk_json_write_object_begin(w); 1432 spdk_json_write_named_uint32(w, "operation_id", status->operation_id); 1433 spdk_json_write_object_end(w); 1434 1435 spdk_jsonrpc_end_result(request, w); 1436 } 1437 1438 cleanup: 1439 free_rpc_bdev_lvol_shallow_copy(&req); 1440 } 1441 1442 SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy, 1443 SPDK_RPC_RUNTIME) 1444 1445 struct rpc_bdev_lvol_shallow_copy_status { 1446 char *src_lvol_name; 1447 uint32_t operation_id; 1448 }; 1449 1450 static void 1451 free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req) 1452 { 1453 free(req->src_lvol_name); 1454 } 1455 1456 static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = { 1457 {"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32}, 1458 }; 1459 1460 static void 1461 rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request, 1462 const struct spdk_json_val *params) 1463 { 1464 struct rpc_bdev_lvol_shallow_copy_status req = {}; 1465 struct rpc_shallow_copy_status *status; 1466 struct spdk_json_write_ctx *w; 1467 uint64_t copied_clusters, total_clusters; 1468 int result; 1469 1470 SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n"); 1471 1472 if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders, 1473 SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders), 1474 &req)) { 1475 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1476 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1477 "spdk_json_decode_object failed"); 1478 goto cleanup; 1479 } 1480 1481 LIST_FOREACH(status, &g_shallow_copy_status_list, link) { 1482 if (status->operation_id == req.operation_id) { 1483 break; 1484 } 1485 } 1486 1487 if (!status) { 1488 SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id); 1489 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1490 goto cleanup; 1491 } 1492 1493 copied_clusters = status->copied_clusters; 1494 total_clusters = status->total_clusters; 1495 result = status->result; 1496 1497 w = spdk_jsonrpc_begin_result(request); 1498 1499 spdk_json_write_object_begin(w); 1500 1501 spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters); 1502 spdk_json_write_named_uint64(w, "total_clusters", total_clusters); 1503 if (copied_clusters < total_clusters && result == 0) { 1504 spdk_json_write_named_string(w, "state", "in progress"); 1505 } else if (copied_clusters == total_clusters && result == 0) { 1506 spdk_json_write_named_string(w, "state", "complete"); 1507 LIST_REMOVE(status, link); 1508 free(status); 1509 } else { 1510 spdk_json_write_named_string(w, "state", "error"); 1511 spdk_json_write_named_string(w, "error", spdk_strerror(-result)); 1512 LIST_REMOVE(status, link); 1513 free(status); 1514 } 1515 1516 spdk_json_write_object_end(w); 1517 1518 spdk_jsonrpc_end_result(request, w); 1519 1520 cleanup: 1521 free_rpc_bdev_lvol_shallow_copy_status(&req); 1522 } 1523 1524 SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy, 1525 SPDK_RPC_RUNTIME) 1526 1527 struct rpc_bdev_lvol_set_parent { 1528 char *lvol_name; 1529 char *parent_name; 1530 }; 1531 1532 static void 1533 free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req) 1534 { 1535 free(req->lvol_name); 1536 free(req->parent_name); 1537 } 1538 1539 static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = { 1540 {"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string}, 1541 {"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string}, 1542 }; 1543 1544 static void 1545 rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno) 1546 { 1547 struct spdk_jsonrpc_request *request = cb_arg; 1548 1549 if (lvolerrno != 0) { 1550 goto invalid; 1551 } 1552 1553 spdk_jsonrpc_send_bool_response(request, true); 1554 return; 1555 1556 invalid: 1557 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1558 spdk_strerror(-lvolerrno)); 1559 } 1560 1561 static void 1562 rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request, 1563 const struct spdk_json_val *params) 1564 { 1565 struct rpc_bdev_lvol_set_parent req = {}; 1566 struct spdk_lvol *lvol, *snapshot; 1567 struct spdk_bdev *lvol_bdev, *snapshot_bdev; 1568 1569 SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n"); 1570 1571 if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders, 1572 SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders), 1573 &req)) { 1574 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1575 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1576 "spdk_json_decode_object failed"); 1577 goto cleanup; 1578 } 1579 1580 lvol_bdev = spdk_bdev_get_by_name(req.lvol_name); 1581 if (lvol_bdev == NULL) { 1582 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name); 1583 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1584 goto cleanup; 1585 } 1586 1587 lvol = vbdev_lvol_get_from_bdev(lvol_bdev); 1588 if (lvol == NULL) { 1589 SPDK_ERRLOG("lvol does not exist\n"); 1590 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1591 goto cleanup; 1592 } 1593 1594 snapshot_bdev = spdk_bdev_get_by_name(req.parent_name); 1595 if (snapshot_bdev == NULL) { 1596 SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name); 1597 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1598 goto cleanup; 1599 } 1600 1601 snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev); 1602 if (snapshot == NULL) { 1603 SPDK_ERRLOG("snapshot does not exist\n"); 1604 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1605 goto cleanup; 1606 } 1607 1608 spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request); 1609 1610 cleanup: 1611 free_rpc_bdev_lvol_set_parent(&req); 1612 } 1613 1614 SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME) 1615 1616 static void 1617 rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request, 1618 const struct spdk_json_val *params) 1619 { 1620 struct rpc_bdev_lvol_set_parent req = {}; 1621 struct spdk_lvol *lvol; 1622 struct spdk_bdev *lvol_bdev; 1623 1624 SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n"); 1625 1626 if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders, 1627 SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders), 1628 &req)) { 1629 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1630 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1631 "spdk_json_decode_object failed"); 1632 goto cleanup; 1633 } 1634 1635 lvol_bdev = spdk_bdev_get_by_name(req.lvol_name); 1636 if (lvol_bdev == NULL) { 1637 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name); 1638 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1639 goto cleanup; 1640 } 1641 1642 lvol = vbdev_lvol_get_from_bdev(lvol_bdev); 1643 if (lvol == NULL) { 1644 SPDK_ERRLOG("lvol does not exist\n"); 1645 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1646 goto cleanup; 1647 } 1648 1649 vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request); 1650 1651 cleanup: 1652 free_rpc_bdev_lvol_set_parent(&req); 1653 } 1654 1655 SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev, 1656 SPDK_RPC_RUNTIME) 1657