xref: /spdk/module/bdev/lvol/vbdev_lvol_rpc.c (revision 6f338d4bf3a8a91b7abe377a605a321ea2b05bf7)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) 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 	bool thin_provision;
273 	char *clear_method;
274 };
275 
276 static void
277 free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
278 {
279 	free(req->uuid);
280 	free(req->lvs_name);
281 	free(req->lvol_name);
282 	free(req->clear_method);
283 }
284 
285 static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
286 	{"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
287 	{"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
288 	{"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
289 	{"size", offsetof(struct rpc_bdev_lvol_create, size), spdk_json_decode_uint64},
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 static void
315 rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
316 		     const struct spdk_json_val *params)
317 {
318 	struct rpc_bdev_lvol_create req = {};
319 	enum lvol_clear_method clear_method;
320 	int rc = 0;
321 	struct spdk_lvol_store *lvs = NULL;
322 
323 	SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
324 
325 	if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
326 				    SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
327 				    &req)) {
328 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
329 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
330 						 "spdk_json_decode_object failed");
331 		goto cleanup;
332 	}
333 
334 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
335 	if (rc != 0) {
336 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
337 		goto cleanup;
338 	}
339 
340 	if (req.clear_method != NULL) {
341 		if (!strcasecmp(req.clear_method, "none")) {
342 			clear_method = LVOL_CLEAR_WITH_NONE;
343 		} else if (!strcasecmp(req.clear_method, "unmap")) {
344 			clear_method = LVOL_CLEAR_WITH_UNMAP;
345 		} else if (!strcasecmp(req.clear_method, "write_zeroes")) {
346 			clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES;
347 		} else {
348 			spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
349 			goto cleanup;
350 		}
351 	} else {
352 		clear_method = LVOL_CLEAR_WITH_DEFAULT;
353 	}
354 
355 	rc = vbdev_lvol_create(lvs, req.lvol_name, req.size, req.thin_provision,
356 			       clear_method, rpc_bdev_lvol_create_cb, request);
357 	if (rc < 0) {
358 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
359 		goto cleanup;
360 	}
361 
362 cleanup:
363 	free_rpc_bdev_lvol_create(&req);
364 }
365 
366 SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME)
367 
368 struct rpc_bdev_lvol_snapshot {
369 	char *lvol_name;
370 	char *snapshot_name;
371 };
372 
373 static void
374 free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
375 {
376 	free(req->lvol_name);
377 	free(req->snapshot_name);
378 }
379 
380 static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = {
381 	{"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string},
382 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string},
383 };
384 
385 static void
386 rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
387 {
388 	struct spdk_json_write_ctx *w;
389 	struct spdk_jsonrpc_request *request = cb_arg;
390 
391 	if (lvolerrno != 0) {
392 		goto invalid;
393 	}
394 
395 	w = spdk_jsonrpc_begin_result(request);
396 	spdk_json_write_string(w, lvol->unique_id);
397 	spdk_jsonrpc_end_result(request, w);
398 	return;
399 
400 invalid:
401 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
402 					 spdk_strerror(-lvolerrno));
403 }
404 
405 static void
406 rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
407 		       const struct spdk_json_val *params)
408 {
409 	struct rpc_bdev_lvol_snapshot req = {};
410 	struct spdk_bdev *bdev;
411 	struct spdk_lvol *lvol;
412 
413 	SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
414 
415 	if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders,
416 				    SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders),
417 				    &req)) {
418 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
419 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
420 						 "spdk_json_decode_object failed");
421 		goto cleanup;
422 	}
423 
424 	bdev = spdk_bdev_get_by_name(req.lvol_name);
425 	if (bdev == NULL) {
426 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name);
427 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
428 		goto cleanup;
429 	}
430 
431 	lvol = vbdev_lvol_get_from_bdev(bdev);
432 	if (lvol == NULL) {
433 		SPDK_ERRLOG("lvol does not exist\n");
434 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
435 		goto cleanup;
436 	}
437 
438 	vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
439 
440 cleanup:
441 	free_rpc_bdev_lvol_snapshot(&req);
442 }
443 
444 SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME)
445 
446 struct rpc_bdev_lvol_clone {
447 	char *snapshot_name;
448 	char *clone_name;
449 };
450 
451 static void
452 free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
453 {
454 	free(req->snapshot_name);
455 	free(req->clone_name);
456 }
457 
458 static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = {
459 	{"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string},
460 	{"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true},
461 };
462 
463 static void
464 rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
465 {
466 	struct spdk_json_write_ctx *w;
467 	struct spdk_jsonrpc_request *request = cb_arg;
468 
469 	if (lvolerrno != 0) {
470 		goto invalid;
471 	}
472 
473 	w = spdk_jsonrpc_begin_result(request);
474 	spdk_json_write_string(w, lvol->unique_id);
475 	spdk_jsonrpc_end_result(request, w);
476 	return;
477 
478 invalid:
479 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
480 					 spdk_strerror(-lvolerrno));
481 }
482 
483 static void
484 rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
485 		    const struct spdk_json_val *params)
486 {
487 	struct rpc_bdev_lvol_clone req = {};
488 	struct spdk_bdev *bdev;
489 	struct spdk_lvol *lvol;
490 
491 	SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
492 
493 	if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders,
494 				    SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders),
495 				    &req)) {
496 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
497 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
498 						 "spdk_json_decode_object failed");
499 		goto cleanup;
500 	}
501 
502 	bdev = spdk_bdev_get_by_name(req.snapshot_name);
503 	if (bdev == NULL) {
504 		SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name);
505 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
506 		goto cleanup;
507 	}
508 
509 	lvol = vbdev_lvol_get_from_bdev(bdev);
510 	if (lvol == NULL) {
511 		SPDK_ERRLOG("lvol does not exist\n");
512 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
513 		goto cleanup;
514 	}
515 
516 	vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
517 
518 cleanup:
519 	free_rpc_bdev_lvol_clone(&req);
520 }
521 
522 SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME)
523 
524 struct rpc_bdev_lvol_rename {
525 	char *old_name;
526 	char *new_name;
527 };
528 
529 static void
530 free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
531 {
532 	free(req->old_name);
533 	free(req->new_name);
534 }
535 
536 static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = {
537 	{"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string},
538 	{"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string},
539 };
540 
541 static void
542 rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
543 {
544 	struct spdk_jsonrpc_request *request = cb_arg;
545 
546 	if (lvolerrno != 0) {
547 		goto invalid;
548 	}
549 
550 	spdk_jsonrpc_send_bool_response(request, true);
551 	return;
552 
553 invalid:
554 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
555 					 spdk_strerror(-lvolerrno));
556 }
557 
558 static void
559 rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
560 		     const struct spdk_json_val *params)
561 {
562 	struct rpc_bdev_lvol_rename req = {};
563 	struct spdk_bdev *bdev;
564 	struct spdk_lvol *lvol;
565 
566 	SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
567 
568 	if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders,
569 				    SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders),
570 				    &req)) {
571 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
572 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
573 						 "spdk_json_decode_object failed");
574 		goto cleanup;
575 	}
576 
577 	bdev = spdk_bdev_get_by_name(req.old_name);
578 	if (bdev == NULL) {
579 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
580 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
581 		goto cleanup;
582 	}
583 
584 	lvol = vbdev_lvol_get_from_bdev(bdev);
585 	if (lvol == NULL) {
586 		SPDK_ERRLOG("lvol does not exist\n");
587 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
588 		goto cleanup;
589 	}
590 
591 	vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
592 
593 cleanup:
594 	free_rpc_bdev_lvol_rename(&req);
595 }
596 
597 SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
598 
599 struct rpc_bdev_lvol_inflate {
600 	char *name;
601 };
602 
603 static void
604 free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
605 {
606 	free(req->name);
607 }
608 
609 static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = {
610 	{"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string},
611 };
612 
613 static void
614 rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
615 {
616 	struct spdk_jsonrpc_request *request = cb_arg;
617 
618 	if (lvolerrno != 0) {
619 		goto invalid;
620 	}
621 
622 	spdk_jsonrpc_send_bool_response(request, true);
623 	return;
624 
625 invalid:
626 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
627 					 spdk_strerror(-lvolerrno));
628 }
629 
630 static void
631 rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
632 		      const struct spdk_json_val *params)
633 {
634 	struct rpc_bdev_lvol_inflate req = {};
635 	struct spdk_bdev *bdev;
636 	struct spdk_lvol *lvol;
637 
638 	SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
639 
640 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
641 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
642 				    &req)) {
643 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
644 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
645 						 "spdk_json_decode_object failed");
646 		goto cleanup;
647 	}
648 
649 	bdev = spdk_bdev_get_by_name(req.name);
650 	if (bdev == NULL) {
651 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
652 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
653 		goto cleanup;
654 	}
655 
656 	lvol = vbdev_lvol_get_from_bdev(bdev);
657 	if (lvol == NULL) {
658 		SPDK_ERRLOG("lvol does not exist\n");
659 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
660 		goto cleanup;
661 	}
662 
663 	spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
664 
665 cleanup:
666 	free_rpc_bdev_lvol_inflate(&req);
667 }
668 
669 SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
670 
671 static void
672 rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
673 			      const struct spdk_json_val *params)
674 {
675 	struct rpc_bdev_lvol_inflate req = {};
676 	struct spdk_bdev *bdev;
677 	struct spdk_lvol *lvol;
678 
679 	SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
680 
681 	if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
682 				    SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
683 				    &req)) {
684 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
685 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
686 						 "spdk_json_decode_object failed");
687 		goto cleanup;
688 	}
689 
690 	bdev = spdk_bdev_get_by_name(req.name);
691 	if (bdev == NULL) {
692 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
693 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
694 		goto cleanup;
695 	}
696 
697 	lvol = vbdev_lvol_get_from_bdev(bdev);
698 	if (lvol == NULL) {
699 		SPDK_ERRLOG("lvol does not exist\n");
700 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
701 		goto cleanup;
702 	}
703 
704 	spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
705 
706 cleanup:
707 	free_rpc_bdev_lvol_inflate(&req);
708 }
709 
710 SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME)
711 
712 struct rpc_bdev_lvol_resize {
713 	char *name;
714 	uint64_t size;
715 };
716 
717 static void
718 free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
719 {
720 	free(req->name);
721 }
722 
723 static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
724 	{"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
725 	{"size", offsetof(struct rpc_bdev_lvol_resize, size), spdk_json_decode_uint64},
726 };
727 
728 static void
729 rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
730 {
731 	struct spdk_jsonrpc_request *request = cb_arg;
732 
733 	if (lvolerrno != 0) {
734 		goto invalid;
735 	}
736 
737 	spdk_jsonrpc_send_bool_response(request, true);
738 	return;
739 
740 invalid:
741 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
742 					 spdk_strerror(-lvolerrno));
743 }
744 
745 static void
746 rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
747 		     const struct spdk_json_val *params)
748 {
749 	struct rpc_bdev_lvol_resize req = {};
750 	struct spdk_bdev *bdev;
751 	struct spdk_lvol *lvol;
752 
753 	SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
754 
755 	if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
756 				    SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
757 				    &req)) {
758 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
759 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
760 						 "spdk_json_decode_object failed");
761 		goto cleanup;
762 	}
763 
764 	bdev = spdk_bdev_get_by_name(req.name);
765 	if (bdev == NULL) {
766 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
767 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
768 		goto cleanup;
769 	}
770 
771 	lvol = vbdev_lvol_get_from_bdev(bdev);
772 	if (lvol == NULL) {
773 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
774 		goto cleanup;
775 	}
776 
777 	vbdev_lvol_resize(lvol, req.size, rpc_bdev_lvol_resize_cb, request);
778 
779 cleanup:
780 	free_rpc_bdev_lvol_resize(&req);
781 }
782 
783 SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
784 
785 struct rpc_set_ro_lvol_bdev {
786 	char *name;
787 };
788 
789 static void
790 free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
791 {
792 	free(req->name);
793 }
794 
795 static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
796 	{"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
797 };
798 
799 static void
800 rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
801 {
802 	struct spdk_jsonrpc_request *request = cb_arg;
803 
804 	if (lvolerrno != 0) {
805 		goto invalid;
806 	}
807 
808 	spdk_jsonrpc_send_bool_response(request, true);
809 	return;
810 
811 invalid:
812 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
813 					 spdk_strerror(-lvolerrno));
814 }
815 
816 static void
817 rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
818 			    const struct spdk_json_val *params)
819 {
820 	struct rpc_set_ro_lvol_bdev req = {};
821 	struct spdk_bdev *bdev;
822 	struct spdk_lvol *lvol;
823 
824 	SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
825 
826 	if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
827 				    SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
828 				    &req)) {
829 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
830 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
831 						 "spdk_json_decode_object failed");
832 		goto cleanup;
833 	}
834 
835 	if (req.name == NULL) {
836 		SPDK_ERRLOG("missing name param\n");
837 		spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
838 		goto cleanup;
839 	}
840 
841 	bdev = spdk_bdev_get_by_name(req.name);
842 	if (bdev == NULL) {
843 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
844 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
845 		goto cleanup;
846 	}
847 
848 	lvol = vbdev_lvol_get_from_bdev(bdev);
849 	if (lvol == NULL) {
850 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
851 		goto cleanup;
852 	}
853 
854 	vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
855 
856 cleanup:
857 	free_rpc_set_ro_lvol_bdev(&req);
858 }
859 
860 SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
861 
862 struct rpc_bdev_lvol_delete {
863 	char *name;
864 };
865 
866 static void
867 free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
868 {
869 	free(req->name);
870 }
871 
872 static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
873 	{"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
874 };
875 
876 static void
877 rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
878 {
879 	struct spdk_jsonrpc_request *request = cb_arg;
880 
881 	if (lvolerrno != 0) {
882 		goto invalid;
883 	}
884 
885 	spdk_jsonrpc_send_bool_response(request, true);
886 	return;
887 
888 invalid:
889 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
890 					 spdk_strerror(-lvolerrno));
891 }
892 
893 static void
894 rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
895 		     const struct spdk_json_val *params)
896 {
897 	struct rpc_bdev_lvol_delete req = {};
898 	struct spdk_bdev *bdev;
899 	struct spdk_lvol *lvol;
900 
901 	if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
902 				    SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
903 				    &req)) {
904 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
905 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
906 						 "spdk_json_decode_object failed");
907 		goto cleanup;
908 	}
909 
910 	bdev = spdk_bdev_get_by_name(req.name);
911 	if (bdev == NULL) {
912 		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
913 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
914 		goto cleanup;
915 	}
916 
917 	lvol = vbdev_lvol_get_from_bdev(bdev);
918 	if (lvol == NULL) {
919 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
920 		goto cleanup;
921 	}
922 
923 	vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
924 
925 cleanup:
926 	free_rpc_bdev_lvol_delete(&req);
927 }
928 
929 SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
930 
931 struct rpc_bdev_lvol_get_lvstores {
932 	char *uuid;
933 	char *lvs_name;
934 };
935 
936 static void
937 free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
938 {
939 	free(req->uuid);
940 	free(req->lvs_name);
941 }
942 
943 static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
944 	{"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
945 	{"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
946 };
947 
948 static void
949 rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
950 {
951 	struct spdk_blob_store *bs;
952 	uint64_t cluster_size;
953 	char uuid[SPDK_UUID_STRING_LEN];
954 
955 	bs = lvs_bdev->lvs->blobstore;
956 	cluster_size = spdk_bs_get_cluster_size(bs);
957 
958 	spdk_json_write_object_begin(w);
959 
960 	spdk_uuid_fmt_lower(uuid, sizeof(uuid), &lvs_bdev->lvs->uuid);
961 	spdk_json_write_named_string(w, "uuid", uuid);
962 
963 	spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
964 
965 	spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
966 
967 	spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
968 
969 	spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
970 
971 	spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
972 
973 	spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
974 
975 	spdk_json_write_object_end(w);
976 }
977 
978 static void
979 rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
980 			   const struct spdk_json_val *params)
981 {
982 	struct rpc_bdev_lvol_get_lvstores req = {};
983 	struct spdk_json_write_ctx *w;
984 	struct lvol_store_bdev *lvs_bdev = NULL;
985 	struct spdk_lvol_store *lvs = NULL;
986 	int rc;
987 
988 	if (params != NULL) {
989 		if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
990 					    SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
991 					    &req)) {
992 			SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
993 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
994 							 "spdk_json_decode_object failed");
995 			goto cleanup;
996 		}
997 
998 		rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
999 		if (rc != 0) {
1000 			spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1001 			goto cleanup;
1002 		}
1003 
1004 		lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1005 		if (lvs_bdev == NULL) {
1006 			spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1007 			goto cleanup;
1008 		}
1009 	}
1010 
1011 	w = spdk_jsonrpc_begin_result(request);
1012 	spdk_json_write_array_begin(w);
1013 
1014 	if (lvs_bdev != NULL) {
1015 		rpc_dump_lvol_store_info(w, lvs_bdev);
1016 	} else {
1017 		for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1018 		     lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1019 			rpc_dump_lvol_store_info(w, lvs_bdev);
1020 		}
1021 	}
1022 	spdk_json_write_array_end(w);
1023 
1024 	spdk_jsonrpc_end_result(request, w);
1025 
1026 cleanup:
1027 	free_rpc_bdev_lvol_get_lvstores(&req);
1028 }
1029 
1030 SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1031 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
1032 
1033 struct rpc_bdev_lvol_grow_lvstore {
1034 	char *uuid;
1035 	char *lvs_name;
1036 };
1037 
1038 static void
1039 free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1040 {
1041 	free(req->uuid);
1042 	free(req->lvs_name);
1043 }
1044 
1045 static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1046 	{"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1047 	{"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1048 };
1049 
1050 static void
1051 rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1052 {
1053 	struct spdk_jsonrpc_request *request = cb_arg;
1054 
1055 	if (lvserrno != 0) {
1056 		goto invalid;
1057 	}
1058 
1059 	spdk_jsonrpc_send_bool_response(request, true);
1060 	return;
1061 
1062 invalid:
1063 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1064 					 spdk_strerror(-lvserrno));
1065 }
1066 
1067 static void
1068 rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1069 			   const struct spdk_json_val *params)
1070 {
1071 	struct rpc_bdev_lvol_grow_lvstore req = {};
1072 	struct spdk_lvol_store *lvs = NULL;
1073 	int rc;
1074 
1075 	if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1076 				    SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1077 				    &req)) {
1078 		SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1079 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1080 						 "spdk_json_decode_object failed");
1081 		goto cleanup;
1082 	}
1083 
1084 	rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1085 	if (rc != 0) {
1086 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1087 		goto cleanup;
1088 	}
1089 	vbdev_lvs_grow(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1090 
1091 cleanup:
1092 	free_rpc_bdev_lvol_grow_lvstore(&req);
1093 }
1094 SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
1095