Properly handle flush error in cache stop

In case of initial flush error stop is aborted. In case
of failure during the second flush, appropriate error
message is presetned to the user.

Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski 2021-04-15 14:01:35 -05:00
parent 3f348cf5d8
commit da0dda2dbd

View File

@ -466,6 +466,7 @@ static int _cache_mngt_core_flush_uninterruptible(ocf_core_t core)
struct _cache_mngt_stop_context { struct _cache_mngt_stop_context {
struct _cache_mngt_async_context async; struct _cache_mngt_async_context async;
int error; int error;
int flush_status;
ocf_cache_t cache; ocf_cache_t cache;
struct task_struct *finish_thread; struct task_struct *finish_thread;
}; };
@ -484,21 +485,21 @@ static int exit_instance_finish(void *data)
struct cache_priv *cache_priv; struct cache_priv *cache_priv;
struct _cache_mngt_stop_context *ctx = data; struct _cache_mngt_stop_context *ctx = data;
ocf_queue_t mngt_queue; ocf_queue_t mngt_queue;
bool flush_status;
int result = 0; int result = 0;
if (kthread_should_stop()) if (kthread_should_stop())
return 0; return 0;
flush_status = ocf_mngt_cache_is_dirty(ctx->cache);
cache_priv = ocf_cache_get_priv(ctx->cache); cache_priv = ocf_cache_get_priv(ctx->cache);
mngt_queue = cache_priv->mngt_queue; mngt_queue = cache_priv->mngt_queue;
if (ctx->error && ctx->error != -OCF_ERR_WRITE_CACHE) if (ctx->error && ctx->error != -OCF_ERR_WRITE_CACHE)
BUG_ON(ctx->error); BUG_ON(ctx->error);
if (!ctx->error && flush_status) if (!ctx->error && ctx->flush_status)
result = -KCAS_ERR_STOPPED_DIRTY; result = -KCAS_ERR_STOPPED_DIRTY;
else
result = ctx->error;
cas_cls_deinit(ctx->cache); cas_cls_deinit(ctx->cache);
@ -2411,15 +2412,8 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush)
*/ */
if (flush) if (flush)
status = _cache_flush_with_lock(cache); status = _cache_flush_with_lock(cache);
switch (status) { if (status)
case -OCF_ERR_CACHE_IN_INCOMPLETE_STATE:
case -OCF_ERR_FLUSHING_INTERRUPTED:
case -KCAS_ERR_WAITING_INTERRUPTED:
goto put; goto put;
default:
flush_status = status;
break;
}
status = _cache_mngt_lock_sync(cache); status = _cache_mngt_lock_sync(cache);
if (status) if (status)
@ -2441,10 +2435,6 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush)
goto stop_thread; goto stop_thread;
} }
} else { } else {
if (flush_status) {
status = flush_status;
goto stop_thread;
}
/* /*
* We are being switched to upgrade in flight mode - * We are being switched to upgrade in flight mode -
* wait for finishing pending core requests * wait for finishing pending core requests
@ -2455,6 +2445,8 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush)
/* Flush cache again. This time we don't allow interruption. */ /* Flush cache again. This time we don't allow interruption. */
if (flush) if (flush)
flush_status = _cache_mngt_cache_flush_uninterruptible(cache); flush_status = _cache_mngt_cache_flush_uninterruptible(cache);
context->flush_status = flush_status;
if (flush && !flush_status) if (flush && !flush_status)
BUG_ON(ocf_mngt_cache_is_dirty(cache)); BUG_ON(ocf_mngt_cache_is_dirty(cache));
@ -2466,6 +2458,12 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush)
"Waiting for cache stop interrupted. " "Waiting for cache stop interrupted. "
"Stop will finish asynchronously.\n"); "Stop will finish asynchronously.\n");
if ((status == 0 || status == -KCAS_ERR_WAITING_INTERRUPTED) &&
flush_status) {
/* "removed dirty" error has a precedence over "interrupted" */
return KCAS_ERR_STOPPED_DIRTY;
}
return status; return status;
stop_thread: stop_thread: