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 : 2118 : 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 : 713 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
42 : : struct spdk_lvol_store **lvs)
43 : : {
44 [ + + - + ]: 713 : if ((uuid == NULL && lvs_name == NULL)) {
45 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
# # ]
46 : 0 : return -EINVAL;
47 [ + + - + ]: 713 : } 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 [ + + ]: 713 : } else if (uuid) {
52 [ # # ]: 563 : *lvs = vbdev_get_lvol_store_by_uuid(uuid);
53 : :
54 [ + + # # ]: 563 : if (*lvs == NULL) {
55 [ - + - + : 45 : SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
# # ]
56 : 45 : return -ENODEV;
57 : : }
58 [ + - ]: 150 : } else if (lvs_name) {
59 : :
60 [ # # ]: 150 : *lvs = vbdev_get_lvol_store_by_name(lvs_name);
61 : :
62 [ + + # # ]: 150 : if (*lvs == NULL) {
63 [ - + - + : 11 : SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
# # ]
64 : 11 : return -ENODEV;
65 : : }
66 : 0 : }
67 : 657 : return 0;
68 : 0 : }
69 : :
70 : : static void
71 : 193 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
72 : : {
73 [ # # # # ]: 193 : free(req->bdev_name);
74 [ # # # # ]: 193 : free(req->lvs_name);
75 [ # # # # ]: 193 : free(req->clear_method);
76 : 193 : }
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 : 187 : 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 : 187 : struct spdk_jsonrpc_request *request = cb_arg;
91 : :
92 [ + + ]: 187 : if (lvserrno != 0) {
93 : 1 : goto invalid;
94 : : }
95 : :
96 : 186 : w = spdk_jsonrpc_begin_result(request);
97 [ # # ]: 186 : spdk_json_write_uuid(w, &lvol_store->uuid);
98 : 186 : spdk_jsonrpc_end_result(request, w);
99 : 186 : return;
100 : :
101 : 1 : invalid:
102 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
103 [ # # ]: 0 : spdk_strerror(-lvserrno));
104 : 0 : }
105 : :
106 : : static void
107 : 193 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
108 : : const struct spdk_json_val *params)
109 : : {
110 : 193 : struct rpc_bdev_lvol_create_lvstore req = {};
111 : 193 : int rc = 0;
112 : : enum lvs_clear_method clear_method;
113 : :
114 [ + + ]: 193 : 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 [ + + # # ]: 192 : if (req.clear_method != NULL) {
124 [ - + + + : 22 : if (!strcasecmp(req.clear_method, "none")) {
# # # # ]
125 : 18 : 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 : 0 : } else {
131 : 1 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
132 : 1 : goto cleanup;
133 : : }
134 : 0 : } else {
135 : 170 : clear_method = LVS_CLEAR_WITH_UNMAP;
136 : : }
137 : :
138 [ # # # # ]: 191 : rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
139 [ # # ]: 0 : req.num_md_pages_per_cluster_ratio, rpc_lvol_store_construct_cb, request);
140 [ + + ]: 191 : if (rc < 0) {
141 [ # # ]: 4 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
142 : 4 : goto cleanup;
143 : : }
144 : 187 : free_rpc_bdev_lvol_create_lvstore(&req);
145 : :
146 : 187 : return;
147 : :
148 : 6 : cleanup:
149 : 6 : free_rpc_bdev_lvol_create_lvstore(&req);
150 : 0 : }
151 : 2118 : 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 [ # # ]: 0 : spdk_strerror(-lvserrno));
185 : 0 : }
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 : 2118 : 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 : 131 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
224 : : {
225 [ # # # # ]: 131 : free(req->uuid);
226 [ # # # # ]: 131 : free(req->lvs_name);
227 : 131 : }
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 : 126 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
236 : : {
237 : 126 : struct spdk_jsonrpc_request *request = cb_arg;
238 : :
239 [ - + ]: 126 : if (lvserrno != 0) {
240 : 0 : goto invalid;
241 : : }
242 : :
243 : 126 : spdk_jsonrpc_send_bool_response(request, true);
244 : 126 : return;
245 : :
246 : 0 : invalid:
247 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
248 [ # # ]: 0 : spdk_strerror(-lvserrno));
249 : 0 : }
250 : :
251 : : static void
252 : 131 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
253 : : const struct spdk_json_val *params)
254 : : {
255 : 131 : struct rpc_bdev_lvol_delete_lvstore req = {};
256 : 131 : struct spdk_lvol_store *lvs = NULL;
257 : : int rc;
258 : :
259 [ - + ]: 131 : 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 [ # # ]: 131 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
269 [ + + ]: 131 : if (rc != 0) {
270 [ # # ]: 5 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
271 : 5 : goto cleanup;
272 : : }
273 : :
274 : 126 : vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
275 : :
276 : 131 : cleanup:
277 : 131 : free_rpc_bdev_lvol_delete_lvstore(&req);
278 : 131 : }
279 : 2118 : 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 : 467 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
292 : : {
293 [ # # # # ]: 467 : free(req->uuid);
294 [ # # # # ]: 467 : free(req->lvs_name);
295 [ # # # # ]: 467 : free(req->lvol_name);
296 [ # # # # ]: 467 : free(req->clear_method);
297 : 467 : }
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 : 465 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
310 : : {
311 : : struct spdk_json_write_ctx *w;
312 : 465 : struct spdk_jsonrpc_request *request = cb_arg;
313 : :
314 [ + + ]: 465 : if (lvolerrno != 0) {
315 : 2 : goto invalid;
316 : : }
317 : :
318 : 463 : w = spdk_jsonrpc_begin_result(request);
319 [ # # ]: 463 : spdk_json_write_string(w, lvol->unique_id);
320 : 463 : spdk_jsonrpc_end_result(request, w);
321 : 463 : return;
322 : :
323 : 2 : invalid:
324 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
325 [ # # ]: 0 : spdk_strerror(-lvolerrno));
326 : 0 : }
327 : :
328 : : static void
329 : 467 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
330 : : const struct spdk_json_val *params)
331 : : {
332 : 467 : struct rpc_bdev_lvol_create req = {};
333 : : enum lvol_clear_method clear_method;
334 : 467 : int rc = 0;
335 : 467 : struct spdk_lvol_store *lvs = NULL;
336 : :
337 [ - + - + : 467 : SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
# # ]
338 : :
339 [ - + ]: 467 : 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 [ # # ]: 467 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
349 [ + + ]: 467 : if (rc != 0) {
350 [ # # ]: 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
351 : 1 : goto cleanup;
352 : : }
353 : :
354 [ + + # # ]: 466 : 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 : 0 : } else {
362 : 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
363 : 0 : goto cleanup;
364 : : }
365 : 0 : } else {
366 : 463 : clear_method = LVOL_CLEAR_WITH_DEFAULT;
367 : : }
368 : :
369 [ # # # # ]: 466 : rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
370 [ - + # # ]: 466 : req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
371 [ + + ]: 466 : if (rc < 0) {
372 [ # # ]: 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
373 : 1 : goto cleanup;
374 : : }
375 : :
376 : 467 : cleanup:
377 : 467 : free_rpc_bdev_lvol_create(&req);
378 : 467 : }
379 : :
380 : 2118 : 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 [ # # ]: 0 : spdk_strerror(-lvolerrno));
417 : 0 : }
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 : 2118 : 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 [ # # ]: 0 : spdk_strerror(-lvolerrno));
495 : 0 : }
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 : 2118 : 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 : 0 : rpc_bdev_lvol_clone_cb, request);
615 : 7 : cleanup:
616 : 7 : free_rpc_bdev_lvol_clone_bdev(&req);
617 : 7 : }
618 : :
619 : 2118 : 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 [ # # ]: 0 : spdk_strerror(-lvolerrno));
653 : 0 : }
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 : 2118 : 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 : 10 : free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
702 : : {
703 [ # # # # ]: 10 : free(req->name);
704 : 10 : }
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 : 10 : rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
712 : : {
713 : 10 : struct spdk_jsonrpc_request *request = cb_arg;
714 : :
715 [ + + ]: 10 : if (lvolerrno != 0) {
716 : 1 : goto invalid;
717 : : }
718 : :
719 : 9 : spdk_jsonrpc_send_bool_response(request, true);
720 : 9 : return;
721 : :
722 : 1 : invalid:
723 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
724 [ # # ]: 0 : spdk_strerror(-lvolerrno));
725 : 0 : }
726 : :
727 : : static void
728 : 7 : rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
729 : : const struct spdk_json_val *params)
730 : : {
731 : 7 : struct rpc_bdev_lvol_inflate req = {};
732 : : struct spdk_bdev *bdev;
733 : : struct spdk_lvol *lvol;
734 : :
735 [ - + - + : 7 : SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
# # ]
736 : :
737 [ - + ]: 7 : 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 : 7 : bdev = spdk_bdev_get_by_name(req.name);
747 [ - + ]: 7 : 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 : 7 : lvol = vbdev_lvol_get_from_bdev(bdev);
754 [ - + ]: 7 : 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 : 7 : spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
761 : :
762 : 7 : cleanup:
763 : 7 : free_rpc_bdev_lvol_inflate(&req);
764 : 7 : }
765 : :
766 : 2118 : 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 : 2118 : 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 : 25 : free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
816 : : {
817 [ # # # # ]: 25 : free(req->name);
818 : 25 : }
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 : 24 : rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
827 : : {
828 : 24 : struct spdk_jsonrpc_request *request = cb_arg;
829 : :
830 [ + + ]: 24 : if (lvolerrno != 0) {
831 : 1 : goto invalid;
832 : : }
833 : :
834 : 23 : spdk_jsonrpc_send_bool_response(request, true);
835 : 23 : return;
836 : :
837 : 1 : invalid:
838 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
839 [ # # ]: 0 : spdk_strerror(-lvolerrno));
840 : 0 : }
841 : :
842 : : static void
843 : 25 : rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
844 : : const struct spdk_json_val *params)
845 : : {
846 : 25 : struct rpc_bdev_lvol_resize req = {};
847 : : struct spdk_bdev *bdev;
848 : : struct spdk_lvol *lvol;
849 : :
850 [ - + - + : 25 : SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
# # ]
851 : :
852 [ - + ]: 25 : 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 : 25 : bdev = spdk_bdev_get_by_name(req.name);
862 [ + + ]: 25 : 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 : 24 : lvol = vbdev_lvol_get_from_bdev(bdev);
869 [ - + ]: 24 : if (lvol == NULL) {
870 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
871 : 0 : goto cleanup;
872 : : }
873 : :
874 : :
875 [ # # ]: 24 : vbdev_lvol_resize(lvol, req.size_in_mib * 1024 * 1024, rpc_bdev_lvol_resize_cb, request);
876 : :
877 : 25 : cleanup:
878 : 25 : free_rpc_bdev_lvol_resize(&req);
879 : 25 : }
880 : :
881 : 2118 : 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 [ # # ]: 0 : spdk_strerror(-lvolerrno));
912 : 0 : }
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 : 2118 : 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 : 227 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
966 : : {
967 [ # # # # ]: 227 : free(req->name);
968 : 227 : }
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 : 227 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
976 : : {
977 : 227 : struct spdk_jsonrpc_request *request = cb_arg;
978 : :
979 [ + + ]: 227 : if (lvolerrno != 0) {
980 : 3 : goto invalid;
981 : : }
982 : :
983 : 224 : spdk_jsonrpc_send_bool_response(request, true);
984 : 224 : return;
985 : :
986 : 3 : invalid:
987 : 3 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
988 [ # # ]: 0 : spdk_strerror(-lvolerrno));
989 : 0 : }
990 : :
991 : : static void
992 : 227 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
993 : : const struct spdk_json_val *params)
994 : : {
995 : 227 : struct rpc_bdev_lvol_delete req = {};
996 : : struct spdk_bdev *bdev;
997 : : struct spdk_lvol *lvol;
998 : 134 : struct spdk_uuid uuid;
999 : : char *lvs_name, *lvol_name;
1000 : :
1001 [ - + ]: 227 : 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 : 227 : bdev = spdk_bdev_get_by_name(req.name);
1012 [ + + ]: 227 : if (bdev != NULL) {
1013 : 225 : lvol = vbdev_lvol_get_from_bdev(bdev);
1014 [ + - ]: 225 : if (lvol != NULL) {
1015 : 225 : goto done;
1016 : : }
1017 : 0 : }
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 : 0 : }
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 : 0 : }
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 : 227 : done:
1044 : 227 : vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1045 : :
1046 : 227 : cleanup:
1047 : 227 : free_rpc_bdev_lvol_delete(&req);
1048 : 227 : }
1049 : :
1050 : 2118 : 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 : 534 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1059 : : {
1060 [ # # # # ]: 534 : free(req->uuid);
1061 [ # # # # ]: 534 : free(req->lvs_name);
1062 : 534 : }
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 : 212 : 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 [ # # # # : 212 : bs = lvs_bdev->lvs->blobstore;
# # # # ]
1076 : 212 : cluster_size = spdk_bs_get_cluster_size(bs);
1077 : :
1078 : 212 : spdk_json_write_object_begin(w);
1079 : :
1080 [ # # # # : 212 : spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
# # ]
1081 [ # # # # : 212 : spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
# # ]
1082 [ # # # # ]: 212 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1083 : 212 : spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1084 : 212 : spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1085 : 212 : spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1086 : 212 : spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1087 : :
1088 : 212 : spdk_json_write_object_end(w);
1089 : 212 : }
1090 : :
1091 : : static void
1092 : 534 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1093 : : const struct spdk_json_val *params)
1094 : : {
1095 : 534 : struct rpc_bdev_lvol_get_lvstores req = {};
1096 : : struct spdk_json_write_ctx *w;
1097 : 534 : struct lvol_store_bdev *lvs_bdev = NULL;
1098 : 534 : struct spdk_lvol_store *lvs = NULL;
1099 : : int rc;
1100 : :
1101 [ + + ]: 534 : if (params != NULL) {
1102 [ - + ]: 106 : 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 [ # # ]: 106 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1112 [ + + ]: 106 : if (rc != 0) {
1113 [ # # ]: 50 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1114 : 50 : goto cleanup;
1115 : : }
1116 : :
1117 : 56 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1118 [ - + ]: 56 : if (lvs_bdev == NULL) {
1119 : 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1120 : 0 : goto cleanup;
1121 : : }
1122 : 0 : }
1123 : :
1124 : 484 : w = spdk_jsonrpc_begin_result(request);
1125 : 484 : spdk_json_write_array_begin(w);
1126 : :
1127 [ + + ]: 484 : if (lvs_bdev != NULL) {
1128 : 56 : rpc_dump_lvol_store_info(w, lvs_bdev);
1129 : 0 : } else {
1130 [ + + ]: 584 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1131 : 156 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1132 : 156 : rpc_dump_lvol_store_info(w, lvs_bdev);
1133 : 0 : }
1134 : : }
1135 : 484 : spdk_json_write_array_end(w);
1136 : :
1137 : 484 : spdk_jsonrpc_end_result(request, w);
1138 : :
1139 : 534 : cleanup:
1140 : 534 : free_rpc_bdev_lvol_get_lvstores(&req);
1141 : 534 : }
1142 : :
1143 : 2118 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1144 : 2118 : 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 : if (lvol->ref_count == 0) {
# # ]
1195 : 0 : continue;
1196 : : }
1197 : 18 : rpc_dump_lvol(w, lvol);
1198 : 0 : }
1199 : 13 : }
1200 : :
1201 : : static void
1202 : 13 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1203 : : {
1204 : 13 : struct rpc_bdev_lvol_get_lvols req = {};
1205 : : struct spdk_json_write_ctx *w;
1206 : 13 : struct lvol_store_bdev *lvs_bdev = NULL;
1207 : 13 : struct spdk_lvol_store *lvs = NULL;
1208 : : int rc;
1209 : :
1210 [ - + ]: 13 : if (params != NULL) {
1211 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1212 : : SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1213 : : &req)) {
1214 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1215 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1216 : : "spdk_json_decode_object failed");
1217 : 0 : goto cleanup;
1218 : : }
1219 : :
1220 [ # # ]: 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1221 [ # # ]: 0 : if (rc != 0) {
1222 [ # # ]: 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1223 : 0 : goto cleanup;
1224 : : }
1225 : :
1226 : 0 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1227 [ # # ]: 0 : if (lvs_bdev == NULL) {
1228 : 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1229 : 0 : goto cleanup;
1230 : : }
1231 : 0 : }
1232 : :
1233 : 13 : w = spdk_jsonrpc_begin_result(request);
1234 : 13 : spdk_json_write_array_begin(w);
1235 : :
1236 [ - + ]: 13 : if (lvs_bdev != NULL) {
1237 : 0 : rpc_dump_lvols(w, lvs_bdev);
1238 : 0 : } else {
1239 [ + + ]: 26 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1240 : 13 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1241 : 13 : rpc_dump_lvols(w, lvs_bdev);
1242 : 0 : }
1243 : : }
1244 : 13 : spdk_json_write_array_end(w);
1245 : :
1246 : 13 : spdk_jsonrpc_end_result(request, w);
1247 : :
1248 : 13 : cleanup:
1249 : 13 : free_rpc_bdev_lvol_get_lvols(&req);
1250 : 13 : }
1251 : :
1252 : 2118 : SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1253 : :
1254 : : struct rpc_bdev_lvol_grow_lvstore {
1255 : : char *uuid;
1256 : : char *lvs_name;
1257 : : };
1258 : :
1259 : : static void
1260 : 2 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1261 : : {
1262 [ # # # # ]: 2 : free(req->uuid);
1263 [ # # # # ]: 2 : free(req->lvs_name);
1264 : 2 : }
1265 : :
1266 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1267 : : {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1268 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1269 : : };
1270 : :
1271 : : static void
1272 : 2 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1273 : : {
1274 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
1275 : :
1276 [ - + ]: 2 : if (lvserrno != 0) {
1277 : 0 : goto invalid;
1278 : : }
1279 : :
1280 : 2 : spdk_jsonrpc_send_bool_response(request, true);
1281 : 2 : return;
1282 : :
1283 : 0 : invalid:
1284 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1285 [ # # ]: 0 : spdk_strerror(-lvserrno));
1286 : 0 : }
1287 : :
1288 : : static void
1289 : 2 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1290 : : const struct spdk_json_val *params)
1291 : : {
1292 : 2 : struct rpc_bdev_lvol_grow_lvstore req = {};
1293 : 2 : struct spdk_lvol_store *lvs = NULL;
1294 : : int rc;
1295 : :
1296 [ - + ]: 2 : if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1297 : : SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1298 : : &req)) {
1299 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1300 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1301 : : "spdk_json_decode_object failed");
1302 : 0 : goto cleanup;
1303 : : }
1304 : :
1305 [ # # ]: 2 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1306 [ - + ]: 2 : if (rc != 0) {
1307 [ # # ]: 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1308 : 0 : goto cleanup;
1309 : : }
1310 [ # # # # ]: 2 : spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1311 : 2 : spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1312 : :
1313 : 2 : cleanup:
1314 : 2 : free_rpc_bdev_lvol_grow_lvstore(&req);
1315 : 2 : }
1316 : 2118 : SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
1317 : :
1318 : : struct rpc_bdev_lvol_shallow_copy {
1319 : : char *src_lvol_name;
1320 : : char *dst_bdev_name;
1321 : : };
1322 : :
1323 : : struct rpc_bdev_lvol_shallow_copy_ctx {
1324 : : struct spdk_jsonrpc_request *request;
1325 : : struct rpc_shallow_copy_status *status;
1326 : : };
1327 : :
1328 : : static void
1329 : 1 : free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
1330 : : {
1331 [ # # # # ]: 1 : free(req->src_lvol_name);
1332 [ # # # # ]: 1 : free(req->dst_bdev_name);
1333 : 1 : }
1334 : :
1335 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
1336 : : {"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
1337 : : {"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
1338 : : };
1339 : :
1340 : : static void
1341 : 1 : rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1342 : : {
1343 : 1 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
1344 : :
1345 [ # # # # : 1 : ctx->status->result = lvolerrno;
# # # # ]
1346 : :
1347 : 1 : free(ctx);
1348 : 1 : }
1349 : :
1350 : : static void
1351 : 2 : rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
1352 : : {
1353 : 2 : struct rpc_shallow_copy_status *status = cb_arg;
1354 : :
1355 [ # # # # ]: 2 : status->copied_clusters = copied_clusters;
1356 : 2 : }
1357 : :
1358 : : static void
1359 : 1 : rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
1360 : : const struct spdk_json_val *params)
1361 : : {
1362 : 1 : struct rpc_bdev_lvol_shallow_copy req = {};
1363 : : struct rpc_bdev_lvol_shallow_copy_ctx *ctx;
1364 : : struct spdk_lvol *src_lvol;
1365 : : struct spdk_bdev *src_lvol_bdev;
1366 : : struct rpc_shallow_copy_status *status;
1367 : : struct spdk_json_write_ctx *w;
1368 : : int rc;
1369 : :
1370 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
# # ]
1371 : :
1372 [ - + ]: 1 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
1373 : : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
1374 : : &req)) {
1375 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1376 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1377 : : "spdk_json_decode_object failed");
1378 : 0 : goto cleanup;
1379 : : }
1380 : :
1381 : 1 : src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
1382 [ - + ]: 1 : if (src_lvol_bdev == NULL) {
1383 : 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
1384 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1385 : 0 : goto cleanup;
1386 : : }
1387 : :
1388 : 1 : src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
1389 [ - + ]: 1 : if (src_lvol == NULL) {
1390 : 0 : SPDK_ERRLOG("lvol does not exist\n");
1391 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1392 : 0 : goto cleanup;
1393 : : }
1394 : :
1395 : 1 : status = calloc(1, sizeof(*status));
1396 [ - + ]: 1 : if (status == NULL) {
1397 : 0 : SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name);
1398 : 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1399 : 0 : goto cleanup;
1400 : : }
1401 : :
1402 [ # # # # ]: 1 : status->operation_id = ++g_shallow_copy_count;
1403 [ # # # # : 1 : status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
# # # # ]
1404 : :
1405 : 1 : ctx = calloc(1, sizeof(*ctx));
1406 [ - + ]: 1 : if (ctx == NULL) {
1407 : 0 : SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name);
1408 : 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1409 : 0 : free(status);
1410 : 0 : goto cleanup;
1411 : : }
1412 [ # # # # ]: 1 : ctx->request = request;
1413 [ # # # # ]: 1 : ctx->status = status;
1414 : :
1415 [ - + # # : 1 : LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
# # # # #
# # # # #
# # # # #
# # # #
# ]
1416 [ # # ]: 1 : rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
1417 : 0 : rpc_bdev_lvol_shallow_copy_status_cb, status,
1418 : 0 : rpc_bdev_lvol_shallow_copy_cb, ctx);
1419 : :
1420 [ - + ]: 1 : if (rc < 0) {
1421 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1422 [ # # ]: 0 : spdk_strerror(-rc));
1423 [ # # # # : 0 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1424 : 0 : free(ctx);
1425 : 0 : free(status);
1426 : 0 : } else {
1427 : 1 : w = spdk_jsonrpc_begin_result(request);
1428 : :
1429 : 1 : spdk_json_write_object_begin(w);
1430 [ # # # # ]: 1 : spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
1431 : 1 : spdk_json_write_object_end(w);
1432 : :
1433 : 1 : spdk_jsonrpc_end_result(request, w);
1434 : : }
1435 : :
1436 : 1 : cleanup:
1437 : 1 : free_rpc_bdev_lvol_shallow_copy(&req);
1438 : 1 : }
1439 : :
1440 : 2118 : SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy,
1441 : : SPDK_RPC_RUNTIME)
1442 : :
1443 : : struct rpc_bdev_lvol_shallow_copy_status {
1444 : : char *src_lvol_name;
1445 : : uint32_t operation_id;
1446 : : };
1447 : :
1448 : : static void
1449 : 1 : free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
1450 : : {
1451 [ # # # # ]: 1 : free(req->src_lvol_name);
1452 : 1 : }
1453 : :
1454 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
1455 : : {"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32},
1456 : : };
1457 : :
1458 : : static void
1459 : 1 : rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
1460 : : const struct spdk_json_val *params)
1461 : : {
1462 : 1 : struct rpc_bdev_lvol_shallow_copy_status req = {};
1463 : : struct rpc_shallow_copy_status *status;
1464 : : struct spdk_json_write_ctx *w;
1465 : : uint64_t copied_clusters, total_clusters;
1466 : : int result;
1467 : :
1468 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
# # ]
1469 : :
1470 [ - + ]: 1 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
1471 : : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
1472 : : &req)) {
1473 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1474 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1475 : : "spdk_json_decode_object failed");
1476 : 0 : goto cleanup;
1477 : : }
1478 : :
1479 [ + - # # : 1 : LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
# # # # ]
1480 [ + - # # : 1 : if (status->operation_id == req.operation_id) {
# # # # ]
1481 : 1 : break;
1482 : : }
1483 : 0 : }
1484 : :
1485 [ - + ]: 1 : if (!status) {
1486 [ # # ]: 0 : SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id);
1487 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1488 : 0 : goto cleanup;
1489 : : }
1490 : :
1491 [ # # # # ]: 1 : copied_clusters = status->copied_clusters;
1492 [ # # # # ]: 1 : total_clusters = status->total_clusters;
1493 [ # # # # ]: 1 : result = status->result;
1494 : :
1495 : 1 : w = spdk_jsonrpc_begin_result(request);
1496 : :
1497 : 1 : spdk_json_write_object_begin(w);
1498 : :
1499 : 1 : spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
1500 : 1 : spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
1501 [ - + - - ]: 1 : if (copied_clusters < total_clusters && result == 0) {
1502 : 0 : spdk_json_write_named_string(w, "state", "in progress");
1503 [ + - + - ]: 1 : } else if (copied_clusters == total_clusters && result == 0) {
1504 : 1 : spdk_json_write_named_string(w, "state", "complete");
1505 [ - + # # : 1 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1506 : 1 : free(status);
1507 : 0 : } else {
1508 : 0 : spdk_json_write_named_string(w, "state", "error");
1509 [ # # ]: 0 : spdk_json_write_named_string(w, "error", spdk_strerror(-result));
1510 [ # # # # : 0 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1511 : 0 : free(status);
1512 : : }
1513 : :
1514 : 1 : spdk_json_write_object_end(w);
1515 : :
1516 : 1 : spdk_jsonrpc_end_result(request, w);
1517 : :
1518 : 1 : cleanup:
1519 : 1 : free_rpc_bdev_lvol_shallow_copy_status(&req);
1520 : 1 : }
1521 : :
1522 : 2118 : SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy,
1523 : : SPDK_RPC_RUNTIME)
1524 : :
1525 : : struct rpc_bdev_lvol_set_parent {
1526 : : char *lvol_name;
1527 : : char *parent_name;
1528 : : };
1529 : :
1530 : : static void
1531 : 14 : free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
1532 : : {
1533 [ # # # # ]: 14 : free(req->lvol_name);
1534 [ # # # # ]: 14 : free(req->parent_name);
1535 : 14 : }
1536 : :
1537 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = {
1538 : : {"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string},
1539 : : {"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string},
1540 : : };
1541 : :
1542 : : static void
1543 : 13 : rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
1544 : : {
1545 : 13 : struct spdk_jsonrpc_request *request = cb_arg;
1546 : :
1547 [ + + ]: 13 : if (lvolerrno != 0) {
1548 : 7 : goto invalid;
1549 : : }
1550 : :
1551 : 6 : spdk_jsonrpc_send_bool_response(request, true);
1552 : 6 : return;
1553 : :
1554 : 7 : invalid:
1555 : 7 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1556 [ # # ]: 0 : spdk_strerror(-lvolerrno));
1557 : 0 : }
1558 : :
1559 : : static void
1560 : 8 : rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
1561 : : const struct spdk_json_val *params)
1562 : : {
1563 : 8 : struct rpc_bdev_lvol_set_parent req = {};
1564 : : struct spdk_lvol *lvol, *snapshot;
1565 : : struct spdk_bdev *lvol_bdev, *snapshot_bdev;
1566 : :
1567 [ - + - + : 8 : SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
# # ]
1568 : :
1569 [ - + ]: 8 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1570 : : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1571 : : &req)) {
1572 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1573 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1574 : : "spdk_json_decode_object failed");
1575 : 0 : goto cleanup;
1576 : : }
1577 : :
1578 : 8 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1579 [ - + ]: 8 : if (lvol_bdev == NULL) {
1580 : 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1581 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1582 : 0 : goto cleanup;
1583 : : }
1584 : :
1585 : 8 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1586 [ - + ]: 8 : if (lvol == NULL) {
1587 : 0 : SPDK_ERRLOG("lvol does not exist\n");
1588 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1589 : 0 : goto cleanup;
1590 : : }
1591 : :
1592 [ # # ]: 8 : snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
1593 [ - + ]: 8 : if (snapshot_bdev == NULL) {
1594 [ # # ]: 0 : SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name);
1595 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1596 : 0 : goto cleanup;
1597 : : }
1598 : :
1599 : 8 : snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
1600 [ + + ]: 8 : if (snapshot == NULL) {
1601 : 1 : SPDK_ERRLOG("snapshot does not exist\n");
1602 : 1 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1603 : 1 : goto cleanup;
1604 : : }
1605 : :
1606 : 7 : spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
1607 : :
1608 : 8 : cleanup:
1609 : 8 : free_rpc_bdev_lvol_set_parent(&req);
1610 : 8 : }
1611 : :
1612 : 2118 : SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1613 : :
1614 : : static void
1615 : 6 : rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1616 : : const struct spdk_json_val *params)
1617 : : {
1618 : 6 : struct rpc_bdev_lvol_set_parent req = {};
1619 : : struct spdk_lvol *lvol;
1620 : : struct spdk_bdev *lvol_bdev;
1621 : :
1622 [ - + - + : 6 : SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
# # ]
1623 : :
1624 [ - + ]: 6 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1625 : : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1626 : : &req)) {
1627 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1628 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1629 : : "spdk_json_decode_object failed");
1630 : 0 : goto cleanup;
1631 : : }
1632 : :
1633 : 6 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1634 [ - + ]: 6 : if (lvol_bdev == NULL) {
1635 : 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1636 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1637 : 0 : goto cleanup;
1638 : : }
1639 : :
1640 : 6 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1641 [ - + ]: 6 : if (lvol == NULL) {
1642 : 0 : SPDK_ERRLOG("lvol does not exist\n");
1643 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1644 : 0 : goto cleanup;
1645 : : }
1646 : :
1647 [ # # ]: 6 : vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1648 : :
1649 : 6 : cleanup:
1650 : 6 : free_rpc_bdev_lvol_set_parent(&req);
1651 : 6 : }
1652 : :
1653 : 2118 : SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1654 : : SPDK_RPC_RUNTIME)
|