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