Merge pull request #332 from mmichal10/stop-pipeline-in-cache
Keep stop pipeline in struct cache.
This commit is contained in:
commit
1ec0a5c053
@ -1153,6 +1153,8 @@ static void _ocf_mngt_attach_handle_error(
|
|||||||
|
|
||||||
if (context->flags.device_alloc)
|
if (context->flags.device_alloc)
|
||||||
env_vfree(cache->device);
|
env_vfree(cache->device);
|
||||||
|
|
||||||
|
ocf_pipeline_destroy(cache->stop_pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _ocf_mngt_cache_init(ocf_cache_t cache,
|
static void _ocf_mngt_cache_init(ocf_cache_t cache,
|
||||||
@ -1304,7 +1306,7 @@ static void _ocf_mngt_attach_load_superblock_complete(void *priv, int error)
|
|||||||
ocf_cache_t cache = context->cache;
|
ocf_cache_t cache = context->cache;
|
||||||
|
|
||||||
if (cache->conf_meta->cachelines !=
|
if (cache->conf_meta->cachelines !=
|
||||||
ocf_metadata_get_cachelines_count(cache)) {
|
ocf_metadata_get_cachelines_count(cache)) {
|
||||||
ocf_cache_log(cache, log_err,
|
ocf_cache_log(cache, log_err,
|
||||||
"ERROR: Cache device size mismatch!\n");
|
"ERROR: Cache device size mismatch!\n");
|
||||||
OCF_PL_FINISH_RET(context->pipeline,
|
OCF_PL_FINISH_RET(context->pipeline,
|
||||||
@ -1539,6 +1541,207 @@ struct ocf_pipeline_properties _ocf_mngt_cache_attach_pipeline_properties = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void (*_ocf_mngt_cache_unplug_end_t)(void *context, int error);
|
||||||
|
|
||||||
|
struct _ocf_mngt_cache_unplug_context {
|
||||||
|
_ocf_mngt_cache_unplug_end_t cmpl;
|
||||||
|
void *priv;
|
||||||
|
ocf_cache_t cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ocf_mngt_cache_stop_context {
|
||||||
|
/* unplug context - this is private structure of _ocf_mngt_cache_unplug,
|
||||||
|
* it is member of stop context only to reserve memory in advance for
|
||||||
|
* _ocf_mngt_cache_unplug, eliminating the possibility of ENOMEM error
|
||||||
|
* at the point where we are effectively unable to handle it */
|
||||||
|
struct _ocf_mngt_cache_unplug_context unplug_context;
|
||||||
|
|
||||||
|
ocf_mngt_cache_stop_end_t cmpl;
|
||||||
|
void *priv;
|
||||||
|
ocf_pipeline_t pipeline;
|
||||||
|
ocf_cache_t cache;
|
||||||
|
ocf_ctx_t ctx;
|
||||||
|
char cache_name[OCF_CACHE_NAME_SIZE];
|
||||||
|
int cache_write_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_stop_wait_metadata_io_finish(void *priv)
|
||||||
|
{
|
||||||
|
struct ocf_mngt_cache_stop_context *context = priv;
|
||||||
|
|
||||||
|
ocf_pipeline_next(context->pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_stop_wait_metadata_io(ocf_pipeline_t pipeline,
|
||||||
|
void *priv, ocf_pipeline_arg_t arg)
|
||||||
|
{
|
||||||
|
struct ocf_mngt_cache_stop_context *context = priv;
|
||||||
|
ocf_cache_t cache = context->cache;
|
||||||
|
|
||||||
|
ocf_refcnt_freeze(&cache->refcnt.metadata);
|
||||||
|
ocf_refcnt_register_zero_cb(&cache->refcnt.metadata,
|
||||||
|
ocf_mngt_cache_stop_wait_metadata_io_finish, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ocf_mngt_cache_stop_remove_cores(ocf_cache_t cache, bool attached)
|
||||||
|
{
|
||||||
|
ocf_core_t core;
|
||||||
|
ocf_core_id_t core_id;
|
||||||
|
int no = cache->conf_meta->core_count;
|
||||||
|
|
||||||
|
/* All exported objects removed, cleaning up rest. */
|
||||||
|
for_each_core_all(cache, core, core_id) {
|
||||||
|
if (!env_bit_test(core_id, cache->conf_meta->valid_core_bitmap))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cache_mngt_core_remove_from_cache(core);
|
||||||
|
if (attached)
|
||||||
|
cache_mngt_core_remove_from_cleaning_pol(core);
|
||||||
|
cache_mngt_core_close(core);
|
||||||
|
if (--no == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ENV_BUG_ON(cache->conf_meta->core_count != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_stop_remove_cores(ocf_pipeline_t pipeline,
|
||||||
|
void *priv, ocf_pipeline_arg_t arg)
|
||||||
|
{
|
||||||
|
struct ocf_mngt_cache_stop_context *context = priv;
|
||||||
|
ocf_cache_t cache = context->cache;
|
||||||
|
|
||||||
|
_ocf_mngt_cache_stop_remove_cores(cache, true);
|
||||||
|
|
||||||
|
ocf_pipeline_next(pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_stop_unplug_complete(void *priv, int error)
|
||||||
|
{
|
||||||
|
struct ocf_mngt_cache_stop_context *context = priv;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
ENV_BUG_ON(error != -OCF_ERR_WRITE_CACHE);
|
||||||
|
context->cache_write_error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocf_pipeline_next(context->pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ocf_mngt_cache_unplug(ocf_cache_t cache, bool stop,
|
||||||
|
struct _ocf_mngt_cache_unplug_context *context,
|
||||||
|
_ocf_mngt_cache_unplug_end_t cmpl, void *priv);
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_stop_unplug(ocf_pipeline_t pipeline,
|
||||||
|
void *priv, ocf_pipeline_arg_t arg)
|
||||||
|
{
|
||||||
|
struct ocf_mngt_cache_stop_context *context = priv;
|
||||||
|
ocf_cache_t cache = context->cache;
|
||||||
|
|
||||||
|
_ocf_mngt_cache_unplug(cache, true, &context->unplug_context,
|
||||||
|
ocf_mngt_cache_stop_unplug_complete, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ocf_mngt_cache_put_io_queues(ocf_cache_t cache)
|
||||||
|
{
|
||||||
|
ocf_queue_t queue, tmp_queue;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(queue, tmp_queue, &cache->io_queues, list)
|
||||||
|
ocf_queue_put(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_stop_put_io_queues(ocf_pipeline_t pipeline,
|
||||||
|
void *priv, ocf_pipeline_arg_t arg)
|
||||||
|
{
|
||||||
|
struct ocf_mngt_cache_stop_context *context = priv;
|
||||||
|
ocf_cache_t cache = context->cache;
|
||||||
|
|
||||||
|
_ocf_mngt_cache_put_io_queues(cache);
|
||||||
|
|
||||||
|
ocf_pipeline_next(pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_remove(ocf_ctx_t ctx, ocf_cache_t cache)
|
||||||
|
{
|
||||||
|
/* Mark device uninitialized */
|
||||||
|
ocf_refcnt_freeze(&cache->refcnt.cache);
|
||||||
|
|
||||||
|
/* Deinitialize locks */
|
||||||
|
ocf_mngt_cache_lock_deinit(cache);
|
||||||
|
env_mutex_destroy(&cache->flush_mutex);
|
||||||
|
|
||||||
|
/* Remove cache from the list */
|
||||||
|
env_rmutex_lock(&ctx->lock);
|
||||||
|
list_del(&cache->list);
|
||||||
|
env_rmutex_unlock(&ctx->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_mngt_cache_stop_finish(ocf_pipeline_t pipeline,
|
||||||
|
void *priv, int error)
|
||||||
|
{
|
||||||
|
struct ocf_mngt_cache_stop_context *context = priv;
|
||||||
|
ocf_cache_t cache = context->cache;
|
||||||
|
ocf_ctx_t ctx = context->ctx;
|
||||||
|
int pipeline_error;
|
||||||
|
ocf_mngt_cache_stop_end_t pipeline_cmpl;
|
||||||
|
void *completion_priv;
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
ocf_mngt_cache_remove(context->ctx, cache);
|
||||||
|
} else {
|
||||||
|
/* undo metadata counter freeze */
|
||||||
|
ocf_refcnt_unfreeze(&cache->refcnt.metadata);
|
||||||
|
|
||||||
|
env_bit_clear(ocf_cache_state_stopping, &cache->cache_state);
|
||||||
|
env_bit_set(ocf_cache_state_running, &cache->cache_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
if (!context->cache_write_error) {
|
||||||
|
ocf_log(ctx, log_info,
|
||||||
|
"Cache %s successfully stopped\n",
|
||||||
|
context->cache_name);
|
||||||
|
} else {
|
||||||
|
ocf_log(ctx, log_warn, "Stopped cache %s with errors\n",
|
||||||
|
context->cache_name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ocf_log(ctx, log_err, "Stopping cache %s failed\n",
|
||||||
|
context->cache_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: Destroying pipeline before completing management operation is a
|
||||||
|
* temporary workaround for insufficient object lifetime management in pyocf
|
||||||
|
* Context must not be referenced after destroying pipeline as this is
|
||||||
|
* typically freed upon pipeline destroy.
|
||||||
|
*/
|
||||||
|
pipeline_error = error ?: context->cache_write_error;
|
||||||
|
pipeline_cmpl = context->cmpl;
|
||||||
|
completion_priv = context->priv;
|
||||||
|
|
||||||
|
ocf_pipeline_destroy(context->pipeline);
|
||||||
|
|
||||||
|
pipeline_cmpl(cache, completion_priv, pipeline_error);
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
/* Finally release cache instance */
|
||||||
|
ocf_mngt_cache_put(cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ocf_pipeline_properties ocf_mngt_cache_stop_pipeline_properties = {
|
||||||
|
.priv_size = sizeof(struct ocf_mngt_cache_stop_context),
|
||||||
|
.finish = ocf_mngt_cache_stop_finish,
|
||||||
|
.steps = {
|
||||||
|
OCF_PL_STEP(ocf_mngt_cache_stop_wait_metadata_io),
|
||||||
|
OCF_PL_STEP(ocf_mngt_cache_stop_remove_cores),
|
||||||
|
OCF_PL_STEP(ocf_mngt_cache_stop_unplug),
|
||||||
|
OCF_PL_STEP(ocf_mngt_cache_stop_put_io_queues),
|
||||||
|
OCF_PL_STEP_TERMINATOR(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void _ocf_mngt_cache_attach(ocf_cache_t cache,
|
static void _ocf_mngt_cache_attach(ocf_cache_t cache,
|
||||||
struct ocf_mngt_cache_device_config *cfg, bool load,
|
struct ocf_mngt_cache_device_config *cfg, bool load,
|
||||||
_ocf_mngt_cache_attach_end_t cmpl, void *priv1, void *priv2)
|
_ocf_mngt_cache_attach_end_t cmpl, void *priv1, void *priv2)
|
||||||
@ -1553,6 +1756,13 @@ static void _ocf_mngt_cache_attach(ocf_cache_t cache,
|
|||||||
if (result)
|
if (result)
|
||||||
OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_NO_MEM);
|
OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_NO_MEM);
|
||||||
|
|
||||||
|
result = ocf_pipeline_create(&cache->stop_pipeline, cache,
|
||||||
|
&ocf_mngt_cache_stop_pipeline_properties);
|
||||||
|
if (result) {
|
||||||
|
ocf_pipeline_destroy(pipeline);
|
||||||
|
OCF_CMPL_RET(cache, priv1, priv2, -OCF_ERR_NO_MEM);
|
||||||
|
}
|
||||||
|
|
||||||
context = ocf_pipeline_get_priv(pipeline);
|
context = ocf_pipeline_get_priv(pipeline);
|
||||||
|
|
||||||
context->cmpl = cmpl;
|
context->cmpl = cmpl;
|
||||||
@ -1591,6 +1801,7 @@ err_uuid:
|
|||||||
env_vfree(data);
|
env_vfree(data);
|
||||||
err_pipeline:
|
err_pipeline:
|
||||||
ocf_pipeline_destroy(pipeline);
|
ocf_pipeline_destroy(pipeline);
|
||||||
|
ocf_pipeline_destroy(cache->stop_pipeline);
|
||||||
OCF_CMPL_RET(cache, priv1, priv2, result);
|
OCF_CMPL_RET(cache, priv1, priv2, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1707,7 +1918,7 @@ static void _ocf_mngt_cache_attach_complete(ocf_cache_t cache, void *priv1,
|
|||||||
ocf_cache_log(cache, log_info, "Successfully attached\n");
|
ocf_cache_log(cache, log_info, "Successfully attached\n");
|
||||||
} else {
|
} else {
|
||||||
ocf_cache_log(cache, log_err, "Attaching cache device "
|
ocf_cache_log(cache, log_err, "Attaching cache device "
|
||||||
"failed\n");
|
"failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
OCF_CMPL_RET(cache, priv2, error);
|
OCF_CMPL_RET(cache, priv2, error);
|
||||||
@ -1733,14 +1944,6 @@ void ocf_mngt_cache_attach(ocf_cache_t cache,
|
|||||||
_ocf_mngt_cache_attach_complete, cmpl, priv);
|
_ocf_mngt_cache_attach_complete, cmpl, priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*_ocf_mngt_cache_unplug_end_t)(void *context, int error);
|
|
||||||
|
|
||||||
struct _ocf_mngt_cache_unplug_context {
|
|
||||||
_ocf_mngt_cache_unplug_end_t cmpl;
|
|
||||||
void *priv;
|
|
||||||
ocf_cache_t cache;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void _ocf_mngt_cache_unplug_complete(void *priv, int error)
|
static void _ocf_mngt_cache_unplug_complete(void *priv, int error)
|
||||||
{
|
{
|
||||||
struct _ocf_mngt_cache_unplug_context *context = priv;
|
struct _ocf_mngt_cache_unplug_context *context = priv;
|
||||||
@ -1771,9 +1974,9 @@ static void _ocf_mngt_cache_unplug_complete(void *priv, int error)
|
|||||||
*
|
*
|
||||||
* @param cache OCF cache instance
|
* @param cache OCF cache instance
|
||||||
* @param stop - true if unplugging during stop - in this case we mark
|
* @param stop - true if unplugging during stop - in this case we mark
|
||||||
* clean shutdown in metadata and flush all containers.
|
* clean shutdown in metadata and flush all containers.
|
||||||
* - false if the device is to be detached from cache - loading
|
* - false if the device is to be detached from cache - loading
|
||||||
* metadata from this device will not be possible.
|
* metadata from this device will not be possible.
|
||||||
* @param context - context for this call, must be zeroed
|
* @param context - context for this call, must be zeroed
|
||||||
* @param cmpl Completion callback
|
* @param cmpl Completion callback
|
||||||
* @param priv Completion context
|
* @param priv Completion context
|
||||||
@ -1881,194 +2084,6 @@ void ocf_mngt_cache_load(ocf_cache_t cache,
|
|||||||
_ocf_mngt_cache_load_complete, cmpl, priv);
|
_ocf_mngt_cache_load_complete, cmpl, priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ocf_mngt_cache_stop_context {
|
|
||||||
/* unplug context - this is private structure of _ocf_mngt_cache_unplug,
|
|
||||||
* it is member of stop context only to reserve memory in advance for
|
|
||||||
* _ocf_mngt_cache_unplug, eliminating the possibility of ENOMEM error
|
|
||||||
* at the point where we are effectively unable to handle it */
|
|
||||||
struct _ocf_mngt_cache_unplug_context unplug_context;
|
|
||||||
|
|
||||||
ocf_mngt_cache_stop_end_t cmpl;
|
|
||||||
void *priv;
|
|
||||||
ocf_pipeline_t pipeline;
|
|
||||||
ocf_cache_t cache;
|
|
||||||
ocf_ctx_t ctx;
|
|
||||||
char cache_name[OCF_CACHE_NAME_SIZE];
|
|
||||||
int cache_write_error;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_wait_metadata_io_finish(void *priv)
|
|
||||||
{
|
|
||||||
struct ocf_mngt_cache_stop_context *context = priv;
|
|
||||||
|
|
||||||
ocf_pipeline_next(context->pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_wait_metadata_io(ocf_pipeline_t pipeline,
|
|
||||||
void *priv, ocf_pipeline_arg_t arg)
|
|
||||||
{
|
|
||||||
struct ocf_mngt_cache_stop_context *context = priv;
|
|
||||||
ocf_cache_t cache = context->cache;
|
|
||||||
|
|
||||||
ocf_refcnt_freeze(&cache->refcnt.metadata);
|
|
||||||
ocf_refcnt_register_zero_cb(&cache->refcnt.metadata,
|
|
||||||
ocf_mngt_cache_stop_wait_metadata_io_finish, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _ocf_mngt_cache_stop_remove_cores(ocf_cache_t cache, bool attached)
|
|
||||||
{
|
|
||||||
ocf_core_t core;
|
|
||||||
ocf_core_id_t core_id;
|
|
||||||
int no = cache->conf_meta->core_count;
|
|
||||||
|
|
||||||
/* All exported objects removed, cleaning up rest. */
|
|
||||||
for_each_core_all(cache, core, core_id) {
|
|
||||||
if (!env_bit_test(core_id, cache->conf_meta->valid_core_bitmap))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cache_mngt_core_remove_from_cache(core);
|
|
||||||
if (attached)
|
|
||||||
cache_mngt_core_remove_from_cleaning_pol(core);
|
|
||||||
cache_mngt_core_close(core);
|
|
||||||
if (--no == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ENV_BUG_ON(cache->conf_meta->core_count != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_remove_cores(ocf_pipeline_t pipeline,
|
|
||||||
void *priv, ocf_pipeline_arg_t arg)
|
|
||||||
{
|
|
||||||
struct ocf_mngt_cache_stop_context *context = priv;
|
|
||||||
ocf_cache_t cache = context->cache;
|
|
||||||
|
|
||||||
_ocf_mngt_cache_stop_remove_cores(cache, true);
|
|
||||||
|
|
||||||
ocf_pipeline_next(pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_unplug_complete(void *priv, int error)
|
|
||||||
{
|
|
||||||
struct ocf_mngt_cache_stop_context *context = priv;
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
ENV_BUG_ON(error != -OCF_ERR_WRITE_CACHE);
|
|
||||||
context->cache_write_error = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ocf_pipeline_next(context->pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_unplug(ocf_pipeline_t pipeline,
|
|
||||||
void *priv, ocf_pipeline_arg_t arg)
|
|
||||||
{
|
|
||||||
struct ocf_mngt_cache_stop_context *context = priv;
|
|
||||||
ocf_cache_t cache = context->cache;
|
|
||||||
|
|
||||||
_ocf_mngt_cache_unplug(cache, true, &context->unplug_context,
|
|
||||||
ocf_mngt_cache_stop_unplug_complete, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _ocf_mngt_cache_put_io_queues(ocf_cache_t cache)
|
|
||||||
{
|
|
||||||
ocf_queue_t queue, tmp_queue;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(queue, tmp_queue, &cache->io_queues, list)
|
|
||||||
ocf_queue_put(queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_put_io_queues(ocf_pipeline_t pipeline,
|
|
||||||
void *priv, ocf_pipeline_arg_t arg)
|
|
||||||
{
|
|
||||||
struct ocf_mngt_cache_stop_context *context = priv;
|
|
||||||
ocf_cache_t cache = context->cache;
|
|
||||||
|
|
||||||
_ocf_mngt_cache_put_io_queues(cache);
|
|
||||||
|
|
||||||
ocf_pipeline_next(pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_remove(ocf_ctx_t ctx, ocf_cache_t cache)
|
|
||||||
{
|
|
||||||
/* Mark device uninitialized */
|
|
||||||
ocf_refcnt_freeze(&cache->refcnt.cache);
|
|
||||||
|
|
||||||
/* Deinitialize locks */
|
|
||||||
ocf_mngt_cache_lock_deinit(cache);
|
|
||||||
env_mutex_destroy(&cache->flush_mutex);
|
|
||||||
|
|
||||||
/* Remove cache from the list */
|
|
||||||
env_rmutex_lock(&ctx->lock);
|
|
||||||
list_del(&cache->list);
|
|
||||||
env_rmutex_unlock(&ctx->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_finish(ocf_pipeline_t pipeline,
|
|
||||||
void *priv, int error)
|
|
||||||
{
|
|
||||||
struct ocf_mngt_cache_stop_context *context = priv;
|
|
||||||
ocf_cache_t cache = context->cache;
|
|
||||||
ocf_ctx_t ctx = context->ctx;
|
|
||||||
int pipeline_error;
|
|
||||||
ocf_mngt_cache_stop_end_t pipeline_cmpl;
|
|
||||||
void *completion_priv;
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
ocf_mngt_cache_remove(context->ctx, cache);
|
|
||||||
} else {
|
|
||||||
/* undo metadata counter freeze */
|
|
||||||
ocf_refcnt_unfreeze(&cache->refcnt.metadata);
|
|
||||||
|
|
||||||
env_bit_clear(ocf_cache_state_stopping, &cache->cache_state);
|
|
||||||
env_bit_set(ocf_cache_state_running, &cache->cache_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
if (!context->cache_write_error) {
|
|
||||||
ocf_log(ctx, log_info,
|
|
||||||
"Cache %s successfully stopped\n",
|
|
||||||
context->cache_name);
|
|
||||||
} else {
|
|
||||||
ocf_log(ctx, log_warn, "Stopped cache %s with errors\n",
|
|
||||||
context->cache_name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ocf_log(ctx, log_err, "Stopping cache %s failed\n",
|
|
||||||
context->cache_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Destroying pipeline before completing management operation is a
|
|
||||||
* temporary workaround for insufficient object lifetime management in pyocf
|
|
||||||
* Context must not be referenced after destroying pipeline as this is
|
|
||||||
* typically freed upon pipeline destroy.
|
|
||||||
*/
|
|
||||||
pipeline_error = error ?: context->cache_write_error;
|
|
||||||
pipeline_cmpl = context->cmpl;
|
|
||||||
completion_priv = context->priv;
|
|
||||||
|
|
||||||
ocf_pipeline_destroy(context->pipeline);
|
|
||||||
|
|
||||||
pipeline_cmpl(cache, completion_priv, pipeline_error);
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
/* Finally release cache instance */
|
|
||||||
ocf_mngt_cache_put(cache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ocf_pipeline_properties ocf_mngt_cache_stop_pipeline_properties = {
|
|
||||||
.priv_size = sizeof(struct ocf_mngt_cache_stop_context),
|
|
||||||
.finish = ocf_mngt_cache_stop_finish,
|
|
||||||
.steps = {
|
|
||||||
OCF_PL_STEP(ocf_mngt_cache_stop_wait_metadata_io),
|
|
||||||
OCF_PL_STEP(ocf_mngt_cache_stop_remove_cores),
|
|
||||||
OCF_PL_STEP(ocf_mngt_cache_stop_unplug),
|
|
||||||
OCF_PL_STEP(ocf_mngt_cache_stop_put_io_queues),
|
|
||||||
OCF_PL_STEP_TERMINATOR(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ocf_mngt_cache_stop_detached(ocf_cache_t cache,
|
static void ocf_mngt_cache_stop_detached(ocf_cache_t cache,
|
||||||
ocf_mngt_cache_stop_end_t cmpl, void *priv)
|
ocf_mngt_cache_stop_end_t cmpl, void *priv)
|
||||||
{
|
{
|
||||||
@ -2086,7 +2101,6 @@ void ocf_mngt_cache_stop(ocf_cache_t cache,
|
|||||||
{
|
{
|
||||||
struct ocf_mngt_cache_stop_context *context;
|
struct ocf_mngt_cache_stop_context *context;
|
||||||
ocf_pipeline_t pipeline;
|
ocf_pipeline_t pipeline;
|
||||||
int result;
|
|
||||||
|
|
||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
|
|
||||||
@ -2097,11 +2111,7 @@ void ocf_mngt_cache_stop(ocf_cache_t cache,
|
|||||||
|
|
||||||
ENV_BUG_ON(!cache->mngt_queue);
|
ENV_BUG_ON(!cache->mngt_queue);
|
||||||
|
|
||||||
result = ocf_pipeline_create(&pipeline, cache,
|
pipeline = cache->stop_pipeline;
|
||||||
&ocf_mngt_cache_stop_pipeline_properties);
|
|
||||||
if (result)
|
|
||||||
OCF_CMPL_RET(cache, priv, -OCF_ERR_NO_MEM);
|
|
||||||
|
|
||||||
context = ocf_pipeline_get_priv(pipeline);
|
context = ocf_pipeline_get_priv(pipeline);
|
||||||
|
|
||||||
context->cmpl = cmpl;
|
context->cmpl = cmpl;
|
||||||
@ -2110,12 +2120,8 @@ void ocf_mngt_cache_stop(ocf_cache_t cache,
|
|||||||
context->cache = cache;
|
context->cache = cache;
|
||||||
context->ctx = cache->owner;
|
context->ctx = cache->owner;
|
||||||
|
|
||||||
result = env_strncpy(context->cache_name, sizeof(context->cache_name),
|
ENV_BUG_ON(env_strncpy(context->cache_name, sizeof(context->cache_name),
|
||||||
ocf_cache_get_name(cache), sizeof(context->cache_name));
|
ocf_cache_get_name(cache), sizeof(context->cache_name)));
|
||||||
if (result) {
|
|
||||||
ocf_pipeline_destroy(pipeline);
|
|
||||||
OCF_CMPL_RET(cache, priv, -OCF_ERR_NO_MEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
ocf_cache_log(cache, log_info, "Stopping cache\n");
|
ocf_cache_log(cache, log_info, "Stopping cache\n");
|
||||||
|
|
||||||
@ -2241,7 +2247,7 @@ int ocf_mngt_cache_set_mode(ocf_cache_t cache, ocf_cache_mode_t mode)
|
|||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
|
|
||||||
if (!ocf_cache_mode_is_valid(mode)) {
|
if (!ocf_cache_mode_is_valid(mode)) {
|
||||||
ocf_cache_log(cache, log_err, "Cache mode %u is invalid\n",
|
ocf_cache_log(cache, log_err, "Cache mode %u is invalid\n",
|
||||||
mode);
|
mode);
|
||||||
return -OCF_ERR_INVAL;
|
return -OCF_ERR_INVAL;
|
||||||
}
|
}
|
||||||
@ -2502,6 +2508,7 @@ static void ocf_mngt_cache_detach_finish(ocf_pipeline_t pipeline,
|
|||||||
error ?: context->cache_write_error);
|
error ?: context->cache_write_error);
|
||||||
|
|
||||||
ocf_pipeline_destroy(context->pipeline);
|
ocf_pipeline_destroy(context->pipeline);
|
||||||
|
ocf_pipeline_destroy(cache->stop_pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ocf_pipeline_properties ocf_mngt_cache_detach_pipeline_properties = {
|
struct ocf_pipeline_properties ocf_mngt_cache_detach_pipeline_properties = {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "metadata/metadata_partition_structs.h"
|
#include "metadata/metadata_partition_structs.h"
|
||||||
#include "metadata/metadata_updater_priv.h"
|
#include "metadata/metadata_updater_priv.h"
|
||||||
#include "utils/utils_list.h"
|
#include "utils/utils_list.h"
|
||||||
|
#include "utils/utils_pipeline.h"
|
||||||
#include "utils/utils_refcnt.h"
|
#include "utils/utils_refcnt.h"
|
||||||
#include "utils/utils_async_lock.h"
|
#include "utils/utils_async_lock.h"
|
||||||
#include "ocf_stats_priv.h"
|
#include "ocf_stats_priv.h"
|
||||||
@ -167,6 +168,8 @@ struct ocf_cache {
|
|||||||
|
|
||||||
struct ocf_trace trace;
|
struct ocf_trace trace;
|
||||||
|
|
||||||
|
ocf_pipeline_t stop_pipeline;
|
||||||
|
|
||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user