Allow flush operations to be interrupted.

When context was allocated on the stack and waiting for completion was
interrupted, completion function would attempt to save flush result in
memory which might in use by other process. This would cause a system crash.

To prevent such scenario, context is allocated dynamiclly and extended with
reference counter. In case of interrupt, completion function doesn't have to
save result in context, it can simply free it's memory.

This commit also enables possibility to interrupt regular flush properly, by
seding SIGING to casadm.

This commit is part of patch that will allow to interrupt waiting for OCF
operations.

Signed-off-by: Michal Mielewczyk <michal.mielewczyk@intel.com>
This commit is contained in:
Michal Mielewczyk 2019-12-17 04:21:47 -05:00
parent b7f1dd69a9
commit 0b5ed3f00b

View File

@ -199,24 +199,36 @@ static int _cache_mngt_save_sync(ocf_cache_t cache)
static void _cache_mngt_cache_flush_complete(ocf_cache_t cache, void *priv,
int error)
{
struct _cache_mngt_sync_context *context = priv;
struct _cache_mngt_async_context *context = priv;
int result;
*context->result = error;
complete(&context->compl);
result = _cache_mngt_async_callee_set_result(context, error);
if (result == -KCAS_ERR_WAITING_INTERRUPTED)
kfree(context);
}
static int _cache_mngt_cache_flush_sync(ocf_cache_t cache, bool interruption)
{
struct cache_priv *cache_priv = ocf_cache_get_priv(cache);
struct _cache_mngt_sync_context context;
int result;
struct _cache_mngt_async_context *context;
struct cache_priv *cache_priv = ocf_cache_get_priv(cache);
init_completion(&context.compl);
context.result = &result;
context = kmalloc(sizeof(*context), GFP_KERNEL);
if (!context)
return -ENOMEM;
_cache_mngt_async_context_init(context);
atomic_set(&cache_priv->flush_interrupt_enabled, interruption);
ocf_mngt_cache_flush(cache, _cache_mngt_cache_flush_complete, context);
result = wait_for_completion_interruptible(&context->cmpl);
result = _cache_mngt_async_caller_set_result(context, result);
if (result != -KCAS_ERR_WAITING_INTERRUPTED)
kfree(context);
atomic_set(&cache_priv->flush_interrupt_enabled, 0);
ocf_mngt_cache_flush(cache, _cache_mngt_cache_flush_complete, &context);
wait_for_completion_interruptible(&context.compl);
atomic_set(&cache_priv->flush_interrupt_enabled, 1);
return result;
@ -225,25 +237,37 @@ static int _cache_mngt_cache_flush_sync(ocf_cache_t cache, bool interruption)
static void _cache_mngt_core_flush_complete(ocf_core_t core, void *priv,
int error)
{
struct _cache_mngt_sync_context *context = priv;
struct _cache_mngt_async_context *context = priv;
int result;
*context->result = error;
complete(&context->compl);
result = _cache_mngt_async_callee_set_result(context, error);
if (result == -KCAS_ERR_WAITING_INTERRUPTED)
kfree(context);
}
static int _cache_mngt_core_flush_sync(ocf_core_t core, bool interruption)
{
int result;
struct _cache_mngt_async_context *context;
ocf_cache_t cache = ocf_core_get_cache(core);
struct cache_priv *cache_priv = ocf_cache_get_priv(cache);
struct _cache_mngt_sync_context context;
int result;
init_completion(&context.compl);
context.result = &result;
context = kmalloc(sizeof(*context), GFP_KERNEL);
if (!context)
return -ENOMEM;
_cache_mngt_async_context_init(context);
atomic_set(&cache_priv->flush_interrupt_enabled, interruption);
ocf_mngt_core_flush(core, _cache_mngt_core_flush_complete, context);
result = wait_for_completion_interruptible(&context->cmpl);
result = _cache_mngt_async_caller_set_result(context, result);
if (result != -KCAS_ERR_WAITING_INTERRUPTED)
kfree(context);
atomic_set(&cache_priv->flush_interrupt_enabled, 0);
ocf_mngt_core_flush(core, _cache_mngt_core_flush_complete, &context);
wait_for_completion_interruptible(&context.compl);
atomic_set(&cache_priv->flush_interrupt_enabled, 1);
return result;