diff --git a/inc/ocf_cache.h b/inc/ocf_cache.h index 1701853..cfb89a0 100644 --- a/inc/ocf_cache.h +++ b/inc/ocf_cache.h @@ -93,8 +93,8 @@ struct ocf_cache_info { uint32_t metadata_end_offset; /*!< LBA offset where metadata ends (in 4KiB blocks) */ - bool failover_detached; - /*!< true if cache drive detached for failover */ + bool standby_detached; + /*!< true if cache volume detached in standby mode */ }; /** diff --git a/inc/ocf_err.h b/inc/ocf_err.h index 41a6891..7ca5aa6 100644 --- a/inc/ocf_err.h +++ b/inc/ocf_err.h @@ -141,9 +141,9 @@ typedef enum { OCF_ERR_CACHE_STANDBY, /** Operation invalid with cache drive atatched in failover standby */ - OCF_ERR_FAILOVER_ATTACHED, + OCF_ERR_STANDBY_ATTACHED, - OCF_ERR_MAX = OCF_ERR_FAILOVER_ATTACHED, + OCF_ERR_MAX = OCF_ERR_STANDBY_ATTACHED, } ocf_error_t; #endif /* __OCF_ERR_H__ */ diff --git a/inc/ocf_mngt.h b/inc/ocf_mngt.h index 9a65dfb..e40d21a 100644 --- a/inc/ocf_mngt.h +++ b/inc/ocf_mngt.h @@ -529,52 +529,108 @@ void ocf_mngt_cache_load(ocf_cache_t cache, ocf_mngt_cache_load_end_t cmpl, void *priv); /** - * @brief Completion callback of cache bind operation + * @brief Completion callback of cache standby attach 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, +typedef void (*ocf_mngt_cache_standby_attach_end_t)(ocf_cache_t cache, void *priv, int error); /** - * @brief Initiate failover standby + * @brief Attach caching device to cache instance in failover standby mode * * @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_standby(ocf_cache_t cache, +void ocf_mngt_cache_standby_attach(ocf_cache_t cache, struct ocf_mngt_cache_attach_config *cfg, - ocf_mngt_cache_bind_end_t cmpl, void *priv); + ocf_mngt_cache_standby_attach_end_t cmpl, void *priv); -typedef void (*ocf_mngt_cache_failover_detach_end_t)(void *priv, int error); - -void ocf_mngt_cache_failover_detach(ocf_cache_t cache, - ocf_mngt_cache_failover_detach_end_t cmpl, void *priv); /** - * @brief Completion callback of cache activate operation + * @brief Completion callback of cache standby load operation * * @param[in] cache Cache handle * @param[in] priv Callback context * @param[in] error Error code (zero on success) */ -typedef void (*ocf_mngt_cache_activate_end_t)(ocf_cache_t cache, +typedef void (*ocf_mngt_cache_standby_load_end_t)(ocf_cache_t cache, void *priv, int error); - /** - * @brief Activate cache instance + * @brief Load cache instance in failover standby mode * * @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_activate(ocf_cache_t cache, - struct ocf_mngt_cache_device_config *cfg, - ocf_mngt_cache_activate_end_t cmpl, void *priv); +void ocf_mngt_cache_standby_load(ocf_cache_t cache, + struct ocf_mngt_cache_attach_config *cfg, + ocf_mngt_cache_standby_load_end_t cmpl, void *priv); + +/** + * @brief Completion callback of cache standby detach operation + * + * @param[in] cache Cache handle + * @param[in] priv Callback context + * @param[in] error Error code (zero on success) + */ +typedef void (*ocf_mngt_cache_standby_detach_end_t)(void *priv, int error); + +/** + * @brief Detach cache volume from cache in standby mode + * + * @param[in] cache Cache handle + * @param[in] cmpl Completion callback + * @param[in] priv Completion callback context + */ +void ocf_mngt_cache_standby_detach(ocf_cache_t cache, + ocf_mngt_cache_standby_detach_end_t cmpl, void *priv); + +/** + * @brief Cache standby activate configuration + */ +struct ocf_mngt_cache_standby_activate_config { + /** + * @brief Cache device configuration - must be the first field + */ + struct ocf_mngt_cache_device_config device; + + /** + * @brief Automatically open core volumes when activating cache + * + * If set to false, cache load will not attempt to open core volumes, + * and so cores will be marked "inactive" unless their volumes were + * earlier added to the core pool. In such case user will be expected + * to add cores later using function ocf_mngt_cache_add_core(). + */ + bool open_cores; +}; + +/** + * @brief Completion callback of standby cache activate operation + * + * @param[in] cache Cache handle + * @param[in] priv Callback context + * @param[in] error Error code (zero on success) + */ +typedef void (*ocf_mngt_cache_standby_activate_end_t)(ocf_cache_t cache, + void *priv, int error); + +/** + * @brief Activate standby 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_standby_activate(ocf_cache_t cache, + struct ocf_mngt_cache_standby_activate_config *cfg, + ocf_mngt_cache_standby_activate_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 b1e2ddf..54b1996 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -584,7 +584,7 @@ static void _ocf_mngt_load_post_metadata_load(ocf_pipeline_t pipeline, ocf_pipeline_next(pipeline); } -void _ocf_mngt_load_init_instance_complete(void *priv, int error) +void _ocf_mngt_load_metadata_complete(void *priv, int error) { struct ocf_cache_attach_context *context = priv; ocf_cache_t cache = context->cache; @@ -601,43 +601,44 @@ void _ocf_mngt_load_init_instance_complete(void *priv, int error) /** * handle load variant */ -static void _ocf_mngt_load_init_instance_clean_load( - struct ocf_cache_attach_context *context) +static void _ocf_mngt_load_metadata_clean(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_metadata_load_all(cache, - _ocf_mngt_load_init_instance_complete, context); + _ocf_mngt_load_metadata_complete, context); } /** * handle recovery variant */ -static void _ocf_mngt_load_init_instance_recovery( - struct ocf_cache_attach_context *context) +static void _ocf_mngt_load_metadata_recovery(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, true); - - ocf_cache_log(cache, log_info, "Initiating recovery sequence...\n"); - ocf_metadata_load_recovery(cache, - _ocf_mngt_load_init_instance_complete, context); + _ocf_mngt_load_metadata_complete, context); } -static void _ocf_mngt_load_init_instance(ocf_pipeline_t pipeline, +static void _ocf_mngt_load_metadata(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { struct ocf_cache_attach_context *context = priv; ocf_cache_t cache = context->cache; if (context->metadata.shutdown_status == ocf_metadata_clean_shutdown) { - _ocf_mngt_load_init_instance_clean_load(context); + _ocf_mngt_load_metadata_clean(pipeline, priv, arg); } else { ocf_cache_log(cache, log_warn, "ERROR: Cache device did not shut down properly!\n"); - _ocf_mngt_load_init_instance_recovery(context); + init_attached_data_structures_recovery(cache, true); + + ocf_cache_log(cache, log_info, "Initiating recovery sequence...\n"); + _ocf_mngt_load_metadata_recovery(pipeline, priv, arg); } } @@ -1722,7 +1723,7 @@ struct ocf_pipeline_properties _ocf_mngt_cache_load_pipeline_properties = { OCF_PL_STEP(_ocf_mngt_init_cleaner), OCF_PL_STEP(_ocf_mngt_init_promotion), OCF_PL_STEP(_ocf_mngt_load_add_cores), - OCF_PL_STEP(_ocf_mngt_load_init_instance), + OCF_PL_STEP(_ocf_mngt_load_metadata), OCF_PL_STEP(_ocf_mngt_load_post_metadata_load), OCF_PL_STEP(_ocf_mngt_attach_flush_metadata), OCF_PL_STEP(_ocf_mngt_attach_shutdown_status), @@ -2026,21 +2027,6 @@ static void _ocf_mngt_init_cache_front_volume(ocf_pipeline_t pipeline, 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_standby_init_properties(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { @@ -2057,17 +2043,6 @@ static void _ocf_mngt_standby_init_properties(ocf_pipeline_t pipeline, ocf_pipeline_next(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_preapre_mempool(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { @@ -2082,15 +2057,36 @@ static void _ocf_mngt_bind_preapre_mempool(ocf_pipeline_t pipeline, OCF_PL_NEXT_ON_SUCCESS_RET(context->pipeline, result); } -static void _ocf_mngt_bind_init_attached_structures(ocf_pipeline_t pipeline, +static void _ocf_mngt_bind_init_structures_attach(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, true); + __populate_free_safe(cache); + + ocf_pipeline_next(pipeline); +} + +static void _ocf_mngt_bind_init_structures_load(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, false); + + ocf_pipeline_next(pipeline); +} + +static void _ocf_mngt_bind_init_pio_concurrency(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { struct ocf_cache_attach_context *context = priv; ocf_cache_t cache = context->cache; int result; - init_attached_data_structures_recovery(cache, false); - result = ocf_pio_concurrency_init(&cache->standby.concurrency, cache); if (!result) context->flags.pio_concurrency = true; @@ -2137,7 +2133,33 @@ static void _ocf_mngt_bind_post_init(ocf_pipeline_t pipeline, ocf_pipeline_next(pipeline); } -struct ocf_pipeline_properties _ocf_mngt_cache_standby_pipeline_properties = { +struct ocf_pipeline_properties _ocf_mngt_cache_standby_attach_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_attach_read_properties), + OCF_PL_STEP(_ocf_mngt_standby_init_properties), + OCF_PL_STEP(_ocf_mngt_init_cache_front_volume), + OCF_PL_STEP(_ocf_mngt_attach_check_ram), + OCF_PL_STEP(_ocf_mngt_attach_prepare_metadata), + OCF_PL_STEP(_ocf_mngt_test_volume), + OCF_PL_STEP(_ocf_mngt_init_cleaner), + OCF_PL_STEP(_ocf_mngt_bind_init_structures_attach), + OCF_PL_STEP(_ocf_mngt_bind_init_cleaning), + OCF_PL_STEP(_ocf_mngt_bind_preapre_mempool), + OCF_PL_STEP(_ocf_mngt_bind_init_pio_concurrency), + OCF_PL_STEP(_ocf_mngt_attach_flush_metadata), + OCF_PL_STEP(_ocf_mngt_attach_discard), + OCF_PL_STEP(_ocf_mngt_attach_flush), + OCF_PL_STEP(_ocf_mngt_bind_post_init), + OCF_PL_STEP_TERMINATOR(), + }, +}; + +struct ocf_pipeline_properties _ocf_mngt_cache_standby_load_pipeline_properties = { .priv_size = sizeof(struct ocf_cache_attach_context), .finish = _ocf_mngt_cache_attach_finish, .steps = { @@ -2149,40 +2171,42 @@ struct ocf_pipeline_properties _ocf_mngt_cache_standby_pipeline_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_preapre_mempool), - OCF_PL_STEP(_ocf_mngt_bind_init_attached_structures), - OCF_PL_STEP(_ocf_mngt_bind_recovery_unsafe), + OCF_PL_STEP(_ocf_mngt_load_superblock), + OCF_PL_STEP(_ocf_mngt_load_metadata_recovery), OCF_PL_STEP(_ocf_mngt_init_cleaner), + OCF_PL_STEP(_ocf_mngt_bind_init_structures_load), OCF_PL_STEP(_ocf_mngt_bind_init_cleaning), + OCF_PL_STEP(_ocf_mngt_bind_preapre_mempool), + OCF_PL_STEP(_ocf_mngt_bind_init_pio_concurrency), + OCF_PL_STEP(_ocf_mngt_bind_recovery_unsafe), OCF_PL_STEP(_ocf_mngt_bind_post_init), OCF_PL_STEP_TERMINATOR(), }, }; -struct ocf_cache_failover_detach_context { +struct ocf_cache_standby_detach_context { ocf_pipeline_t pipeline; ocf_cache_t cache; - ocf_mngt_cache_failover_detach_end_t cmpl; + ocf_mngt_cache_standby_detach_end_t cmpl; void *priv; }; -static void _ocf_mngt_failover_detach_wait_metadata_io_finish(void *priv) +static void _ocf_mngt_standby_detach_wait_metadata_io_finish(void *priv) { - struct ocf_cache_failover_detach_context *context = priv; + struct ocf_cache_standby_detach_context *context = priv; ocf_pipeline_next(context->pipeline); } -static void _ocf_mngt_failover_detach_wait_metadata_io(ocf_pipeline_t pipeline, +static void _ocf_mngt_standby_detach_wait_metadata_io(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { - struct ocf_cache_failover_detach_context *context = priv; + struct ocf_cache_standby_detach_context *context = priv; ocf_cache_t cache = context->cache; ocf_refcnt_freeze(&cache->refcnt.metadata); ocf_refcnt_register_zero_cb(&cache->refcnt.metadata, - _ocf_mngt_failover_detach_wait_metadata_io_finish, context); + _ocf_mngt_standby_detach_wait_metadata_io_finish, context); } static void _ocf_mngt_activate_set_cache_device(ocf_pipeline_t pipeline, @@ -2501,7 +2525,7 @@ ocf_mngt_cache_stop_standby_pipeline_properties = { }, }; -static void _ocf_mngt_cache_standby(ocf_cache_t cache, +static void _ocf_mngt_cache_standby_attach(ocf_cache_t cache, struct ocf_mngt_cache_attach_config *cfg, _ocf_mngt_cache_attach_end_t cmpl, void *priv1, void *priv2) { @@ -2510,7 +2534,7 @@ static void _ocf_mngt_cache_standby(ocf_cache_t cache, int result; result = ocf_pipeline_create(&pipeline, cache, - &_ocf_mngt_cache_standby_pipeline_properties); + &_ocf_mngt_cache_standby_attach_pipeline_properties); if (result) OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_NO_MEM); @@ -2534,10 +2558,43 @@ static void _ocf_mngt_cache_standby(ocf_cache_t cache, OCF_PL_NEXT_RET(pipeline); } -static void _ocf_mngt_failover_detach_close_volume(ocf_pipeline_t pipeline, +static void _ocf_mngt_cache_standby_load(ocf_cache_t cache, + struct ocf_mngt_cache_attach_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_standby_load_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_standby_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 void _ocf_mngt_standby_detach_close_volume(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { - struct ocf_cache_failover_detach_context *context = priv; + struct ocf_cache_standby_detach_context *context = priv; ocf_cache_t cache = context->cache; ocf_volume_close(&cache->device->volume); @@ -2546,10 +2603,10 @@ static void _ocf_mngt_failover_detach_close_volume(ocf_pipeline_t pipeline, ocf_pipeline_next(pipeline); } -static void ocf_mngt_cache_failover_detach_finish(ocf_pipeline_t pipeline, +static void ocf_mngt_cache_standby_detach_finish(ocf_pipeline_t pipeline, void *priv, int error) { - struct ocf_cache_failover_detach_context *context = priv; + struct ocf_cache_standby_detach_context *context = priv; context->cmpl(context->priv, error); @@ -2557,25 +2614,25 @@ static void ocf_mngt_cache_failover_detach_finish(ocf_pipeline_t pipeline, } struct ocf_pipeline_properties -_ocf_mngt_cache_failover_detach_pipeline_properties = { - .priv_size = sizeof(struct ocf_cache_failover_detach_context), - .finish = ocf_mngt_cache_failover_detach_finish, +_ocf_mngt_cache_standby_detach_pipeline_properties = { + .priv_size = sizeof(struct ocf_cache_standby_detach_context), + .finish = ocf_mngt_cache_standby_detach_finish, .steps = { - OCF_PL_STEP(_ocf_mngt_failover_detach_wait_metadata_io), - OCF_PL_STEP(_ocf_mngt_failover_detach_close_volume), + OCF_PL_STEP(_ocf_mngt_standby_detach_wait_metadata_io), + OCF_PL_STEP(_ocf_mngt_standby_detach_close_volume), OCF_PL_STEP_TERMINATOR(), }, }; -void _ocf_mngt_cache_failover_detach(ocf_cache_t cache, - ocf_mngt_cache_failover_detach_end_t cmpl, void *priv) +void _ocf_mngt_cache_standby_detach(ocf_cache_t cache, + ocf_mngt_cache_standby_detach_end_t cmpl, void *priv) { - struct ocf_cache_failover_detach_context *context; + struct ocf_cache_standby_detach_context *context; ocf_pipeline_t pipeline; int result; result = ocf_pipeline_create(&pipeline, cache, - &_ocf_mngt_cache_failover_detach_pipeline_properties); + &_ocf_mngt_cache_standby_detach_pipeline_properties); if (result) OCF_CMPL_RET(priv, -OCF_ERR_NO_MEM); @@ -2590,9 +2647,8 @@ void _ocf_mngt_cache_failover_detach(ocf_cache_t cache, OCF_PL_NEXT_RET(pipeline); } - -static void _ocf_mngt_cache_activate(ocf_cache_t cache, - struct ocf_mngt_cache_device_config *device_cfg, +static void _ocf_mngt_cache_standby_activate(ocf_cache_t cache, + struct ocf_mngt_cache_standby_activate_config *cfg, _ocf_mngt_cache_attach_end_t cmpl, void *priv1, void *priv2) { struct ocf_cache_attach_context *context; @@ -2603,7 +2659,7 @@ static void _ocf_mngt_cache_activate(ocf_cache_t cache, OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_CACHE_EXIST); if (!ocf_refcnt_frozen(&cache->refcnt.metadata)) - OCF_CMPL_RET(cache, priv1, priv2, OCF_ERR_FAILOVER_ATTACHED); + OCF_CMPL_RET(cache, priv1, priv2, OCF_ERR_STANDBY_ATTACHED); result = ocf_pipeline_create(&pipeline, cache, &_ocf_mngt_cache_activate_pipeline_properties); @@ -2618,13 +2674,12 @@ static void _ocf_mngt_cache_activate(ocf_cache_t cache, context->pipeline = pipeline; context->cache = cache; - context->cfg.device = *device_cfg; + context->cfg.device = cfg->device; context->cfg.cache_line_size = cache->metadata.line_size; - context->cfg.open_cores = true; + context->cfg.open_cores = cfg->open_cores; context->cfg.force = false; context->cfg.discard_on_start = false; - OCF_PL_NEXT_RET(pipeline); } @@ -2890,23 +2945,23 @@ 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_standby_complete(ocf_cache_t cache, void *priv1, - void *priv2, int error) +static void _ocf_mngt_cache_standby_attach_complete(ocf_cache_t cache, + void *priv1, void *priv2, int error) { - ocf_mngt_cache_bind_end_t cmpl = priv1; + ocf_mngt_cache_standby_attach_end_t cmpl = priv1; if (error) OCF_CMPL_RET(cache, priv2, error); _ocf_mngt_cache_set_standby(cache); - ocf_cache_log(cache, log_info, "Successfully bound\n"); + ocf_cache_log(cache, log_info, "Successfully attached standby cache\n"); OCF_CMPL_RET(cache, priv2, 0); } -void ocf_mngt_cache_standby(ocf_cache_t cache, +void ocf_mngt_cache_standby_attach(ocf_cache_t cache, struct ocf_mngt_cache_attach_config *cfg, - ocf_mngt_cache_bind_end_t cmpl, void *priv) + ocf_mngt_cache_standby_attach_end_t cmpl, void *priv) { int result; @@ -2916,14 +2971,52 @@ void ocf_mngt_cache_standby(ocf_cache_t cache, if (!cache->mngt_queue) OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); - /* Bind is not allowed in volatile metadata mode */ + /* Standby 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 */ + result = _ocf_mngt_cache_validate_attach_cfg(cfg); + if (result) + OCF_CMPL_RET(cache, priv, result); + + _ocf_mngt_cache_standby_attach(cache, cfg, + _ocf_mngt_cache_standby_attach_complete, cmpl, priv); +} + +static void _ocf_mngt_cache_standby_load_complete(ocf_cache_t cache, + void *priv1, void *priv2, int error) +{ + ocf_mngt_cache_standby_attach_end_t cmpl = priv1; + + if (error) + OCF_CMPL_RET(cache, priv2, error); + + _ocf_mngt_cache_set_standby(cache); + ocf_cache_log(cache, log_info, "Successfully loaded standby cache\n"); + + OCF_CMPL_RET(cache, priv2, 0); +} + +void ocf_mngt_cache_standby_load(ocf_cache_t cache, + struct ocf_mngt_cache_attach_config *cfg, + ocf_mngt_cache_standby_load_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); + + /* Standby is not allowed in volatile metadata mode */ + if (cache->metadata.is_volatile) + OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); + + /* Standby load is not allowed with 'force' flag on */ if (cfg->force) { ocf_cache_log(cache, log_err, "Using 'force' flag is forbidden " - "for bind operation."); + "for standby load operation."); OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); } @@ -2931,14 +3024,31 @@ void ocf_mngt_cache_standby(ocf_cache_t cache, if (result) OCF_CMPL_RET(cache, priv, result); - _ocf_mngt_cache_standby(cache, cfg, _ocf_mngt_cache_standby_complete, - cmpl, priv); + _ocf_mngt_cache_standby_load(cache, cfg, + _ocf_mngt_cache_standby_load_complete, cmpl, priv); } -static void _ocf_mngt_cache_activate_complete(ocf_cache_t cache, void *priv1, - void *priv2, int error) +void ocf_mngt_cache_standby_detach(ocf_cache_t cache, + ocf_mngt_cache_standby_detach_end_t cmpl, void *priv) { - ocf_mngt_cache_activate_end_t cmpl = priv1; + OCF_CHECK_NULL(cache); + + if (!cache->mngt_queue) + OCF_CMPL_RET(priv, -OCF_ERR_INVAL); + + if (!ocf_cache_is_standby(cache)) + OCF_CMPL_RET(priv, -OCF_ERR_CACHE_EXIST); + + if (ocf_refcnt_frozen(&cache->refcnt.metadata)) + OCF_CMPL_RET(priv, -OCF_ERR_INVAL); + + _ocf_mngt_cache_standby_detach(cache, cmpl, priv); +} + +static void _ocf_mngt_cache_standby_activate_complete(ocf_cache_t cache, + void *priv1, void *priv2, int error) +{ + ocf_mngt_cache_standby_activate_end_t cmpl = priv1; if (error) OCF_CMPL_RET(cache, priv2, error); @@ -2952,26 +3062,9 @@ static void _ocf_mngt_cache_activate_complete(ocf_cache_t cache, void *priv1, OCF_CMPL_RET(cache, priv2, 0); } -void ocf_mngt_cache_failover_detach(ocf_cache_t cache, - ocf_mngt_cache_failover_detach_end_t cmpl, void *priv) -{ - OCF_CHECK_NULL(cache); - - if (!cache->mngt_queue) - OCF_CMPL_RET(priv, -OCF_ERR_INVAL); - - if (!ocf_cache_is_standby(cache)) - OCF_CMPL_RET(priv, -OCF_ERR_CACHE_EXIST); - - if (ocf_refcnt_frozen(&cache->refcnt.metadata)) - OCF_CMPL_RET(priv, -OCF_ERR_INVAL); - - _ocf_mngt_cache_failover_detach(cache, cmpl, priv); -} - -void ocf_mngt_cache_activate(ocf_cache_t cache, - struct ocf_mngt_cache_device_config *cfg, - ocf_mngt_cache_activate_end_t cmpl, void *priv) +void ocf_mngt_cache_standby_activate(ocf_cache_t cache, + struct ocf_mngt_cache_standby_activate_config *cfg, + ocf_mngt_cache_standby_activate_end_t cmpl, void *priv) { OCF_CHECK_NULL(cache); OCF_CHECK_NULL(cfg); @@ -2979,10 +3072,11 @@ void ocf_mngt_cache_activate(ocf_cache_t cache, if (!cache->mngt_queue) OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); - if (_ocf_mngt_cache_validate_device_cfg(cfg)) + if (_ocf_mngt_cache_validate_device_cfg(&cfg->device)) OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); - _ocf_mngt_cache_activate(cache, cfg, _ocf_mngt_cache_activate_complete, + _ocf_mngt_cache_standby_activate(cache, cfg, + _ocf_mngt_cache_standby_activate_complete, cmpl, priv); } diff --git a/src/ocf_cache.c b/src/ocf_cache.c index 1a5d203..c784016 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -108,9 +108,9 @@ int ocf_cache_get_info(ocf_cache_t cache, struct ocf_cache_info *info) _ocf_stats_zero(&info->inactive); info->attached = ocf_cache_is_device_attached(cache); - info->failover_detached = ocf_cache_is_standby(cache) && + info->standby_detached = ocf_cache_is_standby(cache) && ocf_refcnt_frozen(&cache->refcnt.metadata); - if (info->attached && !info->failover_detached) { + if (info->attached && !info->standby_detached) { info->volume_type = ocf_ctx_get_volume_type_id(cache->owner, cache->device->volume.type); info->size = cache->conf_meta->cachelines; diff --git a/tests/functional/pyocf/types/shared.py b/tests/functional/pyocf/types/shared.py index 08da467..8c2c274 100644 --- a/tests/functional/pyocf/types/shared.py +++ b/tests/functional/pyocf/types/shared.py @@ -53,7 +53,7 @@ class OcfErrorCode(IntEnum): OCF_ERR_METADATA_LAYOUT_MISMATCH = auto() OCF_ERR_CACHE_LINE_SIZE_MISMATCH = auto() OCF_ERR_CACHE_STANDBY = auto() - OCF_ERR_FAILOVER_ATTACHED = auto() + OCF_ERR_STANDBY_ATTACHED = auto() class OcfCompletion: