From 387cf1b9a54ff8cb19ae29793c3e05f713111194 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Wed, 1 Sep 2021 23:31:55 +0200 Subject: [PATCH 01/26] Fix debug tracing in metadata Signed-off-by: Robert Baldyga --- src/metadata/metadata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index ff6452e..911a7aa 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1772,7 +1772,7 @@ void ocf_metadata_load_properties(ocf_volume_t volume, { int result; - OCF_DEBUG_TRACE(cache); + OCF_DEBUG_TRACE(volume->cache); result = ocf_metadata_read_sb(volume->cache->owner, volume, ocf_metadata_load_properties_cmpl, cmpl, priv); From 82abcd11e78fbbc2cc6751b3cb258b13c7107861 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Wed, 1 Sep 2021 23:35:24 +0200 Subject: [PATCH 02/26] Fix documentation of ocf_metadata_raw_rd_access() Signed-off-by: Robert Baldyga --- src/metadata/metadata_raw.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/metadata/metadata_raw.h b/src/metadata/metadata_raw.h index 0357774..b595d7a 100644 --- a/src/metadata/metadata_raw.h +++ b/src/metadata/metadata_raw.h @@ -234,7 +234,6 @@ static inline void *ocf_metadata_raw_wr_access(ocf_cache_t cache, * @param cache - Cache instance * @param raw - RAW descriptor * @param entry - Entry to be get - * @param data - Data where metadata entry will be copied into * @return 0 - Point to accessed data, in case of error NULL */ static inline const void *ocf_metadata_raw_rd_access( ocf_cache_t cache, From 8015a30348244c4cdb64c72aa89ac68b065dab45 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 31 Aug 2021 10:20:20 +0200 Subject: [PATCH 03/26] Fix documentation of ocf_cache_is_running() Signed-off-by: Robert Baldyga --- inc/ocf_cache.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/ocf_cache.h b/inc/ocf_cache.h index 197abad..24f17c7 100644 --- a/inc/ocf_cache.h +++ b/inc/ocf_cache.h @@ -137,8 +137,8 @@ bool ocf_cache_is_device_attached(ocf_cache_t cache); * * @param[in] cache Cache object * - * @retval 1 Caching device is being stopped - * @retval 0 Caching device is being stopped + * @retval 1 Caching device is running + * @retval 0 Caching device is not running */ bool ocf_cache_is_running(ocf_cache_t cache); From ab034ab53dace62705efc98e13354009530732e7 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 3 Sep 2021 17:21:50 +0200 Subject: [PATCH 04/26] Fix uuid comparison in core pool Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_core_pool.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/mngt/ocf_mngt_core_pool.c b/src/mngt/ocf_mngt_core_pool.c index 959a71b..7a8ce9b 100644 --- a/src/mngt/ocf_mngt_core_pool.c +++ b/src/mngt/ocf_mngt_core_pool.c @@ -74,6 +74,8 @@ ocf_volume_t ocf_mngt_core_pool_lookup(ocf_ctx_t ctx, ocf_uuid_t uuid, ocf_volume_type_t type) { ocf_volume_t svolume; + int result; + int cmp; OCF_CHECK_NULL(ctx); OCF_CHECK_NULL(uuid); @@ -81,10 +83,15 @@ ocf_volume_t ocf_mngt_core_pool_lookup(ocf_ctx_t ctx, ocf_uuid_t uuid, list_for_each_entry(svolume, &ctx->core_pool.core_pool_head, core_pool_item) { - if (svolume->type == type && !env_strncmp(svolume->uuid.data, - svolume->uuid.size, uuid->data, uuid->size)) { - return svolume; - } + if (svolume->type != type) + continue; + + result = env_memcmp(svolume->uuid.data, svolume->uuid.size, + uuid->data, uuid->size, &cmp); + if (result || cmp) + continue; + + return svolume; } return NULL; From 9ab4c51dfaf2ca8e6f1efb127a7f5e09172de907 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 30 Aug 2021 14:58:57 +0200 Subject: [PATCH 05/26] Expose superblock operations as part of internal metadata API Signed-off-by: Robert Baldyga --- src/metadata/metadata.c | 134 +---------------------- src/metadata/metadata_superblock.c | 168 +++++++++++++++++++++++++++++ src/metadata/metadata_superblock.h | 23 ++++ 3 files changed, 195 insertions(+), 130 deletions(-) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 911a7aa..ab33ee7 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1617,102 +1617,6 @@ void ocf_metadata_error(struct ocf_cache *cache) cache->device->metadata_error = -1; } -struct ocf_metadata_read_sb_ctx; - -typedef void (*ocf_metadata_read_sb_end_t)( - struct ocf_metadata_read_sb_ctx *context); - -struct ocf_metadata_read_sb_ctx { - struct ocf_superblock_config superblock; - ocf_metadata_read_sb_end_t cmpl; - ocf_ctx_t ctx; - void *priv1; - void *priv2; - int error; -}; - -static void ocf_metadata_read_sb_complete(struct ocf_io *io, int error) -{ - struct ocf_metadata_read_sb_ctx *context = io->priv1; - ctx_data_t *data = ocf_io_get_data(io); - - if (!error) { - /* Read data from data into super block buffer */ - ctx_data_rd_check(context->ctx, &context->superblock, data, - sizeof(context->superblock)); - } - - ctx_data_free(context->ctx, data); - ocf_io_put(io); - - context->error = error; - context->cmpl(context); - - env_free(context); -} - -static int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume, - ocf_metadata_read_sb_end_t cmpl, void *priv1, void *priv2) -{ - struct ocf_metadata_read_sb_ctx *context; - size_t sb_pages = BYTES_TO_PAGES(sizeof(context->superblock)); - ctx_data_t *data; - struct ocf_io *io; - int result = 0; - - /* Allocate memory for first page of super block */ - context = env_zalloc(sizeof(*context), ENV_MEM_NORMAL); - if (!context) { - ocf_log(ctx, log_err, "Memory allocation error"); - return -OCF_ERR_NO_MEM; - } - - context->cmpl = cmpl; - context->ctx = ctx; - context->priv1 = priv1; - context->priv2 = priv2; - - /* Allocate resources for IO */ - io = ocf_volume_new_io(volume, NULL, 0, sb_pages * PAGE_SIZE, - OCF_READ, 0, 0); - if (!io) { - ocf_log(ctx, log_err, "Memory allocation error"); - result = -OCF_ERR_NO_MEM; - goto err_io; - } - - data = ctx_data_alloc(ctx, sb_pages); - if (!data) { - ocf_log(ctx, log_err, "Memory allocation error"); - result = -OCF_ERR_NO_MEM; - goto err_data; - } - - /* - * Read first page of cache device in order to recover metadata - * properties - */ - result = ocf_io_set_data(io, data, 0); - if (result) { - ocf_log(ctx, log_err, "Metadata IO configuration error\n"); - result = -OCF_ERR_IO; - goto err_set_data; - } - - ocf_io_set_cmpl(io, context, NULL, ocf_metadata_read_sb_complete); - ocf_volume_submit_io(io); - - return 0; - -err_set_data: - ctx_data_free(ctx, data); -err_data: - ocf_io_put(io); -err_io: - env_free(context); - return result; -} - static void ocf_metadata_load_properties_cmpl( struct ocf_metadata_read_sb_ctx *context) { @@ -1721,41 +1625,11 @@ static void ocf_metadata_load_properties_cmpl( ocf_metadata_load_properties_end_t cmpl = context->priv1; void *priv = context->priv2; ocf_ctx_t ctx = context->ctx; + int result; - if (superblock->magic_number != CACHE_MAGIC_NUMBER) { - ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n"); - OCF_CMPL_RET(priv, -OCF_ERR_NO_METADATA, NULL); - } - - if (METADATA_VERSION() != superblock->metadata_version) { - ocf_log(ctx, log_err, "Metadata version mismatch!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_METADATA_VER, NULL); - } - - if (!ocf_cache_line_size_is_valid(superblock->line_size)) { - ocf_log(ctx, log_err, "ERROR: Invalid cache line size!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } - - if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) { - ocf_log(ctx, log_err, "ERROR: Invalid metadata layout!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } - - if (superblock->cache_mode >= ocf_cache_mode_max) { - ocf_log(ctx, log_err, "ERROR: Invalid cache mode!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } - - if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) { - ocf_log(ctx, log_err, "ERROR: Invalid shutdown status!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } - - if (superblock->dirty_flushed > DIRTY_FLUSHED) { - ocf_log(ctx, log_err, "ERROR: Invalid flush status!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } + result = ocf_metadata_validate_superblock(ctx, superblock); + if (result) + OCF_CMPL_RET(priv, result, NULL); properties.line_size = superblock->line_size; properties.layout = superblock->metadata_layout; diff --git a/src/metadata/metadata_superblock.c b/src/metadata/metadata_superblock.c index 00ebb5b..f0f5a14 100644 --- a/src/metadata/metadata_superblock.c +++ b/src/metadata/metadata_superblock.c @@ -10,6 +10,7 @@ #include "metadata_superblock.h" #include "../ocf_priv.h" #include "../utils/utils_io.h" +#include "../utils/utils_cache_line.h" #define OCF_METADATA_SUPERBLOCK_DEBUG 0 @@ -503,3 +504,170 @@ bool ocf_metadata_superblock_get_clean_shutdown( return sb->config->clean_shutdown; } +int ocf_metadata_validate_superblock(ocf_ctx_t ctx, + struct ocf_superblock_config *superblock) +{ + if (superblock->magic_number != CACHE_MAGIC_NUMBER) { + ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n"); + return -OCF_ERR_NO_METADATA; + } + + if (METADATA_VERSION() != superblock->metadata_version) { + ocf_log(ctx, log_err, "Metadata version mismatch!\n"); + return -OCF_ERR_METADATA_VER; + } + + if (!ocf_cache_line_size_is_valid(superblock->line_size)) { + ocf_log(ctx, log_err, "ERROR: Invalid cache line size!\n"); + return -OCF_ERR_INVAL; + } + + if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) { + ocf_log(ctx, log_err, "ERROR: Invalid metadata layout!\n"); + return -OCF_ERR_INVAL; + } + + if (superblock->cache_mode >= ocf_cache_mode_max) { + ocf_log(ctx, log_err, "ERROR: Invalid cache mode!\n"); + return -OCF_ERR_INVAL; + } + + if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) { + ocf_log(ctx, log_err, "ERROR: Invalid shutdown status!\n"); + return -OCF_ERR_INVAL; + } + + if (superblock->dirty_flushed > DIRTY_FLUSHED) { + ocf_log(ctx, log_err, "ERROR: Invalid flush status!\n"); + return -OCF_ERR_INVAL; + } + + return 0; +} + +static void ocf_metadata_read_sb_complete(struct ocf_io *io, int error) +{ + struct ocf_metadata_read_sb_ctx *context = io->priv1; + ctx_data_t *data = ocf_io_get_data(io); + + if (!error) { + /* Read data from data into super block buffer */ + ctx_data_rd_check(context->ctx, &context->superblock, data, + sizeof(context->superblock)); + } + + ctx_data_free(context->ctx, data); + ocf_io_put(io); + + context->error = error; + context->cmpl(context); + + env_free(context); +} + +int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume, + ocf_metadata_read_sb_end_t cmpl, void *priv1, void *priv2) +{ + struct ocf_metadata_read_sb_ctx *context; + size_t sb_pages = BYTES_TO_PAGES(sizeof(context->superblock)); + ctx_data_t *data; + struct ocf_io *io; + int result = 0; + + /* Allocate memory for first page of super block */ + context = env_zalloc(sizeof(*context), ENV_MEM_NORMAL); + if (!context) { + ocf_log(ctx, log_err, "Memory allocation error"); + return -OCF_ERR_NO_MEM; + } + + context->cmpl = cmpl; + context->ctx = ctx; + context->priv1 = priv1; + context->priv2 = priv2; + + /* Allocate resources for IO */ + io = ocf_volume_new_io(volume, NULL, 0, sb_pages * PAGE_SIZE, + OCF_READ, 0, 0); + if (!io) { + ocf_log(ctx, log_err, "Memory allocation error"); + result = -OCF_ERR_NO_MEM; + goto err_io; + } + + data = ctx_data_alloc(ctx, sb_pages); + if (!data) { + ocf_log(ctx, log_err, "Memory allocation error"); + result = -OCF_ERR_NO_MEM; + goto err_data; + } + + /* + * Read first page of cache device in order to recover metadata + * properties + */ + result = ocf_io_set_data(io, data, 0); + if (result) { + ocf_log(ctx, log_err, "Metadata IO configuration error\n"); + result = -OCF_ERR_IO; + goto err_set_data; + } + + ocf_io_set_cmpl(io, context, NULL, ocf_metadata_read_sb_complete); + ocf_volume_submit_io(io); + + return 0; + +err_set_data: + ctx_data_free(ctx, data); +err_data: + ocf_io_put(io); +err_io: + env_free(context); + return result; +} + +static void ocf_metadata_sb_crc_recovery_finish(ocf_pipeline_t pipeline, + void *priv, int error) +{ + struct ocf_metadata_context *context = priv; + + context->cmpl(context->priv, error); + ocf_pipeline_destroy(pipeline); +} + +struct ocf_pipeline_properties ocf_metadata_sb_crc_recovery_pipeline_props = { + .priv_size = sizeof(struct ocf_metadata_context), + .finish = ocf_metadata_sb_crc_recovery_finish, + .steps = { + OCF_PL_STEP(ocf_metadata_check_crc_sb_config), + OCF_PL_STEP_FOREACH(ocf_metadata_check_crc, + ocf_metadata_load_sb_check_crc_args), + OCF_PL_STEP_TERMINATOR(), + }, +}; + +void ocf_metadata_sb_crc_recovery(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *priv) +{ + struct ocf_metadata_context *context; + ocf_pipeline_t pipeline; + int result; + + OCF_DEBUG_TRACE(cache); + + result = ocf_pipeline_create(&pipeline, cache, + &ocf_metadata_sb_crc_recovery_pipeline_props); + if (result) + OCF_CMPL_RET(priv, result); + + context = ocf_pipeline_get_priv(pipeline); + + context->cmpl = cmpl; + context->priv = priv; + context->pipeline = pipeline; + context->cache = cache; + context->ctrl = cache->metadata.priv; + + ocf_pipeline_next(pipeline); +} diff --git a/src/metadata/metadata_superblock.h b/src/metadata/metadata_superblock.h index 4602b3b..290bb24 100644 --- a/src/metadata/metadata_superblock.h +++ b/src/metadata/metadata_superblock.h @@ -97,4 +97,27 @@ void ocf_metadata_superblock_set_checksum( bool ocf_metadata_superblock_get_clean_shutdown( struct ocf_metadata_segment *self); +int ocf_metadata_validate_superblock(ocf_ctx_t ctx, + struct ocf_superblock_config *superblock); + +struct ocf_metadata_read_sb_ctx; + +typedef void (*ocf_metadata_read_sb_end_t)( + struct ocf_metadata_read_sb_ctx *context); + +struct ocf_metadata_read_sb_ctx { + struct ocf_superblock_config superblock; + ocf_metadata_read_sb_end_t cmpl; + ocf_ctx_t ctx; + void *priv1; + void *priv2; + int error; +}; + +int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume, + ocf_metadata_read_sb_end_t cmpl, void *priv1, void *priv2); + +void ocf_metadata_sb_crc_recovery(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *priv); + #endif /* METADATA_SUPERBLOCK_H_ */ From 1f6b83f87d05e4dcbc527daac32c517786b6c126 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 31 Aug 2021 10:23:31 +0200 Subject: [PATCH 06/26] Decouple cache attached state from metadata refcount state Signed-off-by: Robert Baldyga --- src/ocf_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ocf_cache.c b/src/ocf_cache.c index cc29a49..26a0865 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -47,7 +47,7 @@ bool ocf_cache_is_running(ocf_cache_t cache) bool ocf_cache_is_device_attached(ocf_cache_t cache) { OCF_CHECK_NULL(cache); - return !ocf_refcnt_frozen(&cache->refcnt.metadata); + return !!cache->device; } ocf_cache_mode_t ocf_cache_get_mode(ocf_cache_t cache) From 20228561c9b8bf3ce90b5c0bb48205a01dfd4572 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 31 Aug 2021 11:31:33 +0200 Subject: [PATCH 07/26] Move metadata deinit to separate pipeline step Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_cache.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 54a2a67..1c31932 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -1689,6 +1689,29 @@ static void _ocf_mngt_cache_put_io_queues(ocf_cache_t cache) ocf_queue_put(queue); } +static void ocf_mngt_cache_stop_deinit_metadata(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_mngt_cache_stop_context *context = priv; + ocf_cache_t cache = context->cache; + + ocf_volume_close(&cache->device->volume); + + ocf_metadata_deinit_variable_size(cache); + ocf_concurrency_deinit(cache); + + ocf_volume_deinit(&cache->device->volume); + + env_vfree(cache->device); + cache->device = NULL; + + /* TODO: this should be removed from detach after 'attached' stats + are better separated in statistics */ + env_atomic_set(&cache->fallback_pt_error_counter, 0); + + ocf_pipeline_next(pipeline); +} + static void ocf_mngt_cache_stop_put_io_queues(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { @@ -1777,6 +1800,7 @@ struct ocf_pipeline_properties ocf_mngt_cache_stop_pipeline_properties = { OCF_PL_STEP(ocf_mngt_cache_stop_check_dirty), OCF_PL_STEP(ocf_mngt_cache_stop_remove_cores), OCF_PL_STEP(ocf_mngt_cache_stop_unplug), + OCF_PL_STEP(ocf_mngt_cache_stop_deinit_metadata), OCF_PL_STEP(ocf_mngt_cache_stop_put_io_queues), OCF_PL_STEP_TERMINATOR(), }, @@ -1985,21 +2009,6 @@ void ocf_mngt_cache_attach(ocf_cache_t cache, static void _ocf_mngt_cache_unplug_complete(void *priv, int error) { struct _ocf_mngt_cache_unplug_context *context = priv; - ocf_cache_t cache = context->cache; - - ocf_volume_close(&cache->device->volume); - - ocf_metadata_deinit_variable_size(cache); - ocf_concurrency_deinit(cache); - - ocf_volume_deinit(&cache->device->volume); - - env_vfree(cache->device); - cache->device = NULL; - - /* TODO: this should be removed from detach after 'attached' stats - are better separated in statistics */ - env_atomic_set(&cache->fallback_pt_error_counter, 0); context->cmpl(context->priv, error ? -OCF_ERR_WRITE_CACHE : 0); } From 24728330fcc44b5df25bf545ec6ac0c7a8bf118a Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 27 Aug 2021 13:19:11 +0200 Subject: [PATCH 08/26] Make _ocf_mngt_load_add_cores a separate step in pipeline Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_cache.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 1c31932..161ec0a 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -344,9 +344,10 @@ static void _ocf_mngt_close_all_uninitialized_cores( * @brief routine loading metadata from cache device * - attempts to open all the underlying cores */ -static int _ocf_mngt_load_add_cores( - struct ocf_cache_attach_context *context) +static void _ocf_mngt_load_add_cores(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_core_t core; ocf_core_id_t core_id; @@ -438,12 +439,12 @@ static int _ocf_mngt_load_add_cores( } context->flags.cores_opened = true; - return 0; + OCF_PL_NEXT_RET(context->pipeline); err: _ocf_mngt_close_all_uninitialized_cores(cache); - return -OCF_ERR_START_CACHE_FAIL; + OCF_PL_FINISH_RET(pipeline, -OCF_ERR_START_CACHE_FAIL); } void _ocf_mngt_load_init_instance_complete(void *priv, int error) @@ -513,14 +514,6 @@ static void _ocf_mngt_load_init_instance(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 ret; - - OCF_ASSERT_PLUGGED(cache); - - ret = _ocf_mngt_load_add_cores(context); - if (ret) - OCF_PL_FINISH_RET(pipeline, ret); if (context->metadata.shutdown_status == ocf_metadata_clean_shutdown) _ocf_mngt_load_init_instance_clean_load(context); @@ -1554,6 +1547,7 @@ struct ocf_pipeline_properties _ocf_mngt_cache_load_pipeline_properties = { OCF_PL_STEP(_ocf_mngt_load_superblock), 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_attach_flush_metadata), OCF_PL_STEP(_ocf_mngt_attach_shutdown_status), From a2db4d14e887b00f26ea11be8cc5206201323a7e Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 27 Aug 2021 13:19:58 +0200 Subject: [PATCH 09/26] Move core initialization code from metadata to mngt Signed-off-by: Robert Baldyga --- src/metadata/metadata_superblock.c | 20 -------------------- src/mngt/ocf_mngt_cache.c | 14 +++++++++++++- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/metadata/metadata_superblock.c b/src/metadata/metadata_superblock.c index f0f5a14..76f9095 100644 --- a/src/metadata/metadata_superblock.c +++ b/src/metadata/metadata_superblock.c @@ -132,30 +132,10 @@ static void ocf_metadata_load_superblock_post(ocf_pipeline_t pipeline, struct ocf_metadata_ctrl *ctrl; struct ocf_superblock_config *sb_config; ocf_cache_t cache = context->cache; - struct ocf_metadata_uuid *muuid; - struct ocf_volume_uuid uuid; - ocf_volume_type_t volume_type; - ocf_core_t core; - ocf_core_id_t core_id; ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); - for_each_core_metadata(cache, core, core_id) { - muuid = ocf_metadata_get_core_uuid(cache, core_id); - uuid.data = muuid->data; - uuid.size = muuid->size; - - volume_type = ocf_ctx_get_volume_type(cache->owner, - core->conf_meta->type); - - /* Initialize core volume */ - ocf_volume_init(&core->volume, volume_type, &uuid, false); - core->has_volume = true; - } - - /* Restore all dynamics items */ - if (sb_config->core_count > OCF_CORE_MAX) { ocf_cache_log(cache, log_err, "Loading cache state ERROR, invalid cores count\n"); diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 161ec0a..da6edbe 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -362,10 +362,22 @@ static void _ocf_mngt_load_add_cores(ocf_pipeline_t pipeline, /* Check in metadata which cores were saved in cache metadata */ for_each_core_metadata(cache, core, core_id) { + struct ocf_metadata_uuid *muuid; + struct ocf_volume_uuid uuid; + ocf_volume_type_t volume_type; ocf_volume_t tvolume = NULL; - if (!core->volume.type) + muuid = ocf_metadata_get_core_uuid(cache, core_id); + uuid.data = muuid->data; + uuid.size = muuid->size; + + volume_type = ocf_ctx_get_volume_type(cache->owner, + core->conf_meta->type); + + ret = ocf_volume_init(&core->volume, volume_type, &uuid, false); + if (ret) goto err; + core->has_volume = true; tvolume = ocf_mngt_core_pool_lookup(ocf_cache_get_ctx(cache), &core->volume.uuid, core->volume.type); From c6c6618ad82942eeadf0390e92ccc6d2fb061f88 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 2 Sep 2021 21:47:55 +0200 Subject: [PATCH 10/26] Move recovery code from metadata to cache mngt Signed-off-by: Robert Baldyga --- src/metadata/metadata.c | 102 -------------------------------------- src/mngt/ocf_mngt_cache.c | 98 +++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 103 deletions(-) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index ab33ee7..0afae41 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1146,106 +1146,6 @@ void ocf_metadata_load_all(ocf_cache_t cache, ocf_pipeline_next(pipeline); } -static void _recovery_rebuild_cline_metadata(ocf_cache_t cache, - ocf_core_id_t core_id, uint64_t core_line, - ocf_cache_line_t cache_line) -{ - ocf_core_t core = ocf_cache_get_core(cache, core_id); - ocf_part_id_t part_id; - ocf_cache_line_t hash_index; - struct ocf_part_runtime *part; - - part_id = PARTITION_DEFAULT; - part = cache->user_parts[part_id].part.runtime; - - ocf_metadata_set_partition_id(cache, cache_line, part_id); - env_atomic_inc(&part->curr_size); - - hash_index = ocf_metadata_hash_func(cache, core_line, core_id); - ocf_metadata_add_to_collision(cache, core_id, core_line, hash_index, - cache_line); - - ocf_lru_init_cline(cache, cache_line); - - ocf_lru_add(cache, cache_line); - - env_atomic_inc(&core->runtime_meta->cached_clines); - env_atomic_inc(&core->runtime_meta-> - part_counters[part_id].cached_clines); - - if (metadata_test_dirty(cache, cache_line)) { - env_atomic_inc(&core->runtime_meta->dirty_clines); - env_atomic_inc(&core->runtime_meta-> - part_counters[part_id].dirty_clines); - if (!env_atomic64_read(&core->runtime_meta->dirty_since)) - env_atomic64_cmpxchg(&core->runtime_meta->dirty_since, 0, - env_ticks_to_secs(env_get_tick_count())); - } -} - -static void _recovery_invalidate_clean_sec(struct ocf_cache *cache, - ocf_cache_line_t cline) -{ - uint8_t i; - - for (i = ocf_line_start_sector(cache); - i <= ocf_line_end_sector(cache); i++) { - if (!metadata_test_dirty_one(cache, cline, i)) { - /* Invalidate clear sectors */ - metadata_clear_valid_sec_one(cache, cline, i); - } - } -} - -static void _recovery_reset_cline_metadata(struct ocf_cache *cache, - ocf_cache_line_t cline) -{ - - ocf_metadata_set_core_info(cache, cline, OCF_CORE_MAX, ULLONG_MAX); - - metadata_clear_valid(cache, cline); - - ocf_cleaning_init_cache_block(cache, cline); -} - -static void _recovery_rebuild_metadata(ocf_pipeline_t pipeline, - void *priv, ocf_pipeline_arg_t arg) -{ - struct ocf_metadata_context *context = priv; - bool dirty_only = ocf_pipeline_arg_get_int(arg); - ocf_cache_t cache = context->cache; - ocf_cache_line_t cline; - ocf_core_id_t core_id; - uint64_t core_line; - unsigned char step = 0; - const uint64_t collision_table_entries = - ocf_metadata_collision_table_entries(cache); - - ocf_metadata_start_exclusive_access(&cache->metadata.lock); - - for (cline = 0; cline < collision_table_entries; cline++) { - ocf_metadata_get_core_info(cache, cline, &core_id, &core_line); - if (core_id != OCF_CORE_MAX && - (!dirty_only || metadata_test_dirty(cache, - cline))) { - /* Rebuild metadata for mapped cache line */ - _recovery_rebuild_cline_metadata(cache, core_id, - core_line, cline); - if (dirty_only) - _recovery_invalidate_clean_sec(cache, cline); - } else { - /* Reset metadata for not mapped or clean cache line */ - _recovery_reset_cline_metadata(cache, cline); - } - - OCF_COND_RESCHED(step, 128); - } - - ocf_metadata_end_exclusive_access(&cache->metadata.lock); - - ocf_pipeline_next(pipeline); -} - static void ocf_metadata_load_recovery_legacy_finish( ocf_pipeline_t pipeline, void *priv, int error) { @@ -1273,7 +1173,6 @@ ocf_metadata_load_recovery_legacy_pl_props = { .steps = { OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment, metadata_segment_collision), - OCF_PL_STEP_ARG_INT(_recovery_rebuild_metadata, true), OCF_PL_STEP_TERMINATOR(), }, }; @@ -1415,7 +1314,6 @@ ocf_metadata_load_recovery_atomic_pl_props = { .finish = ocf_metadata_load_recovery_atomic_finish, .steps = { OCF_PL_STEP(ocf_metadata_load_atomic_metadata), - OCF_PL_STEP_ARG_INT(_recovery_rebuild_metadata, false), OCF_PL_STEP_TERMINATOR(), }, }; diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index da6edbe..d4fdf83 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -459,6 +459,100 @@ err: OCF_PL_FINISH_RET(pipeline, -OCF_ERR_START_CACHE_FAIL); } +static void _recovery_rebuild_cline_metadata(ocf_cache_t cache, + ocf_core_id_t core_id, uint64_t core_line, + ocf_cache_line_t cache_line) +{ + ocf_core_t core = ocf_cache_get_core(cache, core_id); + ocf_part_id_t part_id; + ocf_cache_line_t hash_index; + struct ocf_part_runtime *part; + + part_id = PARTITION_DEFAULT; + part = cache->user_parts[part_id].part.runtime; + + ocf_metadata_set_partition_id(cache, cache_line, part_id); + env_atomic_inc(&part->curr_size); + + hash_index = ocf_metadata_hash_func(cache, core_line, core_id); + ocf_metadata_add_to_collision(cache, core_id, core_line, hash_index, + cache_line); + + ocf_lru_init_cline(cache, cache_line); + + ocf_lru_add(cache, cache_line); + + env_atomic_inc(&core->runtime_meta->cached_clines); + env_atomic_inc(&core->runtime_meta-> + part_counters[part_id].cached_clines); + + if (metadata_test_dirty(cache, cache_line)) { + env_atomic_inc(&core->runtime_meta->dirty_clines); + env_atomic_inc(&core->runtime_meta-> + part_counters[part_id].dirty_clines); + if (!env_atomic64_read(&core->runtime_meta->dirty_since)) + env_atomic64_cmpxchg(&core->runtime_meta->dirty_since, 0, + env_ticks_to_secs(env_get_tick_count())); + } +} + +static void _recovery_invalidate_clean_sec(struct ocf_cache *cache, + ocf_cache_line_t cline) +{ + uint8_t i; + + for (i = ocf_line_start_sector(cache); + i <= ocf_line_end_sector(cache); i++) { + if (!metadata_test_dirty_one(cache, cline, i)) { + /* Invalidate clear sectors */ + metadata_clear_valid_sec_one(cache, cline, i); + } + } +} + +static void _recovery_reset_cline_metadata(struct ocf_cache *cache, + ocf_cache_line_t cline) +{ + ocf_metadata_set_core_info(cache, cline, OCF_CORE_MAX, ULLONG_MAX); + + metadata_clear_valid(cache, cline); + + ocf_cleaning_init_cache_block(cache, cline); +} + +static void _ocf_mngt_recovery_rebuild_metadata(ocf_cache_t cache) +{ + ocf_cache_line_t cline; + ocf_core_id_t core_id; + uint64_t core_line; + unsigned char step = 0; + bool dirty_only = !ocf_volume_is_atomic(ocf_cache_get_volume(cache)); + const uint64_t collision_table_entries = + ocf_metadata_collision_table_entries(cache); + + ocf_metadata_start_exclusive_access(&cache->metadata.lock); + + for (cline = 0; cline < collision_table_entries; cline++) { + ocf_metadata_get_core_info(cache, cline, &core_id, &core_line); + if (core_id != OCF_CORE_MAX && + (!dirty_only || metadata_test_dirty(cache, + cline))) { + /* Rebuild metadata for mapped cache line */ + _recovery_rebuild_cline_metadata(cache, core_id, + core_line, cline); + if (dirty_only) + _recovery_invalidate_clean_sec(cache, cline); + } else { + /* Reset metadata for not mapped or clean cache line */ + _recovery_reset_cline_metadata(cache, cline); + } + + OCF_COND_RESCHED(step, 128); + } + + ocf_metadata_end_exclusive_access(&cache->metadata.lock); +} + void _ocf_mngt_load_init_instance_complete(void *priv, int error) { struct ocf_cache_attach_context *context = priv; @@ -472,8 +566,10 @@ void _ocf_mngt_load_init_instance_complete(void *priv, int error) OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_START_CACHE_FAIL); } - if (context->metadata.shutdown_status != ocf_metadata_clean_shutdown) + if (context->metadata.shutdown_status != ocf_metadata_clean_shutdown) { + _ocf_mngt_recovery_rebuild_metadata(cache); __populate_free(cache); + } cleaning_policy = cache->conf_meta->cleaning_policy_type; From a00ec916e251e1ee26b5006b23ea809ddffedd15 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 2 Sep 2021 22:36:50 +0200 Subject: [PATCH 11/26] Make post metadata load init a separate step in pipeline Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_cache.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index d4fdf83..6a3e65c 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -553,19 +553,14 @@ static void _ocf_mngt_recovery_rebuild_metadata(ocf_cache_t cache) ocf_metadata_end_exclusive_access(&cache->metadata.lock); } -void _ocf_mngt_load_init_instance_complete(void *priv, int error) +static void _ocf_mngt_load_post_metadata_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; ocf_cleaning_t cleaning_policy; ocf_error_t result; - if (error) { - ocf_cache_log(cache, log_err, - "Cannot read cache metadata\n"); - OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_START_CACHE_FAIL); - } - if (context->metadata.shutdown_status != ocf_metadata_clean_shutdown) { _ocf_mngt_recovery_rebuild_metadata(cache); __populate_free(cache); @@ -581,7 +576,21 @@ void _ocf_mngt_load_init_instance_complete(void *priv, int error) if (result) { ocf_cache_log(cache, log_err, "Cannot initialize cleaning policy\n"); - OCF_PL_FINISH_RET(context->pipeline, result); + OCF_PL_FINISH_RET(pipeline, result); + } + + ocf_pipeline_next(pipeline); +} + +void _ocf_mngt_load_init_instance_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, + "Cannot read cache metadata\n"); + OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_START_CACHE_FAIL); } ocf_pipeline_next(context->pipeline); @@ -1657,6 +1666,7 @@ struct ocf_pipeline_properties _ocf_mngt_cache_load_pipeline_properties = { 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_post_metadata_load), OCF_PL_STEP(_ocf_mngt_attach_flush_metadata), OCF_PL_STEP(_ocf_mngt_attach_shutdown_status), OCF_PL_STEP(_ocf_mngt_attach_post_init), From a2bef439755f4b542934475282279ad1f2875f70 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 6 Aug 2021 10:06:19 +0200 Subject: [PATCH 12/26] Add missing lock in ocf_ctx_get_volume_type_id() Signed-off-by: Robert Baldyga --- src/ocf_ctx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ocf_ctx.c b/src/ocf_ctx.c index c50cb0a..6bbb97d 100644 --- a/src/ocf_ctx.c +++ b/src/ocf_ctx.c @@ -98,12 +98,14 @@ int ocf_ctx_get_volume_type_id(ocf_ctx_t ctx, ocf_volume_type_t type) OCF_CHECK_NULL(ctx); + env_rmutex_lock(&ctx->lock); for (i = 0; i < OCF_VOLUME_TYPE_MAX; ++i) { if (ctx->volume_type[i] == type) - return i; + break; } + env_rmutex_unlock(&ctx->lock); - return -1; + return (i < OCF_VOLUME_TYPE_MAX) ? i : -1; } /* From e31e7283d938d7a1973eb34a24b3d5fe32782ef7 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 2 Sep 2021 22:00:34 +0200 Subject: [PATCH 13/26] Rework volume type management Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_core.c | 3 ++- src/mngt/ocf_mngt_core_pool.c | 7 +++++- src/ocf_core.c | 2 +- src/ocf_ctx.c | 46 +++++++++++++++++++++++++++++------ src/ocf_ctx_priv.h | 15 ++++++++++-- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/mngt/ocf_mngt_core.c b/src/mngt/ocf_mngt_core.c index 1732bc4..a818e25 100644 --- a/src/mngt/ocf_mngt_core.c +++ b/src/mngt/ocf_mngt_core.c @@ -220,7 +220,8 @@ int ocf_mngt_core_init_front_volume(ocf_core_t core) }; int ret; - type = ocf_ctx_get_volume_type(cache->owner, 0); + type = ocf_ctx_get_volume_type_internal(cache->owner, + OCF_VOLUME_TYPE_CORE); if (!type) return -OCF_ERR_INVAL; diff --git a/src/mngt/ocf_mngt_core_pool.c b/src/mngt/ocf_mngt_core_pool.c index 7a8ce9b..57b451c 100644 --- a/src/mngt/ocf_mngt_core_pool.c +++ b/src/mngt/ocf_mngt_core_pool.c @@ -27,13 +27,18 @@ int ocf_mngt_core_pool_get_count(ocf_ctx_t ctx) int ocf_mngt_core_pool_add(ocf_ctx_t ctx, ocf_uuid_t uuid, uint8_t type) { + ocf_volume_type_t volume_type; ocf_volume_t volume; int result = 0; OCF_CHECK_NULL(ctx); - result = ocf_ctx_volume_create(ctx, &volume, uuid, type); + volume_type = ocf_ctx_get_volume_type(ctx, type); + if (!volume_type) + return -OCF_ERR_INVAL; + + result = ocf_volume_create(&volume, volume_type, uuid); if (result) return result; diff --git a/src/ocf_core.c b/src/ocf_core.c index 13804cd..660c383 100644 --- a/src/ocf_core.c +++ b/src/ocf_core.c @@ -519,7 +519,7 @@ const struct ocf_volume_extended ocf_core_volume_extended = { int ocf_core_volume_type_init(ocf_ctx_t ctx) { - return ocf_ctx_register_volume_type_extended(ctx, 0, + return ocf_ctx_register_volume_type_internal(ctx, OCF_VOLUME_TYPE_CORE, &ocf_core_volume_properties, &ocf_core_volume_extended); } diff --git a/src/ocf_ctx.c b/src/ocf_ctx.c index 6bbb97d..083364b 100644 --- a/src/ocf_ctx.c +++ b/src/ocf_ctx.c @@ -10,13 +10,14 @@ #include "ocf_request.h" #include "ocf_logger_priv.h" #include "ocf_core_priv.h" +#include "ocf_cache_priv.h" #include "mngt/ocf_mngt_core_pool_priv.h" #include "metadata/metadata_io.h" /* * */ -int ocf_ctx_register_volume_type_extended(ocf_ctx_t ctx, uint8_t type_id, +int ocf_ctx_register_volume_type_internal(ocf_ctx_t ctx, uint8_t type_id, const struct ocf_volume_properties *properties, const struct ocf_volume_extended *extended) { @@ -55,14 +56,17 @@ err: int ocf_ctx_register_volume_type(ocf_ctx_t ctx, uint8_t type_id, const struct ocf_volume_properties *properties) { - return ocf_ctx_register_volume_type_extended(ctx, type_id, + if (type_id >= OCF_VOLUME_TYPE_MAX_USER) + return -EINVAL; + + return ocf_ctx_register_volume_type_internal(ctx, type_id, properties, NULL); } /* * */ -void ocf_ctx_unregister_volume_type(ocf_ctx_t ctx, uint8_t type_id) +void ocf_ctx_unregister_volume_type_internal(ocf_ctx_t ctx, uint8_t type_id) { OCF_CHECK_NULL(ctx); @@ -76,17 +80,42 @@ void ocf_ctx_unregister_volume_type(ocf_ctx_t ctx, uint8_t type_id) env_rmutex_unlock(&ctx->lock); } +void ocf_ctx_unregister_volume_type(ocf_ctx_t ctx, uint8_t type_id) +{ + OCF_CHECK_NULL(ctx); + + if (type_id < OCF_VOLUME_TYPE_MAX_USER) + ocf_ctx_unregister_volume_type_internal(ctx, type_id); +} + /* * */ -ocf_volume_type_t ocf_ctx_get_volume_type(ocf_ctx_t ctx, uint8_t type_id) +ocf_volume_type_t ocf_ctx_get_volume_type_internal(ocf_ctx_t ctx, + uint8_t type_id) { + ocf_volume_type_t volume_type; + OCF_CHECK_NULL(ctx); if (type_id >= OCF_VOLUME_TYPE_MAX) return NULL; - return ctx->volume_type[type_id]; + env_rmutex_lock(&ctx->lock); + volume_type = ctx->volume_type[type_id]; + env_rmutex_unlock(&ctx->lock); + + return volume_type; +} + +ocf_volume_type_t ocf_ctx_get_volume_type(ocf_ctx_t ctx, uint8_t type_id) +{ + OCF_CHECK_NULL(ctx); + + if (type_id >= OCF_VOLUME_TYPE_MAX_USER) + return NULL; + + return ocf_ctx_get_volume_type_internal(ctx, type_id); } /* @@ -114,12 +143,15 @@ int ocf_ctx_get_volume_type_id(ocf_ctx_t ctx, ocf_volume_type_t type) int ocf_ctx_volume_create(ocf_ctx_t ctx, ocf_volume_t *volume, struct ocf_volume_uuid *uuid, uint8_t type_id) { + ocf_volume_type_t volume_type; + OCF_CHECK_NULL(ctx); - if (type_id >= OCF_VOLUME_TYPE_MAX) + volume_type = ocf_ctx_get_volume_type(ctx, type_id); + if (!volume_type) return -EINVAL; - return ocf_volume_create(volume, ctx->volume_type[type_id], uuid); + return ocf_volume_create(volume, volume_type, uuid); } static void check_ops_provided(const struct ocf_ctx_ops *ops) diff --git a/src/ocf_ctx_priv.h b/src/ocf_ctx_priv.h index 9f8c3ad..ab7385f 100644 --- a/src/ocf_ctx_priv.h +++ b/src/ocf_ctx_priv.h @@ -11,7 +11,13 @@ #include "ocf_logger_priv.h" #include "ocf_volume_priv.h" -#define OCF_VOLUME_TYPE_MAX 8 +#define OCF_VOLUME_TYPE_CNT_USER 8 +#define OCF_VOLUME_TYPE_CNT_PRIV 2 +#define OCF_VOLUME_TYPE_MAX_USER OCF_VOLUME_TYPE_CNT_USER +#define OCF_VOLUME_TYPE_MAX \ + (OCF_VOLUME_TYPE_CNT_USER + OCF_VOLUME_TYPE_CNT_PRIV) + +#define OCF_VOLUME_TYPE_CORE (OCF_VOLUME_TYPE_MAX_USER + 0) /** * @brief OCF main control structure @@ -50,10 +56,15 @@ struct ocf_ctx { #define ocf_log_stack_trace(ctx) \ ocf_log_stack_trace_raw(&ctx->logger) -int ocf_ctx_register_volume_type_extended(ocf_ctx_t ctx, uint8_t type_id, +int ocf_ctx_register_volume_type_internal(ocf_ctx_t ctx, uint8_t type_id, const struct ocf_volume_properties *properties, const struct ocf_volume_extended *extended); +void ocf_ctx_unregister_volume_type_internal(ocf_ctx_t ctx, uint8_t type_id); + +ocf_volume_type_t ocf_ctx_get_volume_type_internal(ocf_ctx_t ctx, + uint8_t type_id); + /** * @name Environment data buffer operations wrappers * @{ From fa8e7564f02a5f20b8bdca804784d88015931699 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 2 Sep 2021 22:01:06 +0200 Subject: [PATCH 14/26] Move ocf_io_get_internal() to private header Signed-off-by: Robert Baldyga --- src/ocf_io.c | 5 ----- src/ocf_io_priv.h | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ocf_io.c b/src/ocf_io.c index 69f1bde..512fed6 100644 --- a/src/ocf_io.c +++ b/src/ocf_io.c @@ -78,11 +78,6 @@ ocf_io_allocator_type_t ocf_io_allocator_get_type_default(void) * IO internal API */ -static struct ocf_io_internal *ocf_io_get_internal(struct ocf_io* io) -{ - return container_of(io, struct ocf_io_internal, io); -} - struct ocf_io *ocf_io_new(ocf_volume_t volume, ocf_queue_t queue, uint64_t addr, uint32_t bytes, uint32_t dir, uint32_t io_class, uint64_t flags) diff --git a/src/ocf_io_priv.h b/src/ocf_io_priv.h index 53c9230..4b2fffa 100644 --- a/src/ocf_io_priv.h +++ b/src/ocf_io_priv.h @@ -22,6 +22,11 @@ struct ocf_io_internal { struct ocf_io io; }; +static inline struct ocf_io_internal *ocf_io_get_internal(struct ocf_io* io) +{ + return container_of(io, struct ocf_io_internal, io); +} + int ocf_io_allocator_init(ocf_io_allocator_t allocator, ocf_io_allocator_type_t type, uint32_t priv_size, const char *name); From ad52a7e2e1d45c1551865989c43536fda1095744 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 2 Sep 2021 22:02:11 +0200 Subject: [PATCH 15/26] Introduce cache front volume Signed-off-by: Robert Baldyga --- src/ocf_cache.c | 184 +++++++++++++++++++++++++++++++++++++++++++ src/ocf_cache_priv.h | 2 + src/ocf_ctx.c | 4 + src/ocf_ctx_priv.h | 1 + 4 files changed, 191 insertions(+) diff --git a/src/ocf_cache.c b/src/ocf_cache.c index 26a0865..47aecde 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -231,3 +231,187 @@ void *ocf_cache_get_priv(ocf_cache_t cache) OCF_CHECK_NULL(cache); return cache->priv; } + +struct ocf_cache_volume_io_priv { + struct ocf_io *io; + struct ctx_data_t *data; +}; + +struct ocf_cache_volume { + ocf_cache_t cache; +}; + +static inline ocf_cache_t ocf_volume_to_cache(ocf_volume_t volume) +{ + struct ocf_cache_volume *cache_volume = ocf_volume_get_priv(volume); + + return cache_volume->cache; +} + +static void ocf_cache_volume_io_complete(struct ocf_io *vol_io, int error) +{ + struct ocf_io *io = vol_io->priv1; + + ocf_io_put(vol_io); + ocf_io_end(io, error); +} + +static int ocf_cache_volume_prepare_vol_io(struct ocf_io *io, + struct ocf_io **vol_io) +{ + struct ocf_cache_volume_io_priv *priv; + ocf_cache_t cache; + struct ocf_io *tmp_io; + int result; + + OCF_CHECK_NULL(io); + + priv = ocf_io_get_priv(io); + cache = ocf_volume_to_cache(ocf_io_get_volume(io)); + + tmp_io = ocf_volume_new_io(ocf_cache_get_volume(cache), io->io_queue, + io->addr, io->bytes, io->dir, io->io_class, io->flags); + if (!tmp_io) + return -OCF_ERR_NO_MEM; + + result = ocf_io_set_data(tmp_io, priv->data, 0); + if (result) { + ocf_io_put(tmp_io); + return result; + } + + ocf_io_set_cmpl(tmp_io, io, NULL, ocf_cache_volume_io_complete); + + *vol_io = tmp_io; + + return 0; +} + + +static void ocf_cache_volume_submit_io(struct ocf_io *io) +{ + struct ocf_io *vol_io; + int result; + + result = ocf_cache_volume_prepare_vol_io(io, &vol_io); + if (result) { + ocf_io_end(io, result); + return; + } + + ocf_volume_submit_io(vol_io); +} + + +static void ocf_cache_volume_submit_flush(struct ocf_io *io) +{ + struct ocf_io *vol_io; + int result; + + result = ocf_cache_volume_prepare_vol_io(io, &vol_io); + if (result) { + ocf_io_end(io, result); + return; + } + + ocf_volume_submit_flush(vol_io); +} + + +static void ocf_cache_volume_submit_discard(struct ocf_io *io) +{ + struct ocf_io *vol_io; + int result; + + result = ocf_cache_volume_prepare_vol_io(io, &vol_io); + if (result) { + ocf_io_end(io, result); + return; + } + + ocf_volume_submit_discard(vol_io); +} + +/* *** VOLUME OPS *** */ + +static int ocf_cache_volume_open(ocf_volume_t volume, void *volume_params) +{ + struct ocf_cache_volume *cache_volume = ocf_volume_get_priv(volume); + const struct ocf_volume_uuid *uuid = ocf_volume_get_uuid(volume); + ocf_cache_t cache = (ocf_cache_t)uuid->data; + + cache_volume->cache = cache; + + return 0; +} + +static void ocf_cache_volume_close(ocf_volume_t volume) +{ +} + +static unsigned int ocf_cache_volume_get_max_io_size(ocf_volume_t volume) +{ + ocf_cache_t cache = ocf_volume_to_cache(volume); + + return ocf_volume_get_max_io_size(ocf_cache_get_volume(cache)); +} + +static uint64_t ocf_cache_volume_get_byte_length(ocf_volume_t volume) +{ + ocf_cache_t cache = ocf_volume_to_cache(volume); + + return ocf_volume_get_length(ocf_cache_get_volume(cache)); +} + +/* *** IO OPS *** */ + +static int ocf_cache_io_set_data(struct ocf_io *io, + ctx_data_t *data, uint32_t offset) +{ + struct ocf_cache_volume_io_priv *priv = ocf_io_get_priv(io); + + if (!data || offset) + return -OCF_ERR_INVAL; + + priv->data = data; + + return 0; +} + +static ctx_data_t *ocf_cache_io_get_data(struct ocf_io *io) +{ + struct ocf_cache_volume_io_priv *priv = ocf_io_get_priv(io); + + return priv->data; +} + +const struct ocf_volume_properties ocf_cache_volume_properties = { + .name = "OCF Cache", + .io_priv_size = sizeof(struct ocf_cache_volume_io_priv), + .volume_priv_size = sizeof(struct ocf_cache_volume), + .caps = { + .atomic_writes = 0, + }, + .ops = { + .submit_io = ocf_cache_volume_submit_io, + .submit_flush = ocf_cache_volume_submit_flush, + .submit_discard = ocf_cache_volume_submit_discard, + .submit_metadata = NULL, + + .open = ocf_cache_volume_open, + .close = ocf_cache_volume_close, + .get_max_io_size = ocf_cache_volume_get_max_io_size, + .get_length = ocf_cache_volume_get_byte_length, + }, + .io_ops = { + .set_data = ocf_cache_io_set_data, + .get_data = ocf_cache_io_get_data, + }, + .deinit = NULL, +}; + +int ocf_cache_volume_type_init(ocf_ctx_t ctx) +{ + return ocf_ctx_register_volume_type_internal(ctx, OCF_VOLUME_TYPE_CACHE, + &ocf_cache_volume_properties, NULL); +} diff --git a/src/ocf_cache_priv.h b/src/ocf_cache_priv.h index 12b2cc2..317918b 100644 --- a/src/ocf_cache_priv.h +++ b/src/ocf_cache_priv.h @@ -169,4 +169,6 @@ static inline uint64_t ocf_get_cache_occupancy(ocf_cache_t cache) int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size); +int ocf_cache_volume_type_init(ocf_ctx_t ctx); + #endif /* __OCF_CACHE_PRIV_H__ */ diff --git a/src/ocf_ctx.c b/src/ocf_ctx.c index 083364b..f714c09 100644 --- a/src/ocf_ctx.c +++ b/src/ocf_ctx.c @@ -216,6 +216,10 @@ int ocf_ctx_create(ocf_ctx_t *ctx, const struct ocf_ctx_config *cfg) if (ret) goto err_utils; + ret = ocf_cache_volume_type_init(ocf_ctx); + if (ret) + goto err_utils; + ocf_mngt_core_pool_init(ocf_ctx); *ctx = ocf_ctx; diff --git a/src/ocf_ctx_priv.h b/src/ocf_ctx_priv.h index ab7385f..baf1cc5 100644 --- a/src/ocf_ctx_priv.h +++ b/src/ocf_ctx_priv.h @@ -18,6 +18,7 @@ (OCF_VOLUME_TYPE_CNT_USER + OCF_VOLUME_TYPE_CNT_PRIV) #define OCF_VOLUME_TYPE_CORE (OCF_VOLUME_TYPE_MAX_USER + 0) +#define OCF_VOLUME_TYPE_CACHE (OCF_VOLUME_TYPE_MAX_USER + 1) /** * @brief OCF main control structure From 85e8b414c4b5b84cc98b84afc6512c29b0df8190 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 31 Aug 2021 18:56:08 +0200 Subject: [PATCH 16/26] Add ocf_metadata_load_unsafe() Signed-off-by: Robert Baldyga --- src/metadata/metadata.c | 73 +++++++++++++++++++++++++++++++++++++++++ src/metadata/metadata.h | 10 ++++++ 2 files changed, 83 insertions(+) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 0afae41..6d8207d 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1146,6 +1146,79 @@ void ocf_metadata_load_all(ocf_cache_t cache, ocf_pipeline_next(pipeline); } +static void ocf_metadata_load_unsafe_finish(ocf_pipeline_t pipeline, + void *priv, int error) +{ + struct ocf_metadata_context *context = priv; + ocf_cache_t cache = context->cache; + + if (error) { + ocf_cache_log(cache, log_err, "Metadata read FAILURE\n"); + ocf_metadata_error(cache); + goto out; + } + + ocf_cache_log(cache, log_info, "Done loading cache state\n"); + +out: + context->cmpl(context->priv, error); + ocf_pipeline_destroy(pipeline); +} + +struct ocf_pipeline_arg ocf_metadata_load_unsafe_args[] = { + OCF_PL_ARG_INT(metadata_segment_sb_config), + OCF_PL_ARG_INT(metadata_segment_sb_runtime), + OCF_PL_ARG_INT(metadata_segment_part_config), + OCF_PL_ARG_INT(metadata_segment_part_runtime), + OCF_PL_ARG_INT(metadata_segment_core_config), + OCF_PL_ARG_INT(metadata_segment_core_runtime), + OCF_PL_ARG_INT(metadata_segment_core_uuid), + OCF_PL_ARG_INT(metadata_segment_cleaning), + OCF_PL_ARG_INT(metadata_segment_lru), + OCF_PL_ARG_INT(metadata_segment_collision), + OCF_PL_ARG_INT(metadata_segment_list_info), + OCF_PL_ARG_INT(metadata_segment_hash), + OCF_PL_ARG_TERMINATOR(), +}; + +struct ocf_pipeline_properties ocf_metadata_load_unsafe_pipeline_props = { + .priv_size = sizeof(struct ocf_metadata_context), + .finish = ocf_metadata_load_unsafe_finish, + .steps = { + OCF_PL_STEP_FOREACH(ocf_metadata_load_segment, + ocf_metadata_load_unsafe_args), + OCF_PL_STEP_TERMINATOR(), + }, +}; + +/* + * Load metadata unsafe + */ +void ocf_metadata_load_unsafe(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *priv) +{ + struct ocf_metadata_context *context; + ocf_pipeline_t pipeline; + int result; + + OCF_DEBUG_TRACE(cache); + + result = ocf_pipeline_create(&pipeline, cache, + &ocf_metadata_load_unsafe_pipeline_props); + if (result) + OCF_CMPL_RET(priv, result); + + context = ocf_pipeline_get_priv(pipeline); + + context->cmpl = cmpl; + context->priv = priv; + context->pipeline = pipeline; + context->cache = cache; + context->ctrl = cache->metadata.priv; + + ocf_pipeline_next(pipeline); +} + static void ocf_metadata_load_recovery_legacy_finish( ocf_pipeline_t pipeline, void *priv, int error) { diff --git a/src/metadata/metadata.h b/src/metadata/metadata.h index a084bb9..8a7e59b 100644 --- a/src/metadata/metadata.h +++ b/src/metadata/metadata.h @@ -164,6 +164,16 @@ void ocf_metadata_flush_do_asynch(struct ocf_cache *cache, void ocf_metadata_load_all(ocf_cache_t cache, ocf_metadata_end_t cmpl, void *priv); +/** + * @brief Load metadata unsafe + * + * @param cache - Cache instance + * @param cmpl - Completion callback + * @param priv - Completion context + */ +void ocf_metadata_load_unsafe(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *priv); + /** * @brief Load metadata required for recovery procedure * From ee42d9aaaf6a5257d1a820d1f8735acf466ab534 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 31 Aug 2021 16:31:53 +0200 Subject: [PATCH 17/26] Duplicate cache name in struct ocf_cache Cache name is needed for logging in passive mode, when config metadata is still not accessible. Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_cache.c | 2 +- src/ocf_cache.c | 9 ++++++++- src/ocf_cache_priv.h | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 6a3e65c..0b9450e 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -1012,7 +1012,7 @@ static void _ocf_mngt_load_read_properties_end(void *priv, int error, /* * Check if name loaded from disk is the same as present one. */ - if (env_strncmp(cache->conf_meta->name, OCF_CACHE_NAME_SIZE, + if (env_strncmp(cache->name, OCF_CACHE_NAME_SIZE, properties->cache_name, OCF_CACHE_NAME_SIZE)) { OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_CACHE_NAME_MISMATCH); } diff --git a/src/ocf_cache.c b/src/ocf_cache.c index 47aecde..3c7d12a 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -21,7 +21,14 @@ ocf_volume_t ocf_cache_get_volume(ocf_cache_t cache) int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size) { + int result; + OCF_CHECK_NULL(cache); + + result = env_strncpy(cache->name, OCF_CACHE_NAME_SIZE, src, src_size); + if (result) + return result; + return env_strncpy(cache->conf_meta->name, OCF_CACHE_NAME_SIZE, src, src_size); } @@ -29,7 +36,7 @@ int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size) const char *ocf_cache_get_name(ocf_cache_t cache) { OCF_CHECK_NULL(cache); - return cache->conf_meta->name; + return cache->name; } bool ocf_cache_is_incomplete(ocf_cache_t cache) diff --git a/src/ocf_cache_priv.h b/src/ocf_cache_priv.h index 317918b..ce5239c 100644 --- a/src/ocf_cache_priv.h +++ b/src/ocf_cache_priv.h @@ -51,6 +51,8 @@ struct ocf_cache_device { }; struct ocf_cache { + char name[OCF_CACHE_NAME_SIZE]; + ocf_ctx_t owner; struct list_head list; From 1fd9a448d4851adc5c0d95bab02dd0cfa07e41b9 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Wed, 11 Aug 2021 19:53:07 +0200 Subject: [PATCH 18/26] 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 From 9b3a0c968e70f7a56176d2714b7076197ae69d1b Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Wed, 1 Sep 2021 21:29:33 +0200 Subject: [PATCH 19/26] Introduce ocf_metadata_passive_update() Signed-off-by: Robert Baldyga --- src/metadata/metadata.c | 48 +++++++++++ src/metadata/metadata.h | 2 + src/metadata/metadata_raw.c | 58 ++++++++++---- src/metadata/metadata_raw.h | 20 +++++ src/metadata/metadata_raw_dynamic.c | 114 +++++++++++++++++---------- src/metadata/metadata_raw_dynamic.h | 7 ++ src/metadata/metadata_raw_volatile.c | 11 +++ src/metadata/metadata_raw_volatile.h | 7 ++ 8 files changed, 211 insertions(+), 56 deletions(-) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 6d8207d..8b642a1 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -2004,3 +2004,51 @@ void ocf_metadata_probe_cores(ocf_ctx_t ctx, ocf_volume_t volume, ocf_metadata_query_cores(ctx, volume, uuids, uuids_count, ocf_metadata_probe_cores_end, context); } + +int ocf_metadata_passive_update(ocf_cache_t cache, struct ocf_io *io) +{ + struct ocf_metadata_ctrl *ctrl = cache->metadata.priv; + ctx_data_t *data = ocf_io_get_data(io); + uint64_t io_start_page = BYTES_TO_PAGES(io->addr); + uint64_t io_end_page = io_start_page + BYTES_TO_PAGES(io->bytes); + enum ocf_metadata_segment_id update_segments[] = { + metadata_segment_sb_config, + metadata_segment_part_config, + metadata_segment_core_config, + metadata_segment_core_uuid, + metadata_segment_collision, + }; + int i; + + if (io->dir == OCF_READ) + return 0; + + if (io->addr % PAGE_SIZE || io->bytes % PAGE_SIZE) { + ocf_cache_log(cache, log_crit, + "Metadata update not aligned to page size!\n"); + return -OCF_ERR_INVAL; + } + + if (io_end_page >= ctrl->count_pages) + return 0; + + for (i = 0; i < ARRAY_SIZE(update_segments); i++) { + enum ocf_metadata_segment_id seg = update_segments[i]; + struct ocf_metadata_raw *raw = &(ctrl->raw_desc[seg]); + uint64_t raw_start_page = raw->ssd_pages_offset; + uint64_t raw_end_page = raw_start_page + raw->ssd_pages; + uint64_t overlap_start = OCF_MAX(io_start_page, raw_start_page); + uint64_t overlap_end = OCF_MIN(io_end_page, raw_end_page); + uint64_t overlap_start_data = overlap_start - io_start_page; + + if (overlap_start < overlap_end) { + ctx_data_seek(cache->owner, data, ctx_data_seek_begin, + PAGES_TO_BYTES(overlap_start_data)); + ocf_metadata_raw_update(cache, raw, data, + overlap_start - raw_start_page, + overlap_end - overlap_start); + } + } + + return 0; +} diff --git a/src/metadata/metadata.h b/src/metadata/metadata.h index 8a7e59b..6b2d4fa 100644 --- a/src/metadata/metadata.h +++ b/src/metadata/metadata.h @@ -226,4 +226,6 @@ static inline ocf_cache_line_t ocf_metadata_collision_table_entries( return cache->device->collision_table_entries; } +int ocf_metadata_passive_update(ocf_cache_t cache, struct ocf_io *io); + #endif /* METADATA_H_ */ diff --git a/src/metadata/metadata_raw.c b/src/metadata/metadata_raw.c index 15287e7..b7ee15c 100644 --- a/src/metadata/metadata_raw.c +++ b/src/metadata/metadata_raw.c @@ -188,6 +188,42 @@ static void *_raw_ram_access(ocf_cache_t cache, return _RAW_RAM_ADDR(raw, entry); } +static int _raw_ram_drain_page(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, uint32_t page) +{ + + uint32_t size = raw->entry_size * raw->entries_in_page; + ocf_cache_line_t line; + + ENV_BUG_ON(page > raw->ssd_pages); + ENV_BUG_ON(size > PAGE_SIZE); + + line = page * raw->entries_in_page; + + OCF_DEBUG_PARAM(cache, "Line = %u, Page = %u", line, page); + + ctx_data_rd_check(cache->owner, _RAW_RAM_ADDR(raw, line), data, size); + ctx_data_seek(cache->owner, data, ctx_data_seek_current, + PAGE_SIZE - size); + + return 0; +} + +/* + * RAM Implementation - update + */ +static int _raw_ram_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + uint64_t i; + + for (i = 0; i < count; i++) + _raw_ram_drain_page(cache, raw, data, page + i); + + return 0; +} + struct _raw_ram_load_all_context { struct ocf_metadata_raw *raw; ocf_metadata_end_t cmpl; @@ -202,23 +238,9 @@ static int _raw_ram_load_all_drain(ocf_cache_t cache, { struct _raw_ram_load_all_context *context = priv; struct ocf_metadata_raw *raw = context->raw; - uint32_t size = raw->entry_size * raw->entries_in_page; - ocf_cache_line_t line; - uint32_t raw_page; - ENV_BUG_ON(!_raw_ssd_page_is_valid(raw, page)); - ENV_BUG_ON(size > PAGE_SIZE); - - raw_page = page - raw->ssd_pages_offset; - line = raw_page * raw->entries_in_page; - - OCF_DEBUG_PARAM(cache, "Line = %u, Page = %u", line, raw_page); - - ctx_data_rd_check(cache->owner, _RAW_RAM_ADDR(raw, line), data, size); - ctx_data_seek(cache->owner, data, ctx_data_seek_current, - PAGE_SIZE - size); - - return 0; + return _raw_ram_drain_page(cache, raw, data, + page - raw->ssd_pages_offset); } static void _raw_ram_load_all_complete(ocf_cache_t cache, @@ -562,6 +584,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = _raw_ram_checksum, .page = _raw_ram_page, .access = _raw_ram_access, + .update = _raw_ram_update, .load_all = _raw_ram_load_all, .flush_all = _raw_ram_flush_all, .flush_mark = _raw_ram_flush_mark, @@ -575,6 +598,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = raw_dynamic_checksum, .page = raw_dynamic_page, .access = raw_dynamic_access, + .update = raw_dynamic_update, .load_all = raw_dynamic_load_all, .flush_all = raw_dynamic_flush_all, .flush_mark = raw_dynamic_flush_mark, @@ -588,6 +612,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = raw_volatile_checksum, .page = _raw_ram_page, .access = _raw_ram_access, + .update = raw_volatile_update, .load_all = raw_volatile_load_all, .flush_all = raw_volatile_flush_all, .flush_mark = raw_volatile_flush_mark, @@ -601,6 +626,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = _raw_ram_checksum, .page = _raw_ram_page, .access = _raw_ram_access, + .update = _raw_ram_update, .load_all = _raw_ram_load_all, .flush_all = _raw_ram_flush_all, .flush_mark = raw_atomic_flush_mark, diff --git a/src/metadata/metadata_raw.h b/src/metadata/metadata_raw.h index b595d7a..d8cf9bd 100644 --- a/src/metadata/metadata_raw.h +++ b/src/metadata/metadata_raw.h @@ -125,6 +125,9 @@ struct raw_iface { void* (*access)(ocf_cache_t cache, struct ocf_metadata_raw *raw, uint32_t entry); + int (*update)(ocf_cache_t cache, struct ocf_metadata_raw *raw, + ctx_data_t *data, uint64_t page, uint64_t count); + void (*load_all)(ocf_cache_t cache, struct ocf_metadata_raw *raw, ocf_metadata_end_t cmpl, void *priv); @@ -242,6 +245,23 @@ static inline const void *ocf_metadata_raw_rd_access( ocf_cache_t cache, return raw->iface->access(cache, raw, entry); } +/** + * @brief Update metadata based on cache device I/O + * + * @param cache - Cache instance + * @param raw - RAW descriptor + * @param data - Data buffer containing metadata pages + * @param page - First metadata page + * @param count - Number of metadata pages + * @return 0 - Operation success, otherwise error + */ +static inline int ocf_metadata_raw_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + return raw->iface->update(cache, raw, data, page, count); +} + /** * @brief Load all entries from SSD cache (cahce cache) * diff --git a/src/metadata/metadata_raw_dynamic.c b/src/metadata/metadata_raw_dynamic.c index 08453ce..3da9a5b 100644 --- a/src/metadata/metadata_raw_dynamic.c +++ b/src/metadata/metadata_raw_dynamic.c @@ -256,6 +256,72 @@ void *raw_dynamic_access(ocf_cache_t cache, return _raw_dynamic_get_item(cache, raw, entry); } +/* + * RAM DYNAMIC Implementation - update + */ +static int raw_dynamic_update_pages(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, uint64_t page, + uint64_t count, uint8_t **buffer, uint8_t *zpage) +{ + struct _raw_ctrl *ctrl = (struct _raw_ctrl *)raw->priv; + int result = 0; + uint64_t i; + int cmp; + + for (i = 0; i < count; i++) { + if (!*buffer) { + *buffer = env_secure_alloc(PAGE_SIZE); + if (!*buffer) + return -OCF_ERR_NO_MEM; + } + + ctx_data_rd_check(cache->owner, *buffer, data, PAGE_SIZE); + + result = env_memcmp(zpage, PAGE_SIZE, *buffer, PAGE_SIZE, &cmp); + if (result < 0) + return result; + + /* When page is zero set, no need to allocate space for it */ + if (cmp == 0) { + OCF_DEBUG_PARAM(cache, "Zero loaded %llu", i); + continue; + } + + OCF_DEBUG_PARAM(cache, "Non-zero loaded %llu", i); + + if (ctrl->pages[page + i]) + env_secure_free(ctrl->pages[page + i], PAGE_SIZE); + ctrl->pages[page + i] = *buffer; + *buffer = NULL; + + env_atomic_inc(&ctrl->count); + } + + return 0; +} + +int raw_dynamic_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + uint8_t *buffer = NULL, *zpage; + int result; + + zpage = env_vzalloc(PAGE_SIZE); + if (!zpage) + return -OCF_ERR_NO_MEM; + + result = raw_dynamic_update_pages(cache, raw, data, page, + count, &buffer, zpage); + + if (buffer) + env_secure_free(buffer, PAGE_SIZE); + + env_vfree(zpage); + + return result; +} + /* * RAM DYNAMIC Implementation - Load all */ @@ -269,7 +335,7 @@ struct raw_dynamic_load_all_context { ctx_data_t *data; uint8_t *zpage; uint8_t *page; - uint64_t i; + uint64_t i_page; int error; ocf_metadata_end_t cmpl; @@ -317,11 +383,12 @@ static int raw_dynamic_load_all_read(struct ocf_request *req) uint64_t count; int result; - count = OCF_MIN(RAW_DYNAMIC_LOAD_PAGES, raw->ssd_pages - context->i); + count = OCF_MIN(RAW_DYNAMIC_LOAD_PAGES, + raw->ssd_pages - context->i_page); /* Allocate IO */ context->io = ocf_new_cache_io(context->cache, req->io_queue, - PAGES_TO_BYTES(raw->ssd_pages_offset + context->i), + PAGES_TO_BYTES(raw->ssd_pages_offset + context->i_page), PAGES_TO_BYTES(count), OCF_READ, 0, 0); if (!context->io) { @@ -354,53 +421,20 @@ static int raw_dynamic_load_all_update(struct ocf_request *req) { struct raw_dynamic_load_all_context *context = req->priv; struct ocf_metadata_raw *raw = context->raw; - struct _raw_ctrl *ctrl = (struct _raw_ctrl *)raw->priv; ocf_cache_t cache = context->cache; uint64_t count = BYTES_TO_PAGES(context->io->bytes); - uint64_t i_page; int result = 0; - int cmp; /* Reset head of data buffer */ ctx_data_seek_check(context->cache->owner, context->data, ctx_data_seek_begin, 0); - for (i_page = 0; i_page < count; i_page++, context->i++) { - if (!context->page) { - context->page = env_secure_alloc(PAGE_SIZE); - if (!context->page) { - /* Allocation error */ - result = -OCF_ERR_NO_MEM; - break; - } - } + result = raw_dynamic_update_pages(cache, raw, context->data, + context->i_page, count, &context->page, context->zpage); - ctx_data_rd_check(cache->owner, context->page, - context->data, PAGE_SIZE); + context->i_page += count; - result = env_memcmp(context->zpage, PAGE_SIZE, context->page, - PAGE_SIZE, &cmp); - if (result) - break; - - /* When page is zero set, no need to allocate space for it */ - if (cmp == 0) { - OCF_DEBUG_PARAM(cache, "Zero loaded %llu", i); - continue; - } - - OCF_DEBUG_PARAM(cache, "Non-zero loaded %llu", i); - - if (ctrl->pages[context->i]) - env_vfree(ctrl->pages[context->i]); - - ctrl->pages[context->i] = context->page; - context->page = NULL; - - env_atomic_inc(&ctrl->count); - } - - if (result || context->i >= raw->ssd_pages) { + if (result || context->i_page >= raw->ssd_pages) { raw_dynamic_load_all_complete(context, result); return 0; } diff --git a/src/metadata/metadata_raw_dynamic.h b/src/metadata/metadata_raw_dynamic.h index 5443bb2..714896d 100644 --- a/src/metadata/metadata_raw_dynamic.h +++ b/src/metadata/metadata_raw_dynamic.h @@ -53,6 +53,13 @@ uint32_t raw_dynamic_page(struct ocf_metadata_raw *raw, uint32_t entry); void *raw_dynamic_access(ocf_cache_t cache, struct ocf_metadata_raw *raw, uint32_t entry); +/* + * RAW DYNAMIC - Update metadata based on cache volume io + */ +int raw_dynamic_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count); + /* * RAW DYNAMIC - Load all metadata of this RAW metadata container * from cache device diff --git a/src/metadata/metadata_raw_volatile.c b/src/metadata/metadata_raw_volatile.c index 0f08b93..ec55fcb 100644 --- a/src/metadata/metadata_raw_volatile.c +++ b/src/metadata/metadata_raw_volatile.c @@ -26,6 +26,17 @@ uint32_t raw_volatile_checksum(ocf_cache_t cache, return 0; } +/* + * RAW volatile Implementation - Update + */ +int raw_volatile_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + /* Do nothing on purpose. */ + return 0; +} + /* * RAW volatile Implementation - Load all metadata elements from SSD */ diff --git a/src/metadata/metadata_raw_volatile.h b/src/metadata/metadata_raw_volatile.h index 0d794b0..24286e0 100644 --- a/src/metadata/metadata_raw_volatile.h +++ b/src/metadata/metadata_raw_volatile.h @@ -17,6 +17,13 @@ uint32_t raw_volatile_size_on_ssd(struct ocf_metadata_raw *raw); uint32_t raw_volatile_checksum(ocf_cache_t cache, struct ocf_metadata_raw *raw); +/* + * RAW volatile Implementation - Update + */ +int raw_volatile_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count); + /* * RAW volatile Implementation - Load all metadata elements from SSD */ From e23342cb0e72c2f7e74fd123ae9cc6a2ddacc827 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 3 Sep 2021 14:51:51 +0200 Subject: [PATCH 20/26] Update metadata in passive mode Signed-off-by: Robert Baldyga --- src/ocf_cache.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/ocf_cache.c b/src/ocf_cache.c index d3e0476..2ad47b3 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -251,6 +251,7 @@ void *ocf_cache_get_priv(ocf_cache_t cache) struct ocf_cache_volume_io_priv { struct ocf_io *io; struct ctx_data_t *data; + env_atomic remaining; }; struct ocf_cache_volume { @@ -266,8 +267,14 @@ static inline ocf_cache_t ocf_volume_to_cache(ocf_volume_t volume) static void ocf_cache_volume_io_complete(struct ocf_io *vol_io, int error) { + struct ocf_cache_volume_io_priv *priv; struct ocf_io *io = vol_io->priv1; + priv = ocf_io_get_priv(io); + + if (env_atomic_dec_return(&priv->remaining)) + return; + ocf_io_put(vol_io); ocf_io_end(io, error); } @@ -306,9 +313,16 @@ static int ocf_cache_volume_prepare_vol_io(struct ocf_io *io, static void ocf_cache_volume_submit_io(struct ocf_io *io) { + struct ocf_cache_volume_io_priv *priv; struct ocf_io *vol_io; + ocf_cache_t cache; int result; + cache = ocf_volume_to_cache(ocf_io_get_volume(io)); + priv = ocf_io_get_priv(io); + + env_atomic_set(&priv->remaining, 2); + result = ocf_cache_volume_prepare_vol_io(io, &vol_io); if (result) { ocf_io_end(io, result); @@ -316,14 +330,30 @@ static void ocf_cache_volume_submit_io(struct ocf_io *io) } ocf_volume_submit_io(vol_io); + + result = ocf_metadata_passive_update(cache, io); + if (result) { + ocf_cache_log(cache, log_crit, + "Metadata update error (error=%d)!\n", result); + } + + if (env_atomic_dec_return(&priv->remaining)) + return; + + ocf_io_put(vol_io); + ocf_io_end(io, 0); } static void ocf_cache_volume_submit_flush(struct ocf_io *io) { + struct ocf_cache_volume_io_priv *priv; struct ocf_io *vol_io; int result; + priv = ocf_io_get_priv(io); + env_atomic_set(&priv->remaining, 1); + result = ocf_cache_volume_prepare_vol_io(io, &vol_io); if (result) { ocf_io_end(io, result); @@ -336,9 +366,13 @@ static void ocf_cache_volume_submit_flush(struct ocf_io *io) static void ocf_cache_volume_submit_discard(struct ocf_io *io) { + struct ocf_cache_volume_io_priv *priv; struct ocf_io *vol_io; int result; + priv = ocf_io_get_priv(io); + env_atomic_set(&priv->remaining, 1); + result = ocf_cache_volume_prepare_vol_io(io, &vol_io); if (result) { ocf_io_end(io, result); From d5bd3fbd78b00d3ba4a8be1661da76b06a09ea4e Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 3 Sep 2021 14:49:53 +0200 Subject: [PATCH 21/26] Free zeroed metadata pages on update in raw_dynamic Signed-off-by: Robert Baldyga --- src/metadata/metadata_raw_dynamic.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/metadata/metadata_raw_dynamic.c b/src/metadata/metadata_raw_dynamic.c index 3da9a5b..50e0536 100644 --- a/src/metadata/metadata_raw_dynamic.c +++ b/src/metadata/metadata_raw_dynamic.c @@ -284,6 +284,12 @@ static int raw_dynamic_update_pages(ocf_cache_t cache, /* When page is zero set, no need to allocate space for it */ if (cmp == 0) { OCF_DEBUG_PARAM(cache, "Zero loaded %llu", i); + if (ctrl->pages[page + i]) { + env_secure_free(ctrl->pages[page + i], + PAGE_SIZE); + ctrl->pages[page + i] = NULL; + env_atomic_dec(&ctrl->count); + } continue; } From c662649f31ab33cdb2a1ee66df3f1525ad60dc6c Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 3 Sep 2021 13:07:06 +0200 Subject: [PATCH 22/26] Increment metadata refcount on cache front volume io Signed-off-by: Robert Baldyga --- src/ocf_cache.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/ocf_cache.c b/src/ocf_cache.c index 2ad47b3..a89655b 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -269,6 +269,7 @@ static void ocf_cache_volume_io_complete(struct ocf_io *vol_io, int error) { struct ocf_cache_volume_io_priv *priv; struct ocf_io *io = vol_io->priv1; + ocf_cache_t cache = ocf_volume_to_cache(ocf_io_get_volume(io)); priv = ocf_io_get_priv(io); @@ -277,6 +278,7 @@ static void ocf_cache_volume_io_complete(struct ocf_io *vol_io, int error) ocf_io_put(vol_io); ocf_io_end(io, error); + ocf_refcnt_dec(&cache->refcnt.metadata); } static int ocf_cache_volume_prepare_vol_io(struct ocf_io *io, @@ -321,6 +323,11 @@ static void ocf_cache_volume_submit_io(struct ocf_io *io) cache = ocf_volume_to_cache(ocf_io_get_volume(io)); priv = ocf_io_get_priv(io); + if (!ocf_refcnt_inc(&cache->refcnt.metadata)) { + ocf_io_end(io, -OCF_ERR_IO); + return; + } + env_atomic_set(&priv->remaining, 2); result = ocf_cache_volume_prepare_vol_io(io, &vol_io); @@ -342,6 +349,7 @@ static void ocf_cache_volume_submit_io(struct ocf_io *io) ocf_io_put(vol_io); ocf_io_end(io, 0); + ocf_refcnt_dec(&cache->refcnt.metadata); } @@ -349,9 +357,17 @@ static void ocf_cache_volume_submit_flush(struct ocf_io *io) { struct ocf_cache_volume_io_priv *priv; struct ocf_io *vol_io; + ocf_cache_t cache; int result; + cache = ocf_volume_to_cache(ocf_io_get_volume(io)); priv = ocf_io_get_priv(io); + + if (!ocf_refcnt_inc(&cache->refcnt.metadata)) { + ocf_io_end(io, -OCF_ERR_IO); + return; + } + env_atomic_set(&priv->remaining, 1); result = ocf_cache_volume_prepare_vol_io(io, &vol_io); @@ -368,9 +384,17 @@ static void ocf_cache_volume_submit_discard(struct ocf_io *io) { struct ocf_cache_volume_io_priv *priv; struct ocf_io *vol_io; + ocf_cache_t cache; int result; + cache = ocf_volume_to_cache(ocf_io_get_volume(io)); priv = ocf_io_get_priv(io); + + if (!ocf_refcnt_inc(&cache->refcnt.metadata)) { + ocf_io_end(io, -OCF_ERR_IO); + return; + } + env_atomic_set(&priv->remaining, 1); result = ocf_cache_volume_prepare_vol_io(io, &vol_io); From f96451a6980000c73425726aa55d67025f33ed7b Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 31 Aug 2021 10:20:52 +0200 Subject: [PATCH 23/26] Introduce ocf_cache_is_passive() Signed-off-by: Robert Baldyga --- inc/ocf_cache.h | 10 ++++++++++ src/ocf_cache.c | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/inc/ocf_cache.h b/inc/ocf_cache.h index cf85cb2..0595d87 100644 --- a/inc/ocf_cache.h +++ b/inc/ocf_cache.h @@ -151,6 +151,16 @@ bool ocf_cache_is_device_attached(ocf_cache_t cache); */ bool ocf_cache_is_running(ocf_cache_t cache); +/** + * @brief Check if cache object is passive + * + * @param[in] cache Cache object + * + * @retval 1 Caching device is in passive state + * @retval 0 Caching device is not in passive state + */ +bool ocf_cache_is_passive(ocf_cache_t cache); + /** * @brief Get cache mode of given cache object * diff --git a/src/ocf_cache.c b/src/ocf_cache.c index a89655b..e78cd14 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -56,6 +56,12 @@ bool ocf_cache_is_running(ocf_cache_t cache) return env_bit_test(ocf_cache_state_running, &cache->cache_state); } +bool ocf_cache_is_passive(ocf_cache_t cache) +{ + OCF_CHECK_NULL(cache); + return env_bit_test(ocf_cache_state_passive, &cache->cache_state); +} + bool ocf_cache_is_device_attached(ocf_cache_t cache) { OCF_CHECK_NULL(cache); From cc22c57cb73688594630ceca58efbbbba6e2c393 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 16 Aug 2021 06:47:34 +0200 Subject: [PATCH 24/26] Set proper cache pointer in front volumes Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_cache.c | 1 + src/mngt/ocf_mngt_core.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 75c7689..a72e593 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -1960,6 +1960,7 @@ static void _ocf_mngt_init_cache_front_volume(ocf_pipeline_t pipeline, result = ocf_volume_init(&cache->device->front_volume, type, &uuid, false); if (result) OCF_PL_FINISH_RET(context->pipeline, result); + cache->device->front_volume.cache = cache; context->flags.front_volume_inited = true; result = ocf_volume_open(&cache->device->front_volume, NULL); diff --git a/src/mngt/ocf_mngt_core.c b/src/mngt/ocf_mngt_core.c index a818e25..f409de9 100644 --- a/src/mngt/ocf_mngt_core.c +++ b/src/mngt/ocf_mngt_core.c @@ -229,6 +229,8 @@ int ocf_mngt_core_init_front_volume(ocf_core_t core) if (ret) return ret; + core->front_volume.cache = cache; + ret = ocf_volume_open(&core->front_volume, NULL); if (ret) ocf_volume_deinit(&core->front_volume); From 7b38ad205ce731c16e6b37d4626432b9b2417123 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 12 Aug 2021 13:04:50 +0200 Subject: [PATCH 25/26] Add cache activation from passive state Signed-off-by: Robert Baldyga --- inc/ocf_err.h | 6 + inc/ocf_mngt.h | 22 ++ src/mngt/ocf_mngt_cache.c | 412 ++++++++++++++++++++++++++++++++++---- 3 files changed, 397 insertions(+), 43 deletions(-) diff --git a/inc/ocf_err.h b/inc/ocf_err.h index 015de7d..b5a889b 100644 --- a/inc/ocf_err.h +++ b/inc/ocf_err.h @@ -128,6 +128,12 @@ typedef enum { /** Core with the uuid already exists */ OCF_ERR_CORE_UUID_EXISTS, + + /** Cache initialized with wrong metadata layout */ + OCF_ERR_METADATA_LAYOUT_MISMATCH, + + /** Cache initialized with wrong cache line size */ + OCF_ERR_CACHE_LINE_SIZE_MISMATCH, } ocf_error_t; #endif /* __OCF_ERR_H__ */ diff --git a/inc/ocf_mngt.h b/inc/ocf_mngt.h index 51f1940..c61db74 100644 --- a/inc/ocf_mngt.h +++ b/inc/ocf_mngt.h @@ -536,6 +536,28 @@ 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); +/** + * @brief Completion callback of 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_activate_end_t)(ocf_cache_t cache, + void *priv, int error); + +/** + * @brief Activate 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_activate(ocf_cache_t cache, + struct ocf_mngt_cache_device_config *cfg, + ocf_mngt_cache_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 a72e593..530d8e1 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -95,6 +95,8 @@ struct ocf_cache_attach_context { uint64_t volume_size; /*!< size of the device in cache lines */ + struct ocf_volume cache_volume; + /** * @brief initialization state (in case of error, it is used to know * which assets have to be deallocated in premature exit from function @@ -103,6 +105,9 @@ struct ocf_cache_attach_context { bool device_alloc : 1; /*!< data structure allocated */ + bool volume_stored : 1; + /*!< underlying device volume is stored in contex */ + bool volume_inited : 1; /*!< underlying device volume is initialized */ @@ -626,9 +631,6 @@ static void _ocf_mngt_load_init_instance_recovery( init_attached_data_structures_recovery(cache); - ocf_cache_log(cache, log_warn, - "ERROR: Cache device did not shut down properly!\n"); - ocf_cache_log(cache, log_info, "Initiating recovery sequence...\n"); ocf_metadata_load_recovery(cache, @@ -639,11 +641,15 @@ static void _ocf_mngt_load_init_instance(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) + if (context->metadata.shutdown_status == ocf_metadata_clean_shutdown) { _ocf_mngt_load_init_instance_clean_load(context); - else + } else { + ocf_cache_log(cache, log_warn, + "ERROR: Cache device did not shut down properly!\n"); _ocf_mngt_load_init_instance_recovery(context); + } } /** @@ -1215,44 +1221,6 @@ static void _ocf_mngt_init_handle_error(ocf_ctx_t ctx, env_rmutex_unlock(&ctx->lock); } -static void _ocf_mngt_attach_handle_error( - struct ocf_cache_attach_context *context) -{ - ocf_cache_t cache = context->cache; - - if (context->flags.cleaner_started) - ocf_stop_cleaner(cache); - - if (context->flags.promotion_initialized) - __deinit_promotion_policy(cache); - - if (context->flags.cores_opened) - _ocf_mngt_close_all_uninitialized_cores(cache); - - if (context->flags.attached_metadata_inited) - ocf_metadata_deinit_variable_size(cache); - - 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); - - ocf_pipeline_destroy(cache->stop_pipeline); -} - static void _ocf_mngt_cache_init(ocf_cache_t cache, struct ocf_cache_mngt_init_params *params) { @@ -1370,6 +1338,15 @@ static void _ocf_mngt_cache_set_passive(ocf_cache_t cache) env_bit_set(ocf_cache_state_passive, &cache->cache_state); } +static void _ocf_mngt_cache_set_active(ocf_cache_t cache) +{ + /* + * Clear passive state and set the running bit. + */ + env_bit_clear(ocf_cache_state_passive, &cache->cache_state); + env_bit_set(ocf_cache_state_running, &cache->cache_state); +} + static void _ocf_mngt_init_attached_nonpersistent(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { @@ -1634,6 +1611,46 @@ static void _ocf_mngt_attach_post_init(ocf_pipeline_t pipeline, ocf_pipeline_next(pipeline); } +static void _ocf_mngt_attach_handle_error( + struct ocf_cache_attach_context *context) +{ + ocf_cache_t cache = context->cache; + + if (context->flags.cleaner_started) + ocf_stop_cleaner(cache); + + if (context->flags.promotion_initialized) + __deinit_promotion_policy(cache); + + if (context->flags.cores_opened) + _ocf_mngt_close_all_uninitialized_cores(cache); + + if (context->flags.attached_metadata_inited) + ocf_metadata_deinit_variable_size(cache); + + 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); + cache->device = NULL; + } + + ocf_pipeline_destroy(cache->stop_pipeline); +} + static void _ocf_mngt_cache_attach_finish(ocf_pipeline_t pipeline, void *priv, int error) { @@ -2038,6 +2055,241 @@ struct ocf_pipeline_properties _ocf_mngt_cache_bind_pipeline_properties = { }, }; +static void _ocf_mngt_activate_wait_metadata_io_finish(void *priv) +{ + struct ocf_cache_attach_context *context = priv; + + ocf_pipeline_next(context->pipeline); +} + +static void _ocf_mngt_activate_wait_metadata_io(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_freeze(&cache->refcnt.metadata); + ocf_refcnt_register_zero_cb(&cache->refcnt.metadata, + _ocf_mngt_activate_wait_metadata_io_finish, context); +} + +static void _ocf_mngt_activate_swap_cache_device(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + const struct ocf_volume_uuid *cache_uuid; + ocf_volume_type_t type; + int ret, cmp; + + cache_uuid = ocf_volume_get_uuid(ocf_cache_get_volume(cache)); + ret = env_memcmp(context->cfg.uuid.data, context->cfg.uuid.size, + cache_uuid->data, cache_uuid->size, &cmp); + if (ret) + OCF_PL_FINISH_RET(pipeline, ret); + + if (cmp == 0) + OCF_PL_NEXT_RET(pipeline); + + ret = ocf_volume_init(&context->cache_volume, 0, NULL, false); + if (!ret) + OCF_PL_FINISH_RET(pipeline, ret); + + ocf_volume_move(&context->cache_volume, &cache->device->volume); + context->flags.volume_stored = true; + + type = ocf_ctx_get_volume_type(cache->owner, context->cfg.volume_type); + if (!type) { + OCF_PL_FINISH_RET(pipeline, + -OCF_ERR_INVAL_VOLUME_TYPE); + } + + ret = ocf_volume_init(&cache->device->volume, type, + &context->cfg.uuid, true); + if (ret) + OCF_PL_FINISH_RET(pipeline, ret); + + cache->device->volume.cache = cache; + context->flags.volume_inited = true; + + ret = ocf_volume_open(&cache->device->volume, + context->cfg.volume_params); + if (ret) { + ocf_cache_log(cache, log_err, "ERROR: Cache not available\n"); + OCF_PL_FINISH_RET(pipeline, ret); + } + context->flags.volume_opened = true; + + context->volume_size = ocf_volume_get_length(&cache->device->volume); + + ocf_pipeline_next(pipeline); +} + +static void _ocf_mngt_activate_check_superblock_complete(void *priv, int error) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + int result; + + if (error) + OCF_PL_FINISH_RET(context->pipeline, error); + + result = ocf_metadata_validate_superblock(cache->owner, + cache->conf_meta); + if (result) + OCF_PL_FINISH_RET(context->pipeline, result); + + if (cache->conf_meta->metadata_layout != cache->metadata.layout) { + OCF_PL_FINISH_RET(context->pipeline, + -OCF_ERR_METADATA_LAYOUT_MISMATCH); + } + + if (cache->conf_meta->line_size != cache->metadata.settings.size) { + OCF_PL_FINISH_RET(context->pipeline, + -OCF_ERR_CACHE_LINE_SIZE_MISMATCH); + } + + ocf_pipeline_next(context->pipeline); +} + +static void _ocf_mngt_activate_check_superblock(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_sb_crc_recovery(cache, + _ocf_mngt_activate_check_superblock_complete, context); +} + +static void _ocf_mngt_activate_compare_superblock_end( + struct ocf_metadata_read_sb_ctx *sb_ctx) +{ + struct ocf_superblock_config *superblock = &sb_ctx->superblock; + struct ocf_cache_attach_context *context = sb_ctx->priv1; + ocf_cache_t cache = context->cache; + int result, diff; + + result = env_memcmp(cache->conf_meta, sizeof(*cache->conf_meta), + superblock, sizeof(*superblock), &diff); + if (result) + OCF_PL_FINISH_RET(context->pipeline, result); + + if (diff) { + ocf_cache_log(cache, log_err, "Superblock missmatch!\n"); + OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_INVAL); + } + + ocf_pipeline_next(context->pipeline); +} + +static void _ocf_mngt_activate_compare_superblock(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; + + result = ocf_metadata_read_sb(cache->owner, ocf_cache_get_volume(cache), + _ocf_mngt_activate_compare_superblock_end, + context, NULL); + if (result) + OCF_PL_FINISH_RET(pipeline, result); +} + +static void _ocf_mngt_activate_init_properties(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_ASSERT_PLUGGED(cache); + + context->metadata.shutdown_status = ocf_metadata_dirty_shutdown; + context->metadata.dirty_flushed = DIRTY_NOT_FLUSHED; + context->metadata.line_size = context->cfg.cache_line_size; + + ocf_pipeline_next(pipeline); +} + +static void _ocf_mngt_activate_handle_error( + struct ocf_cache_attach_context *context) +{ + ocf_cache_t cache = context->cache; + + if (context->flags.cleaner_started) + ocf_stop_cleaner(cache); + + if (context->flags.promotion_initialized) + __deinit_promotion_policy(cache); + + if (context->flags.cores_opened) + _ocf_mngt_close_all_uninitialized_cores(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.volume_stored) + ocf_volume_move(&cache->device->volume, &context->cache_volume); + + ocf_refcnt_unfreeze(&cache->refcnt.metadata); +} + +static void _ocf_mngt_cache_activate_finish(ocf_pipeline_t pipeline, + void *priv, int error) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + ocf_pipeline_t stop_pipeline; + + if (error) { + _ocf_mngt_activate_handle_error(context); + goto out; + } + + error = ocf_pipeline_create(&stop_pipeline, cache, + &ocf_mngt_cache_stop_pipeline_properties); + if (error) { + _ocf_mngt_activate_handle_error(context); + goto out; + } + + ocf_pipeline_destroy(cache->stop_pipeline); + cache->stop_pipeline = stop_pipeline; + + ocf_volume_deinit(&context->cache_volume); + +out: + context->cmpl(context->cache, context->priv1, context->priv2, error); + + env_vfree(context->cfg.uuid.data); + ocf_pipeline_destroy(context->pipeline); +} + +struct ocf_pipeline_properties _ocf_mngt_cache_activate_pipeline_properties = { + .priv_size = sizeof(struct ocf_cache_attach_context), + .finish = _ocf_mngt_cache_activate_finish, + .steps = { + OCF_PL_STEP(_ocf_mngt_copy_uuid_data), + OCF_PL_STEP(_ocf_mngt_activate_wait_metadata_io), + OCF_PL_STEP(_ocf_mngt_activate_swap_cache_device), + OCF_PL_STEP(_ocf_mngt_activate_check_superblock), + OCF_PL_STEP(_ocf_mngt_activate_compare_superblock), + OCF_PL_STEP(_ocf_mngt_activate_init_properties), + OCF_PL_STEP(_ocf_mngt_test_volume), + 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_post_metadata_load), + OCF_PL_STEP(_ocf_mngt_attach_shutdown_status), + OCF_PL_STEP(_ocf_mngt_attach_post_init), + OCF_PL_STEP_TERMINATOR(), + }, +}; + static void _ocf_mngt_cache_attach(ocf_cache_t cache, struct ocf_mngt_cache_device_config *cfg, _ocf_mngt_cache_attach_end_t cmpl, void *priv1, void *priv2) @@ -2149,6 +2401,35 @@ static void _ocf_mngt_cache_bind(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 *cfg, + _ocf_mngt_cache_attach_end_t cmpl, void *priv1, void *priv2) +{ + struct ocf_cache_attach_context *context; + ocf_pipeline_t pipeline; + int result; + + if (!ocf_cache_is_passive(cache)) + OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_CACHE_EXIST); + + result = ocf_pipeline_create(&pipeline, cache, + &_ocf_mngt_cache_activate_pipeline_properties); + if (result) + 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)) @@ -2444,6 +2725,51 @@ void ocf_mngt_cache_bind(ocf_cache_t cache, cmpl, priv); } +static void _ocf_mngt_cache_activate_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_active(cache); + ocf_cache_log(cache, log_info, "Successfully activated\n"); + + OCF_CMPL_RET(cache, priv2, 0); +} + +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) +{ + int result; + + OCF_CHECK_NULL(cache); + OCF_CHECK_NULL(cfg); + + if (!cache->mngt_queue) + OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); + + /* Activate is not allowed in volatile metadata mode */ + if (cache->metadata.is_volatile) + OCF_CMPL_RET(cache, priv, -OCF_ERR_INVAL); + + /* Activate is not allowed with 'force' flag on */ + if (cfg->force) { + ocf_cache_log(cache, log_err, "Using 'force' flag is forbidden " + "for activate 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_activate(cache, cfg, _ocf_mngt_cache_activate_complete, + cmpl, priv); +} + static void ocf_mngt_cache_stop_detached(ocf_cache_t cache, ocf_mngt_cache_stop_end_t cmpl, void *priv) { From 7d43aae3a0b5e13ccc985c0aa29b56fccc257f43 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 6 Sep 2021 20:44:26 +0200 Subject: [PATCH 26/26] pyocf: Add new error codes Signed-off-by: Robert Baldyga --- tests/functional/pyocf/types/shared.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/functional/pyocf/types/shared.py b/tests/functional/pyocf/types/shared.py index df51257..cdd637b 100644 --- a/tests/functional/pyocf/types/shared.py +++ b/tests/functional/pyocf/types/shared.py @@ -49,6 +49,9 @@ class OcfErrorCode(IntEnum): OCF_ERR_INVALID_CACHE_LINE_SIZE = auto() OCF_ERR_CACHE_NAME_MISMATCH = auto() OCF_ERR_INVAL_CACHE_DEV = auto() + OCF_ERR_CORE_UUID_EXISTS = auto() + OCF_ERR_METADATA_LAYOUT_MISMATCH = auto() + OCF_ERR_CACHE_LINE_SIZE_MISMATCH = auto() class OcfCompletion: