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 : 2057 : SPDK_LOG_REGISTER_COMPONENT(lvol_rpc)
15 : :
16 : : struct rpc_bdev_lvol_create_lvstore {
17 : : char *lvs_name;
18 : : char *bdev_name;
19 : : uint32_t cluster_sz;
20 : : char *clear_method;
21 : : uint32_t num_md_pages_per_cluster_ratio;
22 : : };
23 : :
24 : : static int
25 : 675 : vbdev_get_lvol_store_by_uuid_xor_name(const char *uuid, const char *lvs_name,
26 : : struct spdk_lvol_store **lvs)
27 : : {
28 [ + + - + ]: 675 : if ((uuid == NULL && lvs_name == NULL)) {
29 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "lvs UUID nor lvs name specified\n");
30 : 0 : return -EINVAL;
31 [ + + - + ]: 675 : } else if ((uuid && lvs_name)) {
32 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "both lvs UUID '%s' and lvs name '%s' specified\n", uuid,
33 : : lvs_name);
34 : 0 : return -EINVAL;
35 [ + + ]: 675 : } else if (uuid) {
36 : 526 : *lvs = vbdev_get_lvol_store_by_uuid(uuid);
37 : :
38 [ + + ]: 526 : if (*lvs == NULL) {
39 [ - + - + ]: 43 : SPDK_INFOLOG(lvol_rpc, "blobstore with UUID '%s' not found\n", uuid);
40 : 43 : return -ENODEV;
41 : : }
42 [ + - ]: 149 : } else if (lvs_name) {
43 : :
44 : 149 : *lvs = vbdev_get_lvol_store_by_name(lvs_name);
45 : :
46 [ + + ]: 149 : if (*lvs == NULL) {
47 [ - + - + ]: 11 : SPDK_INFOLOG(lvol_rpc, "blobstore with name '%s' not found\n", lvs_name);
48 : 11 : return -ENODEV;
49 : : }
50 : : }
51 : 621 : return 0;
52 : : }
53 : :
54 : : static void
55 : 182 : free_rpc_bdev_lvol_create_lvstore(struct rpc_bdev_lvol_create_lvstore *req)
56 : : {
57 : 182 : free(req->bdev_name);
58 : 182 : free(req->lvs_name);
59 : 182 : free(req->clear_method);
60 : 182 : }
61 : :
62 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_lvstore_decoders[] = {
63 : : {"bdev_name", offsetof(struct rpc_bdev_lvol_create_lvstore, bdev_name), spdk_json_decode_string},
64 : : {"cluster_sz", offsetof(struct rpc_bdev_lvol_create_lvstore, cluster_sz), spdk_json_decode_uint32, true},
65 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_create_lvstore, lvs_name), spdk_json_decode_string},
66 : : {"clear_method", offsetof(struct rpc_bdev_lvol_create_lvstore, clear_method), spdk_json_decode_string, true},
67 : : {"num_md_pages_per_cluster_ratio", offsetof(struct rpc_bdev_lvol_create_lvstore, num_md_pages_per_cluster_ratio), spdk_json_decode_uint32, true},
68 : : };
69 : :
70 : : static void
71 : 176 : rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
72 : : {
73 : : struct spdk_json_write_ctx *w;
74 : 176 : struct spdk_jsonrpc_request *request = cb_arg;
75 : :
76 [ + + ]: 176 : if (lvserrno != 0) {
77 : 1 : goto invalid;
78 : : }
79 : :
80 : 175 : w = spdk_jsonrpc_begin_result(request);
81 : 175 : spdk_json_write_uuid(w, &lvol_store->uuid);
82 : 175 : spdk_jsonrpc_end_result(request, w);
83 : 175 : return;
84 : :
85 : 1 : invalid:
86 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
87 : : spdk_strerror(-lvserrno));
88 : : }
89 : :
90 : : static void
91 : 182 : rpc_bdev_lvol_create_lvstore(struct spdk_jsonrpc_request *request,
92 : : const struct spdk_json_val *params)
93 : : {
94 : 182 : struct rpc_bdev_lvol_create_lvstore req = {};
95 : 182 : int rc = 0;
96 : : enum lvs_clear_method clear_method;
97 : :
98 [ + + ]: 182 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_lvstore_decoders,
99 : : SPDK_COUNTOF(rpc_bdev_lvol_create_lvstore_decoders),
100 : : &req)) {
101 [ - + - + ]: 1 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
102 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
103 : : "spdk_json_decode_object failed");
104 : 1 : goto cleanup;
105 : : }
106 : :
107 [ + + ]: 181 : if (req.clear_method != NULL) {
108 [ - + + + ]: 22 : if (!strcasecmp(req.clear_method, "none")) {
109 : 18 : clear_method = LVS_CLEAR_WITH_NONE;
110 [ - + + + ]: 4 : } else if (!strcasecmp(req.clear_method, "unmap")) {
111 : 2 : clear_method = LVS_CLEAR_WITH_UNMAP;
112 [ - + + + ]: 2 : } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
113 : 1 : clear_method = LVS_CLEAR_WITH_WRITE_ZEROES;
114 : : } else {
115 : 1 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clear_method parameter");
116 : 1 : goto cleanup;
117 : : }
118 : : } else {
119 : 159 : clear_method = LVS_CLEAR_WITH_UNMAP;
120 : : }
121 : :
122 : 180 : rc = vbdev_lvs_create(req.bdev_name, req.lvs_name, req.cluster_sz, clear_method,
123 : : req.num_md_pages_per_cluster_ratio, rpc_lvol_store_construct_cb, request);
124 [ + + ]: 180 : if (rc < 0) {
125 : 4 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
126 : 4 : goto cleanup;
127 : : }
128 : 176 : free_rpc_bdev_lvol_create_lvstore(&req);
129 : :
130 : 176 : return;
131 : :
132 : 6 : cleanup:
133 : 6 : free_rpc_bdev_lvol_create_lvstore(&req);
134 : : }
135 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_create_lvstore", rpc_bdev_lvol_create_lvstore, SPDK_RPC_RUNTIME)
136 : :
137 : : struct rpc_bdev_lvol_rename_lvstore {
138 : : char *old_name;
139 : : char *new_name;
140 : : };
141 : :
142 : : static void
143 : 3 : free_rpc_bdev_lvol_rename_lvstore(struct rpc_bdev_lvol_rename_lvstore *req)
144 : : {
145 : 3 : free(req->old_name);
146 : 3 : free(req->new_name);
147 : 3 : }
148 : :
149 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_lvstore_decoders[] = {
150 : : {"old_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, old_name), spdk_json_decode_string},
151 : : {"new_name", offsetof(struct rpc_bdev_lvol_rename_lvstore, new_name), spdk_json_decode_string},
152 : : };
153 : :
154 : : static void
155 : 2 : rpc_bdev_lvol_rename_lvstore_cb(void *cb_arg, int lvserrno)
156 : : {
157 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
158 : :
159 [ + + ]: 2 : if (lvserrno != 0) {
160 : 1 : goto invalid;
161 : : }
162 : :
163 : 1 : spdk_jsonrpc_send_bool_response(request, true);
164 : 1 : return;
165 : :
166 : 1 : invalid:
167 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
168 : : spdk_strerror(-lvserrno));
169 : : }
170 : :
171 : : static void
172 : 3 : rpc_bdev_lvol_rename_lvstore(struct spdk_jsonrpc_request *request,
173 : : const struct spdk_json_val *params)
174 : : {
175 : 3 : struct rpc_bdev_lvol_rename_lvstore req = {};
176 : : struct spdk_lvol_store *lvs;
177 : :
178 [ - + ]: 3 : if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_lvstore_decoders,
179 : : SPDK_COUNTOF(rpc_bdev_lvol_rename_lvstore_decoders),
180 : : &req)) {
181 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
182 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
183 : : "spdk_json_decode_object failed");
184 : 0 : goto cleanup;
185 : : }
186 : :
187 : 3 : lvs = vbdev_get_lvol_store_by_name(req.old_name);
188 [ + + ]: 3 : if (lvs == NULL) {
189 [ - + - + ]: 1 : SPDK_INFOLOG(lvol_rpc, "no lvs existing for given name\n");
190 : 1 : spdk_jsonrpc_send_error_response_fmt(request, -ENOENT, "Lvol store %s not found", req.old_name);
191 : 1 : goto cleanup;
192 : : }
193 : :
194 : 2 : vbdev_lvs_rename(lvs, req.new_name, rpc_bdev_lvol_rename_lvstore_cb, request);
195 : :
196 : 3 : cleanup:
197 : 3 : free_rpc_bdev_lvol_rename_lvstore(&req);
198 : 3 : }
199 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_rename_lvstore", rpc_bdev_lvol_rename_lvstore, SPDK_RPC_RUNTIME)
200 : :
201 : : struct rpc_bdev_lvol_delete_lvstore {
202 : : char *uuid;
203 : : char *lvs_name;
204 : : };
205 : :
206 : : static void
207 : 118 : free_rpc_bdev_lvol_delete_lvstore(struct rpc_bdev_lvol_delete_lvstore *req)
208 : : {
209 : 118 : free(req->uuid);
210 : 118 : free(req->lvs_name);
211 : 118 : }
212 : :
213 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_lvstore_decoders[] = {
214 : : {"uuid", offsetof(struct rpc_bdev_lvol_delete_lvstore, uuid), spdk_json_decode_string, true},
215 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_delete_lvstore, lvs_name), spdk_json_decode_string, true},
216 : : };
217 : :
218 : : static void
219 : 113 : rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
220 : : {
221 : 113 : struct spdk_jsonrpc_request *request = cb_arg;
222 : :
223 [ - + ]: 113 : if (lvserrno != 0) {
224 : 0 : goto invalid;
225 : : }
226 : :
227 : 113 : spdk_jsonrpc_send_bool_response(request, true);
228 : 113 : return;
229 : :
230 : 0 : invalid:
231 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
232 : : spdk_strerror(-lvserrno));
233 : : }
234 : :
235 : : static void
236 : 118 : rpc_bdev_lvol_delete_lvstore(struct spdk_jsonrpc_request *request,
237 : : const struct spdk_json_val *params)
238 : : {
239 : 118 : struct rpc_bdev_lvol_delete_lvstore req = {};
240 : 118 : struct spdk_lvol_store *lvs = NULL;
241 : : int rc;
242 : :
243 [ - + ]: 118 : if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_lvstore_decoders,
244 : : SPDK_COUNTOF(rpc_bdev_lvol_delete_lvstore_decoders),
245 : : &req)) {
246 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
247 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
248 : : "spdk_json_decode_object failed");
249 : 0 : goto cleanup;
250 : : }
251 : :
252 : 118 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
253 [ + + ]: 118 : if (rc != 0) {
254 : 5 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
255 : 5 : goto cleanup;
256 : : }
257 : :
258 : 113 : vbdev_lvs_destruct(lvs, rpc_lvol_store_destroy_cb, request);
259 : :
260 : 118 : cleanup:
261 : 118 : free_rpc_bdev_lvol_delete_lvstore(&req);
262 : 118 : }
263 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_delete_lvstore", rpc_bdev_lvol_delete_lvstore, SPDK_RPC_RUNTIME)
264 : :
265 : : struct rpc_bdev_lvol_create {
266 : : char *uuid;
267 : : char *lvs_name;
268 : : char *lvol_name;
269 : : uint64_t size;
270 : : uint64_t size_in_mib;
271 : : bool thin_provision;
272 : : char *clear_method;
273 : : };
274 : :
275 : : static void
276 : 454 : free_rpc_bdev_lvol_create(struct rpc_bdev_lvol_create *req)
277 : : {
278 : 454 : free(req->uuid);
279 : 454 : free(req->lvs_name);
280 : 454 : free(req->lvol_name);
281 : 454 : free(req->clear_method);
282 : 454 : }
283 : :
284 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_create_decoders[] = {
285 : : {"uuid", offsetof(struct rpc_bdev_lvol_create, uuid), spdk_json_decode_string, true},
286 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_create, lvs_name), spdk_json_decode_string, true},
287 : : {"lvol_name", offsetof(struct rpc_bdev_lvol_create, lvol_name), spdk_json_decode_string},
288 : : {"size", offsetof(struct rpc_bdev_lvol_create, size), spdk_json_decode_uint64, true},
289 : : {"size_in_mib", offsetof(struct rpc_bdev_lvol_create, size_in_mib), spdk_json_decode_uint64, true},
290 : : {"thin_provision", offsetof(struct rpc_bdev_lvol_create, thin_provision), spdk_json_decode_bool, true},
291 : : {"clear_method", offsetof(struct rpc_bdev_lvol_create, clear_method), spdk_json_decode_string, true},
292 : : };
293 : :
294 : : static void
295 : 452 : rpc_bdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
296 : : {
297 : : struct spdk_json_write_ctx *w;
298 : 452 : struct spdk_jsonrpc_request *request = cb_arg;
299 : :
300 [ + + ]: 452 : if (lvolerrno != 0) {
301 : 2 : goto invalid;
302 : : }
303 : :
304 : 450 : w = spdk_jsonrpc_begin_result(request);
305 : 450 : spdk_json_write_string(w, lvol->unique_id);
306 : 450 : spdk_jsonrpc_end_result(request, w);
307 : 450 : return;
308 : :
309 : 2 : invalid:
310 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
311 : : spdk_strerror(-lvolerrno));
312 : : }
313 : :
314 [ - + ]: 2057 : SPDK_LOG_DEPRECATION_REGISTER(vbdev_lvol_rpc_req_size,
315 : : "rpc_bdev_lvol_create/resize req.size",
316 : : "v23.09", 0);
317 : :
318 : : static void
319 : 454 : rpc_bdev_lvol_create(struct spdk_jsonrpc_request *request,
320 : : const struct spdk_json_val *params)
321 : : {
322 : 454 : struct rpc_bdev_lvol_create req = {};
323 : : enum lvol_clear_method clear_method;
324 : 454 : int rc = 0;
325 : 454 : struct spdk_lvol_store *lvs = NULL;
326 : 454 : uint64_t size = 0;
327 : :
328 [ - + - + ]: 454 : SPDK_INFOLOG(lvol_rpc, "Creating blob\n");
329 : :
330 [ - + ]: 454 : if (spdk_json_decode_object(params, rpc_bdev_lvol_create_decoders,
331 : : SPDK_COUNTOF(rpc_bdev_lvol_create_decoders),
332 : : &req)) {
333 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
334 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
335 : : "spdk_json_decode_object failed");
336 : 0 : goto cleanup;
337 : : }
338 : :
339 [ + + - + ]: 454 : if (req.size > 0 && req.size_in_mib > 0) {
340 : 0 : SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size);
341 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
342 : : "size is deprecated. Specify only size_in_mib instead.");
343 : 0 : goto cleanup;
344 [ + + ]: 454 : } else if (req.size_in_mib > 0) {
345 : 446 : size = req.size_in_mib * 1024 * 1024;
346 : : } else {
347 : 8 : SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size);
348 : 8 : size = req.size;
349 : : }
350 : :
351 : 454 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
352 [ + + ]: 454 : if (rc != 0) {
353 : 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
354 : 1 : goto cleanup;
355 : : }
356 : :
357 [ + + ]: 453 : if (req.clear_method != NULL) {
358 [ - + + + ]: 3 : if (!strcasecmp(req.clear_method, "none")) {
359 : 1 : clear_method = LVOL_CLEAR_WITH_NONE;
360 [ - + + - ]: 2 : } else if (!strcasecmp(req.clear_method, "unmap")) {
361 : 2 : clear_method = LVOL_CLEAR_WITH_UNMAP;
362 [ # # # # ]: 0 : } else if (!strcasecmp(req.clear_method, "write_zeroes")) {
363 : 0 : clear_method = LVOL_CLEAR_WITH_WRITE_ZEROES;
364 : : } else {
365 : 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid clean_method option");
366 : 0 : goto cleanup;
367 : : }
368 : : } else {
369 : 450 : clear_method = LVOL_CLEAR_WITH_DEFAULT;
370 : : }
371 : :
372 [ - + ]: 453 : rc = vbdev_lvol_create(lvs, req.lvol_name, size, req.thin_provision,
373 : : clear_method, rpc_bdev_lvol_create_cb, request);
374 [ + + ]: 453 : if (rc < 0) {
375 : 1 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
376 : 1 : goto cleanup;
377 : : }
378 : :
379 : 454 : cleanup:
380 : 454 : free_rpc_bdev_lvol_create(&req);
381 : 454 : }
382 : :
383 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_create", rpc_bdev_lvol_create, SPDK_RPC_RUNTIME)
384 : :
385 : : struct rpc_bdev_lvol_snapshot {
386 : : char *lvol_name;
387 : : char *snapshot_name;
388 : : };
389 : :
390 : : static void
391 : 30 : free_rpc_bdev_lvol_snapshot(struct rpc_bdev_lvol_snapshot *req)
392 : : {
393 : 30 : free(req->lvol_name);
394 : 30 : free(req->snapshot_name);
395 : 30 : }
396 : :
397 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_snapshot_decoders[] = {
398 : : {"lvol_name", offsetof(struct rpc_bdev_lvol_snapshot, lvol_name), spdk_json_decode_string},
399 : : {"snapshot_name", offsetof(struct rpc_bdev_lvol_snapshot, snapshot_name), spdk_json_decode_string},
400 : : };
401 : :
402 : : static void
403 : 30 : rpc_bdev_lvol_snapshot_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
404 : : {
405 : : struct spdk_json_write_ctx *w;
406 : 30 : struct spdk_jsonrpc_request *request = cb_arg;
407 : :
408 [ + + ]: 30 : if (lvolerrno != 0) {
409 : 1 : goto invalid;
410 : : }
411 : :
412 : 29 : w = spdk_jsonrpc_begin_result(request);
413 : 29 : spdk_json_write_string(w, lvol->unique_id);
414 : 29 : spdk_jsonrpc_end_result(request, w);
415 : 29 : return;
416 : :
417 : 1 : invalid:
418 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
419 : : spdk_strerror(-lvolerrno));
420 : : }
421 : :
422 : : static void
423 : 30 : rpc_bdev_lvol_snapshot(struct spdk_jsonrpc_request *request,
424 : : const struct spdk_json_val *params)
425 : : {
426 : 30 : struct rpc_bdev_lvol_snapshot req = {};
427 : : struct spdk_bdev *bdev;
428 : : struct spdk_lvol *lvol;
429 : :
430 [ - + - + ]: 30 : SPDK_INFOLOG(lvol_rpc, "Snapshotting blob\n");
431 : :
432 [ - + ]: 30 : if (spdk_json_decode_object(params, rpc_bdev_lvol_snapshot_decoders,
433 : : SPDK_COUNTOF(rpc_bdev_lvol_snapshot_decoders),
434 : : &req)) {
435 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
436 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
437 : : "spdk_json_decode_object failed");
438 : 0 : goto cleanup;
439 : : }
440 : :
441 : 30 : bdev = spdk_bdev_get_by_name(req.lvol_name);
442 [ - + ]: 30 : if (bdev == NULL) {
443 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.lvol_name);
444 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
445 : 0 : goto cleanup;
446 : : }
447 : :
448 : 30 : lvol = vbdev_lvol_get_from_bdev(bdev);
449 [ - + ]: 30 : if (lvol == NULL) {
450 : 0 : SPDK_ERRLOG("lvol does not exist\n");
451 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
452 : 0 : goto cleanup;
453 : : }
454 : :
455 : 30 : vbdev_lvol_create_snapshot(lvol, req.snapshot_name, rpc_bdev_lvol_snapshot_cb, request);
456 : :
457 : 30 : cleanup:
458 : 30 : free_rpc_bdev_lvol_snapshot(&req);
459 : 30 : }
460 : :
461 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_snapshot", rpc_bdev_lvol_snapshot, SPDK_RPC_RUNTIME)
462 : :
463 : : struct rpc_bdev_lvol_clone {
464 : : char *snapshot_name;
465 : : char *clone_name;
466 : : };
467 : :
468 : : static void
469 : 22 : free_rpc_bdev_lvol_clone(struct rpc_bdev_lvol_clone *req)
470 : : {
471 : 22 : free(req->snapshot_name);
472 : 22 : free(req->clone_name);
473 : 22 : }
474 : :
475 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_decoders[] = {
476 : : {"snapshot_name", offsetof(struct rpc_bdev_lvol_clone, snapshot_name), spdk_json_decode_string},
477 : : {"clone_name", offsetof(struct rpc_bdev_lvol_clone, clone_name), spdk_json_decode_string, true},
478 : : };
479 : :
480 : : static void
481 : 27 : rpc_bdev_lvol_clone_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
482 : : {
483 : : struct spdk_json_write_ctx *w;
484 : 27 : struct spdk_jsonrpc_request *request = cb_arg;
485 : :
486 [ + + ]: 27 : if (lvolerrno != 0) {
487 : 2 : goto invalid;
488 : : }
489 : :
490 : 25 : w = spdk_jsonrpc_begin_result(request);
491 : 25 : spdk_json_write_string(w, lvol->unique_id);
492 : 25 : spdk_jsonrpc_end_result(request, w);
493 : 25 : return;
494 : :
495 : 2 : invalid:
496 : 2 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
497 : : spdk_strerror(-lvolerrno));
498 : : }
499 : :
500 : : static void
501 : 22 : rpc_bdev_lvol_clone(struct spdk_jsonrpc_request *request,
502 : : const struct spdk_json_val *params)
503 : : {
504 : 22 : struct rpc_bdev_lvol_clone req = {};
505 : : struct spdk_bdev *bdev;
506 : : struct spdk_lvol *lvol;
507 : :
508 [ - + - + ]: 22 : SPDK_INFOLOG(lvol_rpc, "Cloning blob\n");
509 : :
510 [ - + ]: 22 : if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_decoders,
511 : : SPDK_COUNTOF(rpc_bdev_lvol_clone_decoders),
512 : : &req)) {
513 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
514 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
515 : : "spdk_json_decode_object failed");
516 : 0 : goto cleanup;
517 : : }
518 : :
519 : 22 : bdev = spdk_bdev_get_by_name(req.snapshot_name);
520 [ - + ]: 22 : if (bdev == NULL) {
521 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.snapshot_name);
522 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
523 : 0 : goto cleanup;
524 : : }
525 : :
526 : 22 : lvol = vbdev_lvol_get_from_bdev(bdev);
527 [ - + ]: 22 : if (lvol == NULL) {
528 : 0 : SPDK_ERRLOG("lvol does not exist\n");
529 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
530 : 0 : goto cleanup;
531 : : }
532 : :
533 : 22 : vbdev_lvol_create_clone(lvol, req.clone_name, rpc_bdev_lvol_clone_cb, request);
534 : :
535 : 22 : cleanup:
536 : 22 : free_rpc_bdev_lvol_clone(&req);
537 : 22 : }
538 : :
539 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_clone", rpc_bdev_lvol_clone, SPDK_RPC_RUNTIME)
540 : :
541 : : struct rpc_bdev_lvol_clone_bdev {
542 : : /* name or UUID. Whichever is used, the UUID will be stored in the lvol's metadata. */
543 : : char *bdev_name;
544 : : char *lvs_name;
545 : : char *clone_name;
546 : : };
547 : :
548 : : static void
549 : 5 : free_rpc_bdev_lvol_clone_bdev(struct rpc_bdev_lvol_clone_bdev *req)
550 : : {
551 : 5 : free(req->bdev_name);
552 : 5 : free(req->lvs_name);
553 : 5 : free(req->clone_name);
554 : 5 : }
555 : :
556 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_clone_bdev_decoders[] = {
557 : : {
558 : : "bdev", offsetof(struct rpc_bdev_lvol_clone_bdev, bdev_name),
559 : : spdk_json_decode_string, false
560 : : },
561 : : {
562 : : "lvs_name", offsetof(struct rpc_bdev_lvol_clone_bdev, lvs_name),
563 : : spdk_json_decode_string, false
564 : : },
565 : : {
566 : : "clone_name", offsetof(struct rpc_bdev_lvol_clone_bdev, clone_name),
567 : : spdk_json_decode_string, false
568 : : },
569 : : };
570 : :
571 : : static void
572 : 5 : rpc_bdev_lvol_clone_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
573 : : {
574 : 5 : struct rpc_bdev_lvol_clone_bdev req = {};
575 : : struct spdk_bdev *bdev;
576 : 5 : struct spdk_lvol_store *lvs = NULL;
577 : : struct spdk_lvol *lvol;
578 : : int rc;
579 : :
580 [ - + - + ]: 5 : SPDK_INFOLOG(lvol_rpc, "Cloning bdev\n");
581 : :
582 [ - + ]: 5 : if (spdk_json_decode_object(params, rpc_bdev_lvol_clone_bdev_decoders,
583 : : SPDK_COUNTOF(rpc_bdev_lvol_clone_bdev_decoders), &req)) {
584 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
585 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
586 : : "spdk_json_decode_object failed");
587 : 0 : goto cleanup;
588 : : }
589 : :
590 : 5 : rc = vbdev_get_lvol_store_by_uuid_xor_name(NULL, req.lvs_name, &lvs);
591 [ - + ]: 5 : if (rc != 0) {
592 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "lvs_name '%s' not found\n", req.lvs_name);
593 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
594 : : "lvs does not exist");
595 : 0 : goto cleanup;
596 : : }
597 : :
598 : 5 : bdev = spdk_bdev_get_by_name(req.bdev_name);
599 [ - + ]: 5 : if (bdev == NULL) {
600 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' does not exist\n", req.bdev_name);
601 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
602 : : "bdev does not exist");
603 : 0 : goto cleanup;
604 : : }
605 : :
606 : 5 : lvol = vbdev_lvol_get_from_bdev(bdev);
607 [ - + - - ]: 5 : if (lvol != NULL && lvol->lvol_store == lvs) {
608 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "bdev '%s' is an lvol in lvstore '%s\n", req.bdev_name,
609 : : req.lvs_name);
610 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
611 : : "bdev is an lvol in same lvs as clone; "
612 : : "use bdev_lvol_clone instead");
613 : 0 : goto cleanup;
614 : : }
615 : :
616 : 5 : vbdev_lvol_create_bdev_clone(req.bdev_name, lvs, req.clone_name,
617 : : rpc_bdev_lvol_clone_cb, request);
618 : 5 : cleanup:
619 : 5 : free_rpc_bdev_lvol_clone_bdev(&req);
620 : 5 : }
621 : :
622 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_clone_bdev", rpc_bdev_lvol_clone_bdev, SPDK_RPC_RUNTIME)
623 : :
624 : : struct rpc_bdev_lvol_rename {
625 : : char *old_name;
626 : : char *new_name;
627 : : };
628 : :
629 : : static void
630 : 6 : free_rpc_bdev_lvol_rename(struct rpc_bdev_lvol_rename *req)
631 : : {
632 : 6 : free(req->old_name);
633 : 6 : free(req->new_name);
634 : 6 : }
635 : :
636 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_rename_decoders[] = {
637 : : {"old_name", offsetof(struct rpc_bdev_lvol_rename, old_name), spdk_json_decode_string},
638 : : {"new_name", offsetof(struct rpc_bdev_lvol_rename, new_name), spdk_json_decode_string},
639 : : };
640 : :
641 : : static void
642 : 4 : rpc_bdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
643 : : {
644 : 4 : struct spdk_jsonrpc_request *request = cb_arg;
645 : :
646 [ - + ]: 4 : if (lvolerrno != 0) {
647 : 0 : goto invalid;
648 : : }
649 : :
650 : 4 : spdk_jsonrpc_send_bool_response(request, true);
651 : 4 : return;
652 : :
653 : 0 : invalid:
654 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
655 : : spdk_strerror(-lvolerrno));
656 : : }
657 : :
658 : : static void
659 : 6 : rpc_bdev_lvol_rename(struct spdk_jsonrpc_request *request,
660 : : const struct spdk_json_val *params)
661 : : {
662 : 6 : struct rpc_bdev_lvol_rename req = {};
663 : : struct spdk_bdev *bdev;
664 : : struct spdk_lvol *lvol;
665 : :
666 [ - + - + ]: 6 : SPDK_INFOLOG(lvol_rpc, "Renaming lvol\n");
667 : :
668 [ - + ]: 6 : if (spdk_json_decode_object(params, rpc_bdev_lvol_rename_decoders,
669 : : SPDK_COUNTOF(rpc_bdev_lvol_rename_decoders),
670 : : &req)) {
671 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
672 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
673 : : "spdk_json_decode_object failed");
674 : 0 : goto cleanup;
675 : : }
676 : :
677 : 6 : bdev = spdk_bdev_get_by_name(req.old_name);
678 [ + + ]: 6 : if (bdev == NULL) {
679 : 2 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name);
680 : 2 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
681 : 2 : goto cleanup;
682 : : }
683 : :
684 : 4 : lvol = vbdev_lvol_get_from_bdev(bdev);
685 [ - + ]: 4 : if (lvol == NULL) {
686 : 0 : SPDK_ERRLOG("lvol does not exist\n");
687 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
688 : 0 : goto cleanup;
689 : : }
690 : :
691 : 4 : vbdev_lvol_rename(lvol, req.new_name, rpc_bdev_lvol_rename_cb, request);
692 : :
693 : 6 : cleanup:
694 : 6 : free_rpc_bdev_lvol_rename(&req);
695 : 6 : }
696 : :
697 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
698 : :
699 : : struct rpc_bdev_lvol_inflate {
700 : : char *name;
701 : : };
702 : :
703 : : static void
704 : 8 : free_rpc_bdev_lvol_inflate(struct rpc_bdev_lvol_inflate *req)
705 : : {
706 : 8 : free(req->name);
707 : 8 : }
708 : :
709 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_inflate_decoders[] = {
710 : : {"name", offsetof(struct rpc_bdev_lvol_inflate, name), spdk_json_decode_string},
711 : : };
712 : :
713 : : static void
714 : 8 : rpc_bdev_lvol_inflate_cb(void *cb_arg, int lvolerrno)
715 : : {
716 : 8 : struct spdk_jsonrpc_request *request = cb_arg;
717 : :
718 [ + + ]: 8 : if (lvolerrno != 0) {
719 : 1 : goto invalid;
720 : : }
721 : :
722 : 7 : spdk_jsonrpc_send_bool_response(request, true);
723 : 7 : return;
724 : :
725 : 1 : invalid:
726 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
727 : : spdk_strerror(-lvolerrno));
728 : : }
729 : :
730 : : static void
731 : 5 : rpc_bdev_lvol_inflate(struct spdk_jsonrpc_request *request,
732 : : const struct spdk_json_val *params)
733 : : {
734 : 5 : struct rpc_bdev_lvol_inflate req = {};
735 : : struct spdk_bdev *bdev;
736 : : struct spdk_lvol *lvol;
737 : :
738 [ - + - + ]: 5 : SPDK_INFOLOG(lvol_rpc, "Inflating lvol\n");
739 : :
740 [ - + ]: 5 : if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
741 : : SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
742 : : &req)) {
743 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
744 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
745 : : "spdk_json_decode_object failed");
746 : 0 : goto cleanup;
747 : : }
748 : :
749 : 5 : bdev = spdk_bdev_get_by_name(req.name);
750 [ - + ]: 5 : if (bdev == NULL) {
751 : 0 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
752 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
753 : 0 : goto cleanup;
754 : : }
755 : :
756 : 5 : lvol = vbdev_lvol_get_from_bdev(bdev);
757 [ - + ]: 5 : if (lvol == NULL) {
758 : 0 : SPDK_ERRLOG("lvol does not exist\n");
759 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
760 : 0 : goto cleanup;
761 : : }
762 : :
763 : 5 : spdk_lvol_inflate(lvol, rpc_bdev_lvol_inflate_cb, request);
764 : :
765 : 5 : cleanup:
766 : 5 : free_rpc_bdev_lvol_inflate(&req);
767 : 5 : }
768 : :
769 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_inflate", rpc_bdev_lvol_inflate, SPDK_RPC_RUNTIME)
770 : :
771 : : static void
772 : 3 : rpc_bdev_lvol_decouple_parent(struct spdk_jsonrpc_request *request,
773 : : const struct spdk_json_val *params)
774 : : {
775 : 3 : struct rpc_bdev_lvol_inflate req = {};
776 : : struct spdk_bdev *bdev;
777 : : struct spdk_lvol *lvol;
778 : :
779 [ - + - + ]: 3 : SPDK_INFOLOG(lvol_rpc, "Decoupling parent of lvol\n");
780 : :
781 [ - + ]: 3 : if (spdk_json_decode_object(params, rpc_bdev_lvol_inflate_decoders,
782 : : SPDK_COUNTOF(rpc_bdev_lvol_inflate_decoders),
783 : : &req)) {
784 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
785 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
786 : : "spdk_json_decode_object failed");
787 : 0 : goto cleanup;
788 : : }
789 : :
790 : 3 : bdev = spdk_bdev_get_by_name(req.name);
791 [ - + ]: 3 : if (bdev == NULL) {
792 : 0 : SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
793 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
794 : 0 : goto cleanup;
795 : : }
796 : :
797 : 3 : lvol = vbdev_lvol_get_from_bdev(bdev);
798 [ - + ]: 3 : if (lvol == NULL) {
799 : 0 : SPDK_ERRLOG("lvol does not exist\n");
800 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
801 : 0 : goto cleanup;
802 : : }
803 : :
804 : 3 : spdk_lvol_decouple_parent(lvol, rpc_bdev_lvol_inflate_cb, request);
805 : :
806 : 3 : cleanup:
807 : 3 : free_rpc_bdev_lvol_inflate(&req);
808 : 3 : }
809 : :
810 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_decouple_parent", rpc_bdev_lvol_decouple_parent, SPDK_RPC_RUNTIME)
811 : :
812 : : struct rpc_bdev_lvol_resize {
813 : : char *name;
814 : : uint64_t size;
815 : : uint64_t size_in_mib;
816 : : };
817 : :
818 : : static void
819 : 19 : free_rpc_bdev_lvol_resize(struct rpc_bdev_lvol_resize *req)
820 : : {
821 : 19 : free(req->name);
822 : 19 : }
823 : :
824 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_resize_decoders[] = {
825 : : {"name", offsetof(struct rpc_bdev_lvol_resize, name), spdk_json_decode_string},
826 : : {"size", offsetof(struct rpc_bdev_lvol_resize, size), spdk_json_decode_uint64, true},
827 : : {"size_in_mib", offsetof(struct rpc_bdev_lvol_resize, size_in_mib), spdk_json_decode_uint64, true},
828 : : };
829 : :
830 : : static void
831 : 18 : rpc_bdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
832 : : {
833 : 18 : struct spdk_jsonrpc_request *request = cb_arg;
834 : :
835 [ + + ]: 18 : if (lvolerrno != 0) {
836 : 1 : goto invalid;
837 : : }
838 : :
839 : 17 : spdk_jsonrpc_send_bool_response(request, true);
840 : 17 : return;
841 : :
842 : 1 : invalid:
843 : 1 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
844 : : spdk_strerror(-lvolerrno));
845 : : }
846 : :
847 : : static void
848 : 19 : rpc_bdev_lvol_resize(struct spdk_jsonrpc_request *request,
849 : : const struct spdk_json_val *params)
850 : : {
851 : 19 : struct rpc_bdev_lvol_resize req = {};
852 : : struct spdk_bdev *bdev;
853 : : struct spdk_lvol *lvol;
854 : 19 : uint64_t size = 0;
855 : :
856 [ - + - + ]: 19 : SPDK_INFOLOG(lvol_rpc, "Resizing lvol\n");
857 : :
858 [ - + ]: 19 : if (spdk_json_decode_object(params, rpc_bdev_lvol_resize_decoders,
859 : : SPDK_COUNTOF(rpc_bdev_lvol_resize_decoders),
860 : : &req)) {
861 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
862 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
863 : : "spdk_json_decode_object failed");
864 : 0 : goto cleanup;
865 : : }
866 : :
867 [ - + - - ]: 19 : if (req.size > 0 && req.size_in_mib > 0) {
868 : 0 : SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size);
869 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
870 : : "size is deprecated. Specify only size_in_mib instead.");
871 : 0 : goto cleanup;
872 [ + + ]: 19 : } else if (req.size_in_mib > 0) {
873 : 16 : size = req.size_in_mib * 1024 * 1024;
874 : : } else {
875 : 3 : SPDK_LOG_DEPRECATED(vbdev_lvol_rpc_req_size);
876 : 3 : size = req.size;
877 : : }
878 : :
879 : 19 : bdev = spdk_bdev_get_by_name(req.name);
880 [ + + ]: 19 : if (bdev == NULL) {
881 : 1 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
882 : 1 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
883 : 1 : goto cleanup;
884 : : }
885 : :
886 : 18 : lvol = vbdev_lvol_get_from_bdev(bdev);
887 [ - + ]: 18 : if (lvol == NULL) {
888 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
889 : 0 : goto cleanup;
890 : : }
891 : :
892 : :
893 : 18 : vbdev_lvol_resize(lvol, size, rpc_bdev_lvol_resize_cb, request);
894 : :
895 : 19 : cleanup:
896 : 19 : free_rpc_bdev_lvol_resize(&req);
897 : 19 : }
898 : :
899 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_resize", rpc_bdev_lvol_resize, SPDK_RPC_RUNTIME)
900 : :
901 : : struct rpc_set_ro_lvol_bdev {
902 : : char *name;
903 : : };
904 : :
905 : : static void
906 : 3 : free_rpc_set_ro_lvol_bdev(struct rpc_set_ro_lvol_bdev *req)
907 : : {
908 : 3 : free(req->name);
909 : 3 : }
910 : :
911 : : static const struct spdk_json_object_decoder rpc_set_ro_lvol_bdev_decoders[] = {
912 : : {"name", offsetof(struct rpc_set_ro_lvol_bdev, name), spdk_json_decode_string},
913 : : };
914 : :
915 : : static void
916 : 3 : rpc_set_ro_lvol_bdev_cb(void *cb_arg, int lvolerrno)
917 : : {
918 : 3 : struct spdk_jsonrpc_request *request = cb_arg;
919 : :
920 [ - + ]: 3 : if (lvolerrno != 0) {
921 : 0 : goto invalid;
922 : : }
923 : :
924 : 3 : spdk_jsonrpc_send_bool_response(request, true);
925 : 3 : return;
926 : :
927 : 0 : invalid:
928 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
929 : : spdk_strerror(-lvolerrno));
930 : : }
931 : :
932 : : static void
933 : 3 : rpc_bdev_lvol_set_read_only(struct spdk_jsonrpc_request *request,
934 : : const struct spdk_json_val *params)
935 : : {
936 : 3 : struct rpc_set_ro_lvol_bdev req = {};
937 : : struct spdk_bdev *bdev;
938 : : struct spdk_lvol *lvol;
939 : :
940 [ - + - + ]: 3 : SPDK_INFOLOG(lvol_rpc, "Setting lvol as read only\n");
941 : :
942 [ - + ]: 3 : if (spdk_json_decode_object(params, rpc_set_ro_lvol_bdev_decoders,
943 : : SPDK_COUNTOF(rpc_set_ro_lvol_bdev_decoders),
944 : : &req)) {
945 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
946 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
947 : : "spdk_json_decode_object failed");
948 : 0 : goto cleanup;
949 : : }
950 : :
951 [ - + ]: 3 : if (req.name == NULL) {
952 : 0 : SPDK_ERRLOG("missing name param\n");
953 : 0 : spdk_jsonrpc_send_error_response(request, -EINVAL, "Missing name parameter");
954 : 0 : goto cleanup;
955 : : }
956 : :
957 : 3 : bdev = spdk_bdev_get_by_name(req.name);
958 [ - + ]: 3 : if (bdev == NULL) {
959 : 0 : SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
960 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
961 : 0 : goto cleanup;
962 : : }
963 : :
964 : 3 : lvol = vbdev_lvol_get_from_bdev(bdev);
965 [ - + ]: 3 : if (lvol == NULL) {
966 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
967 : 0 : goto cleanup;
968 : : }
969 : :
970 : 3 : vbdev_lvol_set_read_only(lvol, rpc_set_ro_lvol_bdev_cb, request);
971 : :
972 : 3 : cleanup:
973 : 3 : free_rpc_set_ro_lvol_bdev(&req);
974 : 3 : }
975 : :
976 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_set_read_only", rpc_bdev_lvol_set_read_only, SPDK_RPC_RUNTIME)
977 : :
978 : : struct rpc_bdev_lvol_delete {
979 : : char *name;
980 : : };
981 : :
982 : : static void
983 : 206 : free_rpc_bdev_lvol_delete(struct rpc_bdev_lvol_delete *req)
984 : : {
985 : 206 : free(req->name);
986 : 206 : }
987 : :
988 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_delete_decoders[] = {
989 : : {"name", offsetof(struct rpc_bdev_lvol_delete, name), spdk_json_decode_string},
990 : : };
991 : :
992 : : static void
993 : 206 : rpc_bdev_lvol_delete_cb(void *cb_arg, int lvolerrno)
994 : : {
995 : 206 : struct spdk_jsonrpc_request *request = cb_arg;
996 : :
997 [ + + ]: 206 : if (lvolerrno != 0) {
998 : 3 : goto invalid;
999 : : }
1000 : :
1001 : 203 : spdk_jsonrpc_send_bool_response(request, true);
1002 : 203 : return;
1003 : :
1004 : 3 : invalid:
1005 : 3 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1006 : : spdk_strerror(-lvolerrno));
1007 : : }
1008 : :
1009 : : static void
1010 : 206 : rpc_bdev_lvol_delete(struct spdk_jsonrpc_request *request,
1011 : : const struct spdk_json_val *params)
1012 : : {
1013 : 206 : struct rpc_bdev_lvol_delete req = {};
1014 : : struct spdk_bdev *bdev;
1015 : : struct spdk_lvol *lvol;
1016 : 117 : struct spdk_uuid uuid;
1017 : : char *lvs_name, *lvol_name;
1018 : :
1019 [ - + ]: 206 : if (spdk_json_decode_object(params, rpc_bdev_lvol_delete_decoders,
1020 : : SPDK_COUNTOF(rpc_bdev_lvol_delete_decoders),
1021 : : &req)) {
1022 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1023 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1024 : : "spdk_json_decode_object failed");
1025 : 0 : goto cleanup;
1026 : : }
1027 : :
1028 : : /* lvol is not degraded, get lvol via bdev name or alias */
1029 : 206 : bdev = spdk_bdev_get_by_name(req.name);
1030 [ + + ]: 206 : if (bdev != NULL) {
1031 : 204 : lvol = vbdev_lvol_get_from_bdev(bdev);
1032 [ + - ]: 204 : if (lvol != NULL) {
1033 : 204 : goto done;
1034 : : }
1035 : : }
1036 : :
1037 : : /* lvol is degraded, get lvol via UUID */
1038 [ + - ]: 2 : if (spdk_uuid_parse(&uuid, req.name) == 0) {
1039 : 2 : lvol = spdk_lvol_get_by_uuid(&uuid);
1040 [ + - ]: 2 : if (lvol != NULL) {
1041 : 2 : goto done;
1042 : : }
1043 : : }
1044 : :
1045 : : /* lvol is degraded, get lvol via lvs_name/lvol_name */
1046 [ # # ]: 0 : lvol_name = strchr(req.name, '/');
1047 [ # # ]: 0 : if (lvol_name != NULL) {
1048 : 0 : *lvol_name = '\0';
1049 : 0 : lvol_name++;
1050 : 0 : lvs_name = req.name;
1051 : 0 : lvol = spdk_lvol_get_by_names(lvs_name, lvol_name);
1052 [ # # ]: 0 : if (lvol != NULL) {
1053 : 0 : goto done;
1054 : : }
1055 : : }
1056 : :
1057 : : /* Could not find lvol, degraded or not. */
1058 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1059 : 0 : goto cleanup;
1060 : :
1061 : 206 : done:
1062 : 206 : vbdev_lvol_destroy(lvol, rpc_bdev_lvol_delete_cb, request);
1063 : :
1064 : 206 : cleanup:
1065 : 206 : free_rpc_bdev_lvol_delete(&req);
1066 : 206 : }
1067 : :
1068 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_delete", rpc_bdev_lvol_delete, SPDK_RPC_RUNTIME)
1069 : :
1070 : : struct rpc_bdev_lvol_get_lvstores {
1071 : : char *uuid;
1072 : : char *lvs_name;
1073 : : };
1074 : :
1075 : : static void
1076 : 526 : free_rpc_bdev_lvol_get_lvstores(struct rpc_bdev_lvol_get_lvstores *req)
1077 : : {
1078 : 526 : free(req->uuid);
1079 : 526 : free(req->lvs_name);
1080 : 526 : }
1081 : :
1082 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvstores_decoders[] = {
1083 : : {"uuid", offsetof(struct rpc_bdev_lvol_get_lvstores, uuid), spdk_json_decode_string, true},
1084 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvstores, lvs_name), spdk_json_decode_string, true},
1085 : : };
1086 : :
1087 : : static void
1088 : 203 : rpc_dump_lvol_store_info(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1089 : : {
1090 : : struct spdk_blob_store *bs;
1091 : : uint64_t cluster_size;
1092 : :
1093 : 203 : bs = lvs_bdev->lvs->blobstore;
1094 : 203 : cluster_size = spdk_bs_get_cluster_size(bs);
1095 : :
1096 : 203 : spdk_json_write_object_begin(w);
1097 : :
1098 : 203 : spdk_json_write_named_uuid(w, "uuid", &lvs_bdev->lvs->uuid);
1099 : 203 : spdk_json_write_named_string(w, "name", lvs_bdev->lvs->name);
1100 : 203 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(lvs_bdev->bdev));
1101 : 203 : spdk_json_write_named_uint64(w, "total_data_clusters", spdk_bs_total_data_cluster_count(bs));
1102 : 203 : spdk_json_write_named_uint64(w, "free_clusters", spdk_bs_free_cluster_count(bs));
1103 : 203 : spdk_json_write_named_uint64(w, "block_size", spdk_bs_get_io_unit_size(bs));
1104 : 203 : spdk_json_write_named_uint64(w, "cluster_size", cluster_size);
1105 : :
1106 : 203 : spdk_json_write_object_end(w);
1107 : 203 : }
1108 : :
1109 : : static void
1110 : 526 : rpc_bdev_lvol_get_lvstores(struct spdk_jsonrpc_request *request,
1111 : : const struct spdk_json_val *params)
1112 : : {
1113 : 526 : struct rpc_bdev_lvol_get_lvstores req = {};
1114 : : struct spdk_json_write_ctx *w;
1115 : 526 : struct lvol_store_bdev *lvs_bdev = NULL;
1116 : 526 : struct spdk_lvol_store *lvs = NULL;
1117 : : int rc;
1118 : :
1119 [ + + ]: 526 : if (params != NULL) {
1120 [ - + ]: 96 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvstores_decoders,
1121 : : SPDK_COUNTOF(rpc_bdev_lvol_get_lvstores_decoders),
1122 : : &req)) {
1123 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1124 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1125 : : "spdk_json_decode_object failed");
1126 : 0 : goto cleanup;
1127 : : }
1128 : :
1129 : 96 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1130 [ + + ]: 96 : if (rc != 0) {
1131 : 48 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1132 : 48 : goto cleanup;
1133 : : }
1134 : :
1135 : 48 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1136 [ - + ]: 48 : if (lvs_bdev == NULL) {
1137 : 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1138 : 0 : goto cleanup;
1139 : : }
1140 : : }
1141 : :
1142 : 478 : w = spdk_jsonrpc_begin_result(request);
1143 : 478 : spdk_json_write_array_begin(w);
1144 : :
1145 [ + + ]: 478 : if (lvs_bdev != NULL) {
1146 : 48 : rpc_dump_lvol_store_info(w, lvs_bdev);
1147 : : } else {
1148 [ + + ]: 585 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1149 : 155 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1150 : 155 : rpc_dump_lvol_store_info(w, lvs_bdev);
1151 : : }
1152 : : }
1153 : 478 : spdk_json_write_array_end(w);
1154 : :
1155 : 478 : spdk_jsonrpc_end_result(request, w);
1156 : :
1157 : 526 : cleanup:
1158 : 526 : free_rpc_bdev_lvol_get_lvstores(&req);
1159 : 526 : }
1160 : :
1161 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_get_lvstores", rpc_bdev_lvol_get_lvstores, SPDK_RPC_RUNTIME)
1162 : 2057 : SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_lvol_get_lvstores, get_lvol_stores)
1163 : :
1164 : : struct rpc_bdev_lvol_get_lvols {
1165 : : char *lvs_uuid;
1166 : : char *lvs_name;
1167 : : };
1168 : :
1169 : : static void
1170 : 13 : free_rpc_bdev_lvol_get_lvols(struct rpc_bdev_lvol_get_lvols *req)
1171 : : {
1172 : 13 : free(req->lvs_uuid);
1173 : 13 : free(req->lvs_name);
1174 : 13 : }
1175 : :
1176 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_get_lvols_decoders[] = {
1177 : : {"lvs_uuid", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_uuid), spdk_json_decode_string, true},
1178 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_get_lvols, lvs_name), spdk_json_decode_string, true},
1179 : : };
1180 : :
1181 : : static void
1182 : 18 : rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
1183 : : {
1184 : 18 : struct spdk_lvol_store *lvs = lvol->lvol_store;
1185 : :
1186 : 18 : spdk_json_write_object_begin(w);
1187 : :
1188 : 18 : spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
1189 : 18 : spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
1190 : 18 : spdk_json_write_named_string(w, "name", lvol->name);
1191 : 18 : spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
1192 : 18 : spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
1193 : 18 : spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
1194 : 18 : spdk_json_write_named_bool(w, "is_esnap_clone", spdk_blob_is_esnap_clone(lvol->blob));
1195 : 18 : spdk_json_write_named_bool(w, "is_degraded", spdk_blob_is_degraded(lvol->blob));
1196 : :
1197 : 18 : spdk_json_write_named_object_begin(w, "lvs");
1198 : 18 : spdk_json_write_named_string(w, "name", lvs->name);
1199 : 18 : spdk_json_write_named_uuid(w, "uuid", &lvs->uuid);
1200 : 18 : spdk_json_write_object_end(w);
1201 : :
1202 : 18 : spdk_json_write_object_end(w);
1203 : 18 : }
1204 : :
1205 : : static void
1206 : 13 : rpc_dump_lvols(struct spdk_json_write_ctx *w, struct lvol_store_bdev *lvs_bdev)
1207 : : {
1208 : 13 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
1209 : : struct spdk_lvol *lvol;
1210 : :
1211 [ + + ]: 31 : TAILQ_FOREACH(lvol, &lvs->lvols, link) {
1212 : 18 : rpc_dump_lvol(w, lvol);
1213 : : }
1214 : 13 : }
1215 : :
1216 : : static void
1217 : 13 : rpc_bdev_lvol_get_lvols(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
1218 : : {
1219 : 13 : struct rpc_bdev_lvol_get_lvols req = {};
1220 : : struct spdk_json_write_ctx *w;
1221 : 13 : struct lvol_store_bdev *lvs_bdev = NULL;
1222 : 13 : struct spdk_lvol_store *lvs = NULL;
1223 : : int rc;
1224 : :
1225 [ - + ]: 13 : if (params != NULL) {
1226 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_bdev_lvol_get_lvols_decoders,
1227 : : SPDK_COUNTOF(rpc_bdev_lvol_get_lvols_decoders),
1228 : : &req)) {
1229 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1230 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1231 : : "spdk_json_decode_object failed");
1232 : 0 : goto cleanup;
1233 : : }
1234 : :
1235 : 0 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.lvs_uuid, req.lvs_name, &lvs);
1236 [ # # ]: 0 : if (rc != 0) {
1237 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1238 : 0 : goto cleanup;
1239 : : }
1240 : :
1241 : 0 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
1242 [ # # ]: 0 : if (lvs_bdev == NULL) {
1243 : 0 : spdk_jsonrpc_send_error_response(request, ENODEV, spdk_strerror(-ENODEV));
1244 : 0 : goto cleanup;
1245 : : }
1246 : : }
1247 : :
1248 : 13 : w = spdk_jsonrpc_begin_result(request);
1249 : 13 : spdk_json_write_array_begin(w);
1250 : :
1251 [ - + ]: 13 : if (lvs_bdev != NULL) {
1252 : 0 : rpc_dump_lvols(w, lvs_bdev);
1253 : : } else {
1254 [ + + ]: 26 : for (lvs_bdev = vbdev_lvol_store_first(); lvs_bdev != NULL;
1255 : 13 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev)) {
1256 : 13 : rpc_dump_lvols(w, lvs_bdev);
1257 : : }
1258 : : }
1259 : 13 : spdk_json_write_array_end(w);
1260 : :
1261 : 13 : spdk_jsonrpc_end_result(request, w);
1262 : :
1263 : 13 : cleanup:
1264 : 13 : free_rpc_bdev_lvol_get_lvols(&req);
1265 : 13 : }
1266 : :
1267 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_get_lvols", rpc_bdev_lvol_get_lvols, SPDK_RPC_RUNTIME)
1268 : :
1269 : : struct rpc_bdev_lvol_grow_lvstore {
1270 : : char *uuid;
1271 : : char *lvs_name;
1272 : : };
1273 : :
1274 : : static void
1275 : 2 : free_rpc_bdev_lvol_grow_lvstore(struct rpc_bdev_lvol_grow_lvstore *req)
1276 : : {
1277 : 2 : free(req->uuid);
1278 : 2 : free(req->lvs_name);
1279 : 2 : }
1280 : :
1281 : : static const struct spdk_json_object_decoder rpc_bdev_lvol_grow_lvstore_decoders[] = {
1282 : : {"uuid", offsetof(struct rpc_bdev_lvol_grow_lvstore, uuid), spdk_json_decode_string, true},
1283 : : {"lvs_name", offsetof(struct rpc_bdev_lvol_grow_lvstore, lvs_name), spdk_json_decode_string, true},
1284 : : };
1285 : :
1286 : : static void
1287 : 2 : rpc_bdev_lvol_grow_lvstore_cb(void *cb_arg, int lvserrno)
1288 : : {
1289 : 2 : struct spdk_jsonrpc_request *request = cb_arg;
1290 : :
1291 [ - + ]: 2 : if (lvserrno != 0) {
1292 : 0 : goto invalid;
1293 : : }
1294 : :
1295 : 2 : spdk_jsonrpc_send_bool_response(request, true);
1296 : 2 : return;
1297 : :
1298 : 0 : invalid:
1299 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1300 : : spdk_strerror(-lvserrno));
1301 : : }
1302 : :
1303 : : static void
1304 : 2 : rpc_bdev_lvol_grow_lvstore(struct spdk_jsonrpc_request *request,
1305 : : const struct spdk_json_val *params)
1306 : : {
1307 : 2 : struct rpc_bdev_lvol_grow_lvstore req = {};
1308 : 2 : struct spdk_lvol_store *lvs = NULL;
1309 : : int rc;
1310 : :
1311 [ - + ]: 2 : if (spdk_json_decode_object(params, rpc_bdev_lvol_grow_lvstore_decoders,
1312 : : SPDK_COUNTOF(rpc_bdev_lvol_grow_lvstore_decoders),
1313 : : &req)) {
1314 [ # # # # ]: 0 : SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
1315 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1316 : : "spdk_json_decode_object failed");
1317 : 0 : goto cleanup;
1318 : : }
1319 : :
1320 : 2 : rc = vbdev_get_lvol_store_by_uuid_xor_name(req.uuid, req.lvs_name, &lvs);
1321 [ - + ]: 2 : if (rc != 0) {
1322 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1323 : 0 : goto cleanup;
1324 : : }
1325 : 2 : spdk_bdev_update_bs_blockcnt(lvs->bs_dev);
1326 : 2 : spdk_lvs_grow_live(lvs, rpc_bdev_lvol_grow_lvstore_cb, request);
1327 : :
1328 : 2 : cleanup:
1329 : 2 : free_rpc_bdev_lvol_grow_lvstore(&req);
1330 : 2 : }
1331 : 2057 : SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
|