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