Merge pull request #690 from Ostrokrzew/removal

Introduce removing inactive core command
This commit is contained in:
Michał Mielewczyk 2021-03-10 15:56:53 +01:00 committed by GitHub
commit 713f5b3b0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 215 additions and 39 deletions

View File

@ -1904,11 +1904,23 @@ int remove_core(unsigned int cache_id, unsigned int core_id,
if (run_ioctl_interruptible(fd, KCAS_IOCTL_REMOVE_CORE, &cmd,
"Removing core", cache_id, core_id) < 0) {
close(fd);
if (OCF_ERR_FLUSHING_INTERRUPTED == cmd.ext_err_code) {
cas_printf(LOG_ERR, "You have interrupted removal of core. CAS continues to operate normally.\n");
if (cmd.ext_err_code == OCF_ERR_FLUSHING_INTERRUPTED) {
cas_printf(LOG_ERR, "You have interrupted %s of core. "
"CAS continues to operate normally.\n",
detach ? "detaching" : "removal");
return INTERRUPTED;
} else if (cmd.ext_err_code == OCF_ERR_CORE_IN_INACTIVE_STATE) {
cas_printf(LOG_ERR, "Core is inactive. To manage the "
"inactive core use '--remove-inactive' "
"command.\n");
return FAILURE;
} else if (cmd.ext_err_code == KCAS_ERR_REMOVED_DIRTY) {
print_err(cmd.ext_err_code);
return SUCCESS;
} else {
cas_printf(LOG_ERR, "Error while removing core device %d from cache instance %d\n",
cas_printf(LOG_ERR, "Error while %s core device %d "
"from cache instance %d\n",
detach ? "detaching" : "removing",
core_id, cache_id);
print_err(cmd.ext_err_code);
return FAILURE;
@ -1919,6 +1931,43 @@ int remove_core(unsigned int cache_id, unsigned int core_id,
return SUCCESS;
}
int remove_inactive_core(unsigned int cache_id, unsigned int core_id)
{
int fd = 0;
struct kcas_remove_inactive cmd;
/* don't even attempt ioctl if filesystem is mounted */
if (SUCCESS != check_if_mounted(cache_id, core_id)) {
return FAILURE;
}
fd = open_ctrl_device();
if (fd == -1)
return FAILURE;
memset(&cmd, 0, sizeof(cmd));
cmd.cache_id = cache_id;
cmd.core_id = core_id;
if (run_ioctl(fd, KCAS_IOCTL_REMOVE_INACTIVE, &cmd) < 0) {
close(fd);
if (cmd.ext_err_code == KCAS_ERR_CORE_IN_ACTIVE_STATE) {
cas_printf(LOG_ERR, "Core is active. "
"To manage the active core use "
"'--remove-core' command.\n");
} else {
cas_printf(LOG_ERR, "Error while removing inactive "
"core device %d from cache instance "
"%d\n", core_id, cache_id);
print_err(cmd.ext_err_code);
}
return FAILURE;
}
close(fd);
return SUCCESS;
}
int core_pool_remove(const char *core_device)
{
struct kcas_core_pool_remove cmd;

View File

@ -215,6 +215,15 @@ int get_core_info(int fd, int cache_id, int core_id, struct kcas_core_info *info
int remove_core(unsigned int cache_id, unsigned int core_id,
bool detach, bool force_no_flush);
/**
* @brief remove inactive core device from a cache
*
* @param cache_id cache from which inactive core is being removed
* @param cache_id inactive core which is being removed
* @return 0 upon successful core removal, 1 upon failure
*/
int remove_inactive_core(unsigned int cache_id, unsigned int core_id);
int core_pool_remove(const char *core_device);
int get_core_pool_count(int fd);

View File

@ -180,6 +180,23 @@ int remove_core_command_handle_option(char *opt, const char **arg)
return 0;
}
int remove_inactive_core_command_handle_option(char *opt, const char **arg)
{
if (!strcmp(opt, "cache-id")){
if (validate_str_num(arg[0], "cache id", OCF_CACHE_ID_MIN, OCF_CACHE_ID_MAX) == FAILURE)
return FAILURE;
command_args_values.cache_id = atoi(arg[0]);
} else if (!strcmp(opt, "core-id")){
if (validate_str_num(arg[0], "core id", 0, OCF_CORE_ID_MAX) == FAILURE)
return FAILURE;
command_args_values.core_id = atoi(arg[0]);
}
return 0;
}
int core_pool_remove_command_handle_option(char *opt, const char **arg)
{
if (!strcmp(opt, "device")) {
@ -1109,7 +1126,7 @@ int handle_add()
static cli_option remove_options[] = {
{'i', "cache-id", CACHE_ID_DESC, 1, "ID", CLI_OPTION_REQUIRED},
{'j', "core-id", CORE_ID_DESC, 1, "ID", CLI_OPTION_REQUIRED},
{'f', "force", "Force remove inactive core"},
{'f', "force", "Force active core removal without data flush"},
{0}
};
@ -1121,6 +1138,18 @@ int handle_remove()
command_args_values.force);
}
static cli_option remove_inactive_options[] = {
{'i', "cache-id", CACHE_ID_DESC, 1, "ID", CLI_OPTION_REQUIRED},
{'j', "core-id", CORE_ID_DESC, 1, "ID", CLI_OPTION_REQUIRED},
{0}
};
int handle_remove_inactive()
{
return remove_inactive_core(command_args_values.cache_id,
command_args_values.core_id);
}
static cli_option core_pool_remove_options[] = {
{'d', "device", CORE_DEVICE_DESC, 1, "DEVICE", CLI_OPTION_REQUIRED},
{0}
@ -1961,7 +1990,7 @@ static cli_command cas_commands[] = {
{
.name = "remove-core",
.short_name = 'R',
.desc = "Remove core device from cache instance",
.desc = "Remove active core device from cache instance",
.long_desc = NULL,
.options = remove_options,
.command_handle_opts = remove_core_command_handle_option,
@ -1969,6 +1998,16 @@ static cli_command cas_commands[] = {
.flags = CLI_SU_REQUIRED,
.help = NULL,
},
{
.name = "remove-inactive",
.desc = "Remove inactive core device from cache instance",
.long_desc = NULL,
.options = remove_inactive_options,
.command_handle_opts = remove_inactive_core_command_handle_option,
.handle = handle_remove_inactive,
.flags = CLI_SU_REQUIRED,
.help = NULL,
},
{
.name = "remove-detached",
.desc = "Remove core device from core pool",

View File

@ -222,8 +222,8 @@ struct {
},
{
KCAS_ERR_REMOVED_DIRTY,
"Flush error occured. Core has been set to detached state.\n"
"Warning: Core device may contain inconsistent data.\n"
"Warning: Core has been removed or detached without flush.\n"
"Core device may contain inconsistent data.\n"
"To access your data please add core back to the cache."
},
{
@ -256,7 +256,11 @@ struct {
KCAS_ERR_CACHE_STOPPING,
"Cache being stopped"
},
{
KCAS_ERR_CORE_IN_ACTIVE_STATE,
"Core device is in active state"
},
};

View File

@ -1363,27 +1363,19 @@ static int _cache_mngt_remove_core_flush(ocf_cache_t cache,
core_active = (ocf_core_get_state(core) == ocf_core_state_active);
if (cmd->detach && !core_active) {
printk(KERN_WARNING OCF_PREFIX_SHORT
"Cannot detach core which "
"is already inactive!\n");
return -OCF_ERR_CORE_IN_INACTIVE_STATE;
}
if (core_active) {
return _cache_mngt_core_flush_sync(core,
true, _cache_read_unlock_put_cmpl);
} else if (!ocf_mngt_core_is_dirty(core)) {
result = 0;
goto unlock;
} else {
printk(KERN_WARNING OCF_PREFIX_SHORT
"Cannot remove dirty inactive core "
"without force option\n");
if (!core_active) {
result = -OCF_ERR_CORE_IN_INACTIVE_STATE;
goto unlock;
}
if (!ocf_mngt_core_is_dirty(core)) {
result = 0;
goto unlock;
}
return _cache_mngt_core_flush_sync(core, true,
_cache_read_unlock_put_cmpl);
unlock:
ocf_mngt_cache_read_unlock(cache);
put:
@ -1399,20 +1391,22 @@ static int _cache_mngt_remove_core_prepare(ocf_cache_t cache, ocf_core_t core,
core_active = ocf_core_get_state(core) == ocf_core_state_active;
if (cmd->detach && !core_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;
}
if (core_active) {
return -OCF_ERR_CORE_IN_INACTIVE_STATE;
} else {
result = block_dev_destroy_exported_object(core);
if (result)
return result;
}
if (!cmd->force_no_flush)
if (cmd->force_no_flush)
return -KCAS_ERR_REMOVED_DIRTY;
result = _cache_mngt_core_flush_uninterruptible(core);
return result ? -KCAS_ERR_REMOVED_DIRTY : 0;
@ -1463,7 +1457,7 @@ int cache_mngt_remove_core_from_cache(struct kcas_remove_core *cmd)
init_completion(&context.cmpl);
context.result = &result;
if (cmd->detach || prepare_result == -KCAS_ERR_REMOVED_DIRTY) {
if (cmd->detach) {
ocf_mngt_cache_detach_core(core,
_cache_mngt_remove_core_complete, &context);
} else {
@ -1490,6 +1484,60 @@ put:
return result;
}
int cache_mngt_remove_inactive_core(struct kcas_remove_inactive *cmd)
{
struct _cache_mngt_sync_context context;
int result = 0;
ocf_cache_t cache;
ocf_core_t core;
result = mngt_get_cache_by_id(cas_ctx, cmd->cache_id, &cache);
if (result)
return result;
result = _cache_mngt_lock_sync(cache);
if (result)
goto put;
result = get_core_by_id(cache, cmd->core_id, &core);
if (result < 0) {
goto unlock;
}
result = (ocf_core_get_state(core) == ocf_core_state_active);
if (result) {
result = -KCAS_ERR_CORE_IN_ACTIVE_STATE;
goto unlock;
}
/*
* Destroy exported object - in case of error during destruction of
* exported object, instead of trying rolling this back we rather
* inform user about error.
*/
result = block_dev_destroy_exported_object(core);
if (result)
goto unlock;
init_completion(&context.cmpl);
context.result = &result;
ocf_mngt_cache_remove_core(core, _cache_mngt_remove_core_complete,
&context);
wait_for_completion(&context.cmpl);
if (!result) {
mark_core_id_free(cache, cmd->core_id);
}
unlock:
ocf_mngt_cache_unlock(cache);
put:
ocf_mngt_cache_put(cache);
return result;
}
int cache_mngt_reset_stats(const char *cache_name, size_t cache_name_len,
const char *core_name, size_t core_name_len)
{

View File

@ -36,6 +36,8 @@ int cache_mngt_add_core_to_cache(const char *cache_name, size_t name_len,
int cache_mngt_remove_core_from_cache(struct kcas_remove_core *cmd);
int cache_mngt_remove_inactive_core(struct kcas_remove_inactive *cmd);
int cache_mngt_reset_stats(const char *cache_name, size_t cache_name_len,
const char *core_name, size_t core_name_len);

View File

@ -132,6 +132,16 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd,
RETURN_CMD_RESULT(cmd_info, arg, retval);
}
case KCAS_IOCTL_REMOVE_INACTIVE: {
struct kcas_remove_inactive *cmd_info;
GET_CMD_INFO(cmd_info, arg);
retval = cache_mngt_remove_inactive_core(cmd_info);
RETURN_CMD_RESULT(cmd_info, arg, retval);
}
case KCAS_IOCTL_RESET_STATS: {
struct kcas_reset_stats *cmd_info;
char cache_name[OCF_CACHE_NAME_SIZE];

View File

@ -65,6 +65,7 @@ struct {
{ KCAS_ERR_A_PART, EINVAL },
{ KCAS_ERR_REMOVED_DIRTY, EIO },
{ KCAS_ERR_STOPPED_DIRTY, EIO },
{ KCAS_ERR_CORE_IN_ACTIVE_STATE, ENODEV },
};
/*******************************************/

View File

@ -117,12 +117,19 @@ struct kcas_insert_core {
struct kcas_remove_core {
uint16_t cache_id; /**< id of an running cache */
uint16_t core_id; /**< id core object to be removed */
bool force_no_flush; /**< remove core without flushing */
bool force_no_flush; /**< remove active core without flushing */
bool detach; /**< detach core without removing it from cache metadata */
int ext_err_code;
};
struct kcas_remove_inactive {
uint16_t cache_id; /**< id of an running cache */
uint16_t core_id; /**< id core object to be removed */
int ext_err_code;
};
struct kcas_reset_stats {
uint16_t cache_id; /**< id of an running cache */
uint16_t core_id; /**< id core object to be removed */
@ -419,6 +426,7 @@ struct kcas_get_cache_param {
* 34 * KCAS_IOCTL_GET_STATS * OK *
* 35 * KCAS_IOCTL_PURGE_CACHE * OK *
* 36 * KCAS_IOCTL_PURGE_CORE * OK *
* 37 * KCAS_IOCTL_REMOVE_INACTIVE * OK *
*******************************************************************************
*/
@ -473,7 +481,7 @@ struct kcas_get_cache_param {
/** Add core object to an running cache instance */
#define KCAS_IOCTL_INSERT_CORE _IOWR(KCAS_IOCTL_MAGIC, 22, struct kcas_insert_core)
/** Remove core object from an running cache instance */
/** Remove active core object from an running cache instance */
#define KCAS_IOCTL_REMOVE_CORE _IOR(KCAS_IOCTL_MAGIC, 23, struct kcas_remove_core)
/** Retrieve properties of a running cache instance (incl. mode etc.) */
@ -517,6 +525,9 @@ struct kcas_get_cache_param {
* and invalidate all valid cache lines associated with given core. */
#define KCAS_IOCTL_PURGE_CORE _IOWR(KCAS_IOCTL_MAGIC, 36, struct kcas_flush_core)
/** Remove inactive core object from an running cache instance */
#define KCAS_IOCTL_REMOVE_INACTIVE _IOR(KCAS_IOCTL_MAGIC, 37, struct kcas_remove_inactive)
/**
* Extended kernel CAS error codes
*/
@ -566,7 +577,7 @@ enum kcas_error {
/** Given device is a partition */
KCAS_ERR_A_PART,
/** Core has been removed with flush error */
/** Core has been removed, but it may contain dirty data */
KCAS_ERR_REMOVED_DIRTY,
/** Cache has been stopped, but it may contain dirty data */
@ -589,6 +600,9 @@ enum kcas_error {
/** Cache already being stopped*/
KCAS_ERR_CACHE_STOPPING,
/** Core device is in active state */
KCAS_ERR_CORE_IN_ACTIVE_STATE
};
#endif