diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index f673824..f4089e1 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -1967,6 +1967,29 @@ int flush_cache(unsigned int cache_id) return SUCCESS; } +int purge_core(unsigned int cache_id, unsigned int core_id) +{ + int fd = 0; + struct kcas_flush_core cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cache_id = cache_id; + cmd.core_id = core_id; + + fd = open_ctrl_device(); + if (fd == -1) + return FAILURE; + + /* synchronous flag */ + if (run_ioctl_interruptible(fd, KCAS_IOCTL_PURGE_CORE, &cmd, "Purging core", cache_id, core_id) < 0) { + close(fd); + print_err(cmd.ext_err_code); + return FAILURE; + } + close(fd); + return SUCCESS; +} + int flush_core(unsigned int cache_id, unsigned int core_id) { int fd = 0; diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 9dafcdc..e5adefc 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -221,6 +221,7 @@ int get_core_pool_count(int fd); int reset_counters(unsigned int cache_id, unsigned int core_id); int purge_cache(unsigned int cache_id); +int purge_core(unsigned int cache_id, unsigned int core_id); int flush_cache(unsigned int cache_id); int flush_core(unsigned int cache_id, unsigned int core_id); diff --git a/casadm/cas_main.c b/casadm/cas_main.c index 3b8bcef..d4039a6 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -1420,6 +1420,7 @@ enum { script_cmd_add_core, script_cmd_remove_core, script_cmd_purge_cache, + script_cmd_purge_core, script_cmd_max_id, @@ -1486,6 +1487,15 @@ static cli_option script_params_options[] = { .priv = (1 << script_opt_cache_id), .flags = CLI_COMMAND_HIDDEN, }, + [script_cmd_purge_core] = { + .short_name = 0, + .long_name = "purge-core", + .args_count = 0, + .arg = NULL, + .priv = (1 << script_opt_cache_id) + | (1 << script_opt_core_id), + .flags = CLI_COMMAND_HIDDEN, + }, [script_opt_cache_device] = { .short_name = 0, .long_name = "cache-device", @@ -1501,7 +1511,8 @@ static cli_option script_params_options[] = { .arg = "ID", .priv = (1 << script_cmd_remove_core) | (1 << script_cmd_add_core) - | (1 << script_cmd_purge_cache), + | (1 << script_cmd_purge_cache) + | (1 << script_cmd_purge_core), .flags = (CLI_OPTION_RANGE_INT | CLI_OPTION_HIDDEN), .min_value = OCF_CACHE_ID_MIN, .max_value = OCF_CACHE_ID_MAX, @@ -1512,7 +1523,8 @@ static cli_option script_params_options[] = { .args_count = 1, .arg = "ID", .priv = (1 << script_cmd_remove_core) - | (1 << script_cmd_add_core), + | (1 << script_cmd_add_core) + | (1 << script_cmd_purge_core), .flags = (CLI_OPTION_RANGE_INT | CLI_OPTION_HIDDEN), .min_value = OCF_CORE_ID_MIN, .max_value = OCF_CORE_ID_MAX, @@ -1670,6 +1682,11 @@ int script_handle() { ); case script_cmd_purge_cache: return purge_cache(command_args_values.cache_id); + case script_cmd_purge_core: + return purge_core( + command_args_values.cache_id, + command_args_values.core_id + ); } return FAILURE; diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index fd1e1c1..841f9b8 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -279,6 +279,56 @@ static int _cache_mngt_cache_purge_sync(ocf_cache_t cache, return result; } +static void _cache_mngt_core_purge_complete(ocf_core_t core, void *priv, + int error) +{ + struct _cache_mngt_async_context *context = priv; + int result; + ocf_cache_t cache = ocf_core_get_cache(core); + + if (context->compl_func) + context->compl_func(cache); + + result = _cache_mngt_async_callee_set_result(context, error); + + if (result == -KCAS_ERR_WAITING_INTERRUPTED) + kfree(context); +} + +/* + * Possible return values: + * 0 - completion was called and operation succeded + * -KCAS_ERR_WAITING_INTERRUPTED - operation was canceled, caller must + * propagate error + * other values - completion was called and operation failed + */ +static int _cache_mngt_core_purge_sync(ocf_core_t core, bool interruption, + void (*compl)(ocf_cache_t cache)) +{ + int result; + struct _cache_mngt_async_context *context; + ocf_cache_t cache = ocf_core_get_cache(core); + + context = kmalloc(sizeof(*context), GFP_KERNEL); + if (!context) { + if (compl) + compl(cache); + return -ENOMEM; + } + + _cache_mngt_async_context_init(context); + context->compl_func = compl; + + ocf_mngt_core_purge(core, _cache_mngt_core_purge_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; +} static void _cache_mngt_cache_flush_complete(ocf_cache_t cache, void *priv, int error) @@ -659,6 +709,37 @@ static void _cache_read_unlock_put_cmpl(ocf_cache_t cache) ocf_mngt_cache_put(cache); } +int cache_mngt_purge_object(const char *cache_name, size_t cache_name_len, + const char *core_name, size_t core_name_len) +{ + ocf_cache_t cache; + ocf_core_t core; + int result; + + result = ocf_mngt_cache_get_by_name(cas_ctx, cache_name, + cache_name_len, &cache); + if (result) + return result; + + result = _cache_mngt_read_lock_sync(cache); + if (result) { + ocf_mngt_cache_put(cache); + return result; + } + + result = ocf_core_get_by_name(cache, core_name, core_name_len, &core); + if (result) { + ocf_mngt_cache_read_unlock(cache); + ocf_mngt_cache_put(cache); + return result; + } + + result = _cache_mngt_core_purge_sync(core, true, + _cache_read_unlock_put_cmpl); + + return result; +} + int cache_mngt_flush_object(const char *cache_name, size_t cache_name_len, const char *core_name, size_t core_name_len) { diff --git a/modules/cas_cache/layer_cache_management.h b/modules/cas_cache/layer_cache_management.h index 2c9d176..8f24f19 100644 --- a/modules/cas_cache/layer_cache_management.h +++ b/modules/cas_cache/layer_cache_management.h @@ -77,6 +77,9 @@ int cache_mngt_get_seq_cutoff_policy(ocf_core_t core, int cache_mngt_set_cache_mode(const char *cache_name, size_t name_len, ocf_cache_mode_t mode, uint8_t flush); +int cache_mngt_purge_object(const char *cache_name, size_t cache_name_len, + const char *core_name, size_t core_name_len); + int cache_mngt_flush_object(const char *cache_name, size_t cache_name_len, const char *core_name, size_t core_name_len); diff --git a/modules/cas_cache/service_ui_ioctl.c b/modules/cas_cache/service_ui_ioctl.c index 53c7823..f3788fa 100644 --- a/modules/cas_cache/service_ui_ioctl.c +++ b/modules/cas_cache/service_ui_ioctl.c @@ -194,6 +194,23 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, RETURN_CMD_RESULT(cmd_info, arg, retval); } + case KCAS_IOCTL_PURGE_CORE: { + struct kcas_flush_core *cmd_info; + char cache_name[OCF_CACHE_NAME_SIZE]; + char core_name[OCF_CORE_NAME_SIZE]; + + GET_CMD_INFO(cmd_info, arg); + + cache_name_from_id(cache_name, cmd_info->cache_id); + + core_name_from_id(core_name, cmd_info->core_id); + + retval = cache_mngt_purge_object(cache_name, OCF_CACHE_NAME_SIZE, + core_name, OCF_CORE_NAME_SIZE); + + RETURN_CMD_RESULT(cmd_info, arg, retval); + } + case KCAS_IOCTL_FLUSH_CORE: { struct kcas_flush_core *cmd_info; char cache_name[OCF_CACHE_NAME_SIZE]; diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index 26d591d..5f660e8 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -411,6 +411,7 @@ struct kcas_get_cache_param { * 33 * KCAS_IOCTL_GET_CACHE_PARAM * OK * * 34 * KCAS_IOCTL_GET_STATS * OK * * 35 * KCAS_IOCTL_PURGE_CACHE * OK * + * 36 * KCAS_IOCTL_PURGE_CORE * OK * ******************************************************************************* */ @@ -505,6 +506,10 @@ struct kcas_get_cache_param { * and invalidate all valid cache lines */ #define KCAS_IOCTL_PURGE_CACHE _IOWR(KCAS_IOCTL_MAGIC, 35, struct kcas_flush_cache) +/* Flush dirty data from running core object + * and invalidate all valid cache lines associated with given core. */ +#define KCAS_IOCTL_PURGE_CORE _IOWR(KCAS_IOCTL_MAGIC, 36, struct kcas_flush_core) + /** * Extended kernel CAS error codes */