From b83da68f85110fa782cb46ce78584ab3ddae5367 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Tue, 20 Jul 2021 10:49:30 +0200 Subject: [PATCH] Cleaner context ref counter To prevent deinitializing cleaner context (i.e. during switching policy) during processing requests, access to cleaner should be protected with reference counter Signed-off-by: Michal Mielewczyk --- src/cleaning/cleaning.h | 2 ++ src/cleaning/cleaning_ops.h | 48 ++++++++++++++++++++++++++++++++++++- src/mngt/ocf_mngt_cache.c | 2 ++ src/mngt/ocf_mngt_flush.c | 17 ++++++++++--- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/cleaning/cleaning.h b/src/cleaning/cleaning.h index 6a73cae..007dac0 100644 --- a/src/cleaning/cleaning.h +++ b/src/cleaning/cleaning.h @@ -10,6 +10,7 @@ #include "nop_structs.h" #include "acp_structs.h" #include "ocf/ocf_cleaner.h" +#include "../utils/utils_refcnt.h" #define CLEANING_POLICY_CONFIG_BYTES 256 #define CLEANING_POLICY_TYPE_MAX 4 @@ -39,6 +40,7 @@ struct cleaning_policy_meta { }; struct ocf_cleaner { + struct ocf_refcnt refcnt __attribute__((aligned(64))); void *cleaning_policy_context; ocf_queue_t io_queue; ocf_cleaner_end_t end; diff --git a/src/cleaning/cleaning_ops.h b/src/cleaning/cleaning_ops.h index 6210d27..f700dc8 100644 --- a/src/cleaning/cleaning_ops.h +++ b/src/cleaning/cleaning_ops.h @@ -9,6 +9,7 @@ #include "../metadata/metadata_superblock.h" #include "../metadata/metadata_structs.h" #include "../ocf_cache_priv.h" +#include "../utils/utils_refcnt.h" struct cleaning_policy_ops { void (*setup)(ocf_cache_t cache); @@ -104,6 +105,10 @@ static inline int ocf_cleaning_add_core(ocf_cache_t cache, ocf_core_id_t core_id) { ocf_cleaning_t policy; + int result = 0; + + if (unlikely(!ocf_refcnt_inc(&cache->cleaner.refcnt))) + return -OCF_ERR_NO_LOCK; policy = cache->conf_meta->cleaning_policy_type; @@ -112,7 +117,12 @@ static inline int ocf_cleaning_add_core(ocf_cache_t cache, if (unlikely(!cleaning_policy_ops[policy].add_core)) goto unlock; - return cleaning_policy_ops[policy].add_core(cache, core_id); + result = cleaning_policy_ops[policy].add_core(cache, core_id); + +unlock: + ocf_refcnt_dec(&cache->cleaner.refcnt); + + return result; } static inline void ocf_cleaning_remove_core(ocf_cache_t cache, @@ -120,6 +130,9 @@ static inline void ocf_cleaning_remove_core(ocf_cache_t cache, { ocf_cleaning_t policy; + if (unlikely(!ocf_refcnt_inc(&cache->cleaner.refcnt))) + return; + policy = cache->conf_meta->cleaning_policy_type; ENV_BUG_ON(policy >= ocf_cleaning_max); @@ -128,6 +141,9 @@ static inline void ocf_cleaning_remove_core(ocf_cache_t cache, goto unlock; cleaning_policy_ops[policy].remove_core(cache, core_id); + +unlock: + ocf_refcnt_dec(&cache->cleaner.refcnt); } static inline void ocf_cleaning_init_cache_block(ocf_cache_t cache, @@ -135,6 +151,9 @@ static inline void ocf_cleaning_init_cache_block(ocf_cache_t cache, { ocf_cleaning_t policy; + if (unlikely(!ocf_refcnt_inc(&cache->cleaner.refcnt))) + return; + policy = cache->conf_meta->cleaning_policy_type; ENV_BUG_ON(policy >= ocf_cleaning_max); @@ -142,6 +161,9 @@ static inline void ocf_cleaning_init_cache_block(ocf_cache_t cache, goto unlock; cleaning_policy_ops[policy].init_cache_block(cache, cache_line); + +unlock: + ocf_refcnt_dec(&cache->cleaner.refcnt); } static inline void ocf_cleaning_purge_cache_block(ocf_cache_t cache, @@ -149,6 +171,9 @@ static inline void ocf_cleaning_purge_cache_block(ocf_cache_t cache, { ocf_cleaning_t policy; + if (unlikely(!ocf_refcnt_inc(&cache->cleaner.refcnt))) + return; + policy = cache->conf_meta->cleaning_policy_type; ENV_BUG_ON(policy >= ocf_cleaning_max); @@ -156,6 +181,9 @@ static inline void ocf_cleaning_purge_cache_block(ocf_cache_t cache, goto unlock; cleaning_policy_ops[policy].purge_cache_block(cache, cache_line); + +unlock: + ocf_refcnt_dec(&cache->cleaner.refcnt); } static inline void ocf_cleaning_purge_range(ocf_cache_t cache, @@ -163,6 +191,9 @@ static inline void ocf_cleaning_purge_range(ocf_cache_t cache, { ocf_cleaning_t policy; + if (unlikely(!ocf_refcnt_inc(&cache->cleaner.refcnt))) + return; + policy = cache->conf_meta->cleaning_policy_type; ENV_BUG_ON(policy >= ocf_cleaning_max); @@ -171,6 +202,9 @@ static inline void ocf_cleaning_purge_range(ocf_cache_t cache, cleaning_policy_ops[policy].purge_range(cache, core_id, start_byte, end_byte); + +unlock: + ocf_refcnt_dec(&cache->cleaner.refcnt); } static inline void ocf_cleaning_set_hot_cache_line(ocf_cache_t cache, @@ -178,6 +212,9 @@ static inline void ocf_cleaning_set_hot_cache_line(ocf_cache_t cache, { ocf_cleaning_t policy; + if (unlikely(!ocf_refcnt_inc(&cache->cleaner.refcnt))) + return; + policy = cache->conf_meta->cleaning_policy_type; ENV_BUG_ON(policy >= ocf_cleaning_max); @@ -185,6 +222,9 @@ static inline void ocf_cleaning_set_hot_cache_line(ocf_cache_t cache, goto unlock; cleaning_policy_ops[policy].set_hot_cache_line(cache, cache_line); + +unlock: + ocf_refcnt_dec(&cache->cleaner.refcnt); } static inline int ocf_cleaning_set_param(ocf_cache_t cache, @@ -216,6 +256,9 @@ static inline void ocf_cleaning_perform_cleaning(ocf_cache_t cache, { ocf_cleaning_t policy; + if (unlikely(!ocf_refcnt_inc(&cache->cleaner.refcnt))) + return; + policy = cache->conf_meta->cleaning_policy_type; ENV_BUG_ON(policy >= ocf_cleaning_max); @@ -223,6 +266,9 @@ static inline void ocf_cleaning_perform_cleaning(ocf_cache_t cache, goto unlock; cleaning_policy_ops[policy].perform_cleaning(cache, cmpl); + +unlock: + ocf_refcnt_dec(&cache->cleaner.refcnt); } static inline const char *ocf_cleaning_get_name(ocf_cleaning_t policy) diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index b9d60cc..54a2a67 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -205,6 +205,8 @@ static ocf_error_t __init_cleaning_policy(ocf_cache_t cache) OCF_ASSERT_PLUGGED(cache); + ocf_refcnt_init(&cache->cleaner.refcnt); + for (i = 0; i < ocf_cleaning_max; i++) ocf_cleaning_setup(cache, i); diff --git a/src/mngt/ocf_mngt_flush.c b/src/mngt/ocf_mngt_flush.c index afa365d..afa1ab7 100644 --- a/src/mngt/ocf_mngt_flush.c +++ b/src/mngt/ocf_mngt_flush.c @@ -917,6 +917,16 @@ struct ocf_mngt_cache_set_cleaning_context void *priv; }; +static void _ocf_mngt_cleaning_deinit_complete(void *priv) +{ + struct ocf_mngt_cache_set_cleaning_context *context = priv; + ocf_cache_t cache = context->cache; + + ocf_cleaning_deinitialize(cache); + + ocf_pipeline_next(context->pipeline); +} + static void _ocf_mngt_deinit_clean_policy(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { @@ -925,9 +935,9 @@ static void _ocf_mngt_deinit_clean_policy(ocf_pipeline_t pipeline, void *priv, ocf_metadata_start_exclusive_access(&cache->metadata.lock); - ocf_cleaning_deinitialize(cache); - - ocf_pipeline_next(context->pipeline); + ocf_refcnt_freeze(&cache->cleaner.refcnt); + ocf_refcnt_register_zero_cb(&cache->cleaner.refcnt, + _ocf_mngt_cleaning_deinit_complete, context); } static void _ocf_mngt_init_clean_policy(ocf_pipeline_t pipeline, void *priv, @@ -955,6 +965,7 @@ static void _ocf_mngt_init_clean_policy(ocf_pipeline_t pipeline, void *priv, cache->conf_meta->cleaning_policy_type = new_policy; + ocf_refcnt_unfreeze(&cache->cleaner.refcnt); ocf_metadata_end_exclusive_access(&cache->metadata.lock); OCF_PL_NEXT_ON_SUCCESS_RET(pipeline, result);