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 : uint32_t md_page_size;
39 : };
40 :
41 : static int
42 0 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
43 : struct spdk_lvol_store **lvs)
44 : {
45 0 : if ((uuid == NULL && lvs_name == NULL)) {
46 0 : SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
47 0 : return -EINVAL;
48 0 : } else if ((uuid && lvs_name)) {
49 0 : SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid,
50 : lvs_name);
51 0 : return -EINVAL;
52 0 : } else if (uuid) {
53 0 : *lvs = vbdev_get_lvol_store_by_uuid(uuid);
54 :
55 0 : if (*lvs == NULL) {
56 0 : SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
57 0 : return -ENODEV;
58 : }
59 0 : } else if (lvs_name) {
60 :
61 0 : *lvs = vbdev_get_lvol_store_by_name(lvs_name);
62 :
63 0 : if (*lvs == NULL) {
64 0 : SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
65 0 : return -ENODEV;
66 : }
67 : }
68 0 : return 0;
69 : }
70 :
71 : static void
72 0 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
73 : {
74 0 : free(req->bdev_name);
75 0 : free(req->lvs_name);
76 0 : free(req->clear_method);
77 0 : }
78 :
79 : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = {
80 : {"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string},
81 : {"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true},
82 : {"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string},
83 : {"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true},
84 : {"num_md_pages_per_cluster_ratio", offsetof(struct rpc_bdev_lvol_create_lvstore, num_md_pages_per_cluster_ratio), spdk_json_decode_uint32, true},
85 : {"md_page_size", offsetof(struct rpc_bdev_lvol_create_lvstore, md_page_size), spdk_json_decode_uint32, true},
86 : };
87 :
88 : static void
89 0 : rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
90 : {
91 : struct spdk_json_write_ctx *w;
92 0 : struct spdk_jsonrpc_request *request = cb_arg;
93 :
94 0 : if (lvserrno != 0) {
95 0 : goto invalid;
96 : }
97 :
98 0 : w = spdk_jsonrpc_begin_result(request);
99 0 : spdk_json_write_uuid(w, &lvol_store->uuid);
100 0 : spdk_jsonrpc_end_result(request, w);
101 0 : return;
102 :
103 0 : invalid:
104 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
105 : spdk_strerror(-lvserrno));
106 : }
107 :
108 : static void
109 0 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
110 : const struct spdk_json_val *params)
111 : {
112 0 : struct rpc_bdev_lvol_create_lvstore req = {};
113 0 : int rc = 0;
114 : enum lvs_clear_method clear_method;
115 :
116 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
117 : SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
118 : &req)) {
119 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
120 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
121 : "spdk_json_decode_object failed");
122 0 : goto cleanup;
123 : }
124 :
125 0 : if (req.clear_method != NULL) {
126 0 : if (!strcasecmp(req.clear_method, "none")) {
127 0 : clear_method = LVS_CLEAR_WITH_NONE;
128 0 : } else if (!strcasecmp(req.clear_method, "unmap")) {
129 0 : clear_method = LVS_CLEAR_WITH_UNMAP;
130 0 : } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
131 0 : clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
132 : } else {
133 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
134 0 : goto cleanup;
135 : }
136 : } else {
137 0 : clear_method = LVS_CLEAR_WITH_UNMAP;
138 : }
139 :
140 0 : rc = vbdev_lvs_create_ext(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
141 : req.num_md_pages_per_cluster_ratio, req.md_page_size,
142 : rpc_lvol_store_construct_cb, request);
143 0 : if (rc < 0) {
144 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
145 0 : goto cleanup;
146 : }
147 0 : free_rpc_bdev_lvol_create_lvstore(&req);
148 :
149 0 : return;
150 :
151 0 : cleanup:
152 0 : free_rpc_bdev_lvol_create_lvstore(&req);
153 : }
154 0 : SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME)
155 :
156 : struct rpc_bdev_lvol_rename_lvstore {
157 : char *old_name;
158 : char *new_name;
159 : };
160 :
161 : static void
162 0 : free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
163 : {
164 0 : free(req->old_name);
165 0 : free(req->new_name);
166 0 : }
167 :
168 : static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = {
169 : {"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string},
170 : {"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string},
171 : };
172 :
173 : static void
174 0 : rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
175 : {
176 0 : struct spdk_jsonrpc_request *request = cb_arg;
177 :
178 0 : if (lvserrno != 0) {
179 0 : goto invalid;
180 : }
181 :
182 0 : spdk_jsonrpc_send_bool_response(request, true);
183 0 : return;
184 :
185 0 : invalid:
186 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
187 : spdk_strerror(-lvserrno));
188 : }
189 :
190 : static void
191 0 : rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
192 : const struct spdk_json_val *params)
193 : {
194 0 : struct rpc_bdev_lvol_rename_lvstore req = {};
195 : struct spdk_lvol_store *lvs;
196 :
197 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders,
198 : SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders),
199 : &req)) {
200 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
201 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
202 : "spdk_json_decode_object failed");
203 0 : goto cleanup;
204 : }
205 :
206 0 : lvs = vbdev_get_lvol_store_by_name(req.old_name);
207 0 : if (lvs == NULL) {
208 0 : SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
209 0 : spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
210 0 : goto cleanup;
211 : }
212 :
213 0 : vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
214 :
215 0 : cleanup:
216 0 : free_rpc_bdev_lvol_rename_lvstore(&req);
217 0 : }
218 0 : SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME)
219 :
220 : struct rpc_bdev_lvol_delete_lvstore {
221 : char *uuid;
222 : char *lvs_name;
223 : };
224 :
225 : static void
226 0 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
227 : {
228 0 : free(req->uuid);
229 0 : free(req->lvs_name);
230 0 : }
231 :
232 : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = {
233 : {"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true},
234 : {"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true},
235 : };
236 :
237 : static void
238 0 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
239 : {
240 0 : struct spdk_jsonrpc_request *request = cb_arg;
241 :
242 0 : if (lvserrno != 0) {
243 0 : goto invalid;
244 : }
245 :
246 0 : spdk_jsonrpc_send_bool_response(request, true);
247 0 : return;
248 :
249 0 : invalid:
250 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
251 : spdk_strerror(-lvserrno));
252 : }
253 :
254 : static void
255 0 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
256 : const struct spdk_json_val *params)
257 : {
258 0 : struct rpc_bdev_lvol_delete_lvstore req = {};
259 0 : struct spdk_lvol_store *lvs = NULL;
260 : int rc;
261 :
262 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders,
263 : SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders),
264 : &req)) {
265 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
266 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
267 : "spdk_json_decode_object failed");
268 0 : goto cleanup;
269 : }
270 :
271 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
272 0 : if (rc != 0) {
273 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
274 0 : goto cleanup;
275 : }
276 :
277 0 : vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
278 :
279 0 : cleanup:
280 0 : free_rpc_bdev_lvol_delete_lvstore(&req);
281 0 : }
282 0 : SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME)
283 :
284 : struct rpc_bdev_lvol_create {
285 : char *uuid;
286 : char *lvs_name;
287 : char *lvol_name;
288 : uint64_t size_in_mib;
289 : bool thin_provision;
290 : char *clear_method;
291 : };
292 :
293 : static void
294 0 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
295 : {
296 0 : free(req->uuid);
297 0 : free(req->lvs_name);
298 0 : free(req->lvol_name);
299 0 : free(req->clear_method);
300 0 : }
301 :
302 : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
303 : {"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
304 : {"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
305 : {"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
306 : {"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64},
307 : {"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true},
308 : {"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true},
309 : };
310 :
311 : static void
312 0 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
313 : {
314 : struct spdk_json_write_ctx *w;
315 0 : struct spdk_jsonrpc_request *request = cb_arg;
316 :
317 0 : if (lvolerrno != 0) {
318 0 : goto invalid;
319 : }
320 :
321 0 : w = spdk_jsonrpc_begin_result(request);
322 0 : spdk_json_write_string(w, lvol->unique_id);
323 0 : spdk_jsonrpc_end_result(request, w);
324 0 : return;
325 :
326 0 : invalid:
327 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
328 : spdk_strerror(-lvolerrno));
329 : }
330 :
331 : static void
332 0 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
333 : const struct spdk_json_val *params)
334 : {
335 0 : struct rpc_bdev_lvol_create req = {};
336 : enum lvol_clear_method clear_method;
337 0 : int rc = 0;
338 0 : struct spdk_lvol_store *lvs = NULL;
339 :
340 0 : SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
341 :
342 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
343 : SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
344 : &req)) {
345 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
346 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
347 : "spdk_json_decode_object failed");
348 0 : goto cleanup;
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, req.size_in_mib * 1024 * 1024,
373 0 : req.thin_provision, 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_in_mib;
815 : };
816 :
817 : static void
818 0 : free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
819 : {
820 0 : free(req->name);
821 0 : }
822 :
823 : static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
824 : {"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
825 : {"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64},
826 : };
827 :
828 : static void
829 0 : rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
830 : {
831 0 : struct spdk_jsonrpc_request *request = cb_arg;
832 :
833 0 : if (lvolerrno != 0) {
834 0 : goto invalid;
835 : }
836 :
837 0 : spdk_jsonrpc_send_bool_response(request, true);
838 0 : return;
839 :
840 0 : invalid:
841 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
842 : spdk_strerror(-lvolerrno));
843 : }
844 :
845 : static void
846 0 : rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
847 : const struct spdk_json_val *params)
848 : {
849 0 : struct rpc_bdev_lvol_resize req = {};
850 : struct spdk_bdev *bdev;
851 : struct spdk_lvol *lvol;
852 :
853 0 : SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
854 :
855 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
856 : SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
857 : &req)) {
858 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
859 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
860 : "spdk_json_decode_object failed");
861 0 : goto cleanup;
862 : }
863 :
864 0 : bdev = spdk_bdev_get_by_name(req.name);
865 0 : if (bdev == NULL) {
866 0 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
867 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
868 0 : goto cleanup;
869 : }
870 :
871 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
872 0 : if (lvol == NULL) {
873 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
874 0 : goto cleanup;
875 : }
876 :
877 :
878 0 : vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
879 :
880 0 : cleanup:
881 0 : free_rpc_bdev_lvol_resize(&req);
882 0 : }
883 :
884 0 : SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
885 :
886 : struct rpc_set_ro_lvol_bdev {
887 : char *name;
888 : };
889 :
890 : static void
891 0 : free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
892 : {
893 0 : free(req->name);
894 0 : }
895 :
896 : static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
897 : {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
898 : };
899 :
900 : static void
901 0 : rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
902 : {
903 0 : struct spdk_jsonrpc_request *request = cb_arg;
904 :
905 0 : if (lvolerrno != 0) {
906 0 : goto invalid;
907 : }
908 :
909 0 : spdk_jsonrpc_send_bool_response(request, true);
910 0 : return;
911 :
912 0 : invalid:
913 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
914 : spdk_strerror(-lvolerrno));
915 : }
916 :
917 : static void
918 0 : rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
919 : const struct spdk_json_val *params)
920 : {
921 0 : struct rpc_set_ro_lvol_bdev req = {};
922 : struct spdk_bdev *bdev;
923 : struct spdk_lvol *lvol;
924 :
925 0 : SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
926 :
927 0 : if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
928 : SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
929 : &req)) {
930 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
931 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
932 : "spdk_json_decode_object failed");
933 0 : goto cleanup;
934 : }
935 :
936 0 : if (req.name == NULL) {
937 0 : SPDK_ERRLOG("missing name param\n");
938 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
939 0 : goto cleanup;
940 : }
941 :
942 0 : bdev = spdk_bdev_get_by_name(req.name);
943 0 : if (bdev == NULL) {
944 0 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
945 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
946 0 : goto cleanup;
947 : }
948 :
949 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
950 0 : if (lvol == NULL) {
951 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
952 0 : goto cleanup;
953 : }
954 :
955 0 : vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
956 :
957 0 : cleanup:
958 0 : free_rpc_set_ro_lvol_bdev(&req);
959 0 : }
960 :
961 0 : SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
962 :
963 : struct rpc_bdev_lvol_delete {
964 : char *name;
965 : };
966 :
967 : static void
968 0 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
969 : {
970 0 : free(req->name);
971 0 : }
972 :
973 : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
974 : {"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
975 : };
976 :
977 : static void
978 0 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
979 : {
980 0 : struct spdk_jsonrpc_request *request = cb_arg;
981 :
982 0 : if (lvolerrno != 0) {
983 0 : goto invalid;
984 : }
985 :
986 0 : spdk_jsonrpc_send_bool_response(request, true);
987 0 : return;
988 :
989 0 : invalid:
990 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
991 : spdk_strerror(-lvolerrno));
992 : }
993 :
994 : static void
995 0 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
996 : const struct spdk_json_val *params)
997 : {
998 0 : struct rpc_bdev_lvol_delete req = {};
999 : struct spdk_bdev *bdev;
1000 : struct spdk_lvol *lvol;
1001 0 : struct spdk_uuid uuid;
1002 : char *lvs_name, *lvol_name;
1003 :
1004 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
1005 : SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
1006 : &req)) {
1007 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1008 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1009 : "spdk_json_decode_object failed");
1010 0 : goto cleanup;
1011 : }
1012 :
1013 : /* lvol is not degraded, get lvol via bdev name or alias */
1014 0 : bdev = spdk_bdev_get_by_name(req.name);
1015 0 : if (bdev != NULL) {
1016 0 : lvol = vbdev_lvol_get_from_bdev(bdev);
1017 0 : if (lvol != NULL) {
1018 0 : goto done;
1019 : }
1020 : }
1021 :
1022 : /* lvol is degraded, get lvol via UUID */
1023 0 : if (spdk_uuid_parse(&uuid, req.name) == 0) {
1024 0 : lvol = spdk_lvol_get_by_uuid(&uuid);
1025 0 : if (lvol != NULL) {
1026 0 : goto done;
1027 : }
1028 : }
1029 :
1030 : /* lvol is degraded, get lvol via lvs_name/lvol_name */
1031 0 : lvol_name = strchr(req.name, '/');
1032 0 : if (lvol_name != NULL) {
1033 0 : *lvol_name = '\0';
1034 0 : lvol_name++;
1035 0 : lvs_name = req.name;
1036 0 : lvol = spdk_lvol_get_by_names(lvs_name, lvol_name);
1037 0 : if (lvol != NULL) {
1038 0 : goto done;
1039 : }
1040 : }
1041 :
1042 : /* Could not find lvol, degraded or not. */
1043 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1044 0 : goto cleanup;
1045 :
1046 0 : done:
1047 0 : vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1048 :
1049 0 : cleanup:
1050 0 : free_rpc_bdev_lvol_delete(&req);
1051 0 : }
1052 :
1053 0 : SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
1054 :
1055 : struct rpc_bdev_lvol_get_lvstores {
1056 : char *uuid;
1057 : char *lvs_name;
1058 : };
1059 :
1060 : static void
1061 0 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1062 : {
1063 0 : free(req->uuid);
1064 0 : free(req->lvs_name);
1065 0 : }
1066 :
1067 : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
1068 : {"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
1069 : {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
1070 : };
1071 :
1072 : static void
1073 0 : rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1074 : {
1075 : struct spdk_blob_store *bs;
1076 : uint64_t cluster_size;
1077 :
1078 0 : bs = lvs_bdev->lvs->blobstore;
1079 0 : cluster_size = spdk_bs_get_cluster_size(bs);
1080 :
1081 0 : spdk_json_write_object_begin(w);
1082 :
1083 0 : spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
1084 0 : spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
1085 0 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1086 0 : spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1087 0 : spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1088 0 : spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1089 0 : spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1090 :
1091 0 : spdk_json_write_object_end(w);
1092 0 : }
1093 :
1094 : static void
1095 0 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1096 : const struct spdk_json_val *params)
1097 : {
1098 0 : struct rpc_bdev_lvol_get_lvstores req = {};
1099 : struct spdk_json_write_ctx *w;
1100 0 : struct lvol_store_bdev *lvs_bdev = NULL;
1101 0 : struct spdk_lvol_store *lvs = NULL;
1102 : int rc;
1103 :
1104 0 : if (params != NULL) {
1105 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
1106 : SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
1107 : &req)) {
1108 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1109 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1110 : "spdk_json_decode_object failed");
1111 0 : goto cleanup;
1112 : }
1113 :
1114 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1115 0 : if (rc != 0) {
1116 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1117 0 : goto cleanup;
1118 : }
1119 :
1120 0 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1121 0 : if (lvs_bdev == NULL) {
1122 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1123 0 : goto cleanup;
1124 : }
1125 : }
1126 :
1127 0 : w = spdk_jsonrpc_begin_result(request);
1128 0 : spdk_json_write_array_begin(w);
1129 :
1130 0 : if (lvs_bdev != NULL) {
1131 0 : rpc_dump_lvol_store_info(w, lvs_bdev);
1132 : } else {
1133 0 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1134 0 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1135 0 : rpc_dump_lvol_store_info(w, lvs_bdev);
1136 : }
1137 : }
1138 0 : spdk_json_write_array_end(w);
1139 :
1140 0 : spdk_jsonrpc_end_result(request, w);
1141 :
1142 0 : cleanup:
1143 0 : free_rpc_bdev_lvol_get_lvstores(&req);
1144 0 : }
1145 :
1146 0 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1147 0 : SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
1148 :
1149 : struct rpc_bdev_lvol_get_lvols {
1150 : char *lvs_uuid;
1151 : char *lvs_name;
1152 : };
1153 :
1154 : static void
1155 0 : free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
1156 : {
1157 0 : free(req->lvs_uuid);
1158 0 : free(req->lvs_name);
1159 0 : }
1160 :
1161 : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = {
1162 : {"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true},
1163 : {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true},
1164 : };
1165 :
1166 : static void
1167 0 : rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
1168 : {
1169 0 : struct spdk_lvol_store *lvs = lvol->lvol_store;
1170 :
1171 0 : spdk_json_write_object_begin(w);
1172 :
1173 0 : spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
1174 0 : spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
1175 0 : spdk_json_write_named_string(w, "name", lvol->name);
1176 0 : spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
1177 0 : spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
1178 0 : spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
1179 0 : spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
1180 0 : spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
1181 0 : spdk_json_write_named_uint64(w, "num_allocated_clusters",
1182 : spdk_blob_get_num_allocated_clusters(lvol->blob));
1183 :
1184 0 : spdk_json_write_named_object_begin(w, "lvs");
1185 0 : spdk_json_write_named_string(w, "name", lvs->name);
1186 0 : spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1187 0 : spdk_json_write_object_end(w);
1188 :
1189 0 : spdk_json_write_object_end(w);
1190 0 : }
1191 :
1192 : static void
1193 0 : rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1194 : {
1195 0 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1196 : struct spdk_lvol *lvol;
1197 :
1198 0 : TAILQ_FOREACH(lvol, &lvs->lvols, link) {
1199 0 : if (lvol->ref_count == 0) {
1200 0 : continue;
1201 : }
1202 0 : rpc_dump_lvol(w, lvol);
1203 : }
1204 0 : }
1205 :
1206 : static void
1207 0 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1208 : {
1209 0 : struct rpc_bdev_lvol_get_lvols req = {};
1210 : struct spdk_json_write_ctx *w;
1211 0 : struct lvol_store_bdev *lvs_bdev = NULL;
1212 0 : struct spdk_lvol_store *lvs = NULL;
1213 : int rc;
1214 :
1215 0 : if (params != NULL) {
1216 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1217 : SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1218 : &req)) {
1219 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1220 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1221 : "spdk_json_decode_object failed");
1222 0 : goto cleanup;
1223 : }
1224 :
1225 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1226 0 : if (rc != 0) {
1227 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1228 0 : goto cleanup;
1229 : }
1230 :
1231 0 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1232 0 : if (lvs_bdev == NULL) {
1233 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1234 0 : goto cleanup;
1235 : }
1236 : }
1237 :
1238 0 : w = spdk_jsonrpc_begin_result(request);
1239 0 : spdk_json_write_array_begin(w);
1240 :
1241 0 : if (lvs_bdev != NULL) {
1242 0 : rpc_dump_lvols(w, lvs_bdev);
1243 : } else {
1244 0 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1245 0 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1246 0 : rpc_dump_lvols(w, lvs_bdev);
1247 : }
1248 : }
1249 0 : spdk_json_write_array_end(w);
1250 :
1251 0 : spdk_jsonrpc_end_result(request, w);
1252 :
1253 0 : cleanup:
1254 0 : free_rpc_bdev_lvol_get_lvols(&req);
1255 0 : }
1256 :
1257 0 : SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1258 :
1259 : struct rpc_bdev_lvol_grow_lvstore {
1260 : char *uuid;
1261 : char *lvs_name;
1262 : };
1263 :
1264 : static void
1265 0 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1266 : {
1267 0 : free(req->uuid);
1268 0 : free(req->lvs_name);
1269 0 : }
1270 :
1271 : static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1272 : {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1273 : {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1274 : };
1275 :
1276 : static void
1277 0 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1278 : {
1279 0 : struct spdk_jsonrpc_request *request = cb_arg;
1280 :
1281 0 : if (lvserrno != 0) {
1282 0 : goto invalid;
1283 : }
1284 :
1285 0 : spdk_jsonrpc_send_bool_response(request, true);
1286 0 : return;
1287 :
1288 0 : invalid:
1289 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1290 : spdk_strerror(-lvserrno));
1291 : }
1292 :
1293 : static void
1294 0 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1295 : const struct spdk_json_val *params)
1296 : {
1297 0 : struct rpc_bdev_lvol_grow_lvstore req = {};
1298 0 : struct spdk_lvol_store *lvs = NULL;
1299 : int rc;
1300 :
1301 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1302 : SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1303 : &req)) {
1304 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1305 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1306 : "spdk_json_decode_object failed");
1307 0 : goto cleanup;
1308 : }
1309 :
1310 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1311 0 : if (rc != 0) {
1312 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1313 0 : goto cleanup;
1314 : }
1315 0 : spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1316 0 : spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1317 :
1318 0 : cleanup:
1319 0 : free_rpc_bdev_lvol_grow_lvstore(&req);
1320 0 : }
1321 0 : SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
1322 :
1323 : struct rpc_bdev_lvol_shallow_copy {
1324 : char *src_lvol_name;
1325 : char *dst_bdev_name;
1326 : };
1327 :
1328 : struct rpc_bdev_lvol_shallow_copy_ctx {
1329 : struct spdk_jsonrpc_request *request;
1330 : struct rpc_shallow_copy_status *status;
1331 : };
1332 :
1333 : static void
1334 0 : free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
1335 : {
1336 0 : free(req->src_lvol_name);
1337 0 : free(req->dst_bdev_name);
1338 0 : }
1339 :
1340 : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
1341 : {"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
1342 : {"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
1343 : };
1344 :
1345 : static void
1346 0 : rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1347 : {
1348 0 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
1349 :
1350 0 : ctx->status->result = lvolerrno;
1351 :
1352 0 : free(ctx);
1353 0 : }
1354 :
1355 : static void
1356 0 : rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
1357 : {
1358 0 : struct rpc_shallow_copy_status *status = cb_arg;
1359 :
1360 0 : status->copied_clusters = copied_clusters;
1361 0 : }
1362 :
1363 : static void
1364 0 : rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
1365 : const struct spdk_json_val *params)
1366 : {
1367 0 : struct rpc_bdev_lvol_shallow_copy req = {};
1368 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx;
1369 : struct spdk_lvol *src_lvol;
1370 : struct spdk_bdev *src_lvol_bdev;
1371 : struct rpc_shallow_copy_status *status;
1372 : struct spdk_json_write_ctx *w;
1373 : int rc;
1374 :
1375 0 : SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
1376 :
1377 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
1378 : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
1379 : &req)) {
1380 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1381 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1382 : "spdk_json_decode_object failed");
1383 0 : goto cleanup;
1384 : }
1385 :
1386 0 : src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
1387 0 : if (src_lvol_bdev == NULL) {
1388 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
1389 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1390 0 : goto cleanup;
1391 : }
1392 :
1393 0 : src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
1394 0 : if (src_lvol == NULL) {
1395 0 : SPDK_ERRLOG("lvol does not exist\n");
1396 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1397 0 : goto cleanup;
1398 : }
1399 :
1400 0 : status = calloc(1, sizeof(*status));
1401 0 : if (status == NULL) {
1402 0 : SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name);
1403 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1404 0 : goto cleanup;
1405 : }
1406 :
1407 0 : status->operation_id = ++g_shallow_copy_count;
1408 0 : status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
1409 :
1410 0 : ctx = calloc(1, sizeof(*ctx));
1411 0 : if (ctx == NULL) {
1412 0 : SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name);
1413 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1414 0 : free(status);
1415 0 : goto cleanup;
1416 : }
1417 0 : ctx->request = request;
1418 0 : ctx->status = status;
1419 :
1420 0 : LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
1421 0 : rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
1422 : rpc_bdev_lvol_shallow_copy_status_cb, status,
1423 : rpc_bdev_lvol_shallow_copy_cb, ctx);
1424 :
1425 0 : if (rc < 0) {
1426 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1427 : spdk_strerror(-rc));
1428 0 : LIST_REMOVE(status, link);
1429 0 : free(ctx);
1430 0 : free(status);
1431 : } else {
1432 0 : w = spdk_jsonrpc_begin_result(request);
1433 :
1434 0 : spdk_json_write_object_begin(w);
1435 0 : spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
1436 0 : spdk_json_write_object_end(w);
1437 :
1438 0 : spdk_jsonrpc_end_result(request, w);
1439 : }
1440 :
1441 0 : cleanup:
1442 0 : free_rpc_bdev_lvol_shallow_copy(&req);
1443 0 : }
1444 :
1445 0 : SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy,
1446 : SPDK_RPC_RUNTIME)
1447 :
1448 : struct rpc_bdev_lvol_shallow_copy_status {
1449 : char *src_lvol_name;
1450 : uint32_t operation_id;
1451 : };
1452 :
1453 : static void
1454 0 : free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
1455 : {
1456 0 : free(req->src_lvol_name);
1457 0 : }
1458 :
1459 : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
1460 : {"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32},
1461 : };
1462 :
1463 : static void
1464 0 : rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
1465 : const struct spdk_json_val *params)
1466 : {
1467 0 : struct rpc_bdev_lvol_shallow_copy_status req = {};
1468 : struct rpc_shallow_copy_status *status;
1469 : struct spdk_json_write_ctx *w;
1470 : uint64_t copied_clusters, total_clusters;
1471 : int result;
1472 :
1473 0 : SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
1474 :
1475 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
1476 : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
1477 : &req)) {
1478 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1479 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1480 : "spdk_json_decode_object failed");
1481 0 : goto cleanup;
1482 : }
1483 :
1484 0 : LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
1485 0 : if (status->operation_id == req.operation_id) {
1486 0 : break;
1487 : }
1488 : }
1489 :
1490 0 : if (!status) {
1491 0 : SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id);
1492 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1493 0 : goto cleanup;
1494 : }
1495 :
1496 0 : copied_clusters = status->copied_clusters;
1497 0 : total_clusters = status->total_clusters;
1498 0 : result = status->result;
1499 :
1500 0 : w = spdk_jsonrpc_begin_result(request);
1501 :
1502 0 : spdk_json_write_object_begin(w);
1503 :
1504 0 : spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
1505 0 : spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
1506 0 : if (copied_clusters < total_clusters && result == 0) {
1507 0 : spdk_json_write_named_string(w, "state", "in progress");
1508 0 : } else if (copied_clusters == total_clusters && result == 0) {
1509 0 : spdk_json_write_named_string(w, "state", "complete");
1510 0 : LIST_REMOVE(status, link);
1511 0 : free(status);
1512 : } else {
1513 0 : spdk_json_write_named_string(w, "state", "error");
1514 0 : spdk_json_write_named_string(w, "error", spdk_strerror(-result));
1515 0 : LIST_REMOVE(status, link);
1516 0 : free(status);
1517 : }
1518 :
1519 0 : spdk_json_write_object_end(w);
1520 :
1521 0 : spdk_jsonrpc_end_result(request, w);
1522 :
1523 0 : cleanup:
1524 0 : free_rpc_bdev_lvol_shallow_copy_status(&req);
1525 0 : }
1526 :
1527 0 : SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy,
1528 : SPDK_RPC_RUNTIME)
1529 :
1530 : struct rpc_bdev_lvol_set_parent {
1531 : char *lvol_name;
1532 : char *parent_name;
1533 : };
1534 :
1535 : static void
1536 0 : free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
1537 : {
1538 0 : free(req->lvol_name);
1539 0 : free(req->parent_name);
1540 0 : }
1541 :
1542 : static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = {
1543 : {"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string},
1544 : {"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string},
1545 : };
1546 :
1547 : static void
1548 0 : rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
1549 : {
1550 0 : struct spdk_jsonrpc_request *request = cb_arg;
1551 :
1552 0 : if (lvolerrno != 0) {
1553 0 : goto invalid;
1554 : }
1555 :
1556 0 : spdk_jsonrpc_send_bool_response(request, true);
1557 0 : return;
1558 :
1559 0 : invalid:
1560 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1561 : spdk_strerror(-lvolerrno));
1562 : }
1563 :
1564 : static void
1565 0 : rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
1566 : const struct spdk_json_val *params)
1567 : {
1568 0 : struct rpc_bdev_lvol_set_parent req = {};
1569 : struct spdk_lvol *lvol, *snapshot;
1570 : struct spdk_bdev *lvol_bdev, *snapshot_bdev;
1571 :
1572 0 : SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
1573 :
1574 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1575 : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1576 : &req)) {
1577 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1578 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1579 : "spdk_json_decode_object failed");
1580 0 : goto cleanup;
1581 : }
1582 :
1583 0 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1584 0 : if (lvol_bdev == NULL) {
1585 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1586 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1587 0 : goto cleanup;
1588 : }
1589 :
1590 0 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1591 0 : if (lvol == NULL) {
1592 0 : SPDK_ERRLOG("lvol does not exist\n");
1593 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1594 0 : goto cleanup;
1595 : }
1596 :
1597 0 : snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
1598 0 : if (snapshot_bdev == NULL) {
1599 0 : SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name);
1600 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1601 0 : goto cleanup;
1602 : }
1603 :
1604 0 : snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
1605 0 : if (snapshot == NULL) {
1606 0 : SPDK_ERRLOG("snapshot does not exist\n");
1607 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1608 0 : goto cleanup;
1609 : }
1610 :
1611 0 : spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
1612 :
1613 0 : cleanup:
1614 0 : free_rpc_bdev_lvol_set_parent(&req);
1615 0 : }
1616 :
1617 0 : SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1618 :
1619 : static void
1620 0 : rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1621 : const struct spdk_json_val *params)
1622 : {
1623 0 : struct rpc_bdev_lvol_set_parent req = {};
1624 : struct spdk_lvol *lvol;
1625 : struct spdk_bdev *lvol_bdev;
1626 :
1627 0 : SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
1628 :
1629 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1630 : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1631 : &req)) {
1632 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1633 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1634 : "spdk_json_decode_object failed");
1635 0 : goto cleanup;
1636 : }
1637 :
1638 0 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1639 0 : if (lvol_bdev == NULL) {
1640 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1641 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1642 0 : goto cleanup;
1643 : }
1644 :
1645 0 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1646 0 : if (lvol == NULL) {
1647 0 : SPDK_ERRLOG("lvol does not exist\n");
1648 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1649 0 : goto cleanup;
1650 : }
1651 :
1652 0 : vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1653 :
1654 0 : cleanup:
1655 0 : free_rpc_bdev_lvol_set_parent(&req);
1656 0 : }
1657 :
1658 0 : SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1659 : SPDK_RPC_RUNTIME)
|