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 : 2111 : 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 : 492 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
42 : : struct spdk_lvol_store **lvs)
43 : : {
44 [ + + + + ]: 492 : if ((uuid == NULL && lvs_name == NULL)) {
45 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
# # ]
46 : 0 : return -EINVAL;
47 [ + + - + ]: 492 : } 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 [ + + ]: 492 : } else if (uuid) {
52 [ # # ]: 353 : *lvs = vbdev_get_lvol_store_by_uuid(uuid);
53 : :
54 [ + + # # ]: 353 : if (*lvs == NULL) {
55 [ - + - + : 45 : SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
# # ]
56 : 45 : return -ENODEV;
57 : : }
58 [ + + ]: 139 : } else if (lvs_name) {
59 : :
60 [ # # ]: 139 : *lvs = vbdev_get_lvol_store_by_name(lvs_name);
61 : :
62 [ + + # # ]: 139 : if (*lvs == NULL) {
63 [ - + - + : 11 : SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
# # ]
64 : 11 : return -ENODEV;
65 : : }
66 : 3 : }
67 : 436 : return 0;
68 : 3 : }
69 : :
70 : : static void
71 : 163 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
72 : : {
73 [ # # # # ]: 163 : free(req->bdev_name);
74 [ # # # # ]: 163 : free(req->lvs_name);
75 [ # # # # ]: 163 : free(req->clear_method);
76 : 163 : }
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 : 157 : 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 : 157 : struct spdk_jsonrpc_request *request = cb_arg;
91 : :
92 [ + + ]: 157 : if (lvserrno != 0) {
93 : 1 : goto invalid;
94 : : }
95 : :
96 : 156 : w = spdk_jsonrpc_begin_result(request);
97 [ # # ]: 156 : spdk_json_write_uuid(w, &lvol_store->uuid);
98 : 156 : spdk_jsonrpc_end_result(request, w);
99 : 156 : return;
100 : :
101 : 1 : invalid:
102 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
103 [ # # ]: 0 : spdk_strerror(-lvserrno));
104 : 1 : }
105 : :
106 : : static void
107 : 163 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
108 : : const struct spdk_json_val *params)
109 : : {
110 : 163 : struct rpc_bdev_lvol_create_lvstore req = {};
111 : 163 : int rc = 0;
112 : : enum lvs_clear_method clear_method;
113 : :
114 [ + + ]: 163 : 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 [ + + # # ]: 162 : if (req.clear_method != NULL) {
124 [ - + + + : 26 : if (!strcasecmp(req.clear_method, "none")) {
# # # # ]
125 : 22 : 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 : 136 : clear_method = LVS_CLEAR_WITH_UNMAP;
136 : : }
137 : :
138 [ # # # # ]: 162 : rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
139 [ # # ]: 1 : req.num_md_pages_per_cluster_ratio, rpc_lvol_store_construct_cb, request);
140 [ + + ]: 161 : if (rc < 0) {
141 [ # # ]: 4 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
142 : 4 : goto cleanup;
143 : : }
144 : 157 : free_rpc_bdev_lvol_create_lvstore(&req);
145 : :
146 : 157 : return;
147 : :
148 : 6 : cleanup:
149 : 6 : free_rpc_bdev_lvol_create_lvstore(&req);
150 : 1 : }
151 : 2111 : 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 : 2111 : 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 : 117 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
224 : : {
225 [ # # # # ]: 117 : free(req->uuid);
226 [ # # # # ]: 117 : free(req->lvs_name);
227 : 117 : }
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 : 112 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
236 : : {
237 : 112 : struct spdk_jsonrpc_request *request = cb_arg;
238 : :
239 [ + + ]: 112 : if (lvserrno != 0) {
240 : 0 : goto invalid;
241 : : }
242 : :
243 : 112 : spdk_jsonrpc_send_bool_response(request, true);
244 : 112 : return;
245 : :
246 : 0 : invalid:
247 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
248 [ # # ]: 0 : spdk_strerror(-lvserrno));
249 : 1 : }
250 : :
251 : : static void
252 : 117 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
253 : : const struct spdk_json_val *params)
254 : : {
255 : 117 : struct rpc_bdev_lvol_delete_lvstore req = {};
256 : 117 : struct spdk_lvol_store *lvs = NULL;
257 : : int rc;
258 : :
259 [ - + ]: 117 : 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 [ # # ]: 117 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
269 [ + + ]: 117 : if (rc != 0) {
270 [ # # ]: 5 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
271 : 5 : goto cleanup;
272 : : }
273 : :
274 : 112 : vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
275 : :
276 : 116 : cleanup:
277 : 117 : free_rpc_bdev_lvol_delete_lvstore(&req);
278 : 117 : }
279 : 2111 : 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 : 260 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
292 : : {
293 [ # # # # ]: 260 : free(req->uuid);
294 [ # # # # ]: 260 : free(req->lvs_name);
295 [ # # # # ]: 260 : free(req->lvol_name);
296 [ # # # # ]: 260 : free(req->clear_method);
297 : 260 : }
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 : 258 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
310 : : {
311 : : struct spdk_json_write_ctx *w;
312 : 258 : struct spdk_jsonrpc_request *request = cb_arg;
313 : :
314 [ + + ]: 258 : if (lvolerrno != 0) {
315 : 2 : goto invalid;
316 : : }
317 : :
318 : 256 : w = spdk_jsonrpc_begin_result(request);
319 [ # # ]: 256 : spdk_json_write_string(w, lvol->unique_id);
320 : 256 : spdk_jsonrpc_end_result(request, w);
321 : 256 : return;
322 : :
323 : 2 : invalid:
324 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
325 [ # # ]: 0 : spdk_strerror(-lvolerrno));
326 : 2 : }
327 : :
328 : : static void
329 : 260 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
330 : : const struct spdk_json_val *params)
331 : : {
332 : 260 : struct rpc_bdev_lvol_create req = {};
333 : : enum lvol_clear_method clear_method;
334 : 260 : int rc = 0;
335 : 260 : struct spdk_lvol_store *lvs = NULL;
336 : :
337 [ + + - + : 260 : SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
# # ]
338 : :
339 [ - + ]: 260 : 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 [ # # ]: 260 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
349 [ + + ]: 260 : if (rc != 0) {
350 [ # # ]: 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
351 : 1 : goto cleanup;
352 : : }
353 : :
354 [ + + # # ]: 259 : 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 : 256 : clear_method = LVOL_CLEAR_WITH_DEFAULT;
367 : : }
368 : :
369 [ # # # # ]: 261 : rc = vbdev_lvol_create(lvs, req.lvol_name, req.size_in_mib * 1024 * 1024,
370 [ - + # # ]: 259 : req.thin_provision, clear_method, rpc_bdev_lvol_create_cb, request);
371 [ + + ]: 259 : if (rc < 0) {
372 [ # # ]: 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
373 : 1 : goto cleanup;
374 : : }
375 : :
376 : 258 : cleanup:
377 : 260 : free_rpc_bdev_lvol_create(&req);
378 : 260 : }
379 : :
380 : 2111 : 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 : 39 : free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
389 : : {
390 [ # # # # ]: 39 : free(req->lvol_name);
391 [ # # # # ]: 39 : free(req->snapshot_name);
392 : 39 : }
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 : 39 : rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
401 : : {
402 : : struct spdk_json_write_ctx *w;
403 : 39 : struct spdk_jsonrpc_request *request = cb_arg;
404 : :
405 [ + + ]: 39 : if (lvolerrno != 0) {
406 : 1 : goto invalid;
407 : : }
408 : :
409 : 38 : w = spdk_jsonrpc_begin_result(request);
410 [ # # ]: 38 : spdk_json_write_string(w, lvol->unique_id);
411 : 38 : spdk_jsonrpc_end_result(request, w);
412 : 38 : return;
413 : :
414 : 1 : invalid:
415 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
416 [ # # ]: 0 : spdk_strerror(-lvolerrno));
417 : 1 : }
418 : :
419 : : static void
420 : 39 : rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
421 : : const struct spdk_json_val *params)
422 : : {
423 : 39 : struct rpc_bdev_lvol_snapshot req = {};
424 : : struct spdk_bdev *bdev;
425 : : struct spdk_lvol *lvol;
426 : :
427 [ + + - + : 39 : SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
# # ]
428 : :
429 [ - + ]: 39 : 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 : 39 : bdev = spdk_bdev_get_by_name(req.lvol_name);
439 [ + + ]: 39 : 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 : 39 : lvol = vbdev_lvol_get_from_bdev(bdev);
446 [ + + ]: 39 : 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 [ # # ]: 39 : vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
453 : :
454 : 38 : cleanup:
455 : 39 : free_rpc_bdev_lvol_snapshot(&req);
456 : 39 : }
457 : :
458 : 2111 : 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 : 25 : free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
467 : : {
468 [ # # # # ]: 25 : free(req->snapshot_name);
469 [ # # # # ]: 25 : free(req->clone_name);
470 : 25 : }
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 : 32 : rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
479 : : {
480 : : struct spdk_json_write_ctx *w;
481 : 32 : struct spdk_jsonrpc_request *request = cb_arg;
482 : :
483 [ + + ]: 32 : if (lvolerrno != 0) {
484 : 2 : goto invalid;
485 : : }
486 : :
487 : 30 : w = spdk_jsonrpc_begin_result(request);
488 [ # # ]: 30 : spdk_json_write_string(w, lvol->unique_id);
489 : 30 : spdk_jsonrpc_end_result(request, w);
490 : 30 : return;
491 : :
492 : 2 : invalid:
493 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
494 [ # # ]: 0 : spdk_strerror(-lvolerrno));
495 : 1 : }
496 : :
497 : : static void
498 : 25 : rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
499 : : const struct spdk_json_val *params)
500 : : {
501 : 25 : struct rpc_bdev_lvol_clone req = {};
502 : : struct spdk_bdev *bdev;
503 : : struct spdk_lvol *lvol;
504 : :
505 [ + + - + : 25 : SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
# # ]
506 : :
507 [ - + ]: 25 : 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 : 25 : bdev = spdk_bdev_get_by_name(req.snapshot_name);
517 [ + + ]: 25 : 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 : 25 : lvol = vbdev_lvol_get_from_bdev(bdev);
524 [ + + ]: 25 : 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 [ # # ]: 25 : vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
531 : :
532 : 24 : cleanup:
533 : 25 : free_rpc_bdev_lvol_clone(&req);
534 : 25 : }
535 : :
536 : 2111 : 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 : 2111 : 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 : 2111 : 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 : 2111 : 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 : 2111 : 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 : 2111 : 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 : 2111 : 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 : 206 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
966 : : {
967 [ # # # # ]: 206 : free(req->name);
968 : 206 : }
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 : 206 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
976 : : {
977 : 206 : struct spdk_jsonrpc_request *request = cb_arg;
978 : :
979 [ + + ]: 206 : if (lvolerrno != 0) {
980 : 3 : goto invalid;
981 : : }
982 : :
983 : 203 : spdk_jsonrpc_send_bool_response(request, true);
984 : 203 : return;
985 : :
986 : 3 : invalid:
987 : 3 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
988 [ # # ]: 0 : spdk_strerror(-lvolerrno));
989 : 3 : }
990 : :
991 : : static void
992 : 206 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
993 : : const struct spdk_json_val *params)
994 : : {
995 : 206 : struct rpc_bdev_lvol_delete req = {};
996 : : struct spdk_bdev *bdev;
997 : : struct spdk_lvol *lvol;
998 : 126 : struct spdk_uuid uuid;
999 : : char *lvs_name, *lvol_name;
1000 : :
1001 [ - + ]: 206 : 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 : 206 : bdev = spdk_bdev_get_by_name(req.name);
1012 [ + + ]: 206 : if (bdev != NULL) {
1013 : 204 : lvol = vbdev_lvol_get_from_bdev(bdev);
1014 [ + - ]: 204 : if (lvol != NULL) {
1015 : 204 : 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 : 203 : done:
1044 : 206 : vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1045 : :
1046 : 203 : cleanup:
1047 : 206 : free_rpc_bdev_lvol_delete(&req);
1048 : 206 : }
1049 : :
1050 : 2111 : 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 : 486 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1059 : : {
1060 [ # # # # ]: 486 : free(req->uuid);
1061 [ # # # # ]: 486 : free(req->lvs_name);
1062 : 486 : }
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 : 179 : 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 [ # # # # : 179 : bs = lvs_bdev->lvs->blobstore;
# # # # ]
1076 : 179 : cluster_size = spdk_bs_get_cluster_size(bs);
1077 : :
1078 : 179 : spdk_json_write_object_begin(w);
1079 : :
1080 [ # # # # : 179 : spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
# # ]
1081 [ # # # # : 179 : spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
# # ]
1082 [ # # # # ]: 179 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1083 : 179 : spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1084 : 179 : spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1085 : 179 : spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1086 : 179 : spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1087 : :
1088 : 179 : spdk_json_write_object_end(w);
1089 : 179 : }
1090 : :
1091 : : static void
1092 : 486 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1093 : : const struct spdk_json_val *params)
1094 : : {
1095 : 486 : struct rpc_bdev_lvol_get_lvstores req = {};
1096 : : struct spdk_json_write_ctx *w;
1097 : 486 : struct lvol_store_bdev *lvs_bdev = NULL;
1098 : 486 : struct spdk_lvol_store *lvs = NULL;
1099 : : int rc;
1100 : :
1101 [ + + ]: 486 : 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 : 436 : w = spdk_jsonrpc_begin_result(request);
1125 : 436 : spdk_json_write_array_begin(w);
1126 : :
1127 [ + + ]: 436 : if (lvs_bdev != NULL) {
1128 : 56 : rpc_dump_lvol_store_info(w, lvs_bdev);
1129 : 0 : } else {
1130 [ + + ]: 503 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1131 : 123 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1132 : 123 : rpc_dump_lvol_store_info(w, lvs_bdev);
1133 : 0 : }
1134 : : }
1135 : 436 : spdk_json_write_array_end(w);
1136 : :
1137 : 436 : spdk_jsonrpc_end_result(request, w);
1138 : :
1139 : 486 : cleanup:
1140 : 486 : free_rpc_bdev_lvol_get_lvstores(&req);
1141 : 486 : }
1142 : :
1143 : 2111 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1144 : 2111 : 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 : 18 : spdk_json_write_named_uint64(w, "num_allocated_clusters",
1179 [ # # # # ]: 0 : spdk_blob_get_num_allocated_clusters(lvol->blob));
1180 : :
1181 : 18 : spdk_json_write_named_object_begin(w, "lvs");
1182 [ # # ]: 18 : spdk_json_write_named_string(w, "name", lvs->name);
1183 [ # # ]: 18 : spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1184 : 18 : spdk_json_write_object_end(w);
1185 : :
1186 : 18 : spdk_json_write_object_end(w);
1187 : 18 : }
1188 : :
1189 : : static void
1190 : 13 : rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1191 : : {
1192 [ # # # # ]: 13 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1193 : : struct spdk_lvol *lvol;
1194 : :
1195 [ + + # # : 31 : TAILQ_FOREACH(lvol, &lvs->lvols, link) {
# # # # #
# # # #
# ]
1196 [ - + # # : 18 : if (lvol->ref_count == 0) {
# # ]
1197 : 0 : continue;
1198 : : }
1199 : 18 : rpc_dump_lvol(w, lvol);
1200 : 0 : }
1201 : 13 : }
1202 : :
1203 : : static void
1204 : 13 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1205 : : {
1206 : 13 : struct rpc_bdev_lvol_get_lvols req = {};
1207 : : struct spdk_json_write_ctx *w;
1208 : 13 : struct lvol_store_bdev *lvs_bdev = NULL;
1209 : 13 : struct spdk_lvol_store *lvs = NULL;
1210 : : int rc;
1211 : :
1212 [ - + ]: 13 : if (params != NULL) {
1213 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1214 : : SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1215 : : &req)) {
1216 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1217 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1218 : : "spdk_json_decode_object failed");
1219 : 0 : goto cleanup;
1220 : : }
1221 : :
1222 [ # # ]: 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1223 [ # # ]: 0 : if (rc != 0) {
1224 [ # # ]: 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1225 : 0 : goto cleanup;
1226 : : }
1227 : :
1228 : 0 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1229 [ # # ]: 0 : if (lvs_bdev == NULL) {
1230 : 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1231 : 0 : goto cleanup;
1232 : : }
1233 : 0 : }
1234 : :
1235 : 13 : w = spdk_jsonrpc_begin_result(request);
1236 : 13 : spdk_json_write_array_begin(w);
1237 : :
1238 [ - + ]: 13 : if (lvs_bdev != NULL) {
1239 : 0 : rpc_dump_lvols(w, lvs_bdev);
1240 : 0 : } else {
1241 [ + + ]: 26 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1242 : 13 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1243 : 13 : rpc_dump_lvols(w, lvs_bdev);
1244 : 0 : }
1245 : : }
1246 : 13 : spdk_json_write_array_end(w);
1247 : :
1248 : 13 : spdk_jsonrpc_end_result(request, w);
1249 : :
1250 : 13 : cleanup:
1251 : 13 : free_rpc_bdev_lvol_get_lvols(&req);
1252 : 13 : }
1253 : :
1254 : 2111 : SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1255 : :
1256 : : struct rpc_bdev_lvol_grow_lvstore {
1257 : : char *uuid;
1258 : : char *lvs_name;
1259 : : };
1260 : :
1261 : : static void
1262 : 2 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1263 : : {
1264 [ # # # # ]: 2 : free(req->uuid);
1265 [ # # # # ]: 2 : free(req->lvs_name);
1266 : 2 : }
1267 : :
1268 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1269 : : {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1270 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1271 : : };
1272 : :
1273 : : static void
1274 : 2 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1275 : : {
1276 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
1277 : :
1278 [ - + ]: 2 : if (lvserrno != 0) {
1279 : 0 : goto invalid;
1280 : : }
1281 : :
1282 : 2 : spdk_jsonrpc_send_bool_response(request, true);
1283 : 2 : return;
1284 : :
1285 : 0 : invalid:
1286 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1287 [ # # ]: 0 : spdk_strerror(-lvserrno));
1288 : 0 : }
1289 : :
1290 : : static void
1291 : 2 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1292 : : const struct spdk_json_val *params)
1293 : : {
1294 : 2 : struct rpc_bdev_lvol_grow_lvstore req = {};
1295 : 2 : struct spdk_lvol_store *lvs = NULL;
1296 : : int rc;
1297 : :
1298 [ - + ]: 2 : if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1299 : : SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1300 : : &req)) {
1301 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1302 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1303 : : "spdk_json_decode_object failed");
1304 : 0 : goto cleanup;
1305 : : }
1306 : :
1307 [ # # ]: 2 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1308 [ - + ]: 2 : if (rc != 0) {
1309 [ # # ]: 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1310 : 0 : goto cleanup;
1311 : : }
1312 [ # # # # ]: 2 : spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1313 : 2 : spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1314 : :
1315 : 2 : cleanup:
1316 : 2 : free_rpc_bdev_lvol_grow_lvstore(&req);
1317 : 2 : }
1318 : 2111 : SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
1319 : :
1320 : : struct rpc_bdev_lvol_shallow_copy {
1321 : : char *src_lvol_name;
1322 : : char *dst_bdev_name;
1323 : : };
1324 : :
1325 : : struct rpc_bdev_lvol_shallow_copy_ctx {
1326 : : struct spdk_jsonrpc_request *request;
1327 : : struct rpc_shallow_copy_status *status;
1328 : : };
1329 : :
1330 : : static void
1331 : 1 : free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
1332 : : {
1333 [ # # # # ]: 1 : free(req->src_lvol_name);
1334 [ # # # # ]: 1 : free(req->dst_bdev_name);
1335 : 1 : }
1336 : :
1337 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
1338 : : {"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
1339 : : {"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
1340 : : };
1341 : :
1342 : : static void
1343 : 1 : rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1344 : : {
1345 : 1 : struct rpc_bdev_lvol_shallow_copy_ctx *ctx = cb_arg;
1346 : :
1347 [ # # # # : 1 : ctx->status->result = lvolerrno;
# # # # ]
1348 : :
1349 : 1 : free(ctx);
1350 : 1 : }
1351 : :
1352 : : static void
1353 : 2 : rpc_bdev_lvol_shallow_copy_status_cb(uint64_t copied_clusters, void *cb_arg)
1354 : : {
1355 : 2 : struct rpc_shallow_copy_status *status = cb_arg;
1356 : :
1357 [ # # # # ]: 2 : status->copied_clusters = copied_clusters;
1358 : 2 : }
1359 : :
1360 : : static void
1361 : 1 : rpc_bdev_lvol_start_shallow_copy(struct spdk_jsonrpc_request *request,
1362 : : const struct spdk_json_val *params)
1363 : : {
1364 : 1 : struct rpc_bdev_lvol_shallow_copy req = {};
1365 : : struct rpc_bdev_lvol_shallow_copy_ctx *ctx;
1366 : : struct spdk_lvol *src_lvol;
1367 : : struct spdk_bdev *src_lvol_bdev;
1368 : : struct rpc_shallow_copy_status *status;
1369 : : struct spdk_json_write_ctx *w;
1370 : : int rc;
1371 : :
1372 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
# # ]
1373 : :
1374 [ - + ]: 1 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
1375 : : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
1376 : : &req)) {
1377 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1378 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1379 : : "spdk_json_decode_object failed");
1380 : 0 : goto cleanup;
1381 : : }
1382 : :
1383 : 1 : src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
1384 [ - + ]: 1 : if (src_lvol_bdev == NULL) {
1385 : 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
1386 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1387 : 0 : goto cleanup;
1388 : : }
1389 : :
1390 : 1 : src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
1391 [ - + ]: 1 : if (src_lvol == NULL) {
1392 : 0 : SPDK_ERRLOG("lvol does not exist\n");
1393 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1394 : 0 : goto cleanup;
1395 : : }
1396 : :
1397 : 1 : status = calloc(1, sizeof(*status));
1398 [ - + ]: 1 : if (status == NULL) {
1399 : 0 : SPDK_ERRLOG("Cannot allocate status entry for shallow copy of '%s'\n", req.src_lvol_name);
1400 : 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1401 : 0 : goto cleanup;
1402 : : }
1403 : :
1404 [ # # # # ]: 1 : status->operation_id = ++g_shallow_copy_count;
1405 [ # # # # : 1 : status->total_clusters = spdk_blob_get_num_allocated_clusters(src_lvol->blob);
# # # # ]
1406 : :
1407 : 1 : ctx = calloc(1, sizeof(*ctx));
1408 [ - + ]: 1 : if (ctx == NULL) {
1409 : 0 : SPDK_ERRLOG("Cannot allocate context for shallow copy of '%s'\n", req.src_lvol_name);
1410 : 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1411 : 0 : free(status);
1412 : 0 : goto cleanup;
1413 : : }
1414 [ # # # # ]: 1 : ctx->request = request;
1415 [ # # # # ]: 1 : ctx->status = status;
1416 : :
1417 [ - + # # : 1 : LIST_INSERT_HEAD(&g_shallow_copy_status_list, status, link);
# # # # #
# # # # #
# # # # #
# # # #
# ]
1418 [ # # ]: 1 : rc = vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name,
1419 : 0 : rpc_bdev_lvol_shallow_copy_status_cb, status,
1420 : 0 : rpc_bdev_lvol_shallow_copy_cb, ctx);
1421 : :
1422 [ - + ]: 1 : if (rc < 0) {
1423 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1424 [ # # ]: 0 : spdk_strerror(-rc));
1425 [ # # # # : 0 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1426 : 0 : free(ctx);
1427 : 0 : free(status);
1428 : 0 : } else {
1429 : 1 : w = spdk_jsonrpc_begin_result(request);
1430 : :
1431 : 1 : spdk_json_write_object_begin(w);
1432 [ # # # # ]: 1 : spdk_json_write_named_uint32(w, "operation_id", status->operation_id);
1433 : 1 : spdk_json_write_object_end(w);
1434 : :
1435 : 1 : spdk_jsonrpc_end_result(request, w);
1436 : : }
1437 : :
1438 : 1 : cleanup:
1439 : 1 : free_rpc_bdev_lvol_shallow_copy(&req);
1440 : 1 : }
1441 : :
1442 : 2111 : SPDK_RPC_REGISTER("bdev_lvol_start_shallow_copy", rpc_bdev_lvol_start_shallow_copy,
1443 : : SPDK_RPC_RUNTIME)
1444 : :
1445 : : struct rpc_bdev_lvol_shallow_copy_status {
1446 : : char *src_lvol_name;
1447 : : uint32_t operation_id;
1448 : : };
1449 : :
1450 : : static void
1451 : 1 : free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
1452 : : {
1453 [ # # # # ]: 1 : free(req->src_lvol_name);
1454 : 1 : }
1455 : :
1456 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
1457 : : {"operation_id", offsetof(struct rpc_bdev_lvol_shallow_copy_status, operation_id), spdk_json_decode_uint32},
1458 : : };
1459 : :
1460 : : static void
1461 : 1 : rpc_bdev_lvol_check_shallow_copy(struct spdk_jsonrpc_request *request,
1462 : : const struct spdk_json_val *params)
1463 : : {
1464 : 1 : struct rpc_bdev_lvol_shallow_copy_status req = {};
1465 : : struct rpc_shallow_copy_status *status;
1466 : : struct spdk_json_write_ctx *w;
1467 : : uint64_t copied_clusters, total_clusters;
1468 : : int result;
1469 : :
1470 [ - + - + : 1 : SPDK_INFOLOG(lvol_rpc, "Shallow copy check\n");
# # ]
1471 : :
1472 [ - + ]: 1 : if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
1473 : : SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
1474 : : &req)) {
1475 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1476 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1477 : : "spdk_json_decode_object failed");
1478 : 0 : goto cleanup;
1479 : : }
1480 : :
1481 [ + - # # : 1 : LIST_FOREACH(status, &g_shallow_copy_status_list, link) {
# # # # ]
1482 [ + - # # : 1 : if (status->operation_id == req.operation_id) {
# # # # ]
1483 : 1 : break;
1484 : : }
1485 : 0 : }
1486 : :
1487 [ - + ]: 1 : if (!status) {
1488 [ # # ]: 0 : SPDK_ERRLOG("operation id '%d' does not exist\n", req.operation_id);
1489 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1490 : 0 : goto cleanup;
1491 : : }
1492 : :
1493 [ # # # # ]: 1 : copied_clusters = status->copied_clusters;
1494 [ # # # # ]: 1 : total_clusters = status->total_clusters;
1495 [ # # # # ]: 1 : result = status->result;
1496 : :
1497 : 1 : w = spdk_jsonrpc_begin_result(request);
1498 : :
1499 : 1 : spdk_json_write_object_begin(w);
1500 : :
1501 : 1 : spdk_json_write_named_uint64(w, "copied_clusters", copied_clusters);
1502 : 1 : spdk_json_write_named_uint64(w, "total_clusters", total_clusters);
1503 [ - + - - ]: 1 : if (copied_clusters < total_clusters && result == 0) {
1504 : 0 : spdk_json_write_named_string(w, "state", "in progress");
1505 [ + - + - ]: 1 : } else if (copied_clusters == total_clusters && result == 0) {
1506 : 1 : spdk_json_write_named_string(w, "state", "complete");
1507 [ - + # # : 1 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1508 : 1 : free(status);
1509 : 0 : } else {
1510 : 0 : spdk_json_write_named_string(w, "state", "error");
1511 [ # # ]: 0 : spdk_json_write_named_string(w, "error", spdk_strerror(-result));
1512 [ # # # # : 0 : LIST_REMOVE(status, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1513 : 0 : free(status);
1514 : : }
1515 : :
1516 : 1 : spdk_json_write_object_end(w);
1517 : :
1518 : 1 : spdk_jsonrpc_end_result(request, w);
1519 : :
1520 : 1 : cleanup:
1521 : 1 : free_rpc_bdev_lvol_shallow_copy_status(&req);
1522 : 1 : }
1523 : :
1524 : 2111 : SPDK_RPC_REGISTER("bdev_lvol_check_shallow_copy", rpc_bdev_lvol_check_shallow_copy,
1525 : : SPDK_RPC_RUNTIME)
1526 : :
1527 : : struct rpc_bdev_lvol_set_parent {
1528 : : char *lvol_name;
1529 : : char *parent_name;
1530 : : };
1531 : :
1532 : : static void
1533 : 14 : free_rpc_bdev_lvol_set_parent(struct rpc_bdev_lvol_set_parent *req)
1534 : : {
1535 [ # # # # ]: 14 : free(req->lvol_name);
1536 [ # # # # ]: 14 : free(req->parent_name);
1537 : 14 : }
1538 : :
1539 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_set_parent_decoders[] = {
1540 : : {"lvol_name", offsetof(struct rpc_bdev_lvol_set_parent, lvol_name), spdk_json_decode_string},
1541 : : {"parent_name", offsetof(struct rpc_bdev_lvol_set_parent, parent_name), spdk_json_decode_string},
1542 : : };
1543 : :
1544 : : static void
1545 : 13 : rpc_bdev_lvol_set_parent_cb(void *cb_arg, int lvolerrno)
1546 : : {
1547 : 13 : struct spdk_jsonrpc_request *request = cb_arg;
1548 : :
1549 [ + + ]: 13 : if (lvolerrno != 0) {
1550 : 7 : goto invalid;
1551 : : }
1552 : :
1553 : 6 : spdk_jsonrpc_send_bool_response(request, true);
1554 : 6 : return;
1555 : :
1556 : 7 : invalid:
1557 : 7 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1558 [ # # ]: 0 : spdk_strerror(-lvolerrno));
1559 : 0 : }
1560 : :
1561 : : static void
1562 : 8 : rpc_bdev_lvol_set_parent(struct spdk_jsonrpc_request *request,
1563 : : const struct spdk_json_val *params)
1564 : : {
1565 : 8 : struct rpc_bdev_lvol_set_parent req = {};
1566 : : struct spdk_lvol *lvol, *snapshot;
1567 : : struct spdk_bdev *lvol_bdev, *snapshot_bdev;
1568 : :
1569 [ - + - + : 8 : SPDK_INFOLOG(lvol_rpc, "Set parent of lvol\n");
# # ]
1570 : :
1571 [ - + ]: 8 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1572 : : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1573 : : &req)) {
1574 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1575 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1576 : : "spdk_json_decode_object failed");
1577 : 0 : goto cleanup;
1578 : : }
1579 : :
1580 : 8 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1581 [ - + ]: 8 : if (lvol_bdev == NULL) {
1582 : 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1583 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1584 : 0 : goto cleanup;
1585 : : }
1586 : :
1587 : 8 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1588 [ - + ]: 8 : if (lvol == NULL) {
1589 : 0 : SPDK_ERRLOG("lvol does not exist\n");
1590 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1591 : 0 : goto cleanup;
1592 : : }
1593 : :
1594 [ # # ]: 8 : snapshot_bdev = spdk_bdev_get_by_name(req.parent_name);
1595 [ - + ]: 8 : if (snapshot_bdev == NULL) {
1596 [ # # ]: 0 : SPDK_ERRLOG("snapshot bdev '%s' does not exist\n", req.parent_name);
1597 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1598 : 0 : goto cleanup;
1599 : : }
1600 : :
1601 : 8 : snapshot = vbdev_lvol_get_from_bdev(snapshot_bdev);
1602 [ + + ]: 8 : if (snapshot == NULL) {
1603 : 1 : SPDK_ERRLOG("snapshot does not exist\n");
1604 : 1 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1605 : 1 : goto cleanup;
1606 : : }
1607 : :
1608 : 7 : spdk_lvol_set_parent(lvol, snapshot, rpc_bdev_lvol_set_parent_cb, request);
1609 : :
1610 : 8 : cleanup:
1611 : 8 : free_rpc_bdev_lvol_set_parent(&req);
1612 : 8 : }
1613 : :
1614 : 2111 : SPDK_RPC_REGISTER("bdev_lvol_set_parent", rpc_bdev_lvol_set_parent, SPDK_RPC_RUNTIME)
1615 : :
1616 : : static void
1617 : 6 : rpc_bdev_lvol_set_parent_bdev(struct spdk_jsonrpc_request *request,
1618 : : const struct spdk_json_val *params)
1619 : : {
1620 : 6 : struct rpc_bdev_lvol_set_parent req = {};
1621 : : struct spdk_lvol *lvol;
1622 : : struct spdk_bdev *lvol_bdev;
1623 : :
1624 [ - + - + : 6 : SPDK_INFOLOG(lvol_rpc, "Set external parent of lvol\n");
# # ]
1625 : :
1626 [ - + ]: 6 : if (spdk_json_decode_object(params, rpc_bdev_lvol_set_parent_decoders,
1627 : : SPDK_COUNTOF(rpc_bdev_lvol_set_parent_decoders),
1628 : : &req)) {
1629 [ # # # # : 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
# # ]
1630 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1631 : : "spdk_json_decode_object failed");
1632 : 0 : goto cleanup;
1633 : : }
1634 : :
1635 : 6 : lvol_bdev = spdk_bdev_get_by_name(req.lvol_name);
1636 [ - + ]: 6 : if (lvol_bdev == NULL) {
1637 : 0 : SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.lvol_name);
1638 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1639 : 0 : goto cleanup;
1640 : : }
1641 : :
1642 : 6 : lvol = vbdev_lvol_get_from_bdev(lvol_bdev);
1643 [ - + ]: 6 : if (lvol == NULL) {
1644 : 0 : SPDK_ERRLOG("lvol does not exist\n");
1645 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1646 : 0 : goto cleanup;
1647 : : }
1648 : :
1649 [ # # ]: 6 : vbdev_lvol_set_external_parent(lvol, req.parent_name, rpc_bdev_lvol_set_parent_cb, request);
1650 : :
1651 : 6 : cleanup:
1652 : 6 : free_rpc_bdev_lvol_set_parent(&req);
1653 : 6 : }
1654 : :
1655 : 2111 : SPDK_RPC_REGISTER("bdev_lvol_set_parent_bdev", rpc_bdev_lvol_set_parent_bdev,
1656 : : SPDK_RPC_RUNTIME)
|