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_module.h"
9 : : #include "spdk/log.h"
10 : : #include "spdk/string.h"
11 : : #include "spdk/uuid.h"
12 : : #include "spdk/blob.h"
13 : :
14 : : #include "vbdev_lvol.h"
15 : :
16 : : struct vbdev_lvol_io {
17 : : struct spdk_blob_ext_io_opts ext_io_opts;
18 : : };
19 : :
20 : : static TAILQ_HEAD(, lvol_store_bdev) g_spdk_lvol_pairs = TAILQ_HEAD_INITIALIZER(
21 : : g_spdk_lvol_pairs);
22 : :
23 : : static int vbdev_lvs_init(void);
24 : : static void vbdev_lvs_fini_start(void);
25 : : static int vbdev_lvs_get_ctx_size(void);
26 : : static void vbdev_lvs_examine_config(struct spdk_bdev *bdev);
27 : : static void vbdev_lvs_examine_disk(struct spdk_bdev *bdev);
28 : : static bool g_shutdown_started = false;
29 : :
30 : : struct spdk_bdev_module g_lvol_if = {
31 : : .name = "lvol",
32 : : .module_init = vbdev_lvs_init,
33 : : .fini_start = vbdev_lvs_fini_start,
34 : : .async_fini_start = true,
35 : : .examine_config = vbdev_lvs_examine_config,
36 : : .examine_disk = vbdev_lvs_examine_disk,
37 : : .get_ctx_size = vbdev_lvs_get_ctx_size,
38 : :
39 : : };
40 : :
41 : 2334 : SPDK_BDEV_MODULE_REGISTER(lvol, &g_lvol_if)
42 : :
43 : : static void _vbdev_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg);
44 : :
45 : : struct lvol_store_bdev *
46 : 2538 : vbdev_get_lvs_bdev_by_lvs(struct spdk_lvol_store *lvs_orig)
47 : : {
48 : 2538 : struct spdk_lvol_store *lvs = NULL;
49 : 2538 : struct lvol_store_bdev *lvs_bdev = vbdev_lvol_store_first();
50 : :
51 [ + - ]: 2612 : while (lvs_bdev != NULL) {
52 : 2612 : lvs = lvs_bdev->lvs;
53 [ + + ]: 2612 : if (lvs == lvs_orig) {
54 [ - + + + ]: 2538 : if (lvs_bdev->removal_in_progress) {
55 : : /* We do not allow access to lvs that are being unloaded or
56 : : * destroyed */
57 [ - + - + ]: 80 : SPDK_DEBUGLOG(vbdev_lvol, "lvs %s: removal in progress\n",
58 : : lvs_orig->name);
59 : 80 : return NULL;
60 : : } else {
61 : 2458 : return lvs_bdev;
62 : : }
63 : : }
64 : 74 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev);
65 : : }
66 : :
67 : 0 : return NULL;
68 : : }
69 : :
70 : : static int
71 : 24 : _vbdev_lvol_change_bdev_alias(struct spdk_lvol *lvol, const char *new_lvol_name)
72 : : {
73 : : struct spdk_bdev_alias *tmp;
74 : : char *old_alias;
75 : : char *alias;
76 : : int rc;
77 : 24 : int alias_number = 0;
78 : :
79 : : /* bdev representing lvols have only one alias,
80 : : * while we changed lvs name earlier, we have to iterate alias list to get one,
81 : : * and check if there is only one alias */
82 : :
83 [ + + ]: 48 : TAILQ_FOREACH(tmp, spdk_bdev_get_aliases(lvol->bdev), tailq) {
84 [ - + ]: 24 : if (++alias_number > 1) {
85 : 0 : SPDK_ERRLOG("There is more than 1 alias in bdev %s\n", lvol->bdev->name);
86 : 0 : return -EINVAL;
87 : : }
88 : :
89 : 24 : old_alias = tmp->alias.name;
90 : : }
91 : :
92 [ - + ]: 24 : if (alias_number == 0) {
93 : 0 : SPDK_ERRLOG("There are no aliases in bdev %s\n", lvol->bdev->name);
94 : 0 : return -EINVAL;
95 : : }
96 : :
97 : 24 : alias = spdk_sprintf_alloc("%s/%s", lvol->lvol_store->name, new_lvol_name);
98 [ - + ]: 24 : if (alias == NULL) {
99 : 0 : SPDK_ERRLOG("Cannot alloc memory for alias\n");
100 : 0 : return -ENOMEM;
101 : : }
102 : :
103 : 24 : rc = spdk_bdev_alias_add(lvol->bdev, alias);
104 [ + + ]: 24 : if (rc != 0) {
105 : 4 : SPDK_ERRLOG("cannot add alias '%s'\n", alias);
106 : 4 : free(alias);
107 : 4 : return rc;
108 : : }
109 : 20 : free(alias);
110 : :
111 : 20 : rc = spdk_bdev_alias_del(lvol->bdev, old_alias);
112 [ - + ]: 20 : if (rc != 0) {
113 : 0 : SPDK_ERRLOG("cannot remove alias '%s'\n", old_alias);
114 : 0 : return rc;
115 : : }
116 : :
117 : 20 : return 0;
118 : : }
119 : :
120 : : static struct lvol_store_bdev *
121 : 46 : vbdev_get_lvs_bdev_by_bdev(struct spdk_bdev *bdev_orig)
122 : : {
123 : 46 : struct lvol_store_bdev *lvs_bdev = vbdev_lvol_store_first();
124 : :
125 [ + + ]: 50 : while (lvs_bdev != NULL) {
126 [ + + ]: 46 : if (lvs_bdev->bdev == bdev_orig) {
127 [ - + - + ]: 42 : if (lvs_bdev->removal_in_progress) {
128 : : /* We do not allow access to lvs that are being unloaded or
129 : : * destroyed */
130 [ # # # # ]: 0 : SPDK_DEBUGLOG(vbdev_lvol, "lvs %s: removal in progress\n",
131 : : lvs_bdev->lvs->name);
132 : 0 : return NULL;
133 : : } else {
134 : 42 : return lvs_bdev;
135 : : }
136 : : }
137 : 4 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev);
138 : : }
139 : :
140 : 4 : return NULL;
141 : : }
142 : :
143 : : static void
144 : 46 : vbdev_lvs_hotremove_cb(struct spdk_bdev *bdev)
145 : : {
146 : : struct lvol_store_bdev *lvs_bdev;
147 : :
148 : 46 : lvs_bdev = vbdev_get_lvs_bdev_by_bdev(bdev);
149 [ + + ]: 46 : if (lvs_bdev != NULL) {
150 : 42 : SPDK_NOTICELOG("bdev %s being removed: closing lvstore %s\n",
151 : : spdk_bdev_get_name(bdev), lvs_bdev->lvs->name);
152 : 42 : vbdev_lvs_unload(lvs_bdev->lvs, NULL, NULL);
153 : : }
154 : 46 : }
155 : :
156 : : static void
157 : 38 : vbdev_lvs_base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
158 : : void *event_ctx)
159 : : {
160 [ + - ]: 38 : switch (type) {
161 : 38 : case SPDK_BDEV_EVENT_REMOVE:
162 : 38 : vbdev_lvs_hotremove_cb(bdev);
163 : 38 : break;
164 : 0 : default:
165 : 0 : SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
166 : 0 : break;
167 : : }
168 : 38 : }
169 : :
170 : : static void
171 : 211 : _vbdev_lvs_create_cb(void *cb_arg, struct spdk_lvol_store *lvs, int lvserrno)
172 : : {
173 : 211 : struct spdk_lvs_with_handle_req *req = cb_arg;
174 : : struct lvol_store_bdev *lvs_bdev;
175 : 211 : struct spdk_bdev *bdev = req->base_bdev;
176 : 211 : struct spdk_bs_dev *bs_dev = req->bs_dev;
177 : :
178 [ + + ]: 211 : if (lvserrno != 0) {
179 [ - + ]: 5 : assert(lvs == NULL);
180 : 5 : SPDK_ERRLOG("Cannot create lvol store bdev\n");
181 : 5 : goto end;
182 : : }
183 : :
184 : 206 : lvserrno = spdk_bs_bdev_claim(bs_dev, &g_lvol_if);
185 [ - + ]: 206 : if (lvserrno != 0) {
186 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol, "Lvol store base bdev already claimed by another bdev\n");
187 : 0 : req->bs_dev->destroy(req->bs_dev);
188 : 0 : goto end;
189 : : }
190 : :
191 [ - + ]: 206 : assert(lvs != NULL);
192 : :
193 : 206 : lvs_bdev = calloc(1, sizeof(*lvs_bdev));
194 [ - + ]: 206 : if (!lvs_bdev) {
195 : 0 : lvserrno = -ENOMEM;
196 : 0 : goto end;
197 : : }
198 : 206 : lvs_bdev->lvs = lvs;
199 : 206 : lvs_bdev->bdev = bdev;
200 : 206 : lvs_bdev->req = NULL;
201 : :
202 : 206 : TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
203 [ + + + - ]: 206 : SPDK_INFOLOG(vbdev_lvol, "Lvol store bdev inserted\n");
204 : :
205 : 206 : end:
206 : 211 : req->cb_fn(req->cb_arg, lvs, lvserrno);
207 : 211 : free(req);
208 : :
209 : 211 : return;
210 : : }
211 : :
212 : : int
213 : 223 : vbdev_lvs_create(const char *base_bdev_name, const char *name, uint32_t cluster_sz,
214 : : enum lvs_clear_method clear_method, uint32_t num_md_pages_per_cluster_ratio,
215 : : spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
216 : : {
217 : 187 : struct spdk_bs_dev *bs_dev;
218 : : struct spdk_lvs_with_handle_req *lvs_req;
219 : 187 : struct spdk_lvs_opts opts;
220 : : int rc;
221 : : int len;
222 : :
223 [ - + ]: 223 : if (base_bdev_name == NULL) {
224 : 0 : SPDK_ERRLOG("missing base_bdev_name param\n");
225 : 0 : return -EINVAL;
226 : : }
227 : :
228 : 223 : spdk_lvs_opts_init(&opts);
229 [ + + ]: 223 : if (cluster_sz != 0) {
230 : 28 : opts.cluster_sz = cluster_sz;
231 : : }
232 : :
233 [ + + ]: 223 : if (clear_method != 0) {
234 : 11 : opts.clear_method = clear_method;
235 : : }
236 : :
237 [ + + ]: 223 : if (num_md_pages_per_cluster_ratio != 0) {
238 : 1 : opts.num_md_pages_per_cluster_ratio = num_md_pages_per_cluster_ratio;
239 : : }
240 : :
241 [ - + ]: 223 : if (name == NULL) {
242 : 0 : SPDK_ERRLOG("missing name param\n");
243 : 0 : return -EINVAL;
244 : : }
245 : :
246 [ - + ]: 223 : len = strnlen(name, SPDK_LVS_NAME_MAX);
247 : :
248 [ + - - + ]: 223 : if (len == 0 || len == SPDK_LVS_NAME_MAX) {
249 : 0 : SPDK_ERRLOG("name must be between 1 and %d characters\n", SPDK_LVS_NAME_MAX - 1);
250 : 0 : return -EINVAL;
251 : : }
252 : 223 : snprintf(opts.name, sizeof(opts.name), "%s", name);
253 : 223 : opts.esnap_bs_dev_create = vbdev_lvol_esnap_dev_create;
254 : :
255 : 223 : lvs_req = calloc(1, sizeof(*lvs_req));
256 [ - + ]: 223 : if (!lvs_req) {
257 : 0 : SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
258 : 0 : return -ENOMEM;
259 : : }
260 : :
261 : 223 : rc = spdk_bdev_create_bs_dev_ext(base_bdev_name, vbdev_lvs_base_bdev_event_cb,
262 : : NULL, &bs_dev);
263 [ + + ]: 223 : if (rc < 0) {
264 : 6 : SPDK_ERRLOG("Cannot create blobstore device\n");
265 : 6 : free(lvs_req);
266 : 6 : return rc;
267 : : }
268 : :
269 : 217 : lvs_req->bs_dev = bs_dev;
270 : 217 : lvs_req->base_bdev = bs_dev->get_base_bdev(bs_dev);
271 : 217 : lvs_req->cb_fn = cb_fn;
272 : 217 : lvs_req->cb_arg = cb_arg;
273 : :
274 : 217 : rc = spdk_lvs_init(bs_dev, &opts, _vbdev_lvs_create_cb, lvs_req);
275 [ + + ]: 217 : if (rc < 0) {
276 : 6 : free(lvs_req);
277 : 6 : bs_dev->destroy(bs_dev);
278 : 6 : return rc;
279 : : }
280 : :
281 : 211 : return 0;
282 : : }
283 : :
284 : : static void
285 : 10 : _vbdev_lvs_rename_cb(void *cb_arg, int lvserrno)
286 : : {
287 : 10 : struct spdk_lvs_req *req = cb_arg;
288 : : struct spdk_lvol *tmp;
289 : :
290 [ + + ]: 10 : if (lvserrno != 0) {
291 [ - + - + ]: 5 : SPDK_INFOLOG(vbdev_lvol, "Lvol store rename failed\n");
292 : : } else {
293 [ + + ]: 13 : TAILQ_FOREACH(tmp, &req->lvol_store->lvols, link) {
294 : : /* We have to pass current lvol name, since only lvs name changed */
295 : 8 : _vbdev_lvol_change_bdev_alias(tmp, tmp->name);
296 : : }
297 : : }
298 : :
299 : 10 : req->cb_fn(req->cb_arg, lvserrno);
300 : 10 : free(req);
301 : 10 : }
302 : :
303 : : void
304 : 10 : vbdev_lvs_rename(struct spdk_lvol_store *lvs, const char *new_lvs_name,
305 : : spdk_lvs_op_complete cb_fn, void *cb_arg)
306 : : {
307 : : struct lvol_store_bdev *lvs_bdev;
308 : :
309 : : struct spdk_lvs_req *req;
310 : :
311 : 10 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
312 [ - + ]: 10 : if (!lvs_bdev) {
313 : 0 : SPDK_ERRLOG("No such lvol store found\n");
314 : 0 : cb_fn(cb_arg, -ENODEV);
315 : 0 : return;
316 : : }
317 : :
318 : 10 : req = calloc(1, sizeof(*req));
319 [ - + ]: 10 : if (!req) {
320 : 0 : SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
321 : 0 : cb_fn(cb_arg, -ENOMEM);
322 : 0 : return;
323 : : }
324 : 10 : req->cb_fn = cb_fn;
325 : 10 : req->cb_arg = cb_arg;
326 : 10 : req->lvol_store = lvs;
327 : :
328 : 10 : spdk_lvs_rename(lvs, new_lvs_name, _vbdev_lvs_rename_cb, req);
329 : : }
330 : :
331 : : static void
332 : 203 : _vbdev_lvs_remove_cb(void *cb_arg, int lvserrno)
333 : : {
334 : 203 : struct lvol_store_bdev *lvs_bdev = cb_arg;
335 : 203 : struct spdk_lvs_req *req = lvs_bdev->req;
336 : :
337 [ - + ]: 203 : if (lvserrno != 0) {
338 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol, "Lvol store removed with error: %d.\n", lvserrno);
339 : : }
340 : :
341 [ + + ]: 203 : TAILQ_REMOVE(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
342 : 203 : free(lvs_bdev);
343 : :
344 [ + + ]: 203 : if (req->cb_fn != NULL) {
345 : 161 : req->cb_fn(req->cb_arg, lvserrno);
346 : : }
347 : 203 : free(req);
348 : 203 : }
349 : :
350 : : static void
351 : 165 : _vbdev_lvs_remove_lvol_cb(void *cb_arg, int lvolerrno)
352 : : {
353 : 165 : struct lvol_store_bdev *lvs_bdev = cb_arg;
354 : 165 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
355 : : struct spdk_lvol *lvol;
356 : :
357 [ - + ]: 165 : if (lvolerrno != 0) {
358 [ # # # # ]: 0 : SPDK_DEBUGLOG(vbdev_lvol, "Lvol removed with errno %d\n", lvolerrno);
359 : : }
360 : :
361 [ + + ]: 165 : if (TAILQ_EMPTY(&lvs->lvols)) {
362 : 57 : spdk_lvs_destroy(lvs, _vbdev_lvs_remove_cb, lvs_bdev);
363 : 57 : return;
364 : : }
365 : :
366 : 108 : lvol = TAILQ_FIRST(&lvs->lvols);
367 [ + - ]: 110 : while (lvol != NULL) {
368 [ + + ]: 110 : if (spdk_lvol_deletable(lvol)) {
369 : 108 : _vbdev_lvol_destroy(lvol, _vbdev_lvs_remove_lvol_cb, lvs_bdev);
370 : 108 : return;
371 : : }
372 : 2 : lvol = TAILQ_NEXT(lvol, link);
373 : : }
374 : :
375 : : /* If no lvol is deletable, that means there is circular dependency. */
376 : 0 : SPDK_ERRLOG("Lvols left in lvs, but unable to delete.\n");
377 : 0 : assert(false);
378 : : }
379 : :
380 : : static bool
381 : 440 : _vbdev_lvs_are_lvols_closed(struct spdk_lvol_store *lvs)
382 : : {
383 : : struct spdk_lvol *lvol;
384 : :
385 [ + + ]: 646 : TAILQ_FOREACH(lvol, &lvs->lvols, link) {
386 [ + + ]: 415 : if (lvol->ref_count != 0) {
387 : 209 : return false;
388 : : }
389 : : }
390 : 231 : return true;
391 : : }
392 : :
393 : : static void
394 : 66 : _vbdev_lvs_remove_bdev_unregistered_cb(void *cb_arg, int bdeverrno)
395 : : {
396 : 66 : struct lvol_store_bdev *lvs_bdev = cb_arg;
397 : 66 : struct spdk_lvol_store *lvs = lvs_bdev->lvs;
398 : :
399 [ - + ]: 66 : if (bdeverrno != 0) {
400 [ # # # # ]: 0 : SPDK_DEBUGLOG(vbdev_lvol, "Lvol unregistered with errno %d\n", bdeverrno);
401 : : }
402 : :
403 : : /* Lvol store can be unloaded once all lvols are closed. */
404 [ + + ]: 66 : if (_vbdev_lvs_are_lvols_closed(lvs)) {
405 : 34 : spdk_lvs_unload(lvs, _vbdev_lvs_remove_cb, lvs_bdev);
406 : : }
407 : 66 : }
408 : :
409 : : static void
410 : 203 : _vbdev_lvs_remove(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg,
411 : : bool destroy)
412 : : {
413 : : struct spdk_lvs_req *req;
414 : : struct lvol_store_bdev *lvs_bdev;
415 : : struct spdk_lvol *lvol, *tmp;
416 : :
417 : 203 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
418 [ - + ]: 203 : if (!lvs_bdev) {
419 : 0 : SPDK_ERRLOG("No such lvol store found\n");
420 [ # # ]: 0 : if (cb_fn != NULL) {
421 : 0 : cb_fn(cb_arg, -ENODEV);
422 : : }
423 : 0 : return;
424 : : }
425 : :
426 : 203 : req = calloc(1, sizeof(*req));
427 [ - + ]: 203 : if (!req) {
428 : 0 : SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
429 [ # # ]: 0 : if (cb_fn != NULL) {
430 : 0 : cb_fn(cb_arg, -ENOMEM);
431 : : }
432 : 0 : return;
433 : : }
434 : :
435 : 203 : lvs_bdev->removal_in_progress = true;
436 : :
437 : 203 : req->cb_fn = cb_fn;
438 : 203 : req->cb_arg = cb_arg;
439 : 203 : lvs_bdev->req = req;
440 : :
441 [ + + ]: 203 : if (_vbdev_lvs_are_lvols_closed(lvs)) {
442 [ + + ]: 112 : if (destroy) {
443 : 100 : spdk_lvs_destroy(lvs, _vbdev_lvs_remove_cb, lvs_bdev);
444 : 100 : return;
445 : : }
446 : 12 : spdk_lvs_unload(lvs, _vbdev_lvs_remove_cb, lvs_bdev);
447 : 12 : return;
448 : : }
449 [ + + ]: 91 : if (destroy) {
450 : 57 : _vbdev_lvs_remove_lvol_cb(lvs_bdev, 0);
451 : 57 : return;
452 : : }
453 [ + + ]: 100 : TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
454 [ + + ]: 66 : if (lvol->bdev == NULL) {
455 : 3 : spdk_lvol_close(lvol, _vbdev_lvs_remove_bdev_unregistered_cb, lvs_bdev);
456 : 3 : continue;
457 : : }
458 : 63 : spdk_bdev_unregister(lvol->bdev, _vbdev_lvs_remove_bdev_unregistered_cb, lvs_bdev);
459 : : }
460 : : }
461 : :
462 : : void
463 : 46 : vbdev_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
464 : : {
465 : 46 : _vbdev_lvs_remove(lvs, cb_fn, cb_arg, false);
466 : 46 : }
467 : :
468 : : void
469 : 157 : vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
470 : : {
471 : 157 : _vbdev_lvs_remove(lvs, cb_fn, cb_arg, true);
472 : 157 : }
473 : :
474 : : struct lvol_store_bdev *
475 : 5610 : vbdev_lvol_store_first(void)
476 : : {
477 : : struct lvol_store_bdev *lvs_bdev;
478 : :
479 : 5610 : lvs_bdev = TAILQ_FIRST(&g_spdk_lvol_pairs);
480 [ + + ]: 5610 : if (lvs_bdev) {
481 [ - + - + ]: 3156 : SPDK_INFOLOG(vbdev_lvol, "Starting lvolstore iteration at %p\n", lvs_bdev->lvs);
482 : : }
483 : :
484 : 5610 : return lvs_bdev;
485 : : }
486 : :
487 : : struct lvol_store_bdev *
488 : 335 : vbdev_lvol_store_next(struct lvol_store_bdev *prev)
489 : : {
490 : : struct lvol_store_bdev *lvs_bdev;
491 : :
492 [ - + ]: 335 : if (prev == NULL) {
493 : 0 : SPDK_ERRLOG("prev argument cannot be NULL\n");
494 : 0 : return NULL;
495 : : }
496 : :
497 : 335 : lvs_bdev = TAILQ_NEXT(prev, lvol_stores);
498 [ + + ]: 335 : if (lvs_bdev) {
499 [ - + - + ]: 157 : SPDK_INFOLOG(vbdev_lvol, "Continuing lvolstore iteration at %p\n", lvs_bdev->lvs);
500 : : }
501 : :
502 : 335 : return lvs_bdev;
503 : : }
504 : :
505 : : static struct spdk_lvol_store *
506 : 337 : _vbdev_get_lvol_store_by_uuid(const struct spdk_uuid *uuid)
507 : : {
508 : 337 : struct spdk_lvol_store *lvs = NULL;
509 : 337 : struct lvol_store_bdev *lvs_bdev = vbdev_lvol_store_first();
510 : :
511 [ + + ]: 372 : while (lvs_bdev != NULL) {
512 : 329 : lvs = lvs_bdev->lvs;
513 [ + + ]: 329 : if (spdk_uuid_compare(&lvs->uuid, uuid) == 0) {
514 : 294 : return lvs;
515 : : }
516 : 35 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev);
517 : : }
518 : 43 : return NULL;
519 : : }
520 : :
521 : : struct spdk_lvol_store *
522 : 337 : vbdev_get_lvol_store_by_uuid(const char *uuid_str)
523 : : {
524 : 235 : struct spdk_uuid uuid;
525 : :
526 [ - + ]: 337 : if (spdk_uuid_parse(&uuid, uuid_str)) {
527 : 0 : return NULL;
528 : : }
529 : :
530 : 337 : return _vbdev_get_lvol_store_by_uuid(&uuid);
531 : : }
532 : :
533 : : struct spdk_lvol_store *
534 : 116 : vbdev_get_lvol_store_by_name(const char *name)
535 : : {
536 : 116 : struct spdk_lvol_store *lvs = NULL;
537 : 116 : struct lvol_store_bdev *lvs_bdev = vbdev_lvol_store_first();
538 : :
539 [ + + ]: 117 : while (lvs_bdev != NULL) {
540 : 105 : lvs = lvs_bdev->lvs;
541 [ + + - + : 105 : if (strncmp(lvs->name, name, sizeof(lvs->name)) == 0) {
+ + ]
542 : 104 : return lvs;
543 : : }
544 : 1 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev);
545 : : }
546 : 12 : return NULL;
547 : : }
548 : :
549 : : struct vbdev_lvol_destroy_ctx {
550 : : struct spdk_lvol *lvol;
551 : : spdk_lvol_op_complete cb_fn;
552 : : void *cb_arg;
553 : : };
554 : :
555 : : static void
556 : 74 : _vbdev_lvol_unregister_unload_lvs(void *cb_arg, int lvserrno)
557 : : {
558 : 74 : struct lvol_bdev *lvol_bdev = cb_arg;
559 : 74 : struct lvol_store_bdev *lvs_bdev = lvol_bdev->lvs_bdev;
560 : :
561 [ - + ]: 74 : if (lvserrno != 0) {
562 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol, "Lvol store removed with error: %d.\n", lvserrno);
563 : : }
564 : :
565 [ - + ]: 74 : TAILQ_REMOVE(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
566 : 74 : free(lvs_bdev);
567 : :
568 : 74 : spdk_bdev_destruct_done(&lvol_bdev->bdev, lvserrno);
569 : 74 : free(lvol_bdev);
570 : 74 : }
571 : :
572 : : static void
573 : 502 : _vbdev_lvol_unregister_cb(void *ctx, int lvolerrno)
574 : : {
575 : 502 : struct lvol_bdev *lvol_bdev = ctx;
576 : 502 : struct lvol_store_bdev *lvs_bdev = lvol_bdev->lvs_bdev;
577 : :
578 [ + + + + : 502 : if (g_shutdown_started && _vbdev_lvs_are_lvols_closed(lvs_bdev->lvs)) {
+ + ]
579 : 74 : spdk_lvs_unload(lvs_bdev->lvs, _vbdev_lvol_unregister_unload_lvs, lvol_bdev);
580 : 74 : return;
581 : : }
582 : :
583 : 428 : spdk_bdev_destruct_done(&lvol_bdev->bdev, lvolerrno);
584 : 428 : free(lvol_bdev);
585 : : }
586 : :
587 : : static int
588 : 502 : vbdev_lvol_unregister(void *ctx)
589 : : {
590 : 502 : struct spdk_lvol *lvol = ctx;
591 : : struct lvol_bdev *lvol_bdev;
592 : :
593 [ - + ]: 502 : assert(lvol != NULL);
594 : 502 : lvol_bdev = SPDK_CONTAINEROF(lvol->bdev, struct lvol_bdev, bdev);
595 : :
596 : 502 : spdk_bdev_alias_del_all(lvol->bdev);
597 : 502 : spdk_lvol_close(lvol, _vbdev_lvol_unregister_cb, lvol_bdev);
598 : :
599 : : /* return 1 to indicate we have an operation that must finish asynchronously before the
600 : : * lvol is closed
601 : : */
602 : 502 : return 1;
603 : : }
604 : :
605 : : static void
606 : 358 : _vbdev_lvol_destroy_cb(void *cb_arg, int bdeverrno)
607 : : {
608 : 358 : struct vbdev_lvol_destroy_ctx *ctx = cb_arg;
609 : 358 : struct spdk_lvol *lvol = ctx->lvol;
610 : :
611 [ - + ]: 358 : if (bdeverrno < 0) {
612 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol, "Could not unregister bdev during lvol (%s) destroy\n",
613 : : lvol->unique_id);
614 : 0 : ctx->cb_fn(ctx->cb_arg, bdeverrno);
615 : 0 : free(ctx);
616 : 0 : return;
617 : : }
618 : :
619 : 358 : spdk_lvol_destroy(lvol, ctx->cb_fn, ctx->cb_arg);
620 : 358 : free(ctx);
621 : : }
622 : :
623 : : static void
624 : 362 : _vbdev_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
625 : : {
626 : : struct vbdev_lvol_destroy_ctx *ctx;
627 : 272 : size_t count;
628 : :
629 [ - + ]: 362 : assert(lvol != NULL);
630 [ - + ]: 362 : assert(cb_fn != NULL);
631 : :
632 : : /* Callers other than _vbdev_lvs_remove() must ensure the lvstore is not being removed. */
633 [ + + - + ]: 362 : assert(cb_fn == _vbdev_lvs_remove_lvol_cb ||
634 : : vbdev_get_lvs_bdev_by_lvs(lvol->lvol_store) != NULL);
635 : :
636 : : /* Check if it is possible to delete lvol */
637 : 362 : spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, NULL, &count);
638 [ + + ]: 362 : if (count > 1) {
639 : : /* throw an error */
640 : 4 : SPDK_ERRLOG("Cannot delete lvol\n");
641 : 4 : cb_fn(cb_arg, -EPERM);
642 : 4 : return;
643 : : }
644 : :
645 : 358 : ctx = calloc(1, sizeof(*ctx));
646 [ - + ]: 358 : if (!ctx) {
647 : 0 : cb_fn(cb_arg, -ENOMEM);
648 : 0 : return;
649 : : }
650 : :
651 : 358 : ctx->lvol = lvol;
652 : 358 : ctx->cb_fn = cb_fn;
653 : 358 : ctx->cb_arg = cb_arg;
654 : :
655 [ + + ]: 358 : if (spdk_lvol_is_degraded(lvol)) {
656 : 5 : spdk_lvol_close(lvol, _vbdev_lvol_destroy_cb, ctx);
657 : 5 : return;
658 : : }
659 : :
660 : 353 : spdk_bdev_unregister(lvol->bdev, _vbdev_lvol_destroy_cb, ctx);
661 : : }
662 : :
663 : : void
664 : 334 : vbdev_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
665 : : {
666 : : struct lvol_store_bdev *lvs_bdev;
667 : :
668 : : /*
669 : : * During destruction of an lvolstore, _vbdev_lvs_unload() iterates through lvols until they
670 : : * are all deleted. There may be some IO required
671 : : */
672 : 334 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvol->lvol_store);
673 [ + + ]: 334 : if (lvs_bdev == NULL) {
674 [ - + - + ]: 80 : SPDK_DEBUGLOG(vbdev_lvol, "lvol %s: lvolstore is being removed\n",
675 : : lvol->unique_id);
676 : 80 : cb_fn(cb_arg, -ENODEV);
677 : 80 : return;
678 : : }
679 : :
680 : 254 : _vbdev_lvol_destroy(lvol, cb_fn, cb_arg);
681 : : }
682 : :
683 : : static char *
684 : 91 : vbdev_lvol_find_name(struct spdk_lvol *lvol, spdk_blob_id blob_id)
685 : : {
686 : : struct spdk_lvol_store *lvs;
687 : : struct spdk_lvol *_lvol;
688 : :
689 [ - + ]: 91 : assert(lvol != NULL);
690 : :
691 : 91 : lvs = lvol->lvol_store;
692 : :
693 [ - + ]: 91 : assert(lvs);
694 : :
695 [ + - ]: 187 : TAILQ_FOREACH(_lvol, &lvs->lvols, link) {
696 [ + + ]: 187 : if (_lvol->blob_id == blob_id) {
697 : 91 : return _lvol->name;
698 : : }
699 : : }
700 : :
701 : 0 : return NULL;
702 : : }
703 : :
704 : : static int
705 : 1187 : vbdev_lvol_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
706 : : {
707 : 1187 : struct spdk_lvol *lvol = ctx;
708 : : struct lvol_store_bdev *lvs_bdev;
709 : : struct spdk_bdev *bdev;
710 : : struct spdk_blob *blob;
711 : 1187 : spdk_blob_id *ids = NULL;
712 : 1165 : size_t count, i;
713 : : char *name;
714 : 1187 : int rc = 0;
715 : :
716 : 1187 : spdk_json_write_named_object_begin(w, "lvol");
717 : :
718 : 1187 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvol->lvol_store);
719 [ - + ]: 1187 : if (!lvs_bdev) {
720 : 0 : SPDK_ERRLOG("No such lvol store found\n");
721 : 0 : rc = -ENODEV;
722 : 0 : goto end;
723 : : }
724 : :
725 : 1187 : bdev = lvs_bdev->bdev;
726 : :
727 : 1187 : spdk_json_write_named_uuid(w, "lvol_store_uuid", &lvol->lvol_store->uuid);
728 : :
729 : 1187 : spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(bdev));
730 : :
731 : 1187 : blob = lvol->blob;
732 : :
733 : 1187 : spdk_json_write_named_bool(w, "thin_provision", spdk_blob_is_thin_provisioned(blob));
734 : :
735 : 1187 : spdk_json_write_named_uint64(w, "num_allocated_clusters",
736 : : spdk_blob_get_num_allocated_clusters(blob));
737 : :
738 : 1187 : spdk_json_write_named_bool(w, "snapshot", spdk_blob_is_snapshot(blob));
739 : :
740 : 1187 : spdk_json_write_named_bool(w, "clone", spdk_blob_is_clone(blob));
741 : :
742 [ + + ]: 1187 : if (spdk_blob_is_clone(blob)) {
743 : 49 : spdk_blob_id snapshotid = spdk_blob_get_parent_snapshot(lvol->lvol_store->blobstore, lvol->blob_id);
744 [ + - ]: 49 : if (snapshotid != SPDK_BLOBID_INVALID) {
745 : 49 : name = vbdev_lvol_find_name(lvol, snapshotid);
746 [ + - ]: 49 : if (name != NULL) {
747 : 49 : spdk_json_write_named_string(w, "base_snapshot", name);
748 : : } else {
749 : 0 : SPDK_ERRLOG("Cannot obtain snapshots name\n");
750 : : }
751 : : }
752 : : }
753 : :
754 [ + + ]: 1187 : if (spdk_blob_is_snapshot(blob)) {
755 : : /* Take a number of clones */
756 : 34 : rc = spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, NULL, &count);
757 [ + - + + ]: 34 : if (rc == -ENOMEM && count > 0) {
758 : 31 : ids = malloc(sizeof(spdk_blob_id) * count);
759 [ - + ]: 31 : if (ids == NULL) {
760 : 0 : SPDK_ERRLOG("Cannot allocate memory\n");
761 : 0 : rc = -ENOMEM;
762 : 0 : goto end;
763 : : }
764 : :
765 : 31 : rc = spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, ids, &count);
766 [ + - ]: 31 : if (rc == 0) {
767 : 31 : spdk_json_write_named_array_begin(w, "clones");
768 [ + + ]: 73 : for (i = 0; i < count; i++) {
769 : 42 : name = vbdev_lvol_find_name(lvol, ids[i]);
770 [ + - ]: 42 : if (name != NULL) {
771 : 42 : spdk_json_write_string(w, name);
772 : : } else {
773 : 0 : SPDK_ERRLOG("Cannot obtain clone name\n");
774 : : }
775 : :
776 : : }
777 : 31 : spdk_json_write_array_end(w);
778 : : }
779 : 31 : free(ids);
780 : : }
781 : :
782 : : }
783 : :
784 : 1187 : spdk_json_write_named_bool(w, "esnap_clone", spdk_blob_is_esnap_clone(blob));
785 : :
786 [ + + ]: 1187 : if (spdk_blob_is_esnap_clone(blob)) {
787 : 23 : const char *name;
788 : 23 : size_t name_len;
789 : :
790 : 23 : rc = spdk_blob_get_esnap_id(blob, (const void **)&name, &name_len);
791 [ + - + - : 23 : if (rc == 0 && name != NULL && strnlen(name, name_len) + 1 == name_len) {
- + + - ]
792 : 23 : spdk_json_write_named_string(w, "external_snapshot_name", name);
793 : : }
794 : : }
795 : :
796 : 1187 : end:
797 : 1187 : spdk_json_write_object_end(w);
798 : :
799 : 1187 : return rc;
800 : : }
801 : :
802 : : static void
803 : 93 : vbdev_lvol_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
804 : : {
805 : : /* Nothing to dump as lvol configuration is saved on physical device. */
806 : 93 : }
807 : :
808 : : static struct spdk_io_channel *
809 : 648 : vbdev_lvol_get_io_channel(void *ctx)
810 : : {
811 : 648 : struct spdk_lvol *lvol = ctx;
812 : :
813 : 648 : return spdk_lvol_get_io_channel(lvol);
814 : : }
815 : :
816 : : static bool
817 : 27303 : vbdev_lvol_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
818 : : {
819 : 27303 : struct spdk_lvol *lvol = ctx;
820 : :
821 [ + + + ]: 27303 : switch (io_type) {
822 : 6151 : case SPDK_BDEV_IO_TYPE_WRITE:
823 : : case SPDK_BDEV_IO_TYPE_UNMAP:
824 : : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
825 : 6151 : return !spdk_blob_is_read_only(lvol->blob);
826 : 4824 : case SPDK_BDEV_IO_TYPE_RESET:
827 : : case SPDK_BDEV_IO_TYPE_READ:
828 : : case SPDK_BDEV_IO_TYPE_SEEK_DATA:
829 : : case SPDK_BDEV_IO_TYPE_SEEK_HOLE:
830 : 4824 : return true;
831 : 16328 : default:
832 : 16328 : return false;
833 : : }
834 : : }
835 : :
836 : : static void
837 : 4791018 : lvol_op_comp(void *cb_arg, int bserrno)
838 : : {
839 : 4791018 : struct spdk_bdev_io *bdev_io = cb_arg;
840 : 4791018 : enum spdk_bdev_io_status status = SPDK_BDEV_IO_STATUS_SUCCESS;
841 : :
842 [ + + ]: 4791018 : if (bserrno != 0) {
843 [ + + ]: 31062 : if (bserrno == -ENOMEM) {
844 : 31027 : status = SPDK_BDEV_IO_STATUS_NOMEM;
845 : : } else {
846 : 35 : status = SPDK_BDEV_IO_STATUS_FAILED;
847 : : }
848 : : }
849 : :
850 : 4791018 : spdk_bdev_io_complete(bdev_io, status);
851 : 4791018 : }
852 : :
853 : : static void
854 : 97563 : lvol_unmap(struct spdk_lvol *lvol, struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
855 : : {
856 : : uint64_t start_page, num_pages;
857 : 97563 : struct spdk_blob *blob = lvol->blob;
858 : :
859 : 97563 : start_page = bdev_io->u.bdev.offset_blocks;
860 : 97563 : num_pages = bdev_io->u.bdev.num_blocks;
861 : :
862 : 97563 : spdk_blob_io_unmap(blob, ch, start_page, num_pages, lvol_op_comp, bdev_io);
863 : 97563 : }
864 : :
865 : : static void
866 : 26 : lvol_seek_data(struct spdk_lvol *lvol, struct spdk_bdev_io *bdev_io)
867 : : {
868 : 26 : bdev_io->u.bdev.seek.offset = spdk_blob_get_next_allocated_io_unit(lvol->blob,
869 : : bdev_io->u.bdev.offset_blocks);
870 : :
871 : 26 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
872 : 26 : }
873 : :
874 : : static void
875 : 26 : lvol_seek_hole(struct spdk_lvol *lvol, struct spdk_bdev_io *bdev_io)
876 : : {
877 : 26 : bdev_io->u.bdev.seek.offset = spdk_blob_get_next_unallocated_io_unit(lvol->blob,
878 : : bdev_io->u.bdev.offset_blocks);
879 : :
880 : 26 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
881 : 26 : }
882 : :
883 : : static void
884 : 5 : lvol_write_zeroes(struct spdk_lvol *lvol, struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
885 : : {
886 : : uint64_t start_page, num_pages;
887 : 5 : struct spdk_blob *blob = lvol->blob;
888 : :
889 : 5 : start_page = bdev_io->u.bdev.offset_blocks;
890 : 5 : num_pages = bdev_io->u.bdev.num_blocks;
891 : :
892 : 5 : spdk_blob_io_write_zeroes(blob, ch, start_page, num_pages, lvol_op_comp, bdev_io);
893 : 5 : }
894 : :
895 : : static void
896 : 2234196 : lvol_read(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
897 : : {
898 : : uint64_t start_page, num_pages;
899 : 2234196 : struct spdk_lvol *lvol = bdev_io->bdev->ctxt;
900 : 2234196 : struct spdk_blob *blob = lvol->blob;
901 : 2234196 : struct vbdev_lvol_io *lvol_io = (struct vbdev_lvol_io *)bdev_io->driver_ctx;
902 : :
903 : 2234196 : start_page = bdev_io->u.bdev.offset_blocks;
904 : 2234196 : num_pages = bdev_io->u.bdev.num_blocks;
905 : :
906 : 2234196 : lvol_io->ext_io_opts.size = sizeof(lvol_io->ext_io_opts);
907 : 2234196 : lvol_io->ext_io_opts.memory_domain = bdev_io->u.bdev.memory_domain;
908 : 2234196 : lvol_io->ext_io_opts.memory_domain_ctx = bdev_io->u.bdev.memory_domain_ctx;
909 : :
910 : 2234196 : spdk_blob_io_readv_ext(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page,
911 : : num_pages, lvol_op_comp, bdev_io, &lvol_io->ext_io_opts);
912 : 2234196 : }
913 : :
914 : : static void
915 : 2459254 : lvol_write(struct spdk_lvol *lvol, struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
916 : : {
917 : : uint64_t start_page, num_pages;
918 : 2459254 : struct spdk_blob *blob = lvol->blob;
919 : 2459254 : struct vbdev_lvol_io *lvol_io = (struct vbdev_lvol_io *)bdev_io->driver_ctx;
920 : :
921 : 2459254 : start_page = bdev_io->u.bdev.offset_blocks;
922 : 2459254 : num_pages = bdev_io->u.bdev.num_blocks;
923 : :
924 : 2459254 : lvol_io->ext_io_opts.size = sizeof(lvol_io->ext_io_opts);
925 : 2459254 : lvol_io->ext_io_opts.memory_domain = bdev_io->u.bdev.memory_domain;
926 : 2459254 : lvol_io->ext_io_opts.memory_domain_ctx = bdev_io->u.bdev.memory_domain_ctx;
927 : :
928 : 2459254 : spdk_blob_io_writev_ext(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page,
929 : : num_pages, lvol_op_comp, bdev_io, &lvol_io->ext_io_opts);
930 : 2459254 : }
931 : :
932 : : static int
933 : 0 : lvol_reset(struct spdk_bdev_io *bdev_io)
934 : : {
935 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
936 : :
937 : 0 : return 0;
938 : : }
939 : :
940 : : static void
941 : 2234188 : lvol_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success)
942 : : {
943 [ - + ]: 2234188 : if (!success) {
944 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
945 : 0 : return;
946 : : }
947 : :
948 : 2234188 : lvol_read(ch, bdev_io);
949 : : }
950 : :
951 : : static void
952 : 4791042 : vbdev_lvol_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
953 : : {
954 : 4791042 : struct spdk_lvol *lvol = bdev_io->bdev->ctxt;
955 : :
956 [ + + - + : 4791042 : switch (bdev_io->type) {
+ + + - ]
957 : 2234192 : case SPDK_BDEV_IO_TYPE_READ:
958 : 2234192 : spdk_bdev_io_get_buf(bdev_io, lvol_get_buf_cb,
959 : 2234192 : bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
960 : 2234192 : break;
961 : 2459246 : case SPDK_BDEV_IO_TYPE_WRITE:
962 : 2459246 : lvol_write(lvol, ch, bdev_io);
963 : 2459246 : break;
964 : 0 : case SPDK_BDEV_IO_TYPE_RESET:
965 : 0 : lvol_reset(bdev_io);
966 : 0 : break;
967 : 97563 : case SPDK_BDEV_IO_TYPE_UNMAP:
968 : 97563 : lvol_unmap(lvol, ch, bdev_io);
969 : 97563 : break;
970 : 5 : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
971 : 5 : lvol_write_zeroes(lvol, ch, bdev_io);
972 : 5 : break;
973 : 18 : case SPDK_BDEV_IO_TYPE_SEEK_DATA:
974 : 18 : lvol_seek_data(lvol, bdev_io);
975 : 18 : break;
976 : 18 : case SPDK_BDEV_IO_TYPE_SEEK_HOLE:
977 : 18 : lvol_seek_hole(lvol, bdev_io);
978 : 18 : break;
979 : 0 : default:
980 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol, "lvol: unsupported I/O type %d\n", bdev_io->type);
981 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
982 : 0 : return;
983 : : }
984 : 4791042 : return;
985 : : }
986 : :
987 : : static int
988 : 5291 : vbdev_lvol_get_memory_domains(void *ctx, struct spdk_memory_domain **domains, int array_size)
989 : : {
990 : 5291 : struct spdk_lvol *lvol = ctx;
991 : : struct spdk_bdev *base_bdev, *esnap_bdev;
992 : : struct spdk_bs_dev *bs_dev;
993 : : struct spdk_lvol_store *lvs;
994 : : int base_cnt, esnap_cnt;
995 : :
996 : 5291 : lvs = lvol->lvol_store;
997 : 5291 : base_bdev = lvs->bs_dev->get_base_bdev(lvol->lvol_store->bs_dev);
998 : :
999 : 5291 : base_cnt = spdk_bdev_get_memory_domains(base_bdev, domains, array_size);
1000 [ - + ]: 5291 : if (base_cnt < 0) {
1001 : 0 : return base_cnt;
1002 : : }
1003 : :
1004 [ - + ]: 5291 : if (lvol->blob == NULL) {
1005 : : /*
1006 : : * This is probably called due to an open happening during blobstore load. Another
1007 : : * open will follow shortly that has lvol->blob set.
1008 : : */
1009 : 0 : return -EAGAIN;
1010 : : }
1011 : :
1012 [ + + ]: 5291 : if (!spdk_blob_is_esnap_clone(lvol->blob)) {
1013 : 5139 : return base_cnt;
1014 : : }
1015 : :
1016 : 152 : bs_dev = spdk_blob_get_esnap_bs_dev(lvol->blob);
1017 [ - + ]: 152 : if (bs_dev == NULL) {
1018 : 0 : assert(false);
1019 : : SPDK_ERRLOG("lvol %s is an esnap clone but has no esnap device\n", lvol->unique_id);
1020 : : return base_cnt;
1021 : : }
1022 : :
1023 [ - + ]: 152 : if (bs_dev->get_base_bdev == NULL) {
1024 : : /*
1025 : : * If this were a blob_bdev, we wouldn't be here. We are probably here because an
1026 : : * lvol bdev is being registered with spdk_bdev_register() before the external
1027 : : * snapshot bdev is loaded. Ideally, the load of a missing esnap would trigger an
1028 : : * event that causes the lvol bdev's memory domain information to be updated.
1029 : : */
1030 : 0 : return base_cnt;
1031 : : }
1032 : :
1033 : 152 : esnap_bdev = bs_dev->get_base_bdev(bs_dev);
1034 [ - + ]: 152 : if (esnap_bdev == NULL) {
1035 : : /*
1036 : : * The esnap bdev has not yet been loaded. Anyone that has opened at this point may
1037 : : * miss out on using memory domains if base_cnt is zero.
1038 : : */
1039 : 0 : SPDK_NOTICELOG("lvol %s reporting %d memory domains, not including missing esnap\n",
1040 : : lvol->unique_id, base_cnt);
1041 : 0 : return base_cnt;
1042 : : }
1043 : :
1044 [ + + ]: 152 : if (base_cnt < array_size) {
1045 : 23 : array_size -= base_cnt;
1046 : 23 : domains += base_cnt;
1047 : : } else {
1048 : 129 : array_size = 0;
1049 : 129 : domains = NULL;
1050 : : }
1051 : :
1052 : 152 : esnap_cnt = spdk_bdev_get_memory_domains(esnap_bdev, domains, array_size);
1053 [ - + ]: 152 : if (esnap_cnt <= 0) {
1054 : 0 : return base_cnt;
1055 : : }
1056 : :
1057 : 152 : return base_cnt + esnap_cnt;
1058 : : }
1059 : :
1060 : : static struct spdk_bdev_fn_table vbdev_lvol_fn_table = {
1061 : : .destruct = vbdev_lvol_unregister,
1062 : : .io_type_supported = vbdev_lvol_io_type_supported,
1063 : : .submit_request = vbdev_lvol_submit_request,
1064 : : .get_io_channel = vbdev_lvol_get_io_channel,
1065 : : .dump_info_json = vbdev_lvol_dump_info_json,
1066 : : .write_config_json = vbdev_lvol_write_config_json,
1067 : : .get_memory_domains = vbdev_lvol_get_memory_domains,
1068 : : };
1069 : :
1070 : : static void
1071 : 0 : lvol_destroy_cb(void *cb_arg, int bdeverrno)
1072 : : {
1073 : 0 : }
1074 : :
1075 : : static void
1076 : 0 : _create_lvol_disk_destroy_cb(void *cb_arg, int bdeverrno)
1077 : : {
1078 : 0 : struct spdk_lvol *lvol = cb_arg;
1079 : :
1080 [ # # ]: 0 : if (bdeverrno < 0) {
1081 : 0 : SPDK_ERRLOG("Could not unregister bdev for lvol %s\n",
1082 : : lvol->unique_id);
1083 : 0 : return;
1084 : : }
1085 : :
1086 : 0 : spdk_lvol_destroy(lvol, lvol_destroy_cb, NULL);
1087 : : }
1088 : :
1089 : : static void
1090 : 0 : _create_lvol_disk_unload_cb(void *cb_arg, int bdeverrno)
1091 : : {
1092 : 0 : struct spdk_lvol *lvol = cb_arg;
1093 : :
1094 [ # # ]: 0 : if (bdeverrno < 0) {
1095 : 0 : SPDK_ERRLOG("Could not unregister bdev for lvol %s\n",
1096 : : lvol->unique_id);
1097 : 0 : return;
1098 : : }
1099 : :
1100 [ # # ]: 0 : TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
1101 : 0 : free(lvol);
1102 : : }
1103 : :
1104 : : static int
1105 : 515 : _create_lvol_disk(struct spdk_lvol *lvol, bool destroy)
1106 : : {
1107 : : struct spdk_bdev *bdev;
1108 : : struct lvol_bdev *lvol_bdev;
1109 : : struct lvol_store_bdev *lvs_bdev;
1110 : : uint64_t total_size;
1111 : : unsigned char *alias;
1112 : : int rc;
1113 : :
1114 [ + + ]: 515 : if (spdk_lvol_is_degraded(lvol)) {
1115 : 13 : SPDK_NOTICELOG("lvol %s: blob is degraded: deferring bdev creation\n",
1116 : : lvol->unique_id);
1117 : 13 : return 0;
1118 : : }
1119 : :
1120 : 502 : lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvol->lvol_store);
1121 [ - + ]: 502 : if (lvs_bdev == NULL) {
1122 : 0 : SPDK_ERRLOG("No spdk lvs-bdev pair found for lvol %s\n", lvol->unique_id);
1123 : 0 : assert(false);
1124 : : return -ENODEV;
1125 : : }
1126 : :
1127 : 502 : lvol_bdev = calloc(1, sizeof(struct lvol_bdev));
1128 [ - + ]: 502 : if (!lvol_bdev) {
1129 : 0 : SPDK_ERRLOG("Cannot alloc memory for lvol bdev\n");
1130 : 0 : return -ENOMEM;
1131 : : }
1132 : :
1133 : 502 : lvol_bdev->lvol = lvol;
1134 : 502 : lvol_bdev->lvs_bdev = lvs_bdev;
1135 : :
1136 : 502 : bdev = &lvol_bdev->bdev;
1137 : 502 : bdev->name = lvol->unique_id;
1138 : 502 : bdev->product_name = "Logical Volume";
1139 : 502 : bdev->blocklen = spdk_bs_get_io_unit_size(lvol->lvol_store->blobstore);
1140 : 502 : total_size = spdk_blob_get_num_clusters(lvol->blob) *
1141 : 502 : spdk_bs_get_cluster_size(lvol->lvol_store->blobstore);
1142 [ - + - + ]: 502 : assert((total_size % bdev->blocklen) == 0);
1143 [ - + ]: 502 : bdev->blockcnt = total_size / bdev->blocklen;
1144 : 502 : bdev->uuid = lvol->uuid;
1145 : 502 : bdev->required_alignment = lvs_bdev->bdev->required_alignment;
1146 : 502 : bdev->split_on_optimal_io_boundary = true;
1147 [ - + ]: 502 : bdev->optimal_io_boundary = spdk_bs_get_cluster_size(lvol->lvol_store->blobstore) / bdev->blocklen;
1148 : :
1149 : 502 : bdev->ctxt = lvol;
1150 : 502 : bdev->fn_table = &vbdev_lvol_fn_table;
1151 : 502 : bdev->module = &g_lvol_if;
1152 : :
1153 : : /* Set default bdev reset waiting time. This value indicates how much
1154 : : * time a reset should wait before forcing a reset down to the underlying
1155 : : * bdev module.
1156 : : * Setting this parameter is mainly to avoid "empty" resets to a shared
1157 : : * bdev that may be used by multiple lvols. */
1158 : 502 : bdev->reset_io_drain_timeout = SPDK_BDEV_RESET_IO_DRAIN_RECOMMENDED_VALUE;
1159 : :
1160 : 502 : rc = spdk_bdev_register(bdev);
1161 [ - + ]: 502 : if (rc) {
1162 : 0 : free(lvol_bdev);
1163 : 0 : return rc;
1164 : : }
1165 : 502 : lvol->bdev = bdev;
1166 : :
1167 : 502 : alias = spdk_sprintf_alloc("%s/%s", lvs_bdev->lvs->name, lvol->name);
1168 [ - + ]: 502 : if (alias == NULL) {
1169 : 0 : SPDK_ERRLOG("Cannot alloc memory for alias\n");
1170 [ # # ]: 0 : spdk_bdev_unregister(lvol->bdev, (destroy ? _create_lvol_disk_destroy_cb :
1171 : : _create_lvol_disk_unload_cb), lvol);
1172 : 0 : return -ENOMEM;
1173 : : }
1174 : :
1175 : 502 : rc = spdk_bdev_alias_add(bdev, alias);
1176 [ - + ]: 502 : if (rc != 0) {
1177 : 0 : SPDK_ERRLOG("Cannot add alias to lvol bdev\n");
1178 [ # # ]: 0 : spdk_bdev_unregister(lvol->bdev, (destroy ? _create_lvol_disk_destroy_cb :
1179 : : _create_lvol_disk_unload_cb), lvol);
1180 : : }
1181 : 502 : free(alias);
1182 : :
1183 : 502 : return rc;
1184 : : }
1185 : :
1186 : : static void
1187 : 387 : _vbdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
1188 : : {
1189 : 387 : struct spdk_lvol_with_handle_req *req = cb_arg;
1190 : :
1191 [ + + ]: 387 : if (lvolerrno < 0) {
1192 : 5 : goto end;
1193 : : }
1194 : :
1195 : 382 : lvolerrno = _create_lvol_disk(lvol, true);
1196 : :
1197 : 387 : end:
1198 : 387 : req->cb_fn(req->cb_arg, lvol, lvolerrno);
1199 : 387 : free(req);
1200 : 387 : }
1201 : :
1202 : : int
1203 : 296 : vbdev_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz,
1204 : : bool thin_provision, enum lvol_clear_method clear_method, spdk_lvol_op_with_handle_complete cb_fn,
1205 : : void *cb_arg)
1206 : : {
1207 : : struct spdk_lvol_with_handle_req *req;
1208 : : int rc;
1209 : :
1210 : 296 : req = calloc(1, sizeof(*req));
1211 [ - + ]: 296 : if (req == NULL) {
1212 : 0 : return -ENOMEM;
1213 : : }
1214 : 296 : req->cb_fn = cb_fn;
1215 : 296 : req->cb_arg = cb_arg;
1216 : :
1217 : 296 : rc = spdk_lvol_create(lvs, name, sz, thin_provision, clear_method,
1218 : : _vbdev_lvol_create_cb, req);
1219 [ + + ]: 296 : if (rc != 0) {
1220 : 1 : free(req);
1221 : : }
1222 : :
1223 : 296 : return rc;
1224 : : }
1225 : :
1226 : : void
1227 : 46 : vbdev_lvol_create_snapshot(struct spdk_lvol *lvol, const char *snapshot_name,
1228 : : spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
1229 : : {
1230 : : struct spdk_lvol_with_handle_req *req;
1231 : :
1232 : 46 : req = calloc(1, sizeof(*req));
1233 [ - + ]: 46 : if (req == NULL) {
1234 : 0 : cb_fn(cb_arg, NULL, -ENOMEM);
1235 : 0 : return;
1236 : : }
1237 : :
1238 : 46 : req->cb_fn = cb_fn;
1239 : 46 : req->cb_arg = cb_arg;
1240 : :
1241 : 46 : spdk_lvol_create_snapshot(lvol, snapshot_name, _vbdev_lvol_create_cb, req);
1242 : : }
1243 : :
1244 : : void
1245 : 28 : vbdev_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
1246 : : spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
1247 : : {
1248 : : struct spdk_lvol_with_handle_req *req;
1249 : :
1250 : 28 : req = calloc(1, sizeof(*req));
1251 [ - + ]: 28 : if (req == NULL) {
1252 : 0 : cb_fn(cb_arg, NULL, -ENOMEM);
1253 : 0 : return;
1254 : : }
1255 : :
1256 : 28 : req->cb_fn = cb_fn;
1257 : 28 : req->cb_arg = cb_arg;
1258 : :
1259 : 28 : spdk_lvol_create_clone(lvol, clone_name, _vbdev_lvol_create_cb, req);
1260 : : }
1261 : :
1262 : : static void
1263 : 0 : ignore_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx)
1264 : : {
1265 : 0 : }
1266 : :
1267 : : void
1268 : 26 : vbdev_lvol_create_bdev_clone(const char *esnap_name,
1269 : : struct spdk_lvol_store *lvs, const char *clone_name,
1270 : : spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
1271 : : {
1272 : : struct spdk_lvol_with_handle_req *req;
1273 : 26 : struct spdk_bdev_desc *desc;
1274 : : struct spdk_bdev *bdev;
1275 : 26 : char bdev_uuid[SPDK_UUID_STRING_LEN];
1276 : : uint64_t sz;
1277 : : int rc;
1278 : :
1279 [ + + ]: 26 : if (lvs == NULL) {
1280 : 4 : SPDK_ERRLOG("lvol store not specified\n");
1281 : 4 : cb_fn(cb_arg, NULL, -EINVAL);
1282 : 4 : return;
1283 : : }
1284 : :
1285 : 22 : rc = spdk_bdev_open_ext(esnap_name, false, ignore_bdev_event_cb, NULL, &desc);
1286 [ + + ]: 22 : if (rc != 0) {
1287 : 4 : SPDK_ERRLOG("bdev '%s' could not be opened: error %d\n", esnap_name, rc);
1288 : 4 : cb_fn(cb_arg, NULL, rc);
1289 : 4 : return;
1290 : : }
1291 : 18 : bdev = spdk_bdev_desc_get_bdev(desc);
1292 : :
1293 : 18 : rc = spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), spdk_bdev_get_uuid(bdev));
1294 [ - + ]: 18 : if (rc != 0) {
1295 : 0 : spdk_bdev_close(desc);
1296 : 0 : SPDK_ERRLOG("bdev %s: unable to parse UUID\n", esnap_name);
1297 : 0 : assert(false);
1298 : : cb_fn(cb_arg, NULL, -ENODEV);
1299 : : return;
1300 : : }
1301 : :
1302 : 18 : req = calloc(1, sizeof(*req));
1303 [ - + ]: 18 : if (req == NULL) {
1304 : 0 : spdk_bdev_close(desc);
1305 : 0 : cb_fn(cb_arg, NULL, -ENOMEM);
1306 : 0 : return;
1307 : : }
1308 : :
1309 : 18 : req->cb_fn = cb_fn;
1310 : 18 : req->cb_arg = cb_arg;
1311 : :
1312 : 18 : sz = spdk_bdev_get_num_blocks(bdev) * spdk_bdev_get_block_size(bdev);
1313 : 18 : rc = spdk_lvol_create_esnap_clone(bdev_uuid, sizeof(bdev_uuid), sz, lvs, clone_name,
1314 : : _vbdev_lvol_create_cb, req);
1315 : 18 : spdk_bdev_close(desc);
1316 [ - + ]: 18 : if (rc != 0) {
1317 : 0 : cb_fn(cb_arg, NULL, rc);
1318 : 0 : free(req);
1319 : : }
1320 : : }
1321 : :
1322 : : static void
1323 : 12 : _vbdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
1324 : : {
1325 : 12 : struct spdk_lvol_req *req = cb_arg;
1326 : :
1327 [ - + ]: 12 : if (lvolerrno != 0) {
1328 : 0 : SPDK_ERRLOG("Renaming lvol failed\n");
1329 : : }
1330 : :
1331 : 12 : req->cb_fn(req->cb_arg, lvolerrno);
1332 : 12 : free(req);
1333 : 12 : }
1334 : :
1335 : : void
1336 : 16 : vbdev_lvol_rename(struct spdk_lvol *lvol, const char *new_lvol_name,
1337 : : spdk_lvol_op_complete cb_fn, void *cb_arg)
1338 : : {
1339 : : struct spdk_lvol_req *req;
1340 : : int rc;
1341 : :
1342 : 16 : rc = _vbdev_lvol_change_bdev_alias(lvol, new_lvol_name);
1343 [ + + ]: 16 : if (rc != 0) {
1344 : 4 : SPDK_ERRLOG("renaming lvol to '%s' does not succeed\n", new_lvol_name);
1345 : 4 : cb_fn(cb_arg, rc);
1346 : 4 : return;
1347 : : }
1348 : :
1349 : 12 : req = calloc(1, sizeof(*req));
1350 [ - + ]: 12 : if (req == NULL) {
1351 : 0 : cb_fn(cb_arg, -ENOMEM);
1352 : 0 : return;
1353 : : }
1354 : 12 : req->cb_fn = cb_fn;
1355 : 12 : req->cb_arg = cb_arg;
1356 : :
1357 : 12 : spdk_lvol_rename(lvol, new_lvol_name, _vbdev_lvol_rename_cb, req);
1358 : : }
1359 : :
1360 : : static void
1361 : 22 : _vbdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
1362 : : {
1363 : 22 : struct spdk_lvol_req *req = cb_arg;
1364 : 22 : struct spdk_lvol *lvol = req->lvol;
1365 : : uint64_t total_size;
1366 : :
1367 : : /* change bdev size */
1368 [ + + ]: 22 : if (lvolerrno != 0) {
1369 : 1 : SPDK_ERRLOG("CB function for bdev lvol %s receive error no: %d.\n", lvol->name, lvolerrno);
1370 : 1 : goto finish;
1371 : : }
1372 : :
1373 : 21 : total_size = spdk_blob_get_num_clusters(lvol->blob) *
1374 : 21 : spdk_bs_get_cluster_size(lvol->lvol_store->blobstore);
1375 [ - + - + ]: 21 : assert((total_size % lvol->bdev->blocklen) == 0);
1376 : :
1377 [ - + ]: 21 : lvolerrno = spdk_bdev_notify_blockcnt_change(lvol->bdev, total_size / lvol->bdev->blocklen);
1378 [ + - ]: 21 : if (lvolerrno != 0) {
1379 : 0 : SPDK_ERRLOG("Could not change num blocks for bdev lvol %s with error no: %d.\n",
1380 : : lvol->name, lvolerrno);
1381 : : }
1382 : :
1383 : 21 : finish:
1384 : 22 : req->cb_fn(req->cb_arg, lvolerrno);
1385 : 22 : free(req);
1386 : 22 : }
1387 : :
1388 : : void
1389 : 26 : vbdev_lvol_resize(struct spdk_lvol *lvol, uint64_t sz, spdk_lvol_op_complete cb_fn, void *cb_arg)
1390 : : {
1391 : : struct spdk_lvol_req *req;
1392 : :
1393 [ + + ]: 26 : if (lvol == NULL) {
1394 : 4 : SPDK_ERRLOG("lvol does not exist\n");
1395 : 4 : cb_fn(cb_arg, -EINVAL);
1396 : 4 : return;
1397 : : }
1398 : :
1399 [ - + ]: 22 : assert(lvol->bdev != NULL);
1400 : :
1401 : 22 : req = calloc(1, sizeof(*req));
1402 [ - + ]: 22 : if (req == NULL) {
1403 : 0 : cb_fn(cb_arg, -ENOMEM);
1404 : 0 : return;
1405 : : }
1406 : :
1407 : 22 : req->cb_fn = cb_fn;
1408 : 22 : req->cb_arg = cb_arg;
1409 : 22 : req->sz = sz;
1410 : 22 : req->lvol = lvol;
1411 : :
1412 : 22 : spdk_lvol_resize(req->lvol, req->sz, _vbdev_lvol_resize_cb, req);
1413 : : }
1414 : :
1415 : : static void
1416 : 8 : _vbdev_lvol_set_read_only_cb(void *cb_arg, int lvolerrno)
1417 : : {
1418 : 8 : struct spdk_lvol_req *req = cb_arg;
1419 : 8 : struct spdk_lvol *lvol = req->lvol;
1420 : :
1421 [ - + ]: 8 : if (lvolerrno != 0) {
1422 : 0 : SPDK_ERRLOG("Could not set bdev lvol %s as read only due to error: %d.\n", lvol->name, lvolerrno);
1423 : : }
1424 : :
1425 : 8 : req->cb_fn(req->cb_arg, lvolerrno);
1426 : 8 : free(req);
1427 : 8 : }
1428 : :
1429 : : void
1430 : 8 : vbdev_lvol_set_read_only(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
1431 : : {
1432 : : struct spdk_lvol_req *req;
1433 : :
1434 [ - + ]: 8 : if (lvol == NULL) {
1435 : 0 : SPDK_ERRLOG("lvol does not exist\n");
1436 : 0 : cb_fn(cb_arg, -EINVAL);
1437 : 0 : return;
1438 : : }
1439 : :
1440 [ - + ]: 8 : assert(lvol->bdev != NULL);
1441 : :
1442 : 8 : req = calloc(1, sizeof(*req));
1443 [ - + ]: 8 : if (req == NULL) {
1444 : 0 : cb_fn(cb_arg, -ENOMEM);
1445 : 0 : return;
1446 : : }
1447 : :
1448 : 8 : req->cb_fn = cb_fn;
1449 : 8 : req->cb_arg = cb_arg;
1450 : 8 : req->lvol = lvol;
1451 : :
1452 : 8 : spdk_lvol_set_read_only(lvol, _vbdev_lvol_set_read_only_cb, req);
1453 : : }
1454 : :
1455 : : static int
1456 : 2140 : vbdev_lvs_init(void)
1457 : : {
1458 : 2140 : return 0;
1459 : : }
1460 : :
1461 : : static void vbdev_lvs_fini_start_iter(struct lvol_store_bdev *lvs_bdev);
1462 : :
1463 : : static void
1464 : 11 : vbdev_lvs_fini_start_unload_cb(void *cb_arg, int lvserrno)
1465 : : {
1466 : 11 : struct lvol_store_bdev *lvs_bdev = cb_arg;
1467 : 11 : struct lvol_store_bdev *next_lvs_bdev = vbdev_lvol_store_next(lvs_bdev);
1468 : :
1469 [ - + ]: 11 : if (lvserrno != 0) {
1470 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol, "Lvol store removed with error: %d.\n", lvserrno);
1471 : : }
1472 : :
1473 [ - + ]: 11 : TAILQ_REMOVE(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
1474 : 11 : free(lvs_bdev);
1475 : :
1476 : 11 : vbdev_lvs_fini_start_iter(next_lvs_bdev);
1477 : 11 : }
1478 : :
1479 : : static void
1480 : 2159 : vbdev_lvs_fini_start_iter(struct lvol_store_bdev *lvs_bdev)
1481 : : {
1482 : : struct spdk_lvol_store *lvs;
1483 : :
1484 [ + + ]: 2233 : while (lvs_bdev != NULL) {
1485 : 85 : lvs = lvs_bdev->lvs;
1486 : :
1487 [ + + ]: 85 : if (_vbdev_lvs_are_lvols_closed(lvs)) {
1488 : 11 : spdk_lvs_unload(lvs, vbdev_lvs_fini_start_unload_cb, lvs_bdev);
1489 : 11 : return;
1490 : : }
1491 : 74 : lvs_bdev = vbdev_lvol_store_next(lvs_bdev);
1492 : : }
1493 : :
1494 : 2148 : spdk_bdev_module_fini_start_done();
1495 : : }
1496 : :
1497 : : static void
1498 : 2148 : vbdev_lvs_fini_start(void)
1499 : : {
1500 : 2148 : g_shutdown_started = true;
1501 : 2148 : vbdev_lvs_fini_start_iter(vbdev_lvol_store_first());
1502 : 2148 : }
1503 : :
1504 : : static int
1505 : 2161 : vbdev_lvs_get_ctx_size(void)
1506 : : {
1507 : 2161 : return sizeof(struct vbdev_lvol_io);
1508 : : }
1509 : :
1510 : : static void
1511 : 7307 : _vbdev_lvs_examine_done(struct spdk_lvs_req *req, int lvserrno)
1512 : : {
1513 : 7307 : req->cb_fn(req->cb_arg, lvserrno);
1514 : 7307 : }
1515 : :
1516 : : static void
1517 : 0 : _vbdev_lvs_examine_failed(void *cb_arg, int lvserrno)
1518 : : {
1519 : 0 : struct spdk_lvs_req *req = cb_arg;
1520 : :
1521 : 0 : _vbdev_lvs_examine_done(req, req->lvserrno);
1522 : 0 : }
1523 : :
1524 : : static void
1525 : 136 : _vbdev_lvs_examine_finish(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
1526 : : {
1527 : 136 : struct spdk_lvs_req *req = cb_arg;
1528 : 136 : struct spdk_lvol_store *lvs = req->lvol_store;
1529 : :
1530 [ + + ]: 136 : if (lvolerrno != 0) {
1531 [ + + ]: 8 : TAILQ_REMOVE(&lvs->lvols, lvol, link);
1532 [ + + ]: 8 : if (lvolerrno == -ENOMEM) {
1533 : 4 : TAILQ_INSERT_TAIL(&lvs->retry_open_lvols, lvol, link);
1534 : 4 : return;
1535 : : }
1536 : 4 : SPDK_ERRLOG("Error opening lvol %s\n", lvol->unique_id);
1537 : 4 : lvs->lvol_count--;
1538 : 4 : free(lvol);
1539 : 4 : goto end;
1540 : : }
1541 : :
1542 [ - + ]: 128 : if (_create_lvol_disk(lvol, false)) {
1543 : 0 : SPDK_ERRLOG("Cannot create bdev for lvol %s\n", lvol->unique_id);
1544 : 0 : lvs->lvol_count--;
1545 : 0 : goto end;
1546 : : }
1547 : :
1548 : 128 : lvs->lvols_opened++;
1549 [ + + + - ]: 128 : SPDK_INFOLOG(vbdev_lvol, "Opening lvol %s succeeded\n", lvol->unique_id);
1550 : :
1551 : 128 : end:
1552 [ + + ]: 132 : if (!TAILQ_EMPTY(&lvs->retry_open_lvols)) {
1553 : 4 : lvol = TAILQ_FIRST(&lvs->retry_open_lvols);
1554 [ - + ]: 4 : TAILQ_REMOVE(&lvs->retry_open_lvols, lvol, link);
1555 [ + - ]: 4 : TAILQ_INSERT_HEAD(&lvs->lvols, lvol, link);
1556 : 4 : spdk_lvol_open(lvol, _vbdev_lvs_examine_finish, req);
1557 : 4 : return;
1558 : : }
1559 [ + + ]: 128 : if (lvs->lvols_opened >= lvs->lvol_count) {
1560 [ - + - + ]: 75 : SPDK_INFOLOG(vbdev_lvol, "Opening lvols finished\n");
1561 : 75 : _vbdev_lvs_examine_done(req, 0);
1562 : : }
1563 : : }
1564 : :
1565 : : /* Walks a tree of clones that are no longer degraded to create bdevs. */
1566 : : static int
1567 : 5 : create_esnap_clone_lvol_disks(void *ctx, struct spdk_lvol *lvol)
1568 : : {
1569 : 5 : struct spdk_bdev *bdev = ctx;
1570 : : int rc;
1571 : :
1572 : 5 : rc = _create_lvol_disk(lvol, false);
1573 [ - + ]: 5 : if (rc != 0) {
1574 : 0 : SPDK_ERRLOG("lvol %s: failed to create bdev after esnap hotplug of %s: %d\n",
1575 : : lvol->unique_id, spdk_bdev_get_name(bdev), rc);
1576 : : /* Do not prevent creation of other clones in case of one failure. */
1577 : 0 : return 0;
1578 : : }
1579 : :
1580 : 5 : return spdk_lvol_iter_immediate_clones(lvol, create_esnap_clone_lvol_disks, ctx);
1581 : : }
1582 : :
1583 : : static void
1584 : 3 : vbdev_lvs_hotplug(void *ctx, struct spdk_lvol *lvol, int lvolerrno)
1585 : : {
1586 : 3 : struct spdk_bdev *esnap_clone_bdev = ctx;
1587 : :
1588 [ - + ]: 3 : if (lvolerrno != 0) {
1589 : 0 : SPDK_ERRLOG("lvol %s: during examine of bdev %s: not creating clone bdev due to "
1590 : : "error %d\n", lvol->unique_id, spdk_bdev_get_name(esnap_clone_bdev),
1591 : : lvolerrno);
1592 : 0 : return;
1593 : : }
1594 : 3 : create_esnap_clone_lvol_disks(esnap_clone_bdev, lvol);
1595 : : }
1596 : :
1597 : : static void
1598 : 7908 : vbdev_lvs_examine_config(struct spdk_bdev *bdev)
1599 : : {
1600 : 4964 : char uuid_str[SPDK_UUID_STRING_LEN];
1601 : :
1602 : 7908 : spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid);
1603 : :
1604 [ + + ]: 7908 : if (spdk_lvs_notify_hotplug(uuid_str, sizeof(uuid_str), vbdev_lvs_hotplug, bdev)) {
1605 [ - + - + ]: 7 : SPDK_INFOLOG(vbdev_lvol, "bdev %s: claimed by one ore more esnap clones\n",
1606 : : uuid_str);
1607 : : }
1608 : 7908 : spdk_bdev_module_examine_done(&g_lvol_if);
1609 : 7908 : }
1610 : :
1611 : : static void
1612 : 7300 : _vbdev_lvs_examine_cb(void *arg, struct spdk_lvol_store *lvol_store, int lvserrno)
1613 : : {
1614 : : struct lvol_store_bdev *lvs_bdev;
1615 : 7300 : struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)arg;
1616 : : struct spdk_lvol *lvol, *tmp;
1617 : 7300 : struct spdk_lvs_req *ori_req = req->cb_arg;
1618 : :
1619 [ - + ]: 7300 : if (lvserrno == -EEXIST) {
1620 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol,
1621 : : "Name for lvolstore on device %s conflicts with name for already loaded lvs\n",
1622 : : req->base_bdev->name);
1623 : : /* On error blobstore destroys bs_dev itself */
1624 : 0 : _vbdev_lvs_examine_done(ori_req, lvserrno);
1625 : 0 : goto end;
1626 [ + + ]: 7300 : } else if (lvserrno != 0) {
1627 [ - + - + ]: 7218 : SPDK_INFOLOG(vbdev_lvol, "Lvol store not found on %s\n", req->base_bdev->name);
1628 : : /* On error blobstore destroys bs_dev itself */
1629 : 7218 : _vbdev_lvs_examine_done(ori_req, lvserrno);
1630 : 7218 : goto end;
1631 : : }
1632 : :
1633 : 82 : lvserrno = spdk_bs_bdev_claim(lvol_store->bs_dev, &g_lvol_if);
1634 [ - + ]: 82 : if (lvserrno != 0) {
1635 [ # # # # ]: 0 : SPDK_INFOLOG(vbdev_lvol, "Lvol store base bdev already claimed by another bdev\n");
1636 : 0 : ori_req->lvserrno = lvserrno;
1637 : 0 : spdk_lvs_unload(lvol_store, _vbdev_lvs_examine_failed, ori_req);
1638 : 0 : goto end;
1639 : : }
1640 : :
1641 : 82 : lvs_bdev = calloc(1, sizeof(*lvs_bdev));
1642 [ - + ]: 82 : if (!lvs_bdev) {
1643 : 0 : SPDK_ERRLOG("Cannot alloc memory for lvs_bdev\n");
1644 : 0 : ori_req->lvserrno = lvserrno;
1645 : 0 : spdk_lvs_unload(lvol_store, _vbdev_lvs_examine_failed, ori_req);
1646 : 0 : goto end;
1647 : : }
1648 : :
1649 : 82 : lvs_bdev->lvs = lvol_store;
1650 : 82 : lvs_bdev->bdev = req->base_bdev;
1651 : :
1652 : 82 : TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
1653 : :
1654 [ - + - + ]: 82 : SPDK_INFOLOG(vbdev_lvol, "Lvol store found on %s - begin parsing\n",
1655 : : req->base_bdev->name);
1656 : :
1657 : 82 : lvol_store->lvols_opened = 0;
1658 : :
1659 : 82 : ori_req->lvol_store = lvol_store;
1660 : :
1661 [ + + ]: 82 : if (TAILQ_EMPTY(&lvol_store->lvols)) {
1662 [ - + - + ]: 7 : SPDK_INFOLOG(vbdev_lvol, "Lvol store examination done\n");
1663 : 7 : _vbdev_lvs_examine_done(ori_req, 0);
1664 : : } else {
1665 : : /* Open all lvols */
1666 [ + + ]: 207 : TAILQ_FOREACH_SAFE(lvol, &lvol_store->lvols, link, tmp) {
1667 : 132 : spdk_lvol_open(lvol, _vbdev_lvs_examine_finish, ori_req);
1668 : : }
1669 : : }
1670 : :
1671 : 75 : end:
1672 : 7300 : free(req);
1673 : 7300 : }
1674 : :
1675 : : static void
1676 : 7307 : _vbdev_lvs_examine(struct spdk_bdev *bdev, struct spdk_lvs_req *ori_req,
1677 : : void (*action)(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg))
1678 : : {
1679 : 4568 : struct spdk_bs_dev *bs_dev;
1680 : : struct spdk_lvs_with_handle_req *req;
1681 : : int rc;
1682 : :
1683 : 7307 : req = calloc(1, sizeof(*req));
1684 [ - + ]: 7307 : if (req == NULL) {
1685 : 0 : SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
1686 : 0 : _vbdev_lvs_examine_done(ori_req, -ENOMEM);
1687 : 0 : return;
1688 : : }
1689 : :
1690 : 7307 : rc = spdk_bdev_create_bs_dev_ext(bdev->name, vbdev_lvs_base_bdev_event_cb,
1691 : : NULL, &bs_dev);
1692 [ + + ]: 7307 : if (rc < 0) {
1693 [ - + - + ]: 7 : SPDK_INFOLOG(vbdev_lvol, "Cannot create bs dev on %s\n", bdev->name);
1694 : 7 : _vbdev_lvs_examine_done(ori_req, rc);
1695 : 7 : free(req);
1696 : 7 : return;
1697 : : }
1698 : :
1699 : 7300 : req->base_bdev = bdev;
1700 : 7300 : req->cb_arg = ori_req;
1701 : :
1702 : 7300 : action(bs_dev, _vbdev_lvs_examine_cb, req);
1703 : : }
1704 : :
1705 : : static void
1706 : 7307 : vbdev_lvs_examine_done(void *arg, int lvserrno)
1707 : : {
1708 : 7307 : struct spdk_lvs_req *req = arg;
1709 : :
1710 : 7307 : spdk_bdev_module_examine_done(&g_lvol_if);
1711 : 7307 : free(req);
1712 : 7307 : }
1713 : :
1714 : : static void
1715 : 7300 : vbdev_lvs_load(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
1716 : : {
1717 : 4561 : struct spdk_lvs_opts lvs_opts;
1718 : :
1719 : 7300 : spdk_lvs_opts_init(&lvs_opts);
1720 : 7300 : lvs_opts.esnap_bs_dev_create = vbdev_lvol_esnap_dev_create;
1721 : 7300 : spdk_lvs_load_ext(bs_dev, &lvs_opts, cb_fn, cb_arg);
1722 : 7300 : }
1723 : :
1724 : : static void
1725 : 7662 : vbdev_lvs_examine_disk(struct spdk_bdev *bdev)
1726 : : {
1727 : : struct spdk_lvs_req *req;
1728 : :
1729 [ + + ]: 7662 : if (spdk_bdev_get_md_size(bdev) != 0) {
1730 [ - + - + ]: 355 : SPDK_INFOLOG(vbdev_lvol, "Cannot create bs dev on %s\n which is formatted with metadata",
1731 : : bdev->name);
1732 : 355 : spdk_bdev_module_examine_done(&g_lvol_if);
1733 : 355 : return;
1734 : : }
1735 : :
1736 : 7307 : req = calloc(1, sizeof(*req));
1737 [ - + ]: 7307 : if (req == NULL) {
1738 : 0 : SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
1739 : 0 : spdk_bdev_module_examine_done(&g_lvol_if);
1740 : 0 : return;
1741 : : }
1742 : :
1743 : 7307 : req->cb_fn = vbdev_lvs_examine_done;
1744 : 7307 : req->cb_arg = req;
1745 : :
1746 : 7307 : _vbdev_lvs_examine(bdev, req, vbdev_lvs_load);
1747 : : }
1748 : :
1749 : : struct spdk_lvol *
1750 : 324 : vbdev_lvol_get_from_bdev(struct spdk_bdev *bdev)
1751 : : {
1752 [ + - + + ]: 324 : if (!bdev || bdev->module != &g_lvol_if) {
1753 : 8 : return NULL;
1754 : : }
1755 : :
1756 [ - + ]: 316 : if (bdev->ctxt == NULL) {
1757 : 0 : SPDK_ERRLOG("No lvol ctx assigned to bdev %s\n", bdev->name);
1758 : 0 : return NULL;
1759 : : }
1760 : :
1761 : 316 : return (struct spdk_lvol *)bdev->ctxt;
1762 : : }
1763 : :
1764 : : /* Begin degraded blobstore device */
1765 : :
1766 : : /*
1767 : : * When an external snapshot is missing, an instance of bs_dev_degraded is used as the blob's
1768 : : * back_bs_dev. No bdev is registered, so there should be no IO nor requests for channels. The main
1769 : : * purposes of this device are to prevent blobstore from hitting fatal runtime errors and to
1770 : : * indicate that the blob is degraded via the is_degraded() callback.
1771 : : */
1772 : :
1773 : : static void
1774 : 0 : bs_dev_degraded_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
1775 : : uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
1776 : : {
1777 : 0 : assert(false);
1778 : : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EIO);
1779 : : }
1780 : :
1781 : : static void
1782 : 0 : bs_dev_degraded_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
1783 : : struct iovec *iov, int iovcnt, uint64_t lba, uint32_t lba_count,
1784 : : struct spdk_bs_dev_cb_args *cb_args)
1785 : : {
1786 : 0 : assert(false);
1787 : : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EIO);
1788 : : }
1789 : :
1790 : : static void
1791 : 0 : bs_dev_degraded_readv_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
1792 : : struct iovec *iov, int iovcnt, uint64_t lba, uint32_t lba_count,
1793 : : struct spdk_bs_dev_cb_args *cb_args,
1794 : : struct spdk_blob_ext_io_opts *io_opts)
1795 : : {
1796 : 0 : assert(false);
1797 : : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EIO);
1798 : : }
1799 : :
1800 : : static bool
1801 : 0 : bs_dev_degraded_is_zeroes(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
1802 : : {
1803 : 0 : assert(false);
1804 : : return false;
1805 : : }
1806 : :
1807 : : static bool
1808 : 0 : bs_dev_degraded_is_range_valid(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
1809 : : {
1810 : 0 : assert(false);
1811 : : return false;
1812 : : }
1813 : :
1814 : : static struct spdk_io_channel *
1815 : 0 : bs_dev_degraded_create_channel(struct spdk_bs_dev *bs_dev)
1816 : : {
1817 : 0 : assert(false);
1818 : : return NULL;
1819 : : }
1820 : :
1821 : : static void
1822 : 0 : bs_dev_degraded_destroy_channel(struct spdk_bs_dev *bs_dev, struct spdk_io_channel *channel)
1823 : : {
1824 : 0 : assert(false);
1825 : : }
1826 : :
1827 : : static void
1828 : 18 : bs_dev_degraded_destroy(struct spdk_bs_dev *bs_dev)
1829 : : {
1830 : 18 : }
1831 : :
1832 : : static bool
1833 : 28 : bs_dev_degraded_is_degraded(struct spdk_bs_dev *bs_dev)
1834 : : {
1835 : 28 : return true;
1836 : : }
1837 : :
1838 : : static struct spdk_bs_dev bs_dev_degraded = {
1839 : : .create_channel = bs_dev_degraded_create_channel,
1840 : : .destroy_channel = bs_dev_degraded_destroy_channel,
1841 : : .destroy = bs_dev_degraded_destroy,
1842 : : .read = bs_dev_degraded_read,
1843 : : .readv = bs_dev_degraded_readv,
1844 : : .readv_ext = bs_dev_degraded_readv_ext,
1845 : : .is_zeroes = bs_dev_degraded_is_zeroes,
1846 : : .is_range_valid = bs_dev_degraded_is_range_valid,
1847 : : .is_degraded = bs_dev_degraded_is_degraded,
1848 : : /* Make the device as large as possible without risk of uint64 overflow. */
1849 : : .blockcnt = UINT64_MAX / 512,
1850 : : /* Prevent divide by zero errors calculating LBAs that will never be read. */
1851 : : .blocklen = 512,
1852 : : };
1853 : :
1854 : : /* End degraded blobstore device */
1855 : :
1856 : : /* Begin external snapshot support */
1857 : :
1858 : : static void
1859 : 3 : vbdev_lvol_esnap_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
1860 : : void *event_ctx)
1861 : : {
1862 : 3 : SPDK_NOTICELOG("bdev name (%s) received unsupported event type %d\n",
1863 : : spdk_bdev_get_name(bdev), type);
1864 : 3 : }
1865 : :
1866 : : int
1867 : 64 : vbdev_lvol_esnap_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
1868 : : const void *esnap_id, uint32_t id_len,
1869 : : struct spdk_bs_dev **_bs_dev)
1870 : : {
1871 : 64 : struct spdk_lvol_store *lvs = bs_ctx;
1872 : 64 : struct spdk_lvol *lvol = blob_ctx;
1873 : 64 : struct spdk_bs_dev *bs_dev = NULL;
1874 : 64 : struct spdk_uuid uuid;
1875 : : int rc;
1876 : 64 : char uuid_str[SPDK_UUID_STRING_LEN] = { 0 };
1877 : :
1878 [ + + ]: 64 : if (esnap_id == NULL) {
1879 : 4 : SPDK_ERRLOG("lvol %s: NULL esnap ID\n", lvol->unique_id);
1880 : 4 : return -EINVAL;
1881 : : }
1882 : :
1883 : : /* Guard against arbitrary names and unterminated UUID strings */
1884 [ + + ]: 60 : if (id_len != SPDK_UUID_STRING_LEN) {
1885 : 4 : SPDK_ERRLOG("lvol %s: Invalid esnap ID length (%u)\n", lvol->unique_id, id_len);
1886 : 4 : return -EINVAL;
1887 : : }
1888 : :
1889 [ + + ]: 56 : if (spdk_uuid_parse(&uuid, esnap_id)) {
1890 : 4 : SPDK_ERRLOG("lvol %s: Invalid esnap ID: not a UUID\n", lvol->unique_id);
1891 : 4 : return -EINVAL;
1892 : : }
1893 : :
1894 : : /* Format the UUID the same as it is in the bdev names tree. */
1895 : 52 : spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &uuid);
1896 [ - + - + ]: 52 : if (strcmp(uuid_str, esnap_id) != 0) {
1897 : 0 : SPDK_WARNLOG("lvol %s: esnap_id '%*s' does not match parsed uuid '%s'\n",
1898 : : lvol->unique_id, SPDK_UUID_STRING_LEN, (const char *)esnap_id,
1899 : : uuid_str);
1900 : 0 : assert(false);
1901 : : }
1902 : :
1903 : 52 : rc = spdk_bdev_create_bs_dev(uuid_str, false, NULL, 0,
1904 : : vbdev_lvol_esnap_bdev_event_cb, NULL, &bs_dev);
1905 [ + + ]: 52 : if (rc != 0) {
1906 : 18 : goto fail;
1907 : : }
1908 : :
1909 : 34 : rc = spdk_bs_bdev_claim(bs_dev, &g_lvol_if);
1910 [ - + ]: 34 : if (rc != 0) {
1911 : 0 : SPDK_ERRLOG("lvol %s: unable to claim esnap bdev '%s': %d\n", lvol->unique_id,
1912 : : uuid_str, rc);
1913 : 0 : bs_dev->destroy(bs_dev);
1914 : 0 : goto fail;
1915 : : }
1916 : :
1917 : 34 : *_bs_dev = bs_dev;
1918 : 34 : return 0;
1919 : :
1920 : 18 : fail:
1921 : : /* Unable to open or claim the bdev. This lvol is degraded. */
1922 : 18 : bs_dev = &bs_dev_degraded;
1923 : 18 : SPDK_NOTICELOG("lvol %s: bdev %s not available: lvol is degraded\n", lvol->unique_id,
1924 : : uuid_str);
1925 : :
1926 : : /*
1927 : : * Be sure not to call spdk_lvs_missing_add() on an lvol that is already degraded. This can
1928 : : * lead to a cycle in the degraded_lvols tailq.
1929 : : */
1930 [ + + ]: 18 : if (lvol->degraded_set == NULL) {
1931 : 15 : rc = spdk_lvs_esnap_missing_add(lvs, lvol, uuid_str, sizeof(uuid_str));
1932 [ + + ]: 15 : if (rc != 0) {
1933 : 8 : SPDK_NOTICELOG("lvol %s: unable to register missing esnap device %s: "
1934 : : "it will not be hotplugged if added later\n",
1935 : : lvol->unique_id, uuid_str);
1936 : : }
1937 : : }
1938 : :
1939 : 18 : *_bs_dev = bs_dev;
1940 : 18 : return 0;
1941 : : }
1942 : :
1943 : : /* End external snapshot support */
1944 : :
1945 : : static void
1946 : 0 : _vbdev_lvol_shallow_copy_base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
1947 : : void *event_ctx)
1948 : : {
1949 : 0 : }
1950 : :
1951 : : static void
1952 : 5 : _vbdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
1953 : : {
1954 : 5 : struct spdk_lvol_copy_req *req = cb_arg;
1955 : 5 : struct spdk_lvol *lvol = req->lvol;
1956 : :
1957 [ - + ]: 5 : if (lvolerrno != 0) {
1958 : 0 : SPDK_ERRLOG("Could not make a shallow copy of lvol %s due to error: %d\n",
1959 : : lvol->name, lvolerrno);
1960 : : }
1961 : :
1962 : 5 : req->ext_dev->destroy(req->ext_dev);
1963 : 5 : req->cb_fn(req->cb_arg, lvolerrno);
1964 : 5 : free(req);
1965 : 5 : }
1966 : :
1967 : : int
1968 : 13 : vbdev_lvol_shallow_copy(struct spdk_lvol *lvol, const char *bdev_name,
1969 : : spdk_blob_shallow_copy_status status_cb_fn, void *status_cb_arg,
1970 : : spdk_lvol_op_complete cb_fn, void *cb_arg)
1971 : : {
1972 : 13 : struct spdk_bs_dev *ext_dev;
1973 : : struct spdk_lvol_copy_req *req;
1974 : : int rc;
1975 : :
1976 [ + + ]: 13 : if (lvol == NULL) {
1977 : 4 : SPDK_ERRLOG("lvol must not be NULL\n");
1978 : 4 : return -EINVAL;
1979 : : }
1980 : :
1981 [ + + ]: 9 : if (bdev_name == NULL) {
1982 : 4 : SPDK_ERRLOG("lvol %s, bdev name must not be NULL\n", lvol->name);
1983 : 4 : return -EINVAL;
1984 : : }
1985 : :
1986 [ - + ]: 5 : assert(lvol->bdev != NULL);
1987 : :
1988 : 5 : req = calloc(1, sizeof(*req));
1989 [ - + ]: 5 : if (req == NULL) {
1990 : 0 : SPDK_ERRLOG("lvol %s, cannot alloc memory for lvol copy request\n", lvol->name);
1991 : 0 : return -ENOMEM;
1992 : : }
1993 : :
1994 : 5 : rc = spdk_bdev_create_bs_dev_ext(bdev_name, _vbdev_lvol_shallow_copy_base_bdev_event_cb,
1995 : : NULL, &ext_dev);
1996 [ - + ]: 5 : if (rc < 0) {
1997 : 0 : SPDK_ERRLOG("lvol %s, cannot create blobstore block device from bdev %s\n", lvol->name, bdev_name);
1998 : 0 : free(req);
1999 : 0 : return rc;
2000 : : }
2001 : :
2002 : 5 : rc = spdk_bs_bdev_claim(ext_dev, &g_lvol_if);
2003 [ - + ]: 5 : if (rc != 0) {
2004 : 0 : SPDK_ERRLOG("lvol %s, unable to claim bdev %s, error %d\n", lvol->name, bdev_name, rc);
2005 : 0 : ext_dev->destroy(ext_dev);
2006 : 0 : free(req);
2007 : 0 : return rc;
2008 : : }
2009 : :
2010 : 5 : req->cb_fn = cb_fn;
2011 : 5 : req->cb_arg = cb_arg;
2012 : 5 : req->lvol = lvol;
2013 : 5 : req->ext_dev = ext_dev;
2014 : :
2015 : 5 : rc = spdk_lvol_shallow_copy(lvol, ext_dev, status_cb_fn, status_cb_arg, _vbdev_lvol_shallow_copy_cb,
2016 : : req);
2017 : :
2018 [ - + ]: 5 : if (rc < 0) {
2019 : 0 : ext_dev->destroy(ext_dev);
2020 : 0 : free(req);
2021 : : }
2022 : :
2023 : 5 : return rc;
2024 : : }
2025 : :
2026 : : void
2027 : 18 : vbdev_lvol_set_external_parent(struct spdk_lvol *lvol, const char *esnap_name,
2028 : : spdk_lvol_op_complete cb_fn, void *cb_arg)
2029 : : {
2030 : 18 : struct spdk_bdev_desc *desc;
2031 : : struct spdk_bdev *bdev;
2032 : 18 : char bdev_uuid[SPDK_UUID_STRING_LEN];
2033 : : int rc;
2034 : :
2035 : 18 : rc = spdk_bdev_open_ext(esnap_name, false, ignore_bdev_event_cb, NULL, &desc);
2036 [ + + ]: 18 : if (rc != 0) {
2037 : 4 : SPDK_ERRLOG("bdev '%s' could not be opened: error %d\n", esnap_name, rc);
2038 : 4 : cb_fn(cb_arg, -ENODEV);
2039 : 4 : return;
2040 : : }
2041 : 14 : bdev = spdk_bdev_desc_get_bdev(desc);
2042 : :
2043 : 14 : rc = spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), spdk_bdev_get_uuid(bdev));
2044 [ - + ]: 14 : if (rc != 0) {
2045 : 0 : spdk_bdev_close(desc);
2046 : 0 : SPDK_ERRLOG("bdev %s: unable to parse UUID\n", esnap_name);
2047 : 0 : assert(false);
2048 : : cb_fn(cb_arg, -ENODEV);
2049 : : return;
2050 : : }
2051 : :
2052 : : /*
2053 : : * If lvol store is not loaded from disk, and so vbdev_lvs_load is not called, these
2054 : : * assignments are necessary to let vbdev_lvol_esnap_dev_create be called.
2055 : : */
2056 : 14 : lvol->lvol_store->load_esnaps = true;
2057 : 14 : lvol->lvol_store->esnap_bs_dev_create = vbdev_lvol_esnap_dev_create;
2058 : :
2059 : 14 : spdk_lvol_set_external_parent(lvol, bdev_uuid, sizeof(bdev_uuid), cb_fn, cb_arg);
2060 : :
2061 : 14 : spdk_bdev_close(desc);
2062 : : }
2063 : :
2064 : 2334 : SPDK_LOG_REGISTER_COMPONENT(vbdev_lvol)
|