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:
parent
26194fc536
commit
f33a6e5ce0
@ -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
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user