Async wait for cleaner completion

Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski
2019-04-11 13:16:16 -04:00
parent 0e15c693fd
commit 348b0f9ab8
7 changed files with 281 additions and 144 deletions

View File

@@ -560,32 +560,14 @@ err_pipeline:
OCF_CMPL_RET(cache, NULL, priv, result);
}
/*
* Synchronously wait until cleaning triggered by eviction finishes.
* TODO: Replace it with asynchronous mechanism.
*/
static int _ocf_cleaning_wait_for_finish(ocf_cache_t cache, int32_t timeout_ms)
{
if (!ocf_cache_is_device_attached(cache))
return 0;
while (ocf_cache_has_pending_cleaning(cache)) {
env_msleep(20);
timeout_ms -= 20;
if (timeout_ms <= 0)
return -EBUSY;
}
return 0;
}
struct ocf_mngt_cache_remove_core_context {
ocf_mngt_cache_remove_core_end_t cmpl;
void *priv;
ocf_pipeline_t pipeline;
ocf_cache_t cache;
ocf_core_t core;
const char *core_name;
struct ocf_cleaner_wait_context cleaner_wait;
};
static void ocf_mngt_cache_remove_core_finish(ocf_pipeline_t pipeline,
@@ -602,19 +584,13 @@ static void ocf_mngt_cache_remove_core_finish(ocf_pipeline_t pipeline,
context->core_name);
}
ocf_cleaner_refcnt_unfreeze(cache);
context->cmpl(context->priv, error);
ocf_pipeline_destroy(context->pipeline);
}
struct ocf_pipeline_properties ocf_mngt_cache_remove_core_pipeline_props = {
.priv_size = sizeof(struct ocf_mngt_cache_remove_core_context),
.finish = ocf_mngt_cache_remove_core_finish,
.steps = {
OCF_PL_STEP_TERMINATOR(),
},
};
static void ocf_mngt_cache_remove_core_flush_sb_complete(void *priv, int error)
{
struct ocf_mngt_cache_remove_core_context *context = priv;
@@ -623,39 +599,13 @@ static void ocf_mngt_cache_remove_core_flush_sb_complete(void *priv, int error)
error ? -OCF_ERR_WRITE_CACHE : 0);
}
void ocf_mngt_cache_remove_core(ocf_core_t core,
ocf_mngt_cache_remove_core_end_t cmpl, void *priv)
static void _ocf_mngt_cache_remove_core(ocf_pipeline_t pipeline, void *priv,
ocf_pipeline_arg_t arg)
{
struct ocf_mngt_cache_remove_core_context *context;
ocf_pipeline_t pipeline;
ocf_cache_t cache;
ocf_core_id_t core_id;
int result;
OCF_CHECK_NULL(core);
cache = ocf_core_get_cache(core);
core_id = ocf_core_get_id(core);
if (!cache->mngt_queue)
OCF_CMPL_RET(cache, -OCF_ERR_INVAL);
/* TODO: Make this asynchronous */
if (_ocf_cleaning_wait_for_finish(cache, 60 * 1000))
OCF_CMPL_RET(priv, -OCF_ERR_CACHE_IN_USE);
result = ocf_pipeline_create(&pipeline, cache,
&ocf_mngt_cache_remove_core_pipeline_props);
if (result)
OCF_CMPL_RET(priv, result);
context = ocf_pipeline_get_priv(pipeline);
context->cmpl = cmpl;
context->priv = priv;
context->pipeline = pipeline;
context->cache = cache;
context->core_name = ocf_core_get_name(core);
struct ocf_mngt_cache_remove_core_context *context = priv;
ocf_cache_t cache = context->cache;
ocf_core_t core = context->core;
ocf_core_id_t core_id = ocf_core_get_id(core);
ocf_core_log(core, log_debug, "Removing core\n");
@@ -675,53 +625,183 @@ void ocf_mngt_cache_remove_core(ocf_core_t core,
ocf_mngt_cache_remove_core_flush_sb_complete, context);
}
static int _ocf_mngt_cache_detach_core(ocf_core_t core)
static void ocf_mngt_cache_remove_core_wait_cleaning_complete(void *priv)
{
struct ocf_cache *cache = core->volume.cache;
ocf_core_id_t core_id = ocf_core_get_id(core);
int status;
status = cache_mng_core_close(cache, core_id);
if (!status) {
cache->ocf_core_inactive_count++;
env_bit_set(ocf_cache_state_incomplete,
&cache->cache_state);
}
return status;
ocf_pipeline_t pipeline = priv;
ocf_pipeline_next(pipeline);
}
void ocf_mngt_cache_detach_core(ocf_core_t core,
ocf_mngt_cache_detach_core_end_t cmpl, void *priv)
static void ocf_mngt_cache_remove_core_wait_cleaning(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;
if (!ocf_cache_is_device_attached(cache))
OCF_PL_NEXT_RET(pipeline);
ocf_cleaner_refcnt_freeze(cache);
ocf_cleaner_refcnt_register_zero_cb(cache, &context->cleaner_wait,
ocf_mngt_cache_remove_core_wait_cleaning_complete,
pipeline);
}
struct ocf_pipeline_properties ocf_mngt_cache_remove_core_pipeline_props = {
.priv_size = sizeof(struct ocf_mngt_cache_remove_core_context),
.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),
OCF_PL_STEP_TERMINATOR(),
},
};
void ocf_mngt_cache_remove_core(ocf_core_t core,
ocf_mngt_cache_remove_core_end_t cmpl, void *priv)
{
struct ocf_mngt_cache_remove_core_context *context;
ocf_pipeline_t pipeline;
ocf_cache_t cache;
const char *core_name;
int result;
OCF_CHECK_NULL(core);
cache = ocf_core_get_cache(core);
core_name = ocf_core_get_name(core);
if (!cache->mngt_queue)
OCF_CMPL_RET(cache, -OCF_ERR_INVAL);
/* TODO: Make this asynchronous */
if (_ocf_cleaning_wait_for_finish(cache, 60 * 1000))
OCF_CMPL_RET(priv, -OCF_ERR_CACHE_IN_USE);
result = ocf_pipeline_create(&pipeline, cache,
&ocf_mngt_cache_remove_core_pipeline_props);
if (result)
OCF_CMPL_RET(priv, result);
context = ocf_pipeline_get_priv(pipeline);
context->cmpl = cmpl;
context->priv = priv;
context->pipeline = pipeline;
context->cache = cache;
context->core = core;
context->core_name = ocf_core_get_name(core);
ocf_pipeline_next(pipeline);
}
struct ocf_mngt_cache_detach_core_context {
ocf_mngt_cache_detach_core_end_t cmpl;
void *priv;
ocf_pipeline_t pipeline;
ocf_cache_t cache;
ocf_core_t core;
const char *core_name;
struct ocf_cleaner_wait_context cleaner_wait;
};
static void _ocf_mngt_cache_detach_core(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;
ocf_core_id_t core_id = ocf_core_get_id(core);
int status;
ocf_core_log(core, log_debug, "Detaching core\n");
result = _ocf_mngt_cache_detach_core(core);
if (!result) {
status = cache_mng_core_close(cache, core_id);
if (status)
OCF_PL_FINISH_RET(pipeline, status);
cache->ocf_core_inactive_count++;
env_bit_set(ocf_cache_state_incomplete,
&cache->cache_state);
ocf_pipeline_next(pipeline);
}
static void ocf_mngt_cache_detach_core_finish(ocf_pipeline_t pipeline,
void *priv, int error)
{
struct ocf_mngt_cache_remove_core_context *context = priv;
ocf_cache_t cache = context->cache;
if (!error) {
ocf_cache_log(cache, log_info, "Core %s successfully detached\n",
core_name);
context->core_name);
} else {
ocf_cache_log(cache, log_err, "Detaching core %s failed\n",
core_name);
context->core_name);
}
OCF_CMPL_RET(priv, result);
ocf_cleaner_refcnt_unfreeze(context->cache);
context->cmpl(context->priv, error);
ocf_pipeline_destroy(context->pipeline);
}
static void ocf_mngt_cache_detach_core_wait_cleaning_complete(void *priv)
{
ocf_pipeline_t pipeline = priv;
ocf_pipeline_next(pipeline);
}
static void ocf_mngt_cache_detach_core_wait_cleaning(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;
if (!ocf_cache_is_device_attached(cache))
OCF_PL_NEXT_RET(pipeline);
ocf_cleaner_refcnt_freeze(cache);
ocf_cleaner_refcnt_register_zero_cb(cache, &context->cleaner_wait,
ocf_mngt_cache_detach_core_wait_cleaning_complete,
pipeline);
}
struct ocf_pipeline_properties ocf_mngt_cache_detach_core_pipeline_props = {
.priv_size = sizeof(struct ocf_mngt_cache_detach_core_context),
.finish = ocf_mngt_cache_detach_core_finish,
.steps = {
OCF_PL_STEP(ocf_mngt_cache_detach_core_wait_cleaning),
OCF_PL_STEP(_ocf_mngt_cache_detach_core),
OCF_PL_STEP_TERMINATOR(),
},
};
void ocf_mngt_cache_detach_core(ocf_core_t core,
ocf_mngt_cache_detach_core_end_t cmpl, void *priv)
{
struct ocf_mngt_cache_detach_core_context *context;
ocf_pipeline_t pipeline;
ocf_cache_t cache;
int result;
OCF_CHECK_NULL(core);
cache = ocf_core_get_cache(core);
if (!cache->mngt_queue)
OCF_CMPL_RET(cache, -OCF_ERR_INVAL);
result = ocf_pipeline_create(&pipeline, cache,
&ocf_mngt_cache_detach_core_pipeline_props);
if (result)
OCF_CMPL_RET(priv, result);
context = ocf_pipeline_get_priv(pipeline);
context->cmpl = cmpl;
context->priv = priv;
context->pipeline = pipeline;
context->cache = ocf_core_get_cache(core);
context->core = core;
context->core_name = ocf_core_get_name(core);
ocf_pipeline_next(pipeline);
}
int ocf_mngt_core_set_uuid(ocf_core_t core, const struct ocf_volume_uuid *uuid)