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