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