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 <robert.baldyga@intel.com>
This commit is contained in:
Robert Baldyga
2021-01-19 13:19:32 +01:00
parent 3f7139a814
commit 5a88ab2d61
3 changed files with 52 additions and 8 deletions

View File

@@ -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(),
},