Fix deadlock on concurrent flush at the same cache
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
parent
7799b24858
commit
a9c36477d2
@ -102,6 +102,9 @@ typedef enum {
|
|||||||
/** Flushing of core interrupted */
|
/** Flushing of core interrupted */
|
||||||
OCF_ERR_FLUSHING_INTERRUPTED,
|
OCF_ERR_FLUSHING_INTERRUPTED,
|
||||||
|
|
||||||
|
/** Another flushing operation in progress */
|
||||||
|
OCF_ERR_FLUSH_IN_PROGRESS,
|
||||||
|
|
||||||
/** Adding core to core pool failed */
|
/** Adding core to core pool failed */
|
||||||
OCF_ERR_CANNOT_ADD_CORE_TO_POOL,
|
OCF_ERR_CANNOT_ADD_CORE_TO_POOL,
|
||||||
|
|
||||||
|
@ -47,6 +47,11 @@ struct ocf_mngt_cache_flush_context
|
|||||||
/* target core */
|
/* target core */
|
||||||
ocf_core_t core;
|
ocf_core_t core;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool lock : 1;
|
||||||
|
bool freeze : 1;
|
||||||
|
} flags;
|
||||||
|
|
||||||
/* management operation identifier */
|
/* management operation identifier */
|
||||||
enum {
|
enum {
|
||||||
flush_cache = 0,
|
flush_cache = 0,
|
||||||
@ -87,24 +92,22 @@ static void _ocf_mngt_begin_flush(ocf_pipeline_t pipeline, void *priv,
|
|||||||
{
|
{
|
||||||
struct ocf_mngt_cache_flush_context *context = priv;
|
struct ocf_mngt_cache_flush_context *context = priv;
|
||||||
ocf_cache_t cache = context->cache;
|
ocf_cache_t cache = context->cache;
|
||||||
|
int result;
|
||||||
|
|
||||||
/* FIXME: need mechanism for async waiting for outstanding flushes to
|
/* FIXME: need mechanism for async waiting for outstanding flushes to
|
||||||
* finish */
|
* finish */
|
||||||
env_mutex_lock(&cache->flush_mutex);
|
result = env_mutex_trylock(&cache->flush_mutex);
|
||||||
|
if (result)
|
||||||
|
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_FLUSH_IN_PROGRESS);
|
||||||
|
context->flags.lock = true;
|
||||||
|
|
||||||
ocf_refcnt_freeze(&cache->refcnt.dirty);
|
ocf_refcnt_freeze(&cache->refcnt.dirty);
|
||||||
|
context->flags.freeze = true;
|
||||||
|
|
||||||
ocf_refcnt_register_zero_cb(&cache->refcnt.dirty,
|
ocf_refcnt_register_zero_cb(&cache->refcnt.dirty,
|
||||||
_ocf_mngt_begin_flush_complete, context);
|
_ocf_mngt_begin_flush_complete, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _ocf_mngt_end_flush(ocf_cache_t cache)
|
|
||||||
{
|
|
||||||
ocf_refcnt_unfreeze(&cache->refcnt.dirty);
|
|
||||||
|
|
||||||
env_mutex_unlock(&cache->flush_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ocf_mngt_core_is_dirty(ocf_core_t core)
|
bool ocf_mngt_core_is_dirty(ocf_core_t core)
|
||||||
{
|
{
|
||||||
return !!env_atomic_read(&core->runtime_meta->dirty_clines);
|
return !!env_atomic_read(&core->runtime_meta->dirty_clines);
|
||||||
@ -606,7 +609,11 @@ static void _ocf_mngt_flush_finish(ocf_pipeline_t pipeline, void *priv,
|
|||||||
ocf_cache_t cache = context->cache;
|
ocf_cache_t cache = context->cache;
|
||||||
ocf_core_t core = context->core;
|
ocf_core_t core = context->core;
|
||||||
|
|
||||||
_ocf_mngt_end_flush(cache);
|
if (context->flags.freeze)
|
||||||
|
ocf_refcnt_unfreeze(&cache->refcnt.dirty);
|
||||||
|
|
||||||
|
if (context->flags.lock)
|
||||||
|
env_mutex_unlock(&cache->flush_mutex);
|
||||||
|
|
||||||
switch (context->op) {
|
switch (context->op) {
|
||||||
case flush_cache:
|
case flush_cache:
|
||||||
|
@ -41,6 +41,7 @@ class OcfErrorCode(IntEnum):
|
|||||||
OCF_ERR_DIRTY_SHUTDOWN = auto()
|
OCF_ERR_DIRTY_SHUTDOWN = auto()
|
||||||
OCF_ERR_DIRTY_EXISTS = auto()
|
OCF_ERR_DIRTY_EXISTS = auto()
|
||||||
OCF_ERR_FLUSHING_INTERRUPTED = auto()
|
OCF_ERR_FLUSHING_INTERRUPTED = auto()
|
||||||
|
OCF_ERR_FLUSH_IN_PROGRESS = auto()
|
||||||
OCF_ERR_CANNOT_ADD_CORE_TO_POOL = auto()
|
OCF_ERR_CANNOT_ADD_CORE_TO_POOL = auto()
|
||||||
OCF_ERR_CACHE_IN_INCOMPLETE_STATE = auto()
|
OCF_ERR_CACHE_IN_INCOMPLETE_STATE = auto()
|
||||||
OCF_ERR_CORE_IN_INACTIVE_STATE = auto()
|
OCF_ERR_CORE_IN_INACTIVE_STATE = auto()
|
||||||
|
Loading…
Reference in New Issue
Block a user