Purge cache command

Purge invalidates all cache lines. It is very usefull feature for tests.

Calling purge is possbile with casadm `--script` swtich.

Signed-off-by: Michal Mielewczyk <michal.mielewczyk@intel.com>
This commit is contained in:
Michal Mielewczyk 2020-05-08 11:12:31 -04:00
parent f7d854bf70
commit d24288a9b1
7 changed files with 129 additions and 1 deletions

View File

@ -1915,6 +1915,29 @@ int core_pool_remove(const char *core_device)
return SUCCESS;
}
int purge_cache(unsigned int cache_id)
{
int fd = 0;
struct kcas_flush_cache cmd;
fd = open_ctrl_device();
if (fd == -1)
return FAILURE;
memset(&cmd, 0, sizeof(cmd));
cmd.cache_id = cache_id;
/* synchronous flag */
if (run_ioctl_interruptible(fd, KCAS_IOCTL_PURGE_CACHE, &cmd, "Purging cache",
cache_id, OCF_CORE_ID_INVALID) < 0) {
close(fd);
print_err(cmd.ext_err_code);
return FAILURE;
}
close(fd);
return SUCCESS;
}
#define DIRTY_FLUSHING_WARNING "You have interrupted flushing of cache dirty data. CAS continues to operate\nnormally and dirty data that remains on cache device will be flushed by cleaning thread.\n"
int flush_cache(unsigned int cache_id)
{

View File

@ -220,6 +220,8 @@ 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 flush_cache(unsigned int cache_id);
int flush_core(unsigned int cache_id, unsigned int core_id);

View File

@ -1419,6 +1419,7 @@ enum {
script_cmd_add_core,
script_cmd_remove_core,
script_cmd_purge_cache,
script_cmd_max_id,
@ -1477,6 +1478,14 @@ static cli_option script_params_options[] = {
| (1 << script_opt_core_id),
.flags = CLI_COMMAND_HIDDEN,
},
[script_cmd_purge_cache] = {
.short_name = 0,
.long_name = "purge-cache",
.args_count = 0,
.arg = NULL,
.priv = (1 << script_opt_cache_id),
.flags = CLI_COMMAND_HIDDEN,
},
[script_opt_cache_device] = {
.short_name = 0,
.long_name = "cache-device",
@ -1491,7 +1500,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_cache),
.flags = (CLI_OPTION_RANGE_INT | CLI_OPTION_HIDDEN),
.min_value = OCF_CACHE_ID_MIN,
.max_value = OCF_CACHE_ID_MAX,
@ -1658,6 +1668,8 @@ int script_handle() {
command_args_values.detach,
command_args_values.no_flush
);
case script_cmd_purge_cache:
return purge_cache(command_args_values.cache_id);
}
return FAILURE;

View File

@ -230,6 +230,56 @@ static int _cache_mngt_cache_flush_uninterruptible(ocf_cache_t cache)
return result;
}
static void _cache_mngt_cache_purge_complete(ocf_cache_t cache, void *priv,
int error)
{
struct _cache_mngt_async_context *context = priv;
int result;
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_cache_purge_sync(ocf_cache_t cache,
void (*compl)(ocf_cache_t cache))
{
int result;
struct _cache_mngt_async_context *context;
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_cache_purge(cache, _cache_mngt_cache_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)
{
@ -640,6 +690,27 @@ int cache_mngt_flush_object(const char *cache_name, size_t cache_name_len,
return result;
}
int cache_mngt_purge_device(const char *cache_name, size_t name_len)
{
int result;
ocf_cache_t cache;
result = ocf_mngt_cache_get_by_name(cas_ctx, cache_name,
name_len, &cache);
if (result)
return result;
result = _cache_mngt_read_lock_sync(cache);
if (result) {
ocf_mngt_cache_put(cache);
return result;
}
result = _cache_mngt_cache_purge_sync(cache, _cache_read_unlock_put_cmpl);
return result;
}
int cache_mngt_flush_device(const char *cache_name, size_t name_len)
{
int result;

View File

@ -82,6 +82,8 @@ int cache_mngt_flush_object(const char *cache_name, size_t cache_name_len,
int cache_mngt_flush_device(const char *cache_name, size_t name_len);
int cache_mngt_purge_device(const char *cache_name, size_t name_len);
int cache_mngt_list_caches(struct kcas_cache_list *list);
int cache_mngt_interrupt_flushing(const char *cache_name, size_t name_len);

View File

@ -154,6 +154,19 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd,
RETURN_CMD_RESULT(cmd_info, arg, retval);
}
case KCAS_IOCTL_PURGE_CACHE: {
struct kcas_flush_cache *cmd_info;
char cache_name[OCF_CACHE_NAME_SIZE];
GET_CMD_INFO(cmd_info, arg);
cache_name_from_id(cache_name, cmd_info->cache_id);
retval = cache_mngt_purge_device(cache_name, OCF_CACHE_NAME_SIZE);
RETURN_CMD_RESULT(cmd_info, arg, retval);
}
case KCAS_IOCTL_FLUSH_CACHE: {
struct kcas_flush_cache *cmd_info;
char cache_name[OCF_CACHE_NAME_SIZE];

View File

@ -410,6 +410,7 @@ struct kcas_get_cache_param {
* 32 * KCAS_IOCTL_SET_CACHE_PARAM * OK *
* 33 * KCAS_IOCTL_GET_CACHE_PARAM * OK *
* 34 * KCAS_IOCTL_GET_STATS * OK *
* 35 * KCAS_IOCTL_PURGE_CACHE * OK *
*******************************************************************************
*/
@ -500,6 +501,10 @@ struct kcas_get_cache_param {
/** Get stats of particular OCF object */
#define KCAS_IOCTL_GET_STATS _IOR(KCAS_IOCTL_MAGIC, 34, struct kcas_get_stats)
/* Flush dirty data from running cache
* and invalidate all valid cache lines */
#define KCAS_IOCTL_PURGE_CACHE _IOWR(KCAS_IOCTL_MAGIC, 35, struct kcas_flush_cache)
/**
* Extended kernel CAS error codes
*/