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