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_bdev_lvol_create_lvstore { 17 char *lvs_name; 18 char *bdev_name; 19 uint32_t cluster_sz; 20 char *clear_method; 21 uint32_t num_md_pages_per_cluster_ratio; 22 }; 23 24 static int 25 vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name, 26 struct spdk_lvol_store **lvs) 27 { 28 if ((uuid == NULL && lvs_name == NULL)) { 29 SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n"); 30 return -EINVAL; 31 } else if ((uuid && lvs_name)) { 32 SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid, 33 lvs_name); 34 return -EINVAL; 35 } else if (uuid) { 36 *lvs = vbdev_get_lvol_store_by_uuid(uuid); 37 38 if (*lvs == NULL) { 39 SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid); 40 return -ENODEV; 41 } 42 } else if (lvs_name) { 43 44 *lvs = vbdev_get_lvol_store_by_name(lvs_name); 45 46 if (*lvs == NULL) { 47 SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name); 48 return -ENODEV; 49 } 50 } 51 return 0; 52 } 53 54 static void 55 free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req) 56 { 57 free(req->bdev_name); 58 free(req->lvs_name); 59 free(req->clear_method); 60 } 61 62 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = { 63 {"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string}, 64 {"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true}, 65 {"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string}, 66 {"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true}, 67 {"num_md_pages_per_cluster_ratio", offsetof(struct rpc_bdev_lvol_create_lvstore, num_md_pages_per_cluster_ratio), spdk_json_decode_uint32, true}, 68 }; 69 70 static void 71 rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno) 72 { 73 struct spdk_json_write_ctx *w; 74 struct spdk_jsonrpc_request *request = cb_arg; 75 76 if (lvserrno != 0) { 77 goto invalid; 78 } 79 80 w = spdk_jsonrpc_begin_result(request); 81 spdk_json_write_uuid(w, &lvol_store->uuid); 82 spdk_jsonrpc_end_result(request, w); 83 return; 84 85 invalid: 86 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 87 spdk_strerror(-lvserrno)); 88 } 89 90 static void 91 rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request, 92 const struct spdk_json_val *params) 93 { 94 struct rpc_bdev_lvol_create_lvstore req = {}; 95 int rc = 0; 96 enum lvs_clear_method clear_method; 97 98 if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders, 99 SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders), 100 &req)) { 101 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 102 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 103 "spdk_json_decode_object failed"); 104 goto cleanup; 105 } 106 107 if (req.clear_method != NULL) { 108 if (!strcasecmp(req.clear_method, "none")) { 109 clear_method = LVS_CLEAR_WITH_NONE; 110 } else if (!strcasecmp(req.clear_method, "unmap")) { 111 clear_method = LVS_CLEAR_WITH_UNMAP; 112 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 113 clear_method = LVS_CLEAR_WITH_WRITE_ZEROES; 114 } else { 115 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter"); 116 goto cleanup; 117 } 118 } else { 119 clear_method = LVS_CLEAR_WITH_UNMAP; 120 } 121 122 rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method, 123 req.num_md_pages_per_cluster_ratio, rpc_lvol_store_construct_cb, request); 124 if (rc < 0) { 125 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 126 goto cleanup; 127 } 128 free_rpc_bdev_lvol_create_lvstore(&req); 129 130 return; 131 132 cleanup: 133 free_rpc_bdev_lvol_create_lvstore(&req); 134 } 135 SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME) 136 137 struct rpc_bdev_lvol_rename_lvstore { 138 char *old_name; 139 char *new_name; 140 }; 141 142 static void 143 free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req) 144 { 145 free(req->old_name); 146 free(req->new_name); 147 } 148 149 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = { 150 {"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string}, 151 {"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string}, 152 }; 153 154 static void 155 rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno) 156 { 157 struct spdk_jsonrpc_request *request = cb_arg; 158 159 if (lvserrno != 0) { 160 goto invalid; 161 } 162 163 spdk_jsonrpc_send_bool_response(request, true); 164 return; 165 166 invalid: 167 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 168 spdk_strerror(-lvserrno)); 169 } 170 171 static void 172 rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request, 173 const struct spdk_json_val *params) 174 { 175 struct rpc_bdev_lvol_rename_lvstore req = {}; 176 struct spdk_lvol_store *lvs; 177 178 if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders, 179 SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders), 180 &req)) { 181 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 182 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 183 "spdk_json_decode_object failed"); 184 goto cleanup; 185 } 186 187 lvs = vbdev_get_lvol_store_by_name(req.old_name); 188 if (lvs == NULL) { 189 SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n"); 190 spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name); 191 goto cleanup; 192 } 193 194 vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request); 195 196 cleanup: 197 free_rpc_bdev_lvol_rename_lvstore(&req); 198 } 199 SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME) 200 201 struct rpc_bdev_lvol_delete_lvstore { 202 char *uuid; 203 char *lvs_name; 204 }; 205 206 static void 207 free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req) 208 { 209 free(req->uuid); 210 free(req->lvs_name); 211 } 212 213 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = { 214 {"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true}, 215 {"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true}, 216 }; 217 218 static void 219 rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno) 220 { 221 struct spdk_jsonrpc_request *request = cb_arg; 222 223 if (lvserrno != 0) { 224 goto invalid; 225 } 226 227 spdk_jsonrpc_send_bool_response(request, true); 228 return; 229 230 invalid: 231 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 232 spdk_strerror(-lvserrno)); 233 } 234 235 static void 236 rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request, 237 const struct spdk_json_val *params) 238 { 239 struct rpc_bdev_lvol_delete_lvstore req = {}; 240 struct spdk_lvol_store *lvs = NULL; 241 int rc; 242 243 if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders, 244 SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders), 245 &req)) { 246 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 247 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 248 "spdk_json_decode_object failed"); 249 goto cleanup; 250 } 251 252 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 253 if (rc != 0) { 254 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 255 goto cleanup; 256 } 257 258 vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request); 259 260 cleanup: 261 free_rpc_bdev_lvol_delete_lvstore(&req); 262 } 263 SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME) 264 265 struct rpc_bdev_lvol_create { 266 char *uuid; 267 char *lvs_name; 268 char *lvol_name; 269 uint64_t size; 270 uint64_t size_in_mib; 271 bool thin_provision; 272 char *clear_method; 273 }; 274 275 static void 276 free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req) 277 { 278 free(req->uuid); 279 free(req->lvs_name); 280 free(req->lvol_name); 281 free(req->clear_method); 282 } 283 284 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = { 285 {"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true}, 286 {"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true}, 287 {"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string}, 288 {"size", offsetof(struct rpc_bdev_lvol_create, size), spdk_json_decode_uint64, true}, 289 {"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64, true}, 290 {"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true}, 291 {"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true}, 292 }; 293 294 static void 295 rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 296 { 297 struct spdk_json_write_ctx *w; 298 struct spdk_jsonrpc_request *request = cb_arg; 299 300 if (lvolerrno != 0) { 301 goto invalid; 302 } 303 304 w = spdk_jsonrpc_begin_result(request); 305 spdk_json_write_string(w, lvol->unique_id); 306 spdk_jsonrpc_end_result(request, w); 307 return; 308 309 invalid: 310 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 311 spdk_strerror(-lvolerrno)); 312 } 313 314 SPDK_LOG_DEPRECATION_REGISTER(vbdev_lvol_rpc_req_size, 315 "rpc_bdev_lvol_create/resize req.size", 316 "v23.09", 0); 317 318 static void 319 rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request, 320 const struct spdk_json_val *params) 321 { 322 struct rpc_bdev_lvol_create req = {}; 323 enum lvol_clear_method clear_method; 324 int rc = 0; 325 struct spdk_lvol_store *lvs = NULL; 326 uint64_t size = 0; 327 328 SPDK_INFOLOG(lvol_rpc, "Creating blob\n"); 329 330 if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders, 331 SPDK_COUNTOF(rpc_bdev_lvol_create_decoders), 332 &req)) { 333 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 334 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 335 "spdk_json_decode_object failed"); 336 goto cleanup; 337 } 338 339 if (req.size > 0 && req.size_in_mib > 0) { 340 SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size); 341 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 342 "size is deprecated. Specify only size_in_mib instead."); 343 goto cleanup; 344 } else if (req.size_in_mib > 0) { 345 size = req.size_in_mib * 1024 * 1024; 346 } else { 347 SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size); 348 size = req.size; 349 } 350 351 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 352 if (rc != 0) { 353 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 354 goto cleanup; 355 } 356 357 if (req.clear_method != NULL) { 358 if (!strcasecmp(req.clear_method, "none")) { 359 clear_method = LVOL_CLEAR_WITH_NONE; 360 } else if (!strcasecmp(req.clear_method, "unmap")) { 361 clear_method = LVOL_CLEAR_WITH_UNMAP; 362 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 363 clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES; 364 } else { 365 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option"); 366 goto cleanup; 367 } 368 } else { 369 clear_method = LVOL_CLEAR_WITH_DEFAULT; 370 } 371 372 rc = vbdev_lvol_create(lvs, req.lvol_name, size, req.thin_provision, 373 clear_method, rpc_bdev_lvol_create_cb, request); 374 if (rc < 0) { 375 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 376 goto cleanup; 377 } 378 379 cleanup: 380 free_rpc_bdev_lvol_create(&req); 381 } 382 383 SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME) 384 385 struct rpc_bdev_lvol_snapshot { 386 char *lvol_name; 387 char *snapshot_name; 388 }; 389 390 static void 391 free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req) 392 { 393 free(req->lvol_name); 394 free(req->snapshot_name); 395 } 396 397 static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = { 398 {"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string}, 399 {"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string}, 400 }; 401 402 static void 403 rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 404 { 405 struct spdk_json_write_ctx *w; 406 struct spdk_jsonrpc_request *request = cb_arg; 407 408 if (lvolerrno != 0) { 409 goto invalid; 410 } 411 412 w = spdk_jsonrpc_begin_result(request); 413 spdk_json_write_string(w, lvol->unique_id); 414 spdk_jsonrpc_end_result(request, w); 415 return; 416 417 invalid: 418 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 419 spdk_strerror(-lvolerrno)); 420 } 421 422 static void 423 rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request, 424 const struct spdk_json_val *params) 425 { 426 struct rpc_bdev_lvol_snapshot req = {}; 427 struct spdk_bdev *bdev; 428 struct spdk_lvol *lvol; 429 430 SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n"); 431 432 if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders, 433 SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders), 434 &req)) { 435 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 436 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 437 "spdk_json_decode_object failed"); 438 goto cleanup; 439 } 440 441 bdev = spdk_bdev_get_by_name(req.lvol_name); 442 if (bdev == NULL) { 443 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name); 444 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 445 goto cleanup; 446 } 447 448 lvol = vbdev_lvol_get_from_bdev(bdev); 449 if (lvol == NULL) { 450 SPDK_ERRLOG("lvol does not exist\n"); 451 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 452 goto cleanup; 453 } 454 455 vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request); 456 457 cleanup: 458 free_rpc_bdev_lvol_snapshot(&req); 459 } 460 461 SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME) 462 463 struct rpc_bdev_lvol_clone { 464 char *snapshot_name; 465 char *clone_name; 466 }; 467 468 static void 469 free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req) 470 { 471 free(req->snapshot_name); 472 free(req->clone_name); 473 } 474 475 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = { 476 {"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string}, 477 {"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true}, 478 }; 479 480 static void 481 rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 482 { 483 struct spdk_json_write_ctx *w; 484 struct spdk_jsonrpc_request *request = cb_arg; 485 486 if (lvolerrno != 0) { 487 goto invalid; 488 } 489 490 w = spdk_jsonrpc_begin_result(request); 491 spdk_json_write_string(w, lvol->unique_id); 492 spdk_jsonrpc_end_result(request, w); 493 return; 494 495 invalid: 496 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 497 spdk_strerror(-lvolerrno)); 498 } 499 500 static void 501 rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request, 502 const struct spdk_json_val *params) 503 { 504 struct rpc_bdev_lvol_clone req = {}; 505 struct spdk_bdev *bdev; 506 struct spdk_lvol *lvol; 507 508 SPDK_INFOLOG(lvol_rpc, "Cloning blob\n"); 509 510 if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders, 511 SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders), 512 &req)) { 513 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 514 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 515 "spdk_json_decode_object failed"); 516 goto cleanup; 517 } 518 519 bdev = spdk_bdev_get_by_name(req.snapshot_name); 520 if (bdev == NULL) { 521 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name); 522 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 523 goto cleanup; 524 } 525 526 lvol = vbdev_lvol_get_from_bdev(bdev); 527 if (lvol == NULL) { 528 SPDK_ERRLOG("lvol does not exist\n"); 529 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 530 goto cleanup; 531 } 532 533 vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request); 534 535 cleanup: 536 free_rpc_bdev_lvol_clone(&req); 537 } 538 539 SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME) 540 541 struct rpc_bdev_lvol_clone_bdev { 542 /* name or UUID. Whichever is used, the UUID will be stored in the lvol's metadata. */ 543 char *bdev_name; 544 char *lvs_name; 545 char *clone_name; 546 }; 547 548 static void 549 free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req) 550 { 551 free(req->bdev_name); 552 free(req->lvs_name); 553 free(req->clone_name); 554 } 555 556 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_bdev_decoders[] = { 557 { 558 "bdev", offsetof(struct rpc_bdev_lvol_clone_bdev, bdev_name), 559 spdk_json_decode_string, false 560 }, 561 { 562 "lvs_name", offsetof(struct rpc_bdev_lvol_clone_bdev, lvs_name), 563 spdk_json_decode_string, false 564 }, 565 { 566 "clone_name", offsetof(struct rpc_bdev_lvol_clone_bdev, clone_name), 567 spdk_json_decode_string, false 568 }, 569 }; 570 571 static void 572 rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 573 { 574 struct rpc_bdev_lvol_clone_bdev req = {}; 575 struct spdk_bdev *bdev; 576 struct spdk_lvol_store *lvs = NULL; 577 struct spdk_lvol *lvol; 578 int rc; 579 580 SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n"); 581 582 if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_bdev_decoders, 583 SPDK_COUNTOF(rpc_bdev_lvol_clone_bdev_decoders), &req)) { 584 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 585 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 586 "spdk_json_decode_object failed"); 587 goto cleanup; 588 } 589 590 rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs); 591 if (rc != 0) { 592 SPDK_INFOLOG(lvol_rpc, "lvs_name '%s' not found\n", req.lvs_name); 593 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 594 "lvs does not exist"); 595 goto cleanup; 596 } 597 598 bdev = spdk_bdev_get_by_name(req.bdev_name); 599 if (bdev == NULL) { 600 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.bdev_name); 601 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 602 "bdev does not exist"); 603 goto cleanup; 604 } 605 606 lvol = vbdev_lvol_get_from_bdev(bdev); 607 if (lvol != NULL && lvol->lvol_store == lvs) { 608 SPDK_INFOLOG(lvol_rpc, "bdev '%s' is an lvol in lvstore '%s\n", req.bdev_name, 609 req.lvs_name); 610 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 611 "bdev is an lvol in same lvs as clone; " 612 "use bdev_lvol_clone instead"); 613 goto cleanup; 614 } 615 616 vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name, 617 rpc_bdev_lvol_clone_cb, request); 618 cleanup: 619 free_rpc_bdev_lvol_clone_bdev(&req); 620 } 621 622 SPDK_RPC_REGISTER("bdev_lvol_clone_bdev", rpc_bdev_lvol_clone_bdev, SPDK_RPC_RUNTIME) 623 624 struct rpc_bdev_lvol_rename { 625 char *old_name; 626 char *new_name; 627 }; 628 629 static void 630 free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req) 631 { 632 free(req->old_name); 633 free(req->new_name); 634 } 635 636 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = { 637 {"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string}, 638 {"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string}, 639 }; 640 641 static void 642 rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno) 643 { 644 struct spdk_jsonrpc_request *request = cb_arg; 645 646 if (lvolerrno != 0) { 647 goto invalid; 648 } 649 650 spdk_jsonrpc_send_bool_response(request, true); 651 return; 652 653 invalid: 654 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 655 spdk_strerror(-lvolerrno)); 656 } 657 658 static void 659 rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request, 660 const struct spdk_json_val *params) 661 { 662 struct rpc_bdev_lvol_rename req = {}; 663 struct spdk_bdev *bdev; 664 struct spdk_lvol *lvol; 665 666 SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n"); 667 668 if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders, 669 SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders), 670 &req)) { 671 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 672 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 673 "spdk_json_decode_object failed"); 674 goto cleanup; 675 } 676 677 bdev = spdk_bdev_get_by_name(req.old_name); 678 if (bdev == NULL) { 679 SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name); 680 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 681 goto cleanup; 682 } 683 684 lvol = vbdev_lvol_get_from_bdev(bdev); 685 if (lvol == NULL) { 686 SPDK_ERRLOG("lvol does not exist\n"); 687 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 688 goto cleanup; 689 } 690 691 vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request); 692 693 cleanup: 694 free_rpc_bdev_lvol_rename(&req); 695 } 696 697 SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME) 698 699 struct rpc_bdev_lvol_inflate { 700 char *name; 701 }; 702 703 static void 704 free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req) 705 { 706 free(req->name); 707 } 708 709 static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = { 710 {"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string}, 711 }; 712 713 static void 714 rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno) 715 { 716 struct spdk_jsonrpc_request *request = cb_arg; 717 718 if (lvolerrno != 0) { 719 goto invalid; 720 } 721 722 spdk_jsonrpc_send_bool_response(request, true); 723 return; 724 725 invalid: 726 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 727 spdk_strerror(-lvolerrno)); 728 } 729 730 static void 731 rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request, 732 const struct spdk_json_val *params) 733 { 734 struct rpc_bdev_lvol_inflate req = {}; 735 struct spdk_bdev *bdev; 736 struct spdk_lvol *lvol; 737 738 SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n"); 739 740 if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders, 741 SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders), 742 &req)) { 743 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 744 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 745 "spdk_json_decode_object failed"); 746 goto cleanup; 747 } 748 749 bdev = spdk_bdev_get_by_name(req.name); 750 if (bdev == NULL) { 751 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 752 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 753 goto cleanup; 754 } 755 756 lvol = vbdev_lvol_get_from_bdev(bdev); 757 if (lvol == NULL) { 758 SPDK_ERRLOG("lvol does not exist\n"); 759 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 760 goto cleanup; 761 } 762 763 spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request); 764 765 cleanup: 766 free_rpc_bdev_lvol_inflate(&req); 767 } 768 769 SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME) 770 771 static void 772 rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request, 773 const struct spdk_json_val *params) 774 { 775 struct rpc_bdev_lvol_inflate req = {}; 776 struct spdk_bdev *bdev; 777 struct spdk_lvol *lvol; 778 779 SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n"); 780 781 if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders, 782 SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders), 783 &req)) { 784 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 785 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 786 "spdk_json_decode_object failed"); 787 goto cleanup; 788 } 789 790 bdev = spdk_bdev_get_by_name(req.name); 791 if (bdev == NULL) { 792 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 793 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 794 goto cleanup; 795 } 796 797 lvol = vbdev_lvol_get_from_bdev(bdev); 798 if (lvol == NULL) { 799 SPDK_ERRLOG("lvol does not exist\n"); 800 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 801 goto cleanup; 802 } 803 804 spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request); 805 806 cleanup: 807 free_rpc_bdev_lvol_inflate(&req); 808 } 809 810 SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME) 811 812 struct rpc_bdev_lvol_resize { 813 char *name; 814 uint64_t size; 815 uint64_t size_in_mib; 816 }; 817 818 static void 819 free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req) 820 { 821 free(req->name); 822 } 823 824 static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = { 825 {"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string}, 826 {"size", offsetof(struct rpc_bdev_lvol_resize, size), spdk_json_decode_uint64, true}, 827 {"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64, true}, 828 }; 829 830 static void 831 rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno) 832 { 833 struct spdk_jsonrpc_request *request = cb_arg; 834 835 if (lvolerrno != 0) { 836 goto invalid; 837 } 838 839 spdk_jsonrpc_send_bool_response(request, true); 840 return; 841 842 invalid: 843 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 844 spdk_strerror(-lvolerrno)); 845 } 846 847 static void 848 rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request, 849 const struct spdk_json_val *params) 850 { 851 struct rpc_bdev_lvol_resize req = {}; 852 struct spdk_bdev *bdev; 853 struct spdk_lvol *lvol; 854 uint64_t size = 0; 855 856 SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n"); 857 858 if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders, 859 SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders), 860 &req)) { 861 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 862 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 863 "spdk_json_decode_object failed"); 864 goto cleanup; 865 } 866 867 if (req.size > 0 && req.size_in_mib > 0) { 868 SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size); 869 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 870 "size is deprecated. Specify only size_in_mib instead."); 871 goto cleanup; 872 } else if (req.size_in_mib > 0) { 873 size = req.size_in_mib * 1024 * 1024; 874 } else { 875 SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size); 876 size = req.size; 877 } 878 879 bdev = spdk_bdev_get_by_name(req.name); 880 if (bdev == NULL) { 881 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 882 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 883 goto cleanup; 884 } 885 886 lvol = vbdev_lvol_get_from_bdev(bdev); 887 if (lvol == NULL) { 888 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 889 goto cleanup; 890 } 891 892 893 vbdev_lvol_resize(lvol, size, rpc_bdev_lvol_resize_cb, request); 894 895 cleanup: 896 free_rpc_bdev_lvol_resize(&req); 897 } 898 899 SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME) 900 901 struct rpc_set_ro_lvol_bdev { 902 char *name; 903 }; 904 905 static void 906 free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req) 907 { 908 free(req->name); 909 } 910 911 static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = { 912 {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string}, 913 }; 914 915 static void 916 rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno) 917 { 918 struct spdk_jsonrpc_request *request = cb_arg; 919 920 if (lvolerrno != 0) { 921 goto invalid; 922 } 923 924 spdk_jsonrpc_send_bool_response(request, true); 925 return; 926 927 invalid: 928 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 929 spdk_strerror(-lvolerrno)); 930 } 931 932 static void 933 rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request, 934 const struct spdk_json_val *params) 935 { 936 struct rpc_set_ro_lvol_bdev req = {}; 937 struct spdk_bdev *bdev; 938 struct spdk_lvol *lvol; 939 940 SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n"); 941 942 if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders, 943 SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders), 944 &req)) { 945 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 946 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 947 "spdk_json_decode_object failed"); 948 goto cleanup; 949 } 950 951 if (req.name == NULL) { 952 SPDK_ERRLOG("missing name param\n"); 953 spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter"); 954 goto cleanup; 955 } 956 957 bdev = spdk_bdev_get_by_name(req.name); 958 if (bdev == NULL) { 959 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 960 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 961 goto cleanup; 962 } 963 964 lvol = vbdev_lvol_get_from_bdev(bdev); 965 if (lvol == NULL) { 966 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 967 goto cleanup; 968 } 969 970 vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request); 971 972 cleanup: 973 free_rpc_set_ro_lvol_bdev(&req); 974 } 975 976 SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME) 977 978 struct rpc_bdev_lvol_delete { 979 char *name; 980 }; 981 982 static void 983 free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req) 984 { 985 free(req->name); 986 } 987 988 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = { 989 {"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string}, 990 }; 991 992 static void 993 rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno) 994 { 995 struct spdk_jsonrpc_request *request = cb_arg; 996 997 if (lvolerrno != 0) { 998 goto invalid; 999 } 1000 1001 spdk_jsonrpc_send_bool_response(request, true); 1002 return; 1003 1004 invalid: 1005 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1006 spdk_strerror(-lvolerrno)); 1007 } 1008 1009 static void 1010 rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request, 1011 const struct spdk_json_val *params) 1012 { 1013 struct rpc_bdev_lvol_delete req = {}; 1014 struct spdk_bdev *bdev; 1015 struct spdk_lvol *lvol; 1016 struct spdk_uuid uuid; 1017 char *lvs_name, *lvol_name; 1018 1019 if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders, 1020 SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders), 1021 &req)) { 1022 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1023 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1024 "spdk_json_decode_object failed"); 1025 goto cleanup; 1026 } 1027 1028 /* lvol is not degraded, get lvol via bdev name or alias */ 1029 bdev = spdk_bdev_get_by_name(req.name); 1030 if (bdev != NULL) { 1031 lvol = vbdev_lvol_get_from_bdev(bdev); 1032 if (lvol != NULL) { 1033 goto done; 1034 } 1035 } 1036 1037 /* lvol is degraded, get lvol via UUID */ 1038 if (spdk_uuid_parse(&uuid, req.name) == 0) { 1039 lvol = spdk_lvol_get_by_uuid(&uuid); 1040 if (lvol != NULL) { 1041 goto done; 1042 } 1043 } 1044 1045 /* lvol is degraded, get lvol via lvs_name/lvol_name */ 1046 lvol_name = strchr(req.name, '/'); 1047 if (lvol_name != NULL) { 1048 *lvol_name = '\0'; 1049 lvol_name++; 1050 lvs_name = req.name; 1051 lvol = spdk_lvol_get_by_names(lvs_name, lvol_name); 1052 if (lvol != NULL) { 1053 goto done; 1054 } 1055 } 1056 1057 /* Could not find lvol, degraded or not. */ 1058 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1059 goto cleanup; 1060 1061 done: 1062 vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request); 1063 1064 cleanup: 1065 free_rpc_bdev_lvol_delete(&req); 1066 } 1067 1068 SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME) 1069 1070 struct rpc_bdev_lvol_get_lvstores { 1071 char *uuid; 1072 char *lvs_name; 1073 }; 1074 1075 static void 1076 free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req) 1077 { 1078 free(req->uuid); 1079 free(req->lvs_name); 1080 } 1081 1082 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = { 1083 {"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true}, 1084 {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true}, 1085 }; 1086 1087 static void 1088 rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev) 1089 { 1090 struct spdk_blob_store *bs; 1091 uint64_t cluster_size; 1092 1093 bs = lvs_bdev->lvs->blobstore; 1094 cluster_size = spdk_bs_get_cluster_size(bs); 1095 1096 spdk_json_write_object_begin(w); 1097 1098 spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid); 1099 spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name); 1100 spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev)); 1101 spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs)); 1102 spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs)); 1103 spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs)); 1104 spdk_json_write_named_uint64(w, "cluster_size", cluster_size); 1105 1106 spdk_json_write_object_end(w); 1107 } 1108 1109 static void 1110 rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request, 1111 const struct spdk_json_val *params) 1112 { 1113 struct rpc_bdev_lvol_get_lvstores req = {}; 1114 struct spdk_json_write_ctx *w; 1115 struct lvol_store_bdev *lvs_bdev = NULL; 1116 struct spdk_lvol_store *lvs = NULL; 1117 int rc; 1118 1119 if (params != NULL) { 1120 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders, 1121 SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders), 1122 &req)) { 1123 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1124 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1125 "spdk_json_decode_object failed"); 1126 goto cleanup; 1127 } 1128 1129 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 1130 if (rc != 0) { 1131 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1132 goto cleanup; 1133 } 1134 1135 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs); 1136 if (lvs_bdev == NULL) { 1137 spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV)); 1138 goto cleanup; 1139 } 1140 } 1141 1142 w = spdk_jsonrpc_begin_result(request); 1143 spdk_json_write_array_begin(w); 1144 1145 if (lvs_bdev != NULL) { 1146 rpc_dump_lvol_store_info(w, lvs_bdev); 1147 } else { 1148 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL; 1149 lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) { 1150 rpc_dump_lvol_store_info(w, lvs_bdev); 1151 } 1152 } 1153 spdk_json_write_array_end(w); 1154 1155 spdk_jsonrpc_end_result(request, w); 1156 1157 cleanup: 1158 free_rpc_bdev_lvol_get_lvstores(&req); 1159 } 1160 1161 SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME) 1162 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores) 1163 1164 struct rpc_bdev_lvol_get_lvols { 1165 char *lvs_uuid; 1166 char *lvs_name; 1167 }; 1168 1169 static void 1170 free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req) 1171 { 1172 free(req->lvs_uuid); 1173 free(req->lvs_name); 1174 } 1175 1176 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = { 1177 {"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true}, 1178 {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true}, 1179 }; 1180 1181 static void 1182 rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol) 1183 { 1184 struct spdk_lvol_store *lvs = lvol->lvol_store; 1185 1186 spdk_json_write_object_begin(w); 1187 1188 spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name); 1189 spdk_json_write_named_string(w, "uuid", lvol->uuid_str); 1190 spdk_json_write_named_string(w, "name", lvol->name); 1191 spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob)); 1192 spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob)); 1193 spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob)); 1194 spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob)); 1195 spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob)); 1196 1197 spdk_json_write_named_object_begin(w, "lvs"); 1198 spdk_json_write_named_string(w, "name", lvs->name); 1199 spdk_json_write_named_uuid(w, "uuid", &lvs->uuid); 1200 spdk_json_write_object_end(w); 1201 1202 spdk_json_write_object_end(w); 1203 } 1204 1205 static void 1206 rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev) 1207 { 1208 struct spdk_lvol_store *lvs = lvs_bdev->lvs; 1209 struct spdk_lvol *lvol; 1210 1211 TAILQ_FOREACH(lvol, &lvs->lvols, link) { 1212 rpc_dump_lvol(w, lvol); 1213 } 1214 } 1215 1216 static void 1217 rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 1218 { 1219 struct rpc_bdev_lvol_get_lvols req = {}; 1220 struct spdk_json_write_ctx *w; 1221 struct lvol_store_bdev *lvs_bdev = NULL; 1222 struct spdk_lvol_store *lvs = NULL; 1223 int rc; 1224 1225 if (params != NULL) { 1226 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders, 1227 SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders), 1228 &req)) { 1229 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1230 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1231 "spdk_json_decode_object failed"); 1232 goto cleanup; 1233 } 1234 1235 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs); 1236 if (rc != 0) { 1237 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1238 goto cleanup; 1239 } 1240 1241 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs); 1242 if (lvs_bdev == NULL) { 1243 spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV)); 1244 goto cleanup; 1245 } 1246 } 1247 1248 w = spdk_jsonrpc_begin_result(request); 1249 spdk_json_write_array_begin(w); 1250 1251 if (lvs_bdev != NULL) { 1252 rpc_dump_lvols(w, lvs_bdev); 1253 } else { 1254 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL; 1255 lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) { 1256 rpc_dump_lvols(w, lvs_bdev); 1257 } 1258 } 1259 spdk_json_write_array_end(w); 1260 1261 spdk_jsonrpc_end_result(request, w); 1262 1263 cleanup: 1264 free_rpc_bdev_lvol_get_lvols(&req); 1265 } 1266 1267 SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME) 1268 1269 struct rpc_bdev_lvol_grow_lvstore { 1270 char *uuid; 1271 char *lvs_name; 1272 }; 1273 1274 static void 1275 free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req) 1276 { 1277 free(req->uuid); 1278 free(req->lvs_name); 1279 } 1280 1281 static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = { 1282 {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true}, 1283 {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true}, 1284 }; 1285 1286 static void 1287 rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno) 1288 { 1289 struct spdk_jsonrpc_request *request = cb_arg; 1290 1291 if (lvserrno != 0) { 1292 goto invalid; 1293 } 1294 1295 spdk_jsonrpc_send_bool_response(request, true); 1296 return; 1297 1298 invalid: 1299 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1300 spdk_strerror(-lvserrno)); 1301 } 1302 1303 static void 1304 rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request, 1305 const struct spdk_json_val *params) 1306 { 1307 struct rpc_bdev_lvol_grow_lvstore req = {}; 1308 struct spdk_lvol_store *lvs = NULL; 1309 int rc; 1310 1311 if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders, 1312 SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders), 1313 &req)) { 1314 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1315 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1316 "spdk_json_decode_object failed"); 1317 goto cleanup; 1318 } 1319 1320 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 1321 if (rc != 0) { 1322 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1323 goto cleanup; 1324 } 1325 spdk_bdev_update_bs_blockcnt(lvs->bs_dev); 1326 spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request); 1327 1328 cleanup: 1329 free_rpc_bdev_lvol_grow_lvstore(&req); 1330 } 1331 SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME) 1332