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