Make switching cleaning policy asynchronous

Making the operation asynchronous will allow to use refcnt utility as an
synchronization mechanism between processing cachelines and deinitializing
cleaning policy.

Signed-off-by: Michal Mielewczyk <michal.mielewczyk@intel.com>
This commit is contained in:
Michal Mielewczyk 2021-07-21 12:51:39 +02:00
parent 26194fc536
commit f33a6e5ce0
2 changed files with 119 additions and 31 deletions

View File

@ -730,6 +730,15 @@ static inline bool ocf_mngt_cache_mode_has_lazy_write(ocf_cache_mode_t mode)
*/ */
int ocf_mngt_cache_set_mode(ocf_cache_t cache, ocf_cache_mode_t mode); int ocf_mngt_cache_set_mode(ocf_cache_t cache, ocf_cache_mode_t mode);
/**
* @brief Completion callback of switch cleaning policy operation
*
* @param[in] priv Callback context
* @param[in] error Error code (zero on success)
*/
typedef void (*ocf_mngt_cache_set_cleaning_policy_end_t)( void *priv,
int error);
/** /**
* @brief Set cleaning policy in given cache * @brief Set cleaning policy in given cache
* *
@ -737,12 +746,14 @@ int ocf_mngt_cache_set_mode(ocf_cache_t cache, ocf_cache_mode_t mode);
* use function ocf_mngt_cache_save(). * use function ocf_mngt_cache_save().
* *
* @param[in] cache Cache handle * @param[in] cache Cache handle
* @param[in] type Cleaning policy type * @param[out] new_policy New cleaning policy
* @param[in] cmpl Completion callback
* @param[in] priv Completion callback context
* *
* @retval 0 Policy has been set successfully
* @retval Non-zero Error occurred and policy has not been set
*/ */
int ocf_mngt_cache_cleaning_set_policy(ocf_cache_t cache, ocf_cleaning_t type); void ocf_mngt_cache_cleaning_set_policy(ocf_cache_t cache,
ocf_cleaning_t new_policy,
ocf_mngt_cache_set_cleaning_policy_end_t cmpl, void *priv);
/** /**
* @brief Get current cleaning policy from given cache * @brief Get current cleaning policy from given cache

View File

@ -901,46 +901,123 @@ void ocf_mngt_cache_flush_interrupt(ocf_cache_t cache)
cache->flushing_interrupted = 1; cache->flushing_interrupted = 1;
} }
int ocf_mngt_cache_cleaning_set_policy(ocf_cache_t cache, ocf_cleaning_t type) struct ocf_mngt_cache_set_cleaning_context
{ {
ocf_cleaning_t old_type; /* pipeline for switching cleaning policy */
int ret = 0; ocf_pipeline_t pipeline;
/* target cache */
ocf_cache_t cache;
/* new cleaning policy */
ocf_cleaning_t new_policy;
/* old cleaning policy */
ocf_cleaning_t old_policy;
/* completion function */
ocf_mngt_cache_set_cleaning_policy_end_t cmpl;
/* completion function */
void *priv;
};
OCF_CHECK_NULL(cache); static void _ocf_mngt_deinit_clean_policy(ocf_pipeline_t pipeline, void *priv,
ocf_pipeline_arg_t arg)
if (type < 0 || type >= ocf_cleaning_max) {
return -OCF_ERR_INVAL; struct ocf_mngt_cache_set_cleaning_context *context = priv;
ocf_cache_t cache = context->cache;
old_type = cache->conf_meta->cleaning_policy_type;
if (type == old_type) {
ocf_cache_log(cache, log_info, "Cleaning policy %s is already "
"set\n", ocf_cleaning_get_name(old_type));
return 0;
}
ocf_metadata_start_exclusive_access(&cache->metadata.lock); ocf_metadata_start_exclusive_access(&cache->metadata.lock);
ocf_cleaning_deinitialize(cache); ocf_cleaning_deinitialize(cache);
if (ocf_cleaning_initialize(cache, type, 1)) { ocf_pipeline_next(context->pipeline);
/* }
* If initialization of new cleaning policy failed,
* we set cleaning policy to nop. static void _ocf_mngt_init_clean_policy(ocf_pipeline_t pipeline, void *priv,
*/ ocf_pipeline_arg_t arg)
type = ocf_cleaning_nop; {
ret = -OCF_ERR_INVAL; int result;
struct ocf_mngt_cache_set_cleaning_context *context = priv;
ocf_cache_t cache = context->cache;
ocf_cleaning_t old_policy = context->old_policy;
ocf_cleaning_t new_policy = context->new_policy;
ocf_cleaning_t emergency_policy = ocf_cleaning_nop;
result = ocf_cleaning_initialize(cache, new_policy, 1);
if (result) {
ocf_cache_log(cache, log_info, "Failed to initialize %s cleaning "
"policy. Setting %s instead\n",
ocf_cleaning_get_name(new_policy),
ocf_cleaning_get_name(emergency_policy));
new_policy = emergency_policy;
} else {
ocf_cache_log(cache, log_info, "Changing cleaning policy from "
"%s to %s\n", ocf_cleaning_get_name(old_policy),
ocf_cleaning_get_name(new_policy));
} }
cache->conf_meta->cleaning_policy_type = type; cache->conf_meta->cleaning_policy_type = new_policy;
ocf_metadata_end_exclusive_access(&cache->metadata.lock); ocf_metadata_end_exclusive_access(&cache->metadata.lock);
ocf_cache_log(cache, log_info, "Changing cleaning policy from " OCF_PL_NEXT_ON_SUCCESS_RET(pipeline, result);
"%s to %s\n", ocf_cleaning_get_name(old_type), }
ocf_cleaning_get_name(type));
return ret; static void _ocf_mngt_set_cleaning_finish(ocf_pipeline_t pipeline, void *priv,
int error)
{
struct ocf_mngt_cache_set_cleaning_context *context = priv;
context->cmpl(context->priv, error);
ocf_pipeline_destroy(pipeline);
}
static
struct ocf_pipeline_properties _ocf_mngt_cache_set_cleaning_policy = {
.priv_size = sizeof(struct ocf_mngt_cache_set_cleaning_context),
.finish = _ocf_mngt_set_cleaning_finish,
.steps = {
OCF_PL_STEP(_ocf_mngt_deinit_clean_policy),
OCF_PL_STEP(_ocf_mngt_init_clean_policy),
OCF_PL_STEP_TERMINATOR(),
},
};
void ocf_mngt_cache_cleaning_set_policy(ocf_cache_t cache,
ocf_cleaning_t new_policy,
ocf_mngt_cache_set_cleaning_policy_end_t cmpl, void *priv)
{
struct ocf_mngt_cache_set_cleaning_context *context;
ocf_pipeline_t pipeline;
ocf_cleaning_t old_policy;
int ret = 0;
OCF_CHECK_NULL(cache);
if (new_policy < 0 || new_policy >= ocf_cleaning_max)
OCF_CMPL_RET(priv, -OCF_ERR_INVAL);
old_policy = cache->conf_meta->cleaning_policy_type;
if (new_policy == old_policy) {
ocf_cache_log(cache, log_info, "Cleaning policy %s is already "
"set\n", ocf_cleaning_get_name(old_policy));
OCF_CMPL_RET(priv, 0);
}
ret = ocf_pipeline_create(&pipeline, cache,
&_ocf_mngt_cache_set_cleaning_policy);
if (ret)
OCF_CMPL_RET(priv, ret);
context = ocf_pipeline_get_priv(pipeline);
context->cmpl = cmpl;
context->cache = cache;
context->pipeline = pipeline;
context->new_policy = new_policy;
context->old_policy = old_policy;
context->priv = priv;
OCF_PL_NEXT_RET(pipeline);
} }
int ocf_mngt_cache_cleaning_get_policy(ocf_cache_t cache, ocf_cleaning_t *type) int ocf_mngt_cache_cleaning_get_policy(ocf_cache_t cache, ocf_cleaning_t *type)