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