From b7f1dd69a99667cf0399efada8f69faae0545dd0 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Tue, 17 Dec 2019 02:54:41 -0500 Subject: [PATCH] Allow waiting for metadata flush 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 is part of patch that will allow to interrupt waiting for OCF operations. Signed-off-by: Michal Mielewczyk --- modules/cas_cache/layer_cache_management.c | 27 +++++++++++++++------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 2251336..dfda4ae 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -165,22 +165,33 @@ static int _cache_mngt_read_lock_sync(ocf_cache_t cache) static void _cache_mngt_save_sync_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_save_sync(ocf_cache_t cache) { - struct _cache_mngt_sync_context context; + struct _cache_mngt_async_context *context; int result; - init_completion(&context.compl); - context.result = &result; + context = kmalloc(sizeof(*context), GFP_KERNEL); + if (!context) + return -ENOMEM; - ocf_mngt_cache_save(cache, _cache_mngt_save_sync_complete, &context); - wait_for_completion_interruptible(&context.compl); + _cache_mngt_async_context_init(context); + + ocf_mngt_cache_save(cache, _cache_mngt_save_sync_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); return result; }