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