xref: /spdk/module/bdev/lvol/vbdev_lvol_rpc.c (revision e0d7428b482257aa6999b8b4cc44159dcc292df9)
1488570ebSJim Harris /*   SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse  *   Copyright (C) 2017 Intel Corporation.
307fe6a43SSeth Howell  *   All rights reserved.
4a67e0eb3SMike Gerdts  *   Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
507fe6a43SSeth Howell  */
607fe6a43SSeth Howell 
707fe6a43SSeth Howell #include "spdk/rpc.h"
807fe6a43SSeth Howell #include "spdk/bdev.h"
907fe6a43SSeth Howell #include "spdk/util.h"
1007fe6a43SSeth Howell #include "vbdev_lvol.h"
1107fe6a43SSeth Howell #include "spdk/string.h"
124e8e97c8STomasz Zawadzki #include "spdk/log.h"
1307fe6a43SSeth Howell 
142172c432STomasz Zawadzki SPDK_LOG_REGISTER_COMPONENT(lvol_rpc)
1507fe6a43SSeth Howell 
169b3554b5SDamiano Cipriani struct rpc_shallow_copy_status {
179b3554b5SDamiano Cipriani 	uint32_t				operation_id;
189b3554b5SDamiano Cipriani 	/*
199b3554b5SDamiano Cipriani 	 * 0 means ongoing or successfully completed operation
209b3554b5SDamiano Cipriani 	 * a negative value is the -errno of an aborted operation
219b3554b5SDamiano Cipriani 	 */
229b3554b5SDamiano Cipriani 	int					result;
239b3554b5SDamiano Cipriani 	uint64_t				copied_clusters;
249b3554b5SDamiano Cipriani 	uint64_t				total_clusters;
259b3554b5SDamiano Cipriani 	LIST_ENTRY(rpc_shallow_copy_status)	link;
269b3554b5SDamiano Cipriani };
279b3554b5SDamiano Cipriani 
289b3554b5SDamiano Cipriani static uint32_t g_shallow_copy_count = 0;
299b3554b5SDamiano Cipriani static LIST_HEAD(, rpc_shallow_copy_status) g_shallow_copy_status_list = LIST_HEAD_INITIALIZER(
309b3554b5SDamiano Cipriani 			&g_shallow_copy_status_list);
319b3554b5SDamiano Cipriani 
32de756853SMaciej Wawryk struct rpc_bdev_lvol_create_lvstore {
3307fe6a43SSeth Howell 	char *lvs_name;
3407fe6a43SSeth Howell 	char *bdev_name;
3507fe6a43SSeth Howell 	uint32_t cluster_sz;
3607fe6a43SSeth Howell 	char *clear_method;
3788833020Syupeng 	uint32_t num_md_pages_per_cluster_ratio;
38*e0d7428bSAtul Malakar 	uint32_t md_page_size;
3907fe6a43SSeth Howell };
4007fe6a43SSeth Howell 
4107fe6a43SSeth Howell static int
4207fe6a43SSeth Howell vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
4307fe6a43SSeth Howell 				      struct spdk_lvol_store **lvs)
4407fe6a43SSeth Howell {
4507fe6a43SSeth Howell 	if ((uuid == NULL && lvs_name == NULL)) {
462172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
4707fe6a43SSeth Howell 		return -EINVAL;
4807fe6a43SSeth Howell 	} else if ((uuid && lvs_name)) {
492172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid,
5007fe6a43SSeth Howell 			     lvs_name);
5107fe6a43SSeth Howell 		return -EINVAL;
5207fe6a43SSeth Howell 	} else if (uuid) {
5307fe6a43SSeth Howell 		*lvs = vbdev_get_lvol_store_by_uuid(uuid);
5407fe6a43SSeth Howell 
5507fe6a43SSeth Howell 		if (*lvs == NULL) {
562172c432STomasz Zawadzki 			SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
5707fe6a43SSeth Howell 			return -ENODEV;
5807fe6a43SSeth Howell 		}
5907fe6a43SSeth Howell 	} else if (lvs_name) {
6007fe6a43SSeth Howell 
6107fe6a43SSeth Howell 		*lvs = vbdev_get_lvol_store_by_name(lvs_name);
6207fe6a43SSeth Howell 
6307fe6a43SSeth Howell 		if (*lvs == NULL) {
642172c432STomasz Zawadzki 			SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
6507fe6a43SSeth Howell 			return -ENODEV;
6607fe6a43SSeth Howell 		}
6707fe6a43SSeth Howell 	}
6807fe6a43SSeth Howell 	return 0;
6907fe6a43SSeth Howell }
7007fe6a43SSeth Howell 
7107fe6a43SSeth Howell static void
72de756853SMaciej Wawryk free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
7307fe6a43SSeth Howell {
7407fe6a43SSeth Howell 	free(req->bdev_name);
7507fe6a43SSeth Howell 	free(req->lvs_name);
7607fe6a43SSeth Howell 	free(req->clear_method);
7707fe6a43SSeth Howell }
7807fe6a43SSeth Howell 
79de756853SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = {
80de756853SMaciej Wawryk 	{"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string},
81de756853SMaciej Wawryk 	{"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true},
82de756853SMaciej Wawryk 	{"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string},
83de756853SMaciej Wawryk 	{"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true},
8488833020Syupeng 	{"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*e0d7428bSAtul Malakar 	{"md_page_size", offsetof(struct rpc_bdev_lvol_create_lvstore, md_page_size), spdk_json_decode_uint32, true},
8607fe6a43SSeth Howell };
8707fe6a43SSeth Howell 
8807fe6a43SSeth Howell static void
89c93e560fSSeth Howell rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
9007fe6a43SSeth Howell {
9107fe6a43SSeth Howell 	struct spdk_json_write_ctx *w;
9207fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
9307fe6a43SSeth Howell 
9407fe6a43SSeth Howell 	if (lvserrno != 0) {
9507fe6a43SSeth Howell 		goto invalid;
9607fe6a43SSeth Howell 	}
9707fe6a43SSeth Howell 
9807fe6a43SSeth Howell 	w = spdk_jsonrpc_begin_result(request);
998cffbe01SKonrad Sztyber 	spdk_json_write_uuid(w, &lvol_store->uuid);
10007fe6a43SSeth Howell 	spdk_jsonrpc_end_result(request, w);
10107fe6a43SSeth Howell 	return;
10207fe6a43SSeth Howell 
10307fe6a43SSeth Howell invalid:
10407fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
10507fe6a43SSeth Howell 					 spdk_strerror(-lvserrno));
10607fe6a43SSeth Howell }
10707fe6a43SSeth Howell 
10807fe6a43SSeth Howell static void
109c93e560fSSeth Howell rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
11007fe6a43SSeth Howell 			     const struct spdk_json_val *params)
11107fe6a43SSeth Howell {
112de756853SMaciej Wawryk 	struct rpc_bdev_lvol_create_lvstore req = {};
11307fe6a43SSeth Howell 	int rc = 0;
11407fe6a43SSeth Howell 	enum lvs_clear_method clear_method;
11507fe6a43SSeth Howell 
116de756853SMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
117de756853SMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
11807fe6a43SSeth Howell 				    &req)) {
1192172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
12007fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
12107fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
12207fe6a43SSeth Howell 		goto cleanup;
12307fe6a43SSeth Howell 	}
12407fe6a43SSeth Howell 
12507fe6a43SSeth Howell 	if (req.clear_method != NULL) {
12607fe6a43SSeth Howell 		if (!strcasecmp(req.clear_method, "none")) {
12707fe6a43SSeth Howell 			clear_method = LVS_CLEAR_WITH_NONE;
12807fe6a43SSeth Howell 		} else if (!strcasecmp(req.clear_method, "unmap")) {
12907fe6a43SSeth Howell 			clear_method = LVS_CLEAR_WITH_UNMAP;
13007fe6a43SSeth Howell 		} else if (!strcasecmp(req.clear_method, "write_zeroes")) {
13107fe6a43SSeth Howell 			clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
13207fe6a43SSeth Howell 		} else {
13307fe6a43SSeth Howell 			spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
13407fe6a43SSeth Howell 			goto cleanup;
13507fe6a43SSeth Howell 		}
13607fe6a43SSeth Howell 	} else {
13707fe6a43SSeth Howell 		clear_method = LVS_CLEAR_WITH_UNMAP;
13807fe6a43SSeth Howell 	}
13907fe6a43SSeth Howell 
140*e0d7428bSAtul Malakar 	rc = vbdev_lvs_create_ext(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
141*e0d7428bSAtul Malakar 				  req.num_md_pages_per_cluster_ratio, req.md_page_size,
142*e0d7428bSAtul Malakar 				  rpc_lvol_store_construct_cb, request);
14307fe6a43SSeth Howell 	if (rc < 0) {
144669069daSNathan Claudel 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
14507fe6a43SSeth Howell 		goto cleanup;
14607fe6a43SSeth Howell 	}
147de756853SMaciej Wawryk 	free_rpc_bdev_lvol_create_lvstore(&req);
14807fe6a43SSeth Howell 
14907fe6a43SSeth Howell 	return;
15007fe6a43SSeth Howell 
15107fe6a43SSeth Howell cleanup:
152de756853SMaciej Wawryk 	free_rpc_bdev_lvol_create_lvstore(&req);
15307fe6a43SSeth Howell }
154c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME)
15507fe6a43SSeth Howell 
15690e4ae5dSMaciej Wawryk struct rpc_bdev_lvol_rename_lvstore {
15707fe6a43SSeth Howell 	char *old_name;
15807fe6a43SSeth Howell 	char *new_name;
15907fe6a43SSeth Howell };
16007fe6a43SSeth Howell 
16107fe6a43SSeth Howell static void
16290e4ae5dSMaciej Wawryk free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
16307fe6a43SSeth Howell {
16407fe6a43SSeth Howell 	free(req->old_name);
16507fe6a43SSeth Howell 	free(req->new_name);
16607fe6a43SSeth Howell }
16707fe6a43SSeth Howell 
16890e4ae5dSMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = {
16990e4ae5dSMaciej Wawryk 	{"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string},
17090e4ae5dSMaciej Wawryk 	{"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string},
17107fe6a43SSeth Howell };
17207fe6a43SSeth Howell 
17307fe6a43SSeth Howell static void
174c93e560fSSeth Howell rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
17507fe6a43SSeth Howell {
17607fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
17707fe6a43SSeth Howell 
17807fe6a43SSeth Howell 	if (lvserrno != 0) {
17907fe6a43SSeth Howell 		goto invalid;
18007fe6a43SSeth Howell 	}
18107fe6a43SSeth Howell 
182d73077b8Syidong0635 	spdk_jsonrpc_send_bool_response(request, true);
18307fe6a43SSeth Howell 	return;
18407fe6a43SSeth Howell 
18507fe6a43SSeth Howell invalid:
18607fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
18707fe6a43SSeth Howell 					 spdk_strerror(-lvserrno));
18807fe6a43SSeth Howell }
18907fe6a43SSeth Howell 
19007fe6a43SSeth Howell static void
191c93e560fSSeth Howell rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
19207fe6a43SSeth Howell 			     const struct spdk_json_val *params)
19307fe6a43SSeth Howell {
19490e4ae5dSMaciej Wawryk 	struct rpc_bdev_lvol_rename_lvstore req = {};
19507fe6a43SSeth Howell 	struct spdk_lvol_store *lvs;
19607fe6a43SSeth Howell 
19790e4ae5dSMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders,
19890e4ae5dSMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders),
19907fe6a43SSeth Howell 				    &req)) {
2002172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
20107fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
20207fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
20307fe6a43SSeth Howell 		goto cleanup;
20407fe6a43SSeth Howell 	}
20507fe6a43SSeth Howell 
20607fe6a43SSeth Howell 	lvs = vbdev_get_lvol_store_by_name(req.old_name);
20707fe6a43SSeth Howell 	if (lvs == NULL) {
2082172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
20907fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
21007fe6a43SSeth Howell 		goto cleanup;
21107fe6a43SSeth Howell 	}
21207fe6a43SSeth Howell 
213c93e560fSSeth Howell 	vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
21407fe6a43SSeth Howell 
21507fe6a43SSeth Howell cleanup:
21690e4ae5dSMaciej Wawryk 	free_rpc_bdev_lvol_rename_lvstore(&req);
21707fe6a43SSeth Howell }
218c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME)
21907fe6a43SSeth Howell 
2204c049618SMaciej Wawryk struct rpc_bdev_lvol_delete_lvstore {
22107fe6a43SSeth Howell 	char *uuid;
22207fe6a43SSeth Howell 	char *lvs_name;
22307fe6a43SSeth Howell };
22407fe6a43SSeth Howell 
22507fe6a43SSeth Howell static void
2264c049618SMaciej Wawryk free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
22707fe6a43SSeth Howell {
22807fe6a43SSeth Howell 	free(req->uuid);
22907fe6a43SSeth Howell 	free(req->lvs_name);
23007fe6a43SSeth Howell }
23107fe6a43SSeth Howell 
2324c049618SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = {
2334c049618SMaciej Wawryk 	{"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true},
2344c049618SMaciej Wawryk 	{"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true},
23507fe6a43SSeth Howell };
23607fe6a43SSeth Howell 
23707fe6a43SSeth Howell static void
238c93e560fSSeth Howell rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
23907fe6a43SSeth Howell {
24007fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
24107fe6a43SSeth Howell 
24207fe6a43SSeth Howell 	if (lvserrno != 0) {
24307fe6a43SSeth Howell 		goto invalid;
24407fe6a43SSeth Howell 	}
24507fe6a43SSeth Howell 
246d73077b8Syidong0635 	spdk_jsonrpc_send_bool_response(request, true);
24707fe6a43SSeth Howell 	return;
24807fe6a43SSeth Howell 
24907fe6a43SSeth Howell invalid:
25007fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
25107fe6a43SSeth Howell 					 spdk_strerror(-lvserrno));
25207fe6a43SSeth Howell }
25307fe6a43SSeth Howell 
25407fe6a43SSeth Howell static void
255c93e560fSSeth Howell rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
25607fe6a43SSeth Howell 			     const struct spdk_json_val *params)
25707fe6a43SSeth Howell {
2584c049618SMaciej Wawryk 	struct rpc_bdev_lvol_delete_lvstore req = {};
25907fe6a43SSeth Howell 	struct spdk_lvol_store *lvs = NULL;
26007fe6a43SSeth Howell 	int rc;
26107fe6a43SSeth Howell 
2624c049618SMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders,
2634c049618SMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders),
26407fe6a43SSeth Howell 				    &req)) {
2652172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
26607fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
26707fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
26807fe6a43SSeth Howell 		goto cleanup;
26907fe6a43SSeth Howell 	}
27007fe6a43SSeth Howell 
27107fe6a43SSeth Howell 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
27207fe6a43SSeth Howell 	if (rc != 0) {
27307fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
27407fe6a43SSeth Howell 		goto cleanup;
27507fe6a43SSeth Howell 	}
27607fe6a43SSeth Howell 
277c93e560fSSeth Howell 	vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
27807fe6a43SSeth Howell 
27907fe6a43SSeth Howell cleanup:
2804c049618SMaciej Wawryk 	free_rpc_bdev_lvol_delete_lvstore(&req);
28107fe6a43SSeth Howell }
282c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME)
28307fe6a43SSeth Howell 
284c57cd922SMaciej Wawryk struct rpc_bdev_lvol_create {
28507fe6a43SSeth Howell 	char *uuid;
28607fe6a43SSeth Howell 	char *lvs_name;
28707fe6a43SSeth Howell 	char *lvol_name;
2882d590e74SSebastian Brzezinka 	uint64_t size_in_mib;
28907fe6a43SSeth Howell 	bool thin_provision;
29007fe6a43SSeth Howell 	char *clear_method;
29107fe6a43SSeth Howell };
29207fe6a43SSeth Howell 
29307fe6a43SSeth Howell static void
294c57cd922SMaciej Wawryk free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
29507fe6a43SSeth Howell {
29607fe6a43SSeth Howell 	free(req->uuid);
29707fe6a43SSeth Howell 	free(req->lvs_name);
29807fe6a43SSeth Howell 	free(req->lvol_name);
29907fe6a43SSeth Howell 	free(req->clear_method);
30007fe6a43SSeth Howell }
30107fe6a43SSeth Howell 
302c57cd922SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
303c57cd922SMaciej Wawryk 	{"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
304c57cd922SMaciej Wawryk 	{"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
305c57cd922SMaciej Wawryk 	{"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
306ba31ad82SKonrad Sztyber 	{"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64},
307c57cd922SMaciej Wawryk 	{"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true},
308c57cd922SMaciej Wawryk 	{"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true},
30907fe6a43SSeth Howell };
31007fe6a43SSeth Howell 
31107fe6a43SSeth Howell static void
312c93e560fSSeth Howell rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
31307fe6a43SSeth Howell {
31407fe6a43SSeth Howell 	struct spdk_json_write_ctx *w;
31507fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
31607fe6a43SSeth Howell 
31707fe6a43SSeth Howell 	if (lvolerrno != 0) {
31807fe6a43SSeth Howell 		goto invalid;
31907fe6a43SSeth Howell 	}
32007fe6a43SSeth Howell 
32107fe6a43SSeth Howell 	w = spdk_jsonrpc_begin_result(request);
32207fe6a43SSeth Howell 	spdk_json_write_string(w, lvol->unique_id);
32307fe6a43SSeth Howell 	spdk_jsonrpc_end_result(request, w);
32407fe6a43SSeth Howell 	return;
32507fe6a43SSeth Howell 
32607fe6a43SSeth Howell invalid:
32707fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
32807fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
32907fe6a43SSeth Howell }
33007fe6a43SSeth Howell 
33107fe6a43SSeth Howell static void
332c93e560fSSeth Howell rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
33307fe6a43SSeth Howell 		     const struct spdk_json_val *params)
33407fe6a43SSeth Howell {
335c57cd922SMaciej Wawryk 	struct rpc_bdev_lvol_create req = {};
33607fe6a43SSeth Howell 	enum lvol_clear_method clear_method;
33707fe6a43SSeth Howell 	int rc = 0;
33807fe6a43SSeth Howell 	struct spdk_lvol_store *lvs = NULL;
33907fe6a43SSeth Howell 
3402172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
34107fe6a43SSeth Howell 
342c57cd922SMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
343c57cd922SMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
34407fe6a43SSeth Howell 				    &req)) {
3452172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
34607fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
34707fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
34807fe6a43SSeth Howell 		goto cleanup;
34907fe6a43SSeth Howell 	}
35007fe6a43SSeth Howell 
35107fe6a43SSeth Howell 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
35207fe6a43SSeth Howell 	if (rc != 0) {
35307fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
35407fe6a43SSeth Howell 		goto cleanup;
35507fe6a43SSeth Howell 	}
35607fe6a43SSeth Howell 
35707fe6a43SSeth Howell 	if (req.clear_method != NULL) {
35807fe6a43SSeth Howell 		if (!strcasecmp(req.clear_method, "none")) {
35907fe6a43SSeth Howell 			clear_method = LVOL_CLEAR_WITH_NONE;
36007fe6a43SSeth Howell 		} else if (!strcasecmp(req.clear_method, "unmap")) {
36107fe6a43SSeth Howell 			clear_method = LVOL_CLEAR_WITH_UNMAP;
36207fe6a43SSeth Howell 		} else if (!strcasecmp(req.clear_method, "write_zeroes")) {
36307fe6a43SSeth Howell 			clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES;
36407fe6a43SSeth Howell 		} else {
36507fe6a43SSeth Howell 			spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
36607fe6a43SSeth Howell 			goto cleanup;
36707fe6a43SSeth Howell 		}
36807fe6a43SSeth Howell 	} else {
36907fe6a43SSeth Howell 		clear_method = LVOL_CLEAR_WITH_DEFAULT;
37007fe6a43SSeth Howell 	}
37107fe6a43SSeth Howell 
372ba31ad82SKonrad Sztyber 	rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
373ba31ad82SKonrad Sztyber 			       req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
37407fe6a43SSeth Howell 	if (rc < 0) {
37507fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
37607fe6a43SSeth Howell 		goto cleanup;
37707fe6a43SSeth Howell 	}
37807fe6a43SSeth Howell 
37907fe6a43SSeth Howell cleanup:
380c57cd922SMaciej Wawryk 	free_rpc_bdev_lvol_create(&req);
38107fe6a43SSeth Howell }
38207fe6a43SSeth Howell 
383c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME)
38407fe6a43SSeth Howell 
385f5cf8ea1SMaciej Wawryk struct rpc_bdev_lvol_snapshot {
38607fe6a43SSeth Howell 	char *lvol_name;
38707fe6a43SSeth Howell 	char *snapshot_name;
38807fe6a43SSeth Howell };
38907fe6a43SSeth Howell 
39007fe6a43SSeth Howell static void
391f5cf8ea1SMaciej Wawryk free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
39207fe6a43SSeth Howell {
39307fe6a43SSeth Howell 	free(req->lvol_name);
39407fe6a43SSeth Howell 	free(req->snapshot_name);
39507fe6a43SSeth Howell }
39607fe6a43SSeth Howell 
397f5cf8ea1SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = {
398f5cf8ea1SMaciej Wawryk 	{"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string},
399f5cf8ea1SMaciej Wawryk 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string},
40007fe6a43SSeth Howell };
40107fe6a43SSeth Howell 
40207fe6a43SSeth Howell static void
403c93e560fSSeth Howell rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
40407fe6a43SSeth Howell {
40507fe6a43SSeth Howell 	struct spdk_json_write_ctx *w;
40607fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
40707fe6a43SSeth Howell 
40807fe6a43SSeth Howell 	if (lvolerrno != 0) {
40907fe6a43SSeth Howell 		goto invalid;
41007fe6a43SSeth Howell 	}
41107fe6a43SSeth Howell 
41207fe6a43SSeth Howell 	w = spdk_jsonrpc_begin_result(request);
41307fe6a43SSeth Howell 	spdk_json_write_string(w, lvol->unique_id);
41407fe6a43SSeth Howell 	spdk_jsonrpc_end_result(request, w);
41507fe6a43SSeth Howell 	return;
41607fe6a43SSeth Howell 
41707fe6a43SSeth Howell invalid:
41807fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
41907fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
42007fe6a43SSeth Howell }
42107fe6a43SSeth Howell 
42207fe6a43SSeth Howell static void
423c93e560fSSeth Howell rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
42407fe6a43SSeth Howell 		       const struct spdk_json_val *params)
42507fe6a43SSeth Howell {
426f5cf8ea1SMaciej Wawryk 	struct rpc_bdev_lvol_snapshot req = {};
42707fe6a43SSeth Howell 	struct spdk_bdev *bdev;
42807fe6a43SSeth Howell 	struct spdk_lvol *lvol;
42907fe6a43SSeth Howell 
4302172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
43107fe6a43SSeth Howell 
432f5cf8ea1SMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders,
433f5cf8ea1SMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders),
43407fe6a43SSeth Howell 				    &req)) {
4352172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
43607fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
43707fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
43807fe6a43SSeth Howell 		goto cleanup;
43907fe6a43SSeth Howell 	}
44007fe6a43SSeth Howell 
44107fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.lvol_name);
44207fe6a43SSeth Howell 	if (bdev == NULL) {
4432172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name);
44407fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
44507fe6a43SSeth Howell 		goto cleanup;
44607fe6a43SSeth Howell 	}
44707fe6a43SSeth Howell 
44807fe6a43SSeth Howell 	lvol = vbdev_lvol_get_from_bdev(bdev);
44907fe6a43SSeth Howell 	if (lvol == NULL) {
45007fe6a43SSeth Howell 		SPDK_ERRLOG("lvol does not exist\n");
45107fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
45207fe6a43SSeth Howell 		goto cleanup;
45307fe6a43SSeth Howell 	}
45407fe6a43SSeth Howell 
455c93e560fSSeth Howell 	vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
45607fe6a43SSeth Howell 
45707fe6a43SSeth Howell cleanup:
458f5cf8ea1SMaciej Wawryk 	free_rpc_bdev_lvol_snapshot(&req);
45907fe6a43SSeth Howell }
46007fe6a43SSeth Howell 
461c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME)
46207fe6a43SSeth Howell 
463827b2667SMaciej Wawryk struct rpc_bdev_lvol_clone {
46407fe6a43SSeth Howell 	char *snapshot_name;
46507fe6a43SSeth Howell 	char *clone_name;
46607fe6a43SSeth Howell };
46707fe6a43SSeth Howell 
46807fe6a43SSeth Howell static void
469827b2667SMaciej Wawryk free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
47007fe6a43SSeth Howell {
47107fe6a43SSeth Howell 	free(req->snapshot_name);
47207fe6a43SSeth Howell 	free(req->clone_name);
47307fe6a43SSeth Howell }
47407fe6a43SSeth Howell 
475827b2667SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = {
476827b2667SMaciej Wawryk 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string},
477827b2667SMaciej Wawryk 	{"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true},
47807fe6a43SSeth Howell };
47907fe6a43SSeth Howell 
48007fe6a43SSeth Howell static void
481c93e560fSSeth Howell rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
48207fe6a43SSeth Howell {
48307fe6a43SSeth Howell 	struct spdk_json_write_ctx *w;
48407fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
48507fe6a43SSeth Howell 
48607fe6a43SSeth Howell 	if (lvolerrno != 0) {
48707fe6a43SSeth Howell 		goto invalid;
48807fe6a43SSeth Howell 	}
48907fe6a43SSeth Howell 
49007fe6a43SSeth Howell 	w = spdk_jsonrpc_begin_result(request);
49107fe6a43SSeth Howell 	spdk_json_write_string(w, lvol->unique_id);
49207fe6a43SSeth Howell 	spdk_jsonrpc_end_result(request, w);
49307fe6a43SSeth Howell 	return;
49407fe6a43SSeth Howell 
49507fe6a43SSeth Howell invalid:
49607fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
49707fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
49807fe6a43SSeth Howell }
49907fe6a43SSeth Howell 
50007fe6a43SSeth Howell static void
501c93e560fSSeth Howell rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
50207fe6a43SSeth Howell 		    const struct spdk_json_val *params)
50307fe6a43SSeth Howell {
504827b2667SMaciej Wawryk 	struct rpc_bdev_lvol_clone req = {};
50507fe6a43SSeth Howell 	struct spdk_bdev *bdev;
50607fe6a43SSeth Howell 	struct spdk_lvol *lvol;
50707fe6a43SSeth Howell 
5082172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
50907fe6a43SSeth Howell 
510827b2667SMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders,
511827b2667SMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders),
51207fe6a43SSeth Howell 				    &req)) {
5132172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
51407fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
51507fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
51607fe6a43SSeth Howell 		goto cleanup;
51707fe6a43SSeth Howell 	}
51807fe6a43SSeth Howell 
51907fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.snapshot_name);
52007fe6a43SSeth Howell 	if (bdev == NULL) {
5212172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name);
52207fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
52307fe6a43SSeth Howell 		goto cleanup;
52407fe6a43SSeth Howell 	}
52507fe6a43SSeth Howell 
52607fe6a43SSeth Howell 	lvol = vbdev_lvol_get_from_bdev(bdev);
52707fe6a43SSeth Howell 	if (lvol == NULL) {
52807fe6a43SSeth Howell 		SPDK_ERRLOG("lvol does not exist\n");
52907fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
53007fe6a43SSeth Howell 		goto cleanup;
53107fe6a43SSeth Howell 	}
53207fe6a43SSeth Howell 
533c93e560fSSeth Howell 	vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
53407fe6a43SSeth Howell 
53507fe6a43SSeth Howell cleanup:
536827b2667SMaciej Wawryk 	free_rpc_bdev_lvol_clone(&req);
53707fe6a43SSeth Howell }
53807fe6a43SSeth Howell 
539c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME)
54007fe6a43SSeth Howell 
541a67e0eb3SMike Gerdts struct rpc_bdev_lvol_clone_bdev {
542a67e0eb3SMike Gerdts 	/* name or UUID. Whichever is used, the UUID will be stored in the lvol's metadata. */
543a67e0eb3SMike Gerdts 	char *bdev_name;
544a67e0eb3SMike Gerdts 	char *lvs_name;
545a67e0eb3SMike Gerdts 	char *clone_name;
546a67e0eb3SMike Gerdts };
547a67e0eb3SMike Gerdts 
548a67e0eb3SMike Gerdts static void
549a67e0eb3SMike Gerdts free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req)
550a67e0eb3SMike Gerdts {
551a67e0eb3SMike Gerdts 	free(req->bdev_name);
552a67e0eb3SMike Gerdts 	free(req->lvs_name);
553a67e0eb3SMike Gerdts 	free(req->clone_name);
554a67e0eb3SMike Gerdts }
555a67e0eb3SMike Gerdts 
556a67e0eb3SMike Gerdts static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_bdev_decoders[] = {
557a67e0eb3SMike Gerdts 	{
558a67e0eb3SMike Gerdts 		"bdev", offsetof(struct rpc_bdev_lvol_clone_bdev, bdev_name),
559a67e0eb3SMike Gerdts 		spdk_json_decode_string, false
560a67e0eb3SMike Gerdts 	},
561a67e0eb3SMike Gerdts 	{
562a67e0eb3SMike Gerdts 		"lvs_name", offsetof(struct rpc_bdev_lvol_clone_bdev, lvs_name),
563a67e0eb3SMike Gerdts 		spdk_json_decode_string, false
564a67e0eb3SMike Gerdts 	},
565a67e0eb3SMike Gerdts 	{
566a67e0eb3SMike Gerdts 		"clone_name", offsetof(struct rpc_bdev_lvol_clone_bdev, clone_name),
567a67e0eb3SMike Gerdts 		spdk_json_decode_string, false
568a67e0eb3SMike Gerdts 	},
569a67e0eb3SMike Gerdts };
570a67e0eb3SMike Gerdts 
571a67e0eb3SMike Gerdts static void
572a67e0eb3SMike Gerdts rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
573a67e0eb3SMike Gerdts {
574a67e0eb3SMike Gerdts 	struct rpc_bdev_lvol_clone_bdev req = {};
575a67e0eb3SMike Gerdts 	struct spdk_bdev *bdev;
576a67e0eb3SMike Gerdts 	struct spdk_lvol_store *lvs = NULL;
577a67e0eb3SMike Gerdts 	struct spdk_lvol *lvol;
578a67e0eb3SMike Gerdts 	int rc;
579a67e0eb3SMike Gerdts 
580a67e0eb3SMike Gerdts 	SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n");
581a67e0eb3SMike Gerdts 
582a67e0eb3SMike Gerdts 	if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_bdev_decoders,
583a67e0eb3SMike Gerdts 				    SPDK_COUNTOF(rpc_bdev_lvol_clone_bdev_decoders), &req)) {
584a67e0eb3SMike Gerdts 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
585a67e0eb3SMike Gerdts 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
586a67e0eb3SMike Gerdts 						 "spdk_json_decode_object failed");
587a67e0eb3SMike Gerdts 		goto cleanup;
588a67e0eb3SMike Gerdts 	}
589a67e0eb3SMike Gerdts 
590a67e0eb3SMike Gerdts 	rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs);
591a67e0eb3SMike Gerdts 	if (rc != 0) {
592a67e0eb3SMike Gerdts 		SPDK_INFOLOG(lvol_rpc, "lvs_name '%s' not found\n", req.lvs_name);
593a67e0eb3SMike Gerdts 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
594a67e0eb3SMike Gerdts 						 "lvs does not exist");
595a67e0eb3SMike Gerdts 		goto cleanup;
596a67e0eb3SMike Gerdts 	}
597a67e0eb3SMike Gerdts 
598a67e0eb3SMike Gerdts 	bdev = spdk_bdev_get_by_name(req.bdev_name);
599a67e0eb3SMike Gerdts 	if (bdev == NULL) {
600a67e0eb3SMike Gerdts 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.bdev_name);
601a67e0eb3SMike Gerdts 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
602a67e0eb3SMike Gerdts 						 "bdev does not exist");
603a67e0eb3SMike Gerdts 		goto cleanup;
604a67e0eb3SMike Gerdts 	}
605a67e0eb3SMike Gerdts 
606a67e0eb3SMike Gerdts 	lvol = vbdev_lvol_get_from_bdev(bdev);
607a67e0eb3SMike Gerdts 	if (lvol != NULL && lvol->lvol_store == lvs) {
608a67e0eb3SMike Gerdts 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' is an lvol in lvstore '%s\n", req.bdev_name,
609a67e0eb3SMike Gerdts 			     req.lvs_name);
610a67e0eb3SMike Gerdts 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
611a67e0eb3SMike Gerdts 						 "bdev is an lvol in same lvs as clone; "
612a67e0eb3SMike Gerdts 						 "use bdev_lvol_clone instead");
613a67e0eb3SMike Gerdts 		goto cleanup;
614a67e0eb3SMike Gerdts 	}
615a67e0eb3SMike Gerdts 
616a67e0eb3SMike Gerdts 	vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name,
617a67e0eb3SMike Gerdts 				     rpc_bdev_lvol_clone_cb, request);
618a67e0eb3SMike Gerdts cleanup:
619a67e0eb3SMike Gerdts 	free_rpc_bdev_lvol_clone_bdev(&req);
620a67e0eb3SMike Gerdts }
621a67e0eb3SMike Gerdts 
622a67e0eb3SMike Gerdts SPDK_RPC_REGISTER("bdev_lvol_clone_bdev", rpc_bdev_lvol_clone_bdev, SPDK_RPC_RUNTIME)
623a67e0eb3SMike Gerdts 
6240ce883ceSMaciej Wawryk struct rpc_bdev_lvol_rename {
62507fe6a43SSeth Howell 	char *old_name;
62607fe6a43SSeth Howell 	char *new_name;
62707fe6a43SSeth Howell };
62807fe6a43SSeth Howell 
62907fe6a43SSeth Howell static void
6300ce883ceSMaciej Wawryk free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
63107fe6a43SSeth Howell {
63207fe6a43SSeth Howell 	free(req->old_name);
63307fe6a43SSeth Howell 	free(req->new_name);
63407fe6a43SSeth Howell }
63507fe6a43SSeth Howell 
6360ce883ceSMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = {
6370ce883ceSMaciej Wawryk 	{"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string},
6380ce883ceSMaciej Wawryk 	{"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string},
63907fe6a43SSeth Howell };
64007fe6a43SSeth Howell 
64107fe6a43SSeth Howell static void
642c93e560fSSeth Howell rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
64307fe6a43SSeth Howell {
64407fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
64507fe6a43SSeth Howell 
64607fe6a43SSeth Howell 	if (lvolerrno != 0) {
64707fe6a43SSeth Howell 		goto invalid;
64807fe6a43SSeth Howell 	}
64907fe6a43SSeth Howell 
650d73077b8Syidong0635 	spdk_jsonrpc_send_bool_response(request, true);
65107fe6a43SSeth Howell 	return;
65207fe6a43SSeth Howell 
65307fe6a43SSeth Howell invalid:
65407fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
65507fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
65607fe6a43SSeth Howell }
65707fe6a43SSeth Howell 
65807fe6a43SSeth Howell static void
659c93e560fSSeth Howell rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
66007fe6a43SSeth Howell 		     const struct spdk_json_val *params)
66107fe6a43SSeth Howell {
6620ce883ceSMaciej Wawryk 	struct rpc_bdev_lvol_rename req = {};
66307fe6a43SSeth Howell 	struct spdk_bdev *bdev;
66407fe6a43SSeth Howell 	struct spdk_lvol *lvol;
66507fe6a43SSeth Howell 
6662172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
66707fe6a43SSeth Howell 
6680ce883ceSMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders,
6690ce883ceSMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders),
67007fe6a43SSeth Howell 				    &req)) {
6712172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
67207fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
67307fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
67407fe6a43SSeth Howell 		goto cleanup;
67507fe6a43SSeth Howell 	}
67607fe6a43SSeth Howell 
67707fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.old_name);
67807fe6a43SSeth Howell 	if (bdev == NULL) {
67907fe6a43SSeth Howell 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
68007fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
68107fe6a43SSeth Howell 		goto cleanup;
68207fe6a43SSeth Howell 	}
68307fe6a43SSeth Howell 
68407fe6a43SSeth Howell 	lvol = vbdev_lvol_get_from_bdev(bdev);
68507fe6a43SSeth Howell 	if (lvol == NULL) {
68607fe6a43SSeth Howell 		SPDK_ERRLOG("lvol does not exist\n");
68707fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
68807fe6a43SSeth Howell 		goto cleanup;
68907fe6a43SSeth Howell 	}
69007fe6a43SSeth Howell 
691c93e560fSSeth Howell 	vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
69207fe6a43SSeth Howell 
69307fe6a43SSeth Howell cleanup:
6940ce883ceSMaciej Wawryk 	free_rpc_bdev_lvol_rename(&req);
69507fe6a43SSeth Howell }
69607fe6a43SSeth Howell 
697c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
69807fe6a43SSeth Howell 
6997a294f4cSMaciej Wawryk struct rpc_bdev_lvol_inflate {
70007fe6a43SSeth Howell 	char *name;
70107fe6a43SSeth Howell };
70207fe6a43SSeth Howell 
70307fe6a43SSeth Howell static void
7047a294f4cSMaciej Wawryk free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
70507fe6a43SSeth Howell {
70607fe6a43SSeth Howell 	free(req->name);
70707fe6a43SSeth Howell }
70807fe6a43SSeth Howell 
7097a294f4cSMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = {
7107a294f4cSMaciej Wawryk 	{"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string},
71107fe6a43SSeth Howell };
71207fe6a43SSeth Howell 
71307fe6a43SSeth Howell static void
714c93e560fSSeth Howell rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
71507fe6a43SSeth Howell {
71607fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
71707fe6a43SSeth Howell 
71807fe6a43SSeth Howell 	if (lvolerrno != 0) {
71907fe6a43SSeth Howell 		goto invalid;
72007fe6a43SSeth Howell 	}
72107fe6a43SSeth Howell 
722d73077b8Syidong0635 	spdk_jsonrpc_send_bool_response(request, true);
72307fe6a43SSeth Howell 	return;
72407fe6a43SSeth Howell 
72507fe6a43SSeth Howell invalid:
72607fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
72707fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
72807fe6a43SSeth Howell }
72907fe6a43SSeth Howell 
73007fe6a43SSeth Howell static void
731c93e560fSSeth Howell rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
73207fe6a43SSeth Howell 		      const struct spdk_json_val *params)
73307fe6a43SSeth Howell {
7347a294f4cSMaciej Wawryk 	struct rpc_bdev_lvol_inflate req = {};
73507fe6a43SSeth Howell 	struct spdk_bdev *bdev;
73607fe6a43SSeth Howell 	struct spdk_lvol *lvol;
73707fe6a43SSeth Howell 
7382172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
73907fe6a43SSeth Howell 
7407a294f4cSMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
7417a294f4cSMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
74207fe6a43SSeth Howell 				    &req)) {
7432172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
74407fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
74507fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
74607fe6a43SSeth Howell 		goto cleanup;
74707fe6a43SSeth Howell 	}
74807fe6a43SSeth Howell 
74907fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.name);
75007fe6a43SSeth Howell 	if (bdev == NULL) {
75107fe6a43SSeth Howell 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
75207fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
75307fe6a43SSeth Howell 		goto cleanup;
75407fe6a43SSeth Howell 	}
75507fe6a43SSeth Howell 
75607fe6a43SSeth Howell 	lvol = vbdev_lvol_get_from_bdev(bdev);
75707fe6a43SSeth Howell 	if (lvol == NULL) {
75807fe6a43SSeth Howell 		SPDK_ERRLOG("lvol does not exist\n");
75907fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
76007fe6a43SSeth Howell 		goto cleanup;
76107fe6a43SSeth Howell 	}
76207fe6a43SSeth Howell 
763c93e560fSSeth Howell 	spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
76407fe6a43SSeth Howell 
76507fe6a43SSeth Howell cleanup:
7667a294f4cSMaciej Wawryk 	free_rpc_bdev_lvol_inflate(&req);
76707fe6a43SSeth Howell }
76807fe6a43SSeth Howell 
769c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
77007fe6a43SSeth Howell 
77107fe6a43SSeth Howell static void
772c93e560fSSeth Howell rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
77307fe6a43SSeth Howell 			      const struct spdk_json_val *params)
77407fe6a43SSeth Howell {
7757a294f4cSMaciej Wawryk 	struct rpc_bdev_lvol_inflate req = {};
77607fe6a43SSeth Howell 	struct spdk_bdev *bdev;
77707fe6a43SSeth Howell 	struct spdk_lvol *lvol;
77807fe6a43SSeth Howell 
7792172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
78007fe6a43SSeth Howell 
7817a294f4cSMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
7827a294f4cSMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
78307fe6a43SSeth Howell 				    &req)) {
7842172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
78507fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
78607fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
78707fe6a43SSeth Howell 		goto cleanup;
78807fe6a43SSeth Howell 	}
78907fe6a43SSeth Howell 
79007fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.name);
79107fe6a43SSeth Howell 	if (bdev == NULL) {
79207fe6a43SSeth Howell 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
79307fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
79407fe6a43SSeth Howell 		goto cleanup;
79507fe6a43SSeth Howell 	}
79607fe6a43SSeth Howell 
79707fe6a43SSeth Howell 	lvol = vbdev_lvol_get_from_bdev(bdev);
79807fe6a43SSeth Howell 	if (lvol == NULL) {
79907fe6a43SSeth Howell 		SPDK_ERRLOG("lvol does not exist\n");
80007fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
80107fe6a43SSeth Howell 		goto cleanup;
80207fe6a43SSeth Howell 	}
80307fe6a43SSeth Howell 
804c93e560fSSeth Howell 	spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
80507fe6a43SSeth Howell 
80607fe6a43SSeth Howell cleanup:
8077a294f4cSMaciej Wawryk 	free_rpc_bdev_lvol_inflate(&req);
80807fe6a43SSeth Howell }
80907fe6a43SSeth Howell 
810c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME)
81107fe6a43SSeth Howell 
812c2d85bb2SMaciej Wawryk struct rpc_bdev_lvol_resize {
81307fe6a43SSeth Howell 	char *name;
8142d590e74SSebastian Brzezinka 	uint64_t size_in_mib;
81507fe6a43SSeth Howell };
81607fe6a43SSeth Howell 
81707fe6a43SSeth Howell static void
818c2d85bb2SMaciej Wawryk free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
81907fe6a43SSeth Howell {
82007fe6a43SSeth Howell 	free(req->name);
82107fe6a43SSeth Howell }
82207fe6a43SSeth Howell 
823c2d85bb2SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
824c2d85bb2SMaciej Wawryk 	{"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
825ba31ad82SKonrad Sztyber 	{"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64},
82607fe6a43SSeth Howell };
82707fe6a43SSeth Howell 
82807fe6a43SSeth Howell static void
829c93e560fSSeth Howell rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
83007fe6a43SSeth Howell {
83107fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
83207fe6a43SSeth Howell 
83307fe6a43SSeth Howell 	if (lvolerrno != 0) {
83407fe6a43SSeth Howell 		goto invalid;
83507fe6a43SSeth Howell 	}
83607fe6a43SSeth Howell 
837d73077b8Syidong0635 	spdk_jsonrpc_send_bool_response(request, true);
83807fe6a43SSeth Howell 	return;
83907fe6a43SSeth Howell 
84007fe6a43SSeth Howell invalid:
84107fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
84207fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
84307fe6a43SSeth Howell }
84407fe6a43SSeth Howell 
84507fe6a43SSeth Howell static void
846c93e560fSSeth Howell rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
84707fe6a43SSeth Howell 		     const struct spdk_json_val *params)
84807fe6a43SSeth Howell {
849c2d85bb2SMaciej Wawryk 	struct rpc_bdev_lvol_resize req = {};
85007fe6a43SSeth Howell 	struct spdk_bdev *bdev;
85107fe6a43SSeth Howell 	struct spdk_lvol *lvol;
85207fe6a43SSeth Howell 
8532172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
85407fe6a43SSeth Howell 
855c2d85bb2SMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
856c2d85bb2SMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
85707fe6a43SSeth Howell 				    &req)) {
8582172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
85907fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
86007fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
86107fe6a43SSeth Howell 		goto cleanup;
86207fe6a43SSeth Howell 	}
86307fe6a43SSeth Howell 
86407fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.name);
86507fe6a43SSeth Howell 	if (bdev == NULL) {
86607fe6a43SSeth Howell 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
86707fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
86807fe6a43SSeth Howell 		goto cleanup;
86907fe6a43SSeth Howell 	}
87007fe6a43SSeth Howell 
87107fe6a43SSeth Howell 	lvol = vbdev_lvol_get_from_bdev(bdev);
87207fe6a43SSeth Howell 	if (lvol == NULL) {
87307fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
87407fe6a43SSeth Howell 		goto cleanup;
87507fe6a43SSeth Howell 	}
87607fe6a43SSeth Howell 
8772d590e74SSebastian Brzezinka 
878ba31ad82SKonrad Sztyber 	vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
87907fe6a43SSeth Howell 
88007fe6a43SSeth Howell cleanup:
881c2d85bb2SMaciej Wawryk 	free_rpc_bdev_lvol_resize(&req);
88207fe6a43SSeth Howell }
88307fe6a43SSeth Howell 
884c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
88507fe6a43SSeth Howell 
88607fe6a43SSeth Howell struct rpc_set_ro_lvol_bdev {
88707fe6a43SSeth Howell 	char *name;
88807fe6a43SSeth Howell };
88907fe6a43SSeth Howell 
89007fe6a43SSeth Howell static void
89107fe6a43SSeth Howell free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
89207fe6a43SSeth Howell {
89307fe6a43SSeth Howell 	free(req->name);
89407fe6a43SSeth Howell }
89507fe6a43SSeth Howell 
89607fe6a43SSeth Howell static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
89707fe6a43SSeth Howell 	{"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
89807fe6a43SSeth Howell };
89907fe6a43SSeth Howell 
90007fe6a43SSeth Howell static void
901c93e560fSSeth Howell rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
90207fe6a43SSeth Howell {
90307fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
90407fe6a43SSeth Howell 
90507fe6a43SSeth Howell 	if (lvolerrno != 0) {
90607fe6a43SSeth Howell 		goto invalid;
90707fe6a43SSeth Howell 	}
90807fe6a43SSeth Howell 
909d73077b8Syidong0635 	spdk_jsonrpc_send_bool_response(request, true);
91007fe6a43SSeth Howell 	return;
91107fe6a43SSeth Howell 
91207fe6a43SSeth Howell invalid:
91307fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
91407fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
91507fe6a43SSeth Howell }
91607fe6a43SSeth Howell 
91707fe6a43SSeth Howell static void
918c93e560fSSeth Howell rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
91907fe6a43SSeth Howell 			    const struct spdk_json_val *params)
92007fe6a43SSeth Howell {
92107fe6a43SSeth Howell 	struct rpc_set_ro_lvol_bdev req = {};
92207fe6a43SSeth Howell 	struct spdk_bdev *bdev;
92307fe6a43SSeth Howell 	struct spdk_lvol *lvol;
92407fe6a43SSeth Howell 
9252172c432STomasz Zawadzki 	SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
92607fe6a43SSeth Howell 
92707fe6a43SSeth Howell 	if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
92807fe6a43SSeth Howell 				    SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
92907fe6a43SSeth Howell 				    &req)) {
9302172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
93107fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
93207fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
93307fe6a43SSeth Howell 		goto cleanup;
93407fe6a43SSeth Howell 	}
93507fe6a43SSeth Howell 
93607fe6a43SSeth Howell 	if (req.name == NULL) {
93707fe6a43SSeth Howell 		SPDK_ERRLOG("missing name param\n");
93807fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
93907fe6a43SSeth Howell 		goto cleanup;
94007fe6a43SSeth Howell 	}
94107fe6a43SSeth Howell 
94207fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.name);
94307fe6a43SSeth Howell 	if (bdev == NULL) {
94407fe6a43SSeth Howell 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
94507fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
94607fe6a43SSeth Howell 		goto cleanup;
94707fe6a43SSeth Howell 	}
94807fe6a43SSeth Howell 
94907fe6a43SSeth Howell 	lvol = vbdev_lvol_get_from_bdev(bdev);
95007fe6a43SSeth Howell 	if (lvol == NULL) {
95107fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
95207fe6a43SSeth Howell 		goto cleanup;
95307fe6a43SSeth Howell 	}
95407fe6a43SSeth Howell 
955c93e560fSSeth Howell 	vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
95607fe6a43SSeth Howell 
95707fe6a43SSeth Howell cleanup:
95807fe6a43SSeth Howell 	free_rpc_set_ro_lvol_bdev(&req);
95907fe6a43SSeth Howell }
96007fe6a43SSeth Howell 
961c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
96207fe6a43SSeth Howell 
963b5fdf4ecSMaciej Wawryk struct rpc_bdev_lvol_delete {
96407fe6a43SSeth Howell 	char *name;
96507fe6a43SSeth Howell };
96607fe6a43SSeth Howell 
96707fe6a43SSeth Howell static void
968b5fdf4ecSMaciej Wawryk free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
96907fe6a43SSeth Howell {
97007fe6a43SSeth Howell 	free(req->name);
97107fe6a43SSeth Howell }
97207fe6a43SSeth Howell 
973b5fdf4ecSMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
974b5fdf4ecSMaciej Wawryk 	{"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
97507fe6a43SSeth Howell };
97607fe6a43SSeth Howell 
97707fe6a43SSeth Howell static void
978c93e560fSSeth Howell rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
97907fe6a43SSeth Howell {
98007fe6a43SSeth Howell 	struct spdk_jsonrpc_request *request = cb_arg;
98107fe6a43SSeth Howell 
98207fe6a43SSeth Howell 	if (lvolerrno != 0) {
98307fe6a43SSeth Howell 		goto invalid;
98407fe6a43SSeth Howell 	}
98507fe6a43SSeth Howell 
986d73077b8Syidong0635 	spdk_jsonrpc_send_bool_response(request, true);
98707fe6a43SSeth Howell 	return;
98807fe6a43SSeth Howell 
98907fe6a43SSeth Howell invalid:
99007fe6a43SSeth Howell 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
99107fe6a43SSeth Howell 					 spdk_strerror(-lvolerrno));
99207fe6a43SSeth Howell }
99307fe6a43SSeth Howell 
99407fe6a43SSeth Howell static void
995c93e560fSSeth Howell rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
99607fe6a43SSeth Howell 		     const struct spdk_json_val *params)
99707fe6a43SSeth Howell {
998b5fdf4ecSMaciej Wawryk 	struct rpc_bdev_lvol_delete req = {};
99907fe6a43SSeth Howell 	struct spdk_bdev *bdev;
100007fe6a43SSeth Howell 	struct spdk_lvol *lvol;
1001c0ea96cfSMike Gerdts 	struct spdk_uuid uuid;
1002c0ea96cfSMike Gerdts 	char *lvs_name, *lvol_name;
100307fe6a43SSeth Howell 
1004b5fdf4ecSMaciej Wawryk 	if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
1005b5fdf4ecSMaciej Wawryk 				    SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
100607fe6a43SSeth Howell 				    &req)) {
10072172c432STomasz Zawadzki 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
100807fe6a43SSeth Howell 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
100907fe6a43SSeth Howell 						 "spdk_json_decode_object failed");
101007fe6a43SSeth Howell 		goto cleanup;
101107fe6a43SSeth Howell 	}
101207fe6a43SSeth Howell 
1013c0ea96cfSMike Gerdts 	/* lvol is not degraded, get lvol via bdev name or alias */
101407fe6a43SSeth Howell 	bdev = spdk_bdev_get_by_name(req.name);
1015c0ea96cfSMike Gerdts 	if (bdev != NULL) {
101607fe6a43SSeth Howell 		lvol = vbdev_lvol_get_from_bdev(bdev);
1017c0ea96cfSMike Gerdts 		if (lvol != NULL) {
1018c0ea96cfSMike Gerdts 			goto done;
1019c0ea96cfSMike Gerdts 		}
102007fe6a43SSeth Howell 	}
102107fe6a43SSeth Howell 
1022c0ea96cfSMike Gerdts 	/* lvol is degraded, get lvol via UUID */
1023c0ea96cfSMike Gerdts 	if (spdk_uuid_parse(&uuid, req.name) == 0) {
1024c0ea96cfSMike Gerdts 		lvol = spdk_lvol_get_by_uuid(&uuid);
1025c0ea96cfSMike Gerdts 		if (lvol != NULL) {
1026c0ea96cfSMike Gerdts 			goto done;
1027c0ea96cfSMike Gerdts 		}
1028c0ea96cfSMike Gerdts 	}
1029c0ea96cfSMike Gerdts 
1030c0ea96cfSMike Gerdts 	/* lvol is degraded, get lvol via lvs_name/lvol_name */
1031c0ea96cfSMike Gerdts 	lvol_name = strchr(req.name, '/');
1032c0ea96cfSMike Gerdts 	if (lvol_name != NULL) {
1033c0ea96cfSMike Gerdts 		*lvol_name = '\0';
1034c0ea96cfSMike Gerdts 		lvol_name++;
1035c0ea96cfSMike Gerdts 		lvs_name = req.name;
1036c0ea96cfSMike Gerdts 		lvol = spdk_lvol_get_by_names(lvs_name, lvol_name);
1037c0ea96cfSMike Gerdts 		if (lvol != NULL) {
1038c0ea96cfSMike Gerdts 			goto done;
1039c0ea96cfSMike Gerdts 		}
1040c0ea96cfSMike Gerdts 	}
1041c0ea96cfSMike Gerdts 
1042c0ea96cfSMike Gerdts 	/* Could not find lvol, degraded or not. */
1043c0ea96cfSMike Gerdts 	spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1044c0ea96cfSMike Gerdts 	goto cleanup;
1045c0ea96cfSMike Gerdts 
1046c0ea96cfSMike Gerdts done:
1047c93e560fSSeth Howell 	vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
104807fe6a43SSeth Howell 
104907fe6a43SSeth Howell cleanup:
1050b5fdf4ecSMaciej Wawryk 	free_rpc_bdev_lvol_delete(&req);
105107fe6a43SSeth Howell }
105207fe6a43SSeth Howell 
1053c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
105407fe6a43SSeth Howell 
10550b3f378fSMaciej Wawryk struct rpc_bdev_lvol_get_lvstores {
105607fe6a43SSeth Howell 	char *uuid;
105707fe6a43SSeth Howell 	char *lvs_name;
105807fe6a43SSeth Howell };
105907fe6a43SSeth Howell 
106007fe6a43SSeth Howell static void
10610b3f378fSMaciej Wawryk free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
106207fe6a43SSeth Howell {
106307fe6a43SSeth Howell 	free(req->uuid);
106407fe6a43SSeth Howell 	free(req->lvs_name);
106507fe6a43SSeth Howell }
106607fe6a43SSeth Howell 
10670b3f378fSMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
10680b3f378fSMaciej Wawryk 	{"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
10690b3f378fSMaciej Wawryk 	{"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
107007fe6a43SSeth Howell };
107107fe6a43SSeth Howell 
107207fe6a43SSeth Howell static void
1073c93e560fSSeth Howell rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
107407fe6a43SSeth Howell {
107507fe6a43SSeth Howell 	struct spdk_blob_store *bs;
107678f44434STomasz Zawadzki 	uint64_t cluster_size;
107707fe6a43SSeth Howell 
107807fe6a43SSeth Howell 	bs = lvs_bdev->lvs->blobstore;
107907fe6a43SSeth Howell 	cluster_size = spdk_bs_get_cluster_size(bs);
108007fe6a43SSeth Howell 
108107fe6a43SSeth Howell 	spdk_json_write_object_begin(w);
108207fe6a43SSeth Howell 
10838cffbe01SKonrad Sztyber 	spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
108407fe6a43SSeth Howell 	spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
108507fe6a43SSeth Howell 	spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
108607fe6a43SSeth Howell 	spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
108707fe6a43SSeth Howell 	spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
108878f44434STomasz Zawadzki 	spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
108907fe6a43SSeth Howell 	spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
109007fe6a43SSeth Howell 
109107fe6a43SSeth Howell 	spdk_json_write_object_end(w);
109207fe6a43SSeth Howell }
109307fe6a43SSeth Howell 
109407fe6a43SSeth Howell static void
1095c93e560fSSeth Howell rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
109607fe6a43SSeth Howell 			   const struct spdk_json_val *params)
109707fe6a43SSeth Howell {
10980b3f378fSMaciej Wawryk 	struct rpc_bdev_lvol_get_lvstores req = {};
109907fe6a43SSeth Howell 	struct spdk_json_write_ctx *w;
110007fe6a43SSeth Howell 	struct lvol_store_bdev *lvs_bdev = NULL;
110107fe6a43SSeth Howell 	struct spdk_lvol_store *lvs = NULL;
110207fe6a43SSeth Howell 	int rc;
110307fe6a43SSeth Howell 
110407fe6a43SSeth Howell 	if (params != NULL) {
11050b3f378fSMaciej Wawryk 		if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
11060b3f378fSMaciej Wawryk 					    SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
110707fe6a43SSeth Howell 					    &req)) {
11082172c432STomasz Zawadzki 			SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
110907fe6a43SSeth Howell 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
111007fe6a43SSeth Howell 							 "spdk_json_decode_object failed");
111107fe6a43SSeth Howell 			goto cleanup;
111207fe6a43SSeth Howell 		}
111307fe6a43SSeth Howell 
111407fe6a43SSeth Howell 		rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
111507fe6a43SSeth Howell 		if (rc != 0) {
111607fe6a43SSeth Howell 			spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
111707fe6a43SSeth Howell 			goto cleanup;
111807fe6a43SSeth Howell 		}
111907fe6a43SSeth Howell 
112007fe6a43SSeth Howell 		lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
112107fe6a43SSeth Howell 		if (lvs_bdev == NULL) {
112207fe6a43SSeth Howell 			spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
112307fe6a43SSeth Howell 			goto cleanup;
112407fe6a43SSeth Howell 		}
112507fe6a43SSeth Howell 	}
112607fe6a43SSeth Howell 
112707fe6a43SSeth Howell 	w = spdk_jsonrpc_begin_result(request);
112807fe6a43SSeth Howell 	spdk_json_write_array_begin(w);
112907fe6a43SSeth Howell 
113007fe6a43SSeth Howell 	if (lvs_bdev != NULL) {
1131c93e560fSSeth Howell 		rpc_dump_lvol_store_info(w, lvs_bdev);
113207fe6a43SSeth Howell 	} else {
113307fe6a43SSeth Howell 		for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
113407fe6a43SSeth Howell 		     lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1135c93e560fSSeth Howell 			rpc_dump_lvol_store_info(w, lvs_bdev);
113607fe6a43SSeth Howell 		}
113707fe6a43SSeth Howell 	}
113807fe6a43SSeth Howell 	spdk_json_write_array_end(w);
113907fe6a43SSeth Howell 
114007fe6a43SSeth Howell 	spdk_jsonrpc_end_result(request, w);
114107fe6a43SSeth Howell 
114207fe6a43SSeth Howell cleanup:
11430b3f378fSMaciej Wawryk 	free_rpc_bdev_lvol_get_lvstores(&req);
114407fe6a43SSeth Howell }
114507fe6a43SSeth Howell 
1146c93e560fSSeth Howell SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
11471f0b8df7Syupeng SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
11481f0b8df7Syupeng 
1149f3c14b8dSMike Gerdts struct rpc_bdev_lvol_get_lvols {
1150f3c14b8dSMike Gerdts 	char *lvs_uuid;
1151f3c14b8dSMike Gerdts 	char *lvs_name;
1152f3c14b8dSMike Gerdts };
1153f3c14b8dSMike Gerdts 
1154f3c14b8dSMike Gerdts static void
1155f3c14b8dSMike Gerdts free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
1156f3c14b8dSMike Gerdts {
1157f3c14b8dSMike Gerdts 	free(req->lvs_uuid);
1158f3c14b8dSMike Gerdts 	free(req->lvs_name);
1159f3c14b8dSMike Gerdts }
1160f3c14b8dSMike Gerdts 
1161f3c14b8dSMike Gerdts static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = {
1162f3c14b8dSMike Gerdts 	{"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true},
1163f3c14b8dSMike Gerdts 	{"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true},
1164f3c14b8dSMike Gerdts };
1165f3c14b8dSMike Gerdts 
1166f3c14b8dSMike Gerdts static void
1167f3c14b8dSMike Gerdts rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
1168f3c14b8dSMike Gerdts {
1169f3c14b8dSMike Gerdts 	struct spdk_lvol_store *lvs = lvol->lvol_store;
1170f3c14b8dSMike Gerdts 
1171f3c14b8dSMike Gerdts 	spdk_json_write_object_begin(w);
1172f3c14b8dSMike Gerdts 
1173f3c14b8dSMike Gerdts 	spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
1174f3c14b8dSMike Gerdts 	spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
1175f3c14b8dSMike Gerdts 	spdk_json_write_named_string(w, "name", lvol->name);
1176f3c14b8dSMike Gerdts 	spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
1177f3c14b8dSMike Gerdts 	spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
1178f3c14b8dSMike Gerdts 	spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
1179f3c14b8dSMike Gerdts 	spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
1180f3c14b8dSMike Gerdts 	spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
1181a70c3a90SYankun Li 	spdk_json_write_named_uint64(w, "num_allocated_clusters",
1182a70c3a90SYankun Li 				     spdk_blob_get_num_allocated_clusters(lvol->blob));
1183f3c14b8dSMike Gerdts 
1184f3c14b8dSMike Gerdts 	spdk_json_write_named_object_begin(w, "lvs");
1185f3c14b8dSMike Gerdts 	spdk_json_write_named_string(w, "name", lvs->name);
11868cffbe01SKonrad Sztyber 	spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1187f3c14b8dSMike Gerdts 	spdk_json_write_object_end(w);
1188f3c14b8dSMike Gerdts 
1189f3c14b8dSMike Gerdts 	spdk_json_write_object_end(w);
1190f3c14b8dSMike Gerdts }
1191f3c14b8dSMike Gerdts 
1192f3c14b8dSMike Gerdts static void
1193f3c14b8dSMike Gerdts rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1194f3c14b8dSMike Gerdts {
1195f3c14b8dSMike Gerdts 	struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1196f3c14b8dSMike Gerdts 	struct spdk_lvol *lvol;
1197f3c14b8dSMike Gerdts 
1198f3c14b8dSMike Gerdts 	TAILQ_FOREACH(lvol, &lvs->lvols, link) {
1199afcb180bSYalong Wang 		if (lvol->ref_count == 0) {
1200afcb180bSYalong Wang 			continue;
1201afcb180bSYalong Wang 		}
1202f3c14b8dSMike Gerdts 		rpc_dump_lvol(w, lvol);
1203f3c14b8dSMike Gerdts 	}
1204f3c14b8dSMike Gerdts }
1205f3c14b8dSMike Gerdts 
1206f3c14b8dSMike Gerdts static void
1207f3c14b8dSMike Gerdts rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1208f3c14b8dSMike Gerdts {
1209f3c14b8dSMike Gerdts 	struct rpc_bdev_lvol_get_lvols req = {};
1210f3c14b8dSMike Gerdts 	struct spdk_json_write_ctx *w;
1211f3c14b8dSMike Gerdts 	struct lvol_store_bdev *lvs_bdev = NULL;
1212f3c14b8dSMike Gerdts 	struct spdk_lvol_store *lvs = NULL;
1213f3c14b8dSMike Gerdts 	int rc;
1214f3c14b8dSMike Gerdts 
1215f3c14b8dSMike Gerdts 	if (params != NULL) {
1216f3c14b8dSMike Gerdts 		if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1217f3c14b8dSMike Gerdts 					    SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1218f3c14b8dSMike Gerdts 					    &req)) {
1219f3c14b8dSMike Gerdts 			SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1220f3c14b8dSMike Gerdts 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1221f3c14b8dSMike Gerdts 							 "spdk_json_decode_object failed");
1222f3c14b8dSMike Gerdts 			goto cleanup;
1223f3c14b8dSMike Gerdts 		}
1224f3c14b8dSMike Gerdts 
1225f3c14b8dSMike Gerdts 		rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1226f3c14b8dSMike Gerdts 		if (rc != 0) {
1227f3c14b8dSMike Gerdts 			spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1228f3c14b8dSMike Gerdts 			goto cleanup;
1229f3c14b8dSMike Gerdts 		}
1230f3c14b8dSMike Gerdts 
1231f3c14b8dSMike Gerdts 		lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1232f3c14b8dSMike Gerdts 		if (lvs_bdev == NULL) {
1233f3c14b8dSMike Gerdts 			spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1234f3c14b8dSMike Gerdts 			goto cleanup;
1235f3c14b8dSMike Gerdts 		}
1236f3c14b8dSMike Gerdts 	}
1237f3c14b8dSMike Gerdts 
1238f3c14b8dSMike Gerdts 	w = spdk_jsonrpc_begin_result(request);
1239f3c14b8dSMike Gerdts 	spdk_json_write_array_begin(w);
1240f3c14b8dSMike Gerdts 
1241f3c14b8dSMike Gerdts 	if (lvs_bdev != NULL) {
1242f3c14b8dSMike Gerdts 		rpc_dump_lvols(w, lvs_bdev);
1243f3c14b8dSMike Gerdts 	} else {
1244f3c14b8dSMike Gerdts 		for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1245f3c14b8dSMike Gerdts 		     lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1246f3c14b8dSMike Gerdts 			rpc_dump_lvols(w, lvs_bdev);
1247f3c14b8dSMike Gerdts 		}
1248f3c14b8dSMike Gerdts 	}
1249f3c14b8dSMike Gerdts 	spdk_json_write_array_end(w);
1250f3c14b8dSMike Gerdts 
1251f3c14b8dSMike Gerdts 	spdk_jsonrpc_end_result(request, w);
1252f3c14b8dSMike Gerdts 
1253f3c14b8dSMike Gerdts cleanup:
1254f3c14b8dSMike Gerdts 	free_rpc_bdev_lvol_get_lvols(&req);
1255f3c14b8dSMike Gerdts }
1256f3c14b8dSMike Gerdts 
1257f3c14b8dSMike Gerdts SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1258f3c14b8dSMike Gerdts 
12591f0b8df7Syupeng struct rpc_bdev_lvol_grow_lvstore {
12601f0b8df7Syupeng 	char *uuid;
12611f0b8df7Syupeng 	char *lvs_name;
12621f0b8df7Syupeng };
12631f0b8df7Syupeng 
12641f0b8df7Syupeng static void
12651f0b8df7Syupeng free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
12661f0b8df7Syupeng {
12671f0b8df7Syupeng 	free(req->uuid);
12681f0b8df7Syupeng 	free(req->lvs_name);
12691f0b8df7Syupeng }
12701f0b8df7Syupeng 
12711f0b8df7Syupeng static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
12721f0b8df7Syupeng 	{"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
12731f0b8df7Syupeng 	{"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
12741f0b8df7Syupeng };
12751f0b8df7Syupeng 
12761f0b8df7Syupeng static void
12771f0b8df7Syupeng rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
12781f0b8df7Syupeng {
12791f0b8df7Syupeng 	struct spdk_jsonrpc_request *request = cb_arg;
12801f0b8df7Syupeng 
12811f0b8df7Syupeng 	if (lvserrno != 0) {
12821f0b8df7Syupeng 		goto invalid;
12831f0b8df7Syupeng 	}
12841f0b8df7Syupeng 
12851f0b8df7Syupeng 	spdk_jsonrpc_send_bool_response(request, true);
12861f0b8df7Syupeng 	return;
12871f0b8df7Syupeng 
12881f0b8df7Syupeng invalid:
12891f0b8df7Syupeng 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
12901f0b8df7Syupeng 					 spdk_strerror(-lvserrno));
12911f0b8df7Syupeng }
12921f0b8df7Syupeng 
12931f0b8df7Syupeng static void
12941f0b8df7Syupeng rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
12951f0b8df7Syupeng 			   const struct spdk_json_val *params)
12961f0b8df7Syupeng {
12971f0b8df7Syupeng 	struct rpc_bdev_lvol_grow_lvstore req = {};
12981f0b8df7Syupeng 	struct spdk_lvol_store *lvs = NULL;
12991f0b8df7Syupeng 	int rc;
13001f0b8df7Syupeng 
13011f0b8df7Syupeng 	if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
13021f0b8df7Syupeng 				    SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
13031f0b8df7Syupeng 				    &req)) {
13041f0b8df7Syupeng 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
13051f0b8df7Syupeng 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
13061f0b8df7Syupeng 						 "spdk_json_decode_object failed");
13071f0b8df7Syupeng 		goto cleanup;
13081f0b8df7Syupeng 	}
13091f0b8df7Syupeng 
13101f0b8df7Syupeng 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
13111f0b8df7Syupeng 	if (rc != 0) {
13121f0b8df7Syupeng 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
13131f0b8df7Syupeng 		goto cleanup;
13141f0b8df7Syupeng 	}
1315ad5fc351STomasz Zawadzki 	spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1316ad5fc351STomasz Zawadzki 	spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
13171f0b8df7Syupeng 
13181f0b8df7Syupeng cleanup:
13191f0b8df7Syupeng 	free_rpc_bdev_lvol_grow_lvstore(&req);
13201f0b8df7Syupeng }
13211f0b8df7Syupeng SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
13229b3554b5SDamiano Cipriani 
13239b3554b5SDamiano Cipriani struct rpc_bdev_lvol_shallow_copy {
13249b3554b5SDamiano Cipriani 	char *src_lvol_name;
13259b3554b5SDamiano Cipriani 	char *dst_bdev_name;
13269b3554b5SDamiano Cipriani };
13279b3554b5SDamiano Cipriani 
13289b3554b5SDamiano Cipriani struct rpc_bdev_lvol_shallow_copy_ctx {
13299b3554b5SDamiano Cipriani 	struct spdk_jsonrpc_request *request;
13309b3554b5SDamiano Cipriani 	struct rpc_shallow_copy_status *status;
13319b3554b5SDamiano Cipriani };
13329b3554b5SDamiano Cipriani 
13339b3554b5SDamiano Cipriani static void
13349b3554b5SDamiano Cipriani free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
13359b3554b5SDamiano Cipriani {
13369b3554b5SDamiano Cipriani 	free(req->src_lvol_name);
13379b3554b5SDamiano Cipriani 	free(req->dst_bdev_name);
13389b3554b5SDamiano Cipriani }
13399b3554b5SDamiano Cipriani 
13409b3554b5SDamiano Cipriani static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
13419b3554b5SDamiano Cipriani 	{"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
13429b3554b5SDamiano Cipriani 	{"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
13439b3554b5SDamiano Cipriani };
13449b3554b5SDamiano Cipriani 
13459b3554b5SDamiano Cipriani static void
13469b3554b5SDamiano Cipriani rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
13479b3554b5SDamiano Cipriani {
13489b3554b5SDamiano Cipriani 	struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
13499b3554b5SDamiano Cipriani 
13509b3554b5SDamiano Cipriani 	ctx->status->result = lvolerrno;
13519b3554b5SDamiano Cipriani 
13529b3554b5SDamiano Cipriani 	free(ctx);
13539b3554b5SDamiano Cipriani }
13549b3554b5SDamiano Cipriani 
13559b3554b5SDamiano Cipriani static void
13569b3554b5SDamiano Cipriani rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
13579b3554b5SDamiano Cipriani {
13589b3554b5SDamiano Cipriani 	struct rpc_shallow_copy_status *status = cb_arg;
13599b3554b5SDamiano Cipriani 
13609b3554b5SDamiano Cipriani 	status->copied_clusters = copied_clusters;
13619b3554b5SDamiano Cipriani }
13629b3554b5SDamiano Cipriani 
13639b3554b5SDamiano Cipriani static void
13649b3554b5SDamiano Cipriani rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
13659b3554b5SDamiano Cipriani 				 const struct spdk_json_val *params)
13669b3554b5SDamiano Cipriani {
13679b3554b5SDamiano Cipriani 	struct rpc_bdev_lvol_shallow_copy req = {};
13689b3554b5SDamiano Cipriani 	struct rpc_bdev_lvol_shallow_copy_ctx *ctx;
13699b3554b5SDamiano Cipriani 	struct spdk_lvol *src_lvol;
13709b3554b5SDamiano Cipriani 	struct spdk_bdev *src_lvol_bdev;
13719b3554b5SDamiano Cipriani 	struct rpc_shallow_copy_status *status;
13729b3554b5SDamiano Cipriani 	struct spdk_json_write_ctx *w;
13739b3554b5SDamiano Cipriani 	int rc;
13749b3554b5SDamiano Cipriani 
13759b3554b5SDamiano Cipriani 	SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
13769b3554b5SDamiano Cipriani 
13779b3554b5SDamiano Cipriani 	if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
13789b3554b5SDamiano Cipriani 				    SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
13799b3554b5SDamiano Cipriani 				    &req)) {
13809b3554b5SDamiano Cipriani 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
13819b3554b5SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
13829b3554b5SDamiano Cipriani 						 "spdk_json_decode_object failed");
13839b3554b5SDamiano Cipriani 		goto cleanup;
13849b3554b5SDamiano Cipriani 	}
13859b3554b5SDamiano Cipriani 
13869b3554b5SDamiano Cipriani 	src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
13879b3554b5SDamiano Cipriani 	if (src_lvol_bdev == NULL) {
13889b3554b5SDamiano Cipriani 		SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
13899b3554b5SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
13909b3554b5SDamiano Cipriani 		goto cleanup;
13919b3554b5SDamiano Cipriani 	}
13929b3554b5SDamiano Cipriani 
13939b3554b5SDamiano Cipriani 	src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
13949b3554b5SDamiano Cipriani 	if (src_lvol == NULL) {
13959b3554b5SDamiano Cipriani 		SPDK_ERRLOG("lvol does not exist\n");
13969b3554b5SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
13979b3554b5SDamiano Cipriani 		goto cleanup;
13989b3554b5SDamiano Cipriani 	}
13999b3554b5SDamiano Cipriani 
14009b3554b5SDamiano Cipriani 	status = calloc(1, sizeof(*status));
14019b3554b5SDamiano Cipriani 	if (status == NULL) {
14029b3554b5SDamiano Cipriani 		SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name);
14039b3554b5SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
14049b3554b5SDamiano Cipriani 		goto cleanup;
14059b3554b5SDamiano Cipriani 	}
14069b3554b5SDamiano Cipriani 
14079b3554b5SDamiano Cipriani 	status->operation_id = ++g_shallow_copy_count;
14089b3554b5SDamiano Cipriani 	status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
14099b3554b5SDamiano Cipriani 
14109b3554b5SDamiano Cipriani 	ctx = calloc(1, sizeof(*ctx));
14119b3554b5SDamiano Cipriani 	if (ctx == NULL) {
14129b3554b5SDamiano Cipriani 		SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name);
14139b3554b5SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
14149b3554b5SDamiano Cipriani 		free(status);
14159b3554b5SDamiano Cipriani 		goto cleanup;
14169b3554b5SDamiano Cipriani 	}
14179b3554b5SDamiano Cipriani 	ctx->request = request;
14189b3554b5SDamiano Cipriani 	ctx->status = status;
14199b3554b5SDamiano Cipriani 
14209b3554b5SDamiano Cipriani 	LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
14219b3554b5SDamiano Cipriani 	rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
14229b3554b5SDamiano Cipriani 				     rpc_bdev_lvol_shallow_copy_status_cb, status,
14239b3554b5SDamiano Cipriani 				     rpc_bdev_lvol_shallow_copy_cb, ctx);
14249b3554b5SDamiano Cipriani 
14259b3554b5SDamiano Cipriani 	if (rc < 0) {
14269b3554b5SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
14279b3554b5SDamiano Cipriani 						 spdk_strerror(-rc));
14289b3554b5SDamiano Cipriani 		LIST_REMOVE(status, link);
14299b3554b5SDamiano Cipriani 		free(ctx);
14309b3554b5SDamiano Cipriani 		free(status);
14319b3554b5SDamiano Cipriani 	} else {
14329b3554b5SDamiano Cipriani 		w = spdk_jsonrpc_begin_result(request);
14339b3554b5SDamiano Cipriani 
14349b3554b5SDamiano Cipriani 		spdk_json_write_object_begin(w);
14359b3554b5SDamiano Cipriani 		spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
14369b3554b5SDamiano Cipriani 		spdk_json_write_object_end(w);
14379b3554b5SDamiano Cipriani 
14389b3554b5SDamiano Cipriani 		spdk_jsonrpc_end_result(request, w);
14399b3554b5SDamiano Cipriani 	}
14409b3554b5SDamiano Cipriani 
14419b3554b5SDamiano Cipriani cleanup:
14429b3554b5SDamiano Cipriani 	free_rpc_bdev_lvol_shallow_copy(&req);
14439b3554b5SDamiano Cipriani }
14449b3554b5SDamiano Cipriani 
14459b3554b5SDamiano Cipriani SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy,
14469b3554b5SDamiano Cipriani 		  SPDK_RPC_RUNTIME)
14478c41f0d3SDamiano Cipriani 
14488c41f0d3SDamiano Cipriani struct rpc_bdev_lvol_shallow_copy_status {
14498c41f0d3SDamiano Cipriani 	char		*src_lvol_name;
14508c41f0d3SDamiano Cipriani 	uint32_t	operation_id;
14518c41f0d3SDamiano Cipriani };
14528c41f0d3SDamiano Cipriani 
14538c41f0d3SDamiano Cipriani static void
14548c41f0d3SDamiano Cipriani free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
14558c41f0d3SDamiano Cipriani {
14568c41f0d3SDamiano Cipriani 	free(req->src_lvol_name);
14578c41f0d3SDamiano Cipriani }
14588c41f0d3SDamiano Cipriani 
14598c41f0d3SDamiano Cipriani static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
14608c41f0d3SDamiano Cipriani 	{"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32},
14618c41f0d3SDamiano Cipriani };
14628c41f0d3SDamiano Cipriani 
14638c41f0d3SDamiano Cipriani static void
14648c41f0d3SDamiano Cipriani rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
14658c41f0d3SDamiano Cipriani 				 const struct spdk_json_val *params)
14668c41f0d3SDamiano Cipriani {
14678c41f0d3SDamiano Cipriani 	struct rpc_bdev_lvol_shallow_copy_status req = {};
14688c41f0d3SDamiano Cipriani 	struct rpc_shallow_copy_status *status;
14698c41f0d3SDamiano Cipriani 	struct spdk_json_write_ctx *w;
14708c41f0d3SDamiano Cipriani 	uint64_t copied_clusters, total_clusters;
14718c41f0d3SDamiano Cipriani 	int result;
14728c41f0d3SDamiano Cipriani 
14738c41f0d3SDamiano Cipriani 	SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
14748c41f0d3SDamiano Cipriani 
14758c41f0d3SDamiano Cipriani 	if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
14768c41f0d3SDamiano Cipriani 				    SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
14778c41f0d3SDamiano Cipriani 				    &req)) {
14788c41f0d3SDamiano Cipriani 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
14798c41f0d3SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
14808c41f0d3SDamiano Cipriani 						 "spdk_json_decode_object failed");
14818c41f0d3SDamiano Cipriani 		goto cleanup;
14828c41f0d3SDamiano Cipriani 	}
14838c41f0d3SDamiano Cipriani 
14848c41f0d3SDamiano Cipriani 	LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
14858c41f0d3SDamiano Cipriani 		if (status->operation_id == req.operation_id) {
14868c41f0d3SDamiano Cipriani 			break;
14878c41f0d3SDamiano Cipriani 		}
14888c41f0d3SDamiano Cipriani 	}
14898c41f0d3SDamiano Cipriani 
14908c41f0d3SDamiano Cipriani 	if (!status) {
14918c41f0d3SDamiano Cipriani 		SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id);
14928c41f0d3SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
14938c41f0d3SDamiano Cipriani 		goto cleanup;
14948c41f0d3SDamiano Cipriani 	}
14958c41f0d3SDamiano Cipriani 
14968c41f0d3SDamiano Cipriani 	copied_clusters = status->copied_clusters;
14978c41f0d3SDamiano Cipriani 	total_clusters = status->total_clusters;
14988c41f0d3SDamiano Cipriani 	result = status->result;
14998c41f0d3SDamiano Cipriani 
15008c41f0d3SDamiano Cipriani 	w = spdk_jsonrpc_begin_result(request);
15018c41f0d3SDamiano Cipriani 
15028c41f0d3SDamiano Cipriani 	spdk_json_write_object_begin(w);
15038c41f0d3SDamiano Cipriani 
15048c41f0d3SDamiano Cipriani 	spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
15058c41f0d3SDamiano Cipriani 	spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
15068c41f0d3SDamiano Cipriani 	if (copied_clusters < total_clusters && result == 0) {
15078c41f0d3SDamiano Cipriani 		spdk_json_write_named_string(w, "state", "in progress");
15088c41f0d3SDamiano Cipriani 	} else if (copied_clusters == total_clusters && result == 0) {
15098c41f0d3SDamiano Cipriani 		spdk_json_write_named_string(w, "state", "complete");
15108c41f0d3SDamiano Cipriani 		LIST_REMOVE(status, link);
15118c41f0d3SDamiano Cipriani 		free(status);
15128c41f0d3SDamiano Cipriani 	} else {
15138c41f0d3SDamiano Cipriani 		spdk_json_write_named_string(w, "state", "error");
15148c41f0d3SDamiano Cipriani 		spdk_json_write_named_string(w, "error", spdk_strerror(-result));
15158c41f0d3SDamiano Cipriani 		LIST_REMOVE(status, link);
15168c41f0d3SDamiano Cipriani 		free(status);
15178c41f0d3SDamiano Cipriani 	}
15188c41f0d3SDamiano Cipriani 
15198c41f0d3SDamiano Cipriani 	spdk_json_write_object_end(w);
15208c41f0d3SDamiano Cipriani 
15218c41f0d3SDamiano Cipriani 	spdk_jsonrpc_end_result(request, w);
15228c41f0d3SDamiano Cipriani 
15238c41f0d3SDamiano Cipriani cleanup:
15248c41f0d3SDamiano Cipriani 	free_rpc_bdev_lvol_shallow_copy_status(&req);
15258c41f0d3SDamiano Cipriani }
15268c41f0d3SDamiano Cipriani 
15278c41f0d3SDamiano Cipriani SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy,
15288c41f0d3SDamiano Cipriani 		  SPDK_RPC_RUNTIME)
152999ffb3d9SDamiano Cipriani 
153099ffb3d9SDamiano Cipriani struct rpc_bdev_lvol_set_parent {
153199ffb3d9SDamiano Cipriani 	char *lvol_name;
153299ffb3d9SDamiano Cipriani 	char *parent_name;
153399ffb3d9SDamiano Cipriani };
153499ffb3d9SDamiano Cipriani 
153599ffb3d9SDamiano Cipriani static void
153699ffb3d9SDamiano Cipriani free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
153799ffb3d9SDamiano Cipriani {
153899ffb3d9SDamiano Cipriani 	free(req->lvol_name);
153999ffb3d9SDamiano Cipriani 	free(req->parent_name);
154099ffb3d9SDamiano Cipriani }
154199ffb3d9SDamiano Cipriani 
154299ffb3d9SDamiano Cipriani static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = {
154399ffb3d9SDamiano Cipriani 	{"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string},
154499ffb3d9SDamiano Cipriani 	{"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string},
154599ffb3d9SDamiano Cipriani };
154699ffb3d9SDamiano Cipriani 
154799ffb3d9SDamiano Cipriani static void
154899ffb3d9SDamiano Cipriani rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
154999ffb3d9SDamiano Cipriani {
155099ffb3d9SDamiano Cipriani 	struct spdk_jsonrpc_request *request = cb_arg;
155199ffb3d9SDamiano Cipriani 
155299ffb3d9SDamiano Cipriani 	if (lvolerrno != 0) {
155399ffb3d9SDamiano Cipriani 		goto invalid;
155499ffb3d9SDamiano Cipriani 	}
155599ffb3d9SDamiano Cipriani 
155699ffb3d9SDamiano Cipriani 	spdk_jsonrpc_send_bool_response(request, true);
155799ffb3d9SDamiano Cipriani 	return;
155899ffb3d9SDamiano Cipriani 
155999ffb3d9SDamiano Cipriani invalid:
156099ffb3d9SDamiano Cipriani 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
156199ffb3d9SDamiano Cipriani 					 spdk_strerror(-lvolerrno));
156299ffb3d9SDamiano Cipriani }
156399ffb3d9SDamiano Cipriani 
156499ffb3d9SDamiano Cipriani static void
156599ffb3d9SDamiano Cipriani rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
156699ffb3d9SDamiano Cipriani 			 const struct spdk_json_val *params)
156799ffb3d9SDamiano Cipriani {
156899ffb3d9SDamiano Cipriani 	struct rpc_bdev_lvol_set_parent req = {};
156999ffb3d9SDamiano Cipriani 	struct spdk_lvol *lvol, *snapshot;
157099ffb3d9SDamiano Cipriani 	struct spdk_bdev *lvol_bdev, *snapshot_bdev;
157199ffb3d9SDamiano Cipriani 
157299ffb3d9SDamiano Cipriani 	SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
157399ffb3d9SDamiano Cipriani 
157499ffb3d9SDamiano Cipriani 	if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
157599ffb3d9SDamiano Cipriani 				    SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
157699ffb3d9SDamiano Cipriani 				    &req)) {
157799ffb3d9SDamiano Cipriani 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
157899ffb3d9SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
157999ffb3d9SDamiano Cipriani 						 "spdk_json_decode_object failed");
158099ffb3d9SDamiano Cipriani 		goto cleanup;
158199ffb3d9SDamiano Cipriani 	}
158299ffb3d9SDamiano Cipriani 
158399ffb3d9SDamiano Cipriani 	lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
158499ffb3d9SDamiano Cipriani 	if (lvol_bdev == NULL) {
158599ffb3d9SDamiano Cipriani 		SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
158699ffb3d9SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
158799ffb3d9SDamiano Cipriani 		goto cleanup;
158899ffb3d9SDamiano Cipriani 	}
158999ffb3d9SDamiano Cipriani 
159099ffb3d9SDamiano Cipriani 	lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
159199ffb3d9SDamiano Cipriani 	if (lvol == NULL) {
159299ffb3d9SDamiano Cipriani 		SPDK_ERRLOG("lvol does not exist\n");
159399ffb3d9SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
159499ffb3d9SDamiano Cipriani 		goto cleanup;
159599ffb3d9SDamiano Cipriani 	}
159699ffb3d9SDamiano Cipriani 
159799ffb3d9SDamiano Cipriani 	snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
159899ffb3d9SDamiano Cipriani 	if (snapshot_bdev == NULL) {
159999ffb3d9SDamiano Cipriani 		SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name);
160099ffb3d9SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
160199ffb3d9SDamiano Cipriani 		goto cleanup;
160299ffb3d9SDamiano Cipriani 	}
160399ffb3d9SDamiano Cipriani 
160499ffb3d9SDamiano Cipriani 	snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
160599ffb3d9SDamiano Cipriani 	if (snapshot == NULL) {
160699ffb3d9SDamiano Cipriani 		SPDK_ERRLOG("snapshot does not exist\n");
160799ffb3d9SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
160899ffb3d9SDamiano Cipriani 		goto cleanup;
160999ffb3d9SDamiano Cipriani 	}
161099ffb3d9SDamiano Cipriani 
161199ffb3d9SDamiano Cipriani 	spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
161299ffb3d9SDamiano Cipriani 
161399ffb3d9SDamiano Cipriani cleanup:
161499ffb3d9SDamiano Cipriani 	free_rpc_bdev_lvol_set_parent(&req);
161599ffb3d9SDamiano Cipriani }
161699ffb3d9SDamiano Cipriani 
161799ffb3d9SDamiano Cipriani SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1618672ba928SDamiano Cipriani 
1619672ba928SDamiano Cipriani static void
1620672ba928SDamiano Cipriani rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1621672ba928SDamiano Cipriani 			      const struct spdk_json_val *params)
1622672ba928SDamiano Cipriani {
1623672ba928SDamiano Cipriani 	struct rpc_bdev_lvol_set_parent req = {};
1624672ba928SDamiano Cipriani 	struct spdk_lvol *lvol;
1625672ba928SDamiano Cipriani 	struct spdk_bdev *lvol_bdev;
1626672ba928SDamiano Cipriani 
1627672ba928SDamiano Cipriani 	SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
1628672ba928SDamiano Cipriani 
1629672ba928SDamiano Cipriani 	if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1630672ba928SDamiano Cipriani 				    SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1631672ba928SDamiano Cipriani 				    &req)) {
1632672ba928SDamiano Cipriani 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1633672ba928SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1634672ba928SDamiano Cipriani 						 "spdk_json_decode_object failed");
1635672ba928SDamiano Cipriani 		goto cleanup;
1636672ba928SDamiano Cipriani 	}
1637672ba928SDamiano Cipriani 
1638672ba928SDamiano Cipriani 	lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1639672ba928SDamiano Cipriani 	if (lvol_bdev == NULL) {
1640672ba928SDamiano Cipriani 		SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1641672ba928SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1642672ba928SDamiano Cipriani 		goto cleanup;
1643672ba928SDamiano Cipriani 	}
1644672ba928SDamiano Cipriani 
1645672ba928SDamiano Cipriani 	lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1646672ba928SDamiano Cipriani 	if (lvol == NULL) {
1647672ba928SDamiano Cipriani 		SPDK_ERRLOG("lvol does not exist\n");
1648672ba928SDamiano Cipriani 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1649672ba928SDamiano Cipriani 		goto cleanup;
1650672ba928SDamiano Cipriani 	}
1651672ba928SDamiano Cipriani 
1652672ba928SDamiano Cipriani 	vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1653672ba928SDamiano Cipriani 
1654672ba928SDamiano Cipriani cleanup:
1655672ba928SDamiano Cipriani 	free_rpc_bdev_lvol_set_parent(&req);
1656672ba928SDamiano Cipriani }
1657672ba928SDamiano Cipriani 
1658672ba928SDamiano Cipriani SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1659672ba928SDamiano Cipriani 		  SPDK_RPC_RUNTIME)
1660