LCOV - code coverage report
Current view: top level - module/bdev/lvol - vbdev_lvol_rpc.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 769 0.0 %
Date: 2024-07-15 15:03:05 Functions: 0 79 0.0 %

          Line data    Source code
       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           0 : SPDK_LOG_REGISTER_COMPONENT(lvol_rpc)
      15             : 
      16             : struct rpc_shallow_copy_status {
      17             :         uint32_t                                operation_id;
      18             :         /*
      19             :          * 0 means ongoing or successfully completed operation
      20             :          * a negative value is the -errno of an aborted operation
      21             :          */
      22             :         int                                     result;
      23             :         uint64_t                                copied_clusters;
      24             :         uint64_t                                total_clusters;
      25             :         LIST_ENTRY(rpc_shallow_copy_status)     link;
      26             : };
      27             : 
      28             : static uint32_t g_shallow_copy_count = 0;
      29             : static LIST_HEAD(, rpc_shallow_copy_status) g_shallow_copy_status_list = LIST_HEAD_INITIALIZER(
      30             :                         &g_shallow_copy_status_list);
      31             : 
      32             : struct rpc_bdev_lvol_create_lvstore {
      33             :         char *lvs_name;
      34             :         char *bdev_name;
      35             :         uint32_t cluster_sz;
      36             :         char *clear_method;
      37             :         uint32_t num_md_pages_per_cluster_ratio;
      38             : };
      39             : 
      40             : static int
      41           0 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
      42             :                                       struct spdk_lvol_store **lvs)
      43             : {
      44           0 :         if ((uuid == NULL && lvs_name == NULL)) {
      45           0 :                 SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
      46           0 :                 return -EINVAL;
      47           0 :         } else if ((uuid && lvs_name)) {
      48           0 :                 SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid,
      49             :                              lvs_name);
      50           0 :                 return -EINVAL;
      51           0 :         } else if (uuid) {
      52           0 :                 *lvs = vbdev_get_lvol_store_by_uuid(uuid);
      53             : 
      54           0 :                 if (*lvs == NULL) {
      55           0 :                         SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
      56           0 :                         return -ENODEV;
      57             :                 }
      58           0 :         } else if (lvs_name) {
      59             : 
      60           0 :                 *lvs = vbdev_get_lvol_store_by_name(lvs_name);
      61             : 
      62           0 :                 if (*lvs == NULL) {
      63           0 :                         SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
      64           0 :                         return -ENODEV;
      65             :                 }
      66             :         }
      67           0 :         return 0;
      68             : }
      69             : 
      70             : static void
      71           0 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
      72             : {
      73           0 :         free(req->bdev_name);
      74           0 :         free(req->lvs_name);
      75           0 :         free(req->clear_method);
      76           0 : }
      77             : 
      78             : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = {
      79             :         {"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string},
      80             :         {"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true},
      81             :         {"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string},
      82             :         {"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true},
      83             :         {"num_md_pages_per_cluster_ratio", offsetof(struct rpc_bdev_lvol_create_lvstore, num_md_pages_per_cluster_ratio), spdk_json_decode_uint32, true},
      84             : };
      85             : 
      86             : static void
      87           0 : rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
      88             : {
      89             :         struct spdk_json_write_ctx *w;
      90           0 :         struct spdk_jsonrpc_request *request = cb_arg;
      91             : 
      92           0 :         if (lvserrno != 0) {
      93           0 :                 goto invalid;
      94             :         }
      95             : 
      96           0 :         w = spdk_jsonrpc_begin_result(request);
      97           0 :         spdk_json_write_uuid(w, &lvol_store->uuid);
      98           0 :         spdk_jsonrpc_end_result(request, w);
      99           0 :         return;
     100             : 
     101           0 : invalid:
     102           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     103             :                                          spdk_strerror(-lvserrno));
     104             : }
     105             : 
     106             : static void
     107           0 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
     108             :                              const struct spdk_json_val *params)
     109             : {
     110           0 :         struct rpc_bdev_lvol_create_lvstore req = {};
     111           0 :         int rc = 0;
     112             :         enum lvs_clear_method clear_method;
     113             : 
     114           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
     115             :                                     SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
     116             :                                     &req)) {
     117           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     118           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     119             :                                                  "spdk_json_decode_object failed");
     120           0 :                 goto cleanup;
     121             :         }
     122             : 
     123           0 :         if (req.clear_method != NULL) {
     124           0 :                 if (!strcasecmp(req.clear_method, "none")) {
     125           0 :                         clear_method = LVS_CLEAR_WITH_NONE;
     126           0 :                 } else if (!strcasecmp(req.clear_method, "unmap")) {
     127           0 :                         clear_method = LVS_CLEAR_WITH_UNMAP;
     128           0 :                 } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
     129           0 :                         clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
     130             :                 } else {
     131           0 :                         spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
     132           0 :                         goto cleanup;
     133             :                 }
     134             :         } else {
     135           0 :                 clear_method = LVS_CLEAR_WITH_UNMAP;
     136             :         }
     137             : 
     138           0 :         rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
     139             :                               req.num_md_pages_per_cluster_ratio, rpc_lvol_store_construct_cb, request);
     140           0 :         if (rc < 0) {
     141           0 :                 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
     142           0 :                 goto cleanup;
     143             :         }
     144           0 :         free_rpc_bdev_lvol_create_lvstore(&req);
     145             : 
     146           0 :         return;
     147             : 
     148           0 : cleanup:
     149           0 :         free_rpc_bdev_lvol_create_lvstore(&req);
     150             : }
     151           0 : SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME)
     152             : 
     153             : struct rpc_bdev_lvol_rename_lvstore {
     154             :         char *old_name;
     155             :         char *new_name;
     156             : };
     157             : 
     158             : static void
     159           0 : free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
     160             : {
     161           0 :         free(req->old_name);
     162           0 :         free(req->new_name);
     163           0 : }
     164             : 
     165             : static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = {
     166             :         {"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string},
     167             :         {"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string},
     168             : };
     169             : 
     170             : static void
     171           0 : rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
     172             : {
     173           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     174             : 
     175           0 :         if (lvserrno != 0) {
     176           0 :                 goto invalid;
     177             :         }
     178             : 
     179           0 :         spdk_jsonrpc_send_bool_response(request, true);
     180           0 :         return;
     181             : 
     182           0 : invalid:
     183           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     184             :                                          spdk_strerror(-lvserrno));
     185             : }
     186             : 
     187             : static void
     188           0 : rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
     189             :                              const struct spdk_json_val *params)
     190             : {
     191           0 :         struct rpc_bdev_lvol_rename_lvstore req = {};
     192             :         struct spdk_lvol_store *lvs;
     193             : 
     194           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders,
     195             :                                     SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders),
     196             :                                     &req)) {
     197           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     198           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     199             :                                                  "spdk_json_decode_object failed");
     200           0 :                 goto cleanup;
     201             :         }
     202             : 
     203           0 :         lvs = vbdev_get_lvol_store_by_name(req.old_name);
     204           0 :         if (lvs == NULL) {
     205           0 :                 SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
     206           0 :                 spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
     207           0 :                 goto cleanup;
     208             :         }
     209             : 
     210           0 :         vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
     211             : 
     212           0 : cleanup:
     213           0 :         free_rpc_bdev_lvol_rename_lvstore(&req);
     214           0 : }
     215           0 : SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME)
     216             : 
     217             : struct rpc_bdev_lvol_delete_lvstore {
     218             :         char *uuid;
     219             :         char *lvs_name;
     220             : };
     221             : 
     222             : static void
     223           0 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
     224             : {
     225           0 :         free(req->uuid);
     226           0 :         free(req->lvs_name);
     227           0 : }
     228             : 
     229             : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = {
     230             :         {"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true},
     231             :         {"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true},
     232             : };
     233             : 
     234             : static void
     235           0 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
     236             : {
     237           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     238             : 
     239           0 :         if (lvserrno != 0) {
     240           0 :                 goto invalid;
     241             :         }
     242             : 
     243           0 :         spdk_jsonrpc_send_bool_response(request, true);
     244           0 :         return;
     245             : 
     246           0 : invalid:
     247           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     248             :                                          spdk_strerror(-lvserrno));
     249             : }
     250             : 
     251             : static void
     252           0 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
     253             :                              const struct spdk_json_val *params)
     254             : {
     255           0 :         struct rpc_bdev_lvol_delete_lvstore req = {};
     256           0 :         struct spdk_lvol_store *lvs = NULL;
     257             :         int rc;
     258             : 
     259           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders,
     260             :                                     SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders),
     261             :                                     &req)) {
     262           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     263           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     264             :                                                  "spdk_json_decode_object failed");
     265           0 :                 goto cleanup;
     266             :         }
     267             : 
     268           0 :         rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
     269           0 :         if (rc != 0) {
     270           0 :                 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
     271           0 :                 goto cleanup;
     272             :         }
     273             : 
     274           0 :         vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
     275             : 
     276           0 : cleanup:
     277           0 :         free_rpc_bdev_lvol_delete_lvstore(&req);
     278           0 : }
     279           0 : SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME)
     280             : 
     281             : struct rpc_bdev_lvol_create {
     282             :         char *uuid;
     283             :         char *lvs_name;
     284             :         char *lvol_name;
     285             :         uint64_t size_in_mib;
     286             :         bool thin_provision;
     287             :         char *clear_method;
     288             : };
     289             : 
     290             : static void
     291           0 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
     292             : {
     293           0 :         free(req->uuid);
     294           0 :         free(req->lvs_name);
     295           0 :         free(req->lvol_name);
     296           0 :         free(req->clear_method);
     297           0 : }
     298             : 
     299             : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
     300             :         {"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
     301             :         {"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
     302             :         {"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
     303             :         {"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64},
     304             :         {"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true},
     305             :         {"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true},
     306             : };
     307             : 
     308             : static void
     309           0 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
     310             : {
     311             :         struct spdk_json_write_ctx *w;
     312           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     313             : 
     314           0 :         if (lvolerrno != 0) {
     315           0 :                 goto invalid;
     316             :         }
     317             : 
     318           0 :         w = spdk_jsonrpc_begin_result(request);
     319           0 :         spdk_json_write_string(w, lvol->unique_id);
     320           0 :         spdk_jsonrpc_end_result(request, w);
     321           0 :         return;
     322             : 
     323           0 : invalid:
     324           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     325             :                                          spdk_strerror(-lvolerrno));
     326             : }
     327             : 
     328             : static void
     329           0 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
     330             :                      const struct spdk_json_val *params)
     331             : {
     332           0 :         struct rpc_bdev_lvol_create req = {};
     333             :         enum lvol_clear_method clear_method;
     334           0 :         int rc = 0;
     335           0 :         struct spdk_lvol_store *lvs = NULL;
     336             : 
     337           0 :         SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
     338             : 
     339           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
     340             :                                     SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
     341             :                                     &req)) {
     342           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     343           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     344             :                                                  "spdk_json_decode_object failed");
     345           0 :                 goto cleanup;
     346             :         }
     347             : 
     348           0 :         rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
     349           0 :         if (rc != 0) {
     350           0 :                 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
     351           0 :                 goto cleanup;
     352             :         }
     353             : 
     354           0 :         if (req.clear_method != NULL) {
     355           0 :                 if (!strcasecmp(req.clear_method, "none")) {
     356           0 :                         clear_method = LVOL_CLEAR_WITH_NONE;
     357           0 :                 } else if (!strcasecmp(req.clear_method, "unmap")) {
     358           0 :                         clear_method = LVOL_CLEAR_WITH_UNMAP;
     359           0 :                 } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
     360           0 :                         clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES;
     361             :                 } else {
     362           0 :                         spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
     363           0 :                         goto cleanup;
     364             :                 }
     365             :         } else {
     366           0 :                 clear_method = LVOL_CLEAR_WITH_DEFAULT;
     367             :         }
     368             : 
     369           0 :         rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
     370           0 :                                req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
     371           0 :         if (rc < 0) {
     372           0 :                 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
     373           0 :                 goto cleanup;
     374             :         }
     375             : 
     376           0 : cleanup:
     377           0 :         free_rpc_bdev_lvol_create(&req);
     378           0 : }
     379             : 
     380           0 : SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME)
     381             : 
     382             : struct rpc_bdev_lvol_snapshot {
     383             :         char *lvol_name;
     384             :         char *snapshot_name;
     385             : };
     386             : 
     387             : static void
     388           0 : free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
     389             : {
     390           0 :         free(req->lvol_name);
     391           0 :         free(req->snapshot_name);
     392           0 : }
     393             : 
     394             : static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = {
     395             :         {"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string},
     396             :         {"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string},
     397             : };
     398             : 
     399             : static void
     400           0 : rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
     401             : {
     402             :         struct spdk_json_write_ctx *w;
     403           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     404             : 
     405           0 :         if (lvolerrno != 0) {
     406           0 :                 goto invalid;
     407             :         }
     408             : 
     409           0 :         w = spdk_jsonrpc_begin_result(request);
     410           0 :         spdk_json_write_string(w, lvol->unique_id);
     411           0 :         spdk_jsonrpc_end_result(request, w);
     412           0 :         return;
     413             : 
     414           0 : invalid:
     415           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     416             :                                          spdk_strerror(-lvolerrno));
     417             : }
     418             : 
     419             : static void
     420           0 : rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
     421             :                        const struct spdk_json_val *params)
     422             : {
     423           0 :         struct rpc_bdev_lvol_snapshot req = {};
     424             :         struct spdk_bdev *bdev;
     425             :         struct spdk_lvol *lvol;
     426             : 
     427           0 :         SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
     428             : 
     429           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders,
     430             :                                     SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders),
     431             :                                     &req)) {
     432           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     433           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     434             :                                                  "spdk_json_decode_object failed");
     435           0 :                 goto cleanup;
     436             :         }
     437             : 
     438           0 :         bdev = spdk_bdev_get_by_name(req.lvol_name);
     439           0 :         if (bdev == NULL) {
     440           0 :                 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name);
     441           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     442           0 :                 goto cleanup;
     443             :         }
     444             : 
     445           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     446           0 :         if (lvol == NULL) {
     447           0 :                 SPDK_ERRLOG("lvol does not exist\n");
     448           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     449           0 :                 goto cleanup;
     450             :         }
     451             : 
     452           0 :         vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
     453             : 
     454           0 : cleanup:
     455           0 :         free_rpc_bdev_lvol_snapshot(&req);
     456           0 : }
     457             : 
     458           0 : SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME)
     459             : 
     460             : struct rpc_bdev_lvol_clone {
     461             :         char *snapshot_name;
     462             :         char *clone_name;
     463             : };
     464             : 
     465             : static void
     466           0 : free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
     467             : {
     468           0 :         free(req->snapshot_name);
     469           0 :         free(req->clone_name);
     470           0 : }
     471             : 
     472             : static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = {
     473             :         {"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string},
     474             :         {"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true},
     475             : };
     476             : 
     477             : static void
     478           0 : rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
     479             : {
     480             :         struct spdk_json_write_ctx *w;
     481           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     482             : 
     483           0 :         if (lvolerrno != 0) {
     484           0 :                 goto invalid;
     485             :         }
     486             : 
     487           0 :         w = spdk_jsonrpc_begin_result(request);
     488           0 :         spdk_json_write_string(w, lvol->unique_id);
     489           0 :         spdk_jsonrpc_end_result(request, w);
     490           0 :         return;
     491             : 
     492           0 : invalid:
     493           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     494             :                                          spdk_strerror(-lvolerrno));
     495             : }
     496             : 
     497             : static void
     498           0 : rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
     499             :                     const struct spdk_json_val *params)
     500             : {
     501           0 :         struct rpc_bdev_lvol_clone req = {};
     502             :         struct spdk_bdev *bdev;
     503             :         struct spdk_lvol *lvol;
     504             : 
     505           0 :         SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
     506             : 
     507           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders,
     508             :                                     SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders),
     509             :                                     &req)) {
     510           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     511           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     512             :                                                  "spdk_json_decode_object failed");
     513           0 :                 goto cleanup;
     514             :         }
     515             : 
     516           0 :         bdev = spdk_bdev_get_by_name(req.snapshot_name);
     517           0 :         if (bdev == NULL) {
     518           0 :                 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name);
     519           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     520           0 :                 goto cleanup;
     521             :         }
     522             : 
     523           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     524           0 :         if (lvol == NULL) {
     525           0 :                 SPDK_ERRLOG("lvol does not exist\n");
     526           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     527           0 :                 goto cleanup;
     528             :         }
     529             : 
     530           0 :         vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
     531             : 
     532           0 : cleanup:
     533           0 :         free_rpc_bdev_lvol_clone(&req);
     534           0 : }
     535             : 
     536           0 : SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME)
     537             : 
     538             : struct rpc_bdev_lvol_clone_bdev {
     539             :         /* name or UUID. Whichever is used, the UUID will be stored in the lvol's metadata. */
     540             :         char *bdev_name;
     541             :         char *lvs_name;
     542             :         char *clone_name;
     543             : };
     544             : 
     545             : static void
     546           0 : free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req)
     547             : {
     548           0 :         free(req->bdev_name);
     549           0 :         free(req->lvs_name);
     550           0 :         free(req->clone_name);
     551           0 : }
     552             : 
     553             : static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_bdev_decoders[] = {
     554             :         {
     555             :                 "bdev", offsetof(struct rpc_bdev_lvol_clone_bdev, bdev_name),
     556             :                 spdk_json_decode_string, false
     557             :         },
     558             :         {
     559             :                 "lvs_name", offsetof(struct rpc_bdev_lvol_clone_bdev, lvs_name),
     560             :                 spdk_json_decode_string, false
     561             :         },
     562             :         {
     563             :                 "clone_name", offsetof(struct rpc_bdev_lvol_clone_bdev, clone_name),
     564             :                 spdk_json_decode_string, false
     565             :         },
     566             : };
     567             : 
     568             : static void
     569           0 : rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
     570             : {
     571           0 :         struct rpc_bdev_lvol_clone_bdev req = {};
     572             :         struct spdk_bdev *bdev;
     573           0 :         struct spdk_lvol_store *lvs = NULL;
     574             :         struct spdk_lvol *lvol;
     575             :         int rc;
     576             : 
     577           0 :         SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n");
     578             : 
     579           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_bdev_decoders,
     580             :                                     SPDK_COUNTOF(rpc_bdev_lvol_clone_bdev_decoders), &req)) {
     581           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     582           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     583             :                                                  "spdk_json_decode_object failed");
     584           0 :                 goto cleanup;
     585             :         }
     586             : 
     587           0 :         rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs);
     588           0 :         if (rc != 0) {
     589           0 :                 SPDK_INFOLOG(lvol_rpc, "lvs_name '%s' not found\n", req.lvs_name);
     590           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     591             :                                                  "lvs does not exist");
     592           0 :                 goto cleanup;
     593             :         }
     594             : 
     595           0 :         bdev = spdk_bdev_get_by_name(req.bdev_name);
     596           0 :         if (bdev == NULL) {
     597           0 :                 SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.bdev_name);
     598           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     599             :                                                  "bdev does not exist");
     600           0 :                 goto cleanup;
     601             :         }
     602             : 
     603           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     604           0 :         if (lvol != NULL && lvol->lvol_store == lvs) {
     605           0 :                 SPDK_INFOLOG(lvol_rpc, "bdev '%s' is an lvol in lvstore '%s\n", req.bdev_name,
     606             :                              req.lvs_name);
     607           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     608             :                                                  "bdev is an lvol in same lvs as clone; "
     609             :                                                  "use bdev_lvol_clone instead");
     610           0 :                 goto cleanup;
     611             :         }
     612             : 
     613           0 :         vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name,
     614             :                                      rpc_bdev_lvol_clone_cb, request);
     615           0 : cleanup:
     616           0 :         free_rpc_bdev_lvol_clone_bdev(&req);
     617           0 : }
     618             : 
     619           0 : SPDK_RPC_REGISTER("bdev_lvol_clone_bdev", rpc_bdev_lvol_clone_bdev, SPDK_RPC_RUNTIME)
     620             : 
     621             : struct rpc_bdev_lvol_rename {
     622             :         char *old_name;
     623             :         char *new_name;
     624             : };
     625             : 
     626             : static void
     627           0 : free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
     628             : {
     629           0 :         free(req->old_name);
     630           0 :         free(req->new_name);
     631           0 : }
     632             : 
     633             : static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = {
     634             :         {"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string},
     635             :         {"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string},
     636             : };
     637             : 
     638             : static void
     639           0 : rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
     640             : {
     641           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     642             : 
     643           0 :         if (lvolerrno != 0) {
     644           0 :                 goto invalid;
     645             :         }
     646             : 
     647           0 :         spdk_jsonrpc_send_bool_response(request, true);
     648           0 :         return;
     649             : 
     650           0 : invalid:
     651           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     652             :                                          spdk_strerror(-lvolerrno));
     653             : }
     654             : 
     655             : static void
     656           0 : rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
     657             :                      const struct spdk_json_val *params)
     658             : {
     659           0 :         struct rpc_bdev_lvol_rename req = {};
     660             :         struct spdk_bdev *bdev;
     661             :         struct spdk_lvol *lvol;
     662             : 
     663           0 :         SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
     664             : 
     665           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders,
     666             :                                     SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders),
     667             :                                     &req)) {
     668           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     669           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     670             :                                                  "spdk_json_decode_object failed");
     671           0 :                 goto cleanup;
     672             :         }
     673             : 
     674           0 :         bdev = spdk_bdev_get_by_name(req.old_name);
     675           0 :         if (bdev == NULL) {
     676           0 :                 SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
     677           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     678           0 :                 goto cleanup;
     679             :         }
     680             : 
     681           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     682           0 :         if (lvol == NULL) {
     683           0 :                 SPDK_ERRLOG("lvol does not exist\n");
     684           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     685           0 :                 goto cleanup;
     686             :         }
     687             : 
     688           0 :         vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
     689             : 
     690           0 : cleanup:
     691           0 :         free_rpc_bdev_lvol_rename(&req);
     692           0 : }
     693             : 
     694           0 : SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
     695             : 
     696             : struct rpc_bdev_lvol_inflate {
     697             :         char *name;
     698             : };
     699             : 
     700             : static void
     701           0 : free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
     702             : {
     703           0 :         free(req->name);
     704           0 : }
     705             : 
     706             : static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = {
     707             :         {"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string},
     708             : };
     709             : 
     710             : static void
     711           0 : rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
     712             : {
     713           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     714             : 
     715           0 :         if (lvolerrno != 0) {
     716           0 :                 goto invalid;
     717             :         }
     718             : 
     719           0 :         spdk_jsonrpc_send_bool_response(request, true);
     720           0 :         return;
     721             : 
     722           0 : invalid:
     723           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     724             :                                          spdk_strerror(-lvolerrno));
     725             : }
     726             : 
     727             : static void
     728           0 : rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
     729             :                       const struct spdk_json_val *params)
     730             : {
     731           0 :         struct rpc_bdev_lvol_inflate req = {};
     732             :         struct spdk_bdev *bdev;
     733             :         struct spdk_lvol *lvol;
     734             : 
     735           0 :         SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
     736             : 
     737           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
     738             :                                     SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
     739             :                                     &req)) {
     740           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     741           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     742             :                                                  "spdk_json_decode_object failed");
     743           0 :                 goto cleanup;
     744             :         }
     745             : 
     746           0 :         bdev = spdk_bdev_get_by_name(req.name);
     747           0 :         if (bdev == NULL) {
     748           0 :                 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
     749           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     750           0 :                 goto cleanup;
     751             :         }
     752             : 
     753           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     754           0 :         if (lvol == NULL) {
     755           0 :                 SPDK_ERRLOG("lvol does not exist\n");
     756           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     757           0 :                 goto cleanup;
     758             :         }
     759             : 
     760           0 :         spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
     761             : 
     762           0 : cleanup:
     763           0 :         free_rpc_bdev_lvol_inflate(&req);
     764           0 : }
     765             : 
     766           0 : SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
     767             : 
     768             : static void
     769           0 : rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
     770             :                               const struct spdk_json_val *params)
     771             : {
     772           0 :         struct rpc_bdev_lvol_inflate req = {};
     773             :         struct spdk_bdev *bdev;
     774             :         struct spdk_lvol *lvol;
     775             : 
     776           0 :         SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
     777             : 
     778           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
     779             :                                     SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
     780             :                                     &req)) {
     781           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     782           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     783             :                                                  "spdk_json_decode_object failed");
     784           0 :                 goto cleanup;
     785             :         }
     786             : 
     787           0 :         bdev = spdk_bdev_get_by_name(req.name);
     788           0 :         if (bdev == NULL) {
     789           0 :                 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
     790           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     791           0 :                 goto cleanup;
     792             :         }
     793             : 
     794           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     795           0 :         if (lvol == NULL) {
     796           0 :                 SPDK_ERRLOG("lvol does not exist\n");
     797           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     798           0 :                 goto cleanup;
     799             :         }
     800             : 
     801           0 :         spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
     802             : 
     803           0 : cleanup:
     804           0 :         free_rpc_bdev_lvol_inflate(&req);
     805           0 : }
     806             : 
     807           0 : SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME)
     808             : 
     809             : struct rpc_bdev_lvol_resize {
     810             :         char *name;
     811             :         uint64_t size_in_mib;
     812             : };
     813             : 
     814             : static void
     815           0 : free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
     816             : {
     817           0 :         free(req->name);
     818           0 : }
     819             : 
     820             : static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
     821             :         {"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
     822             :         {"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64},
     823             : };
     824             : 
     825             : static void
     826           0 : rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
     827             : {
     828           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     829             : 
     830           0 :         if (lvolerrno != 0) {
     831           0 :                 goto invalid;
     832             :         }
     833             : 
     834           0 :         spdk_jsonrpc_send_bool_response(request, true);
     835           0 :         return;
     836             : 
     837           0 : invalid:
     838           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     839             :                                          spdk_strerror(-lvolerrno));
     840             : }
     841             : 
     842             : static void
     843           0 : rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
     844             :                      const struct spdk_json_val *params)
     845             : {
     846           0 :         struct rpc_bdev_lvol_resize req = {};
     847             :         struct spdk_bdev *bdev;
     848             :         struct spdk_lvol *lvol;
     849             : 
     850           0 :         SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
     851             : 
     852           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
     853             :                                     SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
     854             :                                     &req)) {
     855           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     856           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     857             :                                                  "spdk_json_decode_object failed");
     858           0 :                 goto cleanup;
     859             :         }
     860             : 
     861           0 :         bdev = spdk_bdev_get_by_name(req.name);
     862           0 :         if (bdev == NULL) {
     863           0 :                 SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
     864           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     865           0 :                 goto cleanup;
     866             :         }
     867             : 
     868           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     869           0 :         if (lvol == NULL) {
     870           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     871           0 :                 goto cleanup;
     872             :         }
     873             : 
     874             : 
     875           0 :         vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
     876             : 
     877           0 : cleanup:
     878           0 :         free_rpc_bdev_lvol_resize(&req);
     879           0 : }
     880             : 
     881           0 : SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
     882             : 
     883             : struct rpc_set_ro_lvol_bdev {
     884             :         char *name;
     885             : };
     886             : 
     887             : static void
     888           0 : free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
     889             : {
     890           0 :         free(req->name);
     891           0 : }
     892             : 
     893             : static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
     894             :         {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
     895             : };
     896             : 
     897             : static void
     898           0 : rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
     899             : {
     900           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     901             : 
     902           0 :         if (lvolerrno != 0) {
     903           0 :                 goto invalid;
     904             :         }
     905             : 
     906           0 :         spdk_jsonrpc_send_bool_response(request, true);
     907           0 :         return;
     908             : 
     909           0 : invalid:
     910           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     911             :                                          spdk_strerror(-lvolerrno));
     912             : }
     913             : 
     914             : static void
     915           0 : rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
     916             :                             const struct spdk_json_val *params)
     917             : {
     918           0 :         struct rpc_set_ro_lvol_bdev req = {};
     919             :         struct spdk_bdev *bdev;
     920             :         struct spdk_lvol *lvol;
     921             : 
     922           0 :         SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
     923             : 
     924           0 :         if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
     925             :                                     SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
     926             :                                     &req)) {
     927           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
     928           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     929             :                                                  "spdk_json_decode_object failed");
     930           0 :                 goto cleanup;
     931             :         }
     932             : 
     933           0 :         if (req.name == NULL) {
     934           0 :                 SPDK_ERRLOG("missing name param\n");
     935           0 :                 spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
     936           0 :                 goto cleanup;
     937             :         }
     938             : 
     939           0 :         bdev = spdk_bdev_get_by_name(req.name);
     940           0 :         if (bdev == NULL) {
     941           0 :                 SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
     942           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     943           0 :                 goto cleanup;
     944             :         }
     945             : 
     946           0 :         lvol = vbdev_lvol_get_from_bdev(bdev);
     947           0 :         if (lvol == NULL) {
     948           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
     949           0 :                 goto cleanup;
     950             :         }
     951             : 
     952           0 :         vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
     953             : 
     954           0 : cleanup:
     955           0 :         free_rpc_set_ro_lvol_bdev(&req);
     956           0 : }
     957             : 
     958           0 : SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
     959             : 
     960             : struct rpc_bdev_lvol_delete {
     961             :         char *name;
     962             : };
     963             : 
     964             : static void
     965           0 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
     966             : {
     967           0 :         free(req->name);
     968           0 : }
     969             : 
     970             : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
     971             :         {"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
     972             : };
     973             : 
     974             : static void
     975           0 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
     976             : {
     977           0 :         struct spdk_jsonrpc_request *request = cb_arg;
     978             : 
     979           0 :         if (lvolerrno != 0) {
     980           0 :                 goto invalid;
     981             :         }
     982             : 
     983           0 :         spdk_jsonrpc_send_bool_response(request, true);
     984           0 :         return;
     985             : 
     986           0 : invalid:
     987           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     988             :                                          spdk_strerror(-lvolerrno));
     989             : }
     990             : 
     991             : static void
     992           0 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
     993             :                      const struct spdk_json_val *params)
     994             : {
     995           0 :         struct rpc_bdev_lvol_delete req = {};
     996             :         struct spdk_bdev *bdev;
     997             :         struct spdk_lvol *lvol;
     998           0 :         struct spdk_uuid uuid;
     999             :         char *lvs_name, *lvol_name;
    1000             : 
    1001           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
    1002             :                                     SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
    1003             :                                     &req)) {
    1004           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1005           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1006             :                                                  "spdk_json_decode_object failed");
    1007           0 :                 goto cleanup;
    1008             :         }
    1009             : 
    1010             :         /* lvol is not degraded, get lvol via bdev name or alias */
    1011           0 :         bdev = spdk_bdev_get_by_name(req.name);
    1012           0 :         if (bdev != NULL) {
    1013           0 :                 lvol = vbdev_lvol_get_from_bdev(bdev);
    1014           0 :                 if (lvol != NULL) {
    1015           0 :                         goto done;
    1016             :                 }
    1017             :         }
    1018             : 
    1019             :         /* lvol is degraded, get lvol via UUID */
    1020           0 :         if (spdk_uuid_parse(&uuid, req.name) == 0) {
    1021           0 :                 lvol = spdk_lvol_get_by_uuid(&uuid);
    1022           0 :                 if (lvol != NULL) {
    1023           0 :                         goto done;
    1024             :                 }
    1025             :         }
    1026             : 
    1027             :         /* lvol is degraded, get lvol via lvs_name/lvol_name */
    1028           0 :         lvol_name = strchr(req.name, '/');
    1029           0 :         if (lvol_name != NULL) {
    1030           0 :                 *lvol_name = '\0';
    1031           0 :                 lvol_name++;
    1032           0 :                 lvs_name = req.name;
    1033           0 :                 lvol = spdk_lvol_get_by_names(lvs_name, lvol_name);
    1034           0 :                 if (lvol != NULL) {
    1035           0 :                         goto done;
    1036             :                 }
    1037             :         }
    1038             : 
    1039             :         /* Could not find lvol, degraded or not. */
    1040           0 :         spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1041           0 :         goto cleanup;
    1042             : 
    1043           0 : done:
    1044           0 :         vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
    1045             : 
    1046           0 : cleanup:
    1047           0 :         free_rpc_bdev_lvol_delete(&req);
    1048           0 : }
    1049             : 
    1050           0 : SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
    1051             : 
    1052             : struct rpc_bdev_lvol_get_lvstores {
    1053             :         char *uuid;
    1054             :         char *lvs_name;
    1055             : };
    1056             : 
    1057             : static void
    1058           0 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
    1059             : {
    1060           0 :         free(req->uuid);
    1061           0 :         free(req->lvs_name);
    1062           0 : }
    1063             : 
    1064             : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
    1065             :         {"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
    1066             :         {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
    1067             : };
    1068             : 
    1069             : static void
    1070           0 : rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
    1071             : {
    1072             :         struct spdk_blob_store *bs;
    1073             :         uint64_t cluster_size;
    1074             : 
    1075           0 :         bs = lvs_bdev->lvs->blobstore;
    1076           0 :         cluster_size = spdk_bs_get_cluster_size(bs);
    1077             : 
    1078           0 :         spdk_json_write_object_begin(w);
    1079             : 
    1080           0 :         spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
    1081           0 :         spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
    1082           0 :         spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
    1083           0 :         spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
    1084           0 :         spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
    1085           0 :         spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
    1086           0 :         spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
    1087             : 
    1088           0 :         spdk_json_write_object_end(w);
    1089           0 : }
    1090             : 
    1091             : static void
    1092           0 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
    1093             :                            const struct spdk_json_val *params)
    1094             : {
    1095           0 :         struct rpc_bdev_lvol_get_lvstores req = {};
    1096             :         struct spdk_json_write_ctx *w;
    1097           0 :         struct lvol_store_bdev *lvs_bdev = NULL;
    1098           0 :         struct spdk_lvol_store *lvs = NULL;
    1099             :         int rc;
    1100             : 
    1101           0 :         if (params != NULL) {
    1102           0 :                 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
    1103             :                                             SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
    1104             :                                             &req)) {
    1105           0 :                         SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1106           0 :                         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1107             :                                                          "spdk_json_decode_object failed");
    1108           0 :                         goto cleanup;
    1109             :                 }
    1110             : 
    1111           0 :                 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
    1112           0 :                 if (rc != 0) {
    1113           0 :                         spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
    1114           0 :                         goto cleanup;
    1115             :                 }
    1116             : 
    1117           0 :                 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
    1118           0 :                 if (lvs_bdev == NULL) {
    1119           0 :                         spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
    1120           0 :                         goto cleanup;
    1121             :                 }
    1122             :         }
    1123             : 
    1124           0 :         w = spdk_jsonrpc_begin_result(request);
    1125           0 :         spdk_json_write_array_begin(w);
    1126             : 
    1127           0 :         if (lvs_bdev != NULL) {
    1128           0 :                 rpc_dump_lvol_store_info(w, lvs_bdev);
    1129             :         } else {
    1130           0 :                 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
    1131           0 :                      lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
    1132           0 :                         rpc_dump_lvol_store_info(w, lvs_bdev);
    1133             :                 }
    1134             :         }
    1135           0 :         spdk_json_write_array_end(w);
    1136             : 
    1137           0 :         spdk_jsonrpc_end_result(request, w);
    1138             : 
    1139           0 : cleanup:
    1140           0 :         free_rpc_bdev_lvol_get_lvstores(&req);
    1141           0 : }
    1142             : 
    1143           0 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
    1144           0 : SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
    1145             : 
    1146             : struct rpc_bdev_lvol_get_lvols {
    1147             :         char *lvs_uuid;
    1148             :         char *lvs_name;
    1149             : };
    1150             : 
    1151             : static void
    1152           0 : free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
    1153             : {
    1154           0 :         free(req->lvs_uuid);
    1155           0 :         free(req->lvs_name);
    1156           0 : }
    1157             : 
    1158             : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = {
    1159             :         {"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true},
    1160             :         {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true},
    1161             : };
    1162             : 
    1163             : static void
    1164           0 : rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
    1165             : {
    1166           0 :         struct spdk_lvol_store *lvs = lvol->lvol_store;
    1167             : 
    1168           0 :         spdk_json_write_object_begin(w);
    1169             : 
    1170           0 :         spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
    1171           0 :         spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
    1172           0 :         spdk_json_write_named_string(w, "name", lvol->name);
    1173           0 :         spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
    1174           0 :         spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
    1175           0 :         spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
    1176           0 :         spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
    1177           0 :         spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
    1178             : 
    1179           0 :         spdk_json_write_named_object_begin(w, "lvs");
    1180           0 :         spdk_json_write_named_string(w, "name", lvs->name);
    1181           0 :         spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
    1182           0 :         spdk_json_write_object_end(w);
    1183             : 
    1184           0 :         spdk_json_write_object_end(w);
    1185           0 : }
    1186             : 
    1187             : static void
    1188           0 : rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
    1189             : {
    1190           0 :         struct spdk_lvol_store *lvs = lvs_bdev->lvs;
    1191             :         struct spdk_lvol *lvol;
    1192             : 
    1193           0 :         TAILQ_FOREACH(lvol, &lvs->lvols, link) {
    1194           0 :                 rpc_dump_lvol(w, lvol);
    1195             :         }
    1196           0 : }
    1197             : 
    1198             : static void
    1199           0 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
    1200             : {
    1201           0 :         struct rpc_bdev_lvol_get_lvols req = {};
    1202             :         struct spdk_json_write_ctx *w;
    1203           0 :         struct lvol_store_bdev *lvs_bdev = NULL;
    1204           0 :         struct spdk_lvol_store *lvs = NULL;
    1205             :         int rc;
    1206             : 
    1207           0 :         if (params != NULL) {
    1208           0 :                 if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
    1209             :                                             SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
    1210             :                                             &req)) {
    1211           0 :                         SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1212           0 :                         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1213             :                                                          "spdk_json_decode_object failed");
    1214           0 :                         goto cleanup;
    1215             :                 }
    1216             : 
    1217           0 :                 rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
    1218           0 :                 if (rc != 0) {
    1219           0 :                         spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
    1220           0 :                         goto cleanup;
    1221             :                 }
    1222             : 
    1223           0 :                 lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
    1224           0 :                 if (lvs_bdev == NULL) {
    1225           0 :                         spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
    1226           0 :                         goto cleanup;
    1227             :                 }
    1228             :         }
    1229             : 
    1230           0 :         w = spdk_jsonrpc_begin_result(request);
    1231           0 :         spdk_json_write_array_begin(w);
    1232             : 
    1233           0 :         if (lvs_bdev != NULL) {
    1234           0 :                 rpc_dump_lvols(w, lvs_bdev);
    1235             :         } else {
    1236           0 :                 for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
    1237           0 :                      lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
    1238           0 :                         rpc_dump_lvols(w, lvs_bdev);
    1239             :                 }
    1240             :         }
    1241           0 :         spdk_json_write_array_end(w);
    1242             : 
    1243           0 :         spdk_jsonrpc_end_result(request, w);
    1244             : 
    1245           0 : cleanup:
    1246           0 :         free_rpc_bdev_lvol_get_lvols(&req);
    1247           0 : }
    1248             : 
    1249           0 : SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
    1250             : 
    1251             : struct rpc_bdev_lvol_grow_lvstore {
    1252             :         char *uuid;
    1253             :         char *lvs_name;
    1254             : };
    1255             : 
    1256             : static void
    1257           0 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
    1258             : {
    1259           0 :         free(req->uuid);
    1260           0 :         free(req->lvs_name);
    1261           0 : }
    1262             : 
    1263             : static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
    1264             :         {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
    1265             :         {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
    1266             : };
    1267             : 
    1268             : static void
    1269           0 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
    1270             : {
    1271           0 :         struct spdk_jsonrpc_request *request = cb_arg;
    1272             : 
    1273           0 :         if (lvserrno != 0) {
    1274           0 :                 goto invalid;
    1275             :         }
    1276             : 
    1277           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1278           0 :         return;
    1279             : 
    1280           0 : invalid:
    1281           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1282             :                                          spdk_strerror(-lvserrno));
    1283             : }
    1284             : 
    1285             : static void
    1286           0 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
    1287             :                            const struct spdk_json_val *params)
    1288             : {
    1289           0 :         struct rpc_bdev_lvol_grow_lvstore req = {};
    1290           0 :         struct spdk_lvol_store *lvs = NULL;
    1291             :         int rc;
    1292             : 
    1293           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
    1294             :                                     SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
    1295             :                                     &req)) {
    1296           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1297           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1298             :                                                  "spdk_json_decode_object failed");
    1299           0 :                 goto cleanup;
    1300             :         }
    1301             : 
    1302           0 :         rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
    1303           0 :         if (rc != 0) {
    1304           0 :                 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
    1305           0 :                 goto cleanup;
    1306             :         }
    1307           0 :         spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
    1308           0 :         spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
    1309             : 
    1310           0 : cleanup:
    1311           0 :         free_rpc_bdev_lvol_grow_lvstore(&req);
    1312           0 : }
    1313           0 : SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
    1314             : 
    1315             : struct rpc_bdev_lvol_shallow_copy {
    1316             :         char *src_lvol_name;
    1317             :         char *dst_bdev_name;
    1318             : };
    1319             : 
    1320             : struct rpc_bdev_lvol_shallow_copy_ctx {
    1321             :         struct spdk_jsonrpc_request *request;
    1322             :         struct rpc_shallow_copy_status *status;
    1323             : };
    1324             : 
    1325             : static void
    1326           0 : free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
    1327             : {
    1328           0 :         free(req->src_lvol_name);
    1329           0 :         free(req->dst_bdev_name);
    1330           0 : }
    1331             : 
    1332             : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
    1333             :         {"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
    1334             :         {"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
    1335             : };
    1336             : 
    1337             : static void
    1338           0 : rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
    1339             : {
    1340           0 :         struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
    1341             : 
    1342           0 :         ctx->status->result = lvolerrno;
    1343             : 
    1344           0 :         free(ctx);
    1345           0 : }
    1346             : 
    1347             : static void
    1348           0 : rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
    1349             : {
    1350           0 :         struct rpc_shallow_copy_status *status = cb_arg;
    1351             : 
    1352           0 :         status->copied_clusters = copied_clusters;
    1353           0 : }
    1354             : 
    1355             : static void
    1356           0 : rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
    1357             :                                  const struct spdk_json_val *params)
    1358             : {
    1359           0 :         struct rpc_bdev_lvol_shallow_copy req = {};
    1360             :         struct rpc_bdev_lvol_shallow_copy_ctx *ctx;
    1361             :         struct spdk_lvol *src_lvol;
    1362             :         struct spdk_bdev *src_lvol_bdev;
    1363             :         struct rpc_shallow_copy_status *status;
    1364             :         struct spdk_json_write_ctx *w;
    1365             :         int rc;
    1366             : 
    1367           0 :         SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
    1368             : 
    1369           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
    1370             :                                     SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
    1371             :                                     &req)) {
    1372           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1373           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1374             :                                                  "spdk_json_decode_object failed");
    1375           0 :                 goto cleanup;
    1376             :         }
    1377             : 
    1378           0 :         src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
    1379           0 :         if (src_lvol_bdev == NULL) {
    1380           0 :                 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
    1381           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1382           0 :                 goto cleanup;
    1383             :         }
    1384             : 
    1385           0 :         src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
    1386           0 :         if (src_lvol == NULL) {
    1387           0 :                 SPDK_ERRLOG("lvol does not exist\n");
    1388           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1389           0 :                 goto cleanup;
    1390             :         }
    1391             : 
    1392           0 :         status = calloc(1, sizeof(*status));
    1393           0 :         if (status == NULL) {
    1394           0 :                 SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name);
    1395           0 :                 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
    1396           0 :                 goto cleanup;
    1397             :         }
    1398             : 
    1399           0 :         status->operation_id = ++g_shallow_copy_count;
    1400           0 :         status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
    1401             : 
    1402           0 :         ctx = calloc(1, sizeof(*ctx));
    1403           0 :         if (ctx == NULL) {
    1404           0 :                 SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name);
    1405           0 :                 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
    1406           0 :                 free(status);
    1407           0 :                 goto cleanup;
    1408             :         }
    1409           0 :         ctx->request = request;
    1410           0 :         ctx->status = status;
    1411             : 
    1412           0 :         LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
    1413           0 :         rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
    1414             :                                      rpc_bdev_lvol_shallow_copy_status_cb, status,
    1415             :                                      rpc_bdev_lvol_shallow_copy_cb, ctx);
    1416             : 
    1417           0 :         if (rc < 0) {
    1418           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1419             :                                                  spdk_strerror(-rc));
    1420           0 :                 LIST_REMOVE(status, link);
    1421           0 :                 free(ctx);
    1422           0 :                 free(status);
    1423             :         } else {
    1424           0 :                 w = spdk_jsonrpc_begin_result(request);
    1425             : 
    1426           0 :                 spdk_json_write_object_begin(w);
    1427           0 :                 spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
    1428           0 :                 spdk_json_write_object_end(w);
    1429             : 
    1430           0 :                 spdk_jsonrpc_end_result(request, w);
    1431             :         }
    1432             : 
    1433           0 : cleanup:
    1434           0 :         free_rpc_bdev_lvol_shallow_copy(&req);
    1435           0 : }
    1436             : 
    1437           0 : SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy,
    1438             :                   SPDK_RPC_RUNTIME)
    1439             : 
    1440             : struct rpc_bdev_lvol_shallow_copy_status {
    1441             :         char            *src_lvol_name;
    1442             :         uint32_t        operation_id;
    1443             : };
    1444             : 
    1445             : static void
    1446           0 : free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
    1447             : {
    1448           0 :         free(req->src_lvol_name);
    1449           0 : }
    1450             : 
    1451             : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
    1452             :         {"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32},
    1453             : };
    1454             : 
    1455             : static void
    1456           0 : rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
    1457             :                                  const struct spdk_json_val *params)
    1458             : {
    1459           0 :         struct rpc_bdev_lvol_shallow_copy_status req = {};
    1460             :         struct rpc_shallow_copy_status *status;
    1461             :         struct spdk_json_write_ctx *w;
    1462             :         uint64_t copied_clusters, total_clusters;
    1463             :         int result;
    1464             : 
    1465           0 :         SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
    1466             : 
    1467           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
    1468             :                                     SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
    1469             :                                     &req)) {
    1470           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1471           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1472             :                                                  "spdk_json_decode_object failed");
    1473           0 :                 goto cleanup;
    1474             :         }
    1475             : 
    1476           0 :         LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
    1477           0 :                 if (status->operation_id == req.operation_id) {
    1478           0 :                         break;
    1479             :                 }
    1480             :         }
    1481             : 
    1482           0 :         if (!status) {
    1483           0 :                 SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id);
    1484           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1485           0 :                 goto cleanup;
    1486             :         }
    1487             : 
    1488           0 :         copied_clusters = status->copied_clusters;
    1489           0 :         total_clusters = status->total_clusters;
    1490           0 :         result = status->result;
    1491             : 
    1492           0 :         w = spdk_jsonrpc_begin_result(request);
    1493             : 
    1494           0 :         spdk_json_write_object_begin(w);
    1495             : 
    1496           0 :         spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
    1497           0 :         spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
    1498           0 :         if (copied_clusters < total_clusters && result == 0) {
    1499           0 :                 spdk_json_write_named_string(w, "state", "in progress");
    1500           0 :         } else if (copied_clusters == total_clusters && result == 0) {
    1501           0 :                 spdk_json_write_named_string(w, "state", "complete");
    1502           0 :                 LIST_REMOVE(status, link);
    1503           0 :                 free(status);
    1504             :         } else {
    1505           0 :                 spdk_json_write_named_string(w, "state", "error");
    1506           0 :                 spdk_json_write_named_string(w, "error", spdk_strerror(-result));
    1507           0 :                 LIST_REMOVE(status, link);
    1508           0 :                 free(status);
    1509             :         }
    1510             : 
    1511           0 :         spdk_json_write_object_end(w);
    1512             : 
    1513           0 :         spdk_jsonrpc_end_result(request, w);
    1514             : 
    1515           0 : cleanup:
    1516           0 :         free_rpc_bdev_lvol_shallow_copy_status(&req);
    1517           0 : }
    1518             : 
    1519           0 : SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy,
    1520             :                   SPDK_RPC_RUNTIME)
    1521             : 
    1522             : struct rpc_bdev_lvol_set_parent {
    1523             :         char *lvol_name;
    1524             :         char *parent_name;
    1525             : };
    1526             : 
    1527             : static void
    1528           0 : free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
    1529             : {
    1530           0 :         free(req->lvol_name);
    1531           0 :         free(req->parent_name);
    1532           0 : }
    1533             : 
    1534             : static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = {
    1535             :         {"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string},
    1536             :         {"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string},
    1537             : };
    1538             : 
    1539             : static void
    1540           0 : rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
    1541             : {
    1542           0 :         struct spdk_jsonrpc_request *request = cb_arg;
    1543             : 
    1544           0 :         if (lvolerrno != 0) {
    1545           0 :                 goto invalid;
    1546             :         }
    1547             : 
    1548           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1549           0 :         return;
    1550             : 
    1551           0 : invalid:
    1552           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1553             :                                          spdk_strerror(-lvolerrno));
    1554             : }
    1555             : 
    1556             : static void
    1557           0 : rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
    1558             :                          const struct spdk_json_val *params)
    1559             : {
    1560           0 :         struct rpc_bdev_lvol_set_parent req = {};
    1561             :         struct spdk_lvol *lvol, *snapshot;
    1562             :         struct spdk_bdev *lvol_bdev, *snapshot_bdev;
    1563             : 
    1564           0 :         SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
    1565             : 
    1566           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
    1567             :                                     SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
    1568             :                                     &req)) {
    1569           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1570           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1571             :                                                  "spdk_json_decode_object failed");
    1572           0 :                 goto cleanup;
    1573             :         }
    1574             : 
    1575           0 :         lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
    1576           0 :         if (lvol_bdev == NULL) {
    1577           0 :                 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
    1578           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1579           0 :                 goto cleanup;
    1580             :         }
    1581             : 
    1582           0 :         lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
    1583           0 :         if (lvol == NULL) {
    1584           0 :                 SPDK_ERRLOG("lvol does not exist\n");
    1585           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1586           0 :                 goto cleanup;
    1587             :         }
    1588             : 
    1589           0 :         snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
    1590           0 :         if (snapshot_bdev == NULL) {
    1591           0 :                 SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name);
    1592           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1593           0 :                 goto cleanup;
    1594             :         }
    1595             : 
    1596           0 :         snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
    1597           0 :         if (snapshot == NULL) {
    1598           0 :                 SPDK_ERRLOG("snapshot does not exist\n");
    1599           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1600           0 :                 goto cleanup;
    1601             :         }
    1602             : 
    1603           0 :         spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
    1604             : 
    1605           0 : cleanup:
    1606           0 :         free_rpc_bdev_lvol_set_parent(&req);
    1607           0 : }
    1608             : 
    1609           0 : SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
    1610             : 
    1611             : static void
    1612           0 : rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
    1613             :                               const struct spdk_json_val *params)
    1614             : {
    1615           0 :         struct rpc_bdev_lvol_set_parent req = {};
    1616             :         struct spdk_lvol *lvol;
    1617             :         struct spdk_bdev *lvol_bdev;
    1618             : 
    1619           0 :         SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
    1620             : 
    1621           0 :         if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
    1622             :                                     SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
    1623             :                                     &req)) {
    1624           0 :                 SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
    1625           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1626             :                                                  "spdk_json_decode_object failed");
    1627           0 :                 goto cleanup;
    1628             :         }
    1629             : 
    1630           0 :         lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
    1631           0 :         if (lvol_bdev == NULL) {
    1632           0 :                 SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
    1633           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1634           0 :                 goto cleanup;
    1635             :         }
    1636             : 
    1637           0 :         lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
    1638           0 :         if (lvol == NULL) {
    1639           0 :                 SPDK_ERRLOG("lvol does not exist\n");
    1640           0 :                 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
    1641           0 :                 goto cleanup;
    1642             :         }
    1643             : 
    1644           0 :         vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
    1645             : 
    1646           0 : cleanup:
    1647           0 :         free_rpc_bdev_lvol_set_parent(&req);
    1648           0 : }
    1649             : 
    1650           0 : SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
    1651             :                   SPDK_RPC_RUNTIME)

Generated by: LCOV version 1.15