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

Generated by: LCOV version 1.15