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