xref: /spdk/module/bdev/lvol/vbdev_lvol_rpc.c (revision 7192849ed24874f3e9cc31e8a33a9b32c49b9506)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/rpc.h"
35 #include "spdk/bdev.h"
36 #include "spdk/util.h"
37 #include "vbdev_lvol.h"
38 #include "spdk/string.h"
39 #include "spdk_internal/log.h"
40 
41 SPDK_LOG_REGISTER_COMPONENT("lvolrpc", SPDK_LOG_LVOL_RPC)
42 
43 struct rpc_bdev_lvol_create_lvstore {
44 	char *lvs_name;
45 	char *bdev_name;
46 	uint32_t cluster_sz;
47 	char *clear_method;
48 };
49 
50 static int
51 vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
52 				      struct spdk_lvol_store **lvs)
53 {
54 	if ((uuid == NULL && lvs_name == NULL)) {
55 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "lvs UUID nor lvs name specified\n");
56 		return -EINVAL;
57 	} else if ((uuid && lvs_name)) {
58 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid,
59 			     lvs_name);
60 		return -EINVAL;
61 	} else if (uuid) {
62 		*lvs = vbdev_get_lvol_store_by_uuid(uuid);
63 
64 		if (*lvs == NULL) {
65 			SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "blobstore with UUID '%s' not found\n", uuid);
66 			return -ENODEV;
67 		}
68 	} else if (lvs_name) {
69 
70 		*lvs = vbdev_get_lvol_store_by_name(lvs_name);
71 
72 		if (*lvs == NULL) {
73 			SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "blobstore with name '%s' not found\n", lvs_name);
74 			return -ENODEV;
75 		}
76 	}
77 	return 0;
78 }
79 
80 static void
81 free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
82 {
83 	free(req->bdev_name);
84 	free(req->lvs_name);
85 	free(req->clear_method);
86 }
87 
88 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = {
89 	{"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string},
90 	{"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true},
91 	{"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string},
92 	{"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true},
93 };
94 
95 static void
96 rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
97 {
98 	struct spdk_json_write_ctx *w;
99 	char lvol_store_uuid[SPDK_UUID_STRING_LEN];
100 	struct spdk_jsonrpc_request *request = cb_arg;
101 
102 	if (lvserrno != 0) {
103 		goto invalid;
104 	}
105 
106 	spdk_uuid_fmt_lower(lvol_store_uuid, sizeof(lvol_store_uuid), &lvol_store->uuid);
107 
108 	w = spdk_jsonrpc_begin_result(request);
109 	spdk_json_write_string(w, lvol_store_uuid);
110 	spdk_jsonrpc_end_result(request, w);
111 	return;
112 
113 invalid:
114 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
115 					 spdk_strerror(-lvserrno));
116 }
117 
118 static void
119 rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
120 			     const struct spdk_json_val *params)
121 {
122 	struct rpc_bdev_lvol_create_lvstore req = {};
123 	struct spdk_bdev *bdev;
124 	int rc = 0;
125 	enum lvs_clear_method clear_method;
126 
127 	if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
128 				    SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
129 				    &req)) {
130 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
131 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
132 						 "spdk_json_decode_object failed");
133 		goto cleanup;
134 	}
135 
136 	bdev = spdk_bdev_get_by_name(req.bdev_name);
137 	if (bdev == NULL) {
138 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.bdev_name);
139 		spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, "Bdev %s not found", req.bdev_name);
140 		goto cleanup;
141 	}
142 
143 	if (req.clear_method != NULL) {
144 		if (!strcasecmp(req.clear_method, "none")) {
145 			clear_method = LVS_CLEAR_WITH_NONE;
146 		} else if (!strcasecmp(req.clear_method, "unmap")) {
147 			clear_method = LVS_CLEAR_WITH_UNMAP;
148 		} else if (!strcasecmp(req.clear_method, "write_zeroes")) {
149 			clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
150 		} else {
151 			spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
152 			goto cleanup;
153 		}
154 	} else {
155 		clear_method = LVS_CLEAR_WITH_UNMAP;
156 	}
157 
158 	rc = vbdev_lvs_create(bdev, req.lvs_name, req.cluster_sz, clear_method,
159 			      rpc_lvol_store_construct_cb, request);
160 	if (rc < 0) {
161 		spdk_jsonrpc_send_error_response(request, -rc, spdk_strerror(rc));
162 		goto cleanup;
163 	}
164 	free_rpc_bdev_lvol_create_lvstore(&req);
165 
166 	return;
167 
168 cleanup:
169 	free_rpc_bdev_lvol_create_lvstore(&req);
170 }
171 SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME)
172 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_create_lvstore, construct_lvol_store)
173 
174 struct rpc_bdev_lvol_rename_lvstore {
175 	char *old_name;
176 	char *new_name;
177 };
178 
179 static void
180 free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
181 {
182 	free(req->old_name);
183 	free(req->new_name);
184 }
185 
186 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = {
187 	{"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string},
188 	{"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string},
189 };
190 
191 static void
192 rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
193 {
194 	struct spdk_json_write_ctx *w;
195 	struct spdk_jsonrpc_request *request = cb_arg;
196 
197 	if (lvserrno != 0) {
198 		goto invalid;
199 	}
200 
201 	w = spdk_jsonrpc_begin_result(request);
202 	spdk_json_write_bool(w, true);
203 	spdk_jsonrpc_end_result(request, w);
204 	return;
205 
206 invalid:
207 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
208 					 spdk_strerror(-lvserrno));
209 }
210 
211 static void
212 rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
213 			     const struct spdk_json_val *params)
214 {
215 	struct rpc_bdev_lvol_rename_lvstore req = {};
216 	struct spdk_lvol_store *lvs;
217 
218 	if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders,
219 				    SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders),
220 				    &req)) {
221 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
222 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
223 						 "spdk_json_decode_object failed");
224 		goto cleanup;
225 	}
226 
227 	lvs = vbdev_get_lvol_store_by_name(req.old_name);
228 	if (lvs == NULL) {
229 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "no lvs existing for given name\n");
230 		spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
231 		goto cleanup;
232 	}
233 
234 	vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
235 
236 cleanup:
237 	free_rpc_bdev_lvol_rename_lvstore(&req);
238 }
239 SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME)
240 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_rename_lvstore, rename_lvol_store)
241 
242 struct rpc_bdev_lvol_delete_lvstore {
243 	char *uuid;
244 	char *lvs_name;
245 };
246 
247 static void
248 free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
249 {
250 	free(req->uuid);
251 	free(req->lvs_name);
252 }
253 
254 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = {
255 	{"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true},
256 	{"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true},
257 };
258 
259 static void
260 rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
261 {
262 	struct spdk_json_write_ctx *w;
263 	struct spdk_jsonrpc_request *request = cb_arg;
264 
265 	if (lvserrno != 0) {
266 		goto invalid;
267 	}
268 
269 	w = spdk_jsonrpc_begin_result(request);
270 	spdk_json_write_bool(w, true);
271 	spdk_jsonrpc_end_result(request, w);
272 	return;
273 
274 invalid:
275 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
276 					 spdk_strerror(-lvserrno));
277 }
278 
279 static void
280 rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
281 			     const struct spdk_json_val *params)
282 {
283 	struct rpc_bdev_lvol_delete_lvstore req = {};
284 	struct spdk_lvol_store *lvs = NULL;
285 	int rc;
286 
287 	if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders,
288 				    SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders),
289 				    &req)) {
290 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
291 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
292 						 "spdk_json_decode_object failed");
293 		goto cleanup;
294 	}
295 
296 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
297 	if (rc != 0) {
298 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
299 		goto cleanup;
300 	}
301 
302 	vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
303 
304 cleanup:
305 	free_rpc_bdev_lvol_delete_lvstore(&req);
306 }
307 SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME)
308 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_delete_lvstore, destroy_lvol_store)
309 
310 struct rpc_bdev_lvol_create {
311 	char *uuid;
312 	char *lvs_name;
313 	char *lvol_name;
314 	uint64_t size;
315 	bool thin_provision;
316 	char *clear_method;
317 };
318 
319 static void
320 free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
321 {
322 	free(req->uuid);
323 	free(req->lvs_name);
324 	free(req->lvol_name);
325 	free(req->clear_method);
326 }
327 
328 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
329 	{"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
330 	{"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
331 	{"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
332 	{"size", offsetof(struct rpc_bdev_lvol_create, size), spdk_json_decode_uint64},
333 	{"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true},
334 	{"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true},
335 };
336 
337 static void
338 rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
339 {
340 	struct spdk_json_write_ctx *w;
341 	struct spdk_jsonrpc_request *request = cb_arg;
342 
343 	if (lvolerrno != 0) {
344 		goto invalid;
345 	}
346 
347 	w = spdk_jsonrpc_begin_result(request);
348 	spdk_json_write_string(w, lvol->unique_id);
349 	spdk_jsonrpc_end_result(request, w);
350 	return;
351 
352 invalid:
353 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
354 					 spdk_strerror(-lvolerrno));
355 }
356 
357 static void
358 rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
359 		     const struct spdk_json_val *params)
360 {
361 	struct rpc_bdev_lvol_create req = {};
362 	enum lvol_clear_method clear_method;
363 	int rc = 0;
364 	struct spdk_lvol_store *lvs = NULL;
365 
366 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Creating blob\n");
367 
368 	if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
369 				    SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
370 				    &req)) {
371 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
372 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
373 						 "spdk_json_decode_object failed");
374 		goto cleanup;
375 	}
376 
377 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
378 	if (rc != 0) {
379 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
380 		goto cleanup;
381 	}
382 
383 	if (req.clear_method != NULL) {
384 		if (!strcasecmp(req.clear_method, "none")) {
385 			clear_method = LVOL_CLEAR_WITH_NONE;
386 		} else if (!strcasecmp(req.clear_method, "unmap")) {
387 			clear_method = LVOL_CLEAR_WITH_UNMAP;
388 		} else if (!strcasecmp(req.clear_method, "write_zeroes")) {
389 			clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES;
390 		} else {
391 			spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
392 			goto cleanup;
393 		}
394 	} else {
395 		clear_method = LVOL_CLEAR_WITH_DEFAULT;
396 	}
397 
398 	rc = vbdev_lvol_create(lvs, req.lvol_name, req.size, req.thin_provision,
399 			       clear_method, rpc_bdev_lvol_create_cb, request);
400 	if (rc < 0) {
401 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
402 		goto cleanup;
403 	}
404 
405 cleanup:
406 	free_rpc_bdev_lvol_create(&req);
407 }
408 
409 SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME)
410 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_create, construct_lvol_bdev)
411 
412 struct rpc_bdev_lvol_snapshot {
413 	char *lvol_name;
414 	char *snapshot_name;
415 };
416 
417 static void
418 free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
419 {
420 	free(req->lvol_name);
421 	free(req->snapshot_name);
422 }
423 
424 static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = {
425 	{"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string},
426 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string},
427 };
428 
429 static void
430 rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
431 {
432 	struct spdk_json_write_ctx *w;
433 	struct spdk_jsonrpc_request *request = cb_arg;
434 
435 	if (lvolerrno != 0) {
436 		goto invalid;
437 	}
438 
439 	w = spdk_jsonrpc_begin_result(request);
440 	spdk_json_write_string(w, lvol->unique_id);
441 	spdk_jsonrpc_end_result(request, w);
442 	return;
443 
444 invalid:
445 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
446 					 spdk_strerror(-lvolerrno));
447 }
448 
449 static void
450 rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
451 		       const struct spdk_json_val *params)
452 {
453 	struct rpc_bdev_lvol_snapshot req = {};
454 	struct spdk_bdev *bdev;
455 	struct spdk_lvol *lvol;
456 
457 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Snapshotting blob\n");
458 
459 	if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders,
460 				    SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders),
461 				    &req)) {
462 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
463 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
464 						 "spdk_json_decode_object failed");
465 		goto cleanup;
466 	}
467 
468 	bdev = spdk_bdev_get_by_name(req.lvol_name);
469 	if (bdev == NULL) {
470 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "bdev '%s' does not exist\n", req.lvol_name);
471 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
472 		goto cleanup;
473 	}
474 
475 	lvol = vbdev_lvol_get_from_bdev(bdev);
476 	if (lvol == NULL) {
477 		SPDK_ERRLOG("lvol does not exist\n");
478 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
479 		goto cleanup;
480 	}
481 
482 	vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
483 
484 cleanup:
485 	free_rpc_bdev_lvol_snapshot(&req);
486 }
487 
488 SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME)
489 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_snapshot, snapshot_lvol_bdev)
490 
491 struct rpc_bdev_lvol_clone {
492 	char *snapshot_name;
493 	char *clone_name;
494 };
495 
496 static void
497 free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
498 {
499 	free(req->snapshot_name);
500 	free(req->clone_name);
501 }
502 
503 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = {
504 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string},
505 	{"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true},
506 };
507 
508 static void
509 rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
510 {
511 	struct spdk_json_write_ctx *w;
512 	struct spdk_jsonrpc_request *request = cb_arg;
513 
514 	if (lvolerrno != 0) {
515 		goto invalid;
516 	}
517 
518 	w = spdk_jsonrpc_begin_result(request);
519 	spdk_json_write_string(w, lvol->unique_id);
520 	spdk_jsonrpc_end_result(request, w);
521 	return;
522 
523 invalid:
524 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
525 					 spdk_strerror(-lvolerrno));
526 }
527 
528 static void
529 rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
530 		    const struct spdk_json_val *params)
531 {
532 	struct rpc_bdev_lvol_clone req = {};
533 	struct spdk_bdev *bdev;
534 	struct spdk_lvol *lvol;
535 
536 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Cloning blob\n");
537 
538 	if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders,
539 				    SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders),
540 				    &req)) {
541 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
542 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
543 						 "spdk_json_decode_object failed");
544 		goto cleanup;
545 	}
546 
547 	bdev = spdk_bdev_get_by_name(req.snapshot_name);
548 	if (bdev == NULL) {
549 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "bdev '%s' does not exist\n", req.snapshot_name);
550 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
551 		goto cleanup;
552 	}
553 
554 	lvol = vbdev_lvol_get_from_bdev(bdev);
555 	if (lvol == NULL) {
556 		SPDK_ERRLOG("lvol does not exist\n");
557 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
558 		goto cleanup;
559 	}
560 
561 	vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
562 
563 cleanup:
564 	free_rpc_bdev_lvol_clone(&req);
565 }
566 
567 SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME)
568 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_clone, clone_lvol_bdev)
569 
570 struct rpc_bdev_lvol_rename {
571 	char *old_name;
572 	char *new_name;
573 };
574 
575 static void
576 free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
577 {
578 	free(req->old_name);
579 	free(req->new_name);
580 }
581 
582 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = {
583 	{"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string},
584 	{"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string},
585 };
586 
587 static void
588 rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
589 {
590 	struct spdk_json_write_ctx *w;
591 	struct spdk_jsonrpc_request *request = cb_arg;
592 
593 	if (lvolerrno != 0) {
594 		goto invalid;
595 	}
596 
597 	w = spdk_jsonrpc_begin_result(request);
598 	spdk_json_write_bool(w, true);
599 	spdk_jsonrpc_end_result(request, w);
600 	return;
601 
602 invalid:
603 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
604 					 spdk_strerror(-lvolerrno));
605 }
606 
607 static void
608 rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
609 		     const struct spdk_json_val *params)
610 {
611 	struct rpc_bdev_lvol_rename req = {};
612 	struct spdk_bdev *bdev;
613 	struct spdk_lvol *lvol;
614 
615 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Renaming lvol\n");
616 
617 	if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders,
618 				    SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders),
619 				    &req)) {
620 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
621 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
622 						 "spdk_json_decode_object failed");
623 		goto cleanup;
624 	}
625 
626 	bdev = spdk_bdev_get_by_name(req.old_name);
627 	if (bdev == NULL) {
628 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
629 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
630 		goto cleanup;
631 	}
632 
633 	lvol = vbdev_lvol_get_from_bdev(bdev);
634 	if (lvol == NULL) {
635 		SPDK_ERRLOG("lvol does not exist\n");
636 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
637 		goto cleanup;
638 	}
639 
640 	vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
641 
642 cleanup:
643 	free_rpc_bdev_lvol_rename(&req);
644 }
645 
646 SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
647 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_rename, rename_lvol_bdev)
648 
649 struct rpc_bdev_lvol_inflate {
650 	char *name;
651 };
652 
653 static void
654 free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
655 {
656 	free(req->name);
657 }
658 
659 static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = {
660 	{"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string},
661 };
662 
663 static void
664 rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
665 {
666 	struct spdk_json_write_ctx *w;
667 	struct spdk_jsonrpc_request *request = cb_arg;
668 
669 	if (lvolerrno != 0) {
670 		goto invalid;
671 	}
672 
673 	w = spdk_jsonrpc_begin_result(request);
674 	spdk_json_write_bool(w, true);
675 	spdk_jsonrpc_end_result(request, w);
676 	return;
677 
678 invalid:
679 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
680 					 spdk_strerror(-lvolerrno));
681 }
682 
683 static void
684 rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
685 		      const struct spdk_json_val *params)
686 {
687 	struct rpc_bdev_lvol_inflate req = {};
688 	struct spdk_bdev *bdev;
689 	struct spdk_lvol *lvol;
690 
691 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Inflating lvol\n");
692 
693 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
694 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
695 				    &req)) {
696 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
697 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
698 						 "spdk_json_decode_object failed");
699 		goto cleanup;
700 	}
701 
702 	bdev = spdk_bdev_get_by_name(req.name);
703 	if (bdev == NULL) {
704 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
705 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
706 		goto cleanup;
707 	}
708 
709 	lvol = vbdev_lvol_get_from_bdev(bdev);
710 	if (lvol == NULL) {
711 		SPDK_ERRLOG("lvol does not exist\n");
712 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
713 		goto cleanup;
714 	}
715 
716 	spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
717 
718 cleanup:
719 	free_rpc_bdev_lvol_inflate(&req);
720 }
721 
722 SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
723 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_inflate, inflate_lvol_bdev)
724 
725 static void
726 rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
727 			      const struct spdk_json_val *params)
728 {
729 	struct rpc_bdev_lvol_inflate req = {};
730 	struct spdk_bdev *bdev;
731 	struct spdk_lvol *lvol;
732 
733 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Decoupling parent of lvol\n");
734 
735 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
736 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
737 				    &req)) {
738 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
739 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
740 						 "spdk_json_decode_object failed");
741 		goto cleanup;
742 	}
743 
744 	bdev = spdk_bdev_get_by_name(req.name);
745 	if (bdev == NULL) {
746 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
747 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
748 		goto cleanup;
749 	}
750 
751 	lvol = vbdev_lvol_get_from_bdev(bdev);
752 	if (lvol == NULL) {
753 		SPDK_ERRLOG("lvol does not exist\n");
754 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
755 		goto cleanup;
756 	}
757 
758 	spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
759 
760 cleanup:
761 	free_rpc_bdev_lvol_inflate(&req);
762 }
763 
764 SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME)
765 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_decouple_parent, decouple_parent_lvol_bdev)
766 
767 struct rpc_bdev_lvol_resize {
768 	char *name;
769 	uint64_t size;
770 };
771 
772 static void
773 free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
774 {
775 	free(req->name);
776 }
777 
778 static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
779 	{"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
780 	{"size", offsetof(struct rpc_bdev_lvol_resize, size), spdk_json_decode_uint64},
781 };
782 
783 static void
784 rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
785 {
786 	struct spdk_json_write_ctx *w;
787 	struct spdk_jsonrpc_request *request = cb_arg;
788 
789 	if (lvolerrno != 0) {
790 		goto invalid;
791 	}
792 
793 	w = spdk_jsonrpc_begin_result(request);
794 	spdk_json_write_bool(w, true);
795 	spdk_jsonrpc_end_result(request, w);
796 	return;
797 
798 invalid:
799 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
800 					 spdk_strerror(-lvolerrno));
801 }
802 
803 static void
804 rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
805 		     const struct spdk_json_val *params)
806 {
807 	struct rpc_bdev_lvol_resize req = {};
808 	struct spdk_bdev *bdev;
809 	struct spdk_lvol *lvol;
810 
811 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Resizing lvol\n");
812 
813 	if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
814 				    SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
815 				    &req)) {
816 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
817 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
818 						 "spdk_json_decode_object failed");
819 		goto cleanup;
820 	}
821 
822 	bdev = spdk_bdev_get_by_name(req.name);
823 	if (bdev == NULL) {
824 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
825 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
826 		goto cleanup;
827 	}
828 
829 	lvol = vbdev_lvol_get_from_bdev(bdev);
830 	if (lvol == NULL) {
831 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
832 		goto cleanup;
833 	}
834 
835 	vbdev_lvol_resize(lvol, req.size, rpc_bdev_lvol_resize_cb, request);
836 
837 cleanup:
838 	free_rpc_bdev_lvol_resize(&req);
839 }
840 
841 SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
842 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_resize, resize_lvol_bdev)
843 
844 struct rpc_set_ro_lvol_bdev {
845 	char *name;
846 };
847 
848 static void
849 free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
850 {
851 	free(req->name);
852 }
853 
854 static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
855 	{"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
856 };
857 
858 static void
859 rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
860 {
861 	struct spdk_json_write_ctx *w;
862 	struct spdk_jsonrpc_request *request = cb_arg;
863 
864 	if (lvolerrno != 0) {
865 		goto invalid;
866 	}
867 
868 	w = spdk_jsonrpc_begin_result(request);
869 	spdk_json_write_bool(w, true);
870 	spdk_jsonrpc_end_result(request, w);
871 	return;
872 
873 invalid:
874 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
875 					 spdk_strerror(-lvolerrno));
876 }
877 
878 static void
879 rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
880 			    const struct spdk_json_val *params)
881 {
882 	struct rpc_set_ro_lvol_bdev req = {};
883 	struct spdk_bdev *bdev;
884 	struct spdk_lvol *lvol;
885 
886 	SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Setting lvol as read only\n");
887 
888 	if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
889 				    SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
890 				    &req)) {
891 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
892 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
893 						 "spdk_json_decode_object failed");
894 		goto cleanup;
895 	}
896 
897 	if (req.name == NULL) {
898 		SPDK_ERRLOG("missing name param\n");
899 		spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
900 		goto cleanup;
901 	}
902 
903 	bdev = spdk_bdev_get_by_name(req.name);
904 	if (bdev == NULL) {
905 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
906 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
907 		goto cleanup;
908 	}
909 
910 	lvol = vbdev_lvol_get_from_bdev(bdev);
911 	if (lvol == NULL) {
912 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
913 		goto cleanup;
914 	}
915 
916 	vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
917 
918 cleanup:
919 	free_rpc_set_ro_lvol_bdev(&req);
920 }
921 
922 SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
923 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_set_read_only, set_read_only_lvol_bdev)
924 
925 struct rpc_bdev_lvol_delete {
926 	char *name;
927 };
928 
929 static void
930 free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
931 {
932 	free(req->name);
933 }
934 
935 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
936 	{"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
937 };
938 
939 static void
940 rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
941 {
942 	struct spdk_json_write_ctx *w;
943 	struct spdk_jsonrpc_request *request = cb_arg;
944 
945 	if (lvolerrno != 0) {
946 		goto invalid;
947 	}
948 
949 	w = spdk_jsonrpc_begin_result(request);
950 	spdk_json_write_bool(w, true);
951 	spdk_jsonrpc_end_result(request, w);
952 	return;
953 
954 invalid:
955 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
956 					 spdk_strerror(-lvolerrno));
957 }
958 
959 static void
960 rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
961 		     const struct spdk_json_val *params)
962 {
963 	struct rpc_bdev_lvol_delete req = {};
964 	struct spdk_bdev *bdev;
965 	struct spdk_lvol *lvol;
966 
967 	if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
968 				    SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
969 				    &req)) {
970 		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
971 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
972 						 "spdk_json_decode_object failed");
973 		goto cleanup;
974 	}
975 
976 	bdev = spdk_bdev_get_by_name(req.name);
977 	if (bdev == NULL) {
978 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
979 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
980 		goto cleanup;
981 	}
982 
983 	lvol = vbdev_lvol_get_from_bdev(bdev);
984 	if (lvol == NULL) {
985 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
986 		goto cleanup;
987 	}
988 
989 	vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
990 
991 cleanup:
992 	free_rpc_bdev_lvol_delete(&req);
993 }
994 
995 SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
996 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_delete, destroy_lvol_bdev)
997 
998 struct rpc_bdev_lvol_get_lvstores {
999 	char *uuid;
1000 	char *lvs_name;
1001 };
1002 
1003 static void
1004 free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1005 {
1006 	free(req->uuid);
1007 	free(req->lvs_name);
1008 }
1009 
1010 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
1011 	{"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
1012 	{"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
1013 };
1014 
1015 static void
1016 rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1017 {
1018 	struct spdk_blob_store *bs;
1019 	uint64_t cluster_size;
1020 	char uuid[SPDK_UUID_STRING_LEN];
1021 
1022 	bs = lvs_bdev->lvs->blobstore;
1023 	cluster_size = spdk_bs_get_cluster_size(bs);
1024 
1025 	spdk_json_write_object_begin(w);
1026 
1027 	spdk_uuid_fmt_lower(uuid, sizeof(uuid), &lvs_bdev->lvs->uuid);
1028 	spdk_json_write_named_string(w, "uuid", uuid);
1029 
1030 	spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
1031 
1032 	spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1033 
1034 	spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1035 
1036 	spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1037 
1038 	spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1039 
1040 	spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1041 
1042 	spdk_json_write_object_end(w);
1043 }
1044 
1045 static void
1046 rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1047 			   const struct spdk_json_val *params)
1048 {
1049 	struct rpc_bdev_lvol_get_lvstores req = {};
1050 	struct spdk_json_write_ctx *w;
1051 	struct lvol_store_bdev *lvs_bdev = NULL;
1052 	struct spdk_lvol_store *lvs = NULL;
1053 	int rc;
1054 
1055 	if (params != NULL) {
1056 		if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
1057 					    SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
1058 					    &req)) {
1059 			SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
1060 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1061 							 "spdk_json_decode_object failed");
1062 			goto cleanup;
1063 		}
1064 
1065 		rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1066 		if (rc != 0) {
1067 			spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1068 			goto cleanup;
1069 		}
1070 
1071 		lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1072 		if (lvs_bdev == NULL) {
1073 			spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1074 			goto cleanup;
1075 		}
1076 	}
1077 
1078 	w = spdk_jsonrpc_begin_result(request);
1079 	spdk_json_write_array_begin(w);
1080 
1081 	if (lvs_bdev != NULL) {
1082 		rpc_dump_lvol_store_info(w, lvs_bdev);
1083 	} else {
1084 		for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1085 		     lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1086 			rpc_dump_lvol_store_info(w, lvs_bdev);
1087 		}
1088 	}
1089 	spdk_json_write_array_end(w);
1090 
1091 	spdk_jsonrpc_end_result(request, w);
1092 
1093 cleanup:
1094 	free_rpc_bdev_lvol_get_lvstores(&req);
1095 }
1096 
1097 SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1098 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
1099