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