xref: /spdk/module/bdev/ocf/vbdev_ocf.c (revision 3511bd0927b39cdab5f9554f081c06678a1a3fb9)
1488570ebSJim Harris /*   SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse  *   Copyright (C) 2018 Intel Corporation.
307fe6a43SSeth Howell  *   All rights reserved.
407fe6a43SSeth Howell  */
507fe6a43SSeth Howell 
607fe6a43SSeth Howell #include <ocf/ocf.h>
707fe6a43SSeth Howell #include <ocf/ocf_types.h>
807fe6a43SSeth Howell #include <ocf/ocf_mngt.h>
907fe6a43SSeth Howell 
1007fe6a43SSeth Howell #include "ctx.h"
1107fe6a43SSeth Howell #include "data.h"
1207fe6a43SSeth Howell #include "volume.h"
1307fe6a43SSeth Howell #include "utils.h"
1407fe6a43SSeth Howell #include "vbdev_ocf.h"
1507fe6a43SSeth Howell 
1607fe6a43SSeth Howell #include "spdk/bdev_module.h"
178e05b15cSDarek Stojaczyk #include "spdk/thread.h"
1807fe6a43SSeth Howell #include "spdk/string.h"
194e8e97c8STomasz Zawadzki #include "spdk/log.h"
2007fe6a43SSeth Howell #include "spdk/cpuset.h"
2107fe6a43SSeth Howell 
22504cac51SKrzysztof Karas /* This namespace UUID was generated using uuid_generate() method. */
23504cac51SKrzysztof Karas #define BDEV_OCF_NAMESPACE_UUID "f92b7f49-f6c0-44c8-bd23-3205e8c3b6ad"
24504cac51SKrzysztof Karas 
2507fe6a43SSeth Howell static struct spdk_bdev_module ocf_if;
2607fe6a43SSeth Howell 
2707fe6a43SSeth Howell static TAILQ_HEAD(, vbdev_ocf) g_ocf_vbdev_head
2807fe6a43SSeth Howell 	= TAILQ_HEAD_INITIALIZER(g_ocf_vbdev_head);
2907fe6a43SSeth Howell 
3007fe6a43SSeth Howell static TAILQ_HEAD(, examining_bdev) g_ocf_examining_bdevs_head
3107fe6a43SSeth Howell 	= TAILQ_HEAD_INITIALIZER(g_ocf_examining_bdevs_head);
3207fe6a43SSeth Howell 
33a72cda21SPierre Lestringant static bool g_fini_started = false;
3407fe6a43SSeth Howell 
3507fe6a43SSeth Howell /* Structure for keeping list of bdevs that are claimed but not used yet */
3607fe6a43SSeth Howell struct examining_bdev {
3707fe6a43SSeth Howell 	struct spdk_bdev           *bdev;
3807fe6a43SSeth Howell 	TAILQ_ENTRY(examining_bdev) tailq;
3907fe6a43SSeth Howell };
4007fe6a43SSeth Howell 
4107fe6a43SSeth Howell /* Add bdev to list of claimed */
4207fe6a43SSeth Howell static void
4307fe6a43SSeth Howell examine_start(struct spdk_bdev *bdev)
4407fe6a43SSeth Howell {
4507fe6a43SSeth Howell 	struct examining_bdev *entry = malloc(sizeof(*entry));
4607fe6a43SSeth Howell 
4707fe6a43SSeth Howell 	assert(entry);
4807fe6a43SSeth Howell 	entry->bdev = bdev;
4907fe6a43SSeth Howell 	TAILQ_INSERT_TAIL(&g_ocf_examining_bdevs_head, entry, tailq);
5007fe6a43SSeth Howell }
5107fe6a43SSeth Howell 
5207fe6a43SSeth Howell /* Find bdev on list of claimed bdevs, then remove it,
5307fe6a43SSeth Howell  * if it was the last one on list then report examine done */
5407fe6a43SSeth Howell static void
5507fe6a43SSeth Howell examine_done(int status, struct vbdev_ocf *vbdev, void *cb_arg)
5607fe6a43SSeth Howell {
5707fe6a43SSeth Howell 	struct spdk_bdev *bdev = cb_arg;
5807fe6a43SSeth Howell 	struct examining_bdev *entry, *safe, *found = NULL;
5907fe6a43SSeth Howell 
6007fe6a43SSeth Howell 	TAILQ_FOREACH_SAFE(entry, &g_ocf_examining_bdevs_head, tailq, safe) {
6107fe6a43SSeth Howell 		if (entry->bdev == bdev) {
6207fe6a43SSeth Howell 			if (found) {
6307fe6a43SSeth Howell 				goto remove;
6407fe6a43SSeth Howell 			} else {
6507fe6a43SSeth Howell 				found = entry;
6607fe6a43SSeth Howell 			}
6707fe6a43SSeth Howell 		}
6807fe6a43SSeth Howell 	}
6907fe6a43SSeth Howell 
7007fe6a43SSeth Howell 	assert(found);
7107fe6a43SSeth Howell 	spdk_bdev_module_examine_done(&ocf_if);
7207fe6a43SSeth Howell 
7307fe6a43SSeth Howell remove:
7407fe6a43SSeth Howell 	TAILQ_REMOVE(&g_ocf_examining_bdevs_head, found, tailq);
7507fe6a43SSeth Howell 	free(found);
7607fe6a43SSeth Howell }
7707fe6a43SSeth Howell 
7807fe6a43SSeth Howell /* Free allocated strings and structure itself
7907fe6a43SSeth Howell  * Used at shutdown only */
8007fe6a43SSeth Howell static void
8107fe6a43SSeth Howell free_vbdev(struct vbdev_ocf *vbdev)
8207fe6a43SSeth Howell {
8307fe6a43SSeth Howell 	if (!vbdev) {
8407fe6a43SSeth Howell 		return;
8507fe6a43SSeth Howell 	}
8607fe6a43SSeth Howell 
8707fe6a43SSeth Howell 	free(vbdev->name);
8807fe6a43SSeth Howell 	free(vbdev->cache.name);
8907fe6a43SSeth Howell 	free(vbdev->core.name);
9007fe6a43SSeth Howell 	free(vbdev);
9107fe6a43SSeth Howell }
9207fe6a43SSeth Howell 
9307fe6a43SSeth Howell /* Get existing cache base
9407fe6a43SSeth Howell  * that is attached to other vbdev */
9507fe6a43SSeth Howell static struct vbdev_ocf_base *
9607fe6a43SSeth Howell get_other_cache_base(struct vbdev_ocf_base *base)
9707fe6a43SSeth Howell {
9807fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
9907fe6a43SSeth Howell 
10007fe6a43SSeth Howell 	TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
10107fe6a43SSeth Howell 		if (&vbdev->cache == base || !vbdev->cache.attached) {
10207fe6a43SSeth Howell 			continue;
10307fe6a43SSeth Howell 		}
10407fe6a43SSeth Howell 		if (!strcmp(vbdev->cache.name, base->name)) {
10507fe6a43SSeth Howell 			return &vbdev->cache;
10607fe6a43SSeth Howell 		}
10707fe6a43SSeth Howell 	}
10807fe6a43SSeth Howell 
10907fe6a43SSeth Howell 	return NULL;
11007fe6a43SSeth Howell }
11107fe6a43SSeth Howell 
112868ba177STomasz Zawadzki static bool
113868ba177STomasz Zawadzki is_ocf_cache_running(struct vbdev_ocf *vbdev)
114868ba177STomasz Zawadzki {
115868ba177STomasz Zawadzki 	if (vbdev->cache.attached && vbdev->ocf_cache) {
116868ba177STomasz Zawadzki 		return ocf_cache_is_running(vbdev->ocf_cache);
117868ba177STomasz Zawadzki 	}
118868ba177STomasz Zawadzki 	return false;
119868ba177STomasz Zawadzki }
120868ba177STomasz Zawadzki 
12137975647SAmir Haroush static bool
122*3511bd09SRafal Stefanowski is_ocf_cache_detached(struct vbdev_ocf *vbdev)
12337975647SAmir Haroush {
12437975647SAmir Haroush 	if (vbdev->cache.attached && vbdev->ocf_cache) {
125*3511bd09SRafal Stefanowski 		return ocf_cache_is_detached(vbdev->ocf_cache);
12637975647SAmir Haroush 	}
12737975647SAmir Haroush 	return false;
12837975647SAmir Haroush }
12937975647SAmir Haroush 
13007fe6a43SSeth Howell /* Get existing OCF cache instance
13107fe6a43SSeth Howell  * that is started by other vbdev */
13207fe6a43SSeth Howell static ocf_cache_t
13307fe6a43SSeth Howell get_other_cache_instance(struct vbdev_ocf *vbdev)
13407fe6a43SSeth Howell {
13507fe6a43SSeth Howell 	struct vbdev_ocf *cmp;
13607fe6a43SSeth Howell 
13707fe6a43SSeth Howell 	TAILQ_FOREACH(cmp, &g_ocf_vbdev_head, tailq) {
13807fe6a43SSeth Howell 		if (cmp->state.doing_finish || cmp == vbdev) {
13907fe6a43SSeth Howell 			continue;
14007fe6a43SSeth Howell 		}
14107fe6a43SSeth Howell 		if (strcmp(cmp->cache.name, vbdev->cache.name)) {
14207fe6a43SSeth Howell 			continue;
14307fe6a43SSeth Howell 		}
144*3511bd09SRafal Stefanowski 		if (is_ocf_cache_running(cmp) || is_ocf_cache_detached(cmp)) {
14507fe6a43SSeth Howell 			return cmp->ocf_cache;
14607fe6a43SSeth Howell 		}
14707fe6a43SSeth Howell 	}
14807fe6a43SSeth Howell 
14907fe6a43SSeth Howell 	return NULL;
15007fe6a43SSeth Howell }
15107fe6a43SSeth Howell 
152b3be320dSGangCao static void
153b3be320dSGangCao _remove_base_bdev(void *ctx)
154b3be320dSGangCao {
155b3be320dSGangCao 	struct spdk_bdev_desc *desc = ctx;
156b3be320dSGangCao 
157b3be320dSGangCao 	spdk_bdev_close(desc);
158b3be320dSGangCao }
159b3be320dSGangCao 
16007fe6a43SSeth Howell /* Close and unclaim base bdev */
16107fe6a43SSeth Howell static void
16207fe6a43SSeth Howell remove_base_bdev(struct vbdev_ocf_base *base)
16307fe6a43SSeth Howell {
16407fe6a43SSeth Howell 	if (base->attached) {
1651b6d1c80SMarcin Dziegielewski 		if (base->management_channel) {
1661b6d1c80SMarcin Dziegielewski 			spdk_put_io_channel(base->management_channel);
1671b6d1c80SMarcin Dziegielewski 		}
1681b6d1c80SMarcin Dziegielewski 
16907fe6a43SSeth Howell 		spdk_bdev_module_release_bdev(base->bdev);
170b3be320dSGangCao 		/* Close the underlying bdev on its same opened thread. */
171b3be320dSGangCao 		if (base->thread && base->thread != spdk_get_thread()) {
172b3be320dSGangCao 			spdk_thread_send_msg(base->thread, _remove_base_bdev, base->desc);
173b3be320dSGangCao 		} else {
17407fe6a43SSeth Howell 			spdk_bdev_close(base->desc);
175b3be320dSGangCao 		}
17607fe6a43SSeth Howell 		base->attached = false;
17707fe6a43SSeth Howell 	}
17807fe6a43SSeth Howell }
17907fe6a43SSeth Howell 
18007fe6a43SSeth Howell /* Finish unregister operation */
18107fe6a43SSeth Howell static void
18207fe6a43SSeth Howell unregister_finish(struct vbdev_ocf *vbdev)
18307fe6a43SSeth Howell {
18407fe6a43SSeth Howell 	spdk_bdev_destruct_done(&vbdev->exp_bdev, vbdev->state.stop_status);
1858fcb8b96SRafal Stefanowski 
1868fcb8b96SRafal Stefanowski 	if (vbdev->ocf_cache) {
1871350922dSTomasz Zawadzki 		ocf_mngt_cache_put(vbdev->ocf_cache);
1888fcb8b96SRafal Stefanowski 	}
1898fcb8b96SRafal Stefanowski 
190074a63d5SRafal Stefanowski 	if (vbdev->cache_ctx) {
19107fe6a43SSeth Howell 		vbdev_ocf_cache_ctx_put(vbdev->cache_ctx);
192074a63d5SRafal Stefanowski 	}
19307fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, 0);
19407fe6a43SSeth Howell }
19507fe6a43SSeth Howell 
19607fe6a43SSeth Howell static void
19707fe6a43SSeth Howell close_core_bdev(struct vbdev_ocf *vbdev)
19807fe6a43SSeth Howell {
19907fe6a43SSeth Howell 	remove_base_bdev(&vbdev->core);
20007fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, 0);
20107fe6a43SSeth Howell }
20207fe6a43SSeth Howell 
20307fe6a43SSeth Howell static void
20407fe6a43SSeth Howell remove_core_cmpl(void *priv, int error)
20507fe6a43SSeth Howell {
20607fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = priv;
20707fe6a43SSeth Howell 
20807fe6a43SSeth Howell 	ocf_mngt_cache_unlock(vbdev->ocf_cache);
20907fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, error);
21007fe6a43SSeth Howell }
21107fe6a43SSeth Howell 
21207fe6a43SSeth Howell /* Try to lock cache, then remove core */
21307fe6a43SSeth Howell static void
214c74b4b32SMarcin Dziegielewski remove_core_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
21507fe6a43SSeth Howell {
216c74b4b32SMarcin Dziegielewski 	struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
21707fe6a43SSeth Howell 
218c74b4b32SMarcin Dziegielewski 	if (error) {
219c74b4b32SMarcin Dziegielewski 		SPDK_ERRLOG("Error %d, can not lock cache instance %s\n",
220c74b4b32SMarcin Dziegielewski 			    error, vbdev->name);
221c74b4b32SMarcin Dziegielewski 		vbdev_ocf_mngt_continue(vbdev, error);
22207fe6a43SSeth Howell 		return;
22307fe6a43SSeth Howell 	}
22407fe6a43SSeth Howell 
22507fe6a43SSeth Howell 	ocf_mngt_cache_remove_core(vbdev->ocf_core, remove_core_cmpl, vbdev);
22607fe6a43SSeth Howell }
22707fe6a43SSeth Howell 
22807fe6a43SSeth Howell /* Detach core base */
22907fe6a43SSeth Howell static void
23007fe6a43SSeth Howell detach_core(struct vbdev_ocf *vbdev)
23107fe6a43SSeth Howell {
232868ba177STomasz Zawadzki 	if (is_ocf_cache_running(vbdev)) {
233c74b4b32SMarcin Dziegielewski 		ocf_mngt_cache_lock(vbdev->ocf_cache, remove_core_cache_lock_cmpl, vbdev);
23407fe6a43SSeth Howell 	} else {
23507fe6a43SSeth Howell 		vbdev_ocf_mngt_continue(vbdev, 0);
23607fe6a43SSeth Howell 	}
23707fe6a43SSeth Howell }
23807fe6a43SSeth Howell 
23907fe6a43SSeth Howell static void
24007fe6a43SSeth Howell close_cache_bdev(struct vbdev_ocf *vbdev)
24107fe6a43SSeth Howell {
24207fe6a43SSeth Howell 	remove_base_bdev(&vbdev->cache);
24307fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, 0);
24407fe6a43SSeth Howell }
24507fe6a43SSeth Howell 
24607fe6a43SSeth Howell /* Detach cache base */
24707fe6a43SSeth Howell static void
24807fe6a43SSeth Howell detach_cache(struct vbdev_ocf *vbdev)
24907fe6a43SSeth Howell {
25007fe6a43SSeth Howell 	vbdev->state.stop_status = vbdev->mngt_ctx.status;
25107fe6a43SSeth Howell 
25207fe6a43SSeth Howell 	/* If some other vbdev references this cache bdev,
25307fe6a43SSeth Howell 	 * we detach this only by changing the flag, without actual close */
25407fe6a43SSeth Howell 	if (get_other_cache_base(&vbdev->cache)) {
25507fe6a43SSeth Howell 		vbdev->cache.attached = false;
25607fe6a43SSeth Howell 	}
25707fe6a43SSeth Howell 
25807fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, 0);
25907fe6a43SSeth Howell }
26007fe6a43SSeth Howell 
26107fe6a43SSeth Howell static void
26207fe6a43SSeth Howell stop_vbdev_cmpl(ocf_cache_t cache, void *priv, int error)
26307fe6a43SSeth Howell {
26407fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = priv;
26507fe6a43SSeth Howell 
26607fe6a43SSeth Howell 	vbdev_ocf_queue_put(vbdev->cache_ctx->mngt_queue);
26707fe6a43SSeth Howell 	ocf_mngt_cache_unlock(cache);
26807fe6a43SSeth Howell 
26907fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, error);
27007fe6a43SSeth Howell }
27107fe6a43SSeth Howell 
27207fe6a43SSeth Howell /* Try to lock cache, then stop it */
27307fe6a43SSeth Howell static void
274c74b4b32SMarcin Dziegielewski stop_vbdev_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
275c74b4b32SMarcin Dziegielewski {
276c74b4b32SMarcin Dziegielewski 	struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
277c74b4b32SMarcin Dziegielewski 
278c74b4b32SMarcin Dziegielewski 	if (error) {
279c74b4b32SMarcin Dziegielewski 		SPDK_ERRLOG("Error %d, can not lock cache instance %s\n",
280c74b4b32SMarcin Dziegielewski 			    error, vbdev->name);
281c74b4b32SMarcin Dziegielewski 		vbdev_ocf_mngt_continue(vbdev, error);
282c74b4b32SMarcin Dziegielewski 		return;
283c74b4b32SMarcin Dziegielewski 	}
284c74b4b32SMarcin Dziegielewski 
285c74b4b32SMarcin Dziegielewski 	ocf_mngt_cache_stop(vbdev->ocf_cache, stop_vbdev_cmpl, vbdev);
286c74b4b32SMarcin Dziegielewski }
287c74b4b32SMarcin Dziegielewski 
288c74b4b32SMarcin Dziegielewski /* Stop OCF cache object
289c74b4b32SMarcin Dziegielewski  * vbdev_ocf is not operational after this */
290c74b4b32SMarcin Dziegielewski static void
291c74b4b32SMarcin Dziegielewski stop_vbdev(struct vbdev_ocf *vbdev)
29207fe6a43SSeth Howell {
293868ba177STomasz Zawadzki 	if (!is_ocf_cache_running(vbdev)) {
29407fe6a43SSeth Howell 		vbdev_ocf_mngt_continue(vbdev, 0);
29507fe6a43SSeth Howell 		return;
29607fe6a43SSeth Howell 	}
29707fe6a43SSeth Howell 
29807fe6a43SSeth Howell 	if (!g_fini_started && get_other_cache_instance(vbdev)) {
29907fe6a43SSeth Howell 		SPDK_NOTICELOG("Not stopping cache instance '%s'"
30007fe6a43SSeth Howell 			       " because it is referenced by other OCF bdev\n",
30107fe6a43SSeth Howell 			       vbdev->cache.name);
30207fe6a43SSeth Howell 		vbdev_ocf_mngt_continue(vbdev, 0);
30307fe6a43SSeth Howell 		return;
30407fe6a43SSeth Howell 	}
30507fe6a43SSeth Howell 
306c74b4b32SMarcin Dziegielewski 	ocf_mngt_cache_lock(vbdev->ocf_cache, stop_vbdev_cache_lock_cmpl, vbdev);
30707fe6a43SSeth Howell }
30807fe6a43SSeth Howell 
30907fe6a43SSeth Howell static void
31007fe6a43SSeth Howell flush_vbdev_cmpl(ocf_cache_t cache, void *priv, int error)
31107fe6a43SSeth Howell {
31207fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = priv;
31307fe6a43SSeth Howell 
31407fe6a43SSeth Howell 	ocf_mngt_cache_unlock(cache);
31507fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, error);
31607fe6a43SSeth Howell }
31707fe6a43SSeth Howell 
31807fe6a43SSeth Howell static void
319c74b4b32SMarcin Dziegielewski flush_vbdev_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
32007fe6a43SSeth Howell {
321c74b4b32SMarcin Dziegielewski 	struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
322c74b4b32SMarcin Dziegielewski 
323c74b4b32SMarcin Dziegielewski 	if (error) {
324c74b4b32SMarcin Dziegielewski 		SPDK_ERRLOG("Error %d, can not lock cache instance %s\n",
325c74b4b32SMarcin Dziegielewski 			    error, vbdev->name);
326c74b4b32SMarcin Dziegielewski 		vbdev_ocf_mngt_continue(vbdev, error);
32707fe6a43SSeth Howell 		return;
32807fe6a43SSeth Howell 	}
32907fe6a43SSeth Howell 
33020894340SMarcin Dziegielewski 	ocf_mngt_cache_flush(vbdev->ocf_cache, flush_vbdev_cmpl, vbdev);
33107fe6a43SSeth Howell }
33207fe6a43SSeth Howell 
33307fe6a43SSeth Howell static void
33407fe6a43SSeth Howell flush_vbdev(struct vbdev_ocf *vbdev)
33507fe6a43SSeth Howell {
336868ba177STomasz Zawadzki 	if (!is_ocf_cache_running(vbdev)) {
337c74b4b32SMarcin Dziegielewski 		vbdev_ocf_mngt_continue(vbdev, -EINVAL);
338c74b4b32SMarcin Dziegielewski 		return;
339c74b4b32SMarcin Dziegielewski 	}
340c74b4b32SMarcin Dziegielewski 
341c74b4b32SMarcin Dziegielewski 	ocf_mngt_cache_lock(vbdev->ocf_cache, flush_vbdev_cache_lock_cmpl, vbdev);
34207fe6a43SSeth Howell }
34307fe6a43SSeth Howell 
3441ee2e81bSMarcin Dziegielewski /* Procedures called during dirty unregister */
3451ee2e81bSMarcin Dziegielewski vbdev_ocf_mngt_fn unregister_path_dirty[] = {
34607fe6a43SSeth Howell 	flush_vbdev,
34707fe6a43SSeth Howell 	stop_vbdev,
34807fe6a43SSeth Howell 	detach_cache,
34907fe6a43SSeth Howell 	close_cache_bdev,
35007fe6a43SSeth Howell 	detach_core,
35107fe6a43SSeth Howell 	close_core_bdev,
35207fe6a43SSeth Howell 	unregister_finish,
35307fe6a43SSeth Howell 	NULL
35407fe6a43SSeth Howell };
35507fe6a43SSeth Howell 
3561ee2e81bSMarcin Dziegielewski /* Procedures called during clean unregister */
3571ee2e81bSMarcin Dziegielewski vbdev_ocf_mngt_fn unregister_path_clean[] = {
3581ee2e81bSMarcin Dziegielewski 	flush_vbdev,
3591ee2e81bSMarcin Dziegielewski 	detach_core,
3601ee2e81bSMarcin Dziegielewski 	close_core_bdev,
3611ee2e81bSMarcin Dziegielewski 	stop_vbdev,
3621ee2e81bSMarcin Dziegielewski 	detach_cache,
3631ee2e81bSMarcin Dziegielewski 	close_cache_bdev,
3641ee2e81bSMarcin Dziegielewski 	unregister_finish,
3651ee2e81bSMarcin Dziegielewski 	NULL
3661ee2e81bSMarcin Dziegielewski };
3671ee2e81bSMarcin Dziegielewski 
36807fe6a43SSeth Howell /* Start asynchronous management operation using unregister_path */
36907fe6a43SSeth Howell static void
37007fe6a43SSeth Howell unregister_cb(void *opaque)
37107fe6a43SSeth Howell {
37207fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = opaque;
3731ee2e81bSMarcin Dziegielewski 	vbdev_ocf_mngt_fn *unregister_path;
37407fe6a43SSeth Howell 	int rc;
37507fe6a43SSeth Howell 
3761ee2e81bSMarcin Dziegielewski 	unregister_path = vbdev->state.doing_clean_delete ?
3771ee2e81bSMarcin Dziegielewski 			  unregister_path_clean : unregister_path_dirty;
3781ee2e81bSMarcin Dziegielewski 
37907fe6a43SSeth Howell 	rc = vbdev_ocf_mngt_start(vbdev, unregister_path, NULL, NULL);
38007fe6a43SSeth Howell 	if (rc) {
38107fe6a43SSeth Howell 		SPDK_ERRLOG("Unable to unregister OCF bdev: %d\n", rc);
38207fe6a43SSeth Howell 		spdk_bdev_destruct_done(&vbdev->exp_bdev, rc);
38307fe6a43SSeth Howell 	}
38407fe6a43SSeth Howell }
38507fe6a43SSeth Howell 
3861ee2e81bSMarcin Dziegielewski /* Clean remove case - remove core and then cache, this order
3871ee2e81bSMarcin Dziegielewski  * will remove instance permanently */
3881ee2e81bSMarcin Dziegielewski static void
3891ee2e81bSMarcin Dziegielewski _vbdev_ocf_destruct_clean(struct vbdev_ocf *vbdev)
3901ee2e81bSMarcin Dziegielewski {
3911ee2e81bSMarcin Dziegielewski 	if (vbdev->core.attached) {
3921ee2e81bSMarcin Dziegielewski 		detach_core(vbdev);
3931ee2e81bSMarcin Dziegielewski 		close_core_bdev(vbdev);
3941ee2e81bSMarcin Dziegielewski 	}
3951ee2e81bSMarcin Dziegielewski 
3961ee2e81bSMarcin Dziegielewski 	if (vbdev->cache.attached) {
3971ee2e81bSMarcin Dziegielewski 		detach_cache(vbdev);
3981ee2e81bSMarcin Dziegielewski 		close_cache_bdev(vbdev);
3991ee2e81bSMarcin Dziegielewski 	}
4001ee2e81bSMarcin Dziegielewski }
4011ee2e81bSMarcin Dziegielewski 
4021ee2e81bSMarcin Dziegielewski /* Dirty shutdown/hot remove case - remove cache and then core, this order
4031ee2e81bSMarcin Dziegielewski  * will allow us to recover this instance in the future */
4041ee2e81bSMarcin Dziegielewski static void
4051ee2e81bSMarcin Dziegielewski _vbdev_ocf_destruct_dirty(struct vbdev_ocf *vbdev)
4061ee2e81bSMarcin Dziegielewski {
4071ee2e81bSMarcin Dziegielewski 	if (vbdev->cache.attached) {
4081ee2e81bSMarcin Dziegielewski 		detach_cache(vbdev);
4091ee2e81bSMarcin Dziegielewski 		close_cache_bdev(vbdev);
4101ee2e81bSMarcin Dziegielewski 	}
4111ee2e81bSMarcin Dziegielewski 
4121ee2e81bSMarcin Dziegielewski 	if (vbdev->core.attached) {
4131ee2e81bSMarcin Dziegielewski 		detach_core(vbdev);
4141ee2e81bSMarcin Dziegielewski 		close_core_bdev(vbdev);
4151ee2e81bSMarcin Dziegielewski 	}
4161ee2e81bSMarcin Dziegielewski }
4171ee2e81bSMarcin Dziegielewski 
41807fe6a43SSeth Howell /* Unregister io device with callback to unregister_cb
41907fe6a43SSeth Howell  * This function is called during spdk_bdev_unregister */
42007fe6a43SSeth Howell static int
42107fe6a43SSeth Howell vbdev_ocf_destruct(void *opaque)
42207fe6a43SSeth Howell {
42307fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = opaque;
42407fe6a43SSeth Howell 
42507fe6a43SSeth Howell 	if (vbdev->state.doing_finish) {
42607fe6a43SSeth Howell 		return -EALREADY;
42707fe6a43SSeth Howell 	}
428d1c9e2f7SMarcin Dziegielewski 
429d1c9e2f7SMarcin Dziegielewski 	if (vbdev->state.starting && !vbdev->state.started) {
430d1c9e2f7SMarcin Dziegielewski 		/* Prevent before detach cache/core during register path of
431d1c9e2f7SMarcin Dziegielewski 		  this bdev */
432d1c9e2f7SMarcin Dziegielewski 		return -EBUSY;
433d1c9e2f7SMarcin Dziegielewski 	}
434d1c9e2f7SMarcin Dziegielewski 
43507fe6a43SSeth Howell 	vbdev->state.doing_finish = true;
43607fe6a43SSeth Howell 
43707fe6a43SSeth Howell 	if (vbdev->state.started) {
43807fe6a43SSeth Howell 		spdk_io_device_unregister(vbdev, unregister_cb);
43907fe6a43SSeth Howell 		/* Return 1 because unregister is delayed */
44007fe6a43SSeth Howell 		return 1;
44107fe6a43SSeth Howell 	}
44207fe6a43SSeth Howell 
4431ee2e81bSMarcin Dziegielewski 	if (vbdev->state.doing_clean_delete) {
4441ee2e81bSMarcin Dziegielewski 		_vbdev_ocf_destruct_clean(vbdev);
4451ee2e81bSMarcin Dziegielewski 	} else {
4461ee2e81bSMarcin Dziegielewski 		_vbdev_ocf_destruct_dirty(vbdev);
44707fe6a43SSeth Howell 	}
44807fe6a43SSeth Howell 
44907fe6a43SSeth Howell 	return 0;
45007fe6a43SSeth Howell }
45107fe6a43SSeth Howell 
45207fe6a43SSeth Howell /* Stop OCF cache and unregister SPDK bdev */
45307fe6a43SSeth Howell int
45407fe6a43SSeth Howell vbdev_ocf_delete(struct vbdev_ocf *vbdev, void (*cb)(void *, int), void *cb_arg)
45507fe6a43SSeth Howell {
45607fe6a43SSeth Howell 	int rc = 0;
45707fe6a43SSeth Howell 
45807fe6a43SSeth Howell 	if (vbdev->state.started) {
45907fe6a43SSeth Howell 		spdk_bdev_unregister(&vbdev->exp_bdev, cb, cb_arg);
46007fe6a43SSeth Howell 	} else {
46107fe6a43SSeth Howell 		rc = vbdev_ocf_destruct(vbdev);
46207fe6a43SSeth Howell 		if (rc == 0 && cb) {
46307fe6a43SSeth Howell 			cb(cb_arg, 0);
46407fe6a43SSeth Howell 		}
46507fe6a43SSeth Howell 	}
46607fe6a43SSeth Howell 
46707fe6a43SSeth Howell 	return rc;
46807fe6a43SSeth Howell }
46907fe6a43SSeth Howell 
4701ee2e81bSMarcin Dziegielewski /* Remove cores permanently and then stop OCF cache and unregister SPDK bdev */
4711ee2e81bSMarcin Dziegielewski int
4721ee2e81bSMarcin Dziegielewski vbdev_ocf_delete_clean(struct vbdev_ocf *vbdev, void (*cb)(void *, int),
4731ee2e81bSMarcin Dziegielewski 		       void *cb_arg)
4741ee2e81bSMarcin Dziegielewski {
4751ee2e81bSMarcin Dziegielewski 	vbdev->state.doing_clean_delete = true;
4761ee2e81bSMarcin Dziegielewski 
4771ee2e81bSMarcin Dziegielewski 	return vbdev_ocf_delete(vbdev, cb, cb_arg);
4781ee2e81bSMarcin Dziegielewski }
4791ee2e81bSMarcin Dziegielewski 
4801ee2e81bSMarcin Dziegielewski 
48107fe6a43SSeth Howell /* If vbdev is online, return its object */
48207fe6a43SSeth Howell struct vbdev_ocf *
48307fe6a43SSeth Howell vbdev_ocf_get_by_name(const char *name)
48407fe6a43SSeth Howell {
48507fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
48607fe6a43SSeth Howell 
48707fe6a43SSeth Howell 	if (name == NULL) {
48807fe6a43SSeth Howell 		assert(false);
48907fe6a43SSeth Howell 		return NULL;
49007fe6a43SSeth Howell 	}
49107fe6a43SSeth Howell 
49207fe6a43SSeth Howell 	TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
49307fe6a43SSeth Howell 		if (vbdev->name == NULL || vbdev->state.doing_finish) {
49407fe6a43SSeth Howell 			continue;
49507fe6a43SSeth Howell 		}
49607fe6a43SSeth Howell 		if (strcmp(vbdev->name, name) == 0) {
49707fe6a43SSeth Howell 			return vbdev;
49807fe6a43SSeth Howell 		}
49907fe6a43SSeth Howell 	}
50007fe6a43SSeth Howell 	return NULL;
50107fe6a43SSeth Howell }
50207fe6a43SSeth Howell 
50307fe6a43SSeth Howell /* Return matching base if parent vbdev is online */
50407fe6a43SSeth Howell struct vbdev_ocf_base *
50507fe6a43SSeth Howell vbdev_ocf_get_base_by_name(const char *name)
50607fe6a43SSeth Howell {
50707fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
50807fe6a43SSeth Howell 
50907fe6a43SSeth Howell 	if (name == NULL) {
51007fe6a43SSeth Howell 		assert(false);
51107fe6a43SSeth Howell 		return NULL;
51207fe6a43SSeth Howell 	}
51307fe6a43SSeth Howell 
51407fe6a43SSeth Howell 	TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
51507fe6a43SSeth Howell 		if (vbdev->state.doing_finish) {
51607fe6a43SSeth Howell 			continue;
51707fe6a43SSeth Howell 		}
51807fe6a43SSeth Howell 
51907fe6a43SSeth Howell 		if (vbdev->cache.name && strcmp(vbdev->cache.name, name) == 0) {
52007fe6a43SSeth Howell 			return &vbdev->cache;
52107fe6a43SSeth Howell 		}
52207fe6a43SSeth Howell 		if (vbdev->core.name && strcmp(vbdev->core.name, name) == 0) {
52307fe6a43SSeth Howell 			return &vbdev->core;
52407fe6a43SSeth Howell 		}
52507fe6a43SSeth Howell 	}
52607fe6a43SSeth Howell 	return NULL;
52707fe6a43SSeth Howell }
52807fe6a43SSeth Howell 
52907fe6a43SSeth Howell /* Execute fn for each OCF device that is online or waits for base devices */
53007fe6a43SSeth Howell void
53107fe6a43SSeth Howell vbdev_ocf_foreach(vbdev_ocf_foreach_fn fn, void *ctx)
53207fe6a43SSeth Howell {
53307fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
53407fe6a43SSeth Howell 
53507fe6a43SSeth Howell 	assert(fn != NULL);
53607fe6a43SSeth Howell 
53707fe6a43SSeth Howell 	TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
53807fe6a43SSeth Howell 		if (!vbdev->state.doing_finish) {
53907fe6a43SSeth Howell 			fn(vbdev, ctx);
54007fe6a43SSeth Howell 		}
54107fe6a43SSeth Howell 	}
54207fe6a43SSeth Howell }
54307fe6a43SSeth Howell 
54407fe6a43SSeth Howell /* Called from OCF when SPDK_IO is completed */
54507fe6a43SSeth Howell static void
546*3511bd09SRafal Stefanowski vbdev_ocf_io_submit_cb(ocf_io_t io, void *priv1, void *priv2, int error)
54707fe6a43SSeth Howell {
548*3511bd09SRafal Stefanowski 	struct spdk_bdev_io *bdev_io = priv1;
54907fe6a43SSeth Howell 
55007fe6a43SSeth Howell 	if (error == 0) {
55107fe6a43SSeth Howell 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
55284863d99SGal Hammer 	} else if (error == -OCF_ERR_NO_MEM) {
55307fe6a43SSeth Howell 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
55407fe6a43SSeth Howell 	} else {
55507fe6a43SSeth Howell 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
55607fe6a43SSeth Howell 	}
55707fe6a43SSeth Howell 
55807fe6a43SSeth Howell 	ocf_io_put(io);
55907fe6a43SSeth Howell }
56007fe6a43SSeth Howell 
56107fe6a43SSeth Howell /* Configure io parameters and send it to OCF */
56207fe6a43SSeth Howell static int
563*3511bd09SRafal Stefanowski io_submit_to_ocf(struct spdk_bdev_io *bdev_io, ocf_io_t io)
56407fe6a43SSeth Howell {
56507fe6a43SSeth Howell 	switch (bdev_io->type) {
56607fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_WRITE:
56707fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_READ:
56807fe6a43SSeth Howell 		ocf_core_submit_io(io);
56907fe6a43SSeth Howell 		return 0;
57007fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_FLUSH:
57107fe6a43SSeth Howell 		ocf_core_submit_flush(io);
57207fe6a43SSeth Howell 		return 0;
57307fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_UNMAP:
57407fe6a43SSeth Howell 		ocf_core_submit_discard(io);
57507fe6a43SSeth Howell 		return 0;
57607fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_RESET:
57707fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
57807fe6a43SSeth Howell 	default:
57907fe6a43SSeth Howell 		SPDK_ERRLOG("Unsupported IO type: %d\n", bdev_io->type);
58007fe6a43SSeth Howell 		return -EINVAL;
58107fe6a43SSeth Howell 	}
58207fe6a43SSeth Howell }
58307fe6a43SSeth Howell 
58407fe6a43SSeth Howell /* Submit SPDK-IO to OCF */
58507fe6a43SSeth Howell static void
58607fe6a43SSeth Howell io_handle(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
58707fe6a43SSeth Howell {
58807fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = bdev_io->bdev->ctxt;
589*3511bd09SRafal Stefanowski 	ocf_io_t io = NULL;
59007fe6a43SSeth Howell 	struct bdev_ocf_data *data = NULL;
591af039a7aSyidong0635 	struct vbdev_ocf_qctx *qctx = spdk_io_channel_get_ctx(ch);
592d7a3a052SVitaliy Mysak 	uint64_t len = bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen;
593d7a3a052SVitaliy Mysak 	uint64_t offset = bdev_io->u.bdev.offset_blocks * bdev_io->bdev->blocklen;
594d7a3a052SVitaliy Mysak 	int dir, flags = 0;
59507fe6a43SSeth Howell 	int err;
59607fe6a43SSeth Howell 
597d7a3a052SVitaliy Mysak 	switch (bdev_io->type) {
598d7a3a052SVitaliy Mysak 	case SPDK_BDEV_IO_TYPE_READ:
599d7a3a052SVitaliy Mysak 		dir = OCF_READ;
600d7a3a052SVitaliy Mysak 		break;
601d7a3a052SVitaliy Mysak 	case SPDK_BDEV_IO_TYPE_WRITE:
602d7a3a052SVitaliy Mysak 		dir = OCF_WRITE;
603d7a3a052SVitaliy Mysak 		break;
604d7a3a052SVitaliy Mysak 	case SPDK_BDEV_IO_TYPE_FLUSH:
605d7a3a052SVitaliy Mysak 		dir = OCF_WRITE;
606d7a3a052SVitaliy Mysak 		break;
607d7a3a052SVitaliy Mysak 	case SPDK_BDEV_IO_TYPE_UNMAP:
608d7a3a052SVitaliy Mysak 		dir = OCF_WRITE;
609d7a3a052SVitaliy Mysak 		break;
610d7a3a052SVitaliy Mysak 	default:
611d7a3a052SVitaliy Mysak 		err = -EINVAL;
612d7a3a052SVitaliy Mysak 		goto fail;
613d7a3a052SVitaliy Mysak 	}
614d7a3a052SVitaliy Mysak 
615d7a3a052SVitaliy Mysak 	if (bdev_io->type == SPDK_BDEV_IO_TYPE_FLUSH) {
616d7a3a052SVitaliy Mysak 		flags = OCF_WRITE_FLUSH;
617d7a3a052SVitaliy Mysak 	}
618d7a3a052SVitaliy Mysak 
61937975647SAmir Haroush 	io = ocf_volume_new_io(ocf_core_get_front_volume(vbdev->ocf_core), qctx->queue, offset, len, dir, 0,
62037975647SAmir Haroush 			       flags);
62107fe6a43SSeth Howell 	if (!io) {
62207fe6a43SSeth Howell 		err = -ENOMEM;
62307fe6a43SSeth Howell 		goto fail;
62407fe6a43SSeth Howell 	}
62507fe6a43SSeth Howell 
62607fe6a43SSeth Howell 	data = vbdev_ocf_data_from_spdk_io(bdev_io);
62707fe6a43SSeth Howell 	if (!data) {
62807fe6a43SSeth Howell 		err = -ENOMEM;
62907fe6a43SSeth Howell 		goto fail;
63007fe6a43SSeth Howell 	}
63107fe6a43SSeth Howell 
63207fe6a43SSeth Howell 	err = ocf_io_set_data(io, data, 0);
63307fe6a43SSeth Howell 	if (err) {
63407fe6a43SSeth Howell 		goto fail;
63507fe6a43SSeth Howell 	}
63607fe6a43SSeth Howell 
63707fe6a43SSeth Howell 	ocf_io_set_cmpl(io, bdev_io, NULL, vbdev_ocf_io_submit_cb);
63807fe6a43SSeth Howell 
63907fe6a43SSeth Howell 	err = io_submit_to_ocf(bdev_io, io);
64007fe6a43SSeth Howell 	if (err) {
64107fe6a43SSeth Howell 		goto fail;
64207fe6a43SSeth Howell 	}
64307fe6a43SSeth Howell 
64407fe6a43SSeth Howell 	return;
64507fe6a43SSeth Howell 
64607fe6a43SSeth Howell fail:
64707fe6a43SSeth Howell 	if (io) {
64807fe6a43SSeth Howell 		ocf_io_put(io);
64907fe6a43SSeth Howell 	}
65007fe6a43SSeth Howell 
65107fe6a43SSeth Howell 	if (err == -ENOMEM) {
65207fe6a43SSeth Howell 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
65307fe6a43SSeth Howell 	} else {
65407fe6a43SSeth Howell 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
65507fe6a43SSeth Howell 	}
65607fe6a43SSeth Howell }
65707fe6a43SSeth Howell 
65807fe6a43SSeth Howell static void
65907fe6a43SSeth Howell vbdev_ocf_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
66007fe6a43SSeth Howell 		     bool success)
66107fe6a43SSeth Howell {
66207fe6a43SSeth Howell 	if (!success) {
66307fe6a43SSeth Howell 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
66407fe6a43SSeth Howell 		return;
66507fe6a43SSeth Howell 	}
66607fe6a43SSeth Howell 
66707fe6a43SSeth Howell 	io_handle(ch, bdev_io);
66807fe6a43SSeth Howell }
66907fe6a43SSeth Howell 
67007fe6a43SSeth Howell /* Called from bdev layer when an io to Cache vbdev is submitted */
67107fe6a43SSeth Howell static void
67207fe6a43SSeth Howell vbdev_ocf_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
67307fe6a43SSeth Howell {
67407fe6a43SSeth Howell 	switch (bdev_io->type) {
67507fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_READ:
67607fe6a43SSeth Howell 		/* User does not have to allocate io vectors for the request,
67707fe6a43SSeth Howell 		 * so in case they are not allocated, we allocate them here */
67807fe6a43SSeth Howell 		spdk_bdev_io_get_buf(bdev_io, vbdev_ocf_get_buf_cb,
67907fe6a43SSeth Howell 				     bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
68007fe6a43SSeth Howell 		break;
68107fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_WRITE:
68207fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_FLUSH:
68307fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_UNMAP:
68407fe6a43SSeth Howell 		io_handle(ch, bdev_io);
68507fe6a43SSeth Howell 		break;
68607fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_RESET:
68707fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
68807fe6a43SSeth Howell 	default:
68907fe6a43SSeth Howell 		SPDK_ERRLOG("Unknown I/O type %d\n", bdev_io->type);
69007fe6a43SSeth Howell 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
69107fe6a43SSeth Howell 		break;
69207fe6a43SSeth Howell 	}
69307fe6a43SSeth Howell }
69407fe6a43SSeth Howell 
69507fe6a43SSeth Howell /* Called from bdev layer */
69607fe6a43SSeth Howell static bool
69707fe6a43SSeth Howell vbdev_ocf_io_type_supported(void *opaque, enum spdk_bdev_io_type io_type)
69807fe6a43SSeth Howell {
69907fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = opaque;
70007fe6a43SSeth Howell 
70107fe6a43SSeth Howell 	switch (io_type) {
70207fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_READ:
70307fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_WRITE:
70407fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_FLUSH:
70507fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_UNMAP:
70607fe6a43SSeth Howell 		return spdk_bdev_io_type_supported(vbdev->core.bdev, io_type);
70707fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_RESET:
70807fe6a43SSeth Howell 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
70907fe6a43SSeth Howell 	default:
71007fe6a43SSeth Howell 		return false;
71107fe6a43SSeth Howell 	}
71207fe6a43SSeth Howell }
71307fe6a43SSeth Howell 
71407fe6a43SSeth Howell /* Called from bdev layer */
71507fe6a43SSeth Howell static struct spdk_io_channel *
71607fe6a43SSeth Howell vbdev_ocf_get_io_channel(void *opaque)
71707fe6a43SSeth Howell {
71807fe6a43SSeth Howell 	struct vbdev_ocf *bdev = opaque;
71907fe6a43SSeth Howell 
72007fe6a43SSeth Howell 	return spdk_get_io_channel(bdev);
72107fe6a43SSeth Howell }
72207fe6a43SSeth Howell 
72307fe6a43SSeth Howell static int
72407fe6a43SSeth Howell vbdev_ocf_dump_info_json(void *opaque, struct spdk_json_write_ctx *w)
72507fe6a43SSeth Howell {
72607fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = opaque;
72707fe6a43SSeth Howell 
72807fe6a43SSeth Howell 	spdk_json_write_named_string(w, "cache_device", vbdev->cache.name);
72907fe6a43SSeth Howell 	spdk_json_write_named_string(w, "core_device", vbdev->core.name);
73007fe6a43SSeth Howell 
73107fe6a43SSeth Howell 	spdk_json_write_named_string(w, "mode",
73207fe6a43SSeth Howell 				     ocf_get_cache_modename(ocf_cache_get_mode(vbdev->ocf_cache)));
73307fe6a43SSeth Howell 	spdk_json_write_named_uint32(w, "cache_line_size",
7348fcb8b96SRafal Stefanowski 				     ocf_get_cache_line_size(vbdev->ocf_cache));
73507fe6a43SSeth Howell 	spdk_json_write_named_bool(w, "metadata_volatile",
73607fe6a43SSeth Howell 				   vbdev->cfg.cache.metadata_volatile);
73707fe6a43SSeth Howell 
73807fe6a43SSeth Howell 	return 0;
73907fe6a43SSeth Howell }
74007fe6a43SSeth Howell 
74107fe6a43SSeth Howell static void
74207fe6a43SSeth Howell vbdev_ocf_write_json_config(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
74307fe6a43SSeth Howell {
74407fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = bdev->ctxt;
74507fe6a43SSeth Howell 
74607fe6a43SSeth Howell 	spdk_json_write_object_begin(w);
74707fe6a43SSeth Howell 
748557f8ff9SPawel Kaminski 	spdk_json_write_named_string(w, "method", "bdev_ocf_create");
74907fe6a43SSeth Howell 
75007fe6a43SSeth Howell 	spdk_json_write_named_object_begin(w, "params");
75107fe6a43SSeth Howell 	spdk_json_write_named_string(w, "name", vbdev->name);
75207fe6a43SSeth Howell 	spdk_json_write_named_string(w, "mode",
75307fe6a43SSeth Howell 				     ocf_get_cache_modename(ocf_cache_get_mode(vbdev->ocf_cache)));
7544d91b4efSrafalste 	spdk_json_write_named_uint32(w, "cache_line_size",
7558fcb8b96SRafal Stefanowski 				     ocf_get_cache_line_size(vbdev->ocf_cache));
75607fe6a43SSeth Howell 	spdk_json_write_named_string(w, "cache_bdev_name", vbdev->cache.name);
75707fe6a43SSeth Howell 	spdk_json_write_named_string(w, "core_bdev_name", vbdev->core.name);
75807fe6a43SSeth Howell 	spdk_json_write_object_end(w);
75907fe6a43SSeth Howell 
76007fe6a43SSeth Howell 	spdk_json_write_object_end(w);
76107fe6a43SSeth Howell }
76207fe6a43SSeth Howell 
76307fe6a43SSeth Howell /* Cache vbdev function table
76407fe6a43SSeth Howell  * Used by bdev layer */
76507fe6a43SSeth Howell static struct spdk_bdev_fn_table cache_dev_fn_table = {
76607fe6a43SSeth Howell 	.destruct = vbdev_ocf_destruct,
76707fe6a43SSeth Howell 	.io_type_supported = vbdev_ocf_io_type_supported,
76807fe6a43SSeth Howell 	.submit_request	= vbdev_ocf_submit_request,
76907fe6a43SSeth Howell 	.get_io_channel	= vbdev_ocf_get_io_channel,
77007fe6a43SSeth Howell 	.write_config_json = vbdev_ocf_write_json_config,
77107fe6a43SSeth Howell 	.dump_info_json = vbdev_ocf_dump_info_json,
77207fe6a43SSeth Howell };
77307fe6a43SSeth Howell 
77407fe6a43SSeth Howell /* Poller function for the OCF queue
77507fe6a43SSeth Howell  * We execute OCF requests here synchronously */
77607fe6a43SSeth Howell static int
77707fe6a43SSeth Howell queue_poll(void *opaque)
77807fe6a43SSeth Howell {
779af039a7aSyidong0635 	struct vbdev_ocf_qctx *qctx = opaque;
78007fe6a43SSeth Howell 	uint32_t iono = ocf_queue_pending_io(qctx->queue);
78107fe6a43SSeth Howell 	int i, max = spdk_min(32, iono);
78207fe6a43SSeth Howell 
78307fe6a43SSeth Howell 	for (i = 0; i < max; i++) {
78407fe6a43SSeth Howell 		ocf_queue_run_single(qctx->queue);
78507fe6a43SSeth Howell 	}
78607fe6a43SSeth Howell 
78707fe6a43SSeth Howell 	if (iono > 0) {
788eb05cbd6SMaciej Szwed 		return SPDK_POLLER_BUSY;
78907fe6a43SSeth Howell 	} else {
790eb05cbd6SMaciej Szwed 		return SPDK_POLLER_IDLE;
79107fe6a43SSeth Howell 	}
79207fe6a43SSeth Howell }
79307fe6a43SSeth Howell 
79407fe6a43SSeth Howell /* Called during ocf_submit_io, ocf_purge*
79507fe6a43SSeth Howell  * and any other requests that need to submit io */
79607fe6a43SSeth Howell static void
79707fe6a43SSeth Howell vbdev_ocf_ctx_queue_kick(ocf_queue_t q)
79807fe6a43SSeth Howell {
79907fe6a43SSeth Howell }
80007fe6a43SSeth Howell 
80107fe6a43SSeth Howell /* OCF queue deinitialization
80207fe6a43SSeth Howell  * Called at ocf_cache_stop */
80307fe6a43SSeth Howell static void
80407fe6a43SSeth Howell vbdev_ocf_ctx_queue_stop(ocf_queue_t q)
80507fe6a43SSeth Howell {
806af039a7aSyidong0635 	struct vbdev_ocf_qctx *qctx = ocf_queue_get_priv(q);
80707fe6a43SSeth Howell 
80807fe6a43SSeth Howell 	if (qctx) {
80907fe6a43SSeth Howell 		spdk_put_io_channel(qctx->cache_ch);
81007fe6a43SSeth Howell 		spdk_put_io_channel(qctx->core_ch);
81107fe6a43SSeth Howell 		spdk_poller_unregister(&qctx->poller);
8125817a1cfSMarcin Dziegielewski 		if (qctx->allocated) {
8135817a1cfSMarcin Dziegielewski 			free(qctx);
8145817a1cfSMarcin Dziegielewski 		}
81507fe6a43SSeth Howell 	}
81607fe6a43SSeth Howell }
81707fe6a43SSeth Howell 
81807fe6a43SSeth Howell /* Queue ops is an interface for running queue thread
81907fe6a43SSeth Howell  * stop() operation in called just before queue gets destroyed */
82007fe6a43SSeth Howell const struct ocf_queue_ops queue_ops = {
82107fe6a43SSeth Howell 	.kick_sync = vbdev_ocf_ctx_queue_kick,
82207fe6a43SSeth Howell 	.kick = vbdev_ocf_ctx_queue_kick,
82307fe6a43SSeth Howell 	.stop = vbdev_ocf_ctx_queue_stop,
82407fe6a43SSeth Howell };
82507fe6a43SSeth Howell 
82607fe6a43SSeth Howell /* Called on cache vbdev creation at every thread
82707fe6a43SSeth Howell  * We allocate OCF queues here and SPDK poller for it */
82807fe6a43SSeth Howell static int
82907fe6a43SSeth Howell io_device_create_cb(void *io_device, void *ctx_buf)
83007fe6a43SSeth Howell {
83107fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = io_device;
832af039a7aSyidong0635 	struct vbdev_ocf_qctx *qctx = ctx_buf;
83307fe6a43SSeth Howell 	int rc;
83407fe6a43SSeth Howell 
83507fe6a43SSeth Howell 	rc = vbdev_ocf_queue_create(vbdev->ocf_cache, &qctx->queue, &queue_ops);
83607fe6a43SSeth Howell 	if (rc) {
83707fe6a43SSeth Howell 		return rc;
83807fe6a43SSeth Howell 	}
83907fe6a43SSeth Howell 
84007fe6a43SSeth Howell 	ocf_queue_set_priv(qctx->queue, qctx);
84107fe6a43SSeth Howell 
84207fe6a43SSeth Howell 	qctx->vbdev      = vbdev;
84307fe6a43SSeth Howell 	qctx->cache_ch   = spdk_bdev_get_io_channel(vbdev->cache.desc);
84407fe6a43SSeth Howell 	qctx->core_ch    = spdk_bdev_get_io_channel(vbdev->core.desc);
845ab0bc5c2SShuhei Matsumoto 	qctx->poller     = SPDK_POLLER_REGISTER(queue_poll, qctx, 0);
84607fe6a43SSeth Howell 
84707fe6a43SSeth Howell 	return rc;
84807fe6a43SSeth Howell }
84907fe6a43SSeth Howell 
85007fe6a43SSeth Howell /* Called per thread
85107fe6a43SSeth Howell  * Put OCF queue and relaunch poller with new context to finish pending requests */
85207fe6a43SSeth Howell static void
85307fe6a43SSeth Howell io_device_destroy_cb(void *io_device, void *ctx_buf)
85407fe6a43SSeth Howell {
85507fe6a43SSeth Howell 	/* Making a copy of context to use it after io channel will be destroyed */
856af039a7aSyidong0635 	struct vbdev_ocf_qctx *copy = malloc(sizeof(*copy));
857af039a7aSyidong0635 	struct vbdev_ocf_qctx *qctx = ctx_buf;
85807fe6a43SSeth Howell 
85907fe6a43SSeth Howell 	if (copy) {
86007fe6a43SSeth Howell 		ocf_queue_set_priv(qctx->queue, copy);
86107fe6a43SSeth Howell 		memcpy(copy, qctx, sizeof(*copy));
86207fe6a43SSeth Howell 		spdk_poller_unregister(&qctx->poller);
863ab0bc5c2SShuhei Matsumoto 		copy->poller = SPDK_POLLER_REGISTER(queue_poll, copy, 0);
8645817a1cfSMarcin Dziegielewski 		copy->allocated = true;
86507fe6a43SSeth Howell 	} else {
86607fe6a43SSeth Howell 		SPDK_ERRLOG("Unable to stop OCF queue properly: %s\n",
86707fe6a43SSeth Howell 			    spdk_strerror(ENOMEM));
86807fe6a43SSeth Howell 	}
86907fe6a43SSeth Howell 
87007fe6a43SSeth Howell 	vbdev_ocf_queue_put(qctx->queue);
87107fe6a43SSeth Howell }
87207fe6a43SSeth Howell 
87307fe6a43SSeth Howell /* OCF management queue deinitialization */
87407fe6a43SSeth Howell static void
87507fe6a43SSeth Howell vbdev_ocf_ctx_mngt_queue_stop(ocf_queue_t q)
87607fe6a43SSeth Howell {
87707fe6a43SSeth Howell 	struct spdk_poller *poller = ocf_queue_get_priv(q);
87807fe6a43SSeth Howell 
87907fe6a43SSeth Howell 	if (poller) {
88007fe6a43SSeth Howell 		spdk_poller_unregister(&poller);
88107fe6a43SSeth Howell 	}
88207fe6a43SSeth Howell }
88307fe6a43SSeth Howell 
88407fe6a43SSeth Howell static int
88507fe6a43SSeth Howell mngt_queue_poll(void *opaque)
88607fe6a43SSeth Howell {
88707fe6a43SSeth Howell 	ocf_queue_t q = opaque;
88807fe6a43SSeth Howell 	uint32_t iono = ocf_queue_pending_io(q);
88907fe6a43SSeth Howell 	int i, max = spdk_min(32, iono);
89007fe6a43SSeth Howell 
89107fe6a43SSeth Howell 	for (i = 0; i < max; i++) {
89207fe6a43SSeth Howell 		ocf_queue_run_single(q);
89307fe6a43SSeth Howell 	}
89407fe6a43SSeth Howell 
89507fe6a43SSeth Howell 	if (iono > 0) {
896eb05cbd6SMaciej Szwed 		return SPDK_POLLER_BUSY;
89707fe6a43SSeth Howell 	} else {
898eb05cbd6SMaciej Szwed 		return SPDK_POLLER_IDLE;
89907fe6a43SSeth Howell 	}
90007fe6a43SSeth Howell }
90107fe6a43SSeth Howell 
90207fe6a43SSeth Howell static void
90307fe6a43SSeth Howell vbdev_ocf_ctx_mngt_queue_kick(ocf_queue_t q)
90407fe6a43SSeth Howell {
90507fe6a43SSeth Howell }
90607fe6a43SSeth Howell 
90707fe6a43SSeth Howell /* Queue ops is an interface for running queue thread
90807fe6a43SSeth Howell  * stop() operation in called just before queue gets destroyed */
90907fe6a43SSeth Howell const struct ocf_queue_ops mngt_queue_ops = {
91007fe6a43SSeth Howell 	.kick_sync = NULL,
91107fe6a43SSeth Howell 	.kick = vbdev_ocf_ctx_mngt_queue_kick,
91207fe6a43SSeth Howell 	.stop = vbdev_ocf_ctx_mngt_queue_stop,
91307fe6a43SSeth Howell };
91407fe6a43SSeth Howell 
91559a29646SMarcin Dziegielewski static void
916cb3e674cSyidong0635 vbdev_ocf_mngt_exit(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn *rollback_path, int rc)
917cb3e674cSyidong0635 {
9180881b192Syidong0635 	vbdev->state.starting = false;
919cb3e674cSyidong0635 	vbdev_ocf_mngt_stop(vbdev, rollback_path, rc);
920cb3e674cSyidong0635 }
921cb3e674cSyidong0635 
92207fe6a43SSeth Howell /* Create exported spdk object */
92307fe6a43SSeth Howell static void
92407fe6a43SSeth Howell finish_register(struct vbdev_ocf *vbdev)
92507fe6a43SSeth Howell {
926504cac51SKrzysztof Karas 	struct spdk_uuid ns_uuid;
92707fe6a43SSeth Howell 	int result;
92807fe6a43SSeth Howell 
92907fe6a43SSeth Howell 	/* Copy properties of the base bdev */
93007fe6a43SSeth Howell 	vbdev->exp_bdev.blocklen = vbdev->core.bdev->blocklen;
93107fe6a43SSeth Howell 	vbdev->exp_bdev.write_cache = vbdev->core.bdev->write_cache;
93207fe6a43SSeth Howell 	vbdev->exp_bdev.required_alignment = vbdev->core.bdev->required_alignment;
93307fe6a43SSeth Howell 
93407fe6a43SSeth Howell 	vbdev->exp_bdev.name = vbdev->name;
93507fe6a43SSeth Howell 	vbdev->exp_bdev.product_name = "SPDK OCF";
93607fe6a43SSeth Howell 
93707fe6a43SSeth Howell 	vbdev->exp_bdev.blockcnt = vbdev->core.bdev->blockcnt;
93807fe6a43SSeth Howell 	vbdev->exp_bdev.ctxt = vbdev;
93907fe6a43SSeth Howell 	vbdev->exp_bdev.fn_table = &cache_dev_fn_table;
94007fe6a43SSeth Howell 	vbdev->exp_bdev.module = &ocf_if;
94107fe6a43SSeth Howell 
942504cac51SKrzysztof Karas 	/* Generate UUID based on namespace UUID + base bdev UUID. */
943504cac51SKrzysztof Karas 	spdk_uuid_parse(&ns_uuid, BDEV_OCF_NAMESPACE_UUID);
944504cac51SKrzysztof Karas 	result = spdk_uuid_generate_sha1(&vbdev->exp_bdev.uuid, &ns_uuid,
945504cac51SKrzysztof Karas 					 (const char *)&vbdev->core.bdev->uuid, sizeof(struct spdk_uuid));
946504cac51SKrzysztof Karas 	if (result) {
947504cac51SKrzysztof Karas 		SPDK_ERRLOG("Unable to generate new UUID for ocf bdev\n");
948504cac51SKrzysztof Karas 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, result);
949504cac51SKrzysztof Karas 		return;
950504cac51SKrzysztof Karas 	}
951504cac51SKrzysztof Karas 
95207fe6a43SSeth Howell 	/* Finally register vbdev in SPDK */
95307fe6a43SSeth Howell 	spdk_io_device_register(vbdev, io_device_create_cb, io_device_destroy_cb,
954af039a7aSyidong0635 				sizeof(struct vbdev_ocf_qctx), vbdev->name);
95507fe6a43SSeth Howell 	result = spdk_bdev_register(&vbdev->exp_bdev);
95607fe6a43SSeth Howell 	if (result) {
95759a29646SMarcin Dziegielewski 		SPDK_ERRLOG("Could not register exposed bdev %s\n",
95859a29646SMarcin Dziegielewski 			    vbdev->name);
959cb3e674cSyidong0635 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, result);
96059a29646SMarcin Dziegielewski 		return;
96107fe6a43SSeth Howell 	} else {
96207fe6a43SSeth Howell 		vbdev->state.started = true;
96307fe6a43SSeth Howell 	}
96407fe6a43SSeth Howell 
96507fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, result);
96607fe6a43SSeth Howell }
96707fe6a43SSeth Howell 
96807fe6a43SSeth Howell static void
96907fe6a43SSeth Howell add_core_cmpl(ocf_cache_t cache, ocf_core_t core, void *priv, int error)
97007fe6a43SSeth Howell {
97107fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = priv;
97207fe6a43SSeth Howell 
97307fe6a43SSeth Howell 	ocf_mngt_cache_unlock(cache);
97407fe6a43SSeth Howell 
97507fe6a43SSeth Howell 	if (error) {
97659a29646SMarcin Dziegielewski 		SPDK_ERRLOG("Error %d, failed to add core device to cache instance %s,"
97759a29646SMarcin Dziegielewski 			    "starting rollback\n", error, vbdev->name);
978cb3e674cSyidong0635 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, error);
97959a29646SMarcin Dziegielewski 		return;
98007fe6a43SSeth Howell 	} else {
98107fe6a43SSeth Howell 		vbdev->ocf_core = core;
98207fe6a43SSeth Howell 	}
98307fe6a43SSeth Howell 
98407fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, error);
98507fe6a43SSeth Howell }
98607fe6a43SSeth Howell 
98707fe6a43SSeth Howell /* Try to lock cache, then add core */
98807fe6a43SSeth Howell static void
989c74b4b32SMarcin Dziegielewski add_core_cache_lock_cmpl(ocf_cache_t cache, void *priv, int error)
99007fe6a43SSeth Howell {
991c74b4b32SMarcin Dziegielewski 	struct vbdev_ocf *vbdev = (struct vbdev_ocf *)priv;
99207fe6a43SSeth Howell 
993c74b4b32SMarcin Dziegielewski 	if (error) {
994c74b4b32SMarcin Dziegielewski 		SPDK_ERRLOG("Error %d, can not lock cache instance %s,"
995c74b4b32SMarcin Dziegielewski 			    "starting rollback\n", error, vbdev->name);
996cb3e674cSyidong0635 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, error);
997c74b4b32SMarcin Dziegielewski 	}
99807fe6a43SSeth Howell 	ocf_mngt_cache_add_core(vbdev->ocf_cache, &vbdev->cfg.core, add_core_cmpl, vbdev);
99907fe6a43SSeth Howell }
100007fe6a43SSeth Howell 
100107fe6a43SSeth Howell /* Add core for existing OCF cache instance */
100207fe6a43SSeth Howell static void
100307fe6a43SSeth Howell add_core(struct vbdev_ocf *vbdev)
100407fe6a43SSeth Howell {
1005c74b4b32SMarcin Dziegielewski 	ocf_mngt_cache_lock(vbdev->ocf_cache, add_core_cache_lock_cmpl, vbdev);
100607fe6a43SSeth Howell }
100707fe6a43SSeth Howell 
100807fe6a43SSeth Howell static void
100907fe6a43SSeth Howell start_cache_cmpl(ocf_cache_t cache, void *priv, int error)
101007fe6a43SSeth Howell {
101107fe6a43SSeth Howell 	struct vbdev_ocf *vbdev = priv;
1012*3511bd09SRafal Stefanowski 	uint64_t volume_size;
101380b80d24SRafal Stefanowski 	uint64_t mem_needed;
101407fe6a43SSeth Howell 
101507fe6a43SSeth Howell 	ocf_mngt_cache_unlock(cache);
101607fe6a43SSeth Howell 
101759a29646SMarcin Dziegielewski 	if (error) {
101859a29646SMarcin Dziegielewski 		SPDK_ERRLOG("Error %d during start cache %s, starting rollback\n",
101959a29646SMarcin Dziegielewski 			    error, vbdev->name);
102080b80d24SRafal Stefanowski 
102180b80d24SRafal Stefanowski 		if (error == -OCF_ERR_NO_MEM) {
1022*3511bd09SRafal Stefanowski 			volume_size = vbdev->cache.bdev->blockcnt * vbdev->cache.bdev->blocklen;
1023*3511bd09SRafal Stefanowski 			mem_needed = ocf_mngt_get_ram_needed(cache, volume_size);
102480b80d24SRafal Stefanowski 
102580b80d24SRafal Stefanowski 			SPDK_NOTICELOG("Try to increase hugepage memory size or cache line size. "
102680b80d24SRafal Stefanowski 				       "For your configuration:\nDevice size: %"PRIu64" bytes\n"
102780b80d24SRafal Stefanowski 				       "Cache line size: %"PRIu64" bytes\nFree memory needed to start "
1028*3511bd09SRafal Stefanowski 				       "cache: %"PRIu64" bytes\n",
1029*3511bd09SRafal Stefanowski 				       volume_size, vbdev->cfg.cache.cache_line_size, mem_needed);
103080b80d24SRafal Stefanowski 		}
103180b80d24SRafal Stefanowski 
1032cb3e674cSyidong0635 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, error);
103359a29646SMarcin Dziegielewski 		return;
103459a29646SMarcin Dziegielewski 	}
103559a29646SMarcin Dziegielewski 
103607fe6a43SSeth Howell 	vbdev_ocf_mngt_continue(vbdev, error);
103707fe6a43SSeth Howell }
103807fe6a43SSeth Howell 
103907fe6a43SSeth Howell static int
104007fe6a43SSeth Howell create_management_queue(struct vbdev_ocf *vbdev)
104107fe6a43SSeth Howell {
104207fe6a43SSeth Howell 	struct spdk_poller *mngt_poller;
104307fe6a43SSeth Howell 	int rc;
104407fe6a43SSeth Howell 
1045*3511bd09SRafal Stefanowski 	rc = vbdev_ocf_queue_create_mngt(vbdev->ocf_cache,
1046*3511bd09SRafal Stefanowski 					 &vbdev->cache_ctx->mngt_queue, &mngt_queue_ops);
104707fe6a43SSeth Howell 	if (rc) {
104807fe6a43SSeth Howell 		SPDK_ERRLOG("Unable to create mngt_queue: %d\n", rc);
104907fe6a43SSeth Howell 		return rc;
105007fe6a43SSeth Howell 	}
105107fe6a43SSeth Howell 
1052ab0bc5c2SShuhei Matsumoto 	mngt_poller = SPDK_POLLER_REGISTER(mngt_queue_poll, vbdev->cache_ctx->mngt_queue, 100);
105307fe6a43SSeth Howell 	if (mngt_poller == NULL) {
105407fe6a43SSeth Howell 		SPDK_ERRLOG("Unable to initiate mngt request: %s", spdk_strerror(ENOMEM));
105507fe6a43SSeth Howell 		return -ENOMEM;
105607fe6a43SSeth Howell 	}
105707fe6a43SSeth Howell 
105807fe6a43SSeth Howell 	ocf_queue_set_priv(vbdev->cache_ctx->mngt_queue, mngt_poller);
105907fe6a43SSeth Howell 
106007fe6a43SSeth Howell 	return 0;
106107fe6a43SSeth Howell }
106207fe6a43SSeth Howell 
106307fe6a43SSeth Howell /* Start OCF cache, attach caching device */
106407fe6a43SSeth Howell static void
106507fe6a43SSeth Howell start_cache(struct vbdev_ocf *vbdev)
106607fe6a43SSeth Howell {
106707fe6a43SSeth Howell 	ocf_cache_t existing;
1068074a63d5SRafal Stefanowski 	uint32_t cache_block_size = vbdev->cache.bdev->blocklen;
1069074a63d5SRafal Stefanowski 	uint32_t core_block_size = vbdev->core.bdev->blocklen;
107007fe6a43SSeth Howell 	int rc;
107107fe6a43SSeth Howell 
1072868ba177STomasz Zawadzki 	if (is_ocf_cache_running(vbdev)) {
1073790669ccSMarcin Dziegielewski 		vbdev_ocf_mngt_stop(vbdev, NULL, -EALREADY);
107407fe6a43SSeth Howell 		return;
107507fe6a43SSeth Howell 	}
107607fe6a43SSeth Howell 
1077074a63d5SRafal Stefanowski 	if (cache_block_size > core_block_size) {
1078074a63d5SRafal Stefanowski 		SPDK_ERRLOG("Cache bdev block size (%d) is bigger then core bdev block size (%d)\n",
1079074a63d5SRafal Stefanowski 			    cache_block_size, core_block_size);
1080074a63d5SRafal Stefanowski 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, -EINVAL);
1081074a63d5SRafal Stefanowski 		return;
1082074a63d5SRafal Stefanowski 	}
1083074a63d5SRafal Stefanowski 
108407fe6a43SSeth Howell 	existing = get_other_cache_instance(vbdev);
108507fe6a43SSeth Howell 	if (existing) {
108607fe6a43SSeth Howell 		SPDK_NOTICELOG("OCF bdev %s connects to existing cache device %s\n",
108707fe6a43SSeth Howell 			       vbdev->name, vbdev->cache.name);
108807fe6a43SSeth Howell 		vbdev->ocf_cache = existing;
10891350922dSTomasz Zawadzki 		ocf_mngt_cache_get(vbdev->ocf_cache);
109007fe6a43SSeth Howell 		vbdev->cache_ctx = ocf_cache_get_priv(existing);
109107fe6a43SSeth Howell 		vbdev_ocf_cache_ctx_get(vbdev->cache_ctx);
109207fe6a43SSeth Howell 		vbdev_ocf_mngt_continue(vbdev, 0);
109307fe6a43SSeth Howell 		return;
109407fe6a43SSeth Howell 	}
109507fe6a43SSeth Howell 
109607fe6a43SSeth Howell 	vbdev->cache_ctx = calloc(1, sizeof(struct vbdev_ocf_cache_ctx));
109707fe6a43SSeth Howell 	if (vbdev->cache_ctx == NULL) {
1098cb3e674cSyidong0635 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, -ENOMEM);
109907fe6a43SSeth Howell 		return;
110007fe6a43SSeth Howell 	}
110107fe6a43SSeth Howell 
110207fe6a43SSeth Howell 	vbdev_ocf_cache_ctx_get(vbdev->cache_ctx);
110307fe6a43SSeth Howell 
11043f4474d5SMichal Mielewczyk 	rc = ocf_mngt_cache_start(vbdev_ocf_ctx, &vbdev->ocf_cache, &vbdev->cfg.cache, NULL);
110507fe6a43SSeth Howell 	if (rc) {
11068fcb8b96SRafal Stefanowski 		SPDK_ERRLOG("Could not start cache %s: %d\n", vbdev->name, rc);
1107cb3e674cSyidong0635 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, rc);
110807fe6a43SSeth Howell 		return;
110907fe6a43SSeth Howell 	}
11101350922dSTomasz Zawadzki 	ocf_mngt_cache_get(vbdev->ocf_cache);
111107fe6a43SSeth Howell 
111207fe6a43SSeth Howell 	ocf_cache_set_priv(vbdev->ocf_cache, vbdev->cache_ctx);
111307fe6a43SSeth Howell 
111407fe6a43SSeth Howell 	rc = create_management_queue(vbdev);
111507fe6a43SSeth Howell 	if (rc) {
111607fe6a43SSeth Howell 		SPDK_ERRLOG("Unable to create mngt_queue: %d\n", rc);
1117cb3e674cSyidong0635 		vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, rc);
111807fe6a43SSeth Howell 		return;
111907fe6a43SSeth Howell 	}
112007fe6a43SSeth Howell 
112107fe6a43SSeth Howell 	if (vbdev->cfg.loadq) {
112237975647SAmir Haroush 		ocf_mngt_cache_load(vbdev->ocf_cache, &vbdev->cfg.attach, start_cache_cmpl, vbdev);
112307fe6a43SSeth Howell 	} else {
112437975647SAmir Haroush 		ocf_mngt_cache_attach(vbdev->ocf_cache, &vbdev->cfg.attach, start_cache_cmpl, vbdev);
112507fe6a43SSeth Howell 	}
112607fe6a43SSeth Howell }
112707fe6a43SSeth Howell 
112807fe6a43SSeth Howell /* Procedures called during register operation */
112907fe6a43SSeth Howell vbdev_ocf_mngt_fn register_path[] = {
113007fe6a43SSeth Howell 	start_cache,
113107fe6a43SSeth Howell 	add_core,
113207fe6a43SSeth Howell 	finish_register,
113307fe6a43SSeth Howell 	NULL
113407fe6a43SSeth Howell };
113507fe6a43SSeth Howell 
113607fe6a43SSeth Howell /* Start cache instance and register OCF bdev */
113707fe6a43SSeth Howell static void
113807fe6a43SSeth Howell register_vbdev(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_callback cb, void *cb_arg)
113907fe6a43SSeth Howell {
114007fe6a43SSeth Howell 	int rc;
114107fe6a43SSeth Howell 
114207fe6a43SSeth Howell 	if (!(vbdev->core.attached && vbdev->cache.attached) || vbdev->state.started) {
114307fe6a43SSeth Howell 		cb(-EPERM, vbdev, cb_arg);
114407fe6a43SSeth Howell 		return;
114507fe6a43SSeth Howell 	}
114607fe6a43SSeth Howell 
1147d1c9e2f7SMarcin Dziegielewski 	vbdev->state.starting = true;
114807fe6a43SSeth Howell 	rc = vbdev_ocf_mngt_start(vbdev, register_path, cb, cb_arg);
114907fe6a43SSeth Howell 	if (rc) {
115007fe6a43SSeth Howell 		cb(rc, vbdev, cb_arg);
115107fe6a43SSeth Howell 	}
115207fe6a43SSeth Howell }
115307fe6a43SSeth Howell 
115407fe6a43SSeth Howell /* Init OCF configuration options
115507fe6a43SSeth Howell  * for core and cache devices */
115637975647SAmir Haroush static int
115707fe6a43SSeth Howell init_vbdev_config(struct vbdev_ocf *vbdev)
115807fe6a43SSeth Howell {
115907fe6a43SSeth Howell 	struct vbdev_ocf_config *cfg = &vbdev->cfg;
116037975647SAmir Haroush 	struct ocf_volume_uuid uuid;
116137975647SAmir Haroush 	ocf_volume_type_t type;
116237975647SAmir Haroush 	int ret;
116337975647SAmir Haroush 
116407fe6a43SSeth Howell 
1165502a2d75SRafal Stefanowski 	/* Initialize OCF defaults first */
116637975647SAmir Haroush 	ocf_mngt_cache_attach_config_set_default(&cfg->attach);
1167502a2d75SRafal Stefanowski 	ocf_mngt_cache_config_set_default(&cfg->cache);
1168502a2d75SRafal Stefanowski 	ocf_mngt_core_config_set_default(&cfg->core);
1169502a2d75SRafal Stefanowski 
11700fb65adcSEugene Kobyak 	ret = snprintf(cfg->cache.name, sizeof(cfg->cache.name), "%s", vbdev->name);
11710fb65adcSEugene Kobyak 	if (ret < 0 || (size_t) ret >= sizeof(cfg->cache.name)) {
11720fb65adcSEugene Kobyak 		return -EINVAL;
11730fb65adcSEugene Kobyak 	}
11740fb65adcSEugene Kobyak 	ret = snprintf(cfg->core.name, sizeof(cfg->core.name), "%s", vbdev->core.name);
11750fb65adcSEugene Kobyak 	if (ret < 0 || (size_t) ret >= sizeof(cfg->core.name)) {
11760fb65adcSEugene Kobyak 		return -EINVAL;
11770fb65adcSEugene Kobyak 	}
117807fe6a43SSeth Howell 
117937975647SAmir Haroush 	cfg->attach.open_cores = false;
118037975647SAmir Haroush 	cfg->attach.device.perform_test = false;
118137975647SAmir Haroush 	cfg->attach.discard_on_start = false;
118207fe6a43SSeth Howell 
118307fe6a43SSeth Howell 	vbdev->cfg.cache.locked = true;
118407fe6a43SSeth Howell 
118507fe6a43SSeth Howell 	cfg->core.volume_type = SPDK_OBJECT;
118607fe6a43SSeth Howell 
118707fe6a43SSeth Howell 	if (vbdev->cfg.loadq) {
118807fe6a43SSeth Howell 		/* When doing cache_load(), we need to set try_add to true,
118907fe6a43SSeth Howell 		 * otherwise OCF will interpret this core as new
119007fe6a43SSeth Howell 		 * instead of the inactive one */
119107fe6a43SSeth Howell 		vbdev->cfg.core.try_add = true;
11923048a49cSRafal Stefanowski 	} else {
11933048a49cSRafal Stefanowski 		/* When cache is initialized as new, set force flag to true,
11943048a49cSRafal Stefanowski 		 * to ignore warnings about existing metadata */
119537975647SAmir Haroush 		cfg->attach.force = true;
119607fe6a43SSeth Howell 	}
119707fe6a43SSeth Howell 
119807fe6a43SSeth Howell 	/* Serialize bdev names in OCF UUID to interpret on future loads
11999f133b1bSVitaliy Mysak 	 * Core UUID is a triple of (core name, vbdev name, cache name)
120007fe6a43SSeth Howell 	 * Cache UUID is cache bdev name */
120137975647SAmir Haroush 	type = ocf_ctx_get_volume_type(vbdev_ocf_ctx, SPDK_OBJECT);
120237975647SAmir Haroush 	if (!type) {
120337975647SAmir Haroush 		SPDK_ERRLOG("Fail to get volume type\n");
120437975647SAmir Haroush 		return -EINVAL;
120537975647SAmir Haroush 	}
120637975647SAmir Haroush 	uuid.size = strlen(vbdev->cache.name) + 1;
120737975647SAmir Haroush 	uuid.data = vbdev->cache.name;
120837975647SAmir Haroush 	ret = ocf_volume_create(&cfg->attach.device.volume, type, &uuid);
120937975647SAmir Haroush 	if (ret) {
121037975647SAmir Haroush 		SPDK_ERRLOG("Fail to create volume\n");
121137975647SAmir Haroush 		return -EINVAL;
121237975647SAmir Haroush 	}
121307fe6a43SSeth Howell 
12149f133b1bSVitaliy Mysak 	snprintf(vbdev->uuid, VBDEV_OCF_MD_MAX_LEN, "%s %s %s",
12159f133b1bSVitaliy Mysak 		 vbdev->core.name, vbdev->name, vbdev->cache.name);
121607fe6a43SSeth Howell 	cfg->core.uuid.size = strlen(vbdev->uuid) + 1;
121707fe6a43SSeth Howell 	cfg->core.uuid.data = vbdev->uuid;
121807fe6a43SSeth Howell 	vbdev->uuid[strlen(vbdev->core.name)] = 0;
12199f133b1bSVitaliy Mysak 	vbdev->uuid[strlen(vbdev->core.name) + 1 + strlen(vbdev->name)] = 0;
122037975647SAmir Haroush 
122137975647SAmir Haroush 	return 0;
122207fe6a43SSeth Howell }
122307fe6a43SSeth Howell 
122407fe6a43SSeth Howell /* Allocate vbdev structure object and add it to the global list */
122507fe6a43SSeth Howell static int
122607fe6a43SSeth Howell init_vbdev(const char *vbdev_name,
122707fe6a43SSeth Howell 	   const char *cache_mode_name,
12284d91b4efSrafalste 	   const uint64_t cache_line_size,
122907fe6a43SSeth Howell 	   const char *cache_name,
123007fe6a43SSeth Howell 	   const char *core_name,
123107fe6a43SSeth Howell 	   bool loadq)
123207fe6a43SSeth Howell {
123307fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
123407fe6a43SSeth Howell 	int rc = 0;
123507fe6a43SSeth Howell 
123607fe6a43SSeth Howell 	if (spdk_bdev_get_by_name(vbdev_name) || vbdev_ocf_get_by_name(vbdev_name)) {
123707fe6a43SSeth Howell 		SPDK_ERRLOG("Device with name '%s' already exists\n", vbdev_name);
123807fe6a43SSeth Howell 		return -EPERM;
123907fe6a43SSeth Howell 	}
124007fe6a43SSeth Howell 
124107fe6a43SSeth Howell 	vbdev = calloc(1, sizeof(*vbdev));
124207fe6a43SSeth Howell 	if (!vbdev) {
124307fe6a43SSeth Howell 		goto error_mem;
124407fe6a43SSeth Howell 	}
124507fe6a43SSeth Howell 
1246502a2d75SRafal Stefanowski 	vbdev->name = strdup(vbdev_name);
1247502a2d75SRafal Stefanowski 	if (!vbdev->name) {
1248502a2d75SRafal Stefanowski 		goto error_mem;
1249502a2d75SRafal Stefanowski 	}
1250502a2d75SRafal Stefanowski 
1251502a2d75SRafal Stefanowski 	vbdev->cache.name = strdup(cache_name);
1252502a2d75SRafal Stefanowski 	if (!vbdev->cache.name) {
1253502a2d75SRafal Stefanowski 		goto error_mem;
1254502a2d75SRafal Stefanowski 	}
1255502a2d75SRafal Stefanowski 
1256502a2d75SRafal Stefanowski 	vbdev->core.name = strdup(core_name);
1257502a2d75SRafal Stefanowski 	if (!vbdev->core.name) {
1258502a2d75SRafal Stefanowski 		goto error_mem;
1259502a2d75SRafal Stefanowski 	}
1260502a2d75SRafal Stefanowski 
126107fe6a43SSeth Howell 	vbdev->cache.parent = vbdev;
126207fe6a43SSeth Howell 	vbdev->core.parent = vbdev;
126307fe6a43SSeth Howell 	vbdev->cache.is_cache = true;
126407fe6a43SSeth Howell 	vbdev->core.is_cache = false;
1265502a2d75SRafal Stefanowski 	vbdev->cfg.loadq = loadq;
1266502a2d75SRafal Stefanowski 
126737975647SAmir Haroush 	rc = init_vbdev_config(vbdev);
126837975647SAmir Haroush 	if (rc) {
126937975647SAmir Haroush 		SPDK_ERRLOG("Fail to init vbdev config\n");
127037975647SAmir Haroush 		goto error_free;
127137975647SAmir Haroush 	}
127237975647SAmir Haroush 
127307fe6a43SSeth Howell 
127407fe6a43SSeth Howell 	if (cache_mode_name) {
127507fe6a43SSeth Howell 		vbdev->cfg.cache.cache_mode
127607fe6a43SSeth Howell 			= ocf_get_cache_mode(cache_mode_name);
127707fe6a43SSeth Howell 	} else if (!loadq) { /* In load path it is OK to pass NULL as cache mode */
127807fe6a43SSeth Howell 		SPDK_ERRLOG("No cache mode specified\n");
127907fe6a43SSeth Howell 		rc = -EINVAL;
128007fe6a43SSeth Howell 		goto error_free;
128107fe6a43SSeth Howell 	}
128207fe6a43SSeth Howell 	if (vbdev->cfg.cache.cache_mode < 0) {
128307fe6a43SSeth Howell 		SPDK_ERRLOG("Incorrect cache mode '%s'\n", cache_mode_name);
128407fe6a43SSeth Howell 		rc = -EINVAL;
128507fe6a43SSeth Howell 		goto error_free;
128607fe6a43SSeth Howell 	}
128707fe6a43SSeth Howell 
12884d91b4efSrafalste 	ocf_cache_line_size_t set_cache_line_size = cache_line_size ?
12894d91b4efSrafalste 			(ocf_cache_line_size_t)cache_line_size * KiB :
12904d91b4efSrafalste 			ocf_cache_line_size_default;
12914d91b4efSrafalste 	if (set_cache_line_size == 0) {
12924d91b4efSrafalste 		SPDK_ERRLOG("Cache line size should be non-zero.\n");
12934d91b4efSrafalste 		rc = -EINVAL;
12944d91b4efSrafalste 		goto error_free;
12954d91b4efSrafalste 	}
129637975647SAmir Haroush 	vbdev->cfg.attach.cache_line_size = set_cache_line_size;
12974d91b4efSrafalste 	vbdev->cfg.cache.cache_line_size = set_cache_line_size;
12984d91b4efSrafalste 
129907fe6a43SSeth Howell 	TAILQ_INSERT_TAIL(&g_ocf_vbdev_head, vbdev, tailq);
130007fe6a43SSeth Howell 	return rc;
130107fe6a43SSeth Howell 
130207fe6a43SSeth Howell error_mem:
130307fe6a43SSeth Howell 	rc = -ENOMEM;
130407fe6a43SSeth Howell error_free:
130507fe6a43SSeth Howell 	free_vbdev(vbdev);
130607fe6a43SSeth Howell 	return rc;
130707fe6a43SSeth Howell }
130807fe6a43SSeth Howell 
130907fe6a43SSeth Howell /* Read configuration file at the start of SPDK application
131007fe6a43SSeth Howell  * This adds vbdevs to global list if some mentioned in config */
131107fe6a43SSeth Howell static int
131207fe6a43SSeth Howell vbdev_ocf_init(void)
131307fe6a43SSeth Howell {
131407fe6a43SSeth Howell 	int status;
131507fe6a43SSeth Howell 
131607fe6a43SSeth Howell 	status = vbdev_ocf_ctx_init();
131707fe6a43SSeth Howell 	if (status) {
131807fe6a43SSeth Howell 		SPDK_ERRLOG("OCF ctx initialization failed with=%d\n", status);
131907fe6a43SSeth Howell 		return status;
132007fe6a43SSeth Howell 	}
132107fe6a43SSeth Howell 
132207fe6a43SSeth Howell 	status = vbdev_ocf_volume_init();
132307fe6a43SSeth Howell 	if (status) {
132407fe6a43SSeth Howell 		vbdev_ocf_ctx_cleanup();
132507fe6a43SSeth Howell 		SPDK_ERRLOG("OCF volume initialization failed with=%d\n", status);
132607fe6a43SSeth Howell 		return status;
132707fe6a43SSeth Howell 	}
132807fe6a43SSeth Howell 
132907fe6a43SSeth Howell 	return status;
133007fe6a43SSeth Howell }
133107fe6a43SSeth Howell 
133207fe6a43SSeth Howell /* Called after application shutdown started
133307fe6a43SSeth Howell  * Release memory of allocated structures here */
133407fe6a43SSeth Howell static void
133507fe6a43SSeth Howell vbdev_ocf_module_fini(void)
133607fe6a43SSeth Howell {
133707fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
133807fe6a43SSeth Howell 
133907fe6a43SSeth Howell 	while ((vbdev = TAILQ_FIRST(&g_ocf_vbdev_head))) {
134007fe6a43SSeth Howell 		TAILQ_REMOVE(&g_ocf_vbdev_head, vbdev, tailq);
134107fe6a43SSeth Howell 		free_vbdev(vbdev);
134207fe6a43SSeth Howell 	}
134307fe6a43SSeth Howell 
134407fe6a43SSeth Howell 	vbdev_ocf_volume_cleanup();
134507fe6a43SSeth Howell 	vbdev_ocf_ctx_cleanup();
134607fe6a43SSeth Howell }
134707fe6a43SSeth Howell 
13481960ef16SJosh Soref /* When base device gets unplugged this is called
134907fe6a43SSeth Howell  * We will unregister cache vbdev here
135007fe6a43SSeth Howell  * When cache device is removed, we delete every OCF bdev that used it */
135107fe6a43SSeth Howell static void
13523ac1d76aSShuhei Matsumoto hotremove_cb(struct vbdev_ocf_base *base)
135307fe6a43SSeth Howell {
135407fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
135507fe6a43SSeth Howell 
135607fe6a43SSeth Howell 	if (!base->is_cache) {
135707fe6a43SSeth Howell 		if (base->parent->state.doing_finish) {
135807fe6a43SSeth Howell 			return;
135907fe6a43SSeth Howell 		}
136007fe6a43SSeth Howell 
136107fe6a43SSeth Howell 		SPDK_NOTICELOG("Deinitializing '%s' because its core device '%s' was removed\n",
136207fe6a43SSeth Howell 			       base->parent->name, base->name);
136307fe6a43SSeth Howell 		vbdev_ocf_delete(base->parent, NULL, NULL);
136407fe6a43SSeth Howell 		return;
136507fe6a43SSeth Howell 	}
136607fe6a43SSeth Howell 
136707fe6a43SSeth Howell 	TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
136807fe6a43SSeth Howell 		if (vbdev->state.doing_finish) {
136907fe6a43SSeth Howell 			continue;
137007fe6a43SSeth Howell 		}
137107fe6a43SSeth Howell 		if (strcmp(base->name, vbdev->cache.name) == 0) {
137207fe6a43SSeth Howell 			SPDK_NOTICELOG("Deinitializing '%s' because"
137307fe6a43SSeth Howell 				       " its cache device '%s' was removed\n",
137407fe6a43SSeth Howell 				       vbdev->name, base->name);
137507fe6a43SSeth Howell 			vbdev_ocf_delete(vbdev, NULL, NULL);
137607fe6a43SSeth Howell 		}
137707fe6a43SSeth Howell 	}
137807fe6a43SSeth Howell }
137907fe6a43SSeth Howell 
13803ac1d76aSShuhei Matsumoto static void
13813ac1d76aSShuhei Matsumoto base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
13823ac1d76aSShuhei Matsumoto 		   void *event_ctx)
13833ac1d76aSShuhei Matsumoto {
13843ac1d76aSShuhei Matsumoto 	switch (type) {
13853ac1d76aSShuhei Matsumoto 	case SPDK_BDEV_EVENT_REMOVE:
13863ac1d76aSShuhei Matsumoto 		if (event_ctx) {
13873ac1d76aSShuhei Matsumoto 			hotremove_cb(event_ctx);
13883ac1d76aSShuhei Matsumoto 		}
13893ac1d76aSShuhei Matsumoto 		break;
13903ac1d76aSShuhei Matsumoto 	default:
13913ac1d76aSShuhei Matsumoto 		SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
13923ac1d76aSShuhei Matsumoto 		break;
13933ac1d76aSShuhei Matsumoto 	}
13943ac1d76aSShuhei Matsumoto }
13953ac1d76aSShuhei Matsumoto 
139607fe6a43SSeth Howell /* Open base SPDK bdev and claim it */
139707fe6a43SSeth Howell static int
139807fe6a43SSeth Howell attach_base(struct vbdev_ocf_base *base)
139907fe6a43SSeth Howell {
140007fe6a43SSeth Howell 	int status;
140107fe6a43SSeth Howell 
140207fe6a43SSeth Howell 	if (base->attached) {
140307fe6a43SSeth Howell 		return -EALREADY;
140407fe6a43SSeth Howell 	}
140507fe6a43SSeth Howell 
140607fe6a43SSeth Howell 	/* If base cache bdev was already opened by other vbdev,
140707fe6a43SSeth Howell 	 * we just copy its descriptor here */
140807fe6a43SSeth Howell 	if (base->is_cache) {
140907fe6a43SSeth Howell 		struct vbdev_ocf_base *existing = get_other_cache_base(base);
141007fe6a43SSeth Howell 		if (existing) {
141107fe6a43SSeth Howell 			base->desc = existing->desc;
14121b6d1c80SMarcin Dziegielewski 			base->management_channel = existing->management_channel;
141307fe6a43SSeth Howell 			base->attached = true;
141407fe6a43SSeth Howell 			return 0;
141507fe6a43SSeth Howell 		}
141607fe6a43SSeth Howell 	}
141707fe6a43SSeth Howell 
14183ac1d76aSShuhei Matsumoto 	status = spdk_bdev_open_ext(base->name, true, base_bdev_event_cb, base, &base->desc);
141907fe6a43SSeth Howell 	if (status) {
142007fe6a43SSeth Howell 		SPDK_ERRLOG("Unable to open device '%s' for writing\n", base->name);
142107fe6a43SSeth Howell 		return status;
142207fe6a43SSeth Howell 	}
142307fe6a43SSeth Howell 
142407fe6a43SSeth Howell 	status = spdk_bdev_module_claim_bdev(base->bdev, base->desc,
142507fe6a43SSeth Howell 					     &ocf_if);
142607fe6a43SSeth Howell 	if (status) {
142707fe6a43SSeth Howell 		SPDK_ERRLOG("Unable to claim device '%s'\n", base->name);
142807fe6a43SSeth Howell 		spdk_bdev_close(base->desc);
142907fe6a43SSeth Howell 		return status;
143007fe6a43SSeth Howell 	}
143107fe6a43SSeth Howell 
14321b6d1c80SMarcin Dziegielewski 	base->management_channel = spdk_bdev_get_io_channel(base->desc);
14331b6d1c80SMarcin Dziegielewski 	if (!base->management_channel) {
14341b6d1c80SMarcin Dziegielewski 		SPDK_ERRLOG("Unable to get io channel '%s'\n", base->name);
14351b6d1c80SMarcin Dziegielewski 		spdk_bdev_module_release_bdev(base->bdev);
14361b6d1c80SMarcin Dziegielewski 		spdk_bdev_close(base->desc);
14371b6d1c80SMarcin Dziegielewski 		return -ENOMEM;
14381b6d1c80SMarcin Dziegielewski 	}
14391b6d1c80SMarcin Dziegielewski 
1440b3be320dSGangCao 	/* Save the thread where the base device is opened */
1441b3be320dSGangCao 	base->thread = spdk_get_thread();
1442b3be320dSGangCao 
144307fe6a43SSeth Howell 	base->attached = true;
144407fe6a43SSeth Howell 	return status;
144507fe6a43SSeth Howell }
144607fe6a43SSeth Howell 
144707fe6a43SSeth Howell /* Attach base bdevs */
144807fe6a43SSeth Howell static int
144907fe6a43SSeth Howell attach_base_bdevs(struct vbdev_ocf *vbdev,
145007fe6a43SSeth Howell 		  struct spdk_bdev *cache_bdev,
145107fe6a43SSeth Howell 		  struct spdk_bdev *core_bdev)
145207fe6a43SSeth Howell {
145307fe6a43SSeth Howell 	int rc = 0;
145407fe6a43SSeth Howell 
145507fe6a43SSeth Howell 	if (cache_bdev) {
145607fe6a43SSeth Howell 		vbdev->cache.bdev = cache_bdev;
145707fe6a43SSeth Howell 		rc |= attach_base(&vbdev->cache);
145807fe6a43SSeth Howell 	}
145907fe6a43SSeth Howell 
146007fe6a43SSeth Howell 	if (core_bdev) {
146107fe6a43SSeth Howell 		vbdev->core.bdev = core_bdev;
146207fe6a43SSeth Howell 		rc |= attach_base(&vbdev->core);
146307fe6a43SSeth Howell 	}
146407fe6a43SSeth Howell 
146507fe6a43SSeth Howell 	return rc;
146607fe6a43SSeth Howell }
146707fe6a43SSeth Howell 
146807fe6a43SSeth Howell /* Init and then start vbdev if all base devices are present */
146907fe6a43SSeth Howell void
147007fe6a43SSeth Howell vbdev_ocf_construct(const char *vbdev_name,
147107fe6a43SSeth Howell 		    const char *cache_mode_name,
14724d91b4efSrafalste 		    const uint64_t cache_line_size,
147307fe6a43SSeth Howell 		    const char *cache_name,
147407fe6a43SSeth Howell 		    const char *core_name,
147507fe6a43SSeth Howell 		    bool loadq,
147607fe6a43SSeth Howell 		    void (*cb)(int, struct vbdev_ocf *, void *),
147707fe6a43SSeth Howell 		    void *cb_arg)
147807fe6a43SSeth Howell {
147907fe6a43SSeth Howell 	int rc;
148007fe6a43SSeth Howell 	struct spdk_bdev *cache_bdev = spdk_bdev_get_by_name(cache_name);
148107fe6a43SSeth Howell 	struct spdk_bdev *core_bdev = spdk_bdev_get_by_name(core_name);
148207fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
148307fe6a43SSeth Howell 
14844d91b4efSrafalste 	rc = init_vbdev(vbdev_name, cache_mode_name, cache_line_size, cache_name, core_name, loadq);
148507fe6a43SSeth Howell 	if (rc) {
148607fe6a43SSeth Howell 		cb(rc, NULL, cb_arg);
148707fe6a43SSeth Howell 		return;
148807fe6a43SSeth Howell 	}
148907fe6a43SSeth Howell 
149007fe6a43SSeth Howell 	vbdev = vbdev_ocf_get_by_name(vbdev_name);
149107fe6a43SSeth Howell 	if (vbdev == NULL) {
149207fe6a43SSeth Howell 		cb(-ENODEV, NULL, cb_arg);
149307fe6a43SSeth Howell 		return;
149407fe6a43SSeth Howell 	}
149507fe6a43SSeth Howell 
149607fe6a43SSeth Howell 	if (cache_bdev == NULL) {
149707fe6a43SSeth Howell 		SPDK_NOTICELOG("OCF bdev '%s' is waiting for cache device '%s' to connect\n",
149807fe6a43SSeth Howell 			       vbdev->name, cache_name);
149907fe6a43SSeth Howell 	}
150007fe6a43SSeth Howell 	if (core_bdev == NULL) {
150107fe6a43SSeth Howell 		SPDK_NOTICELOG("OCF bdev '%s' is waiting for core device '%s' to connect\n",
150207fe6a43SSeth Howell 			       vbdev->name, core_name);
150307fe6a43SSeth Howell 	}
150407fe6a43SSeth Howell 
150507fe6a43SSeth Howell 	rc = attach_base_bdevs(vbdev, cache_bdev, core_bdev);
150607fe6a43SSeth Howell 	if (rc) {
150707fe6a43SSeth Howell 		cb(rc, vbdev, cb_arg);
150807fe6a43SSeth Howell 		return;
150907fe6a43SSeth Howell 	}
151007fe6a43SSeth Howell 
151107fe6a43SSeth Howell 	if (core_bdev && cache_bdev) {
151207fe6a43SSeth Howell 		register_vbdev(vbdev, cb, cb_arg);
151307fe6a43SSeth Howell 	} else {
151407fe6a43SSeth Howell 		cb(0, vbdev, cb_arg);
151507fe6a43SSeth Howell 	}
151607fe6a43SSeth Howell }
151707fe6a43SSeth Howell 
15185bdaec63SRafal Stefanowski /* Set new cache mode on OCF cache */
15195bdaec63SRafal Stefanowski void
15205bdaec63SRafal Stefanowski vbdev_ocf_set_cache_mode(struct vbdev_ocf *vbdev,
15215bdaec63SRafal Stefanowski 			 const char *cache_mode_name,
15225bdaec63SRafal Stefanowski 			 void (*cb)(int, struct vbdev_ocf *, void *),
15235bdaec63SRafal Stefanowski 			 void *cb_arg)
15245bdaec63SRafal Stefanowski {
15255bdaec63SRafal Stefanowski 	ocf_cache_t cache;
15265bdaec63SRafal Stefanowski 	ocf_cache_mode_t cache_mode;
15275bdaec63SRafal Stefanowski 	int rc;
15285bdaec63SRafal Stefanowski 
15295bdaec63SRafal Stefanowski 	cache = vbdev->ocf_cache;
15305bdaec63SRafal Stefanowski 	cache_mode = ocf_get_cache_mode(cache_mode_name);
15315bdaec63SRafal Stefanowski 
15325bdaec63SRafal Stefanowski 	rc = ocf_mngt_cache_trylock(cache);
15335bdaec63SRafal Stefanowski 	if (rc) {
15345bdaec63SRafal Stefanowski 		cb(rc, vbdev, cb_arg);
15355bdaec63SRafal Stefanowski 		return;
15365bdaec63SRafal Stefanowski 	}
15375bdaec63SRafal Stefanowski 
15385bdaec63SRafal Stefanowski 	rc = ocf_mngt_cache_set_mode(cache, cache_mode);
15395bdaec63SRafal Stefanowski 	ocf_mngt_cache_unlock(cache);
15405bdaec63SRafal Stefanowski 	cb(rc, vbdev, cb_arg);
15415bdaec63SRafal Stefanowski }
15425bdaec63SRafal Stefanowski 
1543494b1ba8SRafal Stefanowski /* Set sequential cutoff parameters on OCF cache */
1544494b1ba8SRafal Stefanowski void
1545494b1ba8SRafal Stefanowski vbdev_ocf_set_seqcutoff(struct vbdev_ocf *vbdev, const char *policy_name, uint32_t threshold,
1546494b1ba8SRafal Stefanowski 			uint32_t promotion_count, void (*cb)(int, void *), void *cb_arg)
1547494b1ba8SRafal Stefanowski {
1548494b1ba8SRafal Stefanowski 	ocf_cache_t cache;
1549494b1ba8SRafal Stefanowski 	ocf_seq_cutoff_policy policy;
1550494b1ba8SRafal Stefanowski 	int rc;
1551494b1ba8SRafal Stefanowski 
1552494b1ba8SRafal Stefanowski 	cache = vbdev->ocf_cache;
1553494b1ba8SRafal Stefanowski 
1554494b1ba8SRafal Stefanowski 	policy = ocf_get_seqcutoff_policy(policy_name);
1555494b1ba8SRafal Stefanowski 	if (policy == ocf_seq_cutoff_policy_max) {
1556494b1ba8SRafal Stefanowski 		cb(OCF_ERR_INVAL, cb_arg);
1557494b1ba8SRafal Stefanowski 		return;
1558494b1ba8SRafal Stefanowski 	}
1559494b1ba8SRafal Stefanowski 
1560494b1ba8SRafal Stefanowski 	rc = ocf_mngt_cache_trylock(cache);
1561494b1ba8SRafal Stefanowski 	if (rc) {
1562494b1ba8SRafal Stefanowski 		cb(rc, cb_arg);
1563494b1ba8SRafal Stefanowski 		return;
1564494b1ba8SRafal Stefanowski 	}
1565494b1ba8SRafal Stefanowski 
1566494b1ba8SRafal Stefanowski 	rc = ocf_mngt_core_set_seq_cutoff_policy_all(cache, policy);
1567494b1ba8SRafal Stefanowski 	if (rc) {
1568494b1ba8SRafal Stefanowski 		goto end;
1569494b1ba8SRafal Stefanowski 	}
1570494b1ba8SRafal Stefanowski 
1571494b1ba8SRafal Stefanowski 	if (threshold) {
1572494b1ba8SRafal Stefanowski 		threshold = threshold * KiB;
1573494b1ba8SRafal Stefanowski 
1574494b1ba8SRafal Stefanowski 		rc = ocf_mngt_core_set_seq_cutoff_threshold_all(cache, threshold);
1575494b1ba8SRafal Stefanowski 		if (rc) {
1576494b1ba8SRafal Stefanowski 			goto end;
1577494b1ba8SRafal Stefanowski 		}
1578494b1ba8SRafal Stefanowski 	}
1579494b1ba8SRafal Stefanowski 
1580494b1ba8SRafal Stefanowski 	if (promotion_count) {
1581494b1ba8SRafal Stefanowski 		rc = ocf_mngt_core_set_seq_cutoff_promotion_count_all(cache, promotion_count);
1582494b1ba8SRafal Stefanowski 	}
1583494b1ba8SRafal Stefanowski 
1584494b1ba8SRafal Stefanowski end:
1585494b1ba8SRafal Stefanowski 	ocf_mngt_cache_unlock(cache);
1586494b1ba8SRafal Stefanowski 	cb(rc, cb_arg);
1587494b1ba8SRafal Stefanowski }
1588494b1ba8SRafal Stefanowski 
158907fe6a43SSeth Howell /* This called if new device is created in SPDK application
159007fe6a43SSeth Howell  * If that device named as one of base bdevs of OCF vbdev,
159107fe6a43SSeth Howell  * claim and open them */
159207fe6a43SSeth Howell static void
159307fe6a43SSeth Howell vbdev_ocf_examine(struct spdk_bdev *bdev)
159407fe6a43SSeth Howell {
159507fe6a43SSeth Howell 	const char *bdev_name = spdk_bdev_get_name(bdev);
159607fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
159707fe6a43SSeth Howell 
159807fe6a43SSeth Howell 	TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
159907fe6a43SSeth Howell 		if (vbdev->state.doing_finish) {
160007fe6a43SSeth Howell 			continue;
160107fe6a43SSeth Howell 		}
160207fe6a43SSeth Howell 
160307fe6a43SSeth Howell 		if (!strcmp(bdev_name, vbdev->cache.name)) {
160407fe6a43SSeth Howell 			attach_base_bdevs(vbdev, bdev, NULL);
160507fe6a43SSeth Howell 			continue;
160607fe6a43SSeth Howell 		}
160707fe6a43SSeth Howell 		if (!strcmp(bdev_name, vbdev->core.name)) {
160807fe6a43SSeth Howell 			attach_base_bdevs(vbdev, NULL, bdev);
160907fe6a43SSeth Howell 			break;
161007fe6a43SSeth Howell 		}
161107fe6a43SSeth Howell 	}
161207fe6a43SSeth Howell 	spdk_bdev_module_examine_done(&ocf_if);
161307fe6a43SSeth Howell }
161407fe6a43SSeth Howell 
161507fe6a43SSeth Howell struct metadata_probe_ctx {
161607fe6a43SSeth Howell 	struct vbdev_ocf_base base;
161707fe6a43SSeth Howell 	ocf_volume_t volume;
161807fe6a43SSeth Howell 
161907fe6a43SSeth Howell 	struct ocf_volume_uuid *core_uuids;
162007fe6a43SSeth Howell 	unsigned int uuid_count;
162107fe6a43SSeth Howell 
162207fe6a43SSeth Howell 	int result;
162307fe6a43SSeth Howell 	int refcnt;
162407fe6a43SSeth Howell };
162507fe6a43SSeth Howell 
162607fe6a43SSeth Howell static void
1627b3be320dSGangCao _examine_ctx_put(void *ctx)
1628b3be320dSGangCao {
1629b3be320dSGangCao 	struct spdk_bdev_desc *desc = ctx;
1630b3be320dSGangCao 
1631b3be320dSGangCao 	spdk_bdev_close(desc);
1632b3be320dSGangCao }
1633b3be320dSGangCao 
1634b3be320dSGangCao static void
163507fe6a43SSeth Howell examine_ctx_put(struct metadata_probe_ctx *ctx)
163607fe6a43SSeth Howell {
163707fe6a43SSeth Howell 	unsigned int i;
163807fe6a43SSeth Howell 
163907fe6a43SSeth Howell 	ctx->refcnt--;
164007fe6a43SSeth Howell 	if (ctx->refcnt > 0) {
164107fe6a43SSeth Howell 		return;
164207fe6a43SSeth Howell 	}
164307fe6a43SSeth Howell 
164407fe6a43SSeth Howell 	if (ctx->result) {
164507fe6a43SSeth Howell 		SPDK_ERRLOG("OCF metadata probe for bdev '%s' failed with %d\n",
164607fe6a43SSeth Howell 			    spdk_bdev_get_name(ctx->base.bdev), ctx->result);
164707fe6a43SSeth Howell 	}
164807fe6a43SSeth Howell 
164907fe6a43SSeth Howell 	if (ctx->base.desc) {
1650b3be320dSGangCao 		/* Close the underlying bdev on its same opened thread. */
1651b3be320dSGangCao 		if (ctx->base.thread && ctx->base.thread != spdk_get_thread()) {
1652b3be320dSGangCao 			spdk_thread_send_msg(ctx->base.thread, _examine_ctx_put, ctx->base.desc);
1653b3be320dSGangCao 		} else {
165407fe6a43SSeth Howell 			spdk_bdev_close(ctx->base.desc);
165507fe6a43SSeth Howell 		}
1656b3be320dSGangCao 	}
165707fe6a43SSeth Howell 
165807fe6a43SSeth Howell 	if (ctx->volume) {
165907fe6a43SSeth Howell 		ocf_volume_destroy(ctx->volume);
166007fe6a43SSeth Howell 	}
166107fe6a43SSeth Howell 
166207fe6a43SSeth Howell 	if (ctx->core_uuids) {
166307fe6a43SSeth Howell 		for (i = 0; i < ctx->uuid_count; i++) {
166407fe6a43SSeth Howell 			free(ctx->core_uuids[i].data);
166507fe6a43SSeth Howell 		}
166607fe6a43SSeth Howell 	}
166707fe6a43SSeth Howell 	free(ctx->core_uuids);
166807fe6a43SSeth Howell 
166907fe6a43SSeth Howell 	examine_done(ctx->result, NULL, ctx->base.bdev);
167007fe6a43SSeth Howell 	free(ctx);
167107fe6a43SSeth Howell }
167207fe6a43SSeth Howell 
167307fe6a43SSeth Howell static void
167407fe6a43SSeth Howell metadata_probe_cb(void *priv, int rc,
167507fe6a43SSeth Howell 		  struct ocf_metadata_probe_status *status)
167607fe6a43SSeth Howell {
167707fe6a43SSeth Howell 	struct metadata_probe_ctx *ctx = priv;
167807fe6a43SSeth Howell 
167907fe6a43SSeth Howell 	if (rc) {
168007fe6a43SSeth Howell 		/* -ENODATA means device does not have cache metadata on it */
168120894340SMarcin Dziegielewski 		if (rc != -OCF_ERR_NO_METADATA) {
168207fe6a43SSeth Howell 			ctx->result = rc;
168307fe6a43SSeth Howell 		}
168407fe6a43SSeth Howell 	}
168507fe6a43SSeth Howell 
168637975647SAmir Haroush 	examine_ctx_put(ctx);
168707fe6a43SSeth Howell }
168807fe6a43SSeth Howell 
168907fe6a43SSeth Howell /* This is called after vbdev_ocf_examine
169007fe6a43SSeth Howell  * It allows to delay application initialization
169107fe6a43SSeth Howell  * until all OCF bdevs get registered
169207fe6a43SSeth Howell  * If vbdev has all of its base devices it starts asynchronously here
169307fe6a43SSeth Howell  * We first check if bdev appears in configuration,
169407fe6a43SSeth Howell  * if not we do metadata_probe() to create its configuration from bdev metadata */
169507fe6a43SSeth Howell static void
169607fe6a43SSeth Howell vbdev_ocf_examine_disk(struct spdk_bdev *bdev)
169707fe6a43SSeth Howell {
169807fe6a43SSeth Howell 	const char *bdev_name = spdk_bdev_get_name(bdev);
169907fe6a43SSeth Howell 	struct vbdev_ocf *vbdev;
170007fe6a43SSeth Howell 	struct metadata_probe_ctx *ctx;
170107fe6a43SSeth Howell 	bool created_from_config = false;
170207fe6a43SSeth Howell 	int rc;
170307fe6a43SSeth Howell 
170407fe6a43SSeth Howell 	examine_start(bdev);
170507fe6a43SSeth Howell 
170607fe6a43SSeth Howell 	TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
170707fe6a43SSeth Howell 		if (vbdev->state.doing_finish || vbdev->state.started) {
170807fe6a43SSeth Howell 			continue;
170907fe6a43SSeth Howell 		}
171007fe6a43SSeth Howell 
171107fe6a43SSeth Howell 		if (!strcmp(bdev_name, vbdev->cache.name)) {
171207fe6a43SSeth Howell 			examine_start(bdev);
171307fe6a43SSeth Howell 			register_vbdev(vbdev, examine_done, bdev);
171407fe6a43SSeth Howell 			created_from_config = true;
171507fe6a43SSeth Howell 			continue;
171607fe6a43SSeth Howell 		}
171707fe6a43SSeth Howell 		if (!strcmp(bdev_name, vbdev->core.name)) {
171807fe6a43SSeth Howell 			examine_start(bdev);
171907fe6a43SSeth Howell 			register_vbdev(vbdev, examine_done, bdev);
172007fe6a43SSeth Howell 			examine_done(0, NULL, bdev);
172107fe6a43SSeth Howell 			return;
172207fe6a43SSeth Howell 		}
172307fe6a43SSeth Howell 	}
172407fe6a43SSeth Howell 
172507fe6a43SSeth Howell 	/* If devices is discovered during config we do not check for metadata */
172607fe6a43SSeth Howell 	if (created_from_config) {
172707fe6a43SSeth Howell 		examine_done(0, NULL, bdev);
172807fe6a43SSeth Howell 		return;
172907fe6a43SSeth Howell 	}
173007fe6a43SSeth Howell 
173107fe6a43SSeth Howell 	/* Metadata probe path
173207fe6a43SSeth Howell 	 * We create temporary OCF volume and a temporary base structure
173307fe6a43SSeth Howell 	 * to use them for ocf_metadata_probe() and for bottom adapter IOs
173407fe6a43SSeth Howell 	 * Then we get UUIDs of core devices an create configurations based on them */
173507fe6a43SSeth Howell 	ctx = calloc(1, sizeof(*ctx));
173607fe6a43SSeth Howell 	if (!ctx) {
173707fe6a43SSeth Howell 		examine_done(-ENOMEM, NULL, bdev);
173807fe6a43SSeth Howell 		return;
173907fe6a43SSeth Howell 	}
174007fe6a43SSeth Howell 
174107fe6a43SSeth Howell 	ctx->base.bdev = bdev;
174207fe6a43SSeth Howell 	ctx->refcnt = 1;
174307fe6a43SSeth Howell 
17443ac1d76aSShuhei Matsumoto 	rc = spdk_bdev_open_ext(bdev_name, true, base_bdev_event_cb, NULL, &ctx->base.desc);
174507fe6a43SSeth Howell 	if (rc) {
174607fe6a43SSeth Howell 		ctx->result = rc;
174707fe6a43SSeth Howell 		examine_ctx_put(ctx);
174807fe6a43SSeth Howell 		return;
174907fe6a43SSeth Howell 	}
175007fe6a43SSeth Howell 
175107fe6a43SSeth Howell 	rc = ocf_ctx_volume_create(vbdev_ocf_ctx, &ctx->volume, NULL, SPDK_OBJECT);
175207fe6a43SSeth Howell 	if (rc) {
175307fe6a43SSeth Howell 		ctx->result = rc;
175407fe6a43SSeth Howell 		examine_ctx_put(ctx);
175507fe6a43SSeth Howell 		return;
175607fe6a43SSeth Howell 	}
175707fe6a43SSeth Howell 
175807fe6a43SSeth Howell 	rc = ocf_volume_open(ctx->volume, &ctx->base);
175907fe6a43SSeth Howell 	if (rc) {
176007fe6a43SSeth Howell 		ctx->result = rc;
176107fe6a43SSeth Howell 		examine_ctx_put(ctx);
176207fe6a43SSeth Howell 		return;
176307fe6a43SSeth Howell 	}
176407fe6a43SSeth Howell 
1765b3be320dSGangCao 	/* Save the thread where the base device is opened */
1766b3be320dSGangCao 	ctx->base.thread = spdk_get_thread();
1767b3be320dSGangCao 
176807fe6a43SSeth Howell 	ocf_metadata_probe(vbdev_ocf_ctx, ctx->volume, metadata_probe_cb, ctx);
176907fe6a43SSeth Howell }
177007fe6a43SSeth Howell 
177107fe6a43SSeth Howell static int
177207fe6a43SSeth Howell vbdev_ocf_get_ctx_size(void)
177307fe6a43SSeth Howell {
177407fe6a43SSeth Howell 	return sizeof(struct bdev_ocf_data);
177507fe6a43SSeth Howell }
177607fe6a43SSeth Howell 
177707fe6a43SSeth Howell static void
177807fe6a43SSeth Howell fini_start(void)
177907fe6a43SSeth Howell {
178007fe6a43SSeth Howell 	g_fini_started = true;
178107fe6a43SSeth Howell }
178207fe6a43SSeth Howell 
178307fe6a43SSeth Howell /* Module-global function table
178407fe6a43SSeth Howell  * Does not relate to vbdev instances */
178507fe6a43SSeth Howell static struct spdk_bdev_module ocf_if = {
178607fe6a43SSeth Howell 	.name = "ocf",
178707fe6a43SSeth Howell 	.module_init = vbdev_ocf_init,
178807fe6a43SSeth Howell 	.fini_start = fini_start,
178907fe6a43SSeth Howell 	.module_fini = vbdev_ocf_module_fini,
179007fe6a43SSeth Howell 	.get_ctx_size = vbdev_ocf_get_ctx_size,
179107fe6a43SSeth Howell 	.examine_config = vbdev_ocf_examine,
179207fe6a43SSeth Howell 	.examine_disk   = vbdev_ocf_examine_disk,
179307fe6a43SSeth Howell };
179407fe6a43SSeth Howell SPDK_BDEV_MODULE_REGISTER(ocf, &ocf_if);
1795