From 5a88ab2d611d95ab4313e5a7c443d09f44d8e0f7 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 19 Jan 2021 13:19:32 +0100 Subject: [PATCH] Flush metadata collision segment on core remove If there is any dirty data on the cache associated with removed core, we must flush collision metadata after removing core to make metadata persistent in case of dirty shutdown. This fixes the problem when recovery procedure erroneously interprets cache lines that belonged to removed core as valid ones. This also fixes the problem, when after removing core containing dirty data another core is added, and then recovery procedure following dirty shutdown assigns cache lines from removed core to the new one, effectively leading to data corruption. Signed-off-by: Robert Baldyga --- src/metadata/metadata.c | 17 +++++++++++++++++ src/metadata/metadata.h | 10 ++++++++++ src/mngt/ocf_mngt_core.c | 33 +++++++++++++++++++++++++-------- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 537f8e0..4300031 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1024,6 +1024,23 @@ void ocf_metadata_flush_all(ocf_cache_t cache, ocf_pipeline_next(pipeline); } +/* + * Flush collision metadata + */ +void ocf_metadata_flush_collision(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *priv) +{ + struct ocf_metadata_ctrl *ctrl; + struct ocf_metadata_raw *raw; + + OCF_DEBUG_TRACE(cache); + + ctrl = cache->metadata.priv; + raw = &ctrl->raw_desc[metadata_segment_collision]; + + ocf_metadata_raw_flush_all(cache, raw, cmpl, priv); +} + /* * Flush specified cache line */ diff --git a/src/metadata/metadata.h b/src/metadata/metadata.h index 5507b08..a72a927 100644 --- a/src/metadata/metadata.h +++ b/src/metadata/metadata.h @@ -123,6 +123,16 @@ ocf_cache_line_t ocf_metadata_get_pages_count(struct ocf_cache *cache); void ocf_metadata_flush_all(ocf_cache_t cache, ocf_metadata_end_t cmpl, void *priv); +/** + * @brief Flush metadata collision segment + * + * @param cache - Cache instance + * @param cmpl - Completion callback + * @param priv - Completion context + */ +void ocf_metadata_flush_collision(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *priv); + /** * @brief Mark specified cache line to be flushed * diff --git a/src/mngt/ocf_mngt_core.c b/src/mngt/ocf_mngt_core.c index 58b30cf..1dd5cb9 100644 --- a/src/mngt/ocf_mngt_core.c +++ b/src/mngt/ocf_mngt_core.c @@ -603,7 +603,7 @@ static void ocf_mngt_cache_remove_core_finish(ocf_pipeline_t pipeline, ocf_pipeline_destroy(context->pipeline); } -static void ocf_mngt_cache_remove_core_flush_sb_complete(void *priv, int error) +static void ocf_mngt_cache_remove_core_flush_meta_complete(void *priv, int error) { struct ocf_mngt_cache_remove_core_context *context = priv; @@ -611,6 +611,27 @@ static void ocf_mngt_cache_remove_core_flush_sb_complete(void *priv, int error) OCF_PL_NEXT_ON_SUCCESS_RET(context->pipeline, error); } +static void _ocf_mngt_cache_remove_core_attached(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_mngt_cache_remove_core_context *context = priv; + ocf_cache_t cache = context->cache; + ocf_core_t core = context->core; + + if (!ocf_cache_is_device_attached(cache)) + OCF_PL_NEXT_RET(pipeline); + + cache_mngt_core_deinit_attached_meta(core); + cache_mngt_core_remove_from_cleaning_pol(core); + + if (env_atomic_read(&core->runtime_meta->dirty_clines) == 0) + OCF_PL_NEXT_RET(pipeline); + + ocf_metadata_flush_collision(cache, + ocf_mngt_cache_remove_core_flush_meta_complete, + context); +} + static void _ocf_mngt_cache_remove_core(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { @@ -620,18 +641,13 @@ static void _ocf_mngt_cache_remove_core(ocf_pipeline_t pipeline, void *priv, ocf_core_log(core, log_debug, "Removing core\n"); - /* Deinit everything*/ - if (ocf_cache_is_device_attached(cache)) { - cache_mngt_core_deinit_attached_meta(core); - cache_mngt_core_remove_from_cleaning_pol(core); - } cache_mngt_core_remove_from_meta(core); cache_mngt_core_remove_from_cache(core); cache_mngt_core_deinit(core); - /* Update super-block with core device removal */ ocf_metadata_flush_superblock(cache, - ocf_mngt_cache_remove_core_flush_sb_complete, context); + ocf_mngt_cache_remove_core_flush_meta_complete, + context); } static void ocf_mngt_cache_remove_core_wait_cleaning_complete(void *priv) @@ -660,6 +676,7 @@ struct ocf_pipeline_properties ocf_mngt_cache_remove_core_pipeline_props = { .finish = ocf_mngt_cache_remove_core_finish, .steps = { OCF_PL_STEP(ocf_mngt_cache_remove_core_wait_cleaning), + OCF_PL_STEP(_ocf_mngt_cache_remove_core_attached), OCF_PL_STEP(_ocf_mngt_cache_remove_core), OCF_PL_STEP_TERMINATOR(), },