Branch data 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 : 2493 : 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 : 716 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
42 : : struct spdk_lvol_store **lvs)
43 : : {
44 [ + + - + ]: 716 : if ((uuid == NULL && lvs_name == NULL)) {
45 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
46 : 0 : return -EINVAL;
47 [ + + - + ]: 716 : } 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 [ + + ]: 716 : } else if (uuid) {
52 : 557 : *lvs = vbdev_get_lvol_store_by_uuid(uuid);
53 : :
54 [ + + ]: 557 : if (*lvs == NULL) {
55 [ - + - + ]: 44 : SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
56 : 44 : return -ENODEV;
57 : : }
58 [ + - ]: 159 : } else if (lvs_name) {
59 : :
60 : 159 : *lvs = vbdev_get_lvol_store_by_name(lvs_name);
61 : :
62 [ + + ]: 159 : if (*lvs == NULL) {
63 [ - + - + ]: 11 : SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
64 : 11 : return -ENODEV;
65 : : }
66 : : }
67 : 661 : return 0;
68 : : }
69 : :
70 : : static void
71 : 199 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
72 : : {
73 : 199 : free(req->bdev_name);
74 : 199 : free(req->lvs_name);
75 : 199 : free(req->clear_method);
76 : 199 : }
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 : 193 : 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 : 193 : struct spdk_jsonrpc_request *request = cb_arg;
91 : :
92 [ + + ]: 193 : if (lvserrno != 0) {
93 : 1 : goto invalid;
94 : : }
95 : :
96 : 192 : w = spdk_jsonrpc_begin_result(request);
97 : 192 : spdk_json_write_uuid(w, &lvol_store->uuid);
98 : 192 : spdk_jsonrpc_end_result(request, w);
99 : 192 : return;
100 : :
101 : 1 : invalid:
102 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
103 : : spdk_strerror(-lvserrno));
104 : : }
105 : :
106 : : static void
107 : 199 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
108 : : const struct spdk_json_val *params)
109 : : {
110 : 199 : struct rpc_bdev_lvol_create_lvstore req = {};
111 : 199 : int rc = 0;
112 : : enum lvs_clear_method clear_method;
113 : :
114 [ + + ]: 199 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
115 : : SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
116 : : &req)) {
117 [ - + - + ]: 1 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
118 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
119 : : "spdk_json_decode_object failed");
120 : 1 : goto cleanup;
121 : : }
122 : :
123 [ + + ]: 198 : if (req.clear_method != NULL) {
124 [ - + + + ]: 23 : if (!strcasecmp(req.clear_method, "none")) {
125 : 19 : clear_method = LVS_CLEAR_WITH_NONE;
126 [ - + + + ]: 4 : } else if (!strcasecmp(req.clear_method, "unmap")) {
127 : 2 : clear_method = LVS_CLEAR_WITH_UNMAP;
128 [ - + + + ]: 2 : } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
129 : 1 : clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
130 : : } else {
131 : 1 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
132 : 1 : goto cleanup;
133 : : }
134 : : } else {
135 : 175 : clear_method = LVS_CLEAR_WITH_UNMAP;
136 : : }
137 : :
138 : 197 : 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 [ + + ]: 197 : if (rc < 0) {
141 : 4 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
142 : 4 : goto cleanup;
143 : : }
144 : 193 : free_rpc_bdev_lvol_create_lvstore(&req);
145 : :
146 : 193 : return;
147 : :
148 : 6 : cleanup:
149 : 6 : free_rpc_bdev_lvol_create_lvstore(&req);
150 : : }
151 : 2493 : 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 : 3 : free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
160 : : {
161 : 3 : free(req->old_name);
162 : 3 : free(req->new_name);
163 : 3 : }
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 : 2 : rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
172 : : {
173 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
174 : :
175 [ + + ]: 2 : if (lvserrno != 0) {
176 : 1 : goto invalid;
177 : : }
178 : :
179 : 1 : spdk_jsonrpc_send_bool_response(request, true);
180 : 1 : return;
181 : :
182 : 1 : invalid:
183 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
184 : : spdk_strerror(-lvserrno));
185 : : }
186 : :
187 : : static void
188 : 3 : rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
189 : : const struct spdk_json_val *params)
190 : : {
191 : 3 : struct rpc_bdev_lvol_rename_lvstore req = {};
192 : : struct spdk_lvol_store *lvs;
193 : :
194 [ - + ]: 3 : 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 : 3 : lvs = vbdev_get_lvol_store_by_name(req.old_name);
204 [ + + ]: 3 : if (lvs == NULL) {
205 [ - + - + ]: 1 : SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
206 : 1 : spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
207 : 1 : goto cleanup;
208 : : }
209 : :
210 : 2 : vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
211 : :
212 : 3 : cleanup:
213 : 3 : free_rpc_bdev_lvol_rename_lvstore(&req);
214 : 3 : }
215 : 2493 : 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 : 134 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
224 : : {
225 : 134 : free(req->uuid);
226 : 134 : free(req->lvs_name);
227 : 134 : }
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 : 129 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
236 : : {
237 : 129 : struct spdk_jsonrpc_request *request = cb_arg;
238 : :
239 [ - + ]: 129 : if (lvserrno != 0) {
240 : 0 : goto invalid;
241 : : }
242 : :
243 : 129 : spdk_jsonrpc_send_bool_response(request, true);
244 : 129 : 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 : 134 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
253 : : const struct spdk_json_val *params)
254 : : {
255 : 134 : struct rpc_bdev_lvol_delete_lvstore req = {};
256 : 134 : struct spdk_lvol_store *lvs = NULL;
257 : : int rc;
258 : :
259 [ - + ]: 134 : 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 : 134 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
269 [ + + ]: 134 : if (rc != 0) {
270 : 5 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
271 : 5 : goto cleanup;
272 : : }
273 : :
274 : 129 : vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
275 : :
276 : 134 : cleanup:
277 : 134 : free_rpc_bdev_lvol_delete_lvstore(&req);
278 : 134 : }
279 : 2493 : 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 : 472 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
292 : : {
293 : 472 : free(req->uuid);
294 : 472 : free(req->lvs_name);
295 : 472 : free(req->lvol_name);
296 : 472 : free(req->clear_method);
297 : 472 : }
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 : 470 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
310 : : {
311 : : struct spdk_json_write_ctx *w;
312 : 470 : struct spdk_jsonrpc_request *request = cb_arg;
313 : :
314 [ + + ]: 470 : if (lvolerrno != 0) {
315 : 2 : goto invalid;
316 : : }
317 : :
318 : 468 : w = spdk_jsonrpc_begin_result(request);
319 : 468 : spdk_json_write_string(w, lvol->unique_id);
320 : 468 : spdk_jsonrpc_end_result(request, w);
321 : 468 : return;
322 : :
323 : 2 : invalid:
324 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
325 : : spdk_strerror(-lvolerrno));
326 : : }
327 : :
328 : : static void
329 : 472 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
330 : : const struct spdk_json_val *params)
331 : : {
332 : 472 : struct rpc_bdev_lvol_create req = {};
333 : : enum lvol_clear_method clear_method;
334 : 472 : int rc = 0;
335 : 472 : struct spdk_lvol_store *lvs = NULL;
336 : :
337 [ - + - + ]: 472 : SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
338 : :
339 [ - + ]: 472 : 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 : 472 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
349 [ + + ]: 472 : if (rc != 0) {
350 : 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
351 : 1 : goto cleanup;
352 : : }
353 : :
354 [ + + ]: 471 : if (req.clear_method != NULL) {
355 [ - + + + ]: 3 : if (!strcasecmp(req.clear_method, "none")) {
356 : 1 : clear_method = LVOL_CLEAR_WITH_NONE;
357 [ - + + - ]: 2 : } else if (!strcasecmp(req.clear_method, "unmap")) {
358 : 2 : 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 : 468 : clear_method = LVOL_CLEAR_WITH_DEFAULT;
367 : : }
368 : :
369 : 471 : rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
370 [ - + ]: 471 : req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
371 [ + + ]: 471 : if (rc < 0) {
372 : 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
373 : 1 : goto cleanup;
374 : : }
375 : :
376 : 472 : cleanup:
377 : 472 : free_rpc_bdev_lvol_create(&req);
378 : 472 : }
379 : :
380 : 2493 : 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 : 38 : free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
389 : : {
390 : 38 : free(req->lvol_name);
391 : 38 : free(req->snapshot_name);
392 : 38 : }
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 : 38 : rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
401 : : {
402 : : struct spdk_json_write_ctx *w;
403 : 38 : struct spdk_jsonrpc_request *request = cb_arg;
404 : :
405 [ + + ]: 38 : if (lvolerrno != 0) {
406 : 1 : goto invalid;
407 : : }
408 : :
409 : 37 : w = spdk_jsonrpc_begin_result(request);
410 : 37 : spdk_json_write_string(w, lvol->unique_id);
411 : 37 : spdk_jsonrpc_end_result(request, w);
412 : 37 : return;
413 : :
414 : 1 : invalid:
415 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
416 : : spdk_strerror(-lvolerrno));
417 : : }
418 : :
419 : : static void
420 : 38 : rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
421 : : const struct spdk_json_val *params)
422 : : {
423 : 38 : struct rpc_bdev_lvol_snapshot req = {};
424 : : struct spdk_bdev *bdev;
425 : : struct spdk_lvol *lvol;
426 : :
427 [ - + - + ]: 38 : SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
428 : :
429 [ - + ]: 38 : 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 : 38 : bdev = spdk_bdev_get_by_name(req.lvol_name);
439 [ - + ]: 38 : 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 : 38 : lvol = vbdev_lvol_get_from_bdev(bdev);
446 [ - + ]: 38 : 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 : 38 : vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
453 : :
454 : 38 : cleanup:
455 : 38 : free_rpc_bdev_lvol_snapshot(&req);
456 : 38 : }
457 : :
458 : 2493 : 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 : 24 : free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
467 : : {
468 : 24 : free(req->snapshot_name);
469 : 24 : free(req->clone_name);
470 : 24 : }
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 : 31 : rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
479 : : {
480 : : struct spdk_json_write_ctx *w;
481 : 31 : struct spdk_jsonrpc_request *request = cb_arg;
482 : :
483 [ + + ]: 31 : if (lvolerrno != 0) {
484 : 2 : goto invalid;
485 : : }
486 : :
487 : 29 : w = spdk_jsonrpc_begin_result(request);
488 : 29 : spdk_json_write_string(w, lvol->unique_id);
489 : 29 : spdk_jsonrpc_end_result(request, w);
490 : 29 : return;
491 : :
492 : 2 : invalid:
493 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
494 : : spdk_strerror(-lvolerrno));
495 : : }
496 : :
497 : : static void
498 : 24 : rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
499 : : const struct spdk_json_val *params)
500 : : {
501 : 24 : struct rpc_bdev_lvol_clone req = {};
502 : : struct spdk_bdev *bdev;
503 : : struct spdk_lvol *lvol;
504 : :
505 [ - + - + ]: 24 : SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
506 : :
507 [ - + ]: 24 : 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 : 24 : bdev = spdk_bdev_get_by_name(req.snapshot_name);
517 [ - + ]: 24 : 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 : 24 : lvol = vbdev_lvol_get_from_bdev(bdev);
524 [ - + ]: 24 : 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 : 24 : vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
531 : :
532 : 24 : cleanup:
533 : 24 : free_rpc_bdev_lvol_clone(&req);
534 : 24 : }
535 : :
536 : 2493 : 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 : 7 : free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req)
547 : : {
548 : 7 : free(req->bdev_name);
549 : 7 : free(req->lvs_name);
550 : 7 : free(req->clone_name);
551 : 7 : }
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 : 7 : rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
570 : : {
571 : 7 : struct rpc_bdev_lvol_clone_bdev req = {};
572 : : struct spdk_bdev *bdev;
573 : 7 : struct spdk_lvol_store *lvs = NULL;
574 : : struct spdk_lvol *lvol;
575 : : int rc;
576 : :
577 [ - + - + ]: 7 : SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n");
578 : :
579 [ - + ]: 7 : 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 : 7 : rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs);
588 [ - + ]: 7 : 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 : 7 : bdev = spdk_bdev_get_by_name(req.bdev_name);
596 [ - + ]: 7 : 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 : 7 : lvol = vbdev_lvol_get_from_bdev(bdev);
604 [ - + - - ]: 7 : 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 : 7 : vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name,
614 : : rpc_bdev_lvol_clone_cb, request);
615 : 7 : cleanup:
616 : 7 : free_rpc_bdev_lvol_clone_bdev(&req);
617 : 7 : }
618 : :
619 : 2493 : 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 : 6 : free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
628 : : {
629 : 6 : free(req->old_name);
630 : 6 : free(req->new_name);
631 : 6 : }
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 : 4 : rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
640 : : {
641 : 4 : struct spdk_jsonrpc_request *request = cb_arg;
642 : :
643 [ - + ]: 4 : if (lvolerrno != 0) {
644 : 0 : goto invalid;
645 : : }
646 : :
647 : 4 : spdk_jsonrpc_send_bool_response(request, true);
648 : 4 : 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 : 6 : rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
657 : : const struct spdk_json_val *params)
658 : : {
659 : 6 : struct rpc_bdev_lvol_rename req = {};
660 : : struct spdk_bdev *bdev;
661 : : struct spdk_lvol *lvol;
662 : :
663 [ - + - + ]: 6 : SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
664 : :
665 [ - + ]: 6 : 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 : 6 : bdev = spdk_bdev_get_by_name(req.old_name);
675 [ + + ]: 6 : if (bdev == NULL) {
676 : 2 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
677 : 2 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
678 : 2 : goto cleanup;
679 : : }
680 : :
681 : 4 : lvol = vbdev_lvol_get_from_bdev(bdev);
682 [ - + ]: 4 : 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 : 4 : vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
689 : :
690 : 6 : cleanup:
691 : 6 : free_rpc_bdev_lvol_rename(&req);
692 : 6 : }
693 : :
694 : 2493 : 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 : 9 : free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
702 : : {
703 : 9 : free(req->name);
704 : 9 : }
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 : 9 : rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
712 : : {
713 : 9 : struct spdk_jsonrpc_request *request = cb_arg;
714 : :
715 [ + + ]: 9 : if (lvolerrno != 0) {
716 : 1 : goto invalid;
717 : : }
718 : :
719 : 8 : spdk_jsonrpc_send_bool_response(request, true);
720 : 8 : return;
721 : :
722 : 1 : invalid:
723 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
724 : : spdk_strerror(-lvolerrno));
725 : : }
726 : :
727 : : static void
728 : 6 : rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
729 : : const struct spdk_json_val *params)
730 : : {
731 : 6 : struct rpc_bdev_lvol_inflate req = {};
732 : : struct spdk_bdev *bdev;
733 : : struct spdk_lvol *lvol;
734 : :
735 [ - + - + ]: 6 : SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
736 : :
737 [ - + ]: 6 : 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 : 6 : bdev = spdk_bdev_get_by_name(req.name);
747 [ - + ]: 6 : 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 : 6 : lvol = vbdev_lvol_get_from_bdev(bdev);
754 [ - + ]: 6 : 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 : 6 : spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
761 : :
762 : 6 : cleanup:
763 : 6 : free_rpc_bdev_lvol_inflate(&req);
764 : 6 : }
765 : :
766 : 2493 : SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
767 : :
768 : : static void
769 : 3 : rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
770 : : const struct spdk_json_val *params)
771 : : {
772 : 3 : struct rpc_bdev_lvol_inflate req = {};
773 : : struct spdk_bdev *bdev;
774 : : struct spdk_lvol *lvol;
775 : :
776 [ - + - + ]: 3 : SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
777 : :
778 [ - + ]: 3 : 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 : 3 : bdev = spdk_bdev_get_by_name(req.name);
788 [ - + ]: 3 : 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 : 3 : lvol = vbdev_lvol_get_from_bdev(bdev);
795 [ - + ]: 3 : 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 : 3 : spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
802 : :
803 : 3 : cleanup:
804 : 3 : free_rpc_bdev_lvol_inflate(&req);
805 : 3 : }
806 : :
807 : 2493 : 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 : 20 : free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
816 : : {
817 : 20 : free(req->name);
818 : 20 : }
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 : 19 : rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
827 : : {
828 : 19 : struct spdk_jsonrpc_request *request = cb_arg;
829 : :
830 [ + + ]: 19 : if (lvolerrno != 0) {
831 : 1 : goto invalid;
832 : : }
833 : :
834 : 18 : spdk_jsonrpc_send_bool_response(request, true);
835 : 18 : return;
836 : :
837 : 1 : invalid:
838 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
839 : : spdk_strerror(-lvolerrno));
840 : : }
841 : :
842 : : static void
843 : 20 : rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
844 : : const struct spdk_json_val *params)
845 : : {
846 : 20 : struct rpc_bdev_lvol_resize req = {};
847 : : struct spdk_bdev *bdev;
848 : : struct spdk_lvol *lvol;
849 : :
850 [ - + - + ]: 20 : SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
851 : :
852 [ - + ]: 20 : 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 : 20 : bdev = spdk_bdev_get_by_name(req.name);
862 [ + + ]: 20 : if (bdev == NULL) {
863 : 1 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
864 : 1 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
865 : 1 : goto cleanup;
866 : : }
867 : :
868 : 19 : lvol = vbdev_lvol_get_from_bdev(bdev);
869 [ - + ]: 19 : if (lvol == NULL) {
870 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
871 : 0 : goto cleanup;
872 : : }
873 : :
874 : :
875 : 19 : vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
876 : :
877 : 20 : cleanup:
878 : 20 : free_rpc_bdev_lvol_resize(&req);
879 : 20 : }
880 : :
881 : 2493 : 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 : 4 : free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
889 : : {
890 : 4 : free(req->name);
891 : 4 : }
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 : 4 : rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
899 : : {
900 : 4 : struct spdk_jsonrpc_request *request = cb_arg;
901 : :
902 [ - + ]: 4 : if (lvolerrno != 0) {
903 : 0 : goto invalid;
904 : : }
905 : :
906 : 4 : spdk_jsonrpc_send_bool_response(request, true);
907 : 4 : 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 : 4 : rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
916 : : const struct spdk_json_val *params)
917 : : {
918 : 4 : struct rpc_set_ro_lvol_bdev req = {};
919 : : struct spdk_bdev *bdev;
920 : : struct spdk_lvol *lvol;
921 : :
922 [ - + - + ]: 4 : SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
923 : :
924 [ - + ]: 4 : 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 [ - + ]: 4 : 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 : 4 : bdev = spdk_bdev_get_by_name(req.name);
940 [ - + ]: 4 : 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 : 4 : lvol = vbdev_lvol_get_from_bdev(bdev);
947 [ - + ]: 4 : if (lvol == NULL) {
948 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
949 : 0 : goto cleanup;
950 : : }
951 : :
952 : 4 : vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
953 : :
954 : 4 : cleanup:
955 : 4 : free_rpc_set_ro_lvol_bdev(&req);
956 : 4 : }
957 : :
958 : 2493 : 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 : 232 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
966 : : {
967 : 232 : free(req->name);
968 : 232 : }
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 : 232 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
976 : : {
977 : 232 : struct spdk_jsonrpc_request *request = cb_arg;
978 : :
979 [ + + ]: 232 : if (lvolerrno != 0) {
980 : 3 : goto invalid;
981 : : }
982 : :
983 : 229 : spdk_jsonrpc_send_bool_response(request, true);
984 : 229 : return;
985 : :
986 : 3 : invalid:
987 : 3 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
988 : : spdk_strerror(-lvolerrno));
989 : : }
990 : :
991 : : static void
992 : 232 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
993 : : const struct spdk_json_val *params)
994 : : {
995 : 232 : struct rpc_bdev_lvol_delete req = {};
996 : : struct spdk_bdev *bdev;
997 : : struct spdk_lvol *lvol;
998 : 232 : struct spdk_uuid uuid;
999 : : char *lvs_name, *lvol_name;
1000 : :
1001 [ - + ]: 232 : 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 : 232 : bdev = spdk_bdev_get_by_name(req.name);
1012 [ + + ]: 232 : if (bdev != NULL) {
1013 : 230 : lvol = vbdev_lvol_get_from_bdev(bdev);
1014 [ + - ]: 230 : if (lvol != NULL) {
1015 : 230 : goto done;
1016 : : }
1017 : : }
1018 : :
1019 : : /* lvol is degraded, get lvol via UUID */
1020 [ + - ]: 2 : if (spdk_uuid_parse(&uuid, req.name) == 0) {
1021 : 2 : lvol = spdk_lvol_get_by_uuid(&uuid);
1022 [ + - ]: 2 : if (lvol != NULL) {
1023 : 2 : 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 : 232 : done:
1044 : 232 : vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1045 : :
1046 : 232 : cleanup:
1047 : 232 : free_rpc_bdev_lvol_delete(&req);
1048 : 232 : }
1049 : :
1050 : 2493 : 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 : 589 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1059 : : {
1060 : 589 : free(req->uuid);
1061 : 589 : free(req->lvs_name);
1062 : 589 : }
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 : 214 : 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 : 214 : bs = lvs_bdev->lvs->blobstore;
1076 : 214 : cluster_size = spdk_bs_get_cluster_size(bs);
1077 : :
1078 : 214 : spdk_json_write_object_begin(w);
1079 : :
1080 : 214 : spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
1081 : 214 : spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
1082 : 214 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1083 : 214 : spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1084 : 214 : spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1085 : 214 : spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1086 : 214 : spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1087 : :
1088 : 214 : spdk_json_write_object_end(w);
1089 : 214 : }
1090 : :
1091 : : static void
1092 : 589 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1093 : : const struct spdk_json_val *params)
1094 : : {
1095 : 589 : struct rpc_bdev_lvol_get_lvstores req = {};
1096 : : struct spdk_json_write_ctx *w;
1097 : 589 : struct lvol_store_bdev *lvs_bdev = NULL;
1098 : 589 : struct spdk_lvol_store *lvs = NULL;
1099 : : int rc;
1100 : :
1101 [ + + ]: 589 : if (params != NULL) {
1102 [ - + ]: 101 : 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 : 101 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1112 [ + + ]: 101 : if (rc != 0) {
1113 : 49 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1114 : 49 : goto cleanup;
1115 : : }
1116 : :
1117 : 52 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1118 [ - + ]: 52 : if (lvs_bdev == NULL) {
1119 : 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1120 : 0 : goto cleanup;
1121 : : }
1122 : : }
1123 : :
1124 : 540 : w = spdk_jsonrpc_begin_result(request);
1125 : 540 : spdk_json_write_array_begin(w);
1126 : :
1127 [ + + ]: 540 : if (lvs_bdev != NULL) {
1128 : 52 : rpc_dump_lvol_store_info(w, lvs_bdev);
1129 : : } else {
1130 [ + + ]: 650 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1131 : 162 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1132 : 162 : rpc_dump_lvol_store_info(w, lvs_bdev);
1133 : : }
1134 : : }
1135 : 540 : spdk_json_write_array_end(w);
1136 : :
1137 : 540 : spdk_jsonrpc_end_result(request, w);
1138 : :
1139 : 589 : cleanup:
1140 : 589 : free_rpc_bdev_lvol_get_lvstores(&req);
1141 : 589 : }
1142 : :
1143 : 2493 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1144 : 2493 : 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 : 13 : free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
1153 : : {
1154 : 13 : free(req->lvs_uuid);
1155 : 13 : free(req->lvs_name);
1156 : 13 : }
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 : 18 : rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
1165 : : {
1166 : 18 : struct spdk_lvol_store *lvs = lvol->lvol_store;
1167 : :
1168 : 18 : spdk_json_write_object_begin(w);
1169 : :
1170 : 18 : spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
1171 : 18 : spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
1172 : 18 : spdk_json_write_named_string(w, "name", lvol->name);
1173 : 18 : spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
1174 : 18 : spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
1175 : 18 : spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
1176 : 18 : spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
1177 : 18 : spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
1178 : :
1179 : 18 : spdk_json_write_named_object_begin(w, "lvs");
1180 : 18 : spdk_json_write_named_string(w, "name", lvs->name);
1181 : 18 : spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1182 : 18 : spdk_json_write_object_end(w);
1183 : :
1184 : 18 : spdk_json_write_object_end(w);
1185 : 18 : }
1186 : :
1187 : : static void
1188 : 13 : rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1189 : : {
1190 : 13 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1191 : : struct spdk_lvol *lvol;
1192 : :
1193 [ + + ]: 31 : TAILQ_FOREACH(lvol, &lvs->lvols, link) {
1194 : 18 : rpc_dump_lvol(w, lvol);
1195 : : }
1196 : 13 : }
1197 : :
1198 : : static void
1199 : 13 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1200 : : {
1201 : 13 : struct rpc_bdev_lvol_get_lvols req = {};
1202 : : struct spdk_json_write_ctx *w;
1203 : 13 : struct lvol_store_bdev *lvs_bdev = NULL;
1204 : 13 : struct spdk_lvol_store *lvs = NULL;
1205 : : int rc;
1206 : :
1207 [ - + ]: 13 : 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 : 13 : w = spdk_jsonrpc_begin_result(request);
1231 : 13 : spdk_json_write_array_begin(w);
1232 : :
1233 [ - + ]: 13 : if (lvs_bdev != NULL) {
1234 : 0 : rpc_dump_lvols(w, lvs_bdev);
1235 : : } else {
1236 [ + + ]: 26 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1237 : 13 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1238 : 13 : rpc_dump_lvols(w, lvs_bdev);
1239 : : }
1240 : : }
1241 : 13 : spdk_json_write_array_end(w);
1242 : :
1243 : 13 : spdk_jsonrpc_end_result(request, w);
1244 : :
1245 : 13 : cleanup:
1246 : 13 : free_rpc_bdev_lvol_get_lvols(&req);
1247 : 13 : }
1248 : :
1249 : 2493 : 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 : 2 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1258 : : {
1259 : 2 : free(req->uuid);
1260 : 2 : free(req->lvs_name);
1261 : 2 : }
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 : 2 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1270 : : {
1271 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
1272 : :
1273 [ - + ]: 2 : if (lvserrno != 0) {
1274 : 0 : goto invalid;
1275 : : }
1276 : :
1277 : 2 : spdk_jsonrpc_send_bool_response(request, true);
1278 : 2 : 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 : 2 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1287 : : const struct spdk_json_val *params)
1288 : : {
1289 : 2 : struct rpc_bdev_lvol_grow_lvstore req = {};
1290 : 2 : struct spdk_lvol_store *lvs = NULL;
1291 : : int rc;
1292 : :
1293 [ - + ]: 2 : 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 : 2 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1303 [ - + ]: 2 : if (rc != 0) {
1304 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1305 : 0 : goto cleanup;
1306 : : }
1307 : 2 : spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1308 : 2 : spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1309 : :
1310 : 2 : cleanup:
1311 : 2 : free_rpc_bdev_lvol_grow_lvstore(&req);
1312 : 2 : }
1313 : 2493 : 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 : 1 : free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
1327 : : {
1328 : 1 : free(req->src_lvol_name);
1329 : 1 : free(req->dst_bdev_name);
1330 : 1 : }
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 : 1 : rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1339 : : {
1340 : 1 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
1341 : :
1342 : 1 : ctx->status->result = lvolerrno;
1343 : :
1344 : 1 : free(ctx);
1345 : 1 : }
1346 : :
1347 : : static void
1348 : 2 : rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
1349 : : {
1350 : 2 : struct rpc_shallow_copy_status *status = cb_arg;
1351 : :
1352 : 2 : status->copied_clusters = copied_clusters;
1353 : 2 : }
1354 : :
1355 : : static void
1356 : 1 : rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
1357 : : const struct spdk_json_val *params)
1358 : : {
1359 : 1 : 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 [ - + - + ]: 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
1368 : :
1369 [ - + ]: 1 : 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 : 1 : src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
1379 [ - + ]: 1 : 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 : 1 : src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
1386 [ - + ]: 1 : 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 : 1 : status = calloc(1, sizeof(*status));
1393 [ - + ]: 1 : 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 : 1 : status->operation_id = ++g_shallow_copy_count;
1400 : 1 : status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
1401 : :
1402 : 1 : ctx = calloc(1, sizeof(*ctx));
1403 [ - + ]: 1 : 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 : 1 : ctx->request = request;
1410 : 1 : ctx->status = status;
1411 : :
1412 [ - + ]: 1 : LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
1413 : 1 : 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 [ - + ]: 1 : 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 : 1 : w = spdk_jsonrpc_begin_result(request);
1425 : :
1426 : 1 : spdk_json_write_object_begin(w);
1427 : 1 : spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
1428 : 1 : spdk_json_write_object_end(w);
1429 : :
1430 : 1 : spdk_jsonrpc_end_result(request, w);
1431 : : }
1432 : :
1433 : 1 : cleanup:
1434 : 1 : free_rpc_bdev_lvol_shallow_copy(&req);
1435 : 1 : }
1436 : :
1437 : 2493 : 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 : 1 : free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
1447 : : {
1448 : 1 : free(req->src_lvol_name);
1449 : 1 : }
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 : 1 : rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
1457 : : const struct spdk_json_val *params)
1458 : : {
1459 : 1 : 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 [ - + - + ]: 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
1466 : :
1467 [ - + ]: 1 : 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 [ + - ]: 1 : LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
1477 [ + - ]: 1 : if (status->operation_id == req.operation_id) {
1478 : 1 : break;
1479 : : }
1480 : : }
1481 : :
1482 [ - + ]: 1 : 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 : 1 : copied_clusters = status->copied_clusters;
1489 : 1 : total_clusters = status->total_clusters;
1490 : 1 : result = status->result;
1491 : :
1492 : 1 : w = spdk_jsonrpc_begin_result(request);
1493 : :
1494 : 1 : spdk_json_write_object_begin(w);
1495 : :
1496 : 1 : spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
1497 : 1 : spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
1498 [ - + - - ]: 1 : if (copied_clusters < total_clusters && result == 0) {
1499 : 0 : spdk_json_write_named_string(w, "state", "in progress");
1500 [ + - + - ]: 1 : } else if (copied_clusters == total_clusters && result == 0) {
1501 : 1 : spdk_json_write_named_string(w, "state", "complete");
1502 [ - + ]: 1 : LIST_REMOVE(status, link);
1503 : 1 : 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 : 1 : spdk_json_write_object_end(w);
1512 : :
1513 : 1 : spdk_jsonrpc_end_result(request, w);
1514 : :
1515 : 1 : cleanup:
1516 : 1 : free_rpc_bdev_lvol_shallow_copy_status(&req);
1517 : 1 : }
1518 : :
1519 : 2493 : 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 : 14 : free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
1529 : : {
1530 : 14 : free(req->lvol_name);
1531 : 14 : free(req->parent_name);
1532 : 14 : }
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 : 13 : rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
1541 : : {
1542 : 13 : struct spdk_jsonrpc_request *request = cb_arg;
1543 : :
1544 [ + + ]: 13 : if (lvolerrno != 0) {
1545 : 7 : goto invalid;
1546 : : }
1547 : :
1548 : 6 : spdk_jsonrpc_send_bool_response(request, true);
1549 : 6 : return;
1550 : :
1551 : 7 : invalid:
1552 : 7 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1553 : : spdk_strerror(-lvolerrno));
1554 : : }
1555 : :
1556 : : static void
1557 : 8 : rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
1558 : : const struct spdk_json_val *params)
1559 : : {
1560 : 8 : struct rpc_bdev_lvol_set_parent req = {};
1561 : : struct spdk_lvol *lvol, *snapshot;
1562 : : struct spdk_bdev *lvol_bdev, *snapshot_bdev;
1563 : :
1564 [ - + - + ]: 8 : SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
1565 : :
1566 [ - + ]: 8 : 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 : 8 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1576 [ - + ]: 8 : 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 : 8 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1583 [ - + ]: 8 : 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 : 8 : snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
1590 [ - + ]: 8 : 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 : 8 : snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
1597 [ + + ]: 8 : if (snapshot == NULL) {
1598 : 1 : SPDK_ERRLOG("snapshot does not exist\n");
1599 : 1 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1600 : 1 : goto cleanup;
1601 : : }
1602 : :
1603 : 7 : spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
1604 : :
1605 : 8 : cleanup:
1606 : 8 : free_rpc_bdev_lvol_set_parent(&req);
1607 : 8 : }
1608 : :
1609 : 2493 : SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1610 : :
1611 : : static void
1612 : 6 : rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1613 : : const struct spdk_json_val *params)
1614 : : {
1615 : 6 : struct rpc_bdev_lvol_set_parent req = {};
1616 : : struct spdk_lvol *lvol;
1617 : : struct spdk_bdev *lvol_bdev;
1618 : :
1619 [ - + - + ]: 6 : SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
1620 : :
1621 [ - + ]: 6 : 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 : 6 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1631 [ - + ]: 6 : 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 : 6 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1638 [ - + ]: 6 : 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 : 6 : vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1645 : :
1646 : 6 : cleanup:
1647 : 6 : free_rpc_bdev_lvol_set_parent(&req);
1648 : 6 : }
1649 : :
1650 : 2493 : SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1651 : : SPDK_RPC_RUNTIME)
|