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_shallow_copy_status {
17 : uint32_t operation_id;
18 : /*
19 : * 0 means ongoing or successfully completed operation
20 : * a negative value is the -errno of an aborted operation
21 : */
22 : int result;
23 : uint64_t copied_clusters;
24 : uint64_t total_clusters;
25 : LIST_ENTRY(rpc_shallow_copy_status) link;
26 : };
27 :
28 : static uint32_t g_shallow_copy_count = 0;
29 : static LIST_HEAD(, rpc_shallow_copy_status) g_shallow_copy_status_list = LIST_HEAD_INITIALIZER(
30 : &g_shallow_copy_status_list);
31 :
32 : struct rpc_bdev_lvol_create_lvstore {
33 : char *lvs_name;
34 : char *bdev_name;
35 : uint32_t cluster_sz;
36 : char *clear_method;
37 : uint32_t num_md_pages_per_cluster_ratio;
38 : };
39 :
40 : static int
41 0 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
42 : struct spdk_lvol_store **lvs)
43 : {
44 0 : if ((uuid == NULL && lvs_name == NULL)) {
45 0 : SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
46 0 : return -EINVAL;
47 0 : } else if ((uuid && lvs_name)) {
48 0 : SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid,
49 : lvs_name);
50 0 : return -EINVAL;
51 0 : } else if (uuid) {
52 0 : *lvs = vbdev_get_lvol_store_by_uuid(uuid);
53 :
54 0 : if (*lvs == NULL) {
55 0 : SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
56 0 : return -ENODEV;
57 : }
58 0 : } else if (lvs_name) {
59 :
60 0 : *lvs = vbdev_get_lvol_store_by_name(lvs_name);
61 :
62 0 : if (*lvs == NULL) {
63 0 : SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
64 0 : return -ENODEV;
65 : }
66 : }
67 0 : return 0;
68 : }
69 :
70 : static void
71 0 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
72 : {
73 0 : free(req->bdev_name);
74 0 : free(req->lvs_name);
75 0 : free(req->clear_method);
76 0 : }
77 :
78 : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = {
79 : {"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string},
80 : {"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true},
81 : {"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string},
82 : {"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true},
83 : {"num_md_pages_per_cluster_ratio", offsetof(struct rpc_bdev_lvol_create_lvstore, num_md_pages_per_cluster_ratio), spdk_json_decode_uint32, true},
84 : };
85 :
86 : static void
87 0 : rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
88 : {
89 : struct spdk_json_write_ctx *w;
90 0 : struct spdk_jsonrpc_request *request = cb_arg;
91 :
92 0 : if (lvserrno != 0) {
93 0 : goto invalid;
94 : }
95 :
96 0 : w = spdk_jsonrpc_begin_result(request);
97 0 : spdk_json_write_uuid(w, &lvol_store->uuid);
98 0 : spdk_jsonrpc_end_result(request, w);
99 0 : return;
100 :
101 0 : invalid:
102 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
103 : spdk_strerror(-lvserrno));
104 : }
105 :
106 : static void
107 0 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
108 : const struct spdk_json_val *params)
109 : {
110 0 : struct rpc_bdev_lvol_create_lvstore req = {};
111 0 : int rc = 0;
112 : enum lvs_clear_method clear_method;
113 :
114 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
115 : SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
116 : &req)) {
117 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
118 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
119 : "spdk_json_decode_object failed");
120 0 : goto cleanup;
121 : }
122 :
123 0 : if (req.clear_method != NULL) {
124 0 : if (!strcasecmp(req.clear_method, "none")) {
125 0 : clear_method = LVS_CLEAR_WITH_NONE;
126 0 : } else if (!strcasecmp(req.clear_method, "unmap")) {
127 0 : clear_method = LVS_CLEAR_WITH_UNMAP;
128 0 : } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
129 0 : clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
130 : } else {
131 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
132 0 : goto cleanup;
133 : }
134 : } else {
135 0 : clear_method = LVS_CLEAR_WITH_UNMAP;
136 : }
137 :
138 0 : rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
139 : req.num_md_pages_per_cluster_ratio, rpc_lvol_store_construct_cb, request);
140 0 : if (rc < 0) {
141 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
142 0 : goto cleanup;
143 : }
144 0 : free_rpc_bdev_lvol_create_lvstore(&req);
145 :
146 0 : return;
147 :
148 0 : cleanup:
149 0 : free_rpc_bdev_lvol_create_lvstore(&req);
150 : }
151 0 : SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME)
152 :
153 : struct rpc_bdev_lvol_rename_lvstore {
154 : char *old_name;
155 : char *new_name;
156 : };
157 :
158 : static void
159 0 : free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
160 : {
161 0 : free(req->old_name);
162 0 : free(req->new_name);
163 0 : }
164 :
165 : static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = {
166 : {"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string},
167 : {"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string},
168 : };
169 :
170 : static void
171 0 : rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
172 : {
173 0 : struct spdk_jsonrpc_request *request = cb_arg;
174 :
175 0 : if (lvserrno != 0) {
176 0 : goto invalid;
177 : }
178 :
179 0 : spdk_jsonrpc_send_bool_response(request, true);
180 0 : return;
181 :
182 0 : invalid:
183 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
184 : spdk_strerror(-lvserrno));
185 : }
186 :
187 : static void
188 0 : rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
189 : const struct spdk_json_val *params)
190 : {
191 0 : struct rpc_bdev_lvol_rename_lvstore req = {};
192 : struct spdk_lvol_store *lvs;
193 :
194 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders,
195 : SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders),
196 : &req)) {
197 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
198 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
199 : "spdk_json_decode_object failed");
200 0 : goto cleanup;
201 : }
202 :
203 0 : lvs = vbdev_get_lvol_store_by_name(req.old_name);
204 0 : if (lvs == NULL) {
205 0 : SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
206 0 : spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
207 0 : goto cleanup;
208 : }
209 :
210 0 : vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
211 :
212 0 : cleanup:
213 0 : free_rpc_bdev_lvol_rename_lvstore(&req);
214 0 : }
215 0 : SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME)
216 :
217 : struct rpc_bdev_lvol_delete_lvstore {
218 : char *uuid;
219 : char *lvs_name;
220 : };
221 :
222 : static void
223 0 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
224 : {
225 0 : free(req->uuid);
226 0 : free(req->lvs_name);
227 0 : }
228 :
229 : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = {
230 : {"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true},
231 : {"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true},
232 : };
233 :
234 : static void
235 0 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
236 : {
237 0 : struct spdk_jsonrpc_request *request = cb_arg;
238 :
239 0 : if (lvserrno != 0) {
240 0 : goto invalid;
241 : }
242 :
243 0 : spdk_jsonrpc_send_bool_response(request, true);
244 0 : return;
245 :
246 0 : invalid:
247 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
248 : spdk_strerror(-lvserrno));
249 : }
250 :
251 : static void
252 0 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
253 : const struct spdk_json_val *params)
254 : {
255 0 : struct rpc_bdev_lvol_delete_lvstore req = {};
256 0 : struct spdk_lvol_store *lvs = NULL;
257 : int rc;
258 :
259 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders,
260 : SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders),
261 : &req)) {
262 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
263 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
264 : "spdk_json_decode_object failed");
265 0 : goto cleanup;
266 : }
267 :
268 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
269 0 : if (rc != 0) {
270 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
271 0 : goto cleanup;
272 : }
273 :
274 0 : vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
275 :
276 0 : cleanup:
277 0 : free_rpc_bdev_lvol_delete_lvstore(&req);
278 0 : }
279 0 : SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME)
280 :
281 : struct rpc_bdev_lvol_create {
282 : char *uuid;
283 : char *lvs_name;
284 : char *lvol_name;
285 : uint64_t size_in_mib;
286 : bool thin_provision;
287 : char *clear_method;
288 : };
289 :
290 : static void
291 0 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
292 : {
293 0 : free(req->uuid);
294 0 : free(req->lvs_name);
295 0 : free(req->lvol_name);
296 0 : free(req->clear_method);
297 0 : }
298 :
299 : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
300 : {"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
301 : {"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
302 : {"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
303 : {"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64},
304 : {"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true},
305 : {"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true},
306 : };
307 :
308 : static void
309 0 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
310 : {
311 : struct spdk_json_write_ctx *w;
312 0 : struct spdk_jsonrpc_request *request = cb_arg;
313 :
314 0 : if (lvolerrno != 0) {
315 0 : goto invalid;
316 : }
317 :
318 0 : w = spdk_jsonrpc_begin_result(request);
319 0 : spdk_json_write_string(w, lvol->unique_id);
320 0 : spdk_jsonrpc_end_result(request, w);
321 0 : return;
322 :
323 0 : invalid:
324 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
325 : spdk_strerror(-lvolerrno));
326 : }
327 :
328 : static void
329 0 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
330 : const struct spdk_json_val *params)
331 : {
332 0 : struct rpc_bdev_lvol_create req = {};
333 : enum lvol_clear_method clear_method;
334 0 : int rc = 0;
335 0 : struct spdk_lvol_store *lvs = NULL;
336 :
337 0 : SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
338 :
339 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
340 : SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
341 : &req)) {
342 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
343 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
344 : "spdk_json_decode_object failed");
345 0 : goto cleanup;
346 : }
347 :
348 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
349 0 : if (rc != 0) {
350 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
351 0 : goto cleanup;
352 : }
353 :
354 0 : if (req.clear_method != NULL) {
355 0 : if (!strcasecmp(req.clear_method, "none")) {
356 0 : clear_method = LVOL_CLEAR_WITH_NONE;
357 0 : } else if (!strcasecmp(req.clear_method, "unmap")) {
358 0 : clear_method = LVOL_CLEAR_WITH_UNMAP;
359 0 : } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
360 0 : clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES;
361 : } else {
362 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
363 0 : goto cleanup;
364 : }
365 : } else {
366 0 : clear_method = LVOL_CLEAR_WITH_DEFAULT;
367 : }
368 :
369 0 : rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
370 0 : req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
371 0 : if (rc < 0) {
372 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
373 0 : goto cleanup;
374 : }
375 :
376 0 : cleanup:
377 0 : free_rpc_bdev_lvol_create(&req);
378 0 : }
379 :
380 0 : SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME)
381 :
382 : struct rpc_bdev_lvol_snapshot {
383 : char *lvol_name;
384 : char *snapshot_name;
385 : };
386 :
387 : static void
388 0 : free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
389 : {
390 0 : free(req->lvol_name);
391 0 : free(req->snapshot_name);
392 0 : }
393 :
394 : static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = {
395 : {"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string},
396 : {"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string},
397 : };
398 :
399 : static void
400 0 : rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
401 : {
402 : struct spdk_json_write_ctx *w;
403 0 : struct spdk_jsonrpc_request *request = cb_arg;
404 :
405 0 : if (lvolerrno != 0) {
406 0 : goto invalid;
407 : }
408 :
409 0 : w = spdk_jsonrpc_begin_result(request);
410 0 : spdk_json_write_string(w, lvol->unique_id);
411 0 : spdk_jsonrpc_end_result(request, w);
412 0 : return;
413 :
414 0 : invalid:
415 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
416 : spdk_strerror(-lvolerrno));
417 : }
418 :
419 : static void
420 0 : rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
421 : const struct spdk_json_val *params)
422 : {
423 0 : struct rpc_bdev_lvol_snapshot req = {};
424 : struct spdk_bdev *bdev;
425 : struct spdk_lvol *lvol;
426 :
427 0 : SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
428 :
429 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders,
430 : SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders),
431 : &req)) {
432 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
433 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
434 : "spdk_json_decode_object failed");
435 0 : goto cleanup;
436 : }
437 :
438 0 : bdev = spdk_bdev_get_by_name(req.lvol_name);
439 0 : if (bdev == NULL) {
440 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name);
441 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
442 0 : goto cleanup;
443 : }
444 :
445 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
446 0 : if (lvol == NULL) {
447 0 : SPDK_ERRLOG("lvol does not exist\n");
448 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
449 0 : goto cleanup;
450 : }
451 :
452 0 : vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
453 :
454 0 : cleanup:
455 0 : free_rpc_bdev_lvol_snapshot(&req);
456 0 : }
457 :
458 0 : SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME)
459 :
460 : struct rpc_bdev_lvol_clone {
461 : char *snapshot_name;
462 : char *clone_name;
463 : };
464 :
465 : static void
466 0 : free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
467 : {
468 0 : free(req->snapshot_name);
469 0 : free(req->clone_name);
470 0 : }
471 :
472 : static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = {
473 : {"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string},
474 : {"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true},
475 : };
476 :
477 : static void
478 0 : rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
479 : {
480 : struct spdk_json_write_ctx *w;
481 0 : struct spdk_jsonrpc_request *request = cb_arg;
482 :
483 0 : if (lvolerrno != 0) {
484 0 : goto invalid;
485 : }
486 :
487 0 : w = spdk_jsonrpc_begin_result(request);
488 0 : spdk_json_write_string(w, lvol->unique_id);
489 0 : spdk_jsonrpc_end_result(request, w);
490 0 : return;
491 :
492 0 : invalid:
493 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
494 : spdk_strerror(-lvolerrno));
495 : }
496 :
497 : static void
498 0 : rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
499 : const struct spdk_json_val *params)
500 : {
501 0 : struct rpc_bdev_lvol_clone req = {};
502 : struct spdk_bdev *bdev;
503 : struct spdk_lvol *lvol;
504 :
505 0 : SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
506 :
507 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders,
508 : SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders),
509 : &req)) {
510 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
511 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
512 : "spdk_json_decode_object failed");
513 0 : goto cleanup;
514 : }
515 :
516 0 : bdev = spdk_bdev_get_by_name(req.snapshot_name);
517 0 : if (bdev == NULL) {
518 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name);
519 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
520 0 : goto cleanup;
521 : }
522 :
523 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
524 0 : if (lvol == NULL) {
525 0 : SPDK_ERRLOG("lvol does not exist\n");
526 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
527 0 : goto cleanup;
528 : }
529 :
530 0 : vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
531 :
532 0 : cleanup:
533 0 : free_rpc_bdev_lvol_clone(&req);
534 0 : }
535 :
536 0 : SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME)
537 :
538 : struct rpc_bdev_lvol_clone_bdev {
539 : /* name or UUID. Whichever is used, the UUID will be stored in the lvol's metadata. */
540 : char *bdev_name;
541 : char *lvs_name;
542 : char *clone_name;
543 : };
544 :
545 : static void
546 0 : free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req)
547 : {
548 0 : free(req->bdev_name);
549 0 : free(req->lvs_name);
550 0 : free(req->clone_name);
551 0 : }
552 :
553 : static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_bdev_decoders[] = {
554 : {
555 : "bdev", offsetof(struct rpc_bdev_lvol_clone_bdev, bdev_name),
556 : spdk_json_decode_string, false
557 : },
558 : {
559 : "lvs_name", offsetof(struct rpc_bdev_lvol_clone_bdev, lvs_name),
560 : spdk_json_decode_string, false
561 : },
562 : {
563 : "clone_name", offsetof(struct rpc_bdev_lvol_clone_bdev, clone_name),
564 : spdk_json_decode_string, false
565 : },
566 : };
567 :
568 : static void
569 0 : rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
570 : {
571 0 : struct rpc_bdev_lvol_clone_bdev req = {};
572 : struct spdk_bdev *bdev;
573 0 : struct spdk_lvol_store *lvs = NULL;
574 : struct spdk_lvol *lvol;
575 : int rc;
576 :
577 0 : SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n");
578 :
579 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_bdev_decoders,
580 : SPDK_COUNTOF(rpc_bdev_lvol_clone_bdev_decoders), &req)) {
581 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
582 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
583 : "spdk_json_decode_object failed");
584 0 : goto cleanup;
585 : }
586 :
587 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs);
588 0 : if (rc != 0) {
589 0 : SPDK_INFOLOG(lvol_rpc, "lvs_name '%s' not found\n", req.lvs_name);
590 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
591 : "lvs does not exist");
592 0 : goto cleanup;
593 : }
594 :
595 0 : bdev = spdk_bdev_get_by_name(req.bdev_name);
596 0 : if (bdev == NULL) {
597 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.bdev_name);
598 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
599 : "bdev does not exist");
600 0 : goto cleanup;
601 : }
602 :
603 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
604 0 : if (lvol != NULL && lvol->lvol_store == lvs) {
605 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' is an lvol in lvstore '%s\n", req.bdev_name,
606 : req.lvs_name);
607 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
608 : "bdev is an lvol in same lvs as clone; "
609 : "use bdev_lvol_clone instead");
610 0 : goto cleanup;
611 : }
612 :
613 0 : vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name,
614 : rpc_bdev_lvol_clone_cb, request);
615 0 : cleanup:
616 0 : free_rpc_bdev_lvol_clone_bdev(&req);
617 0 : }
618 :
619 0 : SPDK_RPC_REGISTER("bdev_lvol_clone_bdev", rpc_bdev_lvol_clone_bdev, SPDK_RPC_RUNTIME)
620 :
621 : struct rpc_bdev_lvol_rename {
622 : char *old_name;
623 : char *new_name;
624 : };
625 :
626 : static void
627 0 : free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
628 : {
629 0 : free(req->old_name);
630 0 : free(req->new_name);
631 0 : }
632 :
633 : static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = {
634 : {"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string},
635 : {"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string},
636 : };
637 :
638 : static void
639 0 : rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
640 : {
641 0 : struct spdk_jsonrpc_request *request = cb_arg;
642 :
643 0 : if (lvolerrno != 0) {
644 0 : goto invalid;
645 : }
646 :
647 0 : spdk_jsonrpc_send_bool_response(request, true);
648 0 : return;
649 :
650 0 : invalid:
651 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
652 : spdk_strerror(-lvolerrno));
653 : }
654 :
655 : static void
656 0 : rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
657 : const struct spdk_json_val *params)
658 : {
659 0 : struct rpc_bdev_lvol_rename req = {};
660 : struct spdk_bdev *bdev;
661 : struct spdk_lvol *lvol;
662 :
663 0 : SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
664 :
665 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders,
666 : SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders),
667 : &req)) {
668 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
669 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
670 : "spdk_json_decode_object failed");
671 0 : goto cleanup;
672 : }
673 :
674 0 : bdev = spdk_bdev_get_by_name(req.old_name);
675 0 : if (bdev == NULL) {
676 0 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
677 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
678 0 : goto cleanup;
679 : }
680 :
681 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
682 0 : if (lvol == NULL) {
683 0 : SPDK_ERRLOG("lvol does not exist\n");
684 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
685 0 : goto cleanup;
686 : }
687 :
688 0 : vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
689 :
690 0 : cleanup:
691 0 : free_rpc_bdev_lvol_rename(&req);
692 0 : }
693 :
694 0 : SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
695 :
696 : struct rpc_bdev_lvol_inflate {
697 : char *name;
698 : };
699 :
700 : static void
701 0 : free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
702 : {
703 0 : free(req->name);
704 0 : }
705 :
706 : static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = {
707 : {"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string},
708 : };
709 :
710 : static void
711 0 : rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
712 : {
713 0 : struct spdk_jsonrpc_request *request = cb_arg;
714 :
715 0 : if (lvolerrno != 0) {
716 0 : goto invalid;
717 : }
718 :
719 0 : spdk_jsonrpc_send_bool_response(request, true);
720 0 : return;
721 :
722 0 : invalid:
723 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
724 : spdk_strerror(-lvolerrno));
725 : }
726 :
727 : static void
728 0 : rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
729 : const struct spdk_json_val *params)
730 : {
731 0 : struct rpc_bdev_lvol_inflate req = {};
732 : struct spdk_bdev *bdev;
733 : struct spdk_lvol *lvol;
734 :
735 0 : SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
736 :
737 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
738 : SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
739 : &req)) {
740 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
741 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
742 : "spdk_json_decode_object failed");
743 0 : goto cleanup;
744 : }
745 :
746 0 : bdev = spdk_bdev_get_by_name(req.name);
747 0 : if (bdev == NULL) {
748 0 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
749 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
750 0 : goto cleanup;
751 : }
752 :
753 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
754 0 : if (lvol == NULL) {
755 0 : SPDK_ERRLOG("lvol does not exist\n");
756 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
757 0 : goto cleanup;
758 : }
759 :
760 0 : spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
761 :
762 0 : cleanup:
763 0 : free_rpc_bdev_lvol_inflate(&req);
764 0 : }
765 :
766 0 : SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
767 :
768 : static void
769 0 : rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
770 : const struct spdk_json_val *params)
771 : {
772 0 : struct rpc_bdev_lvol_inflate req = {};
773 : struct spdk_bdev *bdev;
774 : struct spdk_lvol *lvol;
775 :
776 0 : SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
777 :
778 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
779 : SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
780 : &req)) {
781 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
782 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
783 : "spdk_json_decode_object failed");
784 0 : goto cleanup;
785 : }
786 :
787 0 : bdev = spdk_bdev_get_by_name(req.name);
788 0 : if (bdev == NULL) {
789 0 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
790 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
791 0 : goto cleanup;
792 : }
793 :
794 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
795 0 : if (lvol == NULL) {
796 0 : SPDK_ERRLOG("lvol does not exist\n");
797 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
798 0 : goto cleanup;
799 : }
800 :
801 0 : spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
802 :
803 0 : cleanup:
804 0 : free_rpc_bdev_lvol_inflate(&req);
805 0 : }
806 :
807 0 : SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME)
808 :
809 : struct rpc_bdev_lvol_resize {
810 : char *name;
811 : uint64_t size_in_mib;
812 : };
813 :
814 : static void
815 0 : free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
816 : {
817 0 : free(req->name);
818 0 : }
819 :
820 : static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
821 : {"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
822 : {"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64},
823 : };
824 :
825 : static void
826 0 : rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
827 : {
828 0 : struct spdk_jsonrpc_request *request = cb_arg;
829 :
830 0 : if (lvolerrno != 0) {
831 0 : goto invalid;
832 : }
833 :
834 0 : spdk_jsonrpc_send_bool_response(request, true);
835 0 : return;
836 :
837 0 : invalid:
838 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
839 : spdk_strerror(-lvolerrno));
840 : }
841 :
842 : static void
843 0 : rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
844 : const struct spdk_json_val *params)
845 : {
846 0 : struct rpc_bdev_lvol_resize req = {};
847 : struct spdk_bdev *bdev;
848 : struct spdk_lvol *lvol;
849 :
850 0 : SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
851 :
852 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
853 : SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
854 : &req)) {
855 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
856 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
857 : "spdk_json_decode_object failed");
858 0 : goto cleanup;
859 : }
860 :
861 0 : bdev = spdk_bdev_get_by_name(req.name);
862 0 : if (bdev == NULL) {
863 0 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
864 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
865 0 : goto cleanup;
866 : }
867 :
868 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
869 0 : if (lvol == NULL) {
870 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
871 0 : goto cleanup;
872 : }
873 :
874 :
875 0 : vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
876 :
877 0 : cleanup:
878 0 : free_rpc_bdev_lvol_resize(&req);
879 0 : }
880 :
881 0 : SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
882 :
883 : struct rpc_set_ro_lvol_bdev {
884 : char *name;
885 : };
886 :
887 : static void
888 0 : free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
889 : {
890 0 : free(req->name);
891 0 : }
892 :
893 : static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
894 : {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
895 : };
896 :
897 : static void
898 0 : rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
899 : {
900 0 : struct spdk_jsonrpc_request *request = cb_arg;
901 :
902 0 : if (lvolerrno != 0) {
903 0 : goto invalid;
904 : }
905 :
906 0 : spdk_jsonrpc_send_bool_response(request, true);
907 0 : return;
908 :
909 0 : invalid:
910 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
911 : spdk_strerror(-lvolerrno));
912 : }
913 :
914 : static void
915 0 : rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
916 : const struct spdk_json_val *params)
917 : {
918 0 : struct rpc_set_ro_lvol_bdev req = {};
919 : struct spdk_bdev *bdev;
920 : struct spdk_lvol *lvol;
921 :
922 0 : SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
923 :
924 0 : if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
925 : SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
926 : &req)) {
927 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
928 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
929 : "spdk_json_decode_object failed");
930 0 : goto cleanup;
931 : }
932 :
933 0 : if (req.name == NULL) {
934 0 : SPDK_ERRLOG("missing name param\n");
935 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
936 0 : goto cleanup;
937 : }
938 :
939 0 : bdev = spdk_bdev_get_by_name(req.name);
940 0 : if (bdev == NULL) {
941 0 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
942 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
943 0 : goto cleanup;
944 : }
945 :
946 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
947 0 : if (lvol == NULL) {
948 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
949 0 : goto cleanup;
950 : }
951 :
952 0 : vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
953 :
954 0 : cleanup:
955 0 : free_rpc_set_ro_lvol_bdev(&req);
956 0 : }
957 :
958 0 : SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
959 :
960 : struct rpc_bdev_lvol_delete {
961 : char *name;
962 : };
963 :
964 : static void
965 0 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
966 : {
967 0 : free(req->name);
968 0 : }
969 :
970 : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
971 : {"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
972 : };
973 :
974 : static void
975 0 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
976 : {
977 0 : struct spdk_jsonrpc_request *request = cb_arg;
978 :
979 0 : if (lvolerrno != 0) {
980 0 : goto invalid;
981 : }
982 :
983 0 : spdk_jsonrpc_send_bool_response(request, true);
984 0 : return;
985 :
986 0 : invalid:
987 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
988 : spdk_strerror(-lvolerrno));
989 : }
990 :
991 : static void
992 0 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
993 : const struct spdk_json_val *params)
994 : {
995 0 : struct rpc_bdev_lvol_delete req = {};
996 : struct spdk_bdev *bdev;
997 : struct spdk_lvol *lvol;
998 0 : struct spdk_uuid uuid;
999 : char *lvs_name, *lvol_name;
1000 :
1001 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
1002 : SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
1003 : &req)) {
1004 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1005 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1006 : "spdk_json_decode_object failed");
1007 0 : goto cleanup;
1008 : }
1009 :
1010 : /* lvol is not degraded, get lvol via bdev name or alias */
1011 0 : bdev = spdk_bdev_get_by_name(req.name);
1012 0 : if (bdev != NULL) {
1013 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
1014 0 : if (lvol != NULL) {
1015 0 : goto done;
1016 : }
1017 : }
1018 :
1019 : /* lvol is degraded, get lvol via UUID */
1020 0 : if (spdk_uuid_parse(&uuid, req.name) == 0) {
1021 0 : lvol = spdk_lvol_get_by_uuid(&uuid);
1022 0 : if (lvol != NULL) {
1023 0 : goto done;
1024 : }
1025 : }
1026 :
1027 : /* lvol is degraded, get lvol via lvs_name/lvol_name */
1028 0 : lvol_name = strchr(req.name, '/');
1029 0 : if (lvol_name != NULL) {
1030 0 : *lvol_name = '\0';
1031 0 : lvol_name++;
1032 0 : lvs_name = req.name;
1033 0 : lvol = spdk_lvol_get_by_names(lvs_name, lvol_name);
1034 0 : if (lvol != NULL) {
1035 0 : goto done;
1036 : }
1037 : }
1038 :
1039 : /* Could not find lvol, degraded or not. */
1040 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1041 0 : goto cleanup;
1042 :
1043 0 : done:
1044 0 : vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1045 :
1046 0 : cleanup:
1047 0 : free_rpc_bdev_lvol_delete(&req);
1048 0 : }
1049 :
1050 0 : SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
1051 :
1052 : struct rpc_bdev_lvol_get_lvstores {
1053 : char *uuid;
1054 : char *lvs_name;
1055 : };
1056 :
1057 : static void
1058 0 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1059 : {
1060 0 : free(req->uuid);
1061 0 : free(req->lvs_name);
1062 0 : }
1063 :
1064 : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
1065 : {"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
1066 : {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
1067 : };
1068 :
1069 : static void
1070 0 : rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1071 : {
1072 : struct spdk_blob_store *bs;
1073 : uint64_t cluster_size;
1074 :
1075 0 : bs = lvs_bdev->lvs->blobstore;
1076 0 : cluster_size = spdk_bs_get_cluster_size(bs);
1077 :
1078 0 : spdk_json_write_object_begin(w);
1079 :
1080 0 : spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
1081 0 : spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
1082 0 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1083 0 : spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1084 0 : spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1085 0 : spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1086 0 : spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1087 :
1088 0 : spdk_json_write_object_end(w);
1089 0 : }
1090 :
1091 : static void
1092 0 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1093 : const struct spdk_json_val *params)
1094 : {
1095 0 : struct rpc_bdev_lvol_get_lvstores req = {};
1096 : struct spdk_json_write_ctx *w;
1097 0 : struct lvol_store_bdev *lvs_bdev = NULL;
1098 0 : struct spdk_lvol_store *lvs = NULL;
1099 : int rc;
1100 :
1101 0 : if (params != NULL) {
1102 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
1103 : SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
1104 : &req)) {
1105 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1106 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1107 : "spdk_json_decode_object failed");
1108 0 : goto cleanup;
1109 : }
1110 :
1111 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1112 0 : if (rc != 0) {
1113 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1114 0 : goto cleanup;
1115 : }
1116 :
1117 0 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1118 0 : if (lvs_bdev == NULL) {
1119 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1120 0 : goto cleanup;
1121 : }
1122 : }
1123 :
1124 0 : w = spdk_jsonrpc_begin_result(request);
1125 0 : spdk_json_write_array_begin(w);
1126 :
1127 0 : if (lvs_bdev != NULL) {
1128 0 : rpc_dump_lvol_store_info(w, lvs_bdev);
1129 : } else {
1130 0 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1131 0 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1132 0 : rpc_dump_lvol_store_info(w, lvs_bdev);
1133 : }
1134 : }
1135 0 : spdk_json_write_array_end(w);
1136 :
1137 0 : spdk_jsonrpc_end_result(request, w);
1138 :
1139 0 : cleanup:
1140 0 : free_rpc_bdev_lvol_get_lvstores(&req);
1141 0 : }
1142 :
1143 0 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1144 0 : SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
1145 :
1146 : struct rpc_bdev_lvol_get_lvols {
1147 : char *lvs_uuid;
1148 : char *lvs_name;
1149 : };
1150 :
1151 : static void
1152 0 : free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
1153 : {
1154 0 : free(req->lvs_uuid);
1155 0 : free(req->lvs_name);
1156 0 : }
1157 :
1158 : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = {
1159 : {"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true},
1160 : {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true},
1161 : };
1162 :
1163 : static void
1164 0 : rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
1165 : {
1166 0 : struct spdk_lvol_store *lvs = lvol->lvol_store;
1167 :
1168 0 : spdk_json_write_object_begin(w);
1169 :
1170 0 : spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
1171 0 : spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
1172 0 : spdk_json_write_named_string(w, "name", lvol->name);
1173 0 : spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
1174 0 : spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
1175 0 : spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
1176 0 : spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
1177 0 : spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
1178 :
1179 0 : spdk_json_write_named_object_begin(w, "lvs");
1180 0 : spdk_json_write_named_string(w, "name", lvs->name);
1181 0 : spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1182 0 : spdk_json_write_object_end(w);
1183 :
1184 0 : spdk_json_write_object_end(w);
1185 0 : }
1186 :
1187 : static void
1188 0 : rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1189 : {
1190 0 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1191 : struct spdk_lvol *lvol;
1192 :
1193 0 : TAILQ_FOREACH(lvol, &lvs->lvols, link) {
1194 0 : rpc_dump_lvol(w, lvol);
1195 : }
1196 0 : }
1197 :
1198 : static void
1199 0 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1200 : {
1201 0 : struct rpc_bdev_lvol_get_lvols req = {};
1202 : struct spdk_json_write_ctx *w;
1203 0 : struct lvol_store_bdev *lvs_bdev = NULL;
1204 0 : struct spdk_lvol_store *lvs = NULL;
1205 : int rc;
1206 :
1207 0 : if (params != NULL) {
1208 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1209 : SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1210 : &req)) {
1211 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1212 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1213 : "spdk_json_decode_object failed");
1214 0 : goto cleanup;
1215 : }
1216 :
1217 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1218 0 : if (rc != 0) {
1219 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1220 0 : goto cleanup;
1221 : }
1222 :
1223 0 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1224 0 : if (lvs_bdev == NULL) {
1225 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1226 0 : goto cleanup;
1227 : }
1228 : }
1229 :
1230 0 : w = spdk_jsonrpc_begin_result(request);
1231 0 : spdk_json_write_array_begin(w);
1232 :
1233 0 : if (lvs_bdev != NULL) {
1234 0 : rpc_dump_lvols(w, lvs_bdev);
1235 : } else {
1236 0 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1237 0 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1238 0 : rpc_dump_lvols(w, lvs_bdev);
1239 : }
1240 : }
1241 0 : spdk_json_write_array_end(w);
1242 :
1243 0 : spdk_jsonrpc_end_result(request, w);
1244 :
1245 0 : cleanup:
1246 0 : free_rpc_bdev_lvol_get_lvols(&req);
1247 0 : }
1248 :
1249 0 : SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1250 :
1251 : struct rpc_bdev_lvol_grow_lvstore {
1252 : char *uuid;
1253 : char *lvs_name;
1254 : };
1255 :
1256 : static void
1257 0 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1258 : {
1259 0 : free(req->uuid);
1260 0 : free(req->lvs_name);
1261 0 : }
1262 :
1263 : static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1264 : {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1265 : {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1266 : };
1267 :
1268 : static void
1269 0 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1270 : {
1271 0 : struct spdk_jsonrpc_request *request = cb_arg;
1272 :
1273 0 : if (lvserrno != 0) {
1274 0 : goto invalid;
1275 : }
1276 :
1277 0 : spdk_jsonrpc_send_bool_response(request, true);
1278 0 : return;
1279 :
1280 0 : invalid:
1281 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1282 : spdk_strerror(-lvserrno));
1283 : }
1284 :
1285 : static void
1286 0 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1287 : const struct spdk_json_val *params)
1288 : {
1289 0 : struct rpc_bdev_lvol_grow_lvstore req = {};
1290 0 : struct spdk_lvol_store *lvs = NULL;
1291 : int rc;
1292 :
1293 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1294 : SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1295 : &req)) {
1296 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1297 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1298 : "spdk_json_decode_object failed");
1299 0 : goto cleanup;
1300 : }
1301 :
1302 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1303 0 : if (rc != 0) {
1304 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1305 0 : goto cleanup;
1306 : }
1307 0 : spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1308 0 : spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1309 :
1310 0 : cleanup:
1311 0 : free_rpc_bdev_lvol_grow_lvstore(&req);
1312 0 : }
1313 0 : SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
1314 :
1315 : struct rpc_bdev_lvol_shallow_copy {
1316 : char *src_lvol_name;
1317 : char *dst_bdev_name;
1318 : };
1319 :
1320 : struct rpc_bdev_lvol_shallow_copy_ctx {
1321 : struct spdk_jsonrpc_request *request;
1322 : struct rpc_shallow_copy_status *status;
1323 : };
1324 :
1325 : static void
1326 0 : free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
1327 : {
1328 0 : free(req->src_lvol_name);
1329 0 : free(req->dst_bdev_name);
1330 0 : }
1331 :
1332 : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
1333 : {"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
1334 : {"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
1335 : };
1336 :
1337 : static void
1338 0 : rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1339 : {
1340 0 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
1341 :
1342 0 : ctx->status->result = lvolerrno;
1343 :
1344 0 : free(ctx);
1345 0 : }
1346 :
1347 : static void
1348 0 : rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
1349 : {
1350 0 : struct rpc_shallow_copy_status *status = cb_arg;
1351 :
1352 0 : status->copied_clusters = copied_clusters;
1353 0 : }
1354 :
1355 : static void
1356 0 : rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
1357 : const struct spdk_json_val *params)
1358 : {
1359 0 : struct rpc_bdev_lvol_shallow_copy req = {};
1360 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx;
1361 : struct spdk_lvol *src_lvol;
1362 : struct spdk_bdev *src_lvol_bdev;
1363 : struct rpc_shallow_copy_status *status;
1364 : struct spdk_json_write_ctx *w;
1365 : int rc;
1366 :
1367 0 : SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
1368 :
1369 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
1370 : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
1371 : &req)) {
1372 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1373 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1374 : "spdk_json_decode_object failed");
1375 0 : goto cleanup;
1376 : }
1377 :
1378 0 : src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
1379 0 : if (src_lvol_bdev == NULL) {
1380 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
1381 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1382 0 : goto cleanup;
1383 : }
1384 :
1385 0 : src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
1386 0 : if (src_lvol == NULL) {
1387 0 : SPDK_ERRLOG("lvol does not exist\n");
1388 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1389 0 : goto cleanup;
1390 : }
1391 :
1392 0 : status = calloc(1, sizeof(*status));
1393 0 : if (status == NULL) {
1394 0 : SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name);
1395 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1396 0 : goto cleanup;
1397 : }
1398 :
1399 0 : status->operation_id = ++g_shallow_copy_count;
1400 0 : status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
1401 :
1402 0 : ctx = calloc(1, sizeof(*ctx));
1403 0 : if (ctx == NULL) {
1404 0 : SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name);
1405 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1406 0 : free(status);
1407 0 : goto cleanup;
1408 : }
1409 0 : ctx->request = request;
1410 0 : ctx->status = status;
1411 :
1412 0 : LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
1413 0 : rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
1414 : rpc_bdev_lvol_shallow_copy_status_cb, status,
1415 : rpc_bdev_lvol_shallow_copy_cb, ctx);
1416 :
1417 0 : if (rc < 0) {
1418 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1419 : spdk_strerror(-rc));
1420 0 : LIST_REMOVE(status, link);
1421 0 : free(ctx);
1422 0 : free(status);
1423 : } else {
1424 0 : w = spdk_jsonrpc_begin_result(request);
1425 :
1426 0 : spdk_json_write_object_begin(w);
1427 0 : spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
1428 0 : spdk_json_write_object_end(w);
1429 :
1430 0 : spdk_jsonrpc_end_result(request, w);
1431 : }
1432 :
1433 0 : cleanup:
1434 0 : free_rpc_bdev_lvol_shallow_copy(&req);
1435 0 : }
1436 :
1437 0 : SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy,
1438 : SPDK_RPC_RUNTIME)
1439 :
1440 : struct rpc_bdev_lvol_shallow_copy_status {
1441 : char *src_lvol_name;
1442 : uint32_t operation_id;
1443 : };
1444 :
1445 : static void
1446 0 : free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
1447 : {
1448 0 : free(req->src_lvol_name);
1449 0 : }
1450 :
1451 : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
1452 : {"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32},
1453 : };
1454 :
1455 : static void
1456 0 : rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
1457 : const struct spdk_json_val *params)
1458 : {
1459 0 : struct rpc_bdev_lvol_shallow_copy_status req = {};
1460 : struct rpc_shallow_copy_status *status;
1461 : struct spdk_json_write_ctx *w;
1462 : uint64_t copied_clusters, total_clusters;
1463 : int result;
1464 :
1465 0 : SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
1466 :
1467 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
1468 : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
1469 : &req)) {
1470 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1471 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1472 : "spdk_json_decode_object failed");
1473 0 : goto cleanup;
1474 : }
1475 :
1476 0 : LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
1477 0 : if (status->operation_id == req.operation_id) {
1478 0 : break;
1479 : }
1480 : }
1481 :
1482 0 : if (!status) {
1483 0 : SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id);
1484 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1485 0 : goto cleanup;
1486 : }
1487 :
1488 0 : copied_clusters = status->copied_clusters;
1489 0 : total_clusters = status->total_clusters;
1490 0 : result = status->result;
1491 :
1492 0 : w = spdk_jsonrpc_begin_result(request);
1493 :
1494 0 : spdk_json_write_object_begin(w);
1495 :
1496 0 : spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
1497 0 : spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
1498 0 : if (copied_clusters < total_clusters && result == 0) {
1499 0 : spdk_json_write_named_string(w, "state", "in progress");
1500 0 : } else if (copied_clusters == total_clusters && result == 0) {
1501 0 : spdk_json_write_named_string(w, "state", "complete");
1502 0 : LIST_REMOVE(status, link);
1503 0 : free(status);
1504 : } else {
1505 0 : spdk_json_write_named_string(w, "state", "error");
1506 0 : spdk_json_write_named_string(w, "error", spdk_strerror(-result));
1507 0 : LIST_REMOVE(status, link);
1508 0 : free(status);
1509 : }
1510 :
1511 0 : spdk_json_write_object_end(w);
1512 :
1513 0 : spdk_jsonrpc_end_result(request, w);
1514 :
1515 0 : cleanup:
1516 0 : free_rpc_bdev_lvol_shallow_copy_status(&req);
1517 0 : }
1518 :
1519 0 : SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy,
1520 : SPDK_RPC_RUNTIME)
1521 :
1522 : struct rpc_bdev_lvol_set_parent {
1523 : char *lvol_name;
1524 : char *parent_name;
1525 : };
1526 :
1527 : static void
1528 0 : free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
1529 : {
1530 0 : free(req->lvol_name);
1531 0 : free(req->parent_name);
1532 0 : }
1533 :
1534 : static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = {
1535 : {"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string},
1536 : {"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string},
1537 : };
1538 :
1539 : static void
1540 0 : rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
1541 : {
1542 0 : struct spdk_jsonrpc_request *request = cb_arg;
1543 :
1544 0 : if (lvolerrno != 0) {
1545 0 : goto invalid;
1546 : }
1547 :
1548 0 : spdk_jsonrpc_send_bool_response(request, true);
1549 0 : return;
1550 :
1551 0 : invalid:
1552 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1553 : spdk_strerror(-lvolerrno));
1554 : }
1555 :
1556 : static void
1557 0 : rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
1558 : const struct spdk_json_val *params)
1559 : {
1560 0 : struct rpc_bdev_lvol_set_parent req = {};
1561 : struct spdk_lvol *lvol, *snapshot;
1562 : struct spdk_bdev *lvol_bdev, *snapshot_bdev;
1563 :
1564 0 : SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
1565 :
1566 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1567 : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1568 : &req)) {
1569 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1570 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1571 : "spdk_json_decode_object failed");
1572 0 : goto cleanup;
1573 : }
1574 :
1575 0 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1576 0 : if (lvol_bdev == NULL) {
1577 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1578 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1579 0 : goto cleanup;
1580 : }
1581 :
1582 0 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1583 0 : if (lvol == NULL) {
1584 0 : SPDK_ERRLOG("lvol does not exist\n");
1585 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1586 0 : goto cleanup;
1587 : }
1588 :
1589 0 : snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
1590 0 : if (snapshot_bdev == NULL) {
1591 0 : SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name);
1592 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1593 0 : goto cleanup;
1594 : }
1595 :
1596 0 : snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
1597 0 : if (snapshot == NULL) {
1598 0 : SPDK_ERRLOG("snapshot does not exist\n");
1599 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1600 0 : goto cleanup;
1601 : }
1602 :
1603 0 : spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
1604 :
1605 0 : cleanup:
1606 0 : free_rpc_bdev_lvol_set_parent(&req);
1607 0 : }
1608 :
1609 0 : SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1610 :
1611 : static void
1612 0 : rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1613 : const struct spdk_json_val *params)
1614 : {
1615 0 : struct rpc_bdev_lvol_set_parent req = {};
1616 : struct spdk_lvol *lvol;
1617 : struct spdk_bdev *lvol_bdev;
1618 :
1619 0 : SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
1620 :
1621 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1622 : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1623 : &req)) {
1624 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1625 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1626 : "spdk_json_decode_object failed");
1627 0 : goto cleanup;
1628 : }
1629 :
1630 0 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1631 0 : if (lvol_bdev == NULL) {
1632 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1633 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1634 0 : goto cleanup;
1635 : }
1636 :
1637 0 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1638 0 : if (lvol == NULL) {
1639 0 : SPDK_ERRLOG("lvol does not exist\n");
1640 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1641 0 : goto cleanup;
1642 : }
1643 :
1644 0 : vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1645 :
1646 0 : cleanup:
1647 0 : free_rpc_bdev_lvol_set_parent(&req);
1648 0 : }
1649 :
1650 0 : SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1651 : SPDK_RPC_RUNTIME)
|