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 : 2024 : 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 : 479 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
43 : : struct spdk_lvol_store **lvs)
44 : : {
45 [ + + + + ]: 479 : if ((uuid == NULL && lvs_name == NULL)) {
46 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
# # ]
47 : 0 : return -EINVAL;
48 [ + + - + ]: 479 : } 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 [ + + ]: 479 : } else if (uuid) {
53 [ # # ]: 343 : *lvs = vbdev_get_lvol_store_by_uuid(uuid);
54 : :
55 [ + + # # ]: 343 : if (*lvs == NULL) {
56 [ - + - + : 45 : SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
# # ]
57 : 45 : return -ENODEV;
58 : : }
59 [ + + ]: 136 : } else if (lvs_name) {
60 : :
61 [ # # ]: 136 : *lvs = vbdev_get_lvol_store_by_name(lvs_name);
62 : :
63 [ + + # # ]: 136 : if (*lvs == NULL) {
64 [ - + - + : 11 : SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
# # ]
65 : 11 : return -ENODEV;
66 : : }
67 : 3 : }
68 : 423 : return 0;
69 : 3 : }
70 : :
71 : : static void
72 : 155 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
73 : : {
74 [ # # # # ]: 155 : free(req->bdev_name);
75 [ # # # # ]: 155 : free(req->lvs_name);
76 [ # # # # ]: 155 : free(req->clear_method);
77 : 155 : }
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 : 148 : 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 : 148 : struct spdk_jsonrpc_request *request = cb_arg;
93 : :
94 [ + + ]: 148 : if (lvserrno != 0) {
95 : 0 : goto invalid;
96 : : }
97 : :
98 : 148 : w = spdk_jsonrpc_begin_result(request);
99 [ # # ]: 148 : spdk_json_write_uuid(w, &lvol_store->uuid);
100 : 148 : spdk_jsonrpc_end_result(request, w);
101 : 148 : return;
102 : :
103 : 0 : invalid:
104 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
105 [ # # ]: 0 : spdk_strerror(-lvserrno));
106 : 1 : }
107 : :
108 : : static void
109 : 155 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
110 : : const struct spdk_json_val *params)
111 : : {
112 : 155 : struct rpc_bdev_lvol_create_lvstore req = {};
113 : 155 : int rc = 0;
114 : : enum lvs_clear_method clear_method;
115 : :
116 [ + + ]: 155 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
117 : : SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
118 : : &req)) {
119 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
120 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
121 : : "spdk_json_decode_object failed");
122 : 1 : goto cleanup;
123 : : }
124 : :
125 [ + + # # ]: 154 : if (req.clear_method != NULL) {
126 [ - + + + : 26 : if (!strcasecmp(req.clear_method, "none")) {
# # # # ]
127 : 22 : clear_method = LVS_CLEAR_WITH_NONE;
128 [ - + + + : 4 : } else if (!strcasecmp(req.clear_method, "unmap")) {
# # # # ]
129 : 2 : clear_method = LVS_CLEAR_WITH_UNMAP;
130 [ - + + + : 2 : } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
# # # # ]
131 : 1 : clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
132 : 0 : } else {
133 : 1 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
134 : 1 : goto cleanup;
135 : : }
136 : 0 : } else {
137 : 128 : clear_method = LVS_CLEAR_WITH_UNMAP;
138 : : }
139 : :
140 [ # # # # ]: 154 : rc = vbdev_lvs_create_ext(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
141 [ # # # # ]: 1 : req.num_md_pages_per_cluster_ratio, req.md_page_size,
142 : 1 : rpc_lvol_store_construct_cb, request);
143 [ + + ]: 153 : if (rc < 0) {
144 [ # # ]: 5 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
145 : 5 : goto cleanup;
146 : : }
147 : 148 : free_rpc_bdev_lvol_create_lvstore(&req);
148 : :
149 : 148 : return;
150 : :
151 : 7 : cleanup:
152 : 7 : free_rpc_bdev_lvol_create_lvstore(&req);
153 : 1 : }
154 : 2024 : 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 : 3 : free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
163 : : {
164 [ # # # # ]: 3 : free(req->old_name);
165 [ # # # # ]: 3 : free(req->new_name);
166 : 3 : }
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 : 2 : rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
175 : : {
176 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
177 : :
178 [ + + ]: 2 : if (lvserrno != 0) {
179 : 1 : goto invalid;
180 : : }
181 : :
182 : 1 : spdk_jsonrpc_send_bool_response(request, true);
183 : 1 : return;
184 : :
185 : 1 : invalid:
186 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
187 [ # # ]: 0 : spdk_strerror(-lvserrno));
188 : 0 : }
189 : :
190 : : static void
191 : 3 : rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
192 : : const struct spdk_json_val *params)
193 : : {
194 : 3 : struct rpc_bdev_lvol_rename_lvstore req = {};
195 : : struct spdk_lvol_store *lvs;
196 : :
197 [ - + ]: 3 : 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 : 3 : lvs = vbdev_get_lvol_store_by_name(req.old_name);
207 [ + + ]: 3 : if (lvs == NULL) {
208 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
# # ]
209 : 1 : spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
210 : 1 : goto cleanup;
211 : : }
212 : :
213 [ # # ]: 2 : vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
214 : :
215 : 3 : cleanup:
216 : 3 : free_rpc_bdev_lvol_rename_lvstore(&req);
217 : 3 : }
218 : 2024 : 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 : 112 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
227 : : {
228 [ # # # # ]: 112 : free(req->uuid);
229 [ # # # # ]: 112 : free(req->lvs_name);
230 : 112 : }
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 : 107 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
239 : : {
240 : 107 : struct spdk_jsonrpc_request *request = cb_arg;
241 : :
242 [ + + ]: 107 : if (lvserrno != 0) {
243 : 0 : goto invalid;
244 : : }
245 : :
246 : 107 : spdk_jsonrpc_send_bool_response(request, true);
247 : 107 : return;
248 : :
249 : 0 : invalid:
250 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
251 [ # # ]: 0 : spdk_strerror(-lvserrno));
252 : 1 : }
253 : :
254 : : static void
255 : 112 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
256 : : const struct spdk_json_val *params)
257 : : {
258 : 112 : struct rpc_bdev_lvol_delete_lvstore req = {};
259 : 112 : struct spdk_lvol_store *lvs = NULL;
260 : : int rc;
261 : :
262 [ - + ]: 112 : 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 [ # # ]: 112 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
272 [ + + ]: 112 : if (rc != 0) {
273 [ # # ]: 5 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
274 : 5 : goto cleanup;
275 : : }
276 : :
277 : 107 : vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
278 : :
279 : 111 : cleanup:
280 : 112 : free_rpc_bdev_lvol_delete_lvstore(&req);
281 : 112 : }
282 : 2024 : 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 : 252 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
295 : : {
296 [ # # # # ]: 252 : free(req->uuid);
297 [ # # # # ]: 252 : free(req->lvs_name);
298 [ # # # # ]: 252 : free(req->lvol_name);
299 [ # # # # ]: 252 : free(req->clear_method);
300 : 252 : }
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 : 250 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
313 : : {
314 : : struct spdk_json_write_ctx *w;
315 : 250 : struct spdk_jsonrpc_request *request = cb_arg;
316 : :
317 [ + + ]: 250 : if (lvolerrno != 0) {
318 : 2 : goto invalid;
319 : : }
320 : :
321 : 248 : w = spdk_jsonrpc_begin_result(request);
322 [ # # ]: 248 : spdk_json_write_string(w, lvol->unique_id);
323 : 248 : spdk_jsonrpc_end_result(request, w);
324 : 248 : return;
325 : :
326 : 2 : invalid:
327 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
328 [ # # ]: 0 : spdk_strerror(-lvolerrno));
329 : 2 : }
330 : :
331 : : static void
332 : 252 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
333 : : const struct spdk_json_val *params)
334 : : {
335 : 252 : struct rpc_bdev_lvol_create req = {};
336 : : enum lvol_clear_method clear_method;
337 : 252 : int rc = 0;
338 : 252 : struct spdk_lvol_store *lvs = NULL;
339 : :
340 [ + + - + : 252 : SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
# # ]
341 : :
342 [ - + ]: 252 : 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 [ # # ]: 252 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
352 [ + + ]: 252 : if (rc != 0) {
353 [ # # ]: 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
354 : 1 : goto cleanup;
355 : : }
356 : :
357 [ + + # # ]: 251 : if (req.clear_method != NULL) {
358 [ - + + + : 3 : if (!strcasecmp(req.clear_method, "none")) {
# # # # ]
359 : 1 : clear_method = LVOL_CLEAR_WITH_NONE;
360 [ - + + - : 2 : } else if (!strcasecmp(req.clear_method, "unmap")) {
# # # # ]
361 : 2 : 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 : 0 : } else {
365 : 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
366 : 0 : goto cleanup;
367 : : }
368 : 0 : } else {
369 : 248 : clear_method = LVOL_CLEAR_WITH_DEFAULT;
370 : : }
371 : :
372 [ # # # # ]: 253 : rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
373 [ - + # # ]: 251 : req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
374 [ + + ]: 251 : if (rc < 0) {
375 [ # # ]: 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
376 : 1 : goto cleanup;
377 : : }
378 : :
379 : 250 : cleanup:
380 : 252 : free_rpc_bdev_lvol_create(&req);
381 : 252 : }
382 : :
383 : 2024 : 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 : 39 : free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
392 : : {
393 [ # # # # ]: 39 : free(req->lvol_name);
394 [ # # # # ]: 39 : free(req->snapshot_name);
395 : 39 : }
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 : 39 : rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
404 : : {
405 : : struct spdk_json_write_ctx *w;
406 : 39 : struct spdk_jsonrpc_request *request = cb_arg;
407 : :
408 [ + + ]: 39 : if (lvolerrno != 0) {
409 : 1 : goto invalid;
410 : : }
411 : :
412 : 38 : w = spdk_jsonrpc_begin_result(request);
413 [ # # ]: 38 : spdk_json_write_string(w, lvol->unique_id);
414 : 38 : spdk_jsonrpc_end_result(request, w);
415 : 38 : return;
416 : :
417 : 1 : invalid:
418 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
419 [ # # ]: 0 : spdk_strerror(-lvolerrno));
420 : 1 : }
421 : :
422 : : static void
423 : 39 : rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
424 : : const struct spdk_json_val *params)
425 : : {
426 : 39 : struct rpc_bdev_lvol_snapshot req = {};
427 : : struct spdk_bdev *bdev;
428 : : struct spdk_lvol *lvol;
429 : :
430 [ + + - + : 39 : SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
# # ]
431 : :
432 [ - + ]: 39 : 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 : 39 : bdev = spdk_bdev_get_by_name(req.lvol_name);
442 [ + + ]: 39 : 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 : 39 : lvol = vbdev_lvol_get_from_bdev(bdev);
449 [ + + ]: 39 : 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 [ # # ]: 39 : vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
456 : :
457 : 38 : cleanup:
458 : 39 : free_rpc_bdev_lvol_snapshot(&req);
459 : 39 : }
460 : :
461 : 2024 : 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 : 25 : free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
470 : : {
471 [ # # # # ]: 25 : free(req->snapshot_name);
472 [ # # # # ]: 25 : free(req->clone_name);
473 : 25 : }
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 : 32 : rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
482 : : {
483 : : struct spdk_json_write_ctx *w;
484 : 32 : struct spdk_jsonrpc_request *request = cb_arg;
485 : :
486 [ + + ]: 32 : if (lvolerrno != 0) {
487 : 2 : goto invalid;
488 : : }
489 : :
490 : 30 : w = spdk_jsonrpc_begin_result(request);
491 [ # # ]: 30 : spdk_json_write_string(w, lvol->unique_id);
492 : 30 : spdk_jsonrpc_end_result(request, w);
493 : 30 : return;
494 : :
495 : 2 : invalid:
496 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
497 [ # # ]: 0 : spdk_strerror(-lvolerrno));
498 : 1 : }
499 : :
500 : : static void
501 : 25 : rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
502 : : const struct spdk_json_val *params)
503 : : {
504 : 25 : struct rpc_bdev_lvol_clone req = {};
505 : : struct spdk_bdev *bdev;
506 : : struct spdk_lvol *lvol;
507 : :
508 [ + + - + : 25 : SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
# # ]
509 : :
510 [ - + ]: 25 : 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 : 25 : bdev = spdk_bdev_get_by_name(req.snapshot_name);
520 [ + + ]: 25 : 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 : 25 : lvol = vbdev_lvol_get_from_bdev(bdev);
527 [ + + ]: 25 : 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 [ # # ]: 25 : vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
534 : :
535 : 24 : cleanup:
536 : 25 : free_rpc_bdev_lvol_clone(&req);
537 : 25 : }
538 : :
539 : 2024 : 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 : 7 : free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req)
550 : : {
551 [ # # # # ]: 7 : free(req->bdev_name);
552 [ # # # # ]: 7 : free(req->lvs_name);
553 [ # # # # ]: 7 : free(req->clone_name);
554 : 7 : }
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 : 7 : rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
573 : : {
574 : 7 : struct rpc_bdev_lvol_clone_bdev req = {};
575 : : struct spdk_bdev *bdev;
576 : 7 : struct spdk_lvol_store *lvs = NULL;
577 : : struct spdk_lvol *lvol;
578 : : int rc;
579 : :
580 [ - + - + : 7 : SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n");
# # ]
581 : :
582 [ - + ]: 7 : 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 [ # # ]: 7 : rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs);
591 [ - + ]: 7 : 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 : 7 : bdev = spdk_bdev_get_by_name(req.bdev_name);
599 [ - + ]: 7 : 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 : 7 : lvol = vbdev_lvol_get_from_bdev(bdev);
607 [ - + - - : 7 : 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 [ # # ]: 7 : vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name,
617 : 0 : rpc_bdev_lvol_clone_cb, request);
618 : 7 : cleanup:
619 : 7 : free_rpc_bdev_lvol_clone_bdev(&req);
620 : 7 : }
621 : :
622 : 2024 : 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 : 6 : free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
631 : : {
632 [ # # # # ]: 6 : free(req->old_name);
633 [ # # # # ]: 6 : free(req->new_name);
634 : 6 : }
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 : 4 : rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
643 : : {
644 : 4 : struct spdk_jsonrpc_request *request = cb_arg;
645 : :
646 [ - + ]: 4 : if (lvolerrno != 0) {
647 : 0 : goto invalid;
648 : : }
649 : :
650 : 4 : spdk_jsonrpc_send_bool_response(request, true);
651 : 4 : return;
652 : :
653 : 0 : invalid:
654 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
655 [ # # ]: 0 : spdk_strerror(-lvolerrno));
656 : 0 : }
657 : :
658 : : static void
659 : 6 : rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
660 : : const struct spdk_json_val *params)
661 : : {
662 : 6 : struct rpc_bdev_lvol_rename req = {};
663 : : struct spdk_bdev *bdev;
664 : : struct spdk_lvol *lvol;
665 : :
666 [ - + - + : 6 : SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
# # ]
667 : :
668 [ - + ]: 6 : 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 : 6 : bdev = spdk_bdev_get_by_name(req.old_name);
678 [ + + ]: 6 : if (bdev == NULL) {
679 : 2 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
680 : 2 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
681 : 2 : goto cleanup;
682 : : }
683 : :
684 : 4 : lvol = vbdev_lvol_get_from_bdev(bdev);
685 [ - + ]: 4 : 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 [ # # ]: 4 : vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
692 : :
693 : 6 : cleanup:
694 : 6 : free_rpc_bdev_lvol_rename(&req);
695 : 6 : }
696 : :
697 : 2024 : 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 : 10 : free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
705 : : {
706 [ # # # # ]: 10 : free(req->name);
707 : 10 : }
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 : 10 : rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
715 : : {
716 : 10 : struct spdk_jsonrpc_request *request = cb_arg;
717 : :
718 [ + + ]: 10 : if (lvolerrno != 0) {
719 : 1 : goto invalid;
720 : : }
721 : :
722 : 9 : spdk_jsonrpc_send_bool_response(request, true);
723 : 9 : return;
724 : :
725 : 1 : invalid:
726 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
727 [ # # ]: 0 : spdk_strerror(-lvolerrno));
728 : 0 : }
729 : :
730 : : static void
731 : 7 : rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
732 : : const struct spdk_json_val *params)
733 : : {
734 : 7 : struct rpc_bdev_lvol_inflate req = {};
735 : : struct spdk_bdev *bdev;
736 : : struct spdk_lvol *lvol;
737 : :
738 [ - + - + : 7 : SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
# # ]
739 : :
740 [ - + ]: 7 : 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 : 7 : bdev = spdk_bdev_get_by_name(req.name);
750 [ - + ]: 7 : 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 : 7 : lvol = vbdev_lvol_get_from_bdev(bdev);
757 [ - + ]: 7 : 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 : 7 : spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
764 : :
765 : 7 : cleanup:
766 : 7 : free_rpc_bdev_lvol_inflate(&req);
767 : 7 : }
768 : :
769 : 2024 : SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
770 : :
771 : : static void
772 : 3 : rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
773 : : const struct spdk_json_val *params)
774 : : {
775 : 3 : struct rpc_bdev_lvol_inflate req = {};
776 : : struct spdk_bdev *bdev;
777 : : struct spdk_lvol *lvol;
778 : :
779 [ - + - + : 3 : SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
# # ]
780 : :
781 [ - + ]: 3 : 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 : 3 : bdev = spdk_bdev_get_by_name(req.name);
791 [ - + ]: 3 : 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 : 3 : lvol = vbdev_lvol_get_from_bdev(bdev);
798 [ - + ]: 3 : 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 : 3 : spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
805 : :
806 : 3 : cleanup:
807 : 3 : free_rpc_bdev_lvol_inflate(&req);
808 : 3 : }
809 : :
810 : 2024 : 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 : 25 : free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
819 : : {
820 [ # # # # ]: 25 : free(req->name);
821 : 25 : }
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 : 24 : rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
830 : : {
831 : 24 : struct spdk_jsonrpc_request *request = cb_arg;
832 : :
833 [ + + ]: 24 : if (lvolerrno != 0) {
834 : 1 : goto invalid;
835 : : }
836 : :
837 : 23 : spdk_jsonrpc_send_bool_response(request, true);
838 : 23 : return;
839 : :
840 : 1 : invalid:
841 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
842 [ # # ]: 0 : spdk_strerror(-lvolerrno));
843 : 0 : }
844 : :
845 : : static void
846 : 25 : rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
847 : : const struct spdk_json_val *params)
848 : : {
849 : 25 : struct rpc_bdev_lvol_resize req = {};
850 : : struct spdk_bdev *bdev;
851 : : struct spdk_lvol *lvol;
852 : :
853 [ - + - + : 25 : SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
# # ]
854 : :
855 [ - + ]: 25 : 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 : 25 : bdev = spdk_bdev_get_by_name(req.name);
865 [ + + ]: 25 : if (bdev == NULL) {
866 : 1 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
867 : 1 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
868 : 1 : goto cleanup;
869 : : }
870 : :
871 : 24 : lvol = vbdev_lvol_get_from_bdev(bdev);
872 [ - + ]: 24 : if (lvol == NULL) {
873 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
874 : 0 : goto cleanup;
875 : : }
876 : :
877 : :
878 [ # # ]: 24 : vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
879 : :
880 : 25 : cleanup:
881 : 25 : free_rpc_bdev_lvol_resize(&req);
882 : 25 : }
883 : :
884 : 2024 : 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 : 4 : free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
892 : : {
893 [ # # # # ]: 4 : free(req->name);
894 : 4 : }
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 : 4 : rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
902 : : {
903 : 4 : struct spdk_jsonrpc_request *request = cb_arg;
904 : :
905 [ - + ]: 4 : if (lvolerrno != 0) {
906 : 0 : goto invalid;
907 : : }
908 : :
909 : 4 : spdk_jsonrpc_send_bool_response(request, true);
910 : 4 : return;
911 : :
912 : 0 : invalid:
913 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
914 [ # # ]: 0 : spdk_strerror(-lvolerrno));
915 : 0 : }
916 : :
917 : : static void
918 : 4 : rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
919 : : const struct spdk_json_val *params)
920 : : {
921 : 4 : struct rpc_set_ro_lvol_bdev req = {};
922 : : struct spdk_bdev *bdev;
923 : : struct spdk_lvol *lvol;
924 : :
925 [ - + - + : 4 : SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
# # ]
926 : :
927 [ - + ]: 4 : 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 [ - + ]: 4 : 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 : 4 : bdev = spdk_bdev_get_by_name(req.name);
943 [ - + ]: 4 : 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 : 4 : lvol = vbdev_lvol_get_from_bdev(bdev);
950 [ - + ]: 4 : if (lvol == NULL) {
951 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
952 : 0 : goto cleanup;
953 : : }
954 : :
955 : 4 : vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
956 : :
957 : 4 : cleanup:
958 : 4 : free_rpc_set_ro_lvol_bdev(&req);
959 : 4 : }
960 : :
961 : 2024 : 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 : 206 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
969 : : {
970 [ # # # # ]: 206 : free(req->name);
971 : 206 : }
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 : 206 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
979 : : {
980 : 206 : struct spdk_jsonrpc_request *request = cb_arg;
981 : :
982 [ + + ]: 206 : if (lvolerrno != 0) {
983 : 3 : goto invalid;
984 : : }
985 : :
986 : 203 : spdk_jsonrpc_send_bool_response(request, true);
987 : 203 : return;
988 : :
989 : 3 : invalid:
990 : 3 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
991 [ # # ]: 0 : spdk_strerror(-lvolerrno));
992 : 3 : }
993 : :
994 : : static void
995 : 206 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
996 : : const struct spdk_json_val *params)
997 : : {
998 : 206 : struct rpc_bdev_lvol_delete req = {};
999 : : struct spdk_bdev *bdev;
1000 : : struct spdk_lvol *lvol;
1001 : 126 : struct spdk_uuid uuid;
1002 : : char *lvs_name, *lvol_name;
1003 : :
1004 [ - + ]: 206 : 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 : 206 : bdev = spdk_bdev_get_by_name(req.name);
1015 [ + + ]: 206 : if (bdev != NULL) {
1016 : 204 : lvol = vbdev_lvol_get_from_bdev(bdev);
1017 [ + - ]: 204 : if (lvol != NULL) {
1018 : 204 : goto done;
1019 : : }
1020 : 0 : }
1021 : :
1022 : : /* lvol is degraded, get lvol via UUID */
1023 [ + - ]: 2 : if (spdk_uuid_parse(&uuid, req.name) == 0) {
1024 : 2 : lvol = spdk_lvol_get_by_uuid(&uuid);
1025 [ + - ]: 2 : if (lvol != NULL) {
1026 : 2 : goto done;
1027 : : }
1028 : 0 : }
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 : 0 : }
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 : 203 : done:
1047 : 206 : vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1048 : :
1049 : 203 : cleanup:
1050 : 206 : free_rpc_bdev_lvol_delete(&req);
1051 : 206 : }
1052 : :
1053 : 2024 : 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 : 499 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1062 : : {
1063 [ # # # # ]: 499 : free(req->uuid);
1064 [ # # # # ]: 499 : free(req->lvs_name);
1065 : 499 : }
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 : 174 : 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 [ # # # # : 174 : bs = lvs_bdev->lvs->blobstore;
# # # # ]
1079 : 174 : cluster_size = spdk_bs_get_cluster_size(bs);
1080 : :
1081 : 174 : spdk_json_write_object_begin(w);
1082 : :
1083 [ # # # # : 174 : spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
# # ]
1084 [ # # # # : 174 : spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
# # ]
1085 [ # # # # ]: 174 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1086 : 174 : spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1087 : 174 : spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1088 : 174 : spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1089 : 174 : spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1090 : :
1091 : 174 : spdk_json_write_object_end(w);
1092 : 174 : }
1093 : :
1094 : : static void
1095 : 499 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1096 : : const struct spdk_json_val *params)
1097 : : {
1098 : 499 : struct rpc_bdev_lvol_get_lvstores req = {};
1099 : : struct spdk_json_write_ctx *w;
1100 : 499 : struct lvol_store_bdev *lvs_bdev = NULL;
1101 : 499 : struct spdk_lvol_store *lvs = NULL;
1102 : : int rc;
1103 : :
1104 [ + + ]: 499 : if (params != NULL) {
1105 [ - + ]: 106 : 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 [ # # ]: 106 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1115 [ + + ]: 106 : if (rc != 0) {
1116 [ # # ]: 50 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1117 : 50 : goto cleanup;
1118 : : }
1119 : :
1120 : 56 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1121 [ - + ]: 56 : if (lvs_bdev == NULL) {
1122 : 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1123 : 0 : goto cleanup;
1124 : : }
1125 : 0 : }
1126 : :
1127 : 449 : w = spdk_jsonrpc_begin_result(request);
1128 : 449 : spdk_json_write_array_begin(w);
1129 : :
1130 [ + + ]: 449 : if (lvs_bdev != NULL) {
1131 : 56 : rpc_dump_lvol_store_info(w, lvs_bdev);
1132 : 0 : } else {
1133 [ + + ]: 511 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1134 : 118 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1135 : 118 : rpc_dump_lvol_store_info(w, lvs_bdev);
1136 : 0 : }
1137 : : }
1138 : 449 : spdk_json_write_array_end(w);
1139 : :
1140 : 449 : spdk_jsonrpc_end_result(request, w);
1141 : :
1142 : 499 : cleanup:
1143 : 499 : free_rpc_bdev_lvol_get_lvstores(&req);
1144 : 499 : }
1145 : :
1146 : 2024 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1147 : 2024 : 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 : 13 : free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
1156 : : {
1157 [ # # # # ]: 13 : free(req->lvs_uuid);
1158 [ # # # # ]: 13 : free(req->lvs_name);
1159 : 13 : }
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 : 18 : rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
1168 : : {
1169 [ # # # # ]: 18 : struct spdk_lvol_store *lvs = lvol->lvol_store;
1170 : :
1171 : 18 : spdk_json_write_object_begin(w);
1172 : :
1173 [ # # # # ]: 18 : spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
1174 [ # # ]: 18 : spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
1175 [ # # ]: 18 : spdk_json_write_named_string(w, "name", lvol->name);
1176 [ # # # # ]: 18 : spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
1177 [ # # # # ]: 18 : spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
1178 [ # # # # ]: 18 : spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
1179 [ # # # # ]: 18 : spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
1180 [ # # # # ]: 18 : spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
1181 : 18 : spdk_json_write_named_uint64(w, "num_allocated_clusters",
1182 [ # # # # ]: 0 : spdk_blob_get_num_allocated_clusters(lvol->blob));
1183 : :
1184 : 18 : spdk_json_write_named_object_begin(w, "lvs");
1185 [ # # ]: 18 : spdk_json_write_named_string(w, "name", lvs->name);
1186 [ # # ]: 18 : spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1187 : 18 : spdk_json_write_object_end(w);
1188 : :
1189 : 18 : spdk_json_write_object_end(w);
1190 : 18 : }
1191 : :
1192 : : static void
1193 : 13 : rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1194 : : {
1195 [ # # # # ]: 13 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1196 : : struct spdk_lvol *lvol;
1197 : :
1198 [ + + # # : 31 : TAILQ_FOREACH(lvol, &lvs->lvols, link) {
# # # # #
# # # #
# ]
1199 [ - + # # : 18 : if (lvol->ref_count == 0) {
# # ]
1200 : 0 : continue;
1201 : : }
1202 : 18 : rpc_dump_lvol(w, lvol);
1203 : 0 : }
1204 : 13 : }
1205 : :
1206 : : static void
1207 : 13 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1208 : : {
1209 : 13 : struct rpc_bdev_lvol_get_lvols req = {};
1210 : : struct spdk_json_write_ctx *w;
1211 : 13 : struct lvol_store_bdev *lvs_bdev = NULL;
1212 : 13 : struct spdk_lvol_store *lvs = NULL;
1213 : : int rc;
1214 : :
1215 [ - + ]: 13 : 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 : 0 : }
1237 : :
1238 : 13 : w = spdk_jsonrpc_begin_result(request);
1239 : 13 : spdk_json_write_array_begin(w);
1240 : :
1241 [ - + ]: 13 : if (lvs_bdev != NULL) {
1242 : 0 : rpc_dump_lvols(w, lvs_bdev);
1243 : 0 : } else {
1244 [ + + ]: 26 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1245 : 13 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1246 : 13 : rpc_dump_lvols(w, lvs_bdev);
1247 : 0 : }
1248 : : }
1249 : 13 : spdk_json_write_array_end(w);
1250 : :
1251 : 13 : spdk_jsonrpc_end_result(request, w);
1252 : :
1253 : 13 : cleanup:
1254 : 13 : free_rpc_bdev_lvol_get_lvols(&req);
1255 : 13 : }
1256 : :
1257 : 2024 : 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 : 2 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1266 : : {
1267 [ # # # # ]: 2 : free(req->uuid);
1268 [ # # # # ]: 2 : free(req->lvs_name);
1269 : 2 : }
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 : 2 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1278 : : {
1279 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
1280 : :
1281 [ - + ]: 2 : if (lvserrno != 0) {
1282 : 0 : goto invalid;
1283 : : }
1284 : :
1285 : 2 : spdk_jsonrpc_send_bool_response(request, true);
1286 : 2 : return;
1287 : :
1288 : 0 : invalid:
1289 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1290 [ # # ]: 0 : spdk_strerror(-lvserrno));
1291 : 0 : }
1292 : :
1293 : : static void
1294 : 2 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1295 : : const struct spdk_json_val *params)
1296 : : {
1297 : 2 : struct rpc_bdev_lvol_grow_lvstore req = {};
1298 : 2 : struct spdk_lvol_store *lvs = NULL;
1299 : : int rc;
1300 : :
1301 [ - + ]: 2 : 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 [ # # ]: 2 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1311 [ - + ]: 2 : if (rc != 0) {
1312 [ # # ]: 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1313 : 0 : goto cleanup;
1314 : : }
1315 [ # # # # ]: 2 : spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1316 : 2 : spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1317 : :
1318 : 2 : cleanup:
1319 : 2 : free_rpc_bdev_lvol_grow_lvstore(&req);
1320 : 2 : }
1321 : 2024 : 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 : 1 : free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
1335 : : {
1336 [ # # # # ]: 1 : free(req->src_lvol_name);
1337 [ # # # # ]: 1 : free(req->dst_bdev_name);
1338 : 1 : }
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 : 1 : rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1347 : : {
1348 : 1 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
1349 : :
1350 [ # # # # : 1 : ctx->status->result = lvolerrno;
# # # # ]
1351 : :
1352 : 1 : free(ctx);
1353 : 1 : }
1354 : :
1355 : : static void
1356 : 2 : rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
1357 : : {
1358 : 2 : struct rpc_shallow_copy_status *status = cb_arg;
1359 : :
1360 [ # # # # ]: 2 : status->copied_clusters = copied_clusters;
1361 : 2 : }
1362 : :
1363 : : static void
1364 : 1 : rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
1365 : : const struct spdk_json_val *params)
1366 : : {
1367 : 1 : 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 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
# # ]
1376 : :
1377 [ - + ]: 1 : 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 : 1 : src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
1387 [ - + ]: 1 : 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 : 1 : src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
1394 [ - + ]: 1 : 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 : 1 : status = calloc(1, sizeof(*status));
1401 [ - + ]: 1 : 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 [ # # # # ]: 1 : status->operation_id = ++g_shallow_copy_count;
1408 [ # # # # : 1 : status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
# # # # ]
1409 : :
1410 : 1 : ctx = calloc(1, sizeof(*ctx));
1411 [ - + ]: 1 : 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 [ # # # # ]: 1 : ctx->request = request;
1418 [ # # # # ]: 1 : ctx->status = status;
1419 : :
1420 [ - + # # : 1 : LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
# # # # #
# # # # #
# # # # #
# # # #
# ]
1421 [ # # ]: 1 : rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
1422 : 0 : rpc_bdev_lvol_shallow_copy_status_cb, status,
1423 : 0 : rpc_bdev_lvol_shallow_copy_cb, ctx);
1424 : :
1425 [ - + ]: 1 : if (rc < 0) {
1426 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1427 [ # # ]: 0 : spdk_strerror(-rc));
1428 [ # # # # : 0 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1429 : 0 : free(ctx);
1430 : 0 : free(status);
1431 : 0 : } else {
1432 : 1 : w = spdk_jsonrpc_begin_result(request);
1433 : :
1434 : 1 : spdk_json_write_object_begin(w);
1435 [ # # # # ]: 1 : spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
1436 : 1 : spdk_json_write_object_end(w);
1437 : :
1438 : 1 : spdk_jsonrpc_end_result(request, w);
1439 : : }
1440 : :
1441 : 1 : cleanup:
1442 : 1 : free_rpc_bdev_lvol_shallow_copy(&req);
1443 : 1 : }
1444 : :
1445 : 2024 : 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 : 1 : free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
1455 : : {
1456 [ # # # # ]: 1 : free(req->src_lvol_name);
1457 : 1 : }
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 : 1 : rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
1465 : : const struct spdk_json_val *params)
1466 : : {
1467 : 1 : 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 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
# # ]
1474 : :
1475 [ - + ]: 1 : 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 [ + - # # : 1 : LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
# # # # ]
1485 [ + - # # : 1 : if (status->operation_id == req.operation_id) {
# # # # ]
1486 : 1 : break;
1487 : : }
1488 : 0 : }
1489 : :
1490 [ - + ]: 1 : 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 [ # # # # ]: 1 : copied_clusters = status->copied_clusters;
1497 [ # # # # ]: 1 : total_clusters = status->total_clusters;
1498 [ # # # # ]: 1 : result = status->result;
1499 : :
1500 : 1 : w = spdk_jsonrpc_begin_result(request);
1501 : :
1502 : 1 : spdk_json_write_object_begin(w);
1503 : :
1504 : 1 : spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
1505 : 1 : spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
1506 [ - + - - ]: 1 : if (copied_clusters < total_clusters && result == 0) {
1507 : 0 : spdk_json_write_named_string(w, "state", "in progress");
1508 [ + - + - ]: 1 : } else if (copied_clusters == total_clusters && result == 0) {
1509 : 1 : spdk_json_write_named_string(w, "state", "complete");
1510 [ - + # # : 1 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1511 : 1 : free(status);
1512 : 0 : } 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 : 1 : spdk_json_write_object_end(w);
1520 : :
1521 : 1 : spdk_jsonrpc_end_result(request, w);
1522 : :
1523 : 1 : cleanup:
1524 : 1 : free_rpc_bdev_lvol_shallow_copy_status(&req);
1525 : 1 : }
1526 : :
1527 : 2024 : 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 : 14 : free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
1537 : : {
1538 [ # # # # ]: 14 : free(req->lvol_name);
1539 [ # # # # ]: 14 : free(req->parent_name);
1540 : 14 : }
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 : 13 : rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
1549 : : {
1550 : 13 : struct spdk_jsonrpc_request *request = cb_arg;
1551 : :
1552 [ + + ]: 13 : if (lvolerrno != 0) {
1553 : 7 : goto invalid;
1554 : : }
1555 : :
1556 : 6 : spdk_jsonrpc_send_bool_response(request, true);
1557 : 6 : return;
1558 : :
1559 : 7 : invalid:
1560 : 7 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1561 [ # # ]: 0 : spdk_strerror(-lvolerrno));
1562 : 0 : }
1563 : :
1564 : : static void
1565 : 8 : rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
1566 : : const struct spdk_json_val *params)
1567 : : {
1568 : 8 : struct rpc_bdev_lvol_set_parent req = {};
1569 : : struct spdk_lvol *lvol, *snapshot;
1570 : : struct spdk_bdev *lvol_bdev, *snapshot_bdev;
1571 : :
1572 [ - + - + : 8 : SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
# # ]
1573 : :
1574 [ - + ]: 8 : 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 : 8 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1584 [ - + ]: 8 : 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 : 8 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1591 [ - + ]: 8 : 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 [ # # ]: 8 : snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
1598 [ - + ]: 8 : 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 : 8 : snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
1605 [ + + ]: 8 : if (snapshot == NULL) {
1606 : 1 : SPDK_ERRLOG("snapshot does not exist\n");
1607 : 1 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1608 : 1 : goto cleanup;
1609 : : }
1610 : :
1611 : 7 : spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
1612 : :
1613 : 8 : cleanup:
1614 : 8 : free_rpc_bdev_lvol_set_parent(&req);
1615 : 8 : }
1616 : :
1617 : 2024 : SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1618 : :
1619 : : static void
1620 : 6 : rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1621 : : const struct spdk_json_val *params)
1622 : : {
1623 : 6 : struct rpc_bdev_lvol_set_parent req = {};
1624 : : struct spdk_lvol *lvol;
1625 : : struct spdk_bdev *lvol_bdev;
1626 : :
1627 [ - + - + : 6 : SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
# # ]
1628 : :
1629 [ - + ]: 6 : 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 : 6 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1639 [ - + ]: 6 : 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 : 6 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1646 [ - + ]: 6 : 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 [ # # ]: 6 : vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1653 : :
1654 : 6 : cleanup:
1655 : 6 : free_rpc_bdev_lvol_set_parent(&req);
1656 : 6 : }
1657 : :
1658 : 2024 : SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1659 : : SPDK_RPC_RUNTIME)
|