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