1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/rpc.h" 35 #include "spdk/bdev.h" 36 #include "spdk/util.h" 37 #include "vbdev_lvol.h" 38 #include "spdk/string.h" 39 #include "spdk/log.h" 40 41 SPDK_LOG_REGISTER_COMPONENT(lvol_rpc) 42 43 struct rpc_bdev_lvol_create_lvstore { 44 char *lvs_name; 45 char *bdev_name; 46 uint32_t cluster_sz; 47 char *clear_method; 48 }; 49 50 static int 51 vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name, 52 struct spdk_lvol_store **lvs) 53 { 54 if ((uuid == NULL && lvs_name == NULL)) { 55 SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n"); 56 return -EINVAL; 57 } else if ((uuid && lvs_name)) { 58 SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid, 59 lvs_name); 60 return -EINVAL; 61 } else if (uuid) { 62 *lvs = vbdev_get_lvol_store_by_uuid(uuid); 63 64 if (*lvs == NULL) { 65 SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid); 66 return -ENODEV; 67 } 68 } else if (lvs_name) { 69 70 *lvs = vbdev_get_lvol_store_by_name(lvs_name); 71 72 if (*lvs == NULL) { 73 SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name); 74 return -ENODEV; 75 } 76 } 77 return 0; 78 } 79 80 static void 81 free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req) 82 { 83 free(req->bdev_name); 84 free(req->lvs_name); 85 free(req->clear_method); 86 } 87 88 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = { 89 {"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string}, 90 {"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true}, 91 {"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string}, 92 {"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true}, 93 }; 94 95 static void 96 rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno) 97 { 98 struct spdk_json_write_ctx *w; 99 char lvol_store_uuid[SPDK_UUID_STRING_LEN]; 100 struct spdk_jsonrpc_request *request = cb_arg; 101 102 if (lvserrno != 0) { 103 goto invalid; 104 } 105 106 spdk_uuid_fmt_lower(lvol_store_uuid, sizeof(lvol_store_uuid), &lvol_store->uuid); 107 108 w = spdk_jsonrpc_begin_result(request); 109 spdk_json_write_string(w, lvol_store_uuid); 110 spdk_jsonrpc_end_result(request, w); 111 return; 112 113 invalid: 114 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 115 spdk_strerror(-lvserrno)); 116 } 117 118 static void 119 rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request, 120 const struct spdk_json_val *params) 121 { 122 struct rpc_bdev_lvol_create_lvstore req = {}; 123 int rc = 0; 124 enum lvs_clear_method clear_method; 125 126 if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders, 127 SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders), 128 &req)) { 129 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 130 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 131 "spdk_json_decode_object failed"); 132 goto cleanup; 133 } 134 135 if (req.clear_method != NULL) { 136 if (!strcasecmp(req.clear_method, "none")) { 137 clear_method = LVS_CLEAR_WITH_NONE; 138 } else if (!strcasecmp(req.clear_method, "unmap")) { 139 clear_method = LVS_CLEAR_WITH_UNMAP; 140 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 141 clear_method = LVS_CLEAR_WITH_WRITE_ZEROES; 142 } else { 143 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter"); 144 goto cleanup; 145 } 146 } else { 147 clear_method = LVS_CLEAR_WITH_UNMAP; 148 } 149 150 rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method, 151 rpc_lvol_store_construct_cb, request); 152 if (rc < 0) { 153 spdk_jsonrpc_send_error_response(request, -rc, spdk_strerror(rc)); 154 goto cleanup; 155 } 156 free_rpc_bdev_lvol_create_lvstore(&req); 157 158 return; 159 160 cleanup: 161 free_rpc_bdev_lvol_create_lvstore(&req); 162 } 163 SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME) 164 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_create_lvstore, construct_lvol_store) 165 166 struct rpc_bdev_lvol_rename_lvstore { 167 char *old_name; 168 char *new_name; 169 }; 170 171 static void 172 free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req) 173 { 174 free(req->old_name); 175 free(req->new_name); 176 } 177 178 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = { 179 {"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string}, 180 {"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string}, 181 }; 182 183 static void 184 rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno) 185 { 186 struct spdk_json_write_ctx *w; 187 struct spdk_jsonrpc_request *request = cb_arg; 188 189 if (lvserrno != 0) { 190 goto invalid; 191 } 192 193 w = spdk_jsonrpc_begin_result(request); 194 spdk_json_write_bool(w, true); 195 spdk_jsonrpc_end_result(request, w); 196 return; 197 198 invalid: 199 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 200 spdk_strerror(-lvserrno)); 201 } 202 203 static void 204 rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request, 205 const struct spdk_json_val *params) 206 { 207 struct rpc_bdev_lvol_rename_lvstore req = {}; 208 struct spdk_lvol_store *lvs; 209 210 if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders, 211 SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders), 212 &req)) { 213 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 214 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 215 "spdk_json_decode_object failed"); 216 goto cleanup; 217 } 218 219 lvs = vbdev_get_lvol_store_by_name(req.old_name); 220 if (lvs == NULL) { 221 SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n"); 222 spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name); 223 goto cleanup; 224 } 225 226 vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request); 227 228 cleanup: 229 free_rpc_bdev_lvol_rename_lvstore(&req); 230 } 231 SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME) 232 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_rename_lvstore, rename_lvol_store) 233 234 struct rpc_bdev_lvol_delete_lvstore { 235 char *uuid; 236 char *lvs_name; 237 }; 238 239 static void 240 free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req) 241 { 242 free(req->uuid); 243 free(req->lvs_name); 244 } 245 246 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = { 247 {"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true}, 248 {"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true}, 249 }; 250 251 static void 252 rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno) 253 { 254 struct spdk_json_write_ctx *w; 255 struct spdk_jsonrpc_request *request = cb_arg; 256 257 if (lvserrno != 0) { 258 goto invalid; 259 } 260 261 w = spdk_jsonrpc_begin_result(request); 262 spdk_json_write_bool(w, true); 263 spdk_jsonrpc_end_result(request, w); 264 return; 265 266 invalid: 267 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 268 spdk_strerror(-lvserrno)); 269 } 270 271 static void 272 rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request, 273 const struct spdk_json_val *params) 274 { 275 struct rpc_bdev_lvol_delete_lvstore req = {}; 276 struct spdk_lvol_store *lvs = NULL; 277 int rc; 278 279 if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders, 280 SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders), 281 &req)) { 282 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 283 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 284 "spdk_json_decode_object failed"); 285 goto cleanup; 286 } 287 288 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 289 if (rc != 0) { 290 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 291 goto cleanup; 292 } 293 294 vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request); 295 296 cleanup: 297 free_rpc_bdev_lvol_delete_lvstore(&req); 298 } 299 SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME) 300 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_delete_lvstore, destroy_lvol_store) 301 302 struct rpc_bdev_lvol_create { 303 char *uuid; 304 char *lvs_name; 305 char *lvol_name; 306 uint64_t size; 307 bool thin_provision; 308 char *clear_method; 309 }; 310 311 static void 312 free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req) 313 { 314 free(req->uuid); 315 free(req->lvs_name); 316 free(req->lvol_name); 317 free(req->clear_method); 318 } 319 320 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = { 321 {"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true}, 322 {"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true}, 323 {"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string}, 324 {"size", offsetof(struct rpc_bdev_lvol_create, size), spdk_json_decode_uint64}, 325 {"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true}, 326 {"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true}, 327 }; 328 329 static void 330 rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 331 { 332 struct spdk_json_write_ctx *w; 333 struct spdk_jsonrpc_request *request = cb_arg; 334 335 if (lvolerrno != 0) { 336 goto invalid; 337 } 338 339 w = spdk_jsonrpc_begin_result(request); 340 spdk_json_write_string(w, lvol->unique_id); 341 spdk_jsonrpc_end_result(request, w); 342 return; 343 344 invalid: 345 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 346 spdk_strerror(-lvolerrno)); 347 } 348 349 static void 350 rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request, 351 const struct spdk_json_val *params) 352 { 353 struct rpc_bdev_lvol_create req = {}; 354 enum lvol_clear_method clear_method; 355 int rc = 0; 356 struct spdk_lvol_store *lvs = NULL; 357 358 SPDK_INFOLOG(lvol_rpc, "Creating blob\n"); 359 360 if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders, 361 SPDK_COUNTOF(rpc_bdev_lvol_create_decoders), 362 &req)) { 363 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 364 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 365 "spdk_json_decode_object failed"); 366 goto cleanup; 367 } 368 369 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 370 if (rc != 0) { 371 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 372 goto cleanup; 373 } 374 375 if (req.clear_method != NULL) { 376 if (!strcasecmp(req.clear_method, "none")) { 377 clear_method = LVOL_CLEAR_WITH_NONE; 378 } else if (!strcasecmp(req.clear_method, "unmap")) { 379 clear_method = LVOL_CLEAR_WITH_UNMAP; 380 } else if (!strcasecmp(req.clear_method, "write_zeroes")) { 381 clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES; 382 } else { 383 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option"); 384 goto cleanup; 385 } 386 } else { 387 clear_method = LVOL_CLEAR_WITH_DEFAULT; 388 } 389 390 rc = vbdev_lvol_create(lvs, req.lvol_name, req.size, req.thin_provision, 391 clear_method, rpc_bdev_lvol_create_cb, request); 392 if (rc < 0) { 393 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 394 goto cleanup; 395 } 396 397 cleanup: 398 free_rpc_bdev_lvol_create(&req); 399 } 400 401 SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME) 402 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_create, construct_lvol_bdev) 403 404 struct rpc_bdev_lvol_snapshot { 405 char *lvol_name; 406 char *snapshot_name; 407 }; 408 409 static void 410 free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req) 411 { 412 free(req->lvol_name); 413 free(req->snapshot_name); 414 } 415 416 static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = { 417 {"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string}, 418 {"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string}, 419 }; 420 421 static void 422 rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 423 { 424 struct spdk_json_write_ctx *w; 425 struct spdk_jsonrpc_request *request = cb_arg; 426 427 if (lvolerrno != 0) { 428 goto invalid; 429 } 430 431 w = spdk_jsonrpc_begin_result(request); 432 spdk_json_write_string(w, lvol->unique_id); 433 spdk_jsonrpc_end_result(request, w); 434 return; 435 436 invalid: 437 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 438 spdk_strerror(-lvolerrno)); 439 } 440 441 static void 442 rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request, 443 const struct spdk_json_val *params) 444 { 445 struct rpc_bdev_lvol_snapshot req = {}; 446 struct spdk_bdev *bdev; 447 struct spdk_lvol *lvol; 448 449 SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n"); 450 451 if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders, 452 SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders), 453 &req)) { 454 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 455 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 456 "spdk_json_decode_object failed"); 457 goto cleanup; 458 } 459 460 bdev = spdk_bdev_get_by_name(req.lvol_name); 461 if (bdev == NULL) { 462 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name); 463 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 464 goto cleanup; 465 } 466 467 lvol = vbdev_lvol_get_from_bdev(bdev); 468 if (lvol == NULL) { 469 SPDK_ERRLOG("lvol does not exist\n"); 470 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 471 goto cleanup; 472 } 473 474 vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request); 475 476 cleanup: 477 free_rpc_bdev_lvol_snapshot(&req); 478 } 479 480 SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME) 481 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_snapshot, snapshot_lvol_bdev) 482 483 struct rpc_bdev_lvol_clone { 484 char *snapshot_name; 485 char *clone_name; 486 }; 487 488 static void 489 free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req) 490 { 491 free(req->snapshot_name); 492 free(req->clone_name); 493 } 494 495 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = { 496 {"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string}, 497 {"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true}, 498 }; 499 500 static void 501 rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 502 { 503 struct spdk_json_write_ctx *w; 504 struct spdk_jsonrpc_request *request = cb_arg; 505 506 if (lvolerrno != 0) { 507 goto invalid; 508 } 509 510 w = spdk_jsonrpc_begin_result(request); 511 spdk_json_write_string(w, lvol->unique_id); 512 spdk_jsonrpc_end_result(request, w); 513 return; 514 515 invalid: 516 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 517 spdk_strerror(-lvolerrno)); 518 } 519 520 static void 521 rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request, 522 const struct spdk_json_val *params) 523 { 524 struct rpc_bdev_lvol_clone req = {}; 525 struct spdk_bdev *bdev; 526 struct spdk_lvol *lvol; 527 528 SPDK_INFOLOG(lvol_rpc, "Cloning blob\n"); 529 530 if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders, 531 SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders), 532 &req)) { 533 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 534 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 535 "spdk_json_decode_object failed"); 536 goto cleanup; 537 } 538 539 bdev = spdk_bdev_get_by_name(req.snapshot_name); 540 if (bdev == NULL) { 541 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name); 542 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 543 goto cleanup; 544 } 545 546 lvol = vbdev_lvol_get_from_bdev(bdev); 547 if (lvol == NULL) { 548 SPDK_ERRLOG("lvol does not exist\n"); 549 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 550 goto cleanup; 551 } 552 553 vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request); 554 555 cleanup: 556 free_rpc_bdev_lvol_clone(&req); 557 } 558 559 SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME) 560 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_clone, clone_lvol_bdev) 561 562 struct rpc_bdev_lvol_rename { 563 char *old_name; 564 char *new_name; 565 }; 566 567 static void 568 free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req) 569 { 570 free(req->old_name); 571 free(req->new_name); 572 } 573 574 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = { 575 {"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string}, 576 {"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string}, 577 }; 578 579 static void 580 rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno) 581 { 582 struct spdk_json_write_ctx *w; 583 struct spdk_jsonrpc_request *request = cb_arg; 584 585 if (lvolerrno != 0) { 586 goto invalid; 587 } 588 589 w = spdk_jsonrpc_begin_result(request); 590 spdk_json_write_bool(w, true); 591 spdk_jsonrpc_end_result(request, w); 592 return; 593 594 invalid: 595 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 596 spdk_strerror(-lvolerrno)); 597 } 598 599 static void 600 rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request, 601 const struct spdk_json_val *params) 602 { 603 struct rpc_bdev_lvol_rename req = {}; 604 struct spdk_bdev *bdev; 605 struct spdk_lvol *lvol; 606 607 SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n"); 608 609 if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders, 610 SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders), 611 &req)) { 612 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 613 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 614 "spdk_json_decode_object failed"); 615 goto cleanup; 616 } 617 618 bdev = spdk_bdev_get_by_name(req.old_name); 619 if (bdev == NULL) { 620 SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name); 621 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 622 goto cleanup; 623 } 624 625 lvol = vbdev_lvol_get_from_bdev(bdev); 626 if (lvol == NULL) { 627 SPDK_ERRLOG("lvol does not exist\n"); 628 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 629 goto cleanup; 630 } 631 632 vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request); 633 634 cleanup: 635 free_rpc_bdev_lvol_rename(&req); 636 } 637 638 SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME) 639 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_rename, rename_lvol_bdev) 640 641 struct rpc_bdev_lvol_inflate { 642 char *name; 643 }; 644 645 static void 646 free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req) 647 { 648 free(req->name); 649 } 650 651 static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = { 652 {"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string}, 653 }; 654 655 static void 656 rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno) 657 { 658 struct spdk_json_write_ctx *w; 659 struct spdk_jsonrpc_request *request = cb_arg; 660 661 if (lvolerrno != 0) { 662 goto invalid; 663 } 664 665 w = spdk_jsonrpc_begin_result(request); 666 spdk_json_write_bool(w, true); 667 spdk_jsonrpc_end_result(request, w); 668 return; 669 670 invalid: 671 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 672 spdk_strerror(-lvolerrno)); 673 } 674 675 static void 676 rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request, 677 const struct spdk_json_val *params) 678 { 679 struct rpc_bdev_lvol_inflate req = {}; 680 struct spdk_bdev *bdev; 681 struct spdk_lvol *lvol; 682 683 SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n"); 684 685 if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders, 686 SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders), 687 &req)) { 688 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 689 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 690 "spdk_json_decode_object failed"); 691 goto cleanup; 692 } 693 694 bdev = spdk_bdev_get_by_name(req.name); 695 if (bdev == NULL) { 696 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 697 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 698 goto cleanup; 699 } 700 701 lvol = vbdev_lvol_get_from_bdev(bdev); 702 if (lvol == NULL) { 703 SPDK_ERRLOG("lvol does not exist\n"); 704 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 705 goto cleanup; 706 } 707 708 spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request); 709 710 cleanup: 711 free_rpc_bdev_lvol_inflate(&req); 712 } 713 714 SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME) 715 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_inflate, inflate_lvol_bdev) 716 717 static void 718 rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request, 719 const struct spdk_json_val *params) 720 { 721 struct rpc_bdev_lvol_inflate req = {}; 722 struct spdk_bdev *bdev; 723 struct spdk_lvol *lvol; 724 725 SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n"); 726 727 if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders, 728 SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders), 729 &req)) { 730 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 731 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 732 "spdk_json_decode_object failed"); 733 goto cleanup; 734 } 735 736 bdev = spdk_bdev_get_by_name(req.name); 737 if (bdev == NULL) { 738 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 739 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 740 goto cleanup; 741 } 742 743 lvol = vbdev_lvol_get_from_bdev(bdev); 744 if (lvol == NULL) { 745 SPDK_ERRLOG("lvol does not exist\n"); 746 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 747 goto cleanup; 748 } 749 750 spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request); 751 752 cleanup: 753 free_rpc_bdev_lvol_inflate(&req); 754 } 755 756 SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME) 757 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_decouple_parent, decouple_parent_lvol_bdev) 758 759 struct rpc_bdev_lvol_resize { 760 char *name; 761 uint64_t size; 762 }; 763 764 static void 765 free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req) 766 { 767 free(req->name); 768 } 769 770 static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = { 771 {"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string}, 772 {"size", offsetof(struct rpc_bdev_lvol_resize, size), spdk_json_decode_uint64}, 773 }; 774 775 static void 776 rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno) 777 { 778 struct spdk_json_write_ctx *w; 779 struct spdk_jsonrpc_request *request = cb_arg; 780 781 if (lvolerrno != 0) { 782 goto invalid; 783 } 784 785 w = spdk_jsonrpc_begin_result(request); 786 spdk_json_write_bool(w, true); 787 spdk_jsonrpc_end_result(request, w); 788 return; 789 790 invalid: 791 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 792 spdk_strerror(-lvolerrno)); 793 } 794 795 static void 796 rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request, 797 const struct spdk_json_val *params) 798 { 799 struct rpc_bdev_lvol_resize req = {}; 800 struct spdk_bdev *bdev; 801 struct spdk_lvol *lvol; 802 803 SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n"); 804 805 if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders, 806 SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders), 807 &req)) { 808 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 809 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 810 "spdk_json_decode_object failed"); 811 goto cleanup; 812 } 813 814 bdev = spdk_bdev_get_by_name(req.name); 815 if (bdev == NULL) { 816 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 817 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 818 goto cleanup; 819 } 820 821 lvol = vbdev_lvol_get_from_bdev(bdev); 822 if (lvol == NULL) { 823 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 824 goto cleanup; 825 } 826 827 vbdev_lvol_resize(lvol, req.size, rpc_bdev_lvol_resize_cb, request); 828 829 cleanup: 830 free_rpc_bdev_lvol_resize(&req); 831 } 832 833 SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME) 834 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_resize, resize_lvol_bdev) 835 836 struct rpc_set_ro_lvol_bdev { 837 char *name; 838 }; 839 840 static void 841 free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req) 842 { 843 free(req->name); 844 } 845 846 static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = { 847 {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string}, 848 }; 849 850 static void 851 rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno) 852 { 853 struct spdk_json_write_ctx *w; 854 struct spdk_jsonrpc_request *request = cb_arg; 855 856 if (lvolerrno != 0) { 857 goto invalid; 858 } 859 860 w = spdk_jsonrpc_begin_result(request); 861 spdk_json_write_bool(w, true); 862 spdk_jsonrpc_end_result(request, w); 863 return; 864 865 invalid: 866 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 867 spdk_strerror(-lvolerrno)); 868 } 869 870 static void 871 rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request, 872 const struct spdk_json_val *params) 873 { 874 struct rpc_set_ro_lvol_bdev req = {}; 875 struct spdk_bdev *bdev; 876 struct spdk_lvol *lvol; 877 878 SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n"); 879 880 if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders, 881 SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders), 882 &req)) { 883 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 884 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 885 "spdk_json_decode_object failed"); 886 goto cleanup; 887 } 888 889 if (req.name == NULL) { 890 SPDK_ERRLOG("missing name param\n"); 891 spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter"); 892 goto cleanup; 893 } 894 895 bdev = spdk_bdev_get_by_name(req.name); 896 if (bdev == NULL) { 897 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 898 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 899 goto cleanup; 900 } 901 902 lvol = vbdev_lvol_get_from_bdev(bdev); 903 if (lvol == NULL) { 904 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 905 goto cleanup; 906 } 907 908 vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request); 909 910 cleanup: 911 free_rpc_set_ro_lvol_bdev(&req); 912 } 913 914 SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME) 915 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_set_read_only, set_read_only_lvol_bdev) 916 917 struct rpc_bdev_lvol_delete { 918 char *name; 919 }; 920 921 static void 922 free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req) 923 { 924 free(req->name); 925 } 926 927 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = { 928 {"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string}, 929 }; 930 931 static void 932 rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno) 933 { 934 struct spdk_json_write_ctx *w; 935 struct spdk_jsonrpc_request *request = cb_arg; 936 937 if (lvolerrno != 0) { 938 goto invalid; 939 } 940 941 w = spdk_jsonrpc_begin_result(request); 942 spdk_json_write_bool(w, true); 943 spdk_jsonrpc_end_result(request, w); 944 return; 945 946 invalid: 947 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 948 spdk_strerror(-lvolerrno)); 949 } 950 951 static void 952 rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request, 953 const struct spdk_json_val *params) 954 { 955 struct rpc_bdev_lvol_delete req = {}; 956 struct spdk_bdev *bdev; 957 struct spdk_lvol *lvol; 958 959 if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders, 960 SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders), 961 &req)) { 962 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 963 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 964 "spdk_json_decode_object failed"); 965 goto cleanup; 966 } 967 968 bdev = spdk_bdev_get_by_name(req.name); 969 if (bdev == NULL) { 970 SPDK_ERRLOG("no bdev for provided name %s\n", req.name); 971 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 972 goto cleanup; 973 } 974 975 lvol = vbdev_lvol_get_from_bdev(bdev); 976 if (lvol == NULL) { 977 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 978 goto cleanup; 979 } 980 981 vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request); 982 983 cleanup: 984 free_rpc_bdev_lvol_delete(&req); 985 } 986 987 SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME) 988 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_delete, destroy_lvol_bdev) 989 990 struct rpc_bdev_lvol_get_lvstores { 991 char *uuid; 992 char *lvs_name; 993 }; 994 995 static void 996 free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req) 997 { 998 free(req->uuid); 999 free(req->lvs_name); 1000 } 1001 1002 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = { 1003 {"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true}, 1004 {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true}, 1005 }; 1006 1007 static void 1008 rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev) 1009 { 1010 struct spdk_blob_store *bs; 1011 uint64_t cluster_size; 1012 char uuid[SPDK_UUID_STRING_LEN]; 1013 1014 bs = lvs_bdev->lvs->blobstore; 1015 cluster_size = spdk_bs_get_cluster_size(bs); 1016 1017 spdk_json_write_object_begin(w); 1018 1019 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &lvs_bdev->lvs->uuid); 1020 spdk_json_write_named_string(w, "uuid", uuid); 1021 1022 spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name); 1023 1024 spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev)); 1025 1026 spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs)); 1027 1028 spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs)); 1029 1030 spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs)); 1031 1032 spdk_json_write_named_uint64(w, "cluster_size", cluster_size); 1033 1034 spdk_json_write_object_end(w); 1035 } 1036 1037 static void 1038 rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request, 1039 const struct spdk_json_val *params) 1040 { 1041 struct rpc_bdev_lvol_get_lvstores req = {}; 1042 struct spdk_json_write_ctx *w; 1043 struct lvol_store_bdev *lvs_bdev = NULL; 1044 struct spdk_lvol_store *lvs = NULL; 1045 int rc; 1046 1047 if (params != NULL) { 1048 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders, 1049 SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders), 1050 &req)) { 1051 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n"); 1052 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1053 "spdk_json_decode_object failed"); 1054 goto cleanup; 1055 } 1056 1057 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs); 1058 if (rc != 0) { 1059 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1060 goto cleanup; 1061 } 1062 1063 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs); 1064 if (lvs_bdev == NULL) { 1065 spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV)); 1066 goto cleanup; 1067 } 1068 } 1069 1070 w = spdk_jsonrpc_begin_result(request); 1071 spdk_json_write_array_begin(w); 1072 1073 if (lvs_bdev != NULL) { 1074 rpc_dump_lvol_store_info(w, lvs_bdev); 1075 } else { 1076 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL; 1077 lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) { 1078 rpc_dump_lvol_store_info(w, lvs_bdev); 1079 } 1080 } 1081 spdk_json_write_array_end(w); 1082 1083 spdk_jsonrpc_end_result(request, w); 1084 1085 cleanup: 1086 free_rpc_bdev_lvol_get_lvstores(&req); 1087 } 1088 1089 SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME) 1090 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores) 1091