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