commit
2a77fd3d4d
@ -1915,6 +1915,29 @@ int core_pool_remove(const char *core_device)
|
|||||||
return SUCCESS;
|
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"
|
#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)
|
int flush_cache(unsigned int cache_id)
|
||||||
{
|
{
|
||||||
@ -1944,6 +1967,29 @@ int flush_cache(unsigned int cache_id)
|
|||||||
return SUCCESS;
|
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 flush_core(unsigned int cache_id, unsigned int core_id)
|
||||||
{
|
{
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
|
@ -220,6 +220,9 @@ int get_core_pool_count(int fd);
|
|||||||
|
|
||||||
int reset_counters(unsigned int cache_id, unsigned int core_id);
|
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_cache(unsigned int cache_id);
|
||||||
int flush_core(unsigned int cache_id, unsigned int core_id);
|
int flush_core(unsigned int cache_id, unsigned int core_id);
|
||||||
|
|
||||||
|
@ -1419,6 +1419,8 @@ enum {
|
|||||||
|
|
||||||
script_cmd_add_core,
|
script_cmd_add_core,
|
||||||
script_cmd_remove_core,
|
script_cmd_remove_core,
|
||||||
|
script_cmd_purge_cache,
|
||||||
|
script_cmd_purge_core,
|
||||||
|
|
||||||
script_cmd_max_id,
|
script_cmd_max_id,
|
||||||
|
|
||||||
@ -1477,6 +1479,23 @@ static cli_option script_params_options[] = {
|
|||||||
| (1 << script_opt_core_id),
|
| (1 << script_opt_core_id),
|
||||||
.flags = CLI_COMMAND_HIDDEN,
|
.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_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] = {
|
[script_opt_cache_device] = {
|
||||||
.short_name = 0,
|
.short_name = 0,
|
||||||
.long_name = "cache-device",
|
.long_name = "cache-device",
|
||||||
@ -1491,7 +1510,9 @@ static cli_option script_params_options[] = {
|
|||||||
.args_count = 1,
|
.args_count = 1,
|
||||||
.arg = "ID",
|
.arg = "ID",
|
||||||
.priv = (1 << script_cmd_remove_core)
|
.priv = (1 << script_cmd_remove_core)
|
||||||
| (1 << script_cmd_add_core),
|
| (1 << script_cmd_add_core)
|
||||||
|
| (1 << script_cmd_purge_cache)
|
||||||
|
| (1 << script_cmd_purge_core),
|
||||||
.flags = (CLI_OPTION_RANGE_INT | CLI_OPTION_HIDDEN),
|
.flags = (CLI_OPTION_RANGE_INT | CLI_OPTION_HIDDEN),
|
||||||
.min_value = OCF_CACHE_ID_MIN,
|
.min_value = OCF_CACHE_ID_MIN,
|
||||||
.max_value = OCF_CACHE_ID_MAX,
|
.max_value = OCF_CACHE_ID_MAX,
|
||||||
@ -1502,7 +1523,8 @@ static cli_option script_params_options[] = {
|
|||||||
.args_count = 1,
|
.args_count = 1,
|
||||||
.arg = "ID",
|
.arg = "ID",
|
||||||
.priv = (1 << script_cmd_remove_core)
|
.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),
|
.flags = (CLI_OPTION_RANGE_INT | CLI_OPTION_HIDDEN),
|
||||||
.min_value = OCF_CORE_ID_MIN,
|
.min_value = OCF_CORE_ID_MIN,
|
||||||
.max_value = OCF_CORE_ID_MAX,
|
.max_value = OCF_CORE_ID_MAX,
|
||||||
@ -1658,6 +1680,13 @@ int script_handle() {
|
|||||||
command_args_values.detach,
|
command_args_values.detach,
|
||||||
command_args_values.no_flush
|
command_args_values.no_flush
|
||||||
);
|
);
|
||||||
|
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;
|
return FAILURE;
|
||||||
|
@ -230,6 +230,106 @@ static int _cache_mngt_cache_flush_uninterruptible(ocf_cache_t cache)
|
|||||||
return result;
|
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_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,
|
static void _cache_mngt_cache_flush_complete(ocf_cache_t cache, void *priv,
|
||||||
int error)
|
int error)
|
||||||
{
|
{
|
||||||
@ -609,6 +709,37 @@ static void _cache_read_unlock_put_cmpl(ocf_cache_t cache)
|
|||||||
ocf_mngt_cache_put(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,
|
int cache_mngt_flush_object(const char *cache_name, size_t cache_name_len,
|
||||||
const char *core_name, size_t core_name_len)
|
const char *core_name, size_t core_name_len)
|
||||||
{
|
{
|
||||||
@ -640,6 +771,27 @@ int cache_mngt_flush_object(const char *cache_name, size_t cache_name_len,
|
|||||||
return result;
|
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 cache_mngt_flush_device(const char *cache_name, size_t name_len)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -77,11 +77,16 @@ 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,
|
int cache_mngt_set_cache_mode(const char *cache_name, size_t name_len,
|
||||||
ocf_cache_mode_t mode, uint8_t flush);
|
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,
|
int cache_mngt_flush_object(const char *cache_name, size_t cache_name_len,
|
||||||
const char *core_name, size_t core_name_len);
|
const char *core_name, size_t core_name_len);
|
||||||
|
|
||||||
int cache_mngt_flush_device(const char *cache_name, size_t 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_list_caches(struct kcas_cache_list *list);
|
||||||
|
|
||||||
int cache_mngt_interrupt_flushing(const char *cache_name, size_t name_len);
|
int cache_mngt_interrupt_flushing(const char *cache_name, size_t name_len);
|
||||||
|
@ -154,6 +154,19 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd,
|
|||||||
RETURN_CMD_RESULT(cmd_info, arg, retval);
|
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: {
|
case KCAS_IOCTL_FLUSH_CACHE: {
|
||||||
struct kcas_flush_cache *cmd_info;
|
struct kcas_flush_cache *cmd_info;
|
||||||
char cache_name[OCF_CACHE_NAME_SIZE];
|
char cache_name[OCF_CACHE_NAME_SIZE];
|
||||||
@ -181,6 +194,23 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd,
|
|||||||
RETURN_CMD_RESULT(cmd_info, arg, retval);
|
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: {
|
case KCAS_IOCTL_FLUSH_CORE: {
|
||||||
struct kcas_flush_core *cmd_info;
|
struct kcas_flush_core *cmd_info;
|
||||||
char cache_name[OCF_CACHE_NAME_SIZE];
|
char cache_name[OCF_CACHE_NAME_SIZE];
|
||||||
|
@ -410,6 +410,8 @@ struct kcas_get_cache_param {
|
|||||||
* 32 * KCAS_IOCTL_SET_CACHE_PARAM * OK *
|
* 32 * KCAS_IOCTL_SET_CACHE_PARAM * OK *
|
||||||
* 33 * KCAS_IOCTL_GET_CACHE_PARAM * OK *
|
* 33 * KCAS_IOCTL_GET_CACHE_PARAM * OK *
|
||||||
* 34 * KCAS_IOCTL_GET_STATS * OK *
|
* 34 * KCAS_IOCTL_GET_STATS * OK *
|
||||||
|
* 35 * KCAS_IOCTL_PURGE_CACHE * OK *
|
||||||
|
* 36 * KCAS_IOCTL_PURGE_CORE * OK *
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -500,6 +502,14 @@ struct kcas_get_cache_param {
|
|||||||
/** Get stats of particular OCF object */
|
/** Get stats of particular OCF object */
|
||||||
#define KCAS_IOCTL_GET_STATS _IOR(KCAS_IOCTL_MAGIC, 34, struct kcas_get_stats)
|
#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)
|
||||||
|
|
||||||
|
/* 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
|
* Extended kernel CAS error codes
|
||||||
*/
|
*/
|
||||||
|
@ -117,6 +117,10 @@ class Cache:
|
|||||||
sync()
|
sync()
|
||||||
assert self.get_dirty_blocks().get_value(Unit.Blocks4096) == 0
|
assert self.get_dirty_blocks().get_value(Unit.Blocks4096) == 0
|
||||||
|
|
||||||
|
def purge_cache(self):
|
||||||
|
casadm.purge_cache(cache_id=self.cache_id)
|
||||||
|
sync()
|
||||||
|
|
||||||
def stop(self, no_data_flush: bool = False):
|
def stop(self, no_data_flush: bool = False):
|
||||||
return casadm.stop_cache(self.cache_id, no_data_flush)
|
return casadm.stop_cache(self.cache_id, no_data_flush)
|
||||||
|
|
||||||
|
@ -79,6 +79,20 @@ def try_add(core_device: Device, cache_id: int):
|
|||||||
return Core(core_device.system_path, cache_id)
|
return Core(core_device.system_path, cache_id)
|
||||||
|
|
||||||
|
|
||||||
|
def purge_cache(cache_id: int):
|
||||||
|
output = TestRun.executor.run(script_purge_cache(str(cache_id)))
|
||||||
|
if output.exit_code != 0:
|
||||||
|
raise CmdException("Purge cache failed.", output)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def purge_core(cache_id: int, core_id: int):
|
||||||
|
output = TestRun.executor.run(script_purge_core(str(cache_id), str(core_id)))
|
||||||
|
if output.exit_code != 0:
|
||||||
|
raise CmdException("Purge core failed.", output)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
def reset_counters(cache_id: int, core_id: int = None, shortcut: bool = False):
|
def reset_counters(cache_id: int, core_id: int = None, shortcut: bool = False):
|
||||||
_core_id = None if core_id is None else str(core_id)
|
_core_id = None if core_id is None else str(core_id)
|
||||||
output = TestRun.executor.run(
|
output = TestRun.executor.run(
|
||||||
|
@ -24,6 +24,14 @@ def script_try_add_cmd(cache_id: str, core_dev: str):
|
|||||||
f"--core-device {core_dev}"
|
f"--core-device {core_dev}"
|
||||||
|
|
||||||
|
|
||||||
|
def script_purge_cache_cmd(cache_id: str):
|
||||||
|
return f"{casadm_bin} --script --purge-cache --cache-id {cache_id}"
|
||||||
|
|
||||||
|
|
||||||
|
def script_purge_core_cmd(cache_id: str, core_id: str):
|
||||||
|
return f"{casadm_bin} --script --purge-core --cache-id {cache_id} --core-id {core_id}"
|
||||||
|
|
||||||
|
|
||||||
def remove_core_cmd(cache_id: str, core_id: str, force: bool = False, shortcut: bool = False):
|
def remove_core_cmd(cache_id: str, core_id: str, force: bool = False, shortcut: bool = False):
|
||||||
command = f" -R -i {cache_id} -j {core_id}" if shortcut \
|
command = f" -R -i {cache_id} -j {core_id}" if shortcut \
|
||||||
else f" --remove-core --cache-id {cache_id} --core-id {core_id}"
|
else f" --remove-core --cache-id {cache_id} --core-id {core_id}"
|
||||||
|
@ -111,6 +111,10 @@ class Core(Device):
|
|||||||
sync()
|
sync()
|
||||||
assert self.get_dirty_blocks().get_value(Unit.Blocks4096) == 0
|
assert self.get_dirty_blocks().get_value(Unit.Blocks4096) == 0
|
||||||
|
|
||||||
|
def purge_core(self):
|
||||||
|
casadm.purge_core(self.cache_id, self.core_id)
|
||||||
|
sync()
|
||||||
|
|
||||||
def set_seq_cutoff_parameters(self, seq_cutoff_param: SeqCutOffParameters):
|
def set_seq_cutoff_parameters(self, seq_cutoff_param: SeqCutOffParameters):
|
||||||
return casadm.set_param_cutoff(self.cache_id, self.core_id,
|
return casadm.set_param_cutoff(self.cache_id, self.core_id,
|
||||||
seq_cutoff_param.threshold, seq_cutoff_param.policy)
|
seq_cutoff_param.threshold, seq_cutoff_param.policy)
|
||||||
|
85
test/functional/tests/cli/test_cli_script.py
Normal file
85
test/functional/tests/cli/test_cli_script.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#
|
||||||
|
# Copyright(c) 2020 Intel Corporation
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from api.cas import casadm, casadm_parser
|
||||||
|
from core.test_run import TestRun
|
||||||
|
from test_utils.os_utils import sync
|
||||||
|
from storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan
|
||||||
|
from test_utils.size import Unit, Size
|
||||||
|
from test_tools.dd import Dd
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.nand, DiskType.optane]))
|
||||||
|
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
|
||||||
|
@pytest.mark.parametrize("purge_target", ["cache", "core"])
|
||||||
|
def test_purge(purge_target):
|
||||||
|
"""
|
||||||
|
title: Call purge without and with `--script` switch
|
||||||
|
description: |
|
||||||
|
Check if purge is called only when `--script` switch is used.
|
||||||
|
pass_criteria:
|
||||||
|
- casadm returns an error when `--script` is missing
|
||||||
|
- cache is wiped when purge command is used properly
|
||||||
|
"""
|
||||||
|
with TestRun.step("Prepare devices"):
|
||||||
|
cache_device = TestRun.disks["cache"]
|
||||||
|
core_device = TestRun.disks["core"]
|
||||||
|
|
||||||
|
cache_device.create_partitions([Size(500, Unit.MebiByte)])
|
||||||
|
core_device.create_partitions([Size(500, Unit.MebiByte)])
|
||||||
|
|
||||||
|
cache_device = cache_device.partitions[0]
|
||||||
|
core_device = core_device.partitions[0]
|
||||||
|
|
||||||
|
with TestRun.step("Prepare cache instance"):
|
||||||
|
cache = casadm.start_cache(cache_device, force=True)
|
||||||
|
core = casadm.add_core(cache, core_device)
|
||||||
|
|
||||||
|
with TestRun.step("Trigger IO to prepared cache instance"):
|
||||||
|
dd = (
|
||||||
|
Dd()
|
||||||
|
.input("/dev/zero")
|
||||||
|
.output(core.system_path)
|
||||||
|
.count(100)
|
||||||
|
.block_size(Size(1, Unit.Blocks512))
|
||||||
|
.oflag("direct")
|
||||||
|
)
|
||||||
|
dd.run()
|
||||||
|
sync()
|
||||||
|
|
||||||
|
with TestRun.step(
|
||||||
|
f"Try to call purge-{purge_target} without `--script` switch"
|
||||||
|
):
|
||||||
|
original_occupancy = cache.get_statistics().usage_stats.occupancy
|
||||||
|
purge_params = f"--cache-id {cache.cache_id} "
|
||||||
|
if purge_target == "core":
|
||||||
|
purge_params += f"--core-id {core.core_id}"
|
||||||
|
TestRun.executor.run_expect_fail(
|
||||||
|
f"casadm --purge-{purge_target} {purge_params}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if cache.get_statistics().usage_stats.occupancy != original_occupancy:
|
||||||
|
TestRun.fail(
|
||||||
|
f"Purge {purge_target} should not be possible to use without `--script` switch!"
|
||||||
|
)
|
||||||
|
|
||||||
|
with TestRun.step(
|
||||||
|
f"Try to call purge-{purge_target} with `--script` switch"
|
||||||
|
):
|
||||||
|
TestRun.executor.run_expect_success(
|
||||||
|
f"casadm --script --purge-{purge_target} {purge_params}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if cache.get_statistics().usage_stats.occupancy.get_value() != 0:
|
||||||
|
TestRun.fail(f"{cache.get_statistics().usage_stats.occupancy.get_value()}")
|
||||||
|
TestRun.fail(f"Purge {purge_target} should invalidate all cache lines!")
|
||||||
|
|
||||||
|
with TestRun.step(
|
||||||
|
f"Stop cache"
|
||||||
|
):
|
||||||
|
casadm.stop_all_caches()
|
Loading…
Reference in New Issue
Block a user