From 1fd9a448d4851adc5c0d95bab02dd0cfa07e41b9 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Wed, 11 Aug 2021 19:53:07 +0200 Subject: [PATCH] Introduce passive cache state Signed-off-by: Robert Baldyga --- inc/ocf_cache.h | 9 ++ inc/ocf_def.h | 3 + inc/ocf_mngt.h | 22 ++++ src/mngt/ocf_mngt_cache.c | 231 ++++++++++++++++++++++++++++++++++++-- src/ocf_cache.c | 21 +++- src/ocf_cache_priv.h | 1 + 6 files changed, 269 insertions(+), 18 deletions(-) diff --git a/inc/ocf_cache.h b/inc/ocf_cache.h index 24f17c7..cf85cb2 100644 --- a/inc/ocf_cache.h +++ b/inc/ocf_cache.h @@ -103,6 +103,15 @@ struct ocf_cache_info { */ ocf_volume_t ocf_cache_get_volume(ocf_cache_t cache); +/** + * @brief Obtain front volume from cache + * + * @param[in] cache Cache object + * + * @retval Volume, NULL if dettached. + */ +ocf_volume_t ocf_cache_get_front_volume(ocf_cache_t cache); + /** * @brief Get name of given cache object * diff --git a/inc/ocf_def.h b/inc/ocf_def.h index 89fb2e0..c654ef0 100644 --- a/inc/ocf_def.h +++ b/inc/ocf_def.h @@ -124,6 +124,9 @@ typedef enum { ocf_cache_state_incomplete = 3, //!< ocf_cache_state_incomplete /*!< OCF cache has at least one inactive core */ + ocf_cache_state_passive = 4, //!< ocf_cache_state_passive + /*!< OCF is currently in passive mode */ + ocf_cache_state_max //!< ocf_cache_state_max /*!< Stopper of cache state enumerator */ } ocf_cache_state_t; diff --git a/inc/ocf_mngt.h b/inc/ocf_mngt.h index 6c3962a..51f1940 100644 --- a/inc/ocf_mngt.h +++ b/inc/ocf_mngt.h @@ -514,6 +514,28 @@ void ocf_mngt_cache_load(ocf_cache_t cache, struct ocf_mngt_cache_device_config *cfg, ocf_mngt_cache_load_end_t cmpl, void *priv); +/** + * @brief Completion callback of cache bind operation + * + * @param[in] cache Cache handle + * @param[in] priv Callback context + * @param[in] error Error code (zero on success) + */ +typedef void (*ocf_mngt_cache_bind_end_t)(ocf_cache_t cache, + void *priv, int error); + +/** + * @brief Bind cache instance + * + * @param[in] cache Cache handle + * @param[in] cfg Caching device configuration + * @param[in] cmpl Completion callback + * @param[in] priv Completion callback context + */ +void ocf_mngt_cache_bind(ocf_cache_t cache, + struct ocf_mngt_cache_device_config *cfg, + ocf_mngt_cache_bind_end_t cmpl, void *priv); + /* Adding and removing cores */ /** diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 0b9450e..75c7689 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -104,14 +104,20 @@ struct ocf_cache_attach_context { /*!< data structure allocated */ bool volume_inited : 1; - /*!< uuid for cache device is allocated */ + /*!< underlying device volume is initialized */ + + bool volume_opened : 1; + /*!< underlying device volume is open */ + + bool front_volume_inited : 1; + /*!< front volume is initialized */ + + bool front_volume_opened : 1; + /*!< front volume is open */ bool attached_metadata_inited : 1; /*!< attached metadata sections initialized */ - bool device_opened : 1; - /*!< underlying device volume is open */ - bool cleaner_started : 1; /*!< Cleaner has been started */ @@ -234,8 +240,10 @@ static void __setup_promotion_policy(ocf_cache_t cache) static void __deinit_promotion_policy(ocf_cache_t cache) { - ocf_promotion_deinit(cache->promotion_policy); - cache->promotion_policy = NULL; + if (cache->promotion_policy) { + ocf_promotion_deinit(cache->promotion_policy); + cache->promotion_policy = NULL; + } } static void __init_free(ocf_cache_t cache) @@ -725,7 +733,7 @@ static void _ocf_mngt_attach_cache_device(ocf_pipeline_t pipeline, ocf_cache_log(cache, log_err, "ERROR: Cache not available\n"); OCF_PL_FINISH_RET(pipeline, ret); } - context->flags.device_opened = true; + context->flags.volume_opened = true; context->volume_size = ocf_volume_get_length(&cache->device->volume); @@ -1224,15 +1232,21 @@ static void _ocf_mngt_attach_handle_error( if (context->flags.attached_metadata_inited) ocf_metadata_deinit_variable_size(cache); - if (context->flags.device_opened) - ocf_volume_close(&cache->device->volume); - if (context->flags.concurrency_inited) ocf_concurrency_deinit(cache); + if (context->flags.volume_opened) + ocf_volume_close(&cache->device->volume); + if (context->flags.volume_inited) ocf_volume_deinit(&cache->device->volume); + if (context->flags.front_volume_opened) + ocf_volume_close(&cache->device->front_volume); + + if (context->flags.front_volume_inited) + ocf_volume_deinit(&cache->device->front_volume); + if (context->flags.device_alloc) env_vfree(cache->device); @@ -1347,6 +1361,15 @@ static void _ocf_mngt_cache_set_valid(ocf_cache_t cache) env_bit_set(ocf_cache_state_running, &cache->cache_state); } +static void _ocf_mngt_cache_set_passive(ocf_cache_t cache) +{ + /* + * Clear initialization state and set the passive bit. + */ + env_bit_clear(ocf_cache_state_initializing, &cache->cache_state); + env_bit_set(ocf_cache_state_passive, &cache->cache_state); +} + static void _ocf_mngt_init_attached_nonpersistent(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { @@ -1918,6 +1941,101 @@ struct ocf_pipeline_properties ocf_mngt_cache_stop_pipeline_properties = { }, }; +static void _ocf_mngt_init_cache_front_volume(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + ocf_volume_type_t type; + struct ocf_volume_uuid uuid = { + .data = cache, + .size = sizeof(cache), + }; + int result; + + type = ocf_ctx_get_volume_type_internal(cache->owner, OCF_VOLUME_TYPE_CACHE); + if (!type) + OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_INVAL); + + result = ocf_volume_init(&cache->device->front_volume, type, &uuid, false); + if (result) + OCF_PL_FINISH_RET(context->pipeline, result); + context->flags.front_volume_inited = true; + + result = ocf_volume_open(&cache->device->front_volume, NULL); + if (result) + OCF_PL_FINISH_RET(context->pipeline, result); + context->flags.front_volume_opened = true; + + ocf_pipeline_next(context->pipeline); +} + +static void _ocf_mngt_load_unsafe_complete(void *priv, int error) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + + if (error) { + ocf_cache_log(cache, log_err, + "ERROR: Cannot load metadata\n"); + OCF_PL_FINISH_RET(context->pipeline, + -OCF_ERR_START_CACHE_FAIL); + } + + ocf_pipeline_next(context->pipeline); +} + +static void _ocf_mngt_load_metadata_unsafe(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + + ocf_cache_log(cache, log_info, "Loading cache state...\n"); + ocf_metadata_load_unsafe(cache, + _ocf_mngt_load_unsafe_complete, context); +} + +static void _ocf_mngt_bind_init_attached_structures(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + + init_attached_data_structures_recovery(cache); + + ocf_pipeline_next(context->pipeline); +} + +static void _ocf_mngt_bind_post_init(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + + ocf_refcnt_unfreeze(&cache->refcnt.metadata); + + ocf_pipeline_next(pipeline); +} + +struct ocf_pipeline_properties _ocf_mngt_cache_bind_pipeline_properties = { + .priv_size = sizeof(struct ocf_cache_attach_context), + .finish = _ocf_mngt_cache_attach_finish, + .steps = { + OCF_PL_STEP(_ocf_mngt_copy_uuid_data), + OCF_PL_STEP(_ocf_mngt_init_attached_nonpersistent), + OCF_PL_STEP(_ocf_mngt_attach_cache_device), + OCF_PL_STEP(_ocf_mngt_init_cache_front_volume), + OCF_PL_STEP(_ocf_mngt_init_properties), + OCF_PL_STEP(_ocf_mngt_attach_check_ram), + OCF_PL_STEP(_ocf_mngt_test_volume), + OCF_PL_STEP(_ocf_mngt_attach_prepare_metadata), + OCF_PL_STEP(_ocf_mngt_load_metadata_unsafe), + OCF_PL_STEP(_ocf_mngt_bind_init_attached_structures), + OCF_PL_STEP(_ocf_mngt_bind_post_init), + OCF_PL_STEP_TERMINATOR(), + }, +}; static void _ocf_mngt_cache_attach(ocf_cache_t cache, struct ocf_mngt_cache_device_config *cfg, @@ -1985,6 +2103,51 @@ static void _ocf_mngt_cache_load(ocf_cache_t cache, OCF_PL_NEXT_RET(pipeline); } +struct ocf_pipeline_properties +ocf_mngt_cache_stop_passive_pipeline_properties = { + .priv_size = sizeof(struct ocf_mngt_cache_stop_context), + .finish = ocf_mngt_cache_stop_finish, + .steps = { + OCF_PL_STEP(ocf_mngt_cache_stop_wait_metadata_io), + OCF_PL_STEP(ocf_mngt_cache_stop_deinit_metadata), + OCF_PL_STEP(ocf_mngt_cache_stop_put_io_queues), + OCF_PL_STEP_TERMINATOR(), + }, +}; + +static void _ocf_mngt_cache_bind(ocf_cache_t cache, + struct ocf_mngt_cache_device_config *cfg, + _ocf_mngt_cache_attach_end_t cmpl, void *priv1, void *priv2) +{ + struct ocf_cache_attach_context *context; + ocf_pipeline_t pipeline; + int result; + + result = ocf_pipeline_create(&pipeline, cache, + &_ocf_mngt_cache_bind_pipeline_properties); + if (result) + OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_NO_MEM); + + result = ocf_pipeline_create(&cache->stop_pipeline, cache, + &ocf_mngt_cache_stop_passive_pipeline_properties); + if (result) { + ocf_pipeline_destroy(pipeline); + OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_NO_MEM); + } + + context = ocf_pipeline_get_priv(pipeline); + + context->cmpl = cmpl; + context->priv1 = priv1; + context->priv2 = priv2; + context->pipeline = pipeline; + + context->cache = cache; + context->cfg = *cfg; + + OCF_PL_NEXT_RET(pipeline); +} + static int _ocf_mngt_cache_validate_cfg(struct ocf_mngt_cache_config *cfg) { if (!strnlen(cfg->name, OCF_CACHE_NAME_SIZE)) @@ -2059,8 +2222,6 @@ int ocf_mngt_cache_start(ocf_ctx_t ctx, ocf_cache_t *cache, result = _ocf_mngt_cache_start(ctx, cache, cfg, priv); if (!result) { - _ocf_mngt_cache_set_valid(*cache); - ocf_cache_log(*cache, log_info, "Successfully added\n"); ocf_cache_log(*cache, log_info, "Cache mode : %s\n", _ocf_cache_mode_get_name(ocf_cache_get_mode(*cache))); @@ -2090,6 +2251,7 @@ static void _ocf_mngt_cache_attach_complete(ocf_cache_t cache, void *priv1, ocf_mngt_cache_attach_end_t cmpl = priv1; if (!error) { + _ocf_mngt_cache_set_valid(cache); ocf_cache_log(cache, log_info, "Successfully attached\n"); } else { ocf_cache_log(cache, log_err, "Attaching cache device " @@ -2236,6 +2398,51 @@ void ocf_mngt_cache_load(ocf_cache_t cache, _ocf_mngt_cache_load(cache, cfg, _ocf_mngt_cache_load_complete, cmpl, priv); } +static void _ocf_mngt_cache_bind_complete(ocf_cache_t cache, void *priv1, + void *priv2, int error) +{ + ocf_mngt_cache_bind_end_t cmpl = priv1; + + if (error) + OCF_CMPL_RET(cache, priv2, error); + + _ocf_mngt_cache_set_passive(cache); + ocf_cache_log(cache, log_info, "Successfully binded\n"); + + OCF_CMPL_RET(cache, priv2, 0); +} + +void ocf_mngt_cache_bind(ocf_cache_t cache, + struct ocf_mngt_cache_device_config *cfg, + ocf_mngt_cache_bind_end_t cmpl, void *priv) +{ + int result; + + OCF_CHECK_NULL(cache); + OCF_CHECK_NULL(cfg); + + if (!cache->mngt_queue) + OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); + + /* Bind is not allowed in volatile metadata mode */ + if (cache->metadata.is_volatile) + OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); + + /* Bind is not allowed with 'force' flag on */ + if (cfg->force) { + ocf_cache_log(cache, log_err, "Using 'force' flag is forbidden " + "for bind operation."); + OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); + } + + result = _ocf_mngt_cache_validate_device_cfg(cfg); + if (result) + OCF_CMPL_RET(cache, priv, result); + + _ocf_mngt_cache_bind(cache, cfg, _ocf_mngt_cache_bind_complete, + cmpl, priv); +} + static void ocf_mngt_cache_stop_detached(ocf_cache_t cache, ocf_mngt_cache_stop_end_t cmpl, void *priv) { diff --git a/src/ocf_cache.c b/src/ocf_cache.c index 3c7d12a..d3e0476 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -19,6 +19,11 @@ ocf_volume_t ocf_cache_get_volume(ocf_cache_t cache) return cache->device ? &cache->device->volume : NULL; } +ocf_volume_t ocf_cache_get_front_volume(ocf_cache_t cache) +{ + return cache->device ? &cache->device->front_volume : NULL; +} + int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size) { int result; @@ -101,6 +106,16 @@ int ocf_cache_get_info(ocf_cache_t cache, struct ocf_cache_info *info) cache->device->volume.type); info->size = cache->conf_meta->cachelines; } + info->state = cache->cache_state; + info->cache_line_size = ocf_line_size(cache); + info->metadata_end_offset = ocf_cache_is_device_attached(cache) ? + cache->device->metadata_offset / PAGE_SIZE : 0; + info->metadata_footprint = ocf_cache_is_device_attached(cache) ? + ocf_metadata_size_of(cache) : 0; + + if (env_bit_test(ocf_cache_state_passive, &cache->cache_state)) + return 0; + info->core_count = cache->conf_meta->core_count; info->cache_mode = ocf_cache_get_mode(cache); @@ -152,10 +167,6 @@ int ocf_cache_get_info(ocf_cache_t cache, struct ocf_cache_info *info) info->dirty_initial = initial_dirty_blocks_total; info->occupancy = cache_occupancy_total; info->dirty_for = _calc_dirty_for(dirty_since); - info->metadata_end_offset = ocf_cache_is_device_attached(cache) ? - cache->device->metadata_offset / PAGE_SIZE : 0; - - info->state = cache->cache_state; if (info->attached) { _set(&info->inactive.occupancy, @@ -179,8 +190,6 @@ int ocf_cache_get_info(ocf_cache_t cache, struct ocf_cache_info *info) info->cleaning_policy = cache->conf_meta->cleaning_policy_type; info->promotion_policy = cache->conf_meta->promotion_policy_type; - info->metadata_footprint = ocf_cache_is_device_attached(cache) ? - ocf_metadata_size_of(cache) : 0; info->cache_line_size = ocf_line_size(cache); return 0; diff --git a/src/ocf_cache_priv.h b/src/ocf_cache_priv.h index ce5239c..e829db0 100644 --- a/src/ocf_cache_priv.h +++ b/src/ocf_cache_priv.h @@ -26,6 +26,7 @@ /* Cache device */ struct ocf_cache_device { + struct ocf_volume front_volume; struct ocf_volume volume; /* Hash Table contains contains pointer to the entry in