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