Clean-up 'remove-core' command

Signed-off-by: Michal Mielewczyk <michal.mielewczyk@intel.com>
This commit is contained in:
Michal Mielewczyk 2021-04-09 10:51:33 +02:00
parent 1cec062f67
commit 083d6fe93e
5 changed files with 79 additions and 70 deletions

View File

@ -1908,7 +1908,7 @@ int remove_core(unsigned int cache_id, unsigned int core_id,
cmd.detach = detach; cmd.detach = detach;
if (run_ioctl_interruptible(fd, KCAS_IOCTL_REMOVE_CORE, &cmd, if (run_ioctl_interruptible(fd, KCAS_IOCTL_REMOVE_CORE, &cmd,
"Removing core", cache_id, core_id) < 0) { cmd.detach?"Detaching core":"Removing core", cache_id, core_id) < 0) {
close(fd); close(fd);
if (cmd.ext_err_code == OCF_ERR_FLUSHING_INTERRUPTED) { if (cmd.ext_err_code == OCF_ERR_FLUSHING_INTERRUPTED) {
cas_printf(LOG_ERR, "You have interrupted %s of core. " cas_printf(LOG_ERR, "You have interrupted %s of core. "
@ -1920,9 +1920,9 @@ int remove_core(unsigned int cache_id, unsigned int core_id,
"inactive core use '--remove-inactive' " "inactive core use '--remove-inactive' "
"command.\n"); "command.\n");
return FAILURE; return FAILURE;
} else if (cmd.ext_err_code == KCAS_ERR_REMOVED_DIRTY) { } else if (cmd.ext_err_code == KCAS_ERR_DETACHED) {
print_err(cmd.ext_err_code); print_err(cmd.ext_err_code);
return SUCCESS; return FAILURE;
} else { } else {
cas_printf(LOG_ERR, "Error while %s core device %d " cas_printf(LOG_ERR, "Error while %s core device %d "
"from cache instance %d\n", "from cache instance %d\n",

View File

@ -225,10 +225,8 @@ struct {
"Formatting of partition is unsupported." "Formatting of partition is unsupported."
}, },
{ {
KCAS_ERR_REMOVED_DIRTY, KCAS_ERR_DETACHED,
"Warning: Core has been removed or detached without flush.\n" "Failed to remove core. See dmesg for more information"
"Core device may contain inconsistent data.\n"
"To access your data please add core back to the cache."
}, },
{ {
KCAS_ERR_STOPPED_DIRTY, KCAS_ERR_STOPPED_DIRTY,

View File

@ -1320,6 +1320,19 @@ error_affter_lock:
return result; return result;
} }
static int _cache_mngt_create_exported_object(ocf_core_t core, void *cntx)
{
int result;
result = block_dev_create_exported_object(core);
if (result)
return result;
result = block_dev_activate_exported_object(core);
return result;
}
static int _cache_mngt_remove_core_flush(ocf_cache_t cache, static int _cache_mngt_remove_core_flush(ocf_cache_t cache,
struct kcas_remove_core *cmd) struct kcas_remove_core *cmd)
{ {
@ -1366,35 +1379,6 @@ put:
return result; return result;
} }
static int _cache_mngt_remove_core_prepare(ocf_cache_t cache, ocf_core_t core,
struct kcas_remove_core *cmd)
{
int result = 0;
bool core_active;
core_active = ocf_core_get_state(core) == ocf_core_state_active;
if (!core_active) {
if (cmd->detach) {
printk(KERN_WARNING OCF_PREFIX_SHORT
"Cannot detach core which "
"is already inactive!\n");
}
return -OCF_ERR_CORE_IN_INACTIVE_STATE;
} else {
result = block_dev_destroy_exported_object(core);
if (result)
return result;
}
if (cmd->force_no_flush)
return -KCAS_ERR_REMOVED_DIRTY;
result = _cache_mngt_core_flush_uninterruptible(core);
return result ? -KCAS_ERR_REMOVED_DIRTY : 0;
}
static void _cache_mngt_remove_core_complete(void *priv, int error) static void _cache_mngt_remove_core_complete(void *priv, int error)
{ {
struct _cache_mngt_sync_context *context = priv; struct _cache_mngt_sync_context *context = priv;
@ -1403,10 +1387,63 @@ static void _cache_mngt_remove_core_complete(void *priv, int error)
complete(&context->cmpl); complete(&context->cmpl);
} }
static void _cache_mngt_remove_core_fallback(ocf_cache_t cache, ocf_core_t core)
{
struct _cache_mngt_sync_context context;
int result;
printk(KERN_ERR "Removing core failed. Detaching %s.%s\n",
ocf_cache_get_name(cache),
ocf_core_get_name(core));
init_completion(&context.cmpl);
context.result = &result;
ocf_mngt_cache_detach_core(core,
_cache_mngt_remove_core_complete, &context);
wait_for_completion(&context.cmpl);
if (!result)
return;
printk(KERN_ERR "Detaching %s.%s\n failed. Please retry the remove operation",
ocf_cache_get_name(cache),
ocf_core_get_name(core));
}
static int _cache_mngt_remove_core_prepare(ocf_cache_t cache, ocf_core_t core,
struct kcas_remove_core *cmd)
{
int result = 0;
bool core_active;
core_active = ocf_core_get_state(core) == ocf_core_state_active;
if (!core_active)
return -OCF_ERR_CORE_IN_INACTIVE_STATE;
result = block_dev_destroy_exported_object(core);
if (result)
return result;
if (cmd->force_no_flush)
return 0;
result = _cache_mngt_core_flush_uninterruptible(core);
if (!result)
return 0;
_cache_mngt_remove_core_fallback(cache, core);
return -KCAS_ERR_DETACHED;
}
int cache_mngt_remove_core_from_cache(struct kcas_remove_core *cmd) int cache_mngt_remove_core_from_cache(struct kcas_remove_core *cmd)
{ {
struct _cache_mngt_sync_context context; struct _cache_mngt_sync_context context;
int result, prepare_result = 0; int result;
ocf_cache_t cache; ocf_cache_t cache;
ocf_core_t core; ocf_core_t core;
@ -1427,14 +1464,8 @@ int cache_mngt_remove_core_from_cache(struct kcas_remove_core *cmd)
goto unlock; goto unlock;
} }
/* result = _cache_mngt_remove_core_prepare(cache, core, cmd);
* Destroy exported object and flush core again but don't allow for if (result)
* interruption - in case of flush error after exported object had been
* destroyed, instead of trying rolling this back we rather detach core
* and then inform user about error.
*/
prepare_result = _cache_mngt_remove_core_prepare(cache, core, cmd);
if (prepare_result && prepare_result != -KCAS_ERR_REMOVED_DIRTY)
goto unlock; goto unlock;
init_completion(&context.cmpl); init_completion(&context.cmpl);
@ -1448,19 +1479,12 @@ int cache_mngt_remove_core_from_cache(struct kcas_remove_core *cmd)
_cache_mngt_remove_core_complete, &context); _cache_mngt_remove_core_complete, &context);
} }
if (!cmd->force_no_flush && !prepare_result)
BUG_ON(ocf_mngt_core_is_dirty(core));
wait_for_completion(&context.cmpl); wait_for_completion(&context.cmpl);
if (!result && !cmd->detach) { if (!result && !cmd->detach)
mark_core_id_free(cache, cmd->core_id); mark_core_id_free(cache, cmd->core_id);
}
unlock: unlock:
if (!result && prepare_result)
result = prepare_result;
ocf_mngt_cache_unlock(cache); ocf_mngt_cache_unlock(cache);
put: put:
ocf_mngt_cache_put(cache); ocf_mngt_cache_put(cache);
@ -1495,7 +1519,7 @@ int cache_mngt_remove_inactive_core(struct kcas_remove_inactive *cmd)
/* /*
* Destroy exported object - in case of error during destruction of * Destroy exported object - in case of error during destruction of
* exported object, instead of trying rolling this back we rather * exported object, instead of trying rolling this back we rather
* inform user about error. * inform user about error.
*/ */
result = block_dev_destroy_exported_object(core); result = block_dev_destroy_exported_object(core);
@ -1635,19 +1659,6 @@ out_get:
return result; return result;
} }
static int _cache_mngt_create_exported_object(ocf_core_t core, void *cntx)
{
int result;
result = block_dev_create_exported_object(core);
if (result)
return result;
result = block_dev_activate_exported_object(core);
return result;
}
static int _cache_mngt_destroy_exported_object(ocf_core_t core, void *cntx) static int _cache_mngt_destroy_exported_object(ocf_core_t core, void *cntx)
{ {
if (block_dev_destroy_exported_object(core)) { if (block_dev_destroy_exported_object(core)) {

View File

@ -63,7 +63,7 @@ struct {
{ KCAS_ERR_NVME_BAD_FORMAT, EINVAL }, { KCAS_ERR_NVME_BAD_FORMAT, EINVAL },
{ KCAS_ERR_CONTAINS_PART, EINVAL }, { KCAS_ERR_CONTAINS_PART, EINVAL },
{ KCAS_ERR_A_PART, EINVAL }, { KCAS_ERR_A_PART, EINVAL },
{ KCAS_ERR_REMOVED_DIRTY, EIO }, { KCAS_ERR_DETACHED, EIO },
{ KCAS_ERR_STOPPED_DIRTY, EIO }, { KCAS_ERR_STOPPED_DIRTY, EIO },
{ KCAS_ERR_CORE_IN_ACTIVE_STATE, ENODEV }, { KCAS_ERR_CORE_IN_ACTIVE_STATE, ENODEV },
}; };

View File

@ -577,8 +577,8 @@ enum kcas_error {
/** Given device is a partition */ /** Given device is a partition */
KCAS_ERR_A_PART, KCAS_ERR_A_PART,
/** Core has been removed, but it may contain dirty data */ /** Removing core failed and rollback failed too */
KCAS_ERR_REMOVED_DIRTY, KCAS_ERR_DETACHED,
/** Cache has been stopped, but it may contain dirty data */ /** Cache has been stopped, but it may contain dirty data */
KCAS_ERR_STOPPED_DIRTY, KCAS_ERR_STOPPED_DIRTY,