xref: /spdk/module/bdev/lvol/vbdev_lvol_rpc.c (revision f387b7fe187572d4505323dfb7a5dc1318638dda)
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_bdev_lvol_create_lvstore {
17 	char *lvs_name;
18 	char *bdev_name;
19 	uint32_t cluster_sz;
20 	char *clear_method;
21 	uint32_t num_md_pages_per_cluster_ratio;
22 };
23 
24 static int
25 vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
26 				      struct spdk_lvol_store **lvs)
27 {
28 	if ((uuid == NULL && lvs_name == NULL)) {
29 		SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
30 		return -EINVAL;
31 	} else if ((uuid && lvs_name)) {
32 		SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid,
33 			     lvs_name);
34 		return -EINVAL;
35 	} else if (uuid) {
36 		*lvs = vbdev_get_lvol_store_by_uuid(uuid);
37 
38 		if (*lvs == NULL) {
39 			SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
40 			return -ENODEV;
41 		}
42 	} else if (lvs_name) {
43 
44 		*lvs = vbdev_get_lvol_store_by_name(lvs_name);
45 
46 		if (*lvs == NULL) {
47 			SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
48 			return -ENODEV;
49 		}
50 	}
51 	return 0;
52 }
53 
54 static void
55 free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
56 {
57 	free(req->bdev_name);
58 	free(req->lvs_name);
59 	free(req->clear_method);
60 }
61 
62 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = {
63 	{"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string},
64 	{"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true},
65 	{"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string},
66 	{"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true},
67 	{"num_md_pages_per_cluster_ratio", offsetof(struct rpc_bdev_lvol_create_lvstore, num_md_pages_per_cluster_ratio), spdk_json_decode_uint32, true},
68 };
69 
70 static void
71 rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
72 {
73 	struct spdk_json_write_ctx *w;
74 	struct spdk_jsonrpc_request *request = cb_arg;
75 
76 	if (lvserrno != 0) {
77 		goto invalid;
78 	}
79 
80 	w = spdk_jsonrpc_begin_result(request);
81 	spdk_json_write_uuid(w, &lvol_store->uuid);
82 	spdk_jsonrpc_end_result(request, w);
83 	return;
84 
85 invalid:
86 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
87 					 spdk_strerror(-lvserrno));
88 }
89 
90 static void
91 rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
92 			     const struct spdk_json_val *params)
93 {
94 	struct rpc_bdev_lvol_create_lvstore req = {};
95 	int rc = 0;
96 	enum lvs_clear_method clear_method;
97 
98 	if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
99 				    SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
100 				    &req)) {
101 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
102 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
103 						 "spdk_json_decode_object failed");
104 		goto cleanup;
105 	}
106 
107 	if (req.clear_method != NULL) {
108 		if (!strcasecmp(req.clear_method, "none")) {
109 			clear_method = LVS_CLEAR_WITH_NONE;
110 		} else if (!strcasecmp(req.clear_method, "unmap")) {
111 			clear_method = LVS_CLEAR_WITH_UNMAP;
112 		} else if (!strcasecmp(req.clear_method, "write_zeroes")) {
113 			clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
114 		} else {
115 			spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
116 			goto cleanup;
117 		}
118 	} else {
119 		clear_method = LVS_CLEAR_WITH_UNMAP;
120 	}
121 
122 	rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
123 			      req.num_md_pages_per_cluster_ratio, rpc_lvol_store_construct_cb, request);
124 	if (rc < 0) {
125 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
126 		goto cleanup;
127 	}
128 	free_rpc_bdev_lvol_create_lvstore(&req);
129 
130 	return;
131 
132 cleanup:
133 	free_rpc_bdev_lvol_create_lvstore(&req);
134 }
135 SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME)
136 
137 struct rpc_bdev_lvol_rename_lvstore {
138 	char *old_name;
139 	char *new_name;
140 };
141 
142 static void
143 free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
144 {
145 	free(req->old_name);
146 	free(req->new_name);
147 }
148 
149 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = {
150 	{"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string},
151 	{"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string},
152 };
153 
154 static void
155 rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
156 {
157 	struct spdk_jsonrpc_request *request = cb_arg;
158 
159 	if (lvserrno != 0) {
160 		goto invalid;
161 	}
162 
163 	spdk_jsonrpc_send_bool_response(request, true);
164 	return;
165 
166 invalid:
167 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
168 					 spdk_strerror(-lvserrno));
169 }
170 
171 static void
172 rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
173 			     const struct spdk_json_val *params)
174 {
175 	struct rpc_bdev_lvol_rename_lvstore req = {};
176 	struct spdk_lvol_store *lvs;
177 
178 	if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders,
179 				    SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders),
180 				    &req)) {
181 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
182 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
183 						 "spdk_json_decode_object failed");
184 		goto cleanup;
185 	}
186 
187 	lvs = vbdev_get_lvol_store_by_name(req.old_name);
188 	if (lvs == NULL) {
189 		SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
190 		spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
191 		goto cleanup;
192 	}
193 
194 	vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
195 
196 cleanup:
197 	free_rpc_bdev_lvol_rename_lvstore(&req);
198 }
199 SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME)
200 
201 struct rpc_bdev_lvol_delete_lvstore {
202 	char *uuid;
203 	char *lvs_name;
204 };
205 
206 static void
207 free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
208 {
209 	free(req->uuid);
210 	free(req->lvs_name);
211 }
212 
213 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = {
214 	{"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true},
215 	{"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true},
216 };
217 
218 static void
219 rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
220 {
221 	struct spdk_jsonrpc_request *request = cb_arg;
222 
223 	if (lvserrno != 0) {
224 		goto invalid;
225 	}
226 
227 	spdk_jsonrpc_send_bool_response(request, true);
228 	return;
229 
230 invalid:
231 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
232 					 spdk_strerror(-lvserrno));
233 }
234 
235 static void
236 rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
237 			     const struct spdk_json_val *params)
238 {
239 	struct rpc_bdev_lvol_delete_lvstore req = {};
240 	struct spdk_lvol_store *lvs = NULL;
241 	int rc;
242 
243 	if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders,
244 				    SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders),
245 				    &req)) {
246 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
247 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
248 						 "spdk_json_decode_object failed");
249 		goto cleanup;
250 	}
251 
252 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
253 	if (rc != 0) {
254 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
255 		goto cleanup;
256 	}
257 
258 	vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
259 
260 cleanup:
261 	free_rpc_bdev_lvol_delete_lvstore(&req);
262 }
263 SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME)
264 
265 struct rpc_bdev_lvol_create {
266 	char *uuid;
267 	char *lvs_name;
268 	char *lvol_name;
269 	uint64_t size_in_mib;
270 	bool thin_provision;
271 	char *clear_method;
272 };
273 
274 static void
275 free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
276 {
277 	free(req->uuid);
278 	free(req->lvs_name);
279 	free(req->lvol_name);
280 	free(req->clear_method);
281 }
282 
283 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
284 	{"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
285 	{"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
286 	{"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
287 	{"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64},
288 	{"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true},
289 	{"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true},
290 };
291 
292 static void
293 rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
294 {
295 	struct spdk_json_write_ctx *w;
296 	struct spdk_jsonrpc_request *request = cb_arg;
297 
298 	if (lvolerrno != 0) {
299 		goto invalid;
300 	}
301 
302 	w = spdk_jsonrpc_begin_result(request);
303 	spdk_json_write_string(w, lvol->unique_id);
304 	spdk_jsonrpc_end_result(request, w);
305 	return;
306 
307 invalid:
308 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
309 					 spdk_strerror(-lvolerrno));
310 }
311 
312 static void
313 rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
314 		     const struct spdk_json_val *params)
315 {
316 	struct rpc_bdev_lvol_create req = {};
317 	enum lvol_clear_method clear_method;
318 	int rc = 0;
319 	struct spdk_lvol_store *lvs = NULL;
320 
321 	SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
322 
323 	if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
324 				    SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
325 				    &req)) {
326 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
327 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
328 						 "spdk_json_decode_object failed");
329 		goto cleanup;
330 	}
331 
332 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
333 	if (rc != 0) {
334 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
335 		goto cleanup;
336 	}
337 
338 	if (req.clear_method != NULL) {
339 		if (!strcasecmp(req.clear_method, "none")) {
340 			clear_method = LVOL_CLEAR_WITH_NONE;
341 		} else if (!strcasecmp(req.clear_method, "unmap")) {
342 			clear_method = LVOL_CLEAR_WITH_UNMAP;
343 		} else if (!strcasecmp(req.clear_method, "write_zeroes")) {
344 			clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES;
345 		} else {
346 			spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
347 			goto cleanup;
348 		}
349 	} else {
350 		clear_method = LVOL_CLEAR_WITH_DEFAULT;
351 	}
352 
353 	rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
354 			       req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
355 	if (rc < 0) {
356 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
357 		goto cleanup;
358 	}
359 
360 cleanup:
361 	free_rpc_bdev_lvol_create(&req);
362 }
363 
364 SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME)
365 
366 struct rpc_bdev_lvol_snapshot {
367 	char *lvol_name;
368 	char *snapshot_name;
369 };
370 
371 static void
372 free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
373 {
374 	free(req->lvol_name);
375 	free(req->snapshot_name);
376 }
377 
378 static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = {
379 	{"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string},
380 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string},
381 };
382 
383 static void
384 rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
385 {
386 	struct spdk_json_write_ctx *w;
387 	struct spdk_jsonrpc_request *request = cb_arg;
388 
389 	if (lvolerrno != 0) {
390 		goto invalid;
391 	}
392 
393 	w = spdk_jsonrpc_begin_result(request);
394 	spdk_json_write_string(w, lvol->unique_id);
395 	spdk_jsonrpc_end_result(request, w);
396 	return;
397 
398 invalid:
399 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
400 					 spdk_strerror(-lvolerrno));
401 }
402 
403 static void
404 rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
405 		       const struct spdk_json_val *params)
406 {
407 	struct rpc_bdev_lvol_snapshot req = {};
408 	struct spdk_bdev *bdev;
409 	struct spdk_lvol *lvol;
410 
411 	SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
412 
413 	if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders,
414 				    SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders),
415 				    &req)) {
416 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
417 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
418 						 "spdk_json_decode_object failed");
419 		goto cleanup;
420 	}
421 
422 	bdev = spdk_bdev_get_by_name(req.lvol_name);
423 	if (bdev == NULL) {
424 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name);
425 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
426 		goto cleanup;
427 	}
428 
429 	lvol = vbdev_lvol_get_from_bdev(bdev);
430 	if (lvol == NULL) {
431 		SPDK_ERRLOG("lvol does not exist\n");
432 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
433 		goto cleanup;
434 	}
435 
436 	vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
437 
438 cleanup:
439 	free_rpc_bdev_lvol_snapshot(&req);
440 }
441 
442 SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME)
443 
444 struct rpc_bdev_lvol_clone {
445 	char *snapshot_name;
446 	char *clone_name;
447 };
448 
449 static void
450 free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
451 {
452 	free(req->snapshot_name);
453 	free(req->clone_name);
454 }
455 
456 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = {
457 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string},
458 	{"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true},
459 };
460 
461 static void
462 rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
463 {
464 	struct spdk_json_write_ctx *w;
465 	struct spdk_jsonrpc_request *request = cb_arg;
466 
467 	if (lvolerrno != 0) {
468 		goto invalid;
469 	}
470 
471 	w = spdk_jsonrpc_begin_result(request);
472 	spdk_json_write_string(w, lvol->unique_id);
473 	spdk_jsonrpc_end_result(request, w);
474 	return;
475 
476 invalid:
477 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
478 					 spdk_strerror(-lvolerrno));
479 }
480 
481 static void
482 rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
483 		    const struct spdk_json_val *params)
484 {
485 	struct rpc_bdev_lvol_clone req = {};
486 	struct spdk_bdev *bdev;
487 	struct spdk_lvol *lvol;
488 
489 	SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
490 
491 	if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders,
492 				    SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders),
493 				    &req)) {
494 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
495 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
496 						 "spdk_json_decode_object failed");
497 		goto cleanup;
498 	}
499 
500 	bdev = spdk_bdev_get_by_name(req.snapshot_name);
501 	if (bdev == NULL) {
502 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name);
503 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
504 		goto cleanup;
505 	}
506 
507 	lvol = vbdev_lvol_get_from_bdev(bdev);
508 	if (lvol == NULL) {
509 		SPDK_ERRLOG("lvol does not exist\n");
510 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
511 		goto cleanup;
512 	}
513 
514 	vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
515 
516 cleanup:
517 	free_rpc_bdev_lvol_clone(&req);
518 }
519 
520 SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME)
521 
522 struct rpc_bdev_lvol_clone_bdev {
523 	/* name or UUID. Whichever is used, the UUID will be stored in the lvol's metadata. */
524 	char *bdev_name;
525 	char *lvs_name;
526 	char *clone_name;
527 };
528 
529 static void
530 free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req)
531 {
532 	free(req->bdev_name);
533 	free(req->lvs_name);
534 	free(req->clone_name);
535 }
536 
537 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_bdev_decoders[] = {
538 	{
539 		"bdev", offsetof(struct rpc_bdev_lvol_clone_bdev, bdev_name),
540 		spdk_json_decode_string, false
541 	},
542 	{
543 		"lvs_name", offsetof(struct rpc_bdev_lvol_clone_bdev, lvs_name),
544 		spdk_json_decode_string, false
545 	},
546 	{
547 		"clone_name", offsetof(struct rpc_bdev_lvol_clone_bdev, clone_name),
548 		spdk_json_decode_string, false
549 	},
550 };
551 
552 static void
553 rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
554 {
555 	struct rpc_bdev_lvol_clone_bdev req = {};
556 	struct spdk_bdev *bdev;
557 	struct spdk_lvol_store *lvs = NULL;
558 	struct spdk_lvol *lvol;
559 	int rc;
560 
561 	SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n");
562 
563 	if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_bdev_decoders,
564 				    SPDK_COUNTOF(rpc_bdev_lvol_clone_bdev_decoders), &req)) {
565 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
566 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
567 						 "spdk_json_decode_object failed");
568 		goto cleanup;
569 	}
570 
571 	rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs);
572 	if (rc != 0) {
573 		SPDK_INFOLOG(lvol_rpc, "lvs_name '%s' not found\n", req.lvs_name);
574 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
575 						 "lvs does not exist");
576 		goto cleanup;
577 	}
578 
579 	bdev = spdk_bdev_get_by_name(req.bdev_name);
580 	if (bdev == NULL) {
581 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.bdev_name);
582 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
583 						 "bdev does not exist");
584 		goto cleanup;
585 	}
586 
587 	lvol = vbdev_lvol_get_from_bdev(bdev);
588 	if (lvol != NULL && lvol->lvol_store == lvs) {
589 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' is an lvol in lvstore '%s\n", req.bdev_name,
590 			     req.lvs_name);
591 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
592 						 "bdev is an lvol in same lvs as clone; "
593 						 "use bdev_lvol_clone instead");
594 		goto cleanup;
595 	}
596 
597 	vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name,
598 				     rpc_bdev_lvol_clone_cb, request);
599 cleanup:
600 	free_rpc_bdev_lvol_clone_bdev(&req);
601 }
602 
603 SPDK_RPC_REGISTER("bdev_lvol_clone_bdev", rpc_bdev_lvol_clone_bdev, SPDK_RPC_RUNTIME)
604 
605 struct rpc_bdev_lvol_rename {
606 	char *old_name;
607 	char *new_name;
608 };
609 
610 static void
611 free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
612 {
613 	free(req->old_name);
614 	free(req->new_name);
615 }
616 
617 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = {
618 	{"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string},
619 	{"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string},
620 };
621 
622 static void
623 rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
624 {
625 	struct spdk_jsonrpc_request *request = cb_arg;
626 
627 	if (lvolerrno != 0) {
628 		goto invalid;
629 	}
630 
631 	spdk_jsonrpc_send_bool_response(request, true);
632 	return;
633 
634 invalid:
635 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
636 					 spdk_strerror(-lvolerrno));
637 }
638 
639 static void
640 rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
641 		     const struct spdk_json_val *params)
642 {
643 	struct rpc_bdev_lvol_rename req = {};
644 	struct spdk_bdev *bdev;
645 	struct spdk_lvol *lvol;
646 
647 	SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
648 
649 	if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders,
650 				    SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders),
651 				    &req)) {
652 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
653 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
654 						 "spdk_json_decode_object failed");
655 		goto cleanup;
656 	}
657 
658 	bdev = spdk_bdev_get_by_name(req.old_name);
659 	if (bdev == NULL) {
660 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
661 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
662 		goto cleanup;
663 	}
664 
665 	lvol = vbdev_lvol_get_from_bdev(bdev);
666 	if (lvol == NULL) {
667 		SPDK_ERRLOG("lvol does not exist\n");
668 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
669 		goto cleanup;
670 	}
671 
672 	vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
673 
674 cleanup:
675 	free_rpc_bdev_lvol_rename(&req);
676 }
677 
678 SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
679 
680 struct rpc_bdev_lvol_inflate {
681 	char *name;
682 };
683 
684 static void
685 free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
686 {
687 	free(req->name);
688 }
689 
690 static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = {
691 	{"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string},
692 };
693 
694 static void
695 rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
696 {
697 	struct spdk_jsonrpc_request *request = cb_arg;
698 
699 	if (lvolerrno != 0) {
700 		goto invalid;
701 	}
702 
703 	spdk_jsonrpc_send_bool_response(request, true);
704 	return;
705 
706 invalid:
707 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
708 					 spdk_strerror(-lvolerrno));
709 }
710 
711 static void
712 rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
713 		      const struct spdk_json_val *params)
714 {
715 	struct rpc_bdev_lvol_inflate req = {};
716 	struct spdk_bdev *bdev;
717 	struct spdk_lvol *lvol;
718 
719 	SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
720 
721 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
722 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
723 				    &req)) {
724 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
725 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
726 						 "spdk_json_decode_object failed");
727 		goto cleanup;
728 	}
729 
730 	bdev = spdk_bdev_get_by_name(req.name);
731 	if (bdev == NULL) {
732 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
733 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
734 		goto cleanup;
735 	}
736 
737 	lvol = vbdev_lvol_get_from_bdev(bdev);
738 	if (lvol == NULL) {
739 		SPDK_ERRLOG("lvol does not exist\n");
740 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
741 		goto cleanup;
742 	}
743 
744 	spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
745 
746 cleanup:
747 	free_rpc_bdev_lvol_inflate(&req);
748 }
749 
750 SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
751 
752 static void
753 rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
754 			      const struct spdk_json_val *params)
755 {
756 	struct rpc_bdev_lvol_inflate req = {};
757 	struct spdk_bdev *bdev;
758 	struct spdk_lvol *lvol;
759 
760 	SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
761 
762 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
763 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
764 				    &req)) {
765 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
766 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
767 						 "spdk_json_decode_object failed");
768 		goto cleanup;
769 	}
770 
771 	bdev = spdk_bdev_get_by_name(req.name);
772 	if (bdev == NULL) {
773 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
774 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
775 		goto cleanup;
776 	}
777 
778 	lvol = vbdev_lvol_get_from_bdev(bdev);
779 	if (lvol == NULL) {
780 		SPDK_ERRLOG("lvol does not exist\n");
781 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
782 		goto cleanup;
783 	}
784 
785 	spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
786 
787 cleanup:
788 	free_rpc_bdev_lvol_inflate(&req);
789 }
790 
791 SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME)
792 
793 struct rpc_bdev_lvol_resize {
794 	char *name;
795 	uint64_t size_in_mib;
796 };
797 
798 static void
799 free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
800 {
801 	free(req->name);
802 }
803 
804 static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
805 	{"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
806 	{"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64},
807 };
808 
809 static void
810 rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
811 {
812 	struct spdk_jsonrpc_request *request = cb_arg;
813 
814 	if (lvolerrno != 0) {
815 		goto invalid;
816 	}
817 
818 	spdk_jsonrpc_send_bool_response(request, true);
819 	return;
820 
821 invalid:
822 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
823 					 spdk_strerror(-lvolerrno));
824 }
825 
826 static void
827 rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
828 		     const struct spdk_json_val *params)
829 {
830 	struct rpc_bdev_lvol_resize req = {};
831 	struct spdk_bdev *bdev;
832 	struct spdk_lvol *lvol;
833 
834 	SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
835 
836 	if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
837 				    SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
838 				    &req)) {
839 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
840 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
841 						 "spdk_json_decode_object failed");
842 		goto cleanup;
843 	}
844 
845 	bdev = spdk_bdev_get_by_name(req.name);
846 	if (bdev == NULL) {
847 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
848 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
849 		goto cleanup;
850 	}
851 
852 	lvol = vbdev_lvol_get_from_bdev(bdev);
853 	if (lvol == NULL) {
854 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
855 		goto cleanup;
856 	}
857 
858 
859 	vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
860 
861 cleanup:
862 	free_rpc_bdev_lvol_resize(&req);
863 }
864 
865 SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
866 
867 struct rpc_set_ro_lvol_bdev {
868 	char *name;
869 };
870 
871 static void
872 free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
873 {
874 	free(req->name);
875 }
876 
877 static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
878 	{"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
879 };
880 
881 static void
882 rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
883 {
884 	struct spdk_jsonrpc_request *request = cb_arg;
885 
886 	if (lvolerrno != 0) {
887 		goto invalid;
888 	}
889 
890 	spdk_jsonrpc_send_bool_response(request, true);
891 	return;
892 
893 invalid:
894 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
895 					 spdk_strerror(-lvolerrno));
896 }
897 
898 static void
899 rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
900 			    const struct spdk_json_val *params)
901 {
902 	struct rpc_set_ro_lvol_bdev req = {};
903 	struct spdk_bdev *bdev;
904 	struct spdk_lvol *lvol;
905 
906 	SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
907 
908 	if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
909 				    SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
910 				    &req)) {
911 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
912 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
913 						 "spdk_json_decode_object failed");
914 		goto cleanup;
915 	}
916 
917 	if (req.name == NULL) {
918 		SPDK_ERRLOG("missing name param\n");
919 		spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
920 		goto cleanup;
921 	}
922 
923 	bdev = spdk_bdev_get_by_name(req.name);
924 	if (bdev == NULL) {
925 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
926 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
927 		goto cleanup;
928 	}
929 
930 	lvol = vbdev_lvol_get_from_bdev(bdev);
931 	if (lvol == NULL) {
932 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
933 		goto cleanup;
934 	}
935 
936 	vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
937 
938 cleanup:
939 	free_rpc_set_ro_lvol_bdev(&req);
940 }
941 
942 SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
943 
944 struct rpc_bdev_lvol_delete {
945 	char *name;
946 };
947 
948 static void
949 free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
950 {
951 	free(req->name);
952 }
953 
954 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
955 	{"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
956 };
957 
958 static void
959 rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
960 {
961 	struct spdk_jsonrpc_request *request = cb_arg;
962 
963 	if (lvolerrno != 0) {
964 		goto invalid;
965 	}
966 
967 	spdk_jsonrpc_send_bool_response(request, true);
968 	return;
969 
970 invalid:
971 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
972 					 spdk_strerror(-lvolerrno));
973 }
974 
975 static void
976 rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
977 		     const struct spdk_json_val *params)
978 {
979 	struct rpc_bdev_lvol_delete req = {};
980 	struct spdk_bdev *bdev;
981 	struct spdk_lvol *lvol;
982 	struct spdk_uuid uuid;
983 	char *lvs_name, *lvol_name;
984 
985 	if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
986 				    SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
987 				    &req)) {
988 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
989 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
990 						 "spdk_json_decode_object failed");
991 		goto cleanup;
992 	}
993 
994 	/* lvol is not degraded, get lvol via bdev name or alias */
995 	bdev = spdk_bdev_get_by_name(req.name);
996 	if (bdev != NULL) {
997 		lvol = vbdev_lvol_get_from_bdev(bdev);
998 		if (lvol != NULL) {
999 			goto done;
1000 		}
1001 	}
1002 
1003 	/* lvol is degraded, get lvol via UUID */
1004 	if (spdk_uuid_parse(&uuid, req.name) == 0) {
1005 		lvol = spdk_lvol_get_by_uuid(&uuid);
1006 		if (lvol != NULL) {
1007 			goto done;
1008 		}
1009 	}
1010 
1011 	/* lvol is degraded, get lvol via lvs_name/lvol_name */
1012 	lvol_name = strchr(req.name, '/');
1013 	if (lvol_name != NULL) {
1014 		*lvol_name = '\0';
1015 		lvol_name++;
1016 		lvs_name = req.name;
1017 		lvol = spdk_lvol_get_by_names(lvs_name, lvol_name);
1018 		if (lvol != NULL) {
1019 			goto done;
1020 		}
1021 	}
1022 
1023 	/* Could not find lvol, degraded or not. */
1024 	spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1025 	goto cleanup;
1026 
1027 done:
1028 	vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1029 
1030 cleanup:
1031 	free_rpc_bdev_lvol_delete(&req);
1032 }
1033 
1034 SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
1035 
1036 struct rpc_bdev_lvol_get_lvstores {
1037 	char *uuid;
1038 	char *lvs_name;
1039 };
1040 
1041 static void
1042 free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1043 {
1044 	free(req->uuid);
1045 	free(req->lvs_name);
1046 }
1047 
1048 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
1049 	{"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
1050 	{"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
1051 };
1052 
1053 static void
1054 rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1055 {
1056 	struct spdk_blob_store *bs;
1057 	uint64_t cluster_size;
1058 
1059 	bs = lvs_bdev->lvs->blobstore;
1060 	cluster_size = spdk_bs_get_cluster_size(bs);
1061 
1062 	spdk_json_write_object_begin(w);
1063 
1064 	spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
1065 	spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
1066 	spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1067 	spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1068 	spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1069 	spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1070 	spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1071 
1072 	spdk_json_write_object_end(w);
1073 }
1074 
1075 static void
1076 rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1077 			   const struct spdk_json_val *params)
1078 {
1079 	struct rpc_bdev_lvol_get_lvstores req = {};
1080 	struct spdk_json_write_ctx *w;
1081 	struct lvol_store_bdev *lvs_bdev = NULL;
1082 	struct spdk_lvol_store *lvs = NULL;
1083 	int rc;
1084 
1085 	if (params != NULL) {
1086 		if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
1087 					    SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
1088 					    &req)) {
1089 			SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1090 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1091 							 "spdk_json_decode_object failed");
1092 			goto cleanup;
1093 		}
1094 
1095 		rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1096 		if (rc != 0) {
1097 			spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1098 			goto cleanup;
1099 		}
1100 
1101 		lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1102 		if (lvs_bdev == NULL) {
1103 			spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1104 			goto cleanup;
1105 		}
1106 	}
1107 
1108 	w = spdk_jsonrpc_begin_result(request);
1109 	spdk_json_write_array_begin(w);
1110 
1111 	if (lvs_bdev != NULL) {
1112 		rpc_dump_lvol_store_info(w, lvs_bdev);
1113 	} else {
1114 		for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1115 		     lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1116 			rpc_dump_lvol_store_info(w, lvs_bdev);
1117 		}
1118 	}
1119 	spdk_json_write_array_end(w);
1120 
1121 	spdk_jsonrpc_end_result(request, w);
1122 
1123 cleanup:
1124 	free_rpc_bdev_lvol_get_lvstores(&req);
1125 }
1126 
1127 SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1128 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
1129 
1130 struct rpc_bdev_lvol_get_lvols {
1131 	char *lvs_uuid;
1132 	char *lvs_name;
1133 };
1134 
1135 static void
1136 free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
1137 {
1138 	free(req->lvs_uuid);
1139 	free(req->lvs_name);
1140 }
1141 
1142 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = {
1143 	{"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true},
1144 	{"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true},
1145 };
1146 
1147 static void
1148 rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
1149 {
1150 	struct spdk_lvol_store *lvs = lvol->lvol_store;
1151 
1152 	spdk_json_write_object_begin(w);
1153 
1154 	spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
1155 	spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
1156 	spdk_json_write_named_string(w, "name", lvol->name);
1157 	spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
1158 	spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
1159 	spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
1160 	spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
1161 	spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
1162 
1163 	spdk_json_write_named_object_begin(w, "lvs");
1164 	spdk_json_write_named_string(w, "name", lvs->name);
1165 	spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1166 	spdk_json_write_object_end(w);
1167 
1168 	spdk_json_write_object_end(w);
1169 }
1170 
1171 static void
1172 rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1173 {
1174 	struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1175 	struct spdk_lvol *lvol;
1176 
1177 	TAILQ_FOREACH(lvol, &lvs->lvols, link) {
1178 		rpc_dump_lvol(w, lvol);
1179 	}
1180 }
1181 
1182 static void
1183 rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1184 {
1185 	struct rpc_bdev_lvol_get_lvols req = {};
1186 	struct spdk_json_write_ctx *w;
1187 	struct lvol_store_bdev *lvs_bdev = NULL;
1188 	struct spdk_lvol_store *lvs = NULL;
1189 	int rc;
1190 
1191 	if (params != NULL) {
1192 		if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1193 					    SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1194 					    &req)) {
1195 			SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1196 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1197 							 "spdk_json_decode_object failed");
1198 			goto cleanup;
1199 		}
1200 
1201 		rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1202 		if (rc != 0) {
1203 			spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1204 			goto cleanup;
1205 		}
1206 
1207 		lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1208 		if (lvs_bdev == NULL) {
1209 			spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1210 			goto cleanup;
1211 		}
1212 	}
1213 
1214 	w = spdk_jsonrpc_begin_result(request);
1215 	spdk_json_write_array_begin(w);
1216 
1217 	if (lvs_bdev != NULL) {
1218 		rpc_dump_lvols(w, lvs_bdev);
1219 	} else {
1220 		for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1221 		     lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1222 			rpc_dump_lvols(w, lvs_bdev);
1223 		}
1224 	}
1225 	spdk_json_write_array_end(w);
1226 
1227 	spdk_jsonrpc_end_result(request, w);
1228 
1229 cleanup:
1230 	free_rpc_bdev_lvol_get_lvols(&req);
1231 }
1232 
1233 SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1234 
1235 struct rpc_bdev_lvol_grow_lvstore {
1236 	char *uuid;
1237 	char *lvs_name;
1238 };
1239 
1240 static void
1241 free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1242 {
1243 	free(req->uuid);
1244 	free(req->lvs_name);
1245 }
1246 
1247 static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1248 	{"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1249 	{"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1250 };
1251 
1252 static void
1253 rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1254 {
1255 	struct spdk_jsonrpc_request *request = cb_arg;
1256 
1257 	if (lvserrno != 0) {
1258 		goto invalid;
1259 	}
1260 
1261 	spdk_jsonrpc_send_bool_response(request, true);
1262 	return;
1263 
1264 invalid:
1265 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1266 					 spdk_strerror(-lvserrno));
1267 }
1268 
1269 static void
1270 rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1271 			   const struct spdk_json_val *params)
1272 {
1273 	struct rpc_bdev_lvol_grow_lvstore req = {};
1274 	struct spdk_lvol_store *lvs = NULL;
1275 	int rc;
1276 
1277 	if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1278 				    SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1279 				    &req)) {
1280 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1281 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1282 						 "spdk_json_decode_object failed");
1283 		goto cleanup;
1284 	}
1285 
1286 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1287 	if (rc != 0) {
1288 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1289 		goto cleanup;
1290 	}
1291 	spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1292 	spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1293 
1294 cleanup:
1295 	free_rpc_bdev_lvol_grow_lvstore(&req);
1296 }
1297 SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
1298