Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2018 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <ocf/ocf.h>
7 : : #include <ocf/ocf_types.h>
8 : : #include <ocf/ocf_mngt.h>
9 : :
10 : : #include "ctx.h"
11 : : #include "data.h"
12 : : #include "volume.h"
13 : : #include "utils.h"
14 : : #include "vbdev_ocf.h"
15 : :
16 : : #include "spdk/bdev_module.h"
17 : : #include "spdk/thread.h"
18 : : #include "spdk/string.h"
19 : : #include "spdk/log.h"
20 : : #include "spdk/cpuset.h"
21 : :
22 : : /* This namespace UUID was generated using uuid_generate() method. */
23 : : #define BDEV_OCF_NAMESPACE_UUID "f92b7f49-f6c0-44c8-bd23-3205e8c3b6ad"
24 : :
25 : : static struct spdk_bdev_module ocf_if;
26 : :
27 : : static TAILQ_HEAD(, vbdev_ocf) g_ocf_vbdev_head
28 : : = TAILQ_HEAD_INITIALIZER(g_ocf_vbdev_head);
29 : :
30 : : static TAILQ_HEAD(, examining_bdev) g_ocf_examining_bdevs_head
31 : : = TAILQ_HEAD_INITIALIZER(g_ocf_examining_bdevs_head);
32 : :
33 : : static bool g_fini_started = false;
34 : :
35 : : /* Structure for keeping list of bdevs that are claimed but not used yet */
36 : : struct examining_bdev {
37 : : struct spdk_bdev *bdev;
38 : : TAILQ_ENTRY(examining_bdev) tailq;
39 : : };
40 : :
41 : : /* Add bdev to list of claimed */
42 : : static void
43 : 127 : examine_start(struct spdk_bdev *bdev)
44 : : {
45 : 127 : struct examining_bdev *entry = malloc(sizeof(*entry));
46 : :
47 [ - + ]: 127 : assert(entry);
48 : 127 : entry->bdev = bdev;
49 : 127 : TAILQ_INSERT_TAIL(&g_ocf_examining_bdevs_head, entry, tailq);
50 : 127 : }
51 : :
52 : : /* Find bdev on list of claimed bdevs, then remove it,
53 : : * if it was the last one on list then report examine done */
54 : : static void
55 : 127 : examine_done(int status, struct vbdev_ocf *vbdev, void *cb_arg)
56 : : {
57 : 127 : struct spdk_bdev *bdev = cb_arg;
58 : 127 : struct examining_bdev *entry, *safe, *found = NULL;
59 : :
60 [ + + ]: 308 : TAILQ_FOREACH_SAFE(entry, &g_ocf_examining_bdevs_head, tailq, safe) {
61 [ + + ]: 183 : if (entry->bdev == bdev) {
62 [ + + ]: 129 : if (found) {
63 : 2 : goto remove;
64 : : } else {
65 : 127 : found = entry;
66 : : }
67 : : }
68 : : }
69 : :
70 [ - + ]: 125 : assert(found);
71 : 125 : spdk_bdev_module_examine_done(&ocf_if);
72 : :
73 : 127 : remove:
74 [ + + ]: 127 : TAILQ_REMOVE(&g_ocf_examining_bdevs_head, found, tailq);
75 : 127 : free(found);
76 : 127 : }
77 : :
78 : : /* Free allocated strings and structure itself
79 : : * Used at shutdown only */
80 : : static void
81 : 30 : free_vbdev(struct vbdev_ocf *vbdev)
82 : : {
83 [ - + ]: 30 : if (!vbdev) {
84 : 0 : return;
85 : : }
86 : :
87 : 30 : free(vbdev->name);
88 : 30 : free(vbdev->cache.name);
89 : 30 : free(vbdev->core.name);
90 : 30 : free(vbdev);
91 : : }
92 : :
93 : : /* Get existing cache base
94 : : * that is attached to other vbdev */
95 : : static struct vbdev_ocf_base *
96 : 56 : get_other_cache_base(struct vbdev_ocf_base *base)
97 : : {
98 : : struct vbdev_ocf *vbdev;
99 : :
100 [ + + ]: 172 : TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
101 [ + + - + : 132 : if (&vbdev->cache == base || !vbdev->cache.attached) {
+ + ]
102 : 104 : continue;
103 : : }
104 [ - + - + : 28 : if (!strcmp(vbdev->cache.name, base->name)) {
+ + ]
105 : 16 : return &vbdev->cache;
106 : : }
107 : : }
108 : :
109 : 40 : return NULL;
110 : : }
111 : :
112 : : static bool
113 : 112 : is_ocf_cache_running(struct vbdev_ocf *vbdev)
114 : : {
115 [ - + + + : 112 : if (vbdev->cache.attached && vbdev->ocf_cache) {
+ + ]
116 : 64 : return ocf_cache_is_running(vbdev->ocf_cache);
117 : : }
118 : 48 : return false;
119 : : }
120 : :
121 : : static bool
122 : 4 : is_ocf_cache_initializing(struct vbdev_ocf *vbdev)
123 : : {
124 [ - + + - : 4 : if (vbdev->cache.attached && vbdev->ocf_cache) {
+ + ]
125 : 1 : return ocf_cache_is_initializing(vbdev->ocf_cache);
126 : : }
127 : 3 : return false;
128 : : }
129 : :
130 : : /* Get existing OCF cache instance
131 : : * that is started by other vbdev */
132 : : static ocf_cache_t
133 : 34 : get_other_cache_instance(struct vbdev_ocf *vbdev)
134 : : {
135 : : struct vbdev_ocf *cmp;
136 : :
137 [ + + ]: 104 : TAILQ_FOREACH(cmp, &g_ocf_vbdev_head, tailq) {
138 [ - + + + : 77 : if (cmp->state.doing_finish || cmp == vbdev) {
+ + ]
139 : 61 : continue;
140 : : }
141 [ - + - + : 16 : if (strcmp(cmp->cache.name, vbdev->cache.name)) {
+ + ]
142 : 6 : continue;
143 : : }
144 [ + + + + ]: 10 : if (is_ocf_cache_running(cmp) || is_ocf_cache_initializing(cmp)) {
145 : 7 : return cmp->ocf_cache;
146 : : }
147 : : }
148 : :
149 : 27 : return NULL;
150 : : }
151 : :
152 : : static void
153 : 0 : _remove_base_bdev(void *ctx)
154 : : {
155 : 0 : struct spdk_bdev_desc *desc = ctx;
156 : :
157 : 0 : spdk_bdev_close(desc);
158 : 0 : }
159 : :
160 : : /* Close and unclaim base bdev */
161 : : static void
162 : 55 : remove_base_bdev(struct vbdev_ocf_base *base)
163 : : {
164 [ - + + + ]: 55 : if (base->attached) {
165 [ + - ]: 47 : if (base->management_channel) {
166 : 47 : spdk_put_io_channel(base->management_channel);
167 : : }
168 : :
169 : 47 : spdk_bdev_module_release_bdev(base->bdev);
170 : : /* Close the underlying bdev on its same opened thread. */
171 [ + + - + ]: 47 : if (base->thread && base->thread != spdk_get_thread()) {
172 : 0 : spdk_thread_send_msg(base->thread, _remove_base_bdev, base->desc);
173 : : } else {
174 : 47 : spdk_bdev_close(base->desc);
175 : : }
176 : 47 : base->attached = false;
177 : : }
178 : 55 : }
179 : :
180 : : /* Finish unregister operation */
181 : : static void
182 : 25 : unregister_finish(struct vbdev_ocf *vbdev)
183 : : {
184 : 25 : spdk_bdev_destruct_done(&vbdev->exp_bdev, vbdev->state.stop_status);
185 : :
186 [ + - ]: 25 : if (vbdev->ocf_cache) {
187 : 25 : ocf_mngt_cache_put(vbdev->ocf_cache);
188 : : }
189 : :
190 [ + - ]: 25 : if (vbdev->cache_ctx) {
191 : 25 : vbdev_ocf_cache_ctx_put(vbdev->cache_ctx);
192 : : }
193 : 25 : vbdev_ocf_mngt_continue(vbdev, 0);
194 : 25 : }
195 : :
196 : : static void
197 : 27 : close_core_bdev(struct vbdev_ocf *vbdev)
198 : : {
199 : 27 : remove_base_bdev(&vbdev->core);
200 : 27 : vbdev_ocf_mngt_continue(vbdev, 0);
201 : 27 : }
202 : :
203 : : static void
204 : 7 : remove_core_cmpl(void *priv, int error)
205 : : {
206 : 7 : struct vbdev_ocf *vbdev = priv;
207 : :
208 : 7 : ocf_mngt_cache_unlock(vbdev->ocf_cache);
209 : 7 : vbdev_ocf_mngt_continue(vbdev, error);
210 : 7 : }
211 : :
212 : : /* Try to lock cache, then remove core */
213 : : static void
214 : 7 : remove_core_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
215 : : {
216 : 7 : struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
217 : :
218 [ - + ]: 7 : if (error) {
219 : 0 : SPDK_ERRLOG("Error %d, can not lock cache instance %s\n",
220 : : error, vbdev->name);
221 : 0 : vbdev_ocf_mngt_continue(vbdev, error);
222 : 0 : return;
223 : : }
224 : :
225 : 7 : ocf_mngt_cache_remove_core(vbdev->ocf_core, remove_core_cmpl, vbdev);
226 : : }
227 : :
228 : : /* Detach core base */
229 : : static void
230 : 27 : detach_core(struct vbdev_ocf *vbdev)
231 : : {
232 [ + + ]: 27 : if (is_ocf_cache_running(vbdev)) {
233 : 7 : ocf_mngt_cache_lock(vbdev->ocf_cache, remove_core_cache_lock_cmpl, vbdev);
234 : : } else {
235 : 20 : vbdev_ocf_mngt_continue(vbdev, 0);
236 : : }
237 : 27 : }
238 : :
239 : : static void
240 : 28 : close_cache_bdev(struct vbdev_ocf *vbdev)
241 : : {
242 : 28 : remove_base_bdev(&vbdev->cache);
243 : 28 : vbdev_ocf_mngt_continue(vbdev, 0);
244 : 28 : }
245 : :
246 : : /* Detach cache base */
247 : : static void
248 : 28 : detach_cache(struct vbdev_ocf *vbdev)
249 : : {
250 : 28 : vbdev->state.stop_status = vbdev->mngt_ctx.status;
251 : :
252 : : /* If some other vbdev references this cache bdev,
253 : : * we detach this only by changing the flag, without actual close */
254 [ + + ]: 28 : if (get_other_cache_base(&vbdev->cache)) {
255 : 8 : vbdev->cache.attached = false;
256 : : }
257 : :
258 : 28 : vbdev_ocf_mngt_continue(vbdev, 0);
259 : 28 : }
260 : :
261 : : static void
262 : 19 : stop_vbdev_cmpl(ocf_cache_t cache, void *priv, int error)
263 : : {
264 : 19 : struct vbdev_ocf *vbdev = priv;
265 : :
266 : 19 : vbdev_ocf_queue_put(vbdev->cache_ctx->mngt_queue);
267 : 19 : ocf_mngt_cache_unlock(cache);
268 : :
269 : 19 : vbdev_ocf_mngt_continue(vbdev, error);
270 : 19 : }
271 : :
272 : : /* Try to lock cache, then stop it */
273 : : static void
274 : 19 : stop_vbdev_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
275 : : {
276 : 19 : struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
277 : :
278 [ - + ]: 19 : if (error) {
279 : 0 : SPDK_ERRLOG("Error %d, can not lock cache instance %s\n",
280 : : error, vbdev->name);
281 : 0 : vbdev_ocf_mngt_continue(vbdev, error);
282 : 0 : return;
283 : : }
284 : :
285 : 19 : ocf_mngt_cache_stop(vbdev->ocf_cache, stop_vbdev_cmpl, vbdev);
286 : : }
287 : :
288 : : /* Stop OCF cache object
289 : : * vbdev_ocf is not operational after this */
290 : : static void
291 : 25 : stop_vbdev(struct vbdev_ocf *vbdev)
292 : : {
293 [ + + ]: 25 : if (!is_ocf_cache_running(vbdev)) {
294 : 5 : vbdev_ocf_mngt_continue(vbdev, 0);
295 : 5 : return;
296 : : }
297 : :
298 [ - + + + : 20 : if (!g_fini_started && get_other_cache_instance(vbdev)) {
+ + ]
299 : 1 : SPDK_NOTICELOG("Not stopping cache instance '%s'"
300 : : " because it is referenced by other OCF bdev\n",
301 : : vbdev->cache.name);
302 : 1 : vbdev_ocf_mngt_continue(vbdev, 0);
303 : 1 : return;
304 : : }
305 : :
306 : 19 : ocf_mngt_cache_lock(vbdev->ocf_cache, stop_vbdev_cache_lock_cmpl, vbdev);
307 : : }
308 : :
309 : : static void
310 : 21 : flush_vbdev_cmpl(ocf_cache_t cache, void *priv, int error)
311 : : {
312 : 21 : struct vbdev_ocf *vbdev = priv;
313 : :
314 : 21 : ocf_mngt_cache_unlock(cache);
315 : 21 : vbdev_ocf_mngt_continue(vbdev, error);
316 : 21 : }
317 : :
318 : : static void
319 : 21 : flush_vbdev_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
320 : : {
321 : 21 : struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
322 : :
323 [ - + ]: 21 : if (error) {
324 : 0 : SPDK_ERRLOG("Error %d, can not lock cache instance %s\n",
325 : : error, vbdev->name);
326 : 0 : vbdev_ocf_mngt_continue(vbdev, error);
327 : 0 : return;
328 : : }
329 : :
330 : 21 : ocf_mngt_cache_flush(vbdev->ocf_cache, flush_vbdev_cmpl, vbdev);
331 : : }
332 : :
333 : : static void
334 : 25 : flush_vbdev(struct vbdev_ocf *vbdev)
335 : : {
336 [ + + ]: 25 : if (!is_ocf_cache_running(vbdev)) {
337 : 4 : vbdev_ocf_mngt_continue(vbdev, -EINVAL);
338 : 4 : return;
339 : : }
340 : :
341 : 21 : ocf_mngt_cache_lock(vbdev->ocf_cache, flush_vbdev_cache_lock_cmpl, vbdev);
342 : : }
343 : :
344 : : /* Procedures called during dirty unregister */
345 : : vbdev_ocf_mngt_fn unregister_path_dirty[] = {
346 : : flush_vbdev,
347 : : stop_vbdev,
348 : : detach_cache,
349 : : close_cache_bdev,
350 : : detach_core,
351 : : close_core_bdev,
352 : : unregister_finish,
353 : : NULL
354 : : };
355 : :
356 : : /* Procedures called during clean unregister */
357 : : vbdev_ocf_mngt_fn unregister_path_clean[] = {
358 : : flush_vbdev,
359 : : detach_core,
360 : : close_core_bdev,
361 : : stop_vbdev,
362 : : detach_cache,
363 : : close_cache_bdev,
364 : : unregister_finish,
365 : : NULL
366 : : };
367 : :
368 : : /* Start asynchronous management operation using unregister_path */
369 : : static void
370 : 25 : unregister_cb(void *opaque)
371 : : {
372 : 25 : struct vbdev_ocf *vbdev = opaque;
373 : : vbdev_ocf_mngt_fn *unregister_path;
374 : : int rc;
375 : :
376 [ - + ]: 25 : unregister_path = vbdev->state.doing_clean_delete ?
377 [ + + ]: 25 : unregister_path_clean : unregister_path_dirty;
378 : :
379 : 25 : rc = vbdev_ocf_mngt_start(vbdev, unregister_path, NULL, NULL);
380 [ - + ]: 25 : if (rc) {
381 : 0 : SPDK_ERRLOG("Unable to unregister OCF bdev: %d\n", rc);
382 : 0 : spdk_bdev_destruct_done(&vbdev->exp_bdev, rc);
383 : : }
384 : 25 : }
385 : :
386 : : /* Clean remove case - remove core and then cache, this order
387 : : * will remove instance permanently */
388 : : static void
389 : 2 : _vbdev_ocf_destruct_clean(struct vbdev_ocf *vbdev)
390 : : {
391 [ - + + + ]: 2 : if (vbdev->core.attached) {
392 : 1 : detach_core(vbdev);
393 : 1 : close_core_bdev(vbdev);
394 : : }
395 : :
396 [ - + + + ]: 2 : if (vbdev->cache.attached) {
397 : 1 : detach_cache(vbdev);
398 : 1 : close_cache_bdev(vbdev);
399 : : }
400 : 2 : }
401 : :
402 : : /* Dirty shutdown/hot remove case - remove cache and then core, this order
403 : : * will allow us to recover this instance in the future */
404 : : static void
405 : 3 : _vbdev_ocf_destruct_dirty(struct vbdev_ocf *vbdev)
406 : : {
407 [ - + + + ]: 3 : if (vbdev->cache.attached) {
408 : 2 : detach_cache(vbdev);
409 : 2 : close_cache_bdev(vbdev);
410 : : }
411 : :
412 [ - + + + ]: 3 : if (vbdev->core.attached) {
413 : 1 : detach_core(vbdev);
414 : 1 : close_core_bdev(vbdev);
415 : : }
416 : 3 : }
417 : :
418 : : /* Unregister io device with callback to unregister_cb
419 : : * This function is called during spdk_bdev_unregister */
420 : : static int
421 : 30 : vbdev_ocf_destruct(void *opaque)
422 : : {
423 : 30 : struct vbdev_ocf *vbdev = opaque;
424 : :
425 [ - + - + ]: 30 : if (vbdev->state.doing_finish) {
426 : 0 : return -EALREADY;
427 : : }
428 : :
429 [ - + + + : 30 : if (vbdev->state.starting && !vbdev->state.started) {
- + - + ]
430 : : /* Prevent before detach cache/core during register path of
431 : : this bdev */
432 : 0 : return -EBUSY;
433 : : }
434 : :
435 : 30 : vbdev->state.doing_finish = true;
436 : :
437 [ - + + + ]: 30 : if (vbdev->state.started) {
438 : 25 : spdk_io_device_unregister(vbdev, unregister_cb);
439 : : /* Return 1 because unregister is delayed */
440 : 25 : return 1;
441 : : }
442 : :
443 [ - + + + ]: 5 : if (vbdev->state.doing_clean_delete) {
444 : 2 : _vbdev_ocf_destruct_clean(vbdev);
445 : : } else {
446 : 3 : _vbdev_ocf_destruct_dirty(vbdev);
447 : : }
448 : :
449 : 5 : return 0;
450 : : }
451 : :
452 : : /* Stop OCF cache and unregister SPDK bdev */
453 : : int
454 : 15 : vbdev_ocf_delete(struct vbdev_ocf *vbdev, void (*cb)(void *, int), void *cb_arg)
455 : : {
456 : 15 : int rc = 0;
457 : :
458 [ - + + + ]: 15 : if (vbdev->state.started) {
459 : 10 : spdk_bdev_unregister(&vbdev->exp_bdev, cb, cb_arg);
460 : : } else {
461 : 5 : rc = vbdev_ocf_destruct(vbdev);
462 [ + - + + ]: 5 : if (rc == 0 && cb) {
463 : 2 : cb(cb_arg, 0);
464 : : }
465 : : }
466 : :
467 : 15 : return rc;
468 : : }
469 : :
470 : : /* Remove cores permanently and then stop OCF cache and unregister SPDK bdev */
471 : : int
472 : 9 : vbdev_ocf_delete_clean(struct vbdev_ocf *vbdev, void (*cb)(void *, int),
473 : : void *cb_arg)
474 : : {
475 : 9 : vbdev->state.doing_clean_delete = true;
476 : :
477 : 9 : return vbdev_ocf_delete(vbdev, cb, cb_arg);
478 : : }
479 : :
480 : :
481 : : /* If vbdev is online, return its object */
482 : : struct vbdev_ocf *
483 : 86 : vbdev_ocf_get_by_name(const char *name)
484 : : {
485 : : struct vbdev_ocf *vbdev;
486 : :
487 [ - + ]: 86 : if (name == NULL) {
488 : 0 : assert(false);
489 : : return NULL;
490 : : }
491 : :
492 [ + + ]: 230 : TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
493 [ + - - + : 198 : if (vbdev->name == NULL || vbdev->state.doing_finish) {
+ + ]
494 : 109 : continue;
495 : : }
496 [ - + - + : 89 : if (strcmp(vbdev->name, name) == 0) {
+ + ]
497 : 54 : return vbdev;
498 : : }
499 : : }
500 : 32 : return NULL;
501 : : }
502 : :
503 : : /* Return matching base if parent vbdev is online */
504 : : struct vbdev_ocf_base *
505 : 46 : vbdev_ocf_get_base_by_name(const char *name)
506 : : {
507 : : struct vbdev_ocf *vbdev;
508 : :
509 [ - + ]: 46 : if (name == NULL) {
510 : 0 : assert(false);
511 : : return NULL;
512 : : }
513 : :
514 [ + - ]: 107 : TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
515 [ - + + + ]: 107 : if (vbdev->state.doing_finish) {
516 : 41 : continue;
517 : : }
518 : :
519 [ + - - + : 66 : if (vbdev->cache.name && strcmp(vbdev->cache.name, name) == 0) {
- + + + ]
520 : 20 : return &vbdev->cache;
521 : : }
522 [ + - - + : 46 : if (vbdev->core.name && strcmp(vbdev->core.name, name) == 0) {
- + + + ]
523 : 26 : return &vbdev->core;
524 : : }
525 : : }
526 : 0 : return NULL;
527 : : }
528 : :
529 : : /* Execute fn for each OCF device that is online or waits for base devices */
530 : : void
531 : 18 : vbdev_ocf_foreach(vbdev_ocf_foreach_fn fn, void *ctx)
532 : : {
533 : : struct vbdev_ocf *vbdev;
534 : :
535 [ - + ]: 18 : assert(fn != NULL);
536 : :
537 [ + + ]: 58 : TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
538 [ - + + + ]: 40 : if (!vbdev->state.doing_finish) {
539 : 19 : fn(vbdev, ctx);
540 : : }
541 : : }
542 : 18 : }
543 : :
544 : : /* Called from OCF when SPDK_IO is completed */
545 : : static void
546 : 1270357 : vbdev_ocf_io_submit_cb(struct ocf_io *io, int error)
547 : : {
548 : 1270357 : struct spdk_bdev_io *bdev_io = io->priv1;
549 : :
550 [ + - ]: 1270357 : if (error == 0) {
551 : 1270357 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
552 [ # # ]: 0 : } else if (error == -OCF_ERR_NO_MEM) {
553 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
554 : : } else {
555 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
556 : : }
557 : :
558 : 1270357 : ocf_io_put(io);
559 : 1270357 : }
560 : :
561 : : /* Configure io parameters and send it to OCF */
562 : : static int
563 : 1270357 : io_submit_to_ocf(struct spdk_bdev_io *bdev_io, struct ocf_io *io)
564 : : {
565 [ + + + - ]: 1270357 : switch (bdev_io->type) {
566 : 854613 : case SPDK_BDEV_IO_TYPE_WRITE:
567 : : case SPDK_BDEV_IO_TYPE_READ:
568 : 854613 : ocf_core_submit_io(io);
569 : 854613 : return 0;
570 : 232928 : case SPDK_BDEV_IO_TYPE_FLUSH:
571 : 232928 : ocf_core_submit_flush(io);
572 : 232928 : return 0;
573 : 182816 : case SPDK_BDEV_IO_TYPE_UNMAP:
574 : 182816 : ocf_core_submit_discard(io);
575 : 182816 : return 0;
576 : 0 : case SPDK_BDEV_IO_TYPE_RESET:
577 : : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
578 : : default:
579 : 0 : SPDK_ERRLOG("Unsupported IO type: %d\n", bdev_io->type);
580 : 0 : return -EINVAL;
581 : : }
582 : : }
583 : :
584 : : /* Submit SPDK-IO to OCF */
585 : : static void
586 : 1270357 : io_handle(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
587 : : {
588 : 1270357 : struct vbdev_ocf *vbdev = bdev_io->bdev->ctxt;
589 : 1270357 : struct ocf_io *io = NULL;
590 : 1270357 : struct bdev_ocf_data *data = NULL;
591 : 1270357 : struct vbdev_ocf_qctx *qctx = spdk_io_channel_get_ctx(ch);
592 : 1270357 : uint64_t len = bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen;
593 : 1270357 : uint64_t offset = bdev_io->u.bdev.offset_blocks * bdev_io->bdev->blocklen;
594 : 1270357 : int dir, flags = 0;
595 : : int err;
596 : :
597 [ + + + + : 1270357 : switch (bdev_io->type) {
- ]
598 : 249626 : case SPDK_BDEV_IO_TYPE_READ:
599 : 249626 : dir = OCF_READ;
600 : 249626 : break;
601 : 604987 : case SPDK_BDEV_IO_TYPE_WRITE:
602 : 604987 : dir = OCF_WRITE;
603 : 604987 : break;
604 : 232928 : case SPDK_BDEV_IO_TYPE_FLUSH:
605 : 232928 : dir = OCF_WRITE;
606 : 232928 : break;
607 : 182816 : case SPDK_BDEV_IO_TYPE_UNMAP:
608 : 182816 : dir = OCF_WRITE;
609 : 182816 : break;
610 : 0 : default:
611 : 0 : err = -EINVAL;
612 : 0 : goto fail;
613 : : }
614 : :
615 [ + + ]: 1270357 : if (bdev_io->type == SPDK_BDEV_IO_TYPE_FLUSH) {
616 : 232928 : flags = OCF_WRITE_FLUSH;
617 : : }
618 : :
619 : 1270357 : io = ocf_volume_new_io(ocf_core_get_front_volume(vbdev->ocf_core), qctx->queue, offset, len, dir, 0,
620 : : flags);
621 [ - + ]: 1270357 : if (!io) {
622 : 0 : err = -ENOMEM;
623 : 0 : goto fail;
624 : : }
625 : :
626 : 1270357 : data = vbdev_ocf_data_from_spdk_io(bdev_io);
627 [ - + ]: 1270357 : if (!data) {
628 : 0 : err = -ENOMEM;
629 : 0 : goto fail;
630 : : }
631 : :
632 : 1270357 : err = ocf_io_set_data(io, data, 0);
633 [ - + ]: 1270357 : if (err) {
634 : 0 : goto fail;
635 : : }
636 : :
637 : 1270357 : ocf_io_set_cmpl(io, bdev_io, NULL, vbdev_ocf_io_submit_cb);
638 : :
639 : 1270357 : err = io_submit_to_ocf(bdev_io, io);
640 [ - + ]: 1270357 : if (err) {
641 : 0 : goto fail;
642 : : }
643 : :
644 : 1270357 : return;
645 : :
646 : 0 : fail:
647 [ # # ]: 0 : if (io) {
648 : 0 : ocf_io_put(io);
649 : : }
650 : :
651 [ # # ]: 0 : if (err == -ENOMEM) {
652 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
653 : : } else {
654 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
655 : : }
656 : : }
657 : :
658 : : static void
659 : 249626 : vbdev_ocf_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
660 : : bool success)
661 : : {
662 [ - + ]: 249626 : if (!success) {
663 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
664 : 0 : return;
665 : : }
666 : :
667 : 249626 : io_handle(ch, bdev_io);
668 : : }
669 : :
670 : : /* Called from bdev layer when an io to Cache vbdev is submitted */
671 : : static void
672 : 1270357 : vbdev_ocf_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
673 : : {
674 [ + + - ]: 1270357 : switch (bdev_io->type) {
675 : 249626 : case SPDK_BDEV_IO_TYPE_READ:
676 : : /* User does not have to allocate io vectors for the request,
677 : : * so in case they are not allocated, we allocate them here */
678 : 249626 : spdk_bdev_io_get_buf(bdev_io, vbdev_ocf_get_buf_cb,
679 : 249626 : bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
680 : 249626 : break;
681 : 1020731 : case SPDK_BDEV_IO_TYPE_WRITE:
682 : : case SPDK_BDEV_IO_TYPE_FLUSH:
683 : : case SPDK_BDEV_IO_TYPE_UNMAP:
684 : 1020731 : io_handle(ch, bdev_io);
685 : 1020731 : break;
686 : 0 : case SPDK_BDEV_IO_TYPE_RESET:
687 : : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
688 : : default:
689 : 0 : SPDK_ERRLOG("Unknown I/O type %d\n", bdev_io->type);
690 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
691 : 0 : break;
692 : : }
693 : 1270357 : }
694 : :
695 : : /* Called from bdev layer */
696 : : static bool
697 : 329 : vbdev_ocf_io_type_supported(void *opaque, enum spdk_bdev_io_type io_type)
698 : : {
699 : 329 : struct vbdev_ocf *vbdev = opaque;
700 : :
701 [ + + ]: 329 : switch (io_type) {
702 : 62 : case SPDK_BDEV_IO_TYPE_READ:
703 : : case SPDK_BDEV_IO_TYPE_WRITE:
704 : : case SPDK_BDEV_IO_TYPE_FLUSH:
705 : : case SPDK_BDEV_IO_TYPE_UNMAP:
706 : 62 : return spdk_bdev_io_type_supported(vbdev->core.bdev, io_type);
707 : 267 : case SPDK_BDEV_IO_TYPE_RESET:
708 : : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
709 : : default:
710 : 267 : return false;
711 : : }
712 : : }
713 : :
714 : : /* Called from bdev layer */
715 : : static struct spdk_io_channel *
716 : 52 : vbdev_ocf_get_io_channel(void *opaque)
717 : : {
718 : 52 : struct vbdev_ocf *bdev = opaque;
719 : :
720 : 52 : return spdk_get_io_channel(bdev);
721 : : }
722 : :
723 : : static int
724 : 12 : vbdev_ocf_dump_info_json(void *opaque, struct spdk_json_write_ctx *w)
725 : : {
726 : 12 : struct vbdev_ocf *vbdev = opaque;
727 : :
728 : 12 : spdk_json_write_named_string(w, "cache_device", vbdev->cache.name);
729 : 12 : spdk_json_write_named_string(w, "core_device", vbdev->core.name);
730 : :
731 : 12 : spdk_json_write_named_string(w, "mode",
732 : : ocf_get_cache_modename(ocf_cache_get_mode(vbdev->ocf_cache)));
733 : 12 : spdk_json_write_named_uint32(w, "cache_line_size",
734 : 12 : ocf_get_cache_line_size(vbdev->ocf_cache));
735 : 12 : spdk_json_write_named_bool(w, "metadata_volatile",
736 [ - + ]: 12 : vbdev->cfg.cache.metadata_volatile);
737 : :
738 : 12 : return 0;
739 : : }
740 : :
741 : : static void
742 : 11 : vbdev_ocf_write_json_config(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
743 : : {
744 : 11 : struct vbdev_ocf *vbdev = bdev->ctxt;
745 : :
746 : 11 : spdk_json_write_object_begin(w);
747 : :
748 : 11 : spdk_json_write_named_string(w, "method", "bdev_ocf_create");
749 : :
750 : 11 : spdk_json_write_named_object_begin(w, "params");
751 : 11 : spdk_json_write_named_string(w, "name", vbdev->name);
752 : 11 : spdk_json_write_named_string(w, "mode",
753 : : ocf_get_cache_modename(ocf_cache_get_mode(vbdev->ocf_cache)));
754 : 11 : spdk_json_write_named_uint32(w, "cache_line_size",
755 : 11 : ocf_get_cache_line_size(vbdev->ocf_cache));
756 : 11 : spdk_json_write_named_string(w, "cache_bdev_name", vbdev->cache.name);
757 : 11 : spdk_json_write_named_string(w, "core_bdev_name", vbdev->core.name);
758 : 11 : spdk_json_write_object_end(w);
759 : :
760 : 11 : spdk_json_write_object_end(w);
761 : 11 : }
762 : :
763 : : /* Cache vbdev function table
764 : : * Used by bdev layer */
765 : : static struct spdk_bdev_fn_table cache_dev_fn_table = {
766 : : .destruct = vbdev_ocf_destruct,
767 : : .io_type_supported = vbdev_ocf_io_type_supported,
768 : : .submit_request = vbdev_ocf_submit_request,
769 : : .get_io_channel = vbdev_ocf_get_io_channel,
770 : : .write_config_json = vbdev_ocf_write_json_config,
771 : : .dump_info_json = vbdev_ocf_dump_info_json,
772 : : };
773 : :
774 : : /* Poller function for the OCF queue
775 : : * We execute OCF requests here synchronously */
776 : : static int
777 : 2972980 : queue_poll(void *opaque)
778 : : {
779 : 2972980 : struct vbdev_ocf_qctx *qctx = opaque;
780 : 2972980 : uint32_t iono = ocf_queue_pending_io(qctx->queue);
781 : 2972980 : int i, max = spdk_min(32, iono);
782 : :
783 [ + + ]: 4794858 : for (i = 0; i < max; i++) {
784 : 1821878 : ocf_queue_run_single(qctx->queue);
785 : : }
786 : :
787 [ + + ]: 2972980 : if (iono > 0) {
788 : 178297 : return SPDK_POLLER_BUSY;
789 : : } else {
790 : 2794683 : return SPDK_POLLER_IDLE;
791 : : }
792 : : }
793 : :
794 : : /* Called during ocf_submit_io, ocf_purge*
795 : : * and any other requests that need to submit io */
796 : : static void
797 : 1821878 : vbdev_ocf_ctx_queue_kick(ocf_queue_t q)
798 : : {
799 : 1821878 : }
800 : :
801 : : /* OCF queue deinitialization
802 : : * Called at ocf_cache_stop */
803 : : static void
804 : 52 : vbdev_ocf_ctx_queue_stop(ocf_queue_t q)
805 : : {
806 : 52 : struct vbdev_ocf_qctx *qctx = ocf_queue_get_priv(q);
807 : :
808 [ + - ]: 52 : if (qctx) {
809 : 52 : spdk_put_io_channel(qctx->cache_ch);
810 : 52 : spdk_put_io_channel(qctx->core_ch);
811 : 52 : spdk_poller_unregister(&qctx->poller);
812 [ - + + - ]: 52 : if (qctx->allocated) {
813 : 52 : free(qctx);
814 : : }
815 : : }
816 : 52 : }
817 : :
818 : : /* Queue ops is an interface for running queue thread
819 : : * stop() operation in called just before queue gets destroyed */
820 : : const struct ocf_queue_ops queue_ops = {
821 : : .kick_sync = vbdev_ocf_ctx_queue_kick,
822 : : .kick = vbdev_ocf_ctx_queue_kick,
823 : : .stop = vbdev_ocf_ctx_queue_stop,
824 : : };
825 : :
826 : : /* Called on cache vbdev creation at every thread
827 : : * We allocate OCF queues here and SPDK poller for it */
828 : : static int
829 : 52 : io_device_create_cb(void *io_device, void *ctx_buf)
830 : : {
831 : 52 : struct vbdev_ocf *vbdev = io_device;
832 : 52 : struct vbdev_ocf_qctx *qctx = ctx_buf;
833 : : int rc;
834 : :
835 : 52 : rc = vbdev_ocf_queue_create(vbdev->ocf_cache, &qctx->queue, &queue_ops);
836 [ - + ]: 52 : if (rc) {
837 : 0 : return rc;
838 : : }
839 : :
840 : 52 : ocf_queue_set_priv(qctx->queue, qctx);
841 : :
842 : 52 : qctx->vbdev = vbdev;
843 : 52 : qctx->cache_ch = spdk_bdev_get_io_channel(vbdev->cache.desc);
844 : 52 : qctx->core_ch = spdk_bdev_get_io_channel(vbdev->core.desc);
845 : 52 : qctx->poller = SPDK_POLLER_REGISTER(queue_poll, qctx, 0);
846 : :
847 : 52 : return rc;
848 : : }
849 : :
850 : : /* Called per thread
851 : : * Put OCF queue and relaunch poller with new context to finish pending requests */
852 : : static void
853 : 52 : io_device_destroy_cb(void *io_device, void *ctx_buf)
854 : : {
855 : : /* Making a copy of context to use it after io channel will be destroyed */
856 : 52 : struct vbdev_ocf_qctx *copy = malloc(sizeof(*copy));
857 : 52 : struct vbdev_ocf_qctx *qctx = ctx_buf;
858 : :
859 [ + - ]: 52 : if (copy) {
860 : 52 : ocf_queue_set_priv(qctx->queue, copy);
861 [ - + - + ]: 52 : memcpy(copy, qctx, sizeof(*copy));
862 : 52 : spdk_poller_unregister(&qctx->poller);
863 : 52 : copy->poller = SPDK_POLLER_REGISTER(queue_poll, copy, 0);
864 : 52 : copy->allocated = true;
865 : : } else {
866 : 0 : SPDK_ERRLOG("Unable to stop OCF queue properly: %s\n",
867 : : spdk_strerror(ENOMEM));
868 : : }
869 : :
870 : 52 : vbdev_ocf_queue_put(qctx->queue);
871 : 52 : }
872 : :
873 : : /* OCF management queue deinitialization */
874 : : static void
875 : 19 : vbdev_ocf_ctx_mngt_queue_stop(ocf_queue_t q)
876 : : {
877 : 19 : struct spdk_poller *poller = ocf_queue_get_priv(q);
878 : :
879 [ + - ]: 19 : if (poller) {
880 : 19 : spdk_poller_unregister(&poller);
881 : : }
882 : 19 : }
883 : :
884 : : static int
885 : 536955 : mngt_queue_poll(void *opaque)
886 : : {
887 : 536955 : ocf_queue_t q = opaque;
888 : 536955 : uint32_t iono = ocf_queue_pending_io(q);
889 : 536955 : int i, max = spdk_min(32, iono);
890 : :
891 [ + + ]: 542204 : for (i = 0; i < max; i++) {
892 : 5249 : ocf_queue_run_single(q);
893 : : }
894 : :
895 [ + + ]: 536955 : if (iono > 0) {
896 : 3248 : return SPDK_POLLER_BUSY;
897 : : } else {
898 : 533707 : return SPDK_POLLER_IDLE;
899 : : }
900 : : }
901 : :
902 : : static void
903 : 5249 : vbdev_ocf_ctx_mngt_queue_kick(ocf_queue_t q)
904 : : {
905 : 5249 : }
906 : :
907 : : /* Queue ops is an interface for running queue thread
908 : : * stop() operation in called just before queue gets destroyed */
909 : : const struct ocf_queue_ops mngt_queue_ops = {
910 : : .kick_sync = NULL,
911 : : .kick = vbdev_ocf_ctx_mngt_queue_kick,
912 : : .stop = vbdev_ocf_ctx_mngt_queue_stop,
913 : : };
914 : :
915 : : static void
916 : 0 : vbdev_ocf_mngt_exit(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn *rollback_path, int rc)
917 : : {
918 : 0 : vbdev->state.starting = false;
919 : 0 : vbdev_ocf_mngt_stop(vbdev, rollback_path, rc);
920 : 0 : }
921 : :
922 : : /* Create exported spdk object */
923 : : static void
924 : 25 : finish_register(struct vbdev_ocf *vbdev)
925 : : {
926 : 0 : struct spdk_uuid ns_uuid;
927 : : int result;
928 : :
929 : : /* Copy properties of the base bdev */
930 : 25 : vbdev->exp_bdev.blocklen = vbdev->core.bdev->blocklen;
931 : 25 : vbdev->exp_bdev.write_cache = vbdev->core.bdev->write_cache;
932 : 25 : vbdev->exp_bdev.required_alignment = vbdev->core.bdev->required_alignment;
933 : :
934 : 25 : vbdev->exp_bdev.name = vbdev->name;
935 : 25 : vbdev->exp_bdev.product_name = "SPDK OCF";
936 : :
937 : 25 : vbdev->exp_bdev.blockcnt = vbdev->core.bdev->blockcnt;
938 : 25 : vbdev->exp_bdev.ctxt = vbdev;
939 : 25 : vbdev->exp_bdev.fn_table = &cache_dev_fn_table;
940 : 25 : vbdev->exp_bdev.module = &ocf_if;
941 : :
942 : : /* Generate UUID based on namespace UUID + base bdev UUID. */
943 : 25 : spdk_uuid_parse(&ns_uuid, BDEV_OCF_NAMESPACE_UUID);
944 : 25 : result = spdk_uuid_generate_sha1(&vbdev->exp_bdev.uuid, &ns_uuid,
945 : 25 : (const char *)&vbdev->core.bdev->uuid, sizeof(struct spdk_uuid));
946 [ - + ]: 25 : if (result) {
947 : 0 : SPDK_ERRLOG("Unable to generate new UUID for ocf bdev\n");
948 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, result);
949 : 0 : return;
950 : : }
951 : :
952 : : /* Finally register vbdev in SPDK */
953 : 25 : spdk_io_device_register(vbdev, io_device_create_cb, io_device_destroy_cb,
954 : 25 : sizeof(struct vbdev_ocf_qctx), vbdev->name);
955 : 25 : result = spdk_bdev_register(&vbdev->exp_bdev);
956 [ - + ]: 25 : if (result) {
957 : 0 : SPDK_ERRLOG("Could not register exposed bdev %s\n",
958 : : vbdev->name);
959 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, result);
960 : 0 : return;
961 : : } else {
962 : 25 : vbdev->state.started = true;
963 : : }
964 : :
965 : 25 : vbdev_ocf_mngt_continue(vbdev, result);
966 : : }
967 : :
968 : : static void
969 : 25 : add_core_cmpl(ocf_cache_t cache, ocf_core_t core, void *priv, int error)
970 : : {
971 : 25 : struct vbdev_ocf *vbdev = priv;
972 : :
973 : 25 : ocf_mngt_cache_unlock(cache);
974 : :
975 [ - + ]: 25 : if (error) {
976 : 0 : SPDK_ERRLOG("Error %d, failed to add core device to cache instance %s,"
977 : : "starting rollback\n", error, vbdev->name);
978 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, error);
979 : 0 : return;
980 : : } else {
981 : 25 : vbdev->ocf_core = core;
982 : : }
983 : :
984 : 25 : vbdev_ocf_mngt_continue(vbdev, error);
985 : : }
986 : :
987 : : /* Try to lock cache, then add core */
988 : : static void
989 : 25 : add_core_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
990 : : {
991 : 25 : struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
992 : :
993 [ - + ]: 25 : if (error) {
994 : 0 : SPDK_ERRLOG("Error %d, can not lock cache instance %s,"
995 : : "starting rollback\n", error, vbdev->name);
996 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, error);
997 : : }
998 : 25 : ocf_mngt_cache_add_core(vbdev->ocf_cache, &vbdev->cfg.core, add_core_cmpl, vbdev);
999 : 25 : }
1000 : :
1001 : : /* Add core for existing OCF cache instance */
1002 : : static void
1003 : 25 : add_core(struct vbdev_ocf *vbdev)
1004 : : {
1005 : 25 : ocf_mngt_cache_lock(vbdev->ocf_cache, add_core_cache_lock_cmpl, vbdev);
1006 : 25 : }
1007 : :
1008 : : static void
1009 : 19 : start_cache_cmpl(ocf_cache_t cache, void *priv, int error)
1010 : : {
1011 : 19 : struct vbdev_ocf *vbdev = priv;
1012 : 0 : uint64_t mem_needed;
1013 : :
1014 : 19 : ocf_mngt_cache_unlock(cache);
1015 : :
1016 [ - + ]: 19 : if (error) {
1017 : 0 : SPDK_ERRLOG("Error %d during start cache %s, starting rollback\n",
1018 : : error, vbdev->name);
1019 : :
1020 [ # # ]: 0 : if (error == -OCF_ERR_NO_MEM) {
1021 : 0 : ocf_mngt_get_ram_needed(cache, &vbdev->cfg.attach.device, &mem_needed);
1022 : :
1023 : 0 : SPDK_NOTICELOG("Try to increase hugepage memory size or cache line size. "
1024 : : "For your configuration:\nDevice size: %"PRIu64" bytes\n"
1025 : : "Cache line size: %"PRIu64" bytes\nFree memory needed to start "
1026 : : "cache: %"PRIu64" bytes\n", vbdev->cache.bdev->blockcnt *
1027 : : vbdev->cache.bdev->blocklen, vbdev->cfg.cache.cache_line_size,
1028 : : mem_needed);
1029 : : }
1030 : :
1031 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, error);
1032 : 0 : return;
1033 : : }
1034 : :
1035 : 19 : vbdev_ocf_mngt_continue(vbdev, error);
1036 : : }
1037 : :
1038 : : static int
1039 : 19 : create_management_queue(struct vbdev_ocf *vbdev)
1040 : : {
1041 : : struct spdk_poller *mngt_poller;
1042 : : int rc;
1043 : :
1044 : 19 : rc = vbdev_ocf_queue_create(vbdev->ocf_cache, &vbdev->cache_ctx->mngt_queue, &mngt_queue_ops);
1045 [ - + ]: 19 : if (rc) {
1046 : 0 : SPDK_ERRLOG("Unable to create mngt_queue: %d\n", rc);
1047 : 0 : return rc;
1048 : : }
1049 : :
1050 : 19 : mngt_poller = SPDK_POLLER_REGISTER(mngt_queue_poll, vbdev->cache_ctx->mngt_queue, 100);
1051 [ - + ]: 19 : if (mngt_poller == NULL) {
1052 : 0 : SPDK_ERRLOG("Unable to initiate mngt request: %s", spdk_strerror(ENOMEM));
1053 : 0 : return -ENOMEM;
1054 : : }
1055 : :
1056 : 19 : ocf_queue_set_priv(vbdev->cache_ctx->mngt_queue, mngt_poller);
1057 : 19 : ocf_mngt_cache_set_mngt_queue(vbdev->ocf_cache, vbdev->cache_ctx->mngt_queue);
1058 : :
1059 : 19 : return 0;
1060 : : }
1061 : :
1062 : : /* Start OCF cache, attach caching device */
1063 : : static void
1064 : 25 : start_cache(struct vbdev_ocf *vbdev)
1065 : : {
1066 : : ocf_cache_t existing;
1067 : 25 : uint32_t cache_block_size = vbdev->cache.bdev->blocklen;
1068 : 25 : uint32_t core_block_size = vbdev->core.bdev->blocklen;
1069 : : int rc;
1070 : :
1071 [ - + ]: 25 : if (is_ocf_cache_running(vbdev)) {
1072 : 0 : vbdev_ocf_mngt_stop(vbdev, NULL, -EALREADY);
1073 : 0 : return;
1074 : : }
1075 : :
1076 [ - + ]: 25 : if (cache_block_size > core_block_size) {
1077 : 0 : SPDK_ERRLOG("Cache bdev block size (%d) is bigger then core bdev block size (%d)\n",
1078 : : cache_block_size, core_block_size);
1079 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, -EINVAL);
1080 : 0 : return;
1081 : : }
1082 : :
1083 : 25 : existing = get_other_cache_instance(vbdev);
1084 [ + + ]: 25 : if (existing) {
1085 : 6 : SPDK_NOTICELOG("OCF bdev %s connects to existing cache device %s\n",
1086 : : vbdev->name, vbdev->cache.name);
1087 : 6 : vbdev->ocf_cache = existing;
1088 : 6 : ocf_mngt_cache_get(vbdev->ocf_cache);
1089 : 6 : vbdev->cache_ctx = ocf_cache_get_priv(existing);
1090 : 6 : vbdev_ocf_cache_ctx_get(vbdev->cache_ctx);
1091 : 6 : vbdev_ocf_mngt_continue(vbdev, 0);
1092 : 6 : return;
1093 : : }
1094 : :
1095 : 19 : vbdev->cache_ctx = calloc(1, sizeof(struct vbdev_ocf_cache_ctx));
1096 [ - + ]: 19 : if (vbdev->cache_ctx == NULL) {
1097 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, -ENOMEM);
1098 : 0 : return;
1099 : : }
1100 : :
1101 : 19 : vbdev_ocf_cache_ctx_get(vbdev->cache_ctx);
1102 [ - + ]: 19 : pthread_mutex_init(&vbdev->cache_ctx->lock, NULL);
1103 : :
1104 : 19 : rc = ocf_mngt_cache_start(vbdev_ocf_ctx, &vbdev->ocf_cache, &vbdev->cfg.cache, NULL);
1105 [ - + ]: 19 : if (rc) {
1106 : 0 : SPDK_ERRLOG("Could not start cache %s: %d\n", vbdev->name, rc);
1107 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, rc);
1108 : 0 : return;
1109 : : }
1110 : 19 : ocf_mngt_cache_get(vbdev->ocf_cache);
1111 : :
1112 : 19 : ocf_cache_set_priv(vbdev->ocf_cache, vbdev->cache_ctx);
1113 : :
1114 : 19 : rc = create_management_queue(vbdev);
1115 [ - + ]: 19 : if (rc) {
1116 : 0 : SPDK_ERRLOG("Unable to create mngt_queue: %d\n", rc);
1117 : 0 : vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, rc);
1118 : 0 : return;
1119 : : }
1120 : :
1121 [ - + - + ]: 19 : if (vbdev->cfg.loadq) {
1122 : 0 : ocf_mngt_cache_load(vbdev->ocf_cache, &vbdev->cfg.attach, start_cache_cmpl, vbdev);
1123 : : } else {
1124 : 19 : ocf_mngt_cache_attach(vbdev->ocf_cache, &vbdev->cfg.attach, start_cache_cmpl, vbdev);
1125 : : }
1126 : : }
1127 : :
1128 : : /* Procedures called during register operation */
1129 : : vbdev_ocf_mngt_fn register_path[] = {
1130 : : start_cache,
1131 : : add_core,
1132 : : finish_register,
1133 : : NULL
1134 : : };
1135 : :
1136 : : /* Start cache instance and register OCF bdev */
1137 : : static void
1138 : 25 : register_vbdev(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_callback cb, void *cb_arg)
1139 : : {
1140 : : int rc;
1141 : :
1142 [ - + + - : 25 : if (!(vbdev->core.attached && vbdev->cache.attached) || vbdev->state.started) {
- + + - -
+ - + ]
1143 : 0 : cb(-EPERM, vbdev, cb_arg);
1144 : 0 : return;
1145 : : }
1146 : :
1147 : 25 : vbdev->state.starting = true;
1148 : 25 : rc = vbdev_ocf_mngt_start(vbdev, register_path, cb, cb_arg);
1149 [ - + ]: 25 : if (rc) {
1150 : 0 : cb(rc, vbdev, cb_arg);
1151 : : }
1152 : : }
1153 : :
1154 : : /* Init OCF configuration options
1155 : : * for core and cache devices */
1156 : : static int
1157 : 30 : init_vbdev_config(struct vbdev_ocf *vbdev)
1158 : : {
1159 : 30 : struct vbdev_ocf_config *cfg = &vbdev->cfg;
1160 : 0 : struct ocf_volume_uuid uuid;
1161 : : ocf_volume_type_t type;
1162 : : int ret;
1163 : :
1164 : :
1165 : : /* Initialize OCF defaults first */
1166 : 30 : ocf_mngt_cache_attach_config_set_default(&cfg->attach);
1167 : 30 : ocf_mngt_cache_config_set_default(&cfg->cache);
1168 : 30 : ocf_mngt_core_config_set_default(&cfg->core);
1169 : :
1170 : 30 : ret = snprintf(cfg->cache.name, sizeof(cfg->cache.name), "%s", vbdev->name);
1171 [ + - - + ]: 30 : if (ret < 0 || (size_t) ret >= sizeof(cfg->cache.name)) {
1172 : 0 : return -EINVAL;
1173 : : }
1174 : 30 : ret = snprintf(cfg->core.name, sizeof(cfg->core.name), "%s", vbdev->core.name);
1175 [ + - - + ]: 30 : if (ret < 0 || (size_t) ret >= sizeof(cfg->core.name)) {
1176 : 0 : return -EINVAL;
1177 : : }
1178 : :
1179 : 30 : cfg->attach.open_cores = false;
1180 : 30 : cfg->attach.device.perform_test = false;
1181 : 30 : cfg->attach.discard_on_start = false;
1182 : :
1183 : 30 : vbdev->cfg.cache.locked = true;
1184 : :
1185 : 30 : cfg->core.volume_type = SPDK_OBJECT;
1186 : :
1187 [ - + - + ]: 30 : if (vbdev->cfg.loadq) {
1188 : : /* When doing cache_load(), we need to set try_add to true,
1189 : : * otherwise OCF will interpret this core as new
1190 : : * instead of the inactive one */
1191 : 0 : vbdev->cfg.core.try_add = true;
1192 : : } else {
1193 : : /* When cache is initialized as new, set force flag to true,
1194 : : * to ignore warnings about existing metadata */
1195 : 30 : cfg->attach.force = true;
1196 : : }
1197 : :
1198 : : /* Serialize bdev names in OCF UUID to interpret on future loads
1199 : : * Core UUID is a triple of (core name, vbdev name, cache name)
1200 : : * Cache UUID is cache bdev name */
1201 : 30 : type = ocf_ctx_get_volume_type(vbdev_ocf_ctx, SPDK_OBJECT);
1202 [ - + ]: 30 : if (!type) {
1203 : 0 : SPDK_ERRLOG("Fail to get volume type\n");
1204 : 0 : return -EINVAL;
1205 : : }
1206 [ - + ]: 30 : uuid.size = strlen(vbdev->cache.name) + 1;
1207 : 30 : uuid.data = vbdev->cache.name;
1208 : 30 : ret = ocf_volume_create(&cfg->attach.device.volume, type, &uuid);
1209 [ - + ]: 30 : if (ret) {
1210 : 0 : SPDK_ERRLOG("Fail to create volume\n");
1211 : 0 : return -EINVAL;
1212 : : }
1213 : :
1214 : 30 : snprintf(vbdev->uuid, VBDEV_OCF_MD_MAX_LEN, "%s %s %s",
1215 : : vbdev->core.name, vbdev->name, vbdev->cache.name);
1216 [ - + ]: 30 : cfg->core.uuid.size = strlen(vbdev->uuid) + 1;
1217 : 30 : cfg->core.uuid.data = vbdev->uuid;
1218 [ - + ]: 30 : vbdev->uuid[strlen(vbdev->core.name)] = 0;
1219 [ - + - + ]: 30 : vbdev->uuid[strlen(vbdev->core.name) + 1 + strlen(vbdev->name)] = 0;
1220 : :
1221 : 30 : return 0;
1222 : : }
1223 : :
1224 : : /* Allocate vbdev structure object and add it to the global list */
1225 : : static int
1226 : 30 : init_vbdev(const char *vbdev_name,
1227 : : const char *cache_mode_name,
1228 : : const uint64_t cache_line_size,
1229 : : const char *cache_name,
1230 : : const char *core_name,
1231 : : bool loadq)
1232 : : {
1233 : : struct vbdev_ocf *vbdev;
1234 : 30 : int rc = 0;
1235 : :
1236 [ + - - + ]: 30 : if (spdk_bdev_get_by_name(vbdev_name) || vbdev_ocf_get_by_name(vbdev_name)) {
1237 : 0 : SPDK_ERRLOG("Device with name '%s' already exists\n", vbdev_name);
1238 : 0 : return -EPERM;
1239 : : }
1240 : :
1241 : 30 : vbdev = calloc(1, sizeof(*vbdev));
1242 [ - + ]: 30 : if (!vbdev) {
1243 : 0 : goto error_mem;
1244 : : }
1245 : :
1246 [ - + ]: 30 : vbdev->name = strdup(vbdev_name);
1247 [ - + ]: 30 : if (!vbdev->name) {
1248 : 0 : goto error_mem;
1249 : : }
1250 : :
1251 [ - + ]: 30 : vbdev->cache.name = strdup(cache_name);
1252 [ - + ]: 30 : if (!vbdev->cache.name) {
1253 : 0 : goto error_mem;
1254 : : }
1255 : :
1256 [ - + ]: 30 : vbdev->core.name = strdup(core_name);
1257 [ - + ]: 30 : if (!vbdev->core.name) {
1258 : 0 : goto error_mem;
1259 : : }
1260 : :
1261 : 30 : vbdev->cache.parent = vbdev;
1262 : 30 : vbdev->core.parent = vbdev;
1263 : 30 : vbdev->cache.is_cache = true;
1264 : 30 : vbdev->core.is_cache = false;
1265 : 30 : vbdev->cfg.loadq = loadq;
1266 : :
1267 : 30 : rc = init_vbdev_config(vbdev);
1268 [ - + ]: 30 : if (rc) {
1269 : 0 : SPDK_ERRLOG("Fail to init vbdev config\n");
1270 : 0 : goto error_free;
1271 : : }
1272 : :
1273 : :
1274 [ + - ]: 30 : if (cache_mode_name) {
1275 : : vbdev->cfg.cache.cache_mode
1276 : 30 : = ocf_get_cache_mode(cache_mode_name);
1277 [ # # ]: 0 : } else if (!loadq) { /* In load path it is OK to pass NULL as cache mode */
1278 : 0 : SPDK_ERRLOG("No cache mode specified\n");
1279 : 0 : rc = -EINVAL;
1280 : 0 : goto error_free;
1281 : : }
1282 [ - + ]: 30 : if (vbdev->cfg.cache.cache_mode < 0) {
1283 : 0 : SPDK_ERRLOG("Incorrect cache mode '%s'\n", cache_mode_name);
1284 : 0 : rc = -EINVAL;
1285 : 0 : goto error_free;
1286 : : }
1287 : :
1288 : 30 : ocf_cache_line_size_t set_cache_line_size = cache_line_size ?
1289 [ + + ]: 30 : (ocf_cache_line_size_t)cache_line_size * KiB :
1290 : : ocf_cache_line_size_default;
1291 [ - + ]: 30 : if (set_cache_line_size == 0) {
1292 : 0 : SPDK_ERRLOG("Cache line size should be non-zero.\n");
1293 : 0 : rc = -EINVAL;
1294 : 0 : goto error_free;
1295 : : }
1296 : 30 : vbdev->cfg.attach.cache_line_size = set_cache_line_size;
1297 : 30 : vbdev->cfg.cache.cache_line_size = set_cache_line_size;
1298 : :
1299 : 30 : TAILQ_INSERT_TAIL(&g_ocf_vbdev_head, vbdev, tailq);
1300 : 30 : return rc;
1301 : :
1302 : 0 : error_mem:
1303 : 0 : rc = -ENOMEM;
1304 : 0 : error_free:
1305 : 0 : free_vbdev(vbdev);
1306 : 0 : return rc;
1307 : : }
1308 : :
1309 : : /* Read configuration file at the start of SPDK application
1310 : : * This adds vbdevs to global list if some mentioned in config */
1311 : : static int
1312 : 66 : vbdev_ocf_init(void)
1313 : : {
1314 : : int status;
1315 : :
1316 : 66 : status = vbdev_ocf_ctx_init();
1317 [ - + ]: 66 : if (status) {
1318 : 0 : SPDK_ERRLOG("OCF ctx initialization failed with=%d\n", status);
1319 : 0 : return status;
1320 : : }
1321 : :
1322 : 66 : status = vbdev_ocf_volume_init();
1323 [ - + ]: 66 : if (status) {
1324 : 0 : vbdev_ocf_ctx_cleanup();
1325 : 0 : SPDK_ERRLOG("OCF volume initialization failed with=%d\n", status);
1326 : 0 : return status;
1327 : : }
1328 : :
1329 : 66 : return status;
1330 : : }
1331 : :
1332 : : /* Called after application shutdown started
1333 : : * Release memory of allocated structures here */
1334 : : static void
1335 : 66 : vbdev_ocf_module_fini(void)
1336 : : {
1337 : : struct vbdev_ocf *vbdev;
1338 : :
1339 [ + + ]: 96 : while ((vbdev = TAILQ_FIRST(&g_ocf_vbdev_head))) {
1340 [ + + ]: 30 : TAILQ_REMOVE(&g_ocf_vbdev_head, vbdev, tailq);
1341 : 30 : free_vbdev(vbdev);
1342 : : }
1343 : :
1344 : 66 : vbdev_ocf_volume_cleanup();
1345 : 66 : vbdev_ocf_ctx_cleanup();
1346 : 66 : }
1347 : :
1348 : : /* When base device gets unplugged this is called
1349 : : * We will unregister cache vbdev here
1350 : : * When cache device is removed, we delete every OCF bdev that used it */
1351 : : static void
1352 : 4 : hotremove_cb(struct vbdev_ocf_base *base)
1353 : : {
1354 : : struct vbdev_ocf *vbdev;
1355 : :
1356 [ - + + + ]: 4 : if (!base->is_cache) {
1357 [ - + - + ]: 1 : if (base->parent->state.doing_finish) {
1358 : 0 : return;
1359 : : }
1360 : :
1361 : 1 : SPDK_NOTICELOG("Deinitializing '%s' because its core device '%s' was removed\n",
1362 : : base->parent->name, base->name);
1363 : 1 : vbdev_ocf_delete(base->parent, NULL, NULL);
1364 : 1 : return;
1365 : : }
1366 : :
1367 [ + + ]: 13 : TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
1368 [ - + + + ]: 10 : if (vbdev->state.doing_finish) {
1369 : 5 : continue;
1370 : : }
1371 [ - + - + : 5 : if (strcmp(base->name, vbdev->cache.name) == 0) {
+ - ]
1372 : 5 : SPDK_NOTICELOG("Deinitializing '%s' because"
1373 : : " its cache device '%s' was removed\n",
1374 : : vbdev->name, base->name);
1375 : 5 : vbdev_ocf_delete(vbdev, NULL, NULL);
1376 : : }
1377 : : }
1378 : : }
1379 : :
1380 : : static void
1381 : 4 : base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
1382 : : void *event_ctx)
1383 : : {
1384 [ + - ]: 4 : switch (type) {
1385 : 4 : case SPDK_BDEV_EVENT_REMOVE:
1386 [ + - ]: 4 : if (event_ctx) {
1387 : 4 : hotremove_cb(event_ctx);
1388 : : }
1389 : 4 : break;
1390 : 0 : default:
1391 : 0 : SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
1392 : 0 : break;
1393 : : }
1394 : 4 : }
1395 : :
1396 : : /* Open base SPDK bdev and claim it */
1397 : : static int
1398 : 55 : attach_base(struct vbdev_ocf_base *base)
1399 : : {
1400 : : int status;
1401 : :
1402 [ - + - + ]: 55 : if (base->attached) {
1403 : 0 : return -EALREADY;
1404 : : }
1405 : :
1406 : : /* If base cache bdev was already opened by other vbdev,
1407 : : * we just copy its descriptor here */
1408 [ - + + + ]: 55 : if (base->is_cache) {
1409 : 28 : struct vbdev_ocf_base *existing = get_other_cache_base(base);
1410 [ + + ]: 28 : if (existing) {
1411 : 8 : base->desc = existing->desc;
1412 : 8 : base->management_channel = existing->management_channel;
1413 : 8 : base->attached = true;
1414 : 8 : return 0;
1415 : : }
1416 : : }
1417 : :
1418 : 47 : status = spdk_bdev_open_ext(base->name, true, base_bdev_event_cb, base, &base->desc);
1419 [ - + ]: 47 : if (status) {
1420 : 0 : SPDK_ERRLOG("Unable to open device '%s' for writing\n", base->name);
1421 : 0 : return status;
1422 : : }
1423 : :
1424 : 47 : status = spdk_bdev_module_claim_bdev(base->bdev, base->desc,
1425 : : &ocf_if);
1426 [ - + ]: 47 : if (status) {
1427 : 0 : SPDK_ERRLOG("Unable to claim device '%s'\n", base->name);
1428 : 0 : spdk_bdev_close(base->desc);
1429 : 0 : return status;
1430 : : }
1431 : :
1432 : 47 : base->management_channel = spdk_bdev_get_io_channel(base->desc);
1433 [ - + ]: 47 : if (!base->management_channel) {
1434 : 0 : SPDK_ERRLOG("Unable to get io channel '%s'\n", base->name);
1435 : 0 : spdk_bdev_module_release_bdev(base->bdev);
1436 : 0 : spdk_bdev_close(base->desc);
1437 : 0 : return -ENOMEM;
1438 : : }
1439 : :
1440 : : /* Save the thread where the base device is opened */
1441 : 47 : base->thread = spdk_get_thread();
1442 : :
1443 : 47 : base->attached = true;
1444 : 47 : return status;
1445 : : }
1446 : :
1447 : : /* Attach base bdevs */
1448 : : static int
1449 : 32 : attach_base_bdevs(struct vbdev_ocf *vbdev,
1450 : : struct spdk_bdev *cache_bdev,
1451 : : struct spdk_bdev *core_bdev)
1452 : : {
1453 : 32 : int rc = 0;
1454 : :
1455 [ + + ]: 32 : if (cache_bdev) {
1456 : 28 : vbdev->cache.bdev = cache_bdev;
1457 : 28 : rc |= attach_base(&vbdev->cache);
1458 : : }
1459 : :
1460 [ + + ]: 32 : if (core_bdev) {
1461 : 27 : vbdev->core.bdev = core_bdev;
1462 : 27 : rc |= attach_base(&vbdev->core);
1463 : : }
1464 : :
1465 : 32 : return rc;
1466 : : }
1467 : :
1468 : : /* Init and then start vbdev if all base devices are present */
1469 : : void
1470 : 30 : vbdev_ocf_construct(const char *vbdev_name,
1471 : : const char *cache_mode_name,
1472 : : const uint64_t cache_line_size,
1473 : : const char *cache_name,
1474 : : const char *core_name,
1475 : : bool loadq,
1476 : : void (*cb)(int, struct vbdev_ocf *, void *),
1477 : : void *cb_arg)
1478 : : {
1479 : : int rc;
1480 : 30 : struct spdk_bdev *cache_bdev = spdk_bdev_get_by_name(cache_name);
1481 : 30 : struct spdk_bdev *core_bdev = spdk_bdev_get_by_name(core_name);
1482 : : struct vbdev_ocf *vbdev;
1483 : :
1484 : 30 : rc = init_vbdev(vbdev_name, cache_mode_name, cache_line_size, cache_name, core_name, loadq);
1485 [ - + ]: 30 : if (rc) {
1486 : 0 : cb(rc, NULL, cb_arg);
1487 : 0 : return;
1488 : : }
1489 : :
1490 : 30 : vbdev = vbdev_ocf_get_by_name(vbdev_name);
1491 [ - + ]: 30 : if (vbdev == NULL) {
1492 : 0 : cb(-ENODEV, NULL, cb_arg);
1493 : 0 : return;
1494 : : }
1495 : :
1496 [ + + ]: 30 : if (cache_bdev == NULL) {
1497 : 4 : SPDK_NOTICELOG("OCF bdev '%s' is waiting for cache device '%s' to connect\n",
1498 : : vbdev->name, cache_name);
1499 : : }
1500 [ + + ]: 30 : if (core_bdev == NULL) {
1501 : 3 : SPDK_NOTICELOG("OCF bdev '%s' is waiting for core device '%s' to connect\n",
1502 : : vbdev->name, core_name);
1503 : : }
1504 : :
1505 : 30 : rc = attach_base_bdevs(vbdev, cache_bdev, core_bdev);
1506 [ - + ]: 30 : if (rc) {
1507 : 0 : cb(rc, vbdev, cb_arg);
1508 : 0 : return;
1509 : : }
1510 : :
1511 [ + + + + ]: 30 : if (core_bdev && cache_bdev) {
1512 : 23 : register_vbdev(vbdev, cb, cb_arg);
1513 : : } else {
1514 : 7 : cb(0, vbdev, cb_arg);
1515 : : }
1516 : : }
1517 : :
1518 : : /* Set new cache mode on OCF cache */
1519 : : void
1520 : 6 : vbdev_ocf_set_cache_mode(struct vbdev_ocf *vbdev,
1521 : : const char *cache_mode_name,
1522 : : void (*cb)(int, struct vbdev_ocf *, void *),
1523 : : void *cb_arg)
1524 : : {
1525 : : ocf_cache_t cache;
1526 : : ocf_cache_mode_t cache_mode;
1527 : : int rc;
1528 : :
1529 : 6 : cache = vbdev->ocf_cache;
1530 : 6 : cache_mode = ocf_get_cache_mode(cache_mode_name);
1531 : :
1532 : 6 : rc = ocf_mngt_cache_trylock(cache);
1533 [ - + ]: 6 : if (rc) {
1534 : 0 : cb(rc, vbdev, cb_arg);
1535 : 0 : return;
1536 : : }
1537 : :
1538 : 6 : rc = ocf_mngt_cache_set_mode(cache, cache_mode);
1539 : 6 : ocf_mngt_cache_unlock(cache);
1540 : 6 : cb(rc, vbdev, cb_arg);
1541 : : }
1542 : :
1543 : : /* Set sequential cutoff parameters on OCF cache */
1544 : : void
1545 : 2 : vbdev_ocf_set_seqcutoff(struct vbdev_ocf *vbdev, const char *policy_name, uint32_t threshold,
1546 : : uint32_t promotion_count, void (*cb)(int, void *), void *cb_arg)
1547 : : {
1548 : : ocf_cache_t cache;
1549 : : ocf_seq_cutoff_policy policy;
1550 : : int rc;
1551 : :
1552 : 2 : cache = vbdev->ocf_cache;
1553 : :
1554 : 2 : policy = ocf_get_seqcutoff_policy(policy_name);
1555 [ - + ]: 2 : if (policy == ocf_seq_cutoff_policy_max) {
1556 : 0 : cb(OCF_ERR_INVAL, cb_arg);
1557 : 0 : return;
1558 : : }
1559 : :
1560 : 2 : rc = ocf_mngt_cache_trylock(cache);
1561 [ - + ]: 2 : if (rc) {
1562 : 0 : cb(rc, cb_arg);
1563 : 0 : return;
1564 : : }
1565 : :
1566 : 2 : rc = ocf_mngt_core_set_seq_cutoff_policy_all(cache, policy);
1567 [ - + ]: 2 : if (rc) {
1568 : 0 : goto end;
1569 : : }
1570 : :
1571 [ + - ]: 2 : if (threshold) {
1572 : 2 : threshold = threshold * KiB;
1573 : :
1574 : 2 : rc = ocf_mngt_core_set_seq_cutoff_threshold_all(cache, threshold);
1575 [ - + ]: 2 : if (rc) {
1576 : 0 : goto end;
1577 : : }
1578 : : }
1579 : :
1580 [ + - ]: 2 : if (promotion_count) {
1581 : 0 : rc = ocf_mngt_core_set_seq_cutoff_promotion_count_all(cache, promotion_count);
1582 : : }
1583 : :
1584 : 2 : end:
1585 : 2 : ocf_mngt_cache_unlock(cache);
1586 : 2 : cb(rc, cb_arg);
1587 : : }
1588 : :
1589 : : /* This called if new device is created in SPDK application
1590 : : * If that device named as one of base bdevs of OCF vbdev,
1591 : : * claim and open them */
1592 : : static void
1593 : 125 : vbdev_ocf_examine(struct spdk_bdev *bdev)
1594 : : {
1595 : 125 : const char *bdev_name = spdk_bdev_get_name(bdev);
1596 : : struct vbdev_ocf *vbdev;
1597 : :
1598 [ + + ]: 218 : TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
1599 [ - + + + ]: 93 : if (vbdev->state.doing_finish) {
1600 : 51 : continue;
1601 : : }
1602 : :
1603 [ - + - + : 42 : if (!strcmp(bdev_name, vbdev->cache.name)) {
+ + ]
1604 : 2 : attach_base_bdevs(vbdev, bdev, NULL);
1605 : 2 : continue;
1606 : : }
1607 [ - + - + : 40 : if (!strcmp(bdev_name, vbdev->core.name)) {
- + ]
1608 : 0 : attach_base_bdevs(vbdev, NULL, bdev);
1609 : 0 : break;
1610 : : }
1611 : : }
1612 : 125 : spdk_bdev_module_examine_done(&ocf_if);
1613 : 125 : }
1614 : :
1615 : : struct metadata_probe_ctx {
1616 : : struct vbdev_ocf_base base;
1617 : : ocf_volume_t volume;
1618 : :
1619 : : struct ocf_volume_uuid *core_uuids;
1620 : : unsigned int uuid_count;
1621 : :
1622 : : int result;
1623 : : int refcnt;
1624 : : };
1625 : :
1626 : : static void
1627 : 0 : _examine_ctx_put(void *ctx)
1628 : : {
1629 : 0 : struct spdk_bdev_desc *desc = ctx;
1630 : :
1631 : 0 : spdk_bdev_close(desc);
1632 : 0 : }
1633 : :
1634 : : static void
1635 : 124 : examine_ctx_put(struct metadata_probe_ctx *ctx)
1636 : : {
1637 : : unsigned int i;
1638 : :
1639 : 124 : ctx->refcnt--;
1640 [ - + ]: 124 : if (ctx->refcnt > 0) {
1641 : 0 : return;
1642 : : }
1643 : :
1644 [ - + ]: 124 : if (ctx->result) {
1645 : 0 : SPDK_ERRLOG("OCF metadata probe for bdev '%s' failed with %d\n",
1646 : : spdk_bdev_get_name(ctx->base.bdev), ctx->result);
1647 : : }
1648 : :
1649 [ + - ]: 124 : if (ctx->base.desc) {
1650 : : /* Close the underlying bdev on its same opened thread. */
1651 [ + - - + ]: 124 : if (ctx->base.thread && ctx->base.thread != spdk_get_thread()) {
1652 : 0 : spdk_thread_send_msg(ctx->base.thread, _examine_ctx_put, ctx->base.desc);
1653 : : } else {
1654 : 124 : spdk_bdev_close(ctx->base.desc);
1655 : : }
1656 : : }
1657 : :
1658 [ + - ]: 124 : if (ctx->volume) {
1659 : 124 : ocf_volume_destroy(ctx->volume);
1660 : : }
1661 : :
1662 [ - + ]: 124 : if (ctx->core_uuids) {
1663 [ # # ]: 0 : for (i = 0; i < ctx->uuid_count; i++) {
1664 : 0 : free(ctx->core_uuids[i].data);
1665 : : }
1666 : : }
1667 : 124 : free(ctx->core_uuids);
1668 : :
1669 : 124 : examine_done(ctx->result, NULL, ctx->base.bdev);
1670 : 124 : free(ctx);
1671 : : }
1672 : :
1673 : : static void
1674 : 124 : metadata_probe_cb(void *priv, int rc,
1675 : : struct ocf_metadata_probe_status *status)
1676 : : {
1677 : 124 : struct metadata_probe_ctx *ctx = priv;
1678 : :
1679 [ + - ]: 124 : if (rc) {
1680 : : /* -ENODATA means device does not have cache metadata on it */
1681 [ - + ]: 124 : if (rc != -OCF_ERR_NO_METADATA) {
1682 : 0 : ctx->result = rc;
1683 : : }
1684 : : }
1685 : :
1686 : 124 : examine_ctx_put(ctx);
1687 : 124 : }
1688 : :
1689 : : /* This is called after vbdev_ocf_examine
1690 : : * It allows to delay application initialization
1691 : : * until all OCF bdevs get registered
1692 : : * If vbdev has all of its base devices it starts asynchronously here
1693 : : * We first check if bdev appears in configuration,
1694 : : * if not we do metadata_probe() to create its configuration from bdev metadata */
1695 : : static void
1696 : 125 : vbdev_ocf_examine_disk(struct spdk_bdev *bdev)
1697 : : {
1698 : 125 : const char *bdev_name = spdk_bdev_get_name(bdev);
1699 : : struct vbdev_ocf *vbdev;
1700 : : struct metadata_probe_ctx *ctx;
1701 : 125 : bool created_from_config = false;
1702 : : int rc;
1703 : :
1704 : 125 : examine_start(bdev);
1705 : :
1706 [ + + ]: 218 : TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
1707 [ - + + + : 93 : if (vbdev->state.doing_finish || vbdev->state.started) {
- + + + ]
1708 : 63 : continue;
1709 : : }
1710 : :
1711 [ - + - + : 30 : if (!strcmp(bdev_name, vbdev->cache.name)) {
+ + ]
1712 : 2 : examine_start(bdev);
1713 : 2 : register_vbdev(vbdev, examine_done, bdev);
1714 : 2 : created_from_config = true;
1715 : 2 : continue;
1716 : : }
1717 [ - + - + : 28 : if (!strcmp(bdev_name, vbdev->core.name)) {
- + ]
1718 : 0 : examine_start(bdev);
1719 : 0 : register_vbdev(vbdev, examine_done, bdev);
1720 : 0 : examine_done(0, NULL, bdev);
1721 : 0 : return;
1722 : : }
1723 : : }
1724 : :
1725 : : /* If devices is discovered during config we do not check for metadata */
1726 [ + + ]: 125 : if (created_from_config) {
1727 : 1 : examine_done(0, NULL, bdev);
1728 : 1 : return;
1729 : : }
1730 : :
1731 : : /* Metadata probe path
1732 : : * We create temporary OCF volume and a temporary base structure
1733 : : * to use them for ocf_metadata_probe() and for bottom adapter IOs
1734 : : * Then we get UUIDs of core devices an create configurations based on them */
1735 : 124 : ctx = calloc(1, sizeof(*ctx));
1736 [ - + ]: 124 : if (!ctx) {
1737 : 0 : examine_done(-ENOMEM, NULL, bdev);
1738 : 0 : return;
1739 : : }
1740 : :
1741 : 124 : ctx->base.bdev = bdev;
1742 : 124 : ctx->refcnt = 1;
1743 : :
1744 : 124 : rc = spdk_bdev_open_ext(bdev_name, true, base_bdev_event_cb, NULL, &ctx->base.desc);
1745 [ - + ]: 124 : if (rc) {
1746 : 0 : ctx->result = rc;
1747 : 0 : examine_ctx_put(ctx);
1748 : 0 : return;
1749 : : }
1750 : :
1751 : 124 : rc = ocf_ctx_volume_create(vbdev_ocf_ctx, &ctx->volume, NULL, SPDK_OBJECT);
1752 [ - + ]: 124 : if (rc) {
1753 : 0 : ctx->result = rc;
1754 : 0 : examine_ctx_put(ctx);
1755 : 0 : return;
1756 : : }
1757 : :
1758 : 124 : rc = ocf_volume_open(ctx->volume, &ctx->base);
1759 [ - + ]: 124 : if (rc) {
1760 : 0 : ctx->result = rc;
1761 : 0 : examine_ctx_put(ctx);
1762 : 0 : return;
1763 : : }
1764 : :
1765 : : /* Save the thread where the base device is opened */
1766 : 124 : ctx->base.thread = spdk_get_thread();
1767 : :
1768 : 124 : ocf_metadata_probe(vbdev_ocf_ctx, ctx->volume, metadata_probe_cb, ctx);
1769 : : }
1770 : :
1771 : : static int
1772 : 66 : vbdev_ocf_get_ctx_size(void)
1773 : : {
1774 : 66 : return sizeof(struct bdev_ocf_data);
1775 : : }
1776 : :
1777 : : static void
1778 : 66 : fini_start(void)
1779 : : {
1780 : 66 : g_fini_started = true;
1781 : 66 : }
1782 : :
1783 : : /* Module-global function table
1784 : : * Does not relate to vbdev instances */
1785 : : static struct spdk_bdev_module ocf_if = {
1786 : : .name = "ocf",
1787 : : .module_init = vbdev_ocf_init,
1788 : : .fini_start = fini_start,
1789 : : .module_fini = vbdev_ocf_module_fini,
1790 : : .get_ctx_size = vbdev_ocf_get_ctx_size,
1791 : : .examine_config = vbdev_ocf_examine,
1792 : : .examine_disk = vbdev_ocf_examine_disk,
1793 : : };
1794 : 74 : SPDK_BDEV_MODULE_REGISTER(ocf, &ocf_if);
|