xref: /spdk/module/bdev/lvol/vbdev_lvol_rpc.c (revision 8afdeef3becfe9409cc9e7372bd0bc10e8b7d46d)
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 		rpc_dump_lvol(w, lvol);
1195 	}
1196 }
1197 
1198 static void
1199 rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1200 {
1201 	struct rpc_bdev_lvol_get_lvols req = {};
1202 	struct spdk_json_write_ctx *w;
1203 	struct lvol_store_bdev *lvs_bdev = NULL;
1204 	struct spdk_lvol_store *lvs = NULL;
1205 	int rc;
1206 
1207 	if (params != NULL) {
1208 		if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1209 					    SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1210 					    &req)) {
1211 			SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1212 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1213 							 "spdk_json_decode_object failed");
1214 			goto cleanup;
1215 		}
1216 
1217 		rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1218 		if (rc != 0) {
1219 			spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1220 			goto cleanup;
1221 		}
1222 
1223 		lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1224 		if (lvs_bdev == NULL) {
1225 			spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1226 			goto cleanup;
1227 		}
1228 	}
1229 
1230 	w = spdk_jsonrpc_begin_result(request);
1231 	spdk_json_write_array_begin(w);
1232 
1233 	if (lvs_bdev != NULL) {
1234 		rpc_dump_lvols(w, lvs_bdev);
1235 	} else {
1236 		for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1237 		     lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1238 			rpc_dump_lvols(w, lvs_bdev);
1239 		}
1240 	}
1241 	spdk_json_write_array_end(w);
1242 
1243 	spdk_jsonrpc_end_result(request, w);
1244 
1245 cleanup:
1246 	free_rpc_bdev_lvol_get_lvols(&req);
1247 }
1248 
1249 SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1250 
1251 struct rpc_bdev_lvol_grow_lvstore {
1252 	char *uuid;
1253 	char *lvs_name;
1254 };
1255 
1256 static void
1257 free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1258 {
1259 	free(req->uuid);
1260 	free(req->lvs_name);
1261 }
1262 
1263 static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1264 	{"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1265 	{"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1266 };
1267 
1268 static void
1269 rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1270 {
1271 	struct spdk_jsonrpc_request *request = cb_arg;
1272 
1273 	if (lvserrno != 0) {
1274 		goto invalid;
1275 	}
1276 
1277 	spdk_jsonrpc_send_bool_response(request, true);
1278 	return;
1279 
1280 invalid:
1281 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1282 					 spdk_strerror(-lvserrno));
1283 }
1284 
1285 static void
1286 rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1287 			   const struct spdk_json_val *params)
1288 {
1289 	struct rpc_bdev_lvol_grow_lvstore req = {};
1290 	struct spdk_lvol_store *lvs = NULL;
1291 	int rc;
1292 
1293 	if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1294 				    SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1295 				    &req)) {
1296 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1297 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1298 						 "spdk_json_decode_object failed");
1299 		goto cleanup;
1300 	}
1301 
1302 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1303 	if (rc != 0) {
1304 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1305 		goto cleanup;
1306 	}
1307 	spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1308 	spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1309 
1310 cleanup:
1311 	free_rpc_bdev_lvol_grow_lvstore(&req);
1312 }
1313 SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
1314 
1315 struct rpc_bdev_lvol_shallow_copy {
1316 	char *src_lvol_name;
1317 	char *dst_bdev_name;
1318 };
1319 
1320 struct rpc_bdev_lvol_shallow_copy_ctx {
1321 	struct spdk_jsonrpc_request *request;
1322 	struct rpc_shallow_copy_status *status;
1323 };
1324 
1325 static void
1326 free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
1327 {
1328 	free(req->src_lvol_name);
1329 	free(req->dst_bdev_name);
1330 }
1331 
1332 static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
1333 	{"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
1334 	{"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
1335 };
1336 
1337 static void
1338 rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1339 {
1340 	struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
1341 
1342 	ctx->status->result = lvolerrno;
1343 
1344 	free(ctx);
1345 }
1346 
1347 static void
1348 rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
1349 {
1350 	struct rpc_shallow_copy_status *status = cb_arg;
1351 
1352 	status->copied_clusters = copied_clusters;
1353 }
1354 
1355 static void
1356 rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
1357 				 const struct spdk_json_val *params)
1358 {
1359 	struct rpc_bdev_lvol_shallow_copy req = {};
1360 	struct rpc_bdev_lvol_shallow_copy_ctx *ctx;
1361 	struct spdk_lvol *src_lvol;
1362 	struct spdk_bdev *src_lvol_bdev;
1363 	struct rpc_shallow_copy_status *status;
1364 	struct spdk_json_write_ctx *w;
1365 	int rc;
1366 
1367 	SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
1368 
1369 	if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
1370 				    SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
1371 				    &req)) {
1372 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1373 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1374 						 "spdk_json_decode_object failed");
1375 		goto cleanup;
1376 	}
1377 
1378 	src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
1379 	if (src_lvol_bdev == NULL) {
1380 		SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
1381 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1382 		goto cleanup;
1383 	}
1384 
1385 	src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
1386 	if (src_lvol == NULL) {
1387 		SPDK_ERRLOG("lvol does not exist\n");
1388 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1389 		goto cleanup;
1390 	}
1391 
1392 	status = calloc(1, sizeof(*status));
1393 	if (status == NULL) {
1394 		SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name);
1395 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1396 		goto cleanup;
1397 	}
1398 
1399 	status->operation_id = ++g_shallow_copy_count;
1400 	status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
1401 
1402 	ctx = calloc(1, sizeof(*ctx));
1403 	if (ctx == NULL) {
1404 		SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name);
1405 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1406 		free(status);
1407 		goto cleanup;
1408 	}
1409 	ctx->request = request;
1410 	ctx->status = status;
1411 
1412 	LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
1413 	rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
1414 				     rpc_bdev_lvol_shallow_copy_status_cb, status,
1415 				     rpc_bdev_lvol_shallow_copy_cb, ctx);
1416 
1417 	if (rc < 0) {
1418 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1419 						 spdk_strerror(-rc));
1420 		LIST_REMOVE(status, link);
1421 		free(ctx);
1422 		free(status);
1423 	} else {
1424 		w = spdk_jsonrpc_begin_result(request);
1425 
1426 		spdk_json_write_object_begin(w);
1427 		spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
1428 		spdk_json_write_object_end(w);
1429 
1430 		spdk_jsonrpc_end_result(request, w);
1431 	}
1432 
1433 cleanup:
1434 	free_rpc_bdev_lvol_shallow_copy(&req);
1435 }
1436 
1437 SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy,
1438 		  SPDK_RPC_RUNTIME)
1439 
1440 struct rpc_bdev_lvol_shallow_copy_status {
1441 	char		*src_lvol_name;
1442 	uint32_t	operation_id;
1443 };
1444 
1445 static void
1446 free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
1447 {
1448 	free(req->src_lvol_name);
1449 }
1450 
1451 static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
1452 	{"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32},
1453 };
1454 
1455 static void
1456 rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
1457 				 const struct spdk_json_val *params)
1458 {
1459 	struct rpc_bdev_lvol_shallow_copy_status req = {};
1460 	struct rpc_shallow_copy_status *status;
1461 	struct spdk_json_write_ctx *w;
1462 	uint64_t copied_clusters, total_clusters;
1463 	int result;
1464 
1465 	SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
1466 
1467 	if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
1468 				    SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
1469 				    &req)) {
1470 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1471 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1472 						 "spdk_json_decode_object failed");
1473 		goto cleanup;
1474 	}
1475 
1476 	LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
1477 		if (status->operation_id == req.operation_id) {
1478 			break;
1479 		}
1480 	}
1481 
1482 	if (!status) {
1483 		SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id);
1484 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1485 		goto cleanup;
1486 	}
1487 
1488 	copied_clusters = status->copied_clusters;
1489 	total_clusters = status->total_clusters;
1490 	result = status->result;
1491 
1492 	w = spdk_jsonrpc_begin_result(request);
1493 
1494 	spdk_json_write_object_begin(w);
1495 
1496 	spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
1497 	spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
1498 	if (copied_clusters < total_clusters && result == 0) {
1499 		spdk_json_write_named_string(w, "state", "in progress");
1500 	} else if (copied_clusters == total_clusters && result == 0) {
1501 		spdk_json_write_named_string(w, "state", "complete");
1502 		LIST_REMOVE(status, link);
1503 		free(status);
1504 	} else {
1505 		spdk_json_write_named_string(w, "state", "error");
1506 		spdk_json_write_named_string(w, "error", spdk_strerror(-result));
1507 		LIST_REMOVE(status, link);
1508 		free(status);
1509 	}
1510 
1511 	spdk_json_write_object_end(w);
1512 
1513 	spdk_jsonrpc_end_result(request, w);
1514 
1515 cleanup:
1516 	free_rpc_bdev_lvol_shallow_copy_status(&req);
1517 }
1518 
1519 SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy,
1520 		  SPDK_RPC_RUNTIME)
1521 
1522 struct rpc_bdev_lvol_set_parent {
1523 	char *lvol_name;
1524 	char *parent_name;
1525 };
1526 
1527 static void
1528 free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
1529 {
1530 	free(req->lvol_name);
1531 	free(req->parent_name);
1532 }
1533 
1534 static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = {
1535 	{"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string},
1536 	{"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string},
1537 };
1538 
1539 static void
1540 rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
1541 {
1542 	struct spdk_jsonrpc_request *request = cb_arg;
1543 
1544 	if (lvolerrno != 0) {
1545 		goto invalid;
1546 	}
1547 
1548 	spdk_jsonrpc_send_bool_response(request, true);
1549 	return;
1550 
1551 invalid:
1552 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1553 					 spdk_strerror(-lvolerrno));
1554 }
1555 
1556 static void
1557 rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
1558 			 const struct spdk_json_val *params)
1559 {
1560 	struct rpc_bdev_lvol_set_parent req = {};
1561 	struct spdk_lvol *lvol, *snapshot;
1562 	struct spdk_bdev *lvol_bdev, *snapshot_bdev;
1563 
1564 	SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
1565 
1566 	if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1567 				    SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1568 				    &req)) {
1569 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1570 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1571 						 "spdk_json_decode_object failed");
1572 		goto cleanup;
1573 	}
1574 
1575 	lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1576 	if (lvol_bdev == NULL) {
1577 		SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1578 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1579 		goto cleanup;
1580 	}
1581 
1582 	lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1583 	if (lvol == NULL) {
1584 		SPDK_ERRLOG("lvol does not exist\n");
1585 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1586 		goto cleanup;
1587 	}
1588 
1589 	snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
1590 	if (snapshot_bdev == NULL) {
1591 		SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name);
1592 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1593 		goto cleanup;
1594 	}
1595 
1596 	snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
1597 	if (snapshot == NULL) {
1598 		SPDK_ERRLOG("snapshot does not exist\n");
1599 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1600 		goto cleanup;
1601 	}
1602 
1603 	spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
1604 
1605 cleanup:
1606 	free_rpc_bdev_lvol_set_parent(&req);
1607 }
1608 
1609 SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1610 
1611 static void
1612 rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1613 			      const struct spdk_json_val *params)
1614 {
1615 	struct rpc_bdev_lvol_set_parent req = {};
1616 	struct spdk_lvol *lvol;
1617 	struct spdk_bdev *lvol_bdev;
1618 
1619 	SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
1620 
1621 	if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1622 				    SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1623 				    &req)) {
1624 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1625 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1626 						 "spdk_json_decode_object failed");
1627 		goto cleanup;
1628 	}
1629 
1630 	lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1631 	if (lvol_bdev == NULL) {
1632 		SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1633 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1634 		goto cleanup;
1635 	}
1636 
1637 	lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1638 	if (lvol == NULL) {
1639 		SPDK_ERRLOG("lvol does not exist\n");
1640 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1641 		goto cleanup;
1642 	}
1643 
1644 	vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1645 
1646 cleanup:
1647 	free_rpc_bdev_lvol_set_parent(&req);
1648 }
1649 
1650 SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1651 		  SPDK_RPC_RUNTIME)
1652